2
// Copyright (C) 2009 Jason Smith, Robert Dyer
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.
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.
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/>.
19
using System.Collections.Generic;
20
using System.Collections.ObjectModel;
29
using Docky.CairoHelper;
33
internal class MenuItemWidget : Gtk.EventBox
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;
44
public event EventHandler SelectedChanged;
46
public bool Selected { get; set; }
48
bool menu_icons = false;
49
public bool MenuShowingIcons {
54
if (menu_icons == value)
61
public Cairo.Color TextColor { get; set; }
63
int TextWidth { get; set; }
64
public int RequestedWidth { get; protected set; }
66
DockySurface icon_surface, emblem_surface;
68
internal MenuItemWidget (MenuItem item) : base()
70
TextColor = new Cairo.Color (1, 1, 1);
72
item.IconChanged += ItemIconChanged;
73
item.TextChanged += ItemTextChanged;
74
item.DisabledChanged += ItemDisabledChanged;
76
AddEvents ((int) Gdk.EventMask.AllEventsMask);
79
VisibleWindow = false;
87
RequestedWidth = TextWidth + 2 * Padding + 1;
89
RequestedWidth += MenuHeight + Padding;
91
SetSizeRequest (RequestedWidth, MenuHeight);
97
Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout ();
98
if (item.Mnemonic.HasValue)
99
layout.SetMarkupWithAccel (item.Text, '_', out accel);
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;
108
Pango.Rectangle logical, ink;
109
layout.GetPixelExtents (out ink, out logical);
111
TextWidth = Math.Min (MaxWidth, Math.Max (MinWidth, logical.Width));
112
HasTooltip = TextWidth < logical.Width;
117
void ItemDisabledChanged (object sender, EventArgs e)
122
void ItemTextChanged (object sender, EventArgs e)
128
void ItemIconChanged (object sender, EventArgs e)
133
protected override bool OnButtonReleaseEvent (EventButton evnt)
137
return item.Disabled;
140
protected override bool OnMotionNotifyEvent (EventMotion evnt)
142
if (!item.Disabled && !Selected) {
144
if (SelectedChanged != null)
145
SelectedChanged (this, EventArgs.Empty);
151
protected override bool OnEnterNotifyEvent (EventCrossing evnt)
153
if (!item.Disabled && !Selected) {
155
if (SelectedChanged != null)
156
SelectedChanged (this, EventArgs.Empty);
162
protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
164
if (!item.Disabled && Selected) {
166
if (SelectedChanged != null)
167
SelectedChanged (this, EventArgs.Empty);
170
return base.OnLeaveNotifyEvent (evnt);
173
protected override bool OnQueryTooltip (int x, int y, bool keyboard_tooltip, Tooltip tooltip)
175
tooltip.Text = item.Text;
179
void PlaceSurface (Context cr, DockySurface surface, Gdk.Rectangle allocation)
181
int iconSize = allocation.Height - IconBuffer * 2;
183
int x = allocation.X + Padding + ((iconSize - surface.Width) / 2);
184
int y = allocation.Y + IconBuffer + ((iconSize - surface.Height) / 2);
186
cr.SetSource (surface.Internal, x, y);
189
DockySurface LoadIcon (Pixbuf icon, int size)
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 ();
200
DockySurface LoadIcon (string icon, int size)
202
bool monochrome = icon.StartsWith ("[monochrome]");
204
icon = icon.Substring ("[monochrome]".Length);
207
DockySurface surface = LoadIcon (DockServices.Drawing.LoadIcon (icon, size), size);
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 ();
221
protected override bool OnExposeEvent (EventExpose evnt)
226
Gdk.Rectangle allocation = Allocation;
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 ();
235
if (item.ForcePixbuf == null)
236
icon_surface = LoadIcon (item.Icon, pixbufSize);
238
icon_surface = LoadIcon (item.ForcePixbuf, pixbufSize);
240
if (!string.IsNullOrEmpty (item.Emblem))
241
emblem_surface = LoadIcon (item.Emblem, pixbufSize);
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);
251
if (item.ShowIcons) {
252
PlaceSurface (cr, icon_surface, allocation);
253
cr.PaintWithAlpha (item.Disabled ? 0.5 : 1);
256
cr.Operator = Operator.Add;
257
PlaceSurface (cr, icon_surface, allocation);
258
cr.PaintWithAlpha (.8);
259
cr.Operator = Operator.Over;
262
if (!string.IsNullOrEmpty (item.Emblem)) {
263
PlaceSurface (cr, emblem_surface, allocation);
268
Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout ();
270
if (item.Mnemonic.HasValue)
271
layout.SetMarkupWithAccel (item.Text, '_', out accel);
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;
280
Pango.Rectangle logical, ink;
281
layout.GetPixelExtents (out ink, out logical);
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);
295
public override void Dispose ()
297
if (icon_surface != null)
298
icon_surface.Dispose ();
300
if (emblem_surface != null)
301
emblem_surface.Dispose ();