~ubuntu-branches/debian/squeeze/f-spot/squeeze

« back to all changes in this revision

Viewing changes to src/Editors/Editor.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane, Mirco Bauer, Iain Lane
  • Date: 2009-02-07 20:23:32 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20090207202332-oc93rfjo1st0571s
Tags: 0.5.0.3-2
[ Mirco Bauer]
* Upload to unstable.
* debian/control:
  + Lowered GNOME# build-deps to 2.0 ABI as that transition didn't happen
    yet in unstable.

[ Iain Lane ]
* debian/patches/svn-r4545_locales-import.dpatch: Patch backported from SVN
  trunk revision 4545 - initialize the translation catalog earlier (LP: #293305)
  (Closes: #514457). Thanks to Florian Heinle for finding the patch and to
  Chris Coulson for preparing the update.
* debian/control: Build-depend on libmono-dev (>= 1.2.4) to match configure
  checks.
* debian/rules: Pass CSC=/usr/bin/csc to configure for gio-sharp to fix FTBFS

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Editor.cs
 
3
 *
 
4
 * Author(s)
 
5
 *      Ruben Vermeersch <ruben@savanne.be>
 
6
 *
 
7
 * This is free software. See COPYING for details.
 
8
 */
 
9
 
 
10
using FSpot;
 
11
using FSpot.Utils;
 
12
 
 
13
using Gdk;
 
14
using Gtk;
 
15
 
 
16
using Mono.Addins;
 
17
using Mono.Unix;
1
18
 
2
19
using System;
3
 
using Gtk;
4
 
using Cairo;
5
 
using Tao.OpenGl;
6
20
 
7
21
namespace FSpot.Editors {
 
22
        [ExtensionNode ("Editor")]
 
23
        public class EditorNode : ExtensionNode {
 
24
                [NodeAttribute (Required=true)]
 
25
                protected string editor_type;
 
26
 
 
27
                public Editor GetEditor () {
 
28
                        return (Editor) Addin.CreateInstance (editor_type);
 
29
                }
 
30
        }
 
31
 
 
32
        public class EditorSelection {
 
33
                public int x, y;
 
34
                public int width, height;
 
35
        }
 
36
 
 
37
        public class EditorState {
 
38
                // The area selected by the user.
 
39
                public EditorSelection Selection;
 
40
 
 
41
                // The images selected by the user.
 
42
                public IBrowsableItem [] Items;
 
43
 
 
44
                // The view, into which images are shown (null if we are in the browse view).
 
45
                public PhotoImageView PhotoImageView;
 
46
 
 
47
                // Has a portion of the image been selected?
 
48
                public bool HasSelection {
 
49
                        get { return Selection != null; }
 
50
                }
 
51
 
 
52
                // Is the user in browse mode?
 
53
                public bool InBrowseMode {
 
54
                        get { return PhotoImageView == null; }
 
55
                }
 
56
        }
 
57
 
 
58
        // This is the base class from which all editors inherit.
8
59
        public abstract class Editor {
9
 
                protected PhotoImageView view;
10
 
                protected Gtk.Window controls;
11
 
                
12
 
                public event EventHandler Done;
13
 
 
14
 
                public Editor (PhotoImageView view)
15
 
                {
16
 
                        SetView (view);
17
 
                }
18
 
 
19
 
                protected virtual string GetTitle ()
20
 
                {
21
 
                        return String.Empty;
22
 
                }
23
 
 
24
 
                protected virtual void SetView (PhotoImageView view)
25
 
                {
26
 
                        if (controls != null)
27
 
                                controls.Destroy ();
28
 
 
29
 
                        controls = null;
30
 
 
31
 
                        this.view = view;
32
 
                        if (view == null)
33
 
                                return;
34
 
 
35
 
                        Widget w = CreateControls ();
36
 
 
37
 
                        if (w != null) {
38
 
#if false
39
 
                                ControlOverlay c = new ControlOverlay (view);
40
 
                                c.AutoHide = false;
41
 
                                w.ShowAll ();
42
 
                                c.Add (w);
43
 
                                c.Visibility = ControlOverlay.VisibilityType.Full;
44
 
                                controls = c;
45
 
#else
46
 
                                Window win = new Window (String.Format ("{0}", GetTitle ()));
47
 
                                win.TransientFor = (Gtk.Window) view.Toplevel;
48
 
                                win.Add (w);
49
 
                                win.ShowAll ();
50
 
                                win.DeleteEvent += delegate { Destroy (); };
51
 
                                controls = win;
52
 
#endif
53
 
                        }
54
 
                        
55
 
                }
56
 
 
57
 
                protected virtual Widget CreateControls ()
58
 
                {
 
60
                public delegate void ProcessingStartedHandler (string name, int count);
 
61
                public delegate void ProcessingStepHandler (int done);
 
62
                public delegate void ProcessingFinishedHandler ();
 
63
 
 
64
                public event ProcessingStartedHandler ProcessingStarted;
 
65
                public event ProcessingStepHandler ProcessingStep;
 
66
                public event ProcessingFinishedHandler ProcessingFinished;
 
67
 
 
68
                // Contains the current selection, the items being edited, ...
 
69
                private EditorState state;
 
70
                public EditorState State {
 
71
                        get {
 
72
                                if (!StateInitialized)
 
73
                                        throw new ApplicationException ("Editor has not been initialized yet!");
 
74
 
 
75
                                return state;
 
76
                        }
 
77
                        private set { state = value; }
 
78
                }
 
79
 
 
80
                public bool StateInitialized {
 
81
                        get { return state != null; }
 
82
                }
 
83
 
 
84
 
 
85
                // Whether the user needs to select a part of the image before it can be applied.
 
86
                public bool NeedsSelection = false;
 
87
 
 
88
                // A tool can be applied if it doesn't need a selection, or if it has one.
 
89
                public bool CanBeApplied {
 
90
                        get {
 
91
                                Log.DebugFormat ("{0} can be applied? {1}", this, !NeedsSelection || (NeedsSelection && State.HasSelection));
 
92
                                return !NeedsSelection || (NeedsSelection && State.HasSelection);
 
93
                        }
 
94
                }
 
95
 
 
96
                private bool can_handle_multiple = false;
 
97
                public bool CanHandleMultiple {
 
98
                        get { return can_handle_multiple; }
 
99
                        protected set { can_handle_multiple = value; }
 
100
                }
 
101
 
 
102
 
 
103
                protected void LoadPhoto (Photo photo, out Pixbuf photo_pixbuf, out Cms.Profile photo_profile) {
 
104
                        // FIXME: We might get this value from the PhotoImageView.
 
105
                        using (ImageFile img = ImageFile.Create (photo.DefaultVersionUri)) {
 
106
                                photo_pixbuf = img.Load ();
 
107
                                photo_profile = img.GetProfile ();
 
108
                        }
 
109
                }
 
110
 
 
111
                // The human readable name for this action.
 
112
                public readonly string Label;
 
113
 
 
114
                // The label on the apply button (usually shorter than the label).
 
115
                private string apply_label = "";
 
116
                public string ApplyLabel {
 
117
                        get { return apply_label == "" ? Label : apply_label; }
 
118
                        protected set { apply_label = value; }
 
119
                }
 
120
 
 
121
 
 
122
                // The icon name for this action (will be loaded from the theme).
 
123
                public readonly string IconName;
 
124
 
 
125
                public Editor (string label, string icon_name) {
 
126
                        Label = label;
 
127
                        IconName = icon_name;
 
128
                }
 
129
 
 
130
                // Apply the editor's action to a photo.
 
131
                public void Apply () {
 
132
                        try {
 
133
                                if (ProcessingStarted != null) {
 
134
                                        ProcessingStarted (Label, State.Items.Length);
 
135
                                }
 
136
                                TryApply ();
 
137
                        } finally {
 
138
                                if (ProcessingFinished != null) {
 
139
                                        ProcessingFinished ();
 
140
                                }
 
141
                        }
 
142
                }
 
143
 
 
144
                private void TryApply () {
 
145
                        if (NeedsSelection && !State.HasSelection) {
 
146
                                throw new Exception ("Cannot apply without selection!");
 
147
                        }
 
148
 
 
149
                        int done = 0;
 
150
                        foreach (Photo photo in State.Items) {
 
151
                                Pixbuf input;
 
152
                                Cms.Profile input_profile;
 
153
                                LoadPhoto (photo, out input, out input_profile);
 
154
 
 
155
                                Pixbuf edited = Process (input, input_profile);
 
156
                                input.Dispose ();
 
157
 
 
158
                                bool create_version = photo.DefaultVersion.IsProtected;
 
159
                                photo.SaveVersion (edited, create_version);
 
160
                                photo.Changes.DataChanged = true;
 
161
                                Core.Database.Photos.Commit (photo);
 
162
 
 
163
                                done++;
 
164
                                if (ProcessingStep != null) {
 
165
                                        ProcessingStep (done);
 
166
                                }
 
167
                        }
 
168
 
 
169
                        Reset ();
 
170
                }
 
171
 
 
172
                protected abstract Pixbuf Process (Pixbuf input, Cms.Profile input_profile);
 
173
 
 
174
                protected virtual Pixbuf ProcessFast (Pixbuf input, Cms.Profile input_profile) {
 
175
                        return Process (input, input_profile);
 
176
                }
 
177
 
 
178
                private bool has_settings;
 
179
                public bool HasSettings {
 
180
                        get { return has_settings; }
 
181
                        protected set { has_settings = value; }
 
182
                }
 
183
 
 
184
                private Pixbuf original;
 
185
                private Pixbuf preview;
 
186
                protected void UpdatePreview () {
 
187
                        if (State.InBrowseMode) {
 
188
                                throw new Exception ("Previews cannot be made in browse mode!");
 
189
                        }
 
190
 
 
191
                        if (State.Items.Length > 1) {
 
192
                                throw new Exception ("We should have one item selected when this happened, otherwise something is terribly wrong.");
 
193
                        }
 
194
 
 
195
                        if (original == null) {
 
196
                                original = State.PhotoImageView.Pixbuf;
 
197
                        }
 
198
 
 
199
                        Pixbuf old_preview = null;
 
200
                        if (preview == null) {
 
201
                                int width, height;
 
202
                                CalcPreviewSize (original, out width, out height);
 
203
                                preview = original.ScaleSimple (width, height, InterpType.Nearest);
 
204
                        } else {
 
205
                                // We're updating a previous preview
 
206
                                old_preview = State.PhotoImageView.Pixbuf;
 
207
                        }
 
208
 
 
209
                        Pixbuf previewed = ProcessFast (preview, null);
 
210
                        State.PhotoImageView.Pixbuf = previewed;
 
211
                        State.PhotoImageView.ZoomFit (false);
 
212
                        MainWindow.Toplevel.InfoBox.UpdateHistogram (previewed);
 
213
 
 
214
                        if (old_preview != null) {
 
215
                                old_preview.Dispose ();
 
216
                        }
 
217
                }
 
218
 
 
219
                private void CalcPreviewSize (Pixbuf input, out int width, out int height) {
 
220
                        int awidth = State.PhotoImageView.Allocation.Width;
 
221
                        int aheight = State.PhotoImageView.Allocation.Height;
 
222
                        int iwidth = input.Width;
 
223
                        int iheight = input.Height;
 
224
 
 
225
                        if (iwidth <= awidth && iheight <= aheight) {
 
226
                                // Do not upscale
 
227
                                width = iwidth;
 
228
                                height = iheight;
 
229
                        } else {
 
230
                                double wratio = (double) iwidth / awidth;
 
231
                                double hratio = (double) iheight / aheight;
 
232
 
 
233
                                double ratio = Math.Max (wratio, hratio);
 
234
                                width = (int) (iwidth / ratio);
 
235
                                height = (int) (iheight / ratio);
 
236
                        }
 
237
                        //Log.DebugFormat ("Preview size: Allocation: {0}x{1}, Input: {2}x{3}, Result: {4}x{5}", awidth, aheight, iwidth, iheight, width, height);
 
238
                }
 
239
 
 
240
                public void Restore () {
 
241
                        if (original != null && State.PhotoImageView != null) {
 
242
                                State.PhotoImageView.Pixbuf = original;
 
243
                                State.PhotoImageView.ZoomFit (false);
 
244
 
 
245
                                MainWindow.Toplevel.InfoBox.UpdateHistogram (null);
 
246
                        }
 
247
 
 
248
                        Reset ();
 
249
                }
 
250
 
 
251
                private void Reset () {
 
252
                        if (preview != null) {
 
253
                                preview.Dispose ();
 
254
                        }
 
255
 
 
256
                        preview = null;
 
257
                        original = null;
 
258
                        State = null;
 
259
                }
 
260
 
 
261
                // Can be overriden to provide a specific configuration widget.
 
262
                // Returning null means no configuration widget.
 
263
                public virtual Widget ConfigurationWidget () {
59
264
                        return null;
60
265
                }
61
266
 
62
 
                public void Destroy ()
63
 
                {
64
 
                        Close ();
65
 
                }
66
 
 
67
 
                protected virtual void Close ()
68
 
                {
69
 
                        
70
 
                        if (controls != null)
71
 
                                controls.Destroy ();
72
 
 
73
 
                        if (Done != null)
74
 
                                Done (this, EventArgs.Empty);
75
 
 
76
 
                        SetView (null);
77
 
                }
78
 
        }
79
 
 
80
 
        public class GlEditor : Editor {
81
 
                protected GlTransition transition;
82
 
                protected Scale scale;
83
 
                protected Texture texture;
84
 
 
85
 
                public GlEditor (PhotoImageView view) : base (view)
86
 
                {
87
 
                        transition = new GlTransition.Flip ();
88
 
                }
89
 
 
90
 
                protected override Widget CreateControls ()
91
 
                {
92
 
                        scale = new HScale (0, 1, 0.01);
93
 
                        scale.ValueChanged += HandleValueChanged;
94
 
                        scale.WidthRequest = 250;
95
 
 
96
 
                        return scale;
97
 
                }
98
 
 
99
 
                protected override void SetView (PhotoImageView value)
100
 
                {
101
 
                        if (view != null) {
102
 
                                view.ExposeEvent -= ExposeEvent;
103
 
                                view.QueueDraw ();
104
 
                        }
105
 
 
106
 
                        base.SetView (value);
107
 
 
108
 
                        if (value == null)
109
 
                                return;
110
 
 
111
 
                        view.ExposeEvent += ExposeEvent;
112
 
                        view.QueueDraw ();
113
 
                }
114
 
 
115
 
                [GLib.ConnectBefore]
116
 
                public virtual void ExposeEvent (object sender, ExposeEventArgs args)
117
 
                {
118
 
                        view.Glx.MakeCurrent (view.GdkWindow);
119
 
                        Gl.glEnable (Gl.GL_CONVOLUTION_2D);
120
 
                        Gdk.Color c = view.Style.Background (view.State);
121
 
                        Gl.glClearColor (c.Red / (float) ushort.MaxValue,
122
 
                                         c.Blue / (float) ushort.MaxValue, 
123
 
                                         c.Green / (float) ushort.MaxValue, 
124
 
                                         1.0f);
125
 
 
126
 
                        if (texture == null) {
127
 
                                float [] kernel = new float [] { .25f, .5f, .25f,
128
 
                                                                 .5f, 1f, .5f,
129
 
                                                                 .25f, .5f, .25f};
130
 
 
131
 
#if false
132
 
                                bool supported = GlExtensionLoader.LoadExtension ("GL_ARB_imaging");
133
 
                                if (!supported) {
134
 
                                        System.Console.WriteLine ("GL_ARB_imaging not supported");
135
 
                                        return;
136
 
                                }       
137
 
#else
138
 
                                GlExtensionLoader.LoadAllExtensions ();
139
 
#endif
140
 
                                
141
 
                                Gl.glConvolutionParameteri (Gl.GL_CONVOLUTION_2D,
142
 
                                                            Gl.GL_CONVOLUTION_BORDER_MODE,
143
 
                                                            Gl.GL_REPLICATE_BORDER);
144
 
 
145
 
                                Gl.glConvolutionFilter2D (Gl.GL_CONVOLUTION_2D,
146
 
                                                          Gl.GL_INTENSITY, 
147
 
                                                          3, 
148
 
                                                          3,
149
 
                                                          Gl.GL_INTENSITY,
150
 
                                                          Gl.GL_FLOAT, 
151
 
                                                          kernel);
152
 
 
153
 
                                texture = new Texture (view.CompletePixbuf ());
154
 
                        }
155
 
 
156
 
                        Gl.glShadeModel(Gl.GL_FLAT);
157
 
 
158
 
                        Gl.glColor3f(1.0f, 1.0f, 1.0f);
159
 
                        
160
 
                        Gl.glEnable (Gl.GL_DEPTH_TEST);
161
 
                        Gl.glEnable (Gl.GL_NORMALIZE);
162
 
                        Gl.glShadeModel (Gl.GL_FLAT);
163
 
                        Gl.glEnable (Gl.GL_TEXTURE_RECTANGLE_ARB);
164
 
                        Gl.glClear (Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
165
 
 
166
 
                        
167
 
 
168
 
                        transition.Draw (view.Allocation, texture, texture);
169
 
                        
170
 
                        view.Glx.SwapBuffers (view.GdkWindow);
171
 
                        args.RetVal = true;
172
 
                        Gl.glDisable (Gl.GL_CONVOLUTION_2D);
173
 
                }
174
 
 
175
 
                private void HandleValueChanged (object sender, System.EventArgs args)
176
 
                {
177
 
                        transition.Percent = (float) scale.Value;
178
 
                        view.QueueDraw ();
179
 
                }
180
 
 
181
 
                protected override void Close ()
182
 
                {
183
 
                        if (texture != null && view != null && view.Glx != null && view.GdkWindow != null) {
184
 
                                view.Glx.MakeCurrent (view.GdkWindow);
185
 
                                texture.Dispose ();
186
 
                        }
187
 
                        
188
 
                        base.Close ();
189
 
                }
190
 
        }
191
 
 
192
 
        public class EffectEditor : Editor {
193
 
                protected IEffect effect;
194
 
                protected Widgets.ImageInfo info;
195
 
                bool double_buffer;
196
 
 
197
 
                public EffectEditor (PhotoImageView view) : base (view)
198
 
                {
199
 
                }
200
 
                
201
 
                protected override void SetView (PhotoImageView value)
202
 
                {
203
 
                        if (view != null) {
204
 
                                view.ExposeEvent -= ExposeEvent;
205
 
                                view.QueueDraw ();
206
 
                                view.DoubleBuffered = double_buffer;
207
 
                        }
208
 
 
209
 
                        base.SetView (value);
210
 
 
211
 
                        if (view == null)
212
 
                                return;
213
 
 
214
 
                        info = new Widgets.ImageInfo (view.CompletePixbuf ());
215
 
 
216
 
                        double_buffer = (view.WidgetFlags & WidgetFlags.DoubleBuffered) == WidgetFlags.DoubleBuffered;
217
 
                        view.DoubleBuffered = true;
218
 
                        view.ExposeEvent += ExposeEvent;
219
 
                        view.QueueDraw ();
220
 
                }
221
 
 
222
 
                [GLib.ConnectBefore]
223
 
                public virtual void ExposeEvent (object sender, ExposeEventArgs args)
224
 
                {
225
 
                        Context ctx = Widgets.CairoUtils.CreateContext (view.GdkWindow);
226
 
                        Gdk.Color c = view.Style.Background (view.State);
227
 
                        ctx.Source = new SolidPattern (c.Red / (float) ushort.MaxValue,
228
 
                                                       c.Blue / (float) ushort.MaxValue, 
229
 
                                                       c.Green / (float) ushort.MaxValue);
230
 
 
231
 
                        ctx.Paint ();
232
 
 
233
 
                        effect.OnExpose (ctx, view.Allocation);
234
 
                        
235
 
                        args.RetVal = true;
236
 
                }
237
 
 
238
 
                protected override void Close ()
239
 
                {
240
 
                        base.Close ();
241
 
 
242
 
                        if (effect != null)
243
 
                                effect.Dispose ();
244
 
                        effect = null;
245
 
                        
246
 
                        if (info != null)
247
 
                                info.Dispose ();
248
 
                        info = null;
249
 
                        
 
267
 
 
268
                public virtual EditorState CreateState () {
 
269
                        return new EditorState ();
 
270
                }
 
271
 
 
272
                public event InitializedHandler Initialized;
 
273
                public delegate void InitializedHandler ();
 
274
 
 
275
                public void Initialize (EditorState state) {
 
276
                        State = state;
 
277
 
 
278
                        if (Initialized != null)
 
279
                                Initialized ();
250
280
                }
251
281
        }
252
282
}
253