~ubuntu-branches/ubuntu/lucid/docky/lucid-proposed

« back to all changes in this revision

Viewing changes to Docky/Docky/Menus/MenuItemWidget.cs

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2010-02-17 15:10:07 UTC
  • Revision ID: james.westby@ubuntu.com-20100217151007-msxpd0lsj300ndde
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  
 
2
//  Copyright (C) 2009 Jason Smith, Robert Dyer
 
3
// 
 
4
//  This program is free software: you can redistribute it and/or modify
 
5
//  it under the terms of the GNU General Public License as published by
 
6
//  the Free Software Foundation, either version 3 of the License, or
 
7
//  (at your option) any later version.
 
8
// 
 
9
//  This program is distributed in the hope that it will be useful,
 
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
//  GNU General Public License for more details.
 
13
// 
 
14
//  You should have received a copy of the GNU General Public License
 
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
// 
 
17
 
 
18
using System;
 
19
using System.Collections.Generic;
 
20
using System.Collections.ObjectModel;
 
21
using System.Linq;
 
22
using System.Text;
 
23
 
 
24
using Cairo;
 
25
using Gdk;
 
26
using Gtk;
 
27
 
 
28
using Docky.Services;
 
29
using Docky.CairoHelper;
 
30
 
 
31
namespace Docky.Menus
 
32
{
 
33
        internal class MenuItemWidget : Gtk.EventBox
 
34
        {
 
35
                const int MenuHeight = 22;
 
36
                const int MinWidth = 100;
 
37
                const int MaxWidth = 350;
 
38
                const int FontSize = 11;
 
39
                const int Padding = 4;
 
40
                const int IconBuffer = Padding - 1;
 
41
                
 
42
                public MenuItem item;
 
43
                
 
44
                public event EventHandler SelectedChanged;
 
45
                
 
46
                public bool Selected { get; set; }
 
47
                
 
48
                bool menu_icons = false;
 
49
                public bool MenuShowingIcons {
 
50
                        get {
 
51
                                return menu_icons;
 
52
                        }
 
53
                        set {
 
54
                                if (menu_icons == value)
 
55
                                        return;
 
56
                                menu_icons = value;
 
57
                                SetSize ();
 
58
                        }
 
59
                }
 
60
                
 
61
                public Cairo.Color TextColor { get; set; }
 
62
                
 
63
                int TextWidth { get; set; }
 
64
                public int RequestedWidth { get; protected set; }
 
65
                
 
66
                DockySurface icon_surface, emblem_surface;
 
67
                
 
68
                internal MenuItemWidget (MenuItem item) : base()
 
69
                {
 
70
                        TextColor = new Cairo.Color (1, 1, 1);
 
71
                        this.item = item;
 
72
                        item.IconChanged += ItemIconChanged;
 
73
                        item.TextChanged += ItemTextChanged;
 
74
                        item.DisabledChanged += ItemDisabledChanged;
 
75
                        
 
76
                        AddEvents ((int) Gdk.EventMask.AllEventsMask);
 
77
                        
 
78
                        HasTooltip = true;
 
79
                        VisibleWindow = false;
 
80
                        AboveChild = true;
 
81
                        
 
82
                        CalcTextWidth ();
 
83
                }
 
84
                
 
85
                void SetSize ()
 
86
                {
 
87
                        RequestedWidth = TextWidth + 2 * Padding + 1;
 
88
                        if (MenuShowingIcons)
 
89
                                RequestedWidth += MenuHeight + Padding;
 
90
                        
 
91
                        SetSizeRequest (RequestedWidth, MenuHeight);
 
92
                }
 
93
                
 
94
                void CalcTextWidth ()
 
95
                {
 
96
                        char accel;
 
97
                        Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout ();
 
98
                        if (item.Mnemonic.HasValue)
 
99
                                layout.SetMarkupWithAccel (item.Text, '_', out accel);
 
100
                        else
 
101
                                layout.SetMarkup (item.Text);
 
102
                        layout.Width = Pango.Units.FromPixels (2 * MaxWidth);
 
103
                        layout.FontDescription = Style.FontDescription;
 
104
                        layout.Ellipsize = Pango.EllipsizeMode.End;
 
105
                        layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels (FontSize);
 
106
                        layout.FontDescription.Weight = Pango.Weight.Bold;
 
107
                        
 
108
                        Pango.Rectangle logical, ink;
 
109
                        layout.GetPixelExtents (out ink, out logical);
 
110
                        
 
111
                        TextWidth = Math.Min (MaxWidth, Math.Max (MinWidth, logical.Width));
 
112
                        HasTooltip = TextWidth < logical.Width;
 
113
                        
 
114
                        SetSize ();
 
115
                }
 
116
 
 
117
                void ItemDisabledChanged (object sender, EventArgs e)
 
118
                {
 
119
                        QueueDraw ();
 
120
                }
 
121
 
 
122
                void ItemTextChanged (object sender, EventArgs e)
 
123
                {
 
124
                        CalcTextWidth ();
 
125
                        QueueDraw ();
 
126
                }
 
127
 
 
128
                void ItemIconChanged (object sender, EventArgs e)
 
129
                {
 
130
                        QueueDraw ();
 
131
                }
 
132
                
 
133
                protected override bool OnButtonReleaseEvent (EventButton evnt)
 
134
                {
 
135
                        if (!item.Disabled)
 
136
                                item.SendClick ();
 
137
                        return item.Disabled;
 
138
                }
 
139
                
 
140
                protected override bool OnMotionNotifyEvent (EventMotion evnt)
 
141
                {
 
142
                        if (!item.Disabled && !Selected) {
 
143
                                Selected = true;
 
144
                                if (SelectedChanged != null)
 
145
                                        SelectedChanged (this, EventArgs.Empty);
 
146
                                QueueDraw ();
 
147
                        }
 
148
                        return false;
 
149
                }
 
150
                
 
151
                protected override bool OnEnterNotifyEvent (EventCrossing evnt)
 
152
                {
 
153
                        if (!item.Disabled && !Selected) {
 
154
                                Selected = true;
 
155
                                if (SelectedChanged != null)
 
156
                                        SelectedChanged (this, EventArgs.Empty);
 
157
                                QueueDraw ();
 
158
                        }
 
159
                        return false;
 
160
                }
 
161
 
 
162
                protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
 
163
                {
 
164
                        if (!item.Disabled && Selected) {
 
165
                                Selected = false;
 
166
                                if (SelectedChanged != null)
 
167
                                        SelectedChanged (this, EventArgs.Empty);
 
168
                                QueueDraw ();
 
169
                        }
 
170
                        return base.OnLeaveNotifyEvent (evnt);
 
171
                }
 
172
                
 
173
                protected override bool OnQueryTooltip (int x, int y, bool keyboard_tooltip, Tooltip tooltip)
 
174
                {
 
175
                        tooltip.Text = item.Text;
 
176
                        return true;
 
177
                }
 
178
                
 
179
                void PlaceSurface (Context cr, DockySurface surface, Gdk.Rectangle allocation)
 
180
                {
 
181
                        int iconSize = allocation.Height - IconBuffer * 2;
 
182
                        
 
183
                        int x = allocation.X + Padding + ((iconSize - surface.Width) / 2);
 
184
                        int y = allocation.Y + IconBuffer + ((iconSize - surface.Height) / 2);
 
185
                        
 
186
                        cr.SetSource (surface.Internal, x, y);
 
187
                }
 
188
                
 
189
                DockySurface LoadIcon (Pixbuf icon, int size)
 
190
                {
 
191
                        DockySurface surface;
 
192
                        using (Gdk.Pixbuf pixbuf = DockServices.Drawing.ARScale (size, size, icon)) {
 
193
                                surface = new DockySurface (pixbuf.Width, pixbuf.Height);
 
194
                                Gdk.CairoHelper.SetSourcePixbuf (surface.Context, pixbuf, 0, 0);
 
195
                                surface.Context.Paint ();
 
196
                        }
 
197
                        return surface;
 
198
                }
 
199
                
 
200
                DockySurface LoadIcon (string icon, int size)
 
201
                {
 
202
                        bool monochrome = icon.StartsWith ("[monochrome]");
 
203
                        if (monochrome) {
 
204
                                icon = icon.Substring ("[monochrome]".Length);
 
205
                        }
 
206
                        
 
207
                        DockySurface surface = LoadIcon (DockServices.Drawing.LoadIcon (icon, size), size);
 
208
                        
 
209
                        if (monochrome) {
 
210
                                surface.Context.Operator = Operator.Atop;
 
211
                                double v = TextColor.GetValue ();
 
212
                                // reduce value by 20%
 
213
                                surface.Context.Color = TextColor.SetValue (v * .8);
 
214
                                surface.Context.Paint ();
 
215
                                surface.ResetContext ();
 
216
                        }
 
217
                        
 
218
                        return surface;
 
219
                }
 
220
                
 
221
                protected override bool OnExposeEvent (EventExpose evnt)
 
222
                {
 
223
                        if (!IsRealized)
 
224
                                return false;
 
225
                        
 
226
                        Gdk.Rectangle allocation = Allocation;
 
227
                        
 
228
                        int pixbufSize = allocation.Height - IconBuffer * 2;
 
229
                        if (item.ShowIcons && (icon_surface == null || (icon_surface.Height != pixbufSize && icon_surface.Width != pixbufSize))) {
 
230
                                if (icon_surface != null)
 
231
                                        icon_surface.Dispose ();
 
232
                                if (emblem_surface != null)
 
233
                                        emblem_surface.Dispose ();
 
234
                                
 
235
                                if (item.ForcePixbuf == null)
 
236
                                        icon_surface = LoadIcon (item.Icon, pixbufSize);
 
237
                                else
 
238
                                        icon_surface = LoadIcon (item.ForcePixbuf, pixbufSize);
 
239
                                
 
240
                                if (!string.IsNullOrEmpty (item.Emblem))
 
241
                                        emblem_surface = LoadIcon (item.Emblem, pixbufSize);
 
242
                        }
 
243
                        
 
244
                        using (Cairo.Context cr = Gdk.CairoHelper.Create (evnt.Window)) {
 
245
                                if (Selected && !item.Disabled) {
 
246
                                        cr.Rectangle (allocation.X, allocation.Y, allocation.Width, allocation.Height);
 
247
                                        cr.Color = TextColor.SetAlpha (.1);
 
248
                                        cr.Fill ();
 
249
                                }
 
250
                                
 
251
                                if (item.ShowIcons) {
 
252
                                        PlaceSurface (cr, icon_surface, allocation);
 
253
                                        cr.PaintWithAlpha (item.Disabled ? 0.5 : 1);
 
254
                                        
 
255
                                        if (item.Bold) {
 
256
                                                cr.Operator = Operator.Add;
 
257
                                                PlaceSurface (cr, icon_surface, allocation);
 
258
                                                cr.PaintWithAlpha (.8);
 
259
                                                cr.Operator = Operator.Over;
 
260
                                        }
 
261
                                        
 
262
                                        if (!string.IsNullOrEmpty (item.Emblem)) {
 
263
                                                PlaceSurface (cr, emblem_surface, allocation);
 
264
                                                cr.Paint ();
 
265
                                        }
 
266
                                }
 
267
                        
 
268
                                Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout ();
 
269
                                char accel;
 
270
                                if (item.Mnemonic.HasValue)
 
271
                                        layout.SetMarkupWithAccel (item.Text, '_', out accel);
 
272
                                else
 
273
                                        layout.SetMarkup (item.Text);
 
274
                                layout.Width = Pango.Units.FromPixels (TextWidth);
 
275
                                layout.FontDescription = Style.FontDescription;
 
276
                                layout.Ellipsize = Pango.EllipsizeMode.End;
 
277
                                layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels (FontSize);
 
278
                                layout.FontDescription.Weight = Pango.Weight.Bold;
 
279
                                
 
280
                                Pango.Rectangle logical, ink;
 
281
                                layout.GetPixelExtents (out ink, out logical);
 
282
                                
 
283
                                int offset = Padding;
 
284
                                if (MenuShowingIcons)
 
285
                                        offset += MenuHeight + Padding;
 
286
                                cr.MoveTo (allocation.X + offset, allocation.Y + (allocation.Height - logical.Height) / 2);
 
287
                                Pango.CairoHelper.LayoutPath (cr, layout);
 
288
                                cr.Color = TextColor.SetAlpha (item.Disabled ? 0.5 : 1);
 
289
                                cr.Fill ();
 
290
                        }
 
291
                        
 
292
                        return true;
 
293
                }
 
294
                
 
295
                public override void Dispose ()
 
296
                {
 
297
                        if (icon_surface != null)
 
298
                                icon_surface.Dispose ();
 
299
                        
 
300
                        if (emblem_surface != null)
 
301
                                emblem_surface.Dispose ();
 
302
                        base.Dispose ();
 
303
                }
 
304
        }
 
305
}