~and471/+junk/do-with-docky

« back to all changes in this revision

Viewing changes to Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/DockPopupMenu.cs

  • Committer: rugby471 at gmail
  • Date: 2010-10-15 16:08:38 UTC
  • Revision ID: rugby471@gmail.com-20101015160838-z9m3utbf7bxzb5ty
reverted to before docky removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// DockPopupMenu.cs
 
2
// 
 
3
// Copyright (C) 2008 GNOME Do
 
4
//
 
5
// This program is free software: you can redistribute it and/or modify
 
6
// it under the terms of the GNU General Public License as published by
 
7
// the Free Software Foundation, either version 3 of the License, or
 
8
// (at your option) any later version.
 
9
//
 
10
// This program is distributed in the hope that it will be useful,
 
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
// GNU General Public License for more details.
 
14
//
 
15
// You should have received a copy of the GNU General Public License
 
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
//
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Linq;
 
22
 
 
23
using Cairo;
 
24
using Gdk;
 
25
using Gtk;
 
26
 
 
27
using Do.Interface;
 
28
using Do.Interface.CairoUtils;
 
29
using Do.Platform;
 
30
 
 
31
using Docky.Utilities;
 
32
 
 
33
namespace Docky.Interface.Menus
 
34
{
 
35
        
 
36
        
 
37
        public class DockPopupMenu : Gtk.Window
 
38
        {
 
39
                public static readonly Cairo.Color BackgroundColor = new Cairo.Color (0.13, 0.13, 0.13, .95);
 
40
                
 
41
                const int TailHeight = 20;
 
42
                const int TailWidth = 25;
 
43
                new const int BorderWidth = 2;
 
44
                const int HeaderSize = 20;
 
45
                const int Radius = 6;
 
46
                const int Width = 180;
 
47
                const double Curviness = .05;
 
48
                const string FormatString = "<b>{0}</b>";
 
49
                
 
50
                int horizontal_offset;
 
51
                int vertical_offset;
 
52
                
 
53
                string header;
 
54
                
 
55
                Gtk.Alignment align;
 
56
                
 
57
                public Gtk.VBox Container { get; private set; }
 
58
 
 
59
                // we are making a new one here for speed reasons
 
60
                public new bool Visible { get; private set; }
 
61
                
 
62
                int HeaderTextOffset {
 
63
                        get {
 
64
                                if (DockPreferences.Orientation == DockOrientation.Bottom)
 
65
                                        return (HeaderSize + 10) / 2;
 
66
                                else
 
67
                                        return (TailHeight + 3) + (HeaderSize + 10) / 2;
 
68
                        }
 
69
                }
 
70
                
 
71
                public DockPopupMenu() : base (Gtk.WindowType.Popup)
 
72
                {
 
73
                        AcceptFocus = false;
 
74
                        Decorated = false;
 
75
                        KeepAbove = true;
 
76
                        AppPaintable = true;
 
77
                        SkipPagerHint = true;
 
78
                        SkipTaskbarHint = true;
 
79
                        Resizable = false;
 
80
                        Modal = true;
 
81
                        TypeHint = WindowTypeHint.PopupMenu;
 
82
                        
 
83
                        WidthRequest = Width;
 
84
                        
 
85
                        this.SetCompositeColormap ();
 
86
                        
 
87
                        AddEvents ((int) EventMask.PointerMotionMask | 
 
88
                                   (int) EventMask.LeaveNotifyMask |
 
89
                                   (int) EventMask.ButtonPressMask | 
 
90
                                   (int) EventMask.ButtonReleaseMask |
 
91
                                   (int) EventMask.FocusChangeMask);
 
92
                        
 
93
                        Container = new Gtk.VBox ();
 
94
                        Build ();
 
95
                        
 
96
                        DockPreferences.OrientationChanged += SetAlignment;
 
97
                }
 
98
                
 
99
                protected virtual void Build ()
 
100
                {
 
101
                        align = new Gtk.Alignment (0.5f, 0.5f, 1, 1);
 
102
                        SetAlignment ();
 
103
                        
 
104
                        align.Add (Container);
 
105
                        Add (align);
 
106
                        align.ShowAll ();
 
107
                }
 
108
 
 
109
                void SetAlignment ()
 
110
                {
 
111
                        align.LeftPadding = 4;
 
112
                        align.RightPadding = 3;
 
113
                        align.TopPadding = align.BottomPadding = 7;
 
114
                        align.TopPadding += HeaderSize;
 
115
                        
 
116
                        switch (DockPreferences.Orientation) {
 
117
                        case DockOrientation.Bottom:
 
118
                                align.BottomPadding += TailHeight + 3;
 
119
                                break;
 
120
                        case DockOrientation.Top:
 
121
                                align.TopPadding += TailHeight + 3;
 
122
                                break;
 
123
                        }
 
124
                }
 
125
                
 
126
                public virtual void PopUp (string description, IEnumerable<AbstractMenuArgs> args, int x, int y)
 
127
                {
 
128
                        header = description;
 
129
                        vertical_offset = horizontal_offset = 0;
 
130
                        ShowAll ();
 
131
                        Gdk.Rectangle geo = LayoutUtils.MonitorGeometry ();
 
132
                        Gtk.Requisition req = SizeRequest ();
 
133
                        
 
134
                        Gdk.Point postion;
 
135
                        switch (DockPreferences.Orientation) {
 
136
                        case DockOrientation.Bottom:
 
137
                                postion = new Gdk.Point (x - req.Width / 2, y - req.Height);
 
138
                                break;
 
139
                        case DockOrientation.Top:
 
140
                                postion = new Gdk.Point (x - req.Width / 2, y);
 
141
                                break;
 
142
                        default:
 
143
                                postion = new Gdk.Point (0, 0);
 
144
                                break;
 
145
                        }
 
146
 
 
147
                        if (postion.X < geo.X) {
 
148
                                horizontal_offset = geo.X - postion.X;
 
149
                        } else if (postion.X + req.Width > geo.X + geo.Width) {
 
150
                                horizontal_offset = (geo.X + geo.Width) - (postion.X + req.Width);
 
151
                        }
 
152
                        
 
153
                        postion.X += horizontal_offset;
 
154
                        postion.Y += vertical_offset;
 
155
                        Move (postion.X, postion.Y);
 
156
                        
 
157
                        Do.Interface.Windowing.PresentWindow (this);
 
158
                }
 
159
                
 
160
                protected override bool OnExposeEvent (Gdk.EventExpose evnt)
 
161
                {
 
162
                        using (Context cr = Gdk.CairoHelper.Create (GdkWindow)) {
 
163
                                cr.AlphaFill ();
 
164
                                DrawBackground (cr);
 
165
                        }
 
166
                        
 
167
                        return base.OnExposeEvent (evnt);
 
168
                }
 
169
                
 
170
                protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
 
171
                {
 
172
                        Gdk.Rectangle rect;
 
173
                        GetSize (out rect.Width, out rect.Height);
 
174
                        
 
175
                        if (evnt.X < 0 || evnt.Y < 0 || evnt.X > rect.Width || evnt.Y > rect.Height) {
 
176
                                Do.Interface.Windowing.UnpresentWindow (this);
 
177
                                Hide ();
 
178
                        }
 
179
                        return base.OnButtonReleaseEvent (evnt);
 
180
                }
 
181
                
 
182
                protected override bool OnKeyReleaseEvent (Gdk.EventKey evnt)
 
183
                {
 
184
                        if (evnt.Key == Gdk.Key.Escape) {
 
185
                                Do.Interface.Windowing.UnpresentWindow (this);
 
186
                                Hide ();
 
187
                        }
 
188
                        return base.OnKeyReleaseEvent (evnt);
 
189
                }
 
190
 
 
191
                protected override void OnShown ()
 
192
                {
 
193
                        Visible = true;
 
194
                        base.OnShown ();
 
195
                }
 
196
 
 
197
                protected override void OnHidden ()
 
198
                {
 
199
                        Visible = false;
 
200
                        base.OnHidden ();
 
201
                }
 
202
 
 
203
                void DrawBackground (Context cr)
 
204
                {
 
205
                        Gdk.Rectangle rect;
 
206
                        GetSize (out rect.Width, out rect.Height);
 
207
                        
 
208
                        SetBackgroundPath (cr);
 
209
                        
 
210
                        cr.Color = BackgroundColor;
 
211
                        cr.FillPreserve ();
 
212
                        
 
213
                        LinearGradient lg = (DockPreferences.Orientation == DockOrientation.Bottom) ? 
 
214
                                new LinearGradient (0, rect.Height - TailHeight, 0, rect.Height) : new LinearGradient (0, TailHeight, 0, 0);
 
215
                        lg.AddColorStop (0, BackgroundColor);
 
216
                        lg.AddColorStop (1, new Cairo.Color (BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, 0));
 
217
                        cr.Pattern = lg;
 
218
                        cr.LineWidth = 3;
 
219
                        cr.StrokePreserve ();
 
220
                        
 
221
                        lg.Destroy ();
 
222
                        lg = (DockPreferences.Orientation == DockOrientation.Bottom) ? 
 
223
                                new LinearGradient (0, rect.Height - TailHeight, 0, rect.Height) : new LinearGradient (0, TailHeight, 0, 0);
 
224
                        lg.AddColorStop (0, new Cairo.Color (1, 1, 1, .25));
 
225
                        lg.AddColorStop (1, new Cairo.Color (1, 1, 1, 0));
 
226
                        cr.Pattern = lg;
 
227
                        cr.LineWidth = 1;
 
228
                        cr.Stroke ();
 
229
                        
 
230
                        lg.Destroy ();
 
231
                        
 
232
                        TextRenderContext context = new TextRenderContext (cr, string.Format (FormatString, header), Width - 16);
 
233
                        context.LeftCenteredPoint = new Gdk.Point (8, HeaderTextOffset);
 
234
                        context.Alignment = Pango.Alignment.Center;
 
235
                        
 
236
                        Core.DockServices.DrawingService.TextPathAtPoint (context);
 
237
                        cr.Color = new Cairo.Color (1, 1, 1);
 
238
                        cr.Fill ();
 
239
                }
 
240
 
 
241
                void SetBackgroundPath (Context context)
 
242
                {
 
243
                        Gdk.Rectangle size;
 
244
                        GetSize (out size.Width, out size.Height);
 
245
 
 
246
                        Gdk.Rectangle mainArea = new Gdk.Rectangle (0, 0, 0, 0);
 
247
                        switch (DockPreferences.Orientation) {
 
248
                        case DockOrientation.Bottom:
 
249
                                mainArea = new Gdk.Rectangle (BorderWidth, 
 
250
                                                              BorderWidth, 
 
251
                                                              size.Width - 2 * BorderWidth, 
 
252
                                                              size.Height - 2 * BorderWidth - TailHeight);
 
253
                                break;
 
254
                        case DockOrientation.Top:
 
255
                                mainArea = new Gdk.Rectangle (BorderWidth, 
 
256
                                                              BorderWidth + TailHeight, 
 
257
                                                              size.Width - 2 * BorderWidth, 
 
258
                                                              size.Height - 2 * BorderWidth - TailHeight);
 
259
                                break;
 
260
                        }
 
261
 
 
262
                        context.Translate (.5, .5);
 
263
                        mainArea.Width -= 1;
 
264
                        mainArea.Height -= 1;
 
265
                        
 
266
                        PointD topLeftRadialCenter = new PointD (mainArea.X + Radius, mainArea.Y + Radius);
 
267
                        PointD topRightRadialCenter = new PointD (mainArea.X + mainArea.Width - Radius, mainArea.Y + Radius);
 
268
                        PointD bottomRightRadialCenter = new PointD (mainArea.X + mainArea.Width - Radius, mainArea.Y + mainArea.Height - Radius);
 
269
                        PointD bottomLeftRadialCenter = new PointD (mainArea.X + Radius, mainArea.Y + mainArea.Height - Radius);
 
270
 
 
271
                        context.MoveTo (mainArea.X, mainArea.Y + Radius);
 
272
                        
 
273
                        context.Arc (topLeftRadialCenter.X, topLeftRadialCenter.Y, Radius, Math.PI, Math.PI * 1.5);
 
274
                        if (DockPreferences.Orientation == DockOrientation.Top) {
 
275
                                Gdk.Point vertex = new Gdk.Point ();
 
276
                                vertex.X = mainArea.X + mainArea.Width / 2;
 
277
                                vertex.Y = mainArea.Y - TailHeight;
 
278
                                vertex.X -= horizontal_offset;
 
279
                                
 
280
                                Gdk.Point top = new Gdk.Point (vertex.X, vertex.Y + TailHeight);
 
281
                                
 
282
                                context.LineTo (top.X - TailWidth, top.Y);
 
283
                                context.CurveTo (top.X - TailWidth * Curviness, top.Y, vertex.X, vertex.Y, vertex.X, vertex.Y);
 
284
                                context.CurveTo (vertex.X, vertex.Y, top.X + TailWidth * Curviness, top.Y, top.X + TailWidth, top.Y);
 
285
                        }
 
286
                        context.Arc (topRightRadialCenter.X, topRightRadialCenter.Y, Radius, Math.PI * 1.5, Math.PI * 2);
 
287
                        context.Arc (bottomRightRadialCenter.X, bottomRightRadialCenter.Y, Radius, 0, Math.PI * .5);
 
288
                        if (DockPreferences.Orientation == DockOrientation.Bottom) {
 
289
                                Gdk.Point vertex = new Gdk.Point ();
 
290
                                vertex.X = mainArea.X + mainArea.Width / 2;
 
291
                                vertex.Y = mainArea.Y + mainArea.Height + TailHeight;
 
292
                                vertex.X -= horizontal_offset;
 
293
                                
 
294
                                Gdk.Point top = new Gdk.Point (vertex.X, vertex.Y - TailHeight);
 
295
                                
 
296
                                context.LineTo (top.X + TailWidth, top.Y);
 
297
                                context.CurveTo (top.X + TailWidth * Curviness, top.Y, vertex.X, vertex.Y, vertex.X, vertex.Y);
 
298
                                context.CurveTo (vertex.X, vertex.Y, top.X - TailWidth * Curviness, top.Y, top.X - TailWidth, top.Y);
 
299
                        }
 
300
                        context.Arc (bottomLeftRadialCenter.X, bottomLeftRadialCenter.Y, Radius, Math.PI * .5, Math.PI);
 
301
                        
 
302
 
 
303
                        context.ClosePath ();
 
304
 
 
305
                        context.Translate (-.5, -.5);
 
306
                }
 
307
                
 
308
                public override void Dispose ()
 
309
                {
 
310
                        DockPreferences.OrientationChanged -= SetAlignment;
 
311
                        base.Dispose ();
 
312
                }
 
313
        }
 
314
}