~mantas/pinta/stable

« back to all changes in this revision

Viewing changes to Pinta/Widgets/LayersListWidget.cs

  • Committer: Iain Lane
  • Date: 2010-03-13 18:20:18 UTC
  • mfrom: (1.1.2)
  • Revision ID: git-v1:1781694a68ecf232d0110c0b2f3d4a1b96c74ec2
Merge commit 'upstream/0.2'

Conflicts:
        debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
//  
4
4
// Author:
5
5
//       Jonathan Pobst <monkey@jpobst.com>
 
6
//       Greg Lowe <greg@vis.net.nz>
6
7
// 
7
8
// Copyright (c) 2010 Jonathan Pobst
8
9
// 
27
28
using System;
28
29
using System.Linq;
29
30
using Pinta.Core;
 
31
using Gtk;
30
32
 
31
33
namespace Pinta
32
34
{
33
 
        // TODO: This needs to be completely redone properly
34
 
        // ie: more than 3 layers, scrolling, etc.
35
 
        // is probably supposed to be a treeview?
36
35
        [System.ComponentModel.ToolboxItem (true)]
37
 
        public class LayersListWidget : Gtk.DrawingArea
 
36
        public class LayersListWidget : ScrolledWindow
38
37
        {
39
 
                private int thumb_width = 56;
40
 
                private int thumb_height = 42;
41
 
                
42
 
                private Cairo.Rectangle layer1_bounds = new Cairo.Rectangle (0, 2, 175, 47);
43
 
                private Cairo.Rectangle layer2_bounds = new Cairo.Rectangle (0, 49, 175, 47);
44
 
                private Cairo.Rectangle layer3_bounds = new Cairo.Rectangle (0, 96, 175, 47);
45
 
 
46
 
                private Cairo.Rectangle layer1_toggle = new Cairo.Rectangle (155, 8, 16, 16);
47
 
                private Cairo.Rectangle layer2_toggle = new Cairo.Rectangle (155, 55, 16, 16);
48
 
                private Cairo.Rectangle layer3_toggle = new Cairo.Rectangle (155, 102, 16, 16);
49
 
                
50
 
                private Gdk.Pixbuf layer_visible;
51
 
                private Gdk.Pixbuf layer_invisible;
52
 
                
53
 
                private Cairo.Surface transparent;
 
38
                private TreeView tree;
 
39
                private TreeStore store;
 
40
                                
 
41
                private const int store_index_thumbnail = 0;
 
42
                private const int store_index_name = 1;
 
43
                private const int store_index_visibility = 2;           
 
44
                private const int store_index_layer = 3;
 
45
                
 
46
                private const int thumbnail_width = 60;
 
47
                private const int thumbnail_height = 40;
 
48
                private const int thumbnail_column_width = 70;
 
49
                
 
50
                private const int name_column_min_width = 100;
 
51
                private const int name_column_max_width = 300;
 
52
                
 
53
                private const int visibility_column_width = 30;
54
54
                
55
55
                public LayersListWidget ()
56
56
                {
57
 
                        this.AddEvents ((int)Gdk.EventMask.ButtonPressMask);
58
 
                        
59
 
                        // Insert initialization code here.
60
 
                        layer_visible = PintaCore.Resources.GetIcon ("LayersWidget.Visible.png");
61
 
                        layer_invisible = PintaCore.Resources.GetIcon ("LayersWidget.Hidden.png");
62
 
                        
63
 
                        transparent = new Cairo.ImageSurface (Cairo.Format.ARGB32, thumb_width, thumb_height);
64
 
                        Cairo.Color gray = new Cairo.Color (.75, .75, .75);
65
 
                        
66
 
                        // Create checkerboard background       
67
 
                        int grid_width = 4;
68
 
                        
69
 
                        using (Cairo.Context g = new Cairo.Context (transparent)) {
70
 
                                g.Color = new Cairo.Color (1, 1, 1);
71
 
                                g.Paint ();
72
 
                                
73
 
                                for (int y = 0; y < thumb_height; y += grid_width)              
74
 
                                        for (int x = 0; x < thumb_width; x += grid_width) {
75
 
                                                if ((x / grid_width % 2) + (y / grid_width % 2) == 1)
76
 
                                                        g.FillRectangle (new Cairo.Rectangle (x, y, grid_width, grid_width), gray);
77
 
                                }
78
 
                        }       
79
 
                        
80
 
                        PintaCore.Layers.LayerAdded += HandlePintaCoreLayersLayerAddedOrRemoved;
81
 
                        PintaCore.Layers.LayerRemoved += HandlePintaCoreLayersLayerAddedOrRemoved;
82
 
                        PintaCore.Layers.SelectedLayerChanged += HandlePintaCoreLayersLayerAddedOrRemoved;
83
 
                        PintaCore.History.HistoryItemAdded += HandlePintaCoreHistoryHistoryItemAdded;
84
 
                        PintaCore.History.ActionRedone += HandlePintaCoreHistoryHistoryItemAdded;
85
 
                        PintaCore.History.ActionUndone += HandlePintaCoreHistoryHistoryItemAdded;
86
 
                }
87
 
 
88
 
                private void HandlePintaCoreHistoryHistoryItemAdded (object sender, EventArgs e)
89
 
                {
90
 
                        this.GdkWindow.Invalidate ();
91
 
                }
92
 
 
93
 
                private void HandlePintaCoreLayersLayerAddedOrRemoved (object sender, EventArgs e)
94
 
                {
95
 
                        this.GdkWindow.Invalidate ();
96
 
 
 
57
                        SetSizeRequest (200, 300);
 
58
                        
 
59
                        SetPolicy (PolicyType.Automatic, PolicyType.Automatic);
 
60
                        
 
61
                        tree = new TreeView ();
 
62
                        
 
63
                        tree.HeadersVisible = false;
 
64
                        tree.FixedHeightMode = true;
 
65
                        tree.Reorderable = false;
 
66
                        tree.EnableGridLines = TreeViewGridLines.None;
 
67
                        tree.EnableTreeLines = false;
 
68
                        tree.ShowExpanders = false;
 
69
                        
 
70
                        var crs = new CellRendererSurface (thumbnail_width, thumbnail_height);
 
71
                        var col = new TreeViewColumn ("Thumbnail", crs, "surface", store_index_thumbnail);
 
72
                        col.Sizing = TreeViewColumnSizing.Fixed;
 
73
                        col.FixedWidth = thumbnail_column_width;
 
74
                        tree.AppendColumn (col);
 
75
                        
 
76
                        col = new TreeViewColumn ("Name", new CellRendererText (), "text", store_index_name);
 
77
                        col.Sizing = TreeViewColumnSizing.Fixed;                        
 
78
                        col.Expand = true;
 
79
                        col.MinWidth = name_column_min_width;
 
80
                        col.MaxWidth = name_column_max_width;
 
81
                        tree.AppendColumn (col);
 
82
                        
 
83
                        var crt = new CellRendererToggle ();
 
84
                        crt.Activatable = true;
 
85
                        crt.Toggled += LayerVisibilityToggled;
 
86
                        
 
87
                        col = new TreeViewColumn ("Visible", crt, "active", store_index_visibility);
 
88
                        col.Sizing = TreeViewColumnSizing.Fixed;
 
89
                        col.FixedWidth = visibility_column_width;
 
90
                        tree.AppendColumn (col);
 
91
                        
 
92
                        store = new TreeStore (typeof (Cairo.ImageSurface), typeof (string), typeof (bool), typeof (Layer));
 
93
                        
 
94
                        tree.Model = store;
 
95
                        tree.RowActivated += HandleRowActivated;
 
96
                        
 
97
                        Add (tree);
 
98
                        
 
99
                        PintaCore.Layers.LayerAdded += HandleLayerAddedOrRemoved;
 
100
                        PintaCore.Layers.LayerRemoved += HandleLayerAddedOrRemoved;
 
101
                        PintaCore.Layers.SelectedLayerChanged += HandleSelectedLayerChanged;
 
102
                        PintaCore.Layers.LayerPropertyChanged += HandlePintaCoreLayersLayerPropertyChanged;
 
103
                        
 
104
                        PintaCore.History.HistoryItemAdded += HandleHistoryItemAdded;
 
105
                        PintaCore.History.ActionRedone += HandleHistoryItemAdded;
 
106
                        PintaCore.History.ActionUndone += HandleHistoryItemAdded;                       
 
107
                        
 
108
                        tree.CursorChanged += HandleLayerSelected;
 
109
                        
 
110
                        ShowAll ();
 
111
                }
 
112
                
 
113
                private Layer GetSelectedLayerInTreeView ()
 
114
                {
 
115
                        Layer layer = null;
 
116
                        TreeIter iter;
 
117
                        
 
118
                        var paths = tree.Selection.GetSelectedRows ();
 
119
                                
 
120
                        if (paths != null && paths.Length > 0 && store.GetIter (out iter, paths[0])) {
 
121
                                layer = store.GetValue (iter, store_index_layer) as Layer;
 
122
                        }
 
123
                        
 
124
                        return layer;
 
125
                }
 
126
                
 
127
                private void SelectLayerInTreeView (int layerIndex)
 
128
                {                                                                       
 
129
                        var path = new TreePath (new int[] { layerIndex });
 
130
                        tree.Selection.SelectPath (path);
 
131
                }
 
132
                
 
133
                private void HandleLayerSelected (object o, EventArgs e)
 
134
                {                       
 
135
                        var layer = GetSelectedLayerInTreeView ();                      
 
136
                        if (PintaCore.Layers.CurrentLayer != layer)
 
137
                                PintaCore.Layers.SetCurrentLayer (GetSelectedLayerInTreeView ());
 
138
                }
 
139
                
 
140
                private void LayerVisibilityToggled (object o, ToggledArgs args)
 
141
                {
 
142
                        TreeIter iter;          
 
143
                        if (store.GetIter (out iter, new TreePath (args.Path))) {
 
144
                                bool b = (bool) store.GetValue (iter, store_index_visibility);                          
 
145
                                store.SetValue(iter, store_index_visibility, !b);
 
146
                                
 
147
                                var layer = (Layer) store.GetValue (iter, store_index_layer);
 
148
                                SetLayerVisibility (layer, !b);
 
149
                        }
 
150
                }
 
151
                
 
152
                private void HandleHistoryItemAdded (object sender, EventArgs e)
 
153
                {       
 
154
                        // TODO: Handle this more efficiently.
 
155
                        Reset ();
 
156
                }
 
157
                
 
158
                private void HandleSelectedLayerChanged (object sender, EventArgs e)
 
159
                {
 
160
                        // TODO: Handle this more efficiently.
 
161
                        Reset ();
 
162
                }               
 
163
 
 
164
                void HandlePintaCoreLayersLayerPropertyChanged (object sender, PropertyChangedEventArgs e)
 
165
                {
 
166
                        // TODO: Handle this more efficiently.
 
167
                        Reset ();
 
168
                }               
 
169
                
 
170
                private void HandleLayerAddedOrRemoved(object sender, EventArgs e)
 
171
                {
 
172
                        // TODO: Handle this more efficiently.
 
173
                        Reset ();
 
174
                        
97
175
                        // TODO: this should be handled elsewhere
98
176
                        PintaCore.Workspace.Invalidate ();
99
177
                }
100
 
 
101
 
                protected override bool OnButtonPressEvent (Gdk.EventButton ev)
102
 
                {
103
 
                        Layer toggled = GetClickedLayerVisibleToggle (ev.X, ev.Y);
104
 
                        Layer clicked = GetClickedLayer (ev.X, ev.Y);
105
 
                        
106
 
                        if (toggled != null)
107
 
                                toggled.Hidden = !toggled.Hidden;
108
 
                        else if (clicked != null)
109
 
                                PintaCore.Layers.SetCurrentLayer (clicked);
110
 
                        
111
 
                        GdkWindow.Invalidate ();
112
 
                        PintaCore.Workspace.Invalidate ();
113
 
                        
114
 
                        // Insert button press handling code here.
115
 
                        return base.OnButtonPressEvent (ev);
116
 
                }
117
 
 
118
 
                private Layer GetClickedLayer (double x, double y)
119
 
                {
120
 
                        int count = PintaCore.Layers.Count;
121
 
                        
122
 
                        if (count == 1) {
123
 
                                if (layer1_bounds.ContainsPoint (x, y))
124
 
                                        return PintaCore.Layers[0];
125
 
                        } else if (count == 2) {
126
 
                                if (layer1_bounds.ContainsPoint (x, y))
127
 
                                        return PintaCore.Layers[1]; 
128
 
                                else if (layer2_bounds.ContainsPoint (x, y))
129
 
                                        return PintaCore.Layers[0];
130
 
                        } else {
131
 
                                if (layer1_bounds.ContainsPoint (x, y))
132
 
                                        return PintaCore.Layers[2]; 
133
 
                                else if (layer2_bounds.ContainsPoint (x, y))
134
 
                                        return PintaCore.Layers[1]; 
135
 
                                else if (layer3_bounds.ContainsPoint (x, y))
136
 
                                        return PintaCore.Layers[0];
137
 
                        }
138
 
                        
139
 
                        return null;
140
 
                }
141
 
 
142
 
                private Layer GetClickedLayerVisibleToggle (double x, double y)
143
 
                {
144
 
                        int count = PintaCore.Layers.Count;
145
 
                        
146
 
                        if (count == 1) {
147
 
                                if (layer1_toggle.ContainsPoint (x, y))
148
 
                                        return PintaCore.Layers[0];
149
 
                        } else if (count == 2) {
150
 
                                if (layer1_toggle.ContainsPoint (x, y))
151
 
                                        return PintaCore.Layers[1]; 
152
 
                                else if (layer2_toggle.ContainsPoint (x, y))
153
 
                                        return PintaCore.Layers[0];
154
 
                        } else {
155
 
                                if (layer1_toggle.ContainsPoint (x, y))
156
 
                                        return PintaCore.Layers[2]; 
157
 
                                else if (layer2_toggle.ContainsPoint (x, y))
158
 
                                        return PintaCore.Layers[1]; 
159
 
                                else if (layer3_toggle.ContainsPoint (x, y))
160
 
                                        return PintaCore.Layers[0];
161
 
                        }
162
 
                        
163
 
                        return null;
 
178
                
 
179
                private void HandleRowActivated(object o, RowActivatedArgs args)
 
180
                {
 
181
                        // The double click to activate will have already selected the layer.
 
182
                        PintaCore.Actions.Layers.Properties.Activate ();
 
183
                }
 
184
                
 
185
                private void Reset()
 
186
                {
 
187
                        store.Clear();
 
188
                        foreach (var layer in PintaCore.Layers.Reverse ()) {
 
189
                                store.AppendValues (layer.Surface, layer.Name, !layer.Hidden, layer);
 
190
                        }
 
191
                                                
 
192
                        SelectLayerInTreeView (PintaCore.Layers.Count - PintaCore.Layers.CurrentLayerIndex - 1);
164
193
                }               
165
 
                protected override bool OnExposeEvent (Gdk.EventExpose ev)
166
 
                {
167
 
                        base.OnExposeEvent (ev);
168
 
                        
169
 
                        
170
 
                        int y = 6;
171
 
                        
172
 
                        foreach (var item in PintaCore.Layers.Reverse ()) {
173
 
                                DrawLayer (item, 5, y, item.Name, item == PintaCore.Layers.CurrentLayer);
174
 
                                y += 47;
175
 
                        }
176
 
                        
177
 
                        // Insert drawing code here.
178
 
                        return true;
179
 
                }
180
 
 
181
 
                protected override void OnSizeAllocated (Gdk.Rectangle allocation)
182
 
                {
183
 
                        base.OnSizeAllocated (allocation);
184
 
                        // Insert layout code here.
185
 
                }
186
 
 
187
 
                protected override void OnSizeRequested (ref Gtk.Requisition requisition)
188
 
                {
189
 
                        // Calculate desired size here.
190
 
                        requisition.Height = 145;
191
 
                        requisition.Width = 175;
192
 
                }
193
194
                
194
 
                private void DrawLayer (Layer l, int x, int y, string name, bool selected)
 
195
                private void SetLayerVisibility (Layer layer, bool visibility)
195
196
                {
196
 
                        using (Cairo.Context g = Gdk.CairoHelper.Create (GdkWindow)) {
197
 
                        
198
 
                        if (selected) {
199
 
                                g.FillRectangle (new Cairo.Rectangle (0, y - 3, 300, 47), new Cairo.Color (0, 0, 1));
200
 
 
201
 
                        }
202
 
                        
203
 
                        g.Save ();
204
 
                        g.Translate (x, y);
205
 
                        g.SetSource (transparent);
206
 
                        g.Paint ();
207
 
 
208
 
                        g.Scale (56 / PintaCore.Workspace.ImageSize.X, 42 / PintaCore.Workspace.ImageSize.Y);
209
 
                        
210
 
                        g.SetSource (l.Surface);
211
 
                        g.Paint ();
212
 
                        g.Restore ();
213
 
                        
214
 
                        g.DrawRectangle (new Cairo.Rectangle (x, y, 56, 42), new Cairo.Color (0, 0, 0), 1);
215
 
                        g.MoveTo (x + 70, y + 26);
216
 
                        g.TextPath (name);
217
 
                        g.Fill ();
218
 
                        
219
 
                        if (!l.Hidden)
220
 
                                Gdk.CairoHelper.SetSourcePixbuf (g, layer_visible, 155, y + 3);
221
 
                        else
222
 
                                Gdk.CairoHelper.SetSourcePixbuf (g, layer_invisible, 155, y + 3);
223
 
                        
224
 
                        g.Paint ();
225
 
                        
226
 
                        }
227
 
                        
 
197
                        if (layer != null)
 
198
                                layer.Hidden = !visibility;
 
199
                        
 
200
                        var initial = new LayerProperties(layer.Name, visibility, layer.Opacity);
 
201
                        var updated = new LayerProperties(layer.Name, !visibility, layer.Opacity);
 
202
                        
 
203
                        var historyItem = new UpdateLayerPropertiesHistoryItem (
 
204
                                "Menu.Layers.LayerProperties.png",
 
205
                                (visibility) ? "Layer Shown" : "Layer Hidden",
 
206
                                PintaCore.Layers.IndexOf (layer),
 
207
                                initial,
 
208
                                updated);
 
209
                        
 
210
                        PintaCore.History.PushNewItem (historyItem);
 
211
                        
 
212
                        //TODO Call this automatically when the layer visibility changes.
 
213
                        PintaCore.Workspace.Invalidate ();                      
228
214
                }
229
215
        }
230
216
}