├── Ribbons.mds
├── Ribbons
├── ApplicationButton.cs
├── ApplicationMenu.cs
├── ApplicationMenuItem.cs
├── BaseButton.cs
├── Button.cs
├── ChangeLog
├── ColorScheme.cs
├── DropdownRibbonGroup.cs
├── ExtraEventBox.cs
├── FlowLayoutContainer.cs
├── Gallery.cs
├── GalleryPopupWindow.cs
├── GroupStyle.cs
├── GroupVariant.cs
├── KeyTip.cs
├── PageAddedHandler.cs
├── PageEventArgs.cs
├── PageMovedEventArgs.cs
├── PageMovedHandler.cs
├── PageRemovedHandler.cs
├── PageSelectedHandler.cs
├── Position.cs
├── QuickAccessToolbar.cs
├── Ribbon.cs
├── RibbonGroup.cs
├── Ribbons.mdp
├── SyntheticEventCrossing.cs
├── SyntheticWindow.cs
├── Theme.cs
├── Tile.cs
├── TileSelectedEventArgs.cs
├── TileSelectedHandler.cs
├── ToggleButton.cs
├── ToolBox.cs
├── ToolPack.cs
├── VariantsCombinaison.cs
├── VariantsCombinaisonSwitcher.cs
└── gtk-gui
│ ├── generated.cs
│ ├── gui.stetic
│ └── objects.xml
├── Sample
├── AssemblyInfo.cs
├── ChangeLog
├── DropdownGroupTest.cs
├── Main.cs
├── MainWindow.cs
├── Sample.mdp
├── SampleTile.cs
└── VariantsCombinaisonTest.cs
└── doc.html
/Ribbons.mds:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Ribbons/ApplicationButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | ///
8 | /// A button used to display the application menu. This button has a theme different than all other buttons.
9 | ///
10 | public class ApplicationButton : BaseButton
11 | {
12 | protected const double lineWidth = 1.0;
13 |
14 | private ApplicationMenu appMenu;
15 | private bool menuOpened;
16 | private KeyTip keyTip;
17 |
18 | /// Fired when the button is clicked.
19 | [GLib.Signal("clicked")]
20 | public event EventHandler Clicked;
21 |
22 | public ApplicationMenu Menu
23 | {
24 | get { return appMenu; }
25 | }
26 |
27 | public KeyTip KeyTip
28 | {
29 | get { return keyTip; }
30 | set { keyTip = value; }
31 | }
32 |
33 | public ApplicationButton()
34 | {
35 | this.SetFlag (WidgetFlags.NoWindow);
36 |
37 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
38 |
39 | menuOpened = false;
40 |
41 | appMenu = new ApplicationMenu (this);
42 | appMenu.Hidden += appMenu_Hidden;
43 |
44 | HeightRequest = 36;
45 | WidthRequest = 36;
46 |
47 | this.enable = true;
48 | }
49 |
50 | /// Fires the Click event.
51 | public void Click ()
52 | {
53 | if(enable && Clicked != null) Clicked (this, EventArgs.Empty);
54 |
55 | int x, y;
56 | ParentWindow.GetOrigin (out x, out y);
57 | x += Allocation.X;
58 | y += Allocation.Bottom;
59 |
60 | appMenu.ShowAt (x, y);
61 | menuOpened = true;
62 | QueueDraw ();
63 | }
64 |
65 | private void appMenu_Hidden (object sender, EventArgs args)
66 | {
67 | menuOpened = false;
68 | QueueDraw ();
69 | }
70 |
71 | protected override void BindedWidget_ButtonPressEvent (object sender, ButtonPressEventArgs evnt)
72 | {
73 | ProcessEvent (evnt.Event);
74 | }
75 |
76 | protected override void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt)
77 | {
78 | ProcessEvent (evnt.Event);
79 | Click ();
80 | }
81 |
82 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
83 | {
84 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
85 |
86 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
87 | cr.Clip ();
88 | Draw (cr);
89 |
90 | ((IDisposable)cr.Target).Dispose ();
91 | ((IDisposable)cr).Dispose ();
92 |
93 | return base.OnExposeEvent (evnt);
94 | }
95 |
96 | protected void Draw (Context cr)
97 | {
98 | Theme.ButtonState state = this.state;
99 | if(menuOpened) state = Theme.ButtonState.Pressed;
100 | theme.DrawApplicationButton (cr, Allocation, state, lineWidth, this);
101 | }
102 |
103 | public void ShowKeyTips ()
104 | {
105 | if(keyTip != null)
106 | {
107 | Gdk.Rectangle alloc = Allocation;
108 | int x, y;
109 | GdkWindow.GetOrigin (out x, out y);
110 | keyTip.ShowAt (x + alloc.X + (alloc.Width >> 1), y + alloc.Y + (alloc.Height >> 1), 0.5, 0.5);
111 | }
112 | }
113 |
114 | public void HideKeyTips ()
115 | {
116 | if(keyTip != null)
117 | {
118 | keyTip.Hide ();
119 | }
120 | }
121 |
122 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
123 | {
124 | bool ret = base.OnButtonPressEvent (evnt);
125 | state = Theme.ButtonState.Pressed;
126 | if(!enable) state = Theme.ButtonState.Default;
127 | this.QueueDraw ();
128 | Click ();
129 | return ret;
130 | }
131 |
132 | protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
133 | {
134 | bool ret = base.OnButtonReleaseEvent (evnt);
135 | state = Theme.ButtonState.Hover;
136 | if(!enable) state = Theme.ButtonState.Default;
137 | this.QueueDraw ();
138 | return ret;
139 | }
140 |
141 | protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
142 | {
143 | bool ret = base.OnEnterNotifyEvent (evnt);
144 | state = Theme.ButtonState.Hover;
145 | if(!enable) state = Theme.ButtonState.Default;
146 | this.QueueDraw ();
147 | return ret;
148 | }
149 |
150 | protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
151 | {
152 | bool ret = base.OnLeaveNotifyEvent (evnt);
153 | state = Theme.ButtonState.Default;
154 | this.QueueDraw ();
155 | return ret;
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/Ribbons/ApplicationMenu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using Gtk;
5 | using Cairo;
6 |
7 | namespace Ribbons
8 | {
9 | ///
10 | /// The main menu of an application, displaying application-level commands, and documents list.
11 | ///
12 | public class ApplicationMenu : Container
13 | {
14 | private static readonly TimeSpan openTimeoutSec = new TimeSpan (0, 0, 0, 0, 300);
15 |
16 | private const int verticalWindowOffset = topPadding - space;
17 | private const double lineWidth = 1.0;
18 | private const int topPadding = 24;
19 | private const int borderWidth = 6;
20 | private const int space = 2;
21 |
22 | protected Theme theme = Theme.DefaultTheme;
23 |
24 | private ApplicationButton appBtn;
25 | private List items;
26 | private Widget defaultMenu;
27 | private int itemHeight;
28 | private Gdk.Size menuSize;
29 |
30 | private Button optionsBtn, exitBtn;
31 | private Widget activeMenu;
32 |
33 | private Gdk.Rectangle itemsAlloc;
34 | private int menuItemsColWidth;
35 | private int buttonsHeight;
36 | private int exitBtnWidth, optionsBtnWidth;
37 | private int visibleMenuItems;
38 | private bool activeMenuVisible;
39 | private bool optionsBtnVisible, exitBtnVisible;
40 |
41 | private Window win;
42 |
43 | public ApplicationButton ApplicationButton
44 | {
45 | get { return appBtn; }
46 | }
47 |
48 | public Button OptionsButton
49 | {
50 | get { return optionsBtn; }
51 | set
52 | {
53 | if(optionsBtn == value) return;
54 | if(optionsBtn != null) optionsBtn.Unparent ();
55 | optionsBtn = value;
56 | if(value != null)
57 | {
58 | value.DrawBackground = true;
59 | value.OpaqueBackground = true;
60 | value.Parent = this;
61 | value.Visible = true;
62 | }
63 | }
64 | }
65 |
66 | public Button ExitButton
67 | {
68 | get { return exitBtn; }
69 | set
70 | {
71 | if(exitBtn == value) return;
72 | if(exitBtn != null) exitBtn.Unparent ();
73 | exitBtn = value;
74 | if(value != null)
75 | {
76 | value.DrawBackground = true;
77 | value.OpaqueBackground = true;
78 | value.Parent = this;
79 | value.Visible = true;
80 | }
81 | }
82 | }
83 |
84 | public int ItemHeigth
85 | {
86 | get { return itemHeight; }
87 | set
88 | {
89 | if(itemHeight == value) return;
90 | itemHeight = value;
91 | QueueResize ();
92 | }
93 | }
94 |
95 | public Gdk.Size MenuSize
96 | {
97 | get { return menuSize; }
98 | set
99 | {
100 | if(menuSize == value) return;
101 | menuSize = value;
102 | QueueResize ();
103 | }
104 | }
105 |
106 | public Widget DefaultMenu
107 | {
108 | get { return defaultMenu; }
109 | set
110 | {
111 | if(defaultMenu == value) return;
112 | bool updateActive = defaultMenu == activeMenu;
113 | if(updateActive && defaultMenu != null) defaultMenu.Unparent ();
114 | defaultMenu = value;
115 | if(updateActive) SetActiveMenu (value);
116 | }
117 | }
118 |
119 | /// Returns the number of children.
120 | public int NChildren
121 | {
122 | get { return items.Count; }
123 | }
124 |
125 | /// Default constructor.
126 | internal ApplicationMenu (ApplicationButton Button)
127 | {
128 | this.SetFlag (WidgetFlags.NoWindow);
129 |
130 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
131 |
132 | //this.children = new List ();
133 |
134 | //Append (new Button ("OK"));
135 |
136 | appBtn = Button;
137 | items = new List ();
138 | itemHeight = 32;
139 | menuSize = new Gdk.Size (240, 320);
140 | }
141 |
142 | public void Prepend (ApplicationMenuItem i)
143 | {
144 | Insert (i, 0);
145 | }
146 |
147 | public void Append (ApplicationMenuItem i)
148 | {
149 | Insert (i, -1);
150 | }
151 |
152 | public void Insert (ApplicationMenuItem i, int ItemIndex)
153 | {
154 | i.Parent = this;
155 | i.Visible = true;
156 |
157 | if(ItemIndex == -1)
158 | items.Add (i);
159 | else
160 | items.Insert (ItemIndex, i);
161 | }
162 |
163 | public void Remove (int ItemIndex)
164 | {
165 | if(ItemIndex == -1) ItemIndex = items.Count - 1;
166 |
167 | items[ItemIndex].Unparent ();
168 | items.RemoveAt (ItemIndex);
169 | }
170 |
171 | public void ActivateMenu (Widget w)
172 | {
173 | if(w == null) w = defaultMenu;
174 | SetActiveMenu (w);
175 | }
176 |
177 | private void SetActiveMenu (Widget w)
178 | {
179 | if(activeMenu != null) activeMenu.Unparent ();
180 | activeMenu = w;
181 | w.Parent = this;
182 | w.Visible = true;
183 | QueueResize ();
184 | }
185 |
186 | public void ShowAt (int x, int y)
187 | {
188 | //if(win != null) KillMenu (true);
189 |
190 | //foreach(ApplicationMenuItem item in items) item.Parent = this;
191 |
192 | if(win == null)
193 | {
194 | win = new SyntheticWindow (WindowType.Popup);
195 | win.Child = this;
196 |
197 | win.Hidden += delegate { KillMenu (true); };
198 |
199 | win.ShowAll ();
200 | win.GdkWindow.Move (x, y - verticalWindowOffset);
201 |
202 | win.ButtonPressEvent += delegate { KillMenu (true); };
203 | win.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
204 | }
205 | else
206 | {
207 | win.ShowAll ();
208 | win.GdkWindow.Move (x, y - verticalWindowOffset);
209 | }
210 |
211 | Grab.Add (win);
212 | Gdk.GrabStatus grabbed = Gdk.Pointer.Grab (win.GdkWindow, true, Gdk.EventMask.ButtonPressMask, null, null, 0);
213 | if(grabbed != Gdk.GrabStatus.Success)
214 | {
215 | KillMenu (false);
216 | return;
217 | }
218 |
219 | grabbed = Gdk.Keyboard.Grab (win.GdkWindow, true, 0);
220 | if(grabbed != Gdk.GrabStatus.Success)
221 | {
222 | KillMenu (false);
223 | return;
224 | }
225 | }
226 |
227 | private void KillMenu (bool Ungrab)
228 | {
229 | if(this.win == null) return;
230 |
231 | //Window win = this.win;
232 | //this.win = null;
233 |
234 | //win.Child = null;
235 |
236 | Grab.Remove (win);
237 | if(Ungrab)
238 | {
239 | Gdk.Pointer.Ungrab (0);
240 | Gdk.Keyboard.Ungrab (0);
241 | }
242 | win.Hide ();
243 | this.Hide ();
244 | //win.Destroy ();
245 | }
246 |
247 | protected override void ForAll (bool include_internals, Callback callback)
248 | {
249 | foreach(Widget w in items)
250 | {
251 | if(w.Visible) callback (w);
252 | }
253 |
254 | if(optionsBtn != null && optionsBtn.Visible)
255 | {
256 | callback (optionsBtn);
257 | }
258 |
259 | if(exitBtn != null && exitBtn.Visible)
260 | {
261 | callback (exitBtn);
262 | }
263 |
264 | if(activeMenu != null && activeMenu.Visible)
265 | {
266 | callback (activeMenu);
267 | }
268 | }
269 |
270 | protected override void OnSizeRequested (ref Requisition requisition)
271 | {
272 | base.OnSizeRequested (ref requisition);
273 |
274 | menuItemsColWidth = 0;
275 | int menuItemsColHeight = 0;
276 |
277 | foreach(ApplicationMenuItem mi in items)
278 | {
279 | if(mi.Visible)
280 | {
281 | mi.HeightRequest = itemHeight;
282 | Gtk.Requisition req = mi.SizeRequest ();
283 | if(req.Width > menuItemsColWidth) menuItemsColWidth = req.Width;
284 | menuItemsColHeight += itemHeight;
285 | }
286 | }
287 |
288 | requisition.Height = menuItemsColHeight;
289 | requisition.Width = menuItemsColWidth;
290 |
291 | if(activeMenu != null)
292 | {
293 | /*Gtk.Requisition req = activeMenu.SizeRequest ();
294 | requisition.Width += req.Width;
295 | if(req.Height > requisition.Height) requisition.Height = req.Height;*/
296 |
297 | requisition.Width += menuSize.Width;
298 | if(menuSize.Height > requisition.Height) requisition.Height = menuSize.Height;
299 | }
300 |
301 | int buttonsWidth = 0;
302 | buttonsHeight = 0;
303 |
304 | if(optionsBtn != null)
305 | {
306 | Gtk.Requisition req = optionsBtn.SizeRequest ();
307 | buttonsWidth = req.Width;
308 | buttonsHeight = req.Height;
309 | optionsBtnWidth = req.Width;
310 | }
311 |
312 | if(exitBtn != null)
313 | {
314 | Gtk.Requisition req = exitBtn.SizeRequest ();
315 | buttonsWidth += req.Width;
316 | if(optionsBtn != null) buttonsWidth += space;
317 | if(req.Height > buttonsHeight) buttonsHeight = req.Height;
318 | exitBtnWidth = req.Width;
319 | }
320 |
321 | if(buttonsWidth > requisition.Width) requisition.Width = buttonsWidth;
322 |
323 | if(buttonsHeight > 0) requisition.Height += buttonsHeight + space;
324 | requisition.Width += borderWidth << 1;
325 | requisition.Height += borderWidth + topPadding;
326 |
327 | this.menuItemsColWidth = menuItemsColWidth;
328 | }
329 |
330 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
331 | {
332 | base.OnSizeAllocated (allocation);
333 |
334 | visibleMenuItems = 0;
335 | exitBtnVisible = optionsBtnVisible = false;
336 |
337 | allocation.Height -= borderWidth;
338 |
339 | if(buttonsHeight + topPadding <= allocation.Height)
340 | {
341 | Gdk.Rectangle alloc;
342 |
343 | if(buttonsHeight > 0)
344 | {
345 | alloc.X = allocation.Right - borderWidth;
346 | alloc.Y = allocation.Bottom - buttonsHeight;
347 | alloc.Height = buttonsHeight;
348 |
349 | if(exitBtn != null)
350 | {
351 | alloc.X -= exitBtnWidth;
352 | alloc.Width = exitBtnWidth;
353 | if(alloc.X >= allocation.X + borderWidth)
354 | {
355 | exitBtn.SizeAllocate (alloc);
356 | }
357 | }
358 |
359 | if(optionsBtn != null)
360 | {
361 | if(exitBtn != null) alloc.X -= space;
362 | alloc.X -= optionsBtnWidth;
363 | alloc.Width = optionsBtnWidth;
364 | if(alloc.X >= allocation.X + borderWidth)
365 | {
366 | optionsBtn.SizeAllocate (alloc);
367 | }
368 | }
369 |
370 | allocation.Height -= buttonsHeight + space;
371 | }
372 |
373 | alloc.X = allocation.X + borderWidth;
374 | alloc.Y = allocation.Y + topPadding;
375 | itemsAlloc.X = alloc.X;
376 | itemsAlloc.Y = alloc.Y;
377 | alloc.Height = itemHeight;
378 | if(allocation.Right - alloc.X - borderWidth < menuItemsColWidth)
379 | {
380 | menuItemsColWidth = allocation.Right - alloc.X - borderWidth;
381 | }
382 |
383 | if(menuItemsColWidth > 0)
384 | {
385 | alloc.Width = menuItemsColWidth;
386 |
387 | foreach(ApplicationMenuItem mi in items)
388 | {
389 | if(mi.Visible)
390 | {
391 | if(alloc.Bottom <= allocation.Bottom)
392 | {
393 | mi.SizeAllocate (alloc);
394 | alloc.Y += itemHeight;
395 | ++visibleMenuItems;
396 | }
397 | }
398 | }
399 | }
400 |
401 | itemsAlloc.Width = menuItemsColWidth + space;
402 | itemsAlloc.Height = allocation.Bottom - itemsAlloc.Y - borderWidth;
403 |
404 | if(activeMenu != null)
405 | {
406 | alloc.X = allocation.X + borderWidth + menuItemsColWidth + space;
407 | alloc.Width = allocation.Right - alloc.X - borderWidth;
408 | alloc.Y = allocation.Y + topPadding;
409 | alloc.Height = allocation.Bottom - alloc.Y - borderWidth;
410 |
411 | if(alloc.Width > 0 && alloc.Width > 0)
412 | {
413 | activeMenu.SizeAllocate (alloc);
414 | }
415 | }
416 | }
417 | }
418 |
419 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
420 | {
421 | SetActiveMenu (defaultMenu);
422 | return base.OnButtonPressEvent (evnt);
423 | }
424 |
425 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
426 | {
427 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
428 |
429 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
430 | cr.Clip ();
431 | Draw (cr);
432 |
433 | ((IDisposable)cr.Target).Dispose ();
434 | ((IDisposable)cr).Dispose ();
435 |
436 | return base.OnExposeEvent (evnt);
437 | }
438 |
439 | protected void Draw (Context cr)
440 | {
441 | Rectangle rect = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
442 | theme.DrawApplicationMenu (cr, rect, itemsAlloc, lineWidth, this);
443 | }
444 | }
445 | }
446 |
--------------------------------------------------------------------------------
/Ribbons/ApplicationMenuItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Gtk;
4 | using Cairo;
5 |
6 | namespace Ribbons
7 | {
8 | ///
9 | /// Single item to be displayed in the application menu.
10 | ///
11 | public class ApplicationMenuItem : Bin
12 | {
13 | private static readonly TimeSpan openTimeoutSec = new TimeSpan (0, 0, 0, 0, 300);
14 | private const double lineWidth = 1.0;
15 | private const double arrowPadding = 2.0;
16 | private const double arrowSize = 10.0;
17 | private const double roundSize = 3.0;
18 |
19 | private Theme.MenuItemState state = Theme.MenuItemState.Default;
20 | private bool menuOpened = false;
21 | private int padding = 2;
22 | private Gdk.Rectangle arrowAllocation;
23 | private double effectiveArrowSize;
24 |
25 | private Timer timer;
26 |
27 | private Widget img;
28 | private Label lbl;
29 | private Widget menu;
30 |
31 | protected Theme theme = Theme.DefaultTheme;
32 |
33 | [GLib.Signal("action")]
34 | public event EventHandler Action;
35 |
36 | /// Image to display.
37 | public Widget Image
38 | {
39 | set
40 | {
41 | if(img == value) return;
42 | if(img != null) UnbindWidget (img);
43 | img = value;
44 | if(img != null) BindWidget (img);
45 | UpdateImageLabel ();
46 | }
47 | get { return img; }
48 | }
49 |
50 | /// Label to display.
51 | public string Label
52 | {
53 | set
54 | {
55 | if(lbl != null) UnbindWidget (lbl);
56 | lbl = new Gtk.Label (value);
57 | lbl.Xalign = 0;
58 | if(lbl != null) BindWidget (lbl);
59 | UpdateImageLabel ();
60 | }
61 | get
62 | {
63 | return lbl == null ? null : lbl.Text;
64 | }
65 | }
66 |
67 | public Widget Menu
68 | {
69 | get { return menu; }
70 | set
71 | {
72 | menu = value;
73 | QueueResize ();
74 | }
75 | }
76 |
77 | /// Default constructor.
78 | public ApplicationMenuItem ()
79 | {
80 | this.SetFlag (WidgetFlags.NoWindow);
81 |
82 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
83 |
84 | this.timer = new Timer (OpenMenuNow);
85 | }
86 |
87 | /// Constructor given a label to display.
88 | /// Label to display.
89 | public ApplicationMenuItem (string Label) : this ()
90 | {
91 | this.Label = Label;
92 | }
93 |
94 | /// Constructor given an image to display.
95 | /// Image to display
96 | public ApplicationMenuItem (Image Image) : this ()
97 | {
98 | this.Image = Image;
99 | }
100 |
101 | /// Constructor given a label and an image to display.
102 | /// Image to display.
103 | /// Label to display.
104 | public ApplicationMenuItem (Image Image, string Label) : this ()
105 | {
106 | this.Image = Image;
107 | this.Label = Label;
108 | }
109 |
110 | /// Constructs a Button from a stock.
111 | /// Name of the stock.
112 | /// true if the image should be large, false otherwise.
113 | public static ApplicationMenuItem FromStockIcon (string Name, bool Large)
114 | {
115 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
116 | return new ApplicationMenuItem (img);
117 | }
118 |
119 | /// Constructs a Button from a stock.
120 | /// Name of the stock.
121 | /// Label to display.
122 | /// true if the image should be large, false otherwise.
123 | public static ApplicationMenuItem FromStockIcon (string Name, string Label, bool Large)
124 | {
125 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
126 | return new ApplicationMenuItem (img, Label);
127 | }
128 |
129 | public override void Dispose ()
130 | {
131 | base.Dispose ();
132 | timer.Dispose ();
133 | }
134 |
135 | /// Fires the Action event.
136 | public void Click ()
137 | {
138 | if(Action != null) Action (this, EventArgs.Empty);
139 | }
140 |
141 | private void OpenMenuNow (object State)
142 | {
143 | ApplicationMenu win = Parent as ApplicationMenu;
144 | win.ActivateMenu (menu);
145 | }
146 |
147 | /// Updates the child widget containing the label and/or image.
148 | protected void UpdateImageLabel ()
149 | {
150 | if(Child != null)
151 | {
152 | Container con = Child as Container;
153 | if(con != null)
154 | {
155 | con.Remove (img);
156 | con.Remove (lbl);
157 | }
158 | Remove (Child);
159 | }
160 |
161 | if(lbl != null && img != null)
162 | {
163 | HBox box = new HBox (false, 0);
164 | box.Add (img);
165 | box.Add (lbl);
166 | Child = box;
167 | }
168 | else if(lbl != null)
169 | {
170 | Child = lbl;
171 | }
172 | else if(img != null)
173 | {
174 | Child = img;
175 | }
176 | }
177 |
178 | /// Binds a widget to listen to all button events.
179 | protected void BindWidget (Widget w)
180 | {
181 | w.ButtonPressEvent += BindedWidget_ButtonPressEvent;
182 | w.ButtonReleaseEvent += BindedWidget_ButtonReleaseEvent;
183 | }
184 |
185 | /// Unbinds a widget to no longer listen to button events.
186 | protected void UnbindWidget (Widget w)
187 | {
188 | w.ButtonPressEvent -= BindedWidget_ButtonPressEvent;
189 | w.ButtonReleaseEvent -= BindedWidget_ButtonReleaseEvent;
190 | }
191 |
192 | protected void BindedWidget_ButtonPressEvent (object sender, ButtonPressEventArgs evnt)
193 | {
194 | ProcessEvent (evnt.Event);
195 | }
196 |
197 | protected void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt)
198 | {
199 | ProcessEvent (evnt.Event);
200 | Click ();
201 | }
202 |
203 | protected override void OnSizeRequested (ref Requisition requisition)
204 | {
205 | base.OnSizeRequested (ref requisition);
206 |
207 | Requisition childRequisition = new Requisition ();
208 | if(Child != null)
209 | {
210 | childRequisition = Child.SizeRequest ();
211 | }
212 |
213 | if(Menu != null)
214 | {
215 | int arrowSpace = (int)(arrowSize + 2 * (lineWidth + arrowPadding));
216 | childRequisition.Width += arrowSpace;
217 | }
218 |
219 | if(HeightRequest == -1)
220 | {
221 | requisition.Height = childRequisition.Height + (int)(lineWidth * 4 + padding * 2);
222 | }
223 | if(WidthRequest == -1)
224 | {
225 | requisition.Width = childRequisition.Width + (int)(lineWidth * 4 + padding * 2);
226 | }
227 | }
228 |
229 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
230 | {
231 | base.OnSizeAllocated (allocation);
232 |
233 | effectiveArrowSize = arrowSize;
234 |
235 | if(Menu != null)
236 | {
237 | if(Action != null)
238 | arrowAllocation.Width = (int)(arrowSize + 2 * arrowPadding);
239 | else
240 | arrowAllocation.Width = (int)(allocation.Width - 4 * lineWidth);
241 |
242 | arrowAllocation.Height = (int)(allocation.Height - 4 * lineWidth);
243 |
244 | arrowAllocation.X = (int)(allocation.Right - arrowAllocation.Width - 2 * lineWidth);
245 | arrowAllocation.Y = (int)(allocation.Bottom - arrowAllocation.Height - 2 * lineWidth);
246 | }
247 | else
248 | {
249 | effectiveArrowSize = 0;
250 | }
251 |
252 | allocation.X += (int)(lineWidth * 2 + padding);
253 | allocation.Y += (int)(lineWidth * 2 + padding);
254 | allocation.Height -= (int)(lineWidth * 4 + padding * 2);
255 | allocation.Width -= (int)(lineWidth * 4 + padding * 2);
256 |
257 | if(Menu != null)
258 | {
259 | int arrowSpace = (int)(effectiveArrowSize + 2 * (lineWidth + arrowPadding));
260 | allocation.Width -= arrowSpace;
261 | }
262 |
263 | if(allocation.Height < 0) allocation.Height = 0;
264 | if(allocation.Width < 0) allocation.Width = 0;
265 |
266 | if(Child != null)
267 | {
268 | Child.SizeAllocate (allocation);
269 | }
270 | }
271 |
272 | protected override bool OnMotionNotifyEvent (Gdk.EventMotion evnt)
273 | {
274 | bool ret = base.OnMotionNotifyEvent (evnt);
275 | UpdateState ((int)evnt.X, (int)evnt.Y);
276 | return ret;
277 | }
278 |
279 | protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
280 | {
281 | bool ret = base.OnEnterNotifyEvent (evnt);
282 | menuOpened = false;
283 | UpdateState ((int)evnt.X, (int)evnt.Y);
284 | return ret;
285 | }
286 |
287 | private void UpdateState (int x, int y)
288 | {
289 | Theme.MenuItemState newState;
290 |
291 | if(Menu != null && Action != null && arrowAllocation.Contains (x, y))
292 | {
293 | newState = Theme.MenuItemState.HilightMenu;
294 | }
295 | else if(menuOpened || Action == null)
296 | {
297 | newState = Theme.MenuItemState.Hilight;
298 | }
299 | else
300 | {
301 | newState = Theme.MenuItemState.HilightAction;
302 | }
303 |
304 | if(state != newState)
305 | {
306 | if(newState == Theme.MenuItemState.Hilight || newState == Theme.MenuItemState.HilightMenu)
307 | timer.Change (openTimeoutSec, new TimeSpan (-1));
308 | else
309 | timer.Change (-1, -1);
310 |
311 | state = newState;
312 | this.QueueDraw ();
313 | }
314 | }
315 |
316 | protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
317 | {
318 | timer.Change (-1, -1);
319 |
320 | bool ret = base.OnLeaveNotifyEvent (evnt);
321 | state = Theme.MenuItemState.Default;
322 | this.QueueDraw ();
323 | return ret;
324 | }
325 |
326 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
327 | {
328 | bool ret = base.OnButtonPressEvent (evnt);
329 |
330 | /*if(Menu != null && arrowAllocation.Contains ((int)evnt.X, (int)evnt.Y))
331 | {
332 | ActivateMenu ();
333 | }*/
334 |
335 | return ret;
336 | }
337 |
338 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
339 | {
340 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
341 |
342 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
343 | cr.Clip ();
344 | Draw (cr);
345 |
346 | ((IDisposable)cr.Target).Dispose ();
347 | ((IDisposable)cr).Dispose ();
348 |
349 | return base.OnExposeEvent (evnt);
350 | }
351 |
352 | protected void Draw (Context cr)
353 | {
354 | Rectangle rect = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
355 | bool drawSeparator = Action != null && Menu != null;
356 | theme.DrawApplicationMenuItem (cr, rect, state, roundSize, lineWidth, effectiveArrowSize, arrowPadding, drawSeparator, this);
357 | }
358 | }
359 | }
360 |
--------------------------------------------------------------------------------
/Ribbons/BaseButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Foundation of all buttons.
8 | public abstract class BaseButton : Bin
9 | {
10 | protected Theme theme = Theme.DefaultTheme;
11 | protected GroupStyle groupStyle;
12 | protected Theme.ButtonState state = Theme.ButtonState.Default;
13 | protected PositionType imgPos;
14 | protected bool drawBg, opaqueBg;
15 | protected Widget img;
16 | protected Label lbl;
17 | protected double padding;
18 | protected bool isSmall;
19 | protected bool enable;
20 |
21 | /// Spacing between the content and the widget.
22 | public double Padding
23 | {
24 | set
25 | {
26 | if(padding == value) return;
27 | padding = value;
28 | QueueDraw ();
29 | }
30 | get { return padding; }
31 | }
32 |
33 | /// Shape of the widget.
34 | public GroupStyle GroupStyle
35 | {
36 | set { groupStyle = value; }
37 | get { return groupStyle; }
38 | }
39 |
40 | /// true if the widget should paint a background, false otherwise.
41 | public bool DrawBackground
42 | {
43 | set
44 | {
45 | if(drawBg == value) return;
46 | drawBg = value;
47 | QueueDraw ();
48 | }
49 | get { return drawBg; }
50 | }
51 |
52 | public bool OpaqueBackground
53 | {
54 | set
55 | {
56 | if(opaqueBg == value) return;
57 | opaqueBg = value;
58 | QueueDraw ();
59 | }
60 | get { return opaqueBg; }
61 | }
62 |
63 | /// true if the button is enabled, false otherwise.
64 | public bool Enabled
65 | {
66 | set
67 | {
68 | if(enable == value) return;
69 | enable = value;
70 | QueueDraw ();
71 | }
72 | get { return enable; }
73 | }
74 |
75 | /// Image to display.
76 | public Widget Image
77 | {
78 | set
79 | {
80 | if(img == value) return;
81 | if(img != null) UnbindWidget (img);
82 | img = value;
83 | if(img != null) BindWidget (img);
84 | UpdateImageLabel ();
85 | }
86 | get { return img; }
87 | }
88 |
89 | /// Position of the image relative to the label.
90 | public PositionType ImagePosition
91 | {
92 | set
93 | {
94 | if(imgPos == value) return;
95 | imgPos = value;
96 | UpdateImageLabel ();
97 | }
98 | get { return imgPos; }
99 | }
100 |
101 | /// Label to display.
102 | public string Label
103 | {
104 | set
105 | {
106 | if(lbl != null) UnbindWidget (lbl);
107 | lbl = new Gtk.Label (value);
108 | if(lbl != null) BindWidget (lbl);
109 | UpdateImageLabel ();
110 | }
111 | get
112 | {
113 | return lbl == null ? null : lbl.Text;
114 | }
115 | }
116 |
117 | /// Theme used to draw the widget.
118 | public Theme Theme
119 | {
120 | set
121 | {
122 | theme = value;
123 | QueueDraw ();
124 | }
125 | get { return theme; }
126 | }
127 |
128 | /// Binds a widget to listen to all button events.
129 | protected void BindWidget (Widget w)
130 | {
131 | w.ButtonPressEvent += BindedWidget_ButtonPressEvent;
132 | w.ButtonReleaseEvent += BindedWidget_ButtonReleaseEvent;
133 | }
134 |
135 | /// Unbinds a widget to no longer listen to button events.
136 | protected void UnbindWidget (Widget w)
137 | {
138 | w.ButtonPressEvent -= BindedWidget_ButtonPressEvent;
139 | w.ButtonReleaseEvent -= BindedWidget_ButtonReleaseEvent;
140 | }
141 |
142 | /// Called when a mouse button has been pressed on a binded widget.
143 | protected abstract void BindedWidget_ButtonPressEvent (object sender, ButtonPressEventArgs evnt);
144 |
145 | /// Called when a mouse button has been release on a binded widget.
146 | protected abstract void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt);
147 |
148 | /// Updates the child widget containing the label and/or image.
149 | protected void UpdateImageLabel ()
150 | {
151 | if(Child != null)
152 | {
153 | Container con = Child as Container;
154 | if(con != null)
155 | {
156 | con.Remove (img);
157 | con.Remove (lbl);
158 | }
159 | Remove (Child);
160 | }
161 |
162 | if(lbl != null && img != null)
163 | {
164 | switch(imgPos)
165 | {
166 | case PositionType.Top:
167 | {
168 | VBox box = new VBox (false, 0);
169 | box.Add (img);
170 | box.Add (lbl);
171 | Child = box;
172 | break;
173 | }
174 | case PositionType.Bottom:
175 | {
176 | VBox box = new VBox (false, 0);
177 | box.Add (lbl);
178 | box.Add (img);
179 | Child = box;
180 | break;
181 | }
182 | case PositionType.Left:
183 | {
184 | HBox box = new HBox (false, 0);
185 | box.Add (img);
186 | box.Add (lbl);
187 | Child = box;
188 | break;
189 | }
190 | case PositionType.Right:
191 | {
192 | HBox box = new HBox (false, 0);
193 | box.Add (lbl);
194 | box.Add (img);
195 | Child = box;
196 | break;
197 | }
198 | }
199 | }
200 | else if(lbl != null)
201 | {
202 | Child = lbl;
203 | }
204 | else if(img != null)
205 | {
206 | Child = img;
207 | }
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/Ribbons/Button.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Button to be used in Ribbons.
8 | public class Button : BaseButton
9 | {
10 | private Menu dropDownMenu;
11 |
12 | private double arrowSize;
13 | private Gdk.Rectangle arrowAllocation;
14 |
15 | protected const double lineWidth = 1.0;
16 | protected const double arrowPadding = 2.0;
17 | protected const double smallArrowSize = 5.0;
18 | protected const double bigArrowSize = 8.0;
19 |
20 | /// Fired when the button is clicked.
21 | [GLib.Signal("clicked")]
22 | public event EventHandler Clicked;
23 |
24 | /// Drop down menu displayed when the arrow is pressed.
25 | public Menu DropDownMenu
26 | {
27 | set
28 | {
29 | dropDownMenu = value;
30 | QueueDraw ();
31 | }
32 | get
33 | {
34 | return dropDownMenu;
35 | }
36 | }
37 |
38 | /// Default constructor.
39 | public Button ()
40 | {
41 | this.SetFlag (WidgetFlags.NoWindow);
42 |
43 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
44 |
45 | this.Padding = 2;
46 | this.ImagePosition = PositionType.Top;
47 | this.isSmall = false;
48 | this.enable = true;
49 | }
50 |
51 | /// Constructor given a label to display.
52 | /// Label to display.
53 | public Button (string Label) : this ()
54 | {
55 | this.Label = Label;
56 | }
57 |
58 | /// Constructor given an image to display.
59 | /// Image to display
60 | public Button (Image Image) : this ()
61 | {
62 | this.Image = Image;
63 | }
64 |
65 | /// Constructor given a label and an image to display.
66 | /// Image to display.
67 | /// Label to display.
68 | public Button (Image Image, string Label) : this ()
69 | {
70 | this.Image = Image;
71 | this.Label = Label;
72 | }
73 |
74 | /// Constructs a Button from a stock.
75 | /// Name of the stock.
76 | /// true if the image should be large, false otherwise.
77 | public static Button FromStockIcon (string Name, bool Large)
78 | {
79 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
80 | Button btn = new Button (img);
81 | if(!Large) btn.ImagePosition = PositionType.Left;
82 | return btn;
83 | }
84 |
85 | /// Constructs a Button from a stock.
86 | /// Name of the stock.
87 | /// Label to display.
88 | /// true if the image should be large, false otherwise.
89 | public static Button FromStockIcon (string Name, string Label, bool Large)
90 | {
91 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
92 | Button btn = new Button (img, Label);
93 | if(!Large) btn.ImagePosition = PositionType.Left;
94 | return btn;
95 | }
96 |
97 | /// Fires the Click event.
98 | public virtual void Click ()
99 | {
100 | if(enable && Clicked != null) Clicked (this, EventArgs.Empty);
101 | }
102 |
103 | /// Displays the drop down menu if any.
104 | public void Popup ()
105 | {
106 | if(enable && dropDownMenu != null)
107 | {
108 | dropDownMenu.Popup ();
109 | dropDownMenu.ShowAll ();
110 | }
111 | }
112 |
113 | protected override void BindedWidget_ButtonPressEvent (object sender, ButtonPressEventArgs evnt)
114 | {
115 | ProcessEvent (evnt.Event);
116 | }
117 |
118 | protected override void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt)
119 | {
120 | ProcessEvent (evnt.Event);
121 | Click ();
122 | }
123 |
124 | protected override void OnSizeRequested (ref Requisition requisition)
125 | {
126 | base.OnSizeRequested (ref requisition);
127 |
128 | Requisition childRequisition = new Requisition ();
129 | if(Child != null && Child.Visible)
130 | {
131 | childRequisition = Child.SizeRequest ();
132 | }
133 |
134 | if(dropDownMenu != null)
135 | {
136 | int arrowSpace = (int)((isSmall ? smallArrowSize : bigArrowSize) + 2 * (lineWidth + arrowPadding));
137 |
138 | if(imgPos == PositionType.Top || imgPos == PositionType.Bottom)
139 | {
140 | childRequisition.Height += arrowSpace;
141 | }
142 | else
143 | {
144 | childRequisition.Width += arrowSpace;
145 | }
146 | }
147 |
148 | if(HeightRequest == -1)
149 | {
150 | requisition.Height = childRequisition.Height + (int)(lineWidth * 4 + padding * 2);
151 | }
152 | if(WidthRequest == -1)
153 | {
154 | requisition.Width = childRequisition.Width + (int)(lineWidth * 4 + padding * 2);
155 | }
156 | }
157 |
158 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
159 | {
160 | base.OnSizeAllocated (allocation);
161 |
162 | if(dropDownMenu != null)
163 | {
164 | arrowSize = isSmall ? smallArrowSize : bigArrowSize;
165 |
166 | if(imgPos == PositionType.Top || imgPos == PositionType.Bottom)
167 | {
168 | if(Clicked != null)
169 | arrowAllocation.Height = (int)(arrowSize + 2 * arrowPadding);
170 | else
171 | arrowAllocation.Height = (int)(allocation.Height - 4 * lineWidth);
172 |
173 | arrowAllocation.Width = (int)(allocation.Width - 4 * lineWidth);
174 | }
175 | else
176 | {
177 | if(Clicked != null)
178 | arrowAllocation.Width = (int)(arrowSize + 2 * arrowPadding);
179 | else
180 | arrowAllocation.Width = (int)(allocation.Width - 4 * lineWidth);
181 |
182 | arrowAllocation.Height = (int)(allocation.Height - 4 * lineWidth);
183 | }
184 |
185 | arrowAllocation.X = (int)(allocation.Right - arrowAllocation.Width - 2 * lineWidth);
186 | arrowAllocation.Y = (int)(allocation.Bottom - arrowAllocation.Height - 2 * lineWidth);
187 | }
188 | else
189 | {
190 | arrowSize = 0;
191 | }
192 |
193 | allocation.X += (int)(lineWidth * 2 + padding);
194 | allocation.Y += (int)(lineWidth * 2 + padding);
195 | allocation.Height -= (int)(lineWidth * 4 + padding * 2);
196 | allocation.Width -= (int)(lineWidth * 4 + padding * 2);
197 |
198 | if(dropDownMenu != null)
199 | {
200 | int arrowSpace = (int)((isSmall ? smallArrowSize : bigArrowSize) + 2 * (lineWidth + arrowPadding));
201 |
202 | if(imgPos == PositionType.Top || imgPos == PositionType.Bottom)
203 | {
204 | allocation.Height -= arrowSpace;
205 | }
206 | else
207 | {
208 | allocation.Width -= arrowSpace;
209 | }
210 | }
211 |
212 | if(allocation.Height < 0) allocation.Height = 0;
213 | if(allocation.Width < 0) allocation.Width = 0;
214 |
215 | if(Child != null && Child.Visible)
216 | {
217 | Child.SizeAllocate (allocation);
218 | }
219 | }
220 |
221 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
222 | {
223 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
224 |
225 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
226 | cr.Clip ();
227 | Draw (cr);
228 |
229 | ((IDisposable)cr.Target).Dispose ();
230 | ((IDisposable)cr).Dispose ();
231 |
232 | return base.OnExposeEvent (evnt);
233 | }
234 |
235 | protected void Draw (Context cr)
236 | {
237 | Rectangle rect = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
238 | double roundSize = isSmall ? 2.0 : 3.0;
239 | bool drawSeparator = (Clicked != null) && (dropDownMenu != null);
240 | theme.DrawButton (cr, rect, state, roundSize, lineWidth, arrowSize, arrowPadding, drawSeparator, this);
241 | }
242 |
243 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
244 | {
245 | bool ret = base.OnButtonPressEvent (evnt);
246 | state = Theme.ButtonState.Pressed;
247 | if(!enable) state = Theme.ButtonState.Default;
248 | this.QueueDraw ();
249 |
250 | if(dropDownMenu != null && arrowAllocation.Contains ((int)evnt.X, (int)evnt.Y))
251 | {
252 | Popup ();
253 | }
254 |
255 | return ret;
256 | }
257 |
258 | protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
259 | {
260 | bool ret = base.OnButtonReleaseEvent (evnt);
261 | state = Theme.ButtonState.Hover;
262 | if(!enable) state = Theme.ButtonState.Default;
263 | this.QueueDraw ();
264 | return ret;
265 | }
266 |
267 | protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
268 | {
269 | bool ret = base.OnEnterNotifyEvent (evnt);
270 | state = Theme.ButtonState.Hover;
271 | if(!enable) state = Theme.ButtonState.Default;
272 | this.QueueDraw ();
273 | return ret;
274 | }
275 |
276 | protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
277 | {
278 | bool ret = base.OnLeaveNotifyEvent (evnt);
279 | state = Theme.ButtonState.Default;
280 | this.QueueDraw ();
281 | return ret;
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/Ribbons/ChangeLog:
--------------------------------------------------------------------------------
1 | 2008-08-26 Laurent Debacker
2 |
3 | * QuickAccessToolbar.cs, Gallery.cs, Theme.cs, ApplicationMenuItem.cs,
4 | Ribbon.cs, RibbonGroup.cs, ApplicationMenu.cs, BaseButton.cs: Use the
5 | Default Theme instead of creating a new instance for each widget.
6 |
7 | 2008-08-18 Laurent Debacker
8 |
9 | * QuickAccessToolbar.cs, Ribbon.cs: Add support for key tips.
10 | * VariantsCombinaisonSwitcher.cs, ApplicationMenuItem.cs,
11 | VariantsCombinaison.cs, ApplicationMenu.cs, DropdownRibbonGroup.cs: Add
12 | summary.
13 | * Gallery.cs: Add support for multi selection.
14 | * Theme.cs: Update theme for key tips.
15 | * SyntheticWindow.cs: Remove debug code.
16 | * KeyTip.cs: Initial commit of KeyTip.
17 | * ApplicationButton.cs: Support for key tips.
18 |
19 | 2008-08-15 Laurent Debacker
20 |
21 |
22 |
23 | 2008-08-11 Laurent Debacker
24 |
25 | * Button.cs: Make Click method virtual
26 | * ToggleButton.cs: Allow toggle buttons to display an arrow
27 | * VariantsCombinaisonSwitcher.cs: Introduction of variants combinaisons
28 | switcher.
29 | * ToolBox.cs: Bugfix for size requests
30 | * VariantsCombinaison.cs: Bugfix for size requests, and hierachy
31 | * Ribbon.cs: Revert to previous version of Ribbon (I have opted for another
32 | solution for variants combinaisons)
33 | * DropdownRibbonGroup.cs: Introduction of Drop down ribbon group
34 |
35 | 2008-08-05 Laurent Debacker
36 |
37 | * GroupVariant.cs: Implementation of the concept of "variant" for Group.
38 | * VariantsCombinaison.cs: Implementation for the concept of variant
39 | combinaisons.
40 | * Ribbon.cs: Migrating Ribbon to variants combinaisons.
41 |
42 | 2008-07-24 Laurent Debacker
43 |
44 | * Theme.cs: Enhanced key tip theme
45 | * SyntheticWindow.cs: Debug code
46 | * RibbonGroup.cs: Avoid memory leak
47 |
48 | 2008-07-18 Laurent Debacker
49 |
50 | * ApplicationMenuItem.cs: Open/close menu on mouse hover, with timer
51 | * ApplicationMenu.cs: Reset default menu on button click
52 |
53 | 2008-07-17 Laurent Debacker
54 |
55 | * ApplicationMenu.cs: hide container when windows is hidden
56 | * ApplicationButton.cs: keep the app menu pressed while the app menu is
57 | opened
58 |
59 | 2008-07-14 Laurent Debacker
60 |
61 | * ApplicationMenuItem.cs: Text align fix, and delayed menu opening.
62 | * ApplicationMenu.cs: One hard-coded value removed
63 |
64 | 2008-07-11 Laurent Debacker
65 |
66 | * Theme.cs: More compliant app menu background, and new feature for buttons:
67 | opaque background.
68 | * ApplicationMenu.cs: Opaque buttons, window offset.
69 | * ApplicationButton.cs: API update
70 | * BaseButton.cs: New feature: opaque background
71 |
72 | 2008-07-11 Laurent Debacker
73 |
74 | * Theme.cs: Nicer menu items background
75 | * ApplicationMenuItem.cs: Attempt to fix justification of menu item labels,
76 | not ok yet
77 | * ApplicationMenu.cs: Fixed menu size
78 |
79 | 2008-07-11 Laurent Debacker
80 |
81 | * ApplicationMenu.cs: Working menu opening
82 |
83 | 2008-07-11 Laurent Debacker
84 |
85 | * Theme.cs: First steps for the app menu theme
86 | * ApplicationMenuItem.cs: Better handling of fast moving pointers
87 | * ApplicationMenu.cs: Bugfixes
88 |
89 | 2008-07-11 Laurent Debacker
90 |
91 | * Theme.cs: Better behavior of hilighs for app menu item
92 | * ApplicationMenuItem.cs: More work on proper app menu item behavior
93 | (hilights)
94 |
95 | 2008-07-10 Laurent Debacker
96 |
97 | * Theme.cs: Fix them code for app menu item
98 | * ApplicationMenuItem.cs: Bug fixes
99 | * ApplicationMenu.cs: Remove debug code
100 |
101 | 2008-07-09 Laurent Debacker
102 |
103 | * ApplicationMenu.cs: Bugfix, can now open app menu multiple times
104 |
105 | 2008-07-08 Laurent Debacker
106 |
107 | * QuickAccessToolbar.cs, FlowLayoutContainer.cs: Bugfix in remove
108 | * Theme.cs, ApplicationMenuItem.cs: API update
109 | * ApplicationMenu.cs: Lot of work to solve the rendering bug. It is now
110 | gone, but I cannot open the menu more than once...
111 |
112 | 2008-07-07 Laurent Debacker
113 |
114 | * Theme.cs: Initial theme code for app menu item borowed from button
115 | * ApplicationMenuItem.cs: Size alloc, size request, drawing
116 | * ApplicationMenu.cs: Bug fix in size alloc
117 |
118 | 2008-07-07 Laurent Debacker
119 |
120 | * ApplicationMenu.cs: Autohide the app menu when required
121 |
122 | 2008-07-07 Laurent Debacker
123 |
124 | * Theme.cs: Updated for new app menu API
125 | * ApplicationMenuItem.cs, ApplicationMenu.cs: Major refactoring
126 | * ApplicationButton.cs: Update for new App menu API
127 |
128 | 2008-07-06 Laurent Debacker
129 |
130 | * ApplicationMenu.cs: Compilation bug fixes, sorry
131 |
132 | 2008-07-06 Laurent Debacker
133 |
134 | * Theme.cs: Dummy renderer for App menu and app menu item
135 | * ApplicationMenu.cs: More work on app menu item
136 |
137 | 2008-07-04 Laurent Debacker
138 |
139 | * ApplicationButton.cs: Bugfixes for popup position, and misc other bug
140 | fixes
141 |
142 | 2008-07-04 Laurent Debacker
143 |
144 | * ApplicationMenu.cs: Implementation of SizeAllocated for app menu, and more
145 | work on SizeRequest
146 |
147 | 2008-07-04 Laurent Debacker
148 |
149 | * ApplicationMenu.cs: Size requisition for app menu
150 |
151 | 2008-07-03 Laurent Debacker
152 |
153 | * Theme.cs: Fix background theme for Quick Access Toolbar when there is no
154 | app button
155 |
156 | 2008-06-30 Laurent Debacker
157 |
158 | * Theme.cs: Quick Access Toolbar background
159 | * ApplicationMenu.cs: Initial stub API for application menu.
160 | * QuickAccessToolbar.cs: Take care of height requests from children widgets
161 |
162 | 2008-06-28 Laurent Debacker
163 |
164 | * Theme.cs: Title bar's background is not compliant
165 | * Ribbon.cs: Fix title bar layout code
166 |
167 | 2008-06-28 Laurent Debacker
168 |
169 | * Theme.cs: Implementation of the required drop shadow for the app button
170 |
171 | 2008-06-27 Laurent Debacker
172 |
173 | * Theme.cs: Change background color depending on current state
174 | * Ribbon.cs: Bugfix for layout code
175 | * ApplicationButton.cs: Bugfix for widget initialization
176 |
177 | 2008-06-27 Laurent Debacker
178 |
179 | * QuickAccessToolbar.cs: Bugfix, add NO_WINDOW flag
180 | * Theme.cs: Implement final app button theme
181 | * Ribbon.cs: Bugfix, call app button and quick access toolbar when calling
182 | children
183 |
184 | 2008-06-23 Laurent Debacker
185 |
186 | * QuickAccessToolbar.cs: Implement size request and size allocation.
187 |
188 | 2008-06-16 Laurent Debacker
189 |
190 | * Theme.cs: Stub for the application button.
191 | * Ribbon.cs: Support for the application button.
192 | * ApplicationButton.cs: Initial commit.
193 |
194 | 2008-06-09 Laurent Debacker
195 |
196 | * Ribbon.cs:
197 |
198 | * More work a the layout of the QuickAccessToolbar
199 |
200 | * QuickAccessToolbar.cs:
201 |
202 | * Add minimal code to be able to use it as a child widget in the demo.
203 |
204 | * Theme.cs:
205 |
206 | * Drawing of the QuickAccessToolbar's background.
207 |
208 | 2008-06-02 Laurent Debacker
209 |
210 | * Ribbon.cs:
211 |
212 | * Add new Toolbar property to control the QuickAccessToolbar that
213 | belongs to a Ribbon.
214 |
215 | * Update Size Request
216 |
217 | * Update Allocations
218 |
219 | * Bugfix in the allocation
220 |
221 | * QuickAccessToolbar.cs:
222 |
223 | * Initial commit of the new Quick Access Toolbar widget with bare metal
224 | API.
225 |
226 | * ToolBox.cs:
227 |
228 | * Fixed a typo in a comment.
229 |
230 | 2008-06-02 Laurent Debacker
231 |
232 | * Ribbon.cs:
233 |
234 | * Add new Toolbar property to control the QuickAccessToolbar that
235 | belongs to a Ribbon.
236 |
237 | * Update Size Request
238 |
239 | * Update Allocations
240 |
241 | * Bugfix in the allocation
242 |
243 | * QuickAccessToolbar.cs:
244 |
245 | * Initial commit of the new Quick Access Toolbar widget with bare metal
246 | API.
247 |
248 | * ToolBox.cs:
249 |
250 | * Fixed a typo in a comment.
251 |
252 | 2008-02-07 Laurent Debacker
253 |
254 | * Gallery.cs, GalleryPopupWindow.cs: * You can now click anywhere to close
255 | the popup. (Paweł 'X4lldux' Drygas).
256 |
257 | * Proper tile selection. (Paweł 'X4lldux' Drygas).
258 |
259 | 2008-01-25 Laurent Debacker
260 |
261 | * RibbonGroup.cs, Button.cs: Added signal names to enable accelerators.
262 |
263 | 2008-01-19 Laurent Debacker
264 |
265 | * Theme.cs, Position.cs, RibbonGroup.cs, Ribbons.mdp: Left, Right, and Top
266 | position for the label of RibbonGroup implemented.
267 |
268 | 2007-12-27 Laurent Debacker
269 |
270 | * Ribbon.cs, ToggleButton.cs, RibbonGroup.cs, Tile.cs, Gallery.cs, Theme.cs,
271 | gtk-gui/generated.cs, gtk-gui/objects.xml, gtk-gui/gui.stetic,
272 | Ribbons.mdp, Button.cs, ChangeLog: Fixing calls to Dispose() and
273 | Destroy()
274 |
275 |
--------------------------------------------------------------------------------
/Ribbons/ColorScheme.cs:
--------------------------------------------------------------------------------
1 | using Cairo;
2 | using System;
3 |
4 | namespace Ribbons
5 | {
6 | /// Color scheme.
7 | public class ColorScheme
8 | {
9 | private Color prettyDark, dark, lightDark, normal, lightBright, bright, prettyBright;
10 |
11 | public Color PrettyDark
12 | {
13 | set { prettyDark = value; }
14 | get { return prettyDark; }
15 | }
16 |
17 | public Color Dark
18 | {
19 | set { dark = value; }
20 | get { return dark; }
21 | }
22 |
23 | public Color LightDark
24 | {
25 | set { lightDark = value; }
26 | get { return lightDark; }
27 | }
28 |
29 | public Color Normal
30 | {
31 | set { normal = value; }
32 | get { return normal; }
33 | }
34 |
35 | public Color LightBright
36 | {
37 | set { lightBright = value; }
38 | get { return lightBright; }
39 | }
40 |
41 | public Color Bright
42 | {
43 | set { bright = value; }
44 | get { return bright; }
45 | }
46 |
47 | public Color PrettyBright
48 | {
49 | set { prettyBright = value; }
50 | get { return prettyBright; }
51 | }
52 |
53 | //public ColorScheme() : this (new Color(0.957, 0.957, 0.957))
54 | public ColorScheme() : this (new Color(0.867, 0.867, 0.867))
55 | //public ColorScheme() : this (new Color(0.925, 0.914, 0.847))
56 | //public ColorScheme() : this (new Color(0.937, 0.922, 0.898))
57 | {
58 |
59 | }
60 |
61 | public ColorScheme (Color Normal)
62 | {
63 | prettyDark = GetColorRelative (Normal, -0.4);
64 | dark = GetColorRelative (Normal, -0.1);
65 | lightDark = GetColorRelative (Normal, -0.05);
66 | normal = Normal;
67 | lightBright = GetColorRelative (Normal, 0.05);
68 | bright = GetColorRelative (Normal, 0.1);
69 | prettyBright = GetColorRelative (Normal, 0.15);
70 | }
71 |
72 | internal static Color SetAlphaChannel(Color C, double Alpha)
73 | {
74 | return new Color (C.R, C.G, C.B, Alpha);
75 | }
76 |
77 | internal static Color GetColorAbsolute(Color C, double luminance)
78 | {
79 | /*double h, s, v;
80 | RGB2HSV(C, out h, out s, out v);
81 | v = v + (1.7 * (luminance - 1));
82 | if(v < 0) v = 0; else if(v > 1) v = 1;
83 | return HSV2RGB(h, s, v);*/
84 |
85 | double h, s, l;
86 | RGB2HSL(C, out h, out s, out l);
87 | /*double a = (h % 60) / 60;
88 | if(a > 0.5) a -= 0.5;*/
89 | //l = l + (1.7 * (luminance - 1));
90 | l = luminance;
91 | if(l < 0) l = 0; else if(l > 1) l = 1;
92 | return HSL2RGB(h, s, l);
93 | }
94 |
95 | internal static Color GetColorRelative(Color C, double luminance)
96 | {
97 | double h, s, l;
98 | RGB2HSL(C, out h, out s, out l);
99 | /*double a = (h % 60) / 60;
100 | if(a > 0.5) a -= 0.5;*/
101 | l = l + luminance;
102 | if(l < 0) l = 0; else if(l > 1) l = 1;
103 | return HSL2RGB(h, s, l);
104 | }
105 |
106 | private static void RGB2HSL(Color C, out double H, out double S, out double L)
107 | {
108 | double r = C.R, g = C.G, b = C.B;
109 | double max = Math.Max(r, Math.Max(g, b));
110 | double min = Math.Min(r, Math.Min(g, b));
111 | L = 0.5 * (max + min);
112 | if(max == min)
113 | {
114 | H = double.NaN;
115 | }
116 | else
117 | {
118 | if(max == r)
119 | {
120 | if(g >= b)
121 | H = (g-b)/(max-min) * 60;
122 | else
123 | H = (g-b)/(max-min) * 60 + 360;
124 | }
125 | else if(max == g)
126 | H = (b-r)/(max-min) * 60 + 120;
127 | else
128 | H = (r-g)/(max-min) * 60 + 240;
129 | }
130 | if(0.0000001 <= L && L <= 0.5)
131 | S = (max-min) / (2*L);
132 | else if(L > 0.5)
133 | S = (max-min) / (2-2*L);
134 | else
135 | S = 0;
136 | }
137 |
138 | private static Color HSL2RGB(double H, double S, double L)
139 | {
140 | double r = L, g = L, b = L;
141 | double Q;
142 | if(L < 0.5)
143 | Q = L * (1 + S);
144 | else
145 | Q = L + S - L * S;
146 | double P = 2 * L - Q;
147 | if(Q > 0)
148 | {
149 | double m = L + L - Q;
150 | H /= 60;
151 | int i = (int)H % 6;
152 | double vsf = Q * (Q - m) / Q * (H - i);
153 | switch(i)
154 | {
155 | case 0:
156 | r = Q;
157 | g = m + vsf;
158 | b = m;
159 | break;
160 | case 1:
161 | r = m - vsf;
162 | g = Q;
163 | b = m;
164 | break;
165 | case 2:
166 | r = m;
167 | g = Q;
168 | b = m + vsf;
169 | break;
170 | case 3:
171 | r = m;
172 | g = m - vsf;
173 | b = Q;
174 | break;
175 | case 4:
176 | r = m + vsf;
177 | g = m;
178 | b = Q;
179 | break;
180 | case 5:
181 | r = Q;
182 | g = m;
183 | b = m - vsf;
184 | break;
185 | }
186 | }
187 | return new Color (r, g, b);
188 | }
189 |
190 | private static void RGB2HSV(Color C, out double H, out double S, out double V)
191 | { // http://www.daniweb.com/techtalkforums/thread38302.html
192 | double r = C.R, g = C.G, b = C.B;
193 | double max = Math.Max (r, Math.Max (g, b));
194 | double min = Math.Min (r, Math.Min (g, b));
195 | double delta = max - min;
196 | V = max;
197 | if(Math.Abs (delta) < 0.0000001)
198 | {
199 | H = S = 0;
200 | }
201 | else
202 | {
203 | S = delta / max;
204 | if(r == max)
205 | H = 60.0 * (g - b) / delta;
206 | else if(g == max)
207 | H = 60.0 * (2 + (b - r) / delta);
208 | else
209 | H = 60.0 * (4 + (r - g) / delta);
210 | if(H < 0) H += 360; else if(H > 360) H -= 360;
211 | }
212 | }
213 |
214 | private static Color HSV2RGB(double H, double S, double V)
215 | { // http://en.wikipedia.org/wiki/HSV_color_space
216 | int H_i = (int)(H / 60) % 6;
217 | double f = H / 60 - H_i;
218 | if(H_i == 0) return new Color (V, V * (1 - (1 - f) * S), V * (1 - S));
219 | if(H_i == 1) return new Color (V * (1 - f * S), V, V * (1 - S));
220 | if(H_i == 2) return new Color (V * (1 - S), V, V * (1 - (1 - f) * S));
221 | if(H_i == 3) return new Color (V * (1 - S), V * (1 - f * S), V);
222 | if(H_i == 4) return new Color (V * (1 - (1 - f) * S), V * (1 - S), V);
223 | return new Color (V, V * (1 - S), V * (1 - f * S));
224 | }
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/Ribbons/DropdownRibbonGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Gtk;
3 |
4 | namespace Ribbons
5 | {
6 | ///
7 | /// A toggle button replacing a ribbon group when space is too constrained.
8 | ///
9 | public class DropdownRibbonGroup : ToggleButton
10 | {
11 | private RibbonGroup group;
12 | private SyntheticWindow win;
13 |
14 | public RibbonGroup Group
15 | {
16 | get { return group; }
17 | set { group = value; }
18 | }
19 |
20 | public DropdownRibbonGroup ()
21 | {
22 | DrawBackground = true;
23 | ImagePosition = PositionType.Top;
24 | isSmall = false;
25 | DisplayArrow = true;
26 | }
27 |
28 | protected override void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt)
29 | {
30 | base.BindedWidget_ButtonReleaseEvent (sender, evnt);
31 |
32 | if(Value)
33 | {
34 | int x, y;
35 | ParentWindow.GetOrigin (out x, out y);
36 | x += Allocation.X;
37 | y += Allocation.Bottom;
38 |
39 | ShowAt (x, y);
40 | }
41 | else
42 | {
43 | KillMenu (true);
44 | }
45 | }
46 |
47 | private void ShowAt (int x, int y)
48 | {
49 | if(win != null) return;
50 |
51 | win = new SyntheticWindow (WindowType.Popup);
52 | win.Child = group;
53 |
54 | win.Hidden += delegate { KillMenu (true); };
55 |
56 | win.ShowAll ();
57 | win.GdkWindow.Move (x, y);
58 |
59 | win.ButtonReleaseEvent += delegate { KillMenu (true); };
60 | win.AddEvents ((int)(Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
61 |
62 | Grab.Add (win);
63 | Gdk.GrabStatus grabbed = Gdk.Pointer.Grab (win.GdkWindow, true, Gdk.EventMask.ButtonPressMask, null, null, 0);
64 | if(grabbed != Gdk.GrabStatus.Success)
65 | {
66 | KillMenu (false);
67 | return;
68 | }
69 |
70 | grabbed = Gdk.Keyboard.Grab (win.GdkWindow, true, 0);
71 | if(grabbed != Gdk.GrabStatus.Success)
72 | {
73 | KillMenu (false);
74 | return;
75 | }
76 | }
77 |
78 | private void KillMenu (bool Ungrab)
79 | {
80 | if(win == null) return;
81 |
82 | Grab.Remove (win);
83 | if(Ungrab)
84 | {
85 | Gdk.Pointer.Ungrab (0);
86 | Gdk.Keyboard.Ungrab (0);
87 | }
88 | win.Hide ();
89 | group.Unparent ();
90 | win = null;
91 |
92 | Value = false;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Ribbons/ExtraEventBox.cs:
--------------------------------------------------------------------------------
1 | using Gtk;
2 | using System;
3 |
4 | namespace Ribbons
5 | {
6 | /// EventBox extended to transmit all events.
7 | public class ExtraEventBox : EventBox
8 | {
9 | protected override bool OnWidgetEvent (Gdk.Event evnt)
10 | {
11 | if(evnt.Window.Equals (this.GdkWindow))
12 | {
13 | if(evnt.Type != Gdk.EventType.Expose)
14 | {
15 | if(Child != null) Child.ProcessEvent (evnt);
16 | }
17 | }
18 | return base.OnWidgetEvent (evnt);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Ribbons/FlowLayoutContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Container displaying children using a flow layout.
8 | public class FlowLayoutContainer : Container
9 | {
10 | private List children;
11 | private Requisition[] childReqs;
12 |
13 | /// Returns the number of children.
14 | public int NChildren
15 | {
16 | get { return children.Count; }
17 | }
18 |
19 | /// Default constructor.
20 | public FlowLayoutContainer()
21 | {
22 | this.SetFlag (WidgetFlags.NoWindow);
23 |
24 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
25 |
26 | this.children = new List ();
27 | }
28 |
29 | /// Adds a widget before all existing widgetw.
30 | /// The widget to add.
31 | public void Prepend (Widget w)
32 | {
33 | Insert (w, 0);
34 | }
35 |
36 | /// Adds a widget after all existing widgets.
37 | /// The widget to add.
38 | public void Append (Widget w)
39 | {
40 | Insert (w, -1);
41 | }
42 |
43 | /// Inserts a widget at the specified location.
44 | /// The widget to add.
45 | /// The index (starting at 0) at which the widget must be inserted, or -1 to insert the widget after all existing widgets.
46 | public void Insert (Widget w, int WidgetIndex)
47 | {
48 | w.Parent = this;
49 | w.Visible = true;
50 |
51 | if(WidgetIndex == -1)
52 | children.Add (w);
53 | else
54 | children.Insert (WidgetIndex, w);
55 |
56 | ShowAll ();
57 | }
58 |
59 | /// Removes the widget at the specified index.
60 | /// Index of the widget to remove.
61 | public void Remove (int WidgetIndex)
62 | {
63 | if(WidgetIndex == -1) WidgetIndex = children.Count - 1;
64 |
65 | children[WidgetIndex].Parent = null;
66 | children.RemoveAt (WidgetIndex);
67 |
68 | ShowAll ();
69 | }
70 |
71 | protected override void ForAll (bool include_internals, Callback callback)
72 | {
73 | foreach(Widget w in children)
74 | {
75 | if(w.Visible) callback (w);
76 | }
77 | }
78 |
79 | protected override void OnSizeRequested (ref Requisition requisition)
80 | {
81 | base.OnSizeRequested (ref requisition);
82 |
83 | int n = children.Count, nVisible = 0;
84 | childReqs = new Requisition[n];
85 | for(int i = 0 ; i < n ; ++i)
86 | {
87 | if(children[i].Visible)
88 | {
89 | childReqs[i] = children[i].SizeRequest ();
90 | ++nVisible;
91 | }
92 | }
93 |
94 | if(WidthRequest != -1)
95 | {
96 | if(HeightRequest == -1)
97 | {
98 | int currentLineHeight = 0, currentLineWidth = 0;
99 | foreach(Widget w in children)
100 | {
101 | if(w.Visible)
102 | {
103 | Requisition childReq = w.SizeRequest ();
104 | currentLineHeight = Math.Max (childReq.Height, currentLineHeight);
105 | currentLineWidth += childReq.Width;
106 | if(currentLineWidth >= WidthRequest)
107 | {
108 | currentLineHeight = 0;
109 | currentLineWidth = 0;
110 | }
111 | }
112 | }
113 | requisition.Height = currentLineHeight;
114 | }
115 | }
116 | else // (WidthRequest == -1)
117 | {
118 | if(HeightRequest == -1)
119 | {
120 | foreach(Widget w in children)
121 | {
122 | if(w.Visible)
123 | {
124 | Requisition childReq = w.SizeRequest ();
125 | requisition.Height = Math.Max (childReq.Height, requisition.Height);
126 | requisition.Width += childReq.Width;
127 | }
128 | }
129 | }
130 | else
131 | {
132 | #if !EXPERIMENTAL
133 | int totalWidth = 0, maxWidth = 0;
134 | for(int i = 0 ; i < n ; ++i)
135 | {
136 | if(children[i].Visible)
137 | {
138 | totalWidth += childReqs[i].Width;
139 | maxWidth = Math.Max (childReqs[i].Width, maxWidth);
140 | }
141 | }
142 |
143 | // TODO: the following algorithm a dichotomic-like search approach (lower bound: 1, upper bound: number of widgets)
144 |
145 | int lineCount = 0;
146 | int totalHeight = 0;
147 |
148 | do
149 | {
150 | ++lineCount;
151 | int lineWidth = (int)Math.Ceiling ((double)totalWidth / lineCount);
152 | if(lineWidth < maxWidth) break;
153 | int currentLineWidth = 0, currentLineHeight = 0;
154 | for(int i = 0 ; i < n ; ++i)
155 | {
156 | if(children[i].Visible)
157 | {
158 | currentLineWidth += childReqs[i].Width;
159 | if(currentLineWidth > lineWidth)
160 | {
161 | totalHeight += currentLineHeight;
162 | currentLineWidth = childReqs[i].Width;
163 | currentLineHeight = 0;
164 | }
165 | currentLineHeight = Math.Max (childReqs[i].Height, currentLineHeight);
166 | }
167 | }
168 | totalHeight += currentLineHeight;
169 |
170 | if(totalHeight <= HeightRequest)
171 | {
172 | requisition.Width = lineWidth;
173 | }
174 | } while(totalHeight < HeightRequest && lineCount < nVisible);
175 | #else
176 | int height = 0;
177 | for(int i = 0 ; i < n ; ++i)
178 | {
179 | height = Math.Max (childReqs[i].Height, height);
180 | }
181 |
182 | List segments = new List();
183 | segments.Add (0);
184 | segments.Add (n);
185 |
186 | for(;;)
187 | {
188 | int bestCandidateHeight = int.MaxValue;
189 | int bestSplit = -1;
190 | for(int i = 1 ; i < segments.Count ; ++i)
191 | {
192 | int oldSum, newSum;
193 | int splitPos = SplitWidgetsInTwo (childReqs, segments[i-1], segments[i] - 1, out oldSum, out newSum);
194 | int candidate = height - oldSum + newSum;
195 | if(newSum < oldSum && candidate < bestCandidateHeight)
196 | {
197 | bestSplit = splitPos;
198 | bestCandidateHeight = candidate;
199 | }
200 | }
201 |
202 | if(bestCandidateHeight < HeightRequest)
203 | {
204 | segments.Insert (~segments.BinarySearch (bestSplit), bestSplit);
205 | }
206 | else break;
207 | }
208 |
209 | int currentSegmentWidth = 0, currentSegmentNr = 1;
210 | for(int i = 0 ; i < n ; ++i)
211 | {
212 | if(i == segments[currentSegmentNr])
213 | {
214 | ++currentSegmentNr;
215 | WidthRequest = Math.Max (currentSegmentNr, WidthRequest);
216 | currentSegmentNr = 0;
217 | }
218 | currentSegmentWidth += childReqs[i].Width;
219 | }
220 | requisition.Width = Math.Max (currentSegmentNr, WidthRequest);
221 | #endif
222 | }
223 | }
224 | }
225 |
226 | #if EXPERIMENTAL
227 | private int SplitWidgetsInTwo (Requisition[] Requisitions, int Index, int Length, out int PreviousSum, out int NewSum)
228 | {
229 | int[] maxLeft = new int[Length], maxRight = new int[Length];
230 | maxLeft[0] = Requisitions[Index].Width;
231 | maxRight[Length-1] = Requisitions[Index+Length-1].Width;
232 | PreviousSum = 0;
233 | for(int i = 1 ; i < Length ; ++i)
234 | {
235 | maxLeft[i] = Math.Max (maxLeft[i-1] , Requisitions[i+Index].Width);
236 | maxRight[Length-1-i] = Math.Max (maxLeft[Length-i] , Requisitions[Length-1-i+Index].Width);
237 | PreviousSum += Requisitions[i+Index].Height;
238 | }
239 |
240 | int ret = 0, smallestSum = int.MaxValue;
241 | for(int i = 0 ; i < Length ; ++i)
242 | {
243 | int sum = maxLeft[i] + maxRight[i];
244 | if(sum < smallestSum)
245 | {
246 | smallestSum = sum;
247 | ret = i + Index + 1;
248 | }
249 | }
250 |
251 | NewSum = smallestSum;
252 | return ret;
253 | }
254 | #endif
255 |
256 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
257 | {
258 | base.OnSizeAllocated (allocation);
259 |
260 | int n = children.Count;
261 | Gdk.Rectangle childAlloc = allocation;
262 | int lineHeight = 0;
263 | for(int i = 0 ; i < n ; ++i)
264 | {
265 | if(children[i].Visible)
266 | {
267 | childAlloc.Width = childReqs[i].Width;
268 | childAlloc.Height = childReqs[i].Height;
269 |
270 | if(childAlloc.X != allocation.X && childAlloc.Right > allocation.Right)
271 | {
272 | childAlloc.X = allocation.X;
273 | childAlloc.Y += lineHeight;
274 | lineHeight = 0;
275 | }
276 |
277 | children[i].SizeAllocate (childAlloc);
278 | childAlloc.X += childAlloc.Width;
279 | lineHeight = Math.Max (childAlloc.Height, lineHeight);
280 | }
281 | }
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/Ribbons/Gallery.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Cairo;
4 | using Gtk;
5 |
6 | namespace Ribbons
7 | {
8 | /// Gallery of Tiles.
9 | public class Gallery : Container
10 | {
11 | protected Theme theme = Theme.DefaultTheme;
12 | private int tileWidth, tileHeight;
13 | private List tiles;
14 | private Button up, down;
15 | private ToggleButton expand;
16 | private int defaultTilesPerRow;
17 | private int tileSpacing;
18 | private GalleryPopupWindow popup;
19 |
20 | private bool multiSelect;
21 | private List selectedTiles;
22 | private int firstDisplayedTileIndex, lastDisplayedTileIndex;
23 | private int btnWidth;
24 | private Requisition upReq, downReq, expandReq;
25 | private Gdk.Rectangle tilesAlloc;
26 |
27 | private const double space = 2.0;
28 | private const double lineWidth = 1.0;
29 |
30 | /// Fired when a Tile has been selected.
31 | public event TileSelectedHandler TileSelected;
32 |
33 | /// Gets or sets the width of Tiles.
34 | public int TileWidth
35 | {
36 | set
37 | {
38 | tileWidth = value;
39 | QueueDraw ();
40 | }
41 | get { return tileWidth; }
42 | }
43 |
44 | /// Gets or sets the height of Tiles.
45 | public int TileHeight
46 | {
47 | set
48 | {
49 | tileHeight = value;
50 | QueueDraw ();
51 | }
52 | get { return tileHeight; }
53 | }
54 |
55 | /// Gets or sets the spacing between Tiles.
56 | public int TileSpacing
57 | {
58 | set
59 | {
60 | tileSpacing = value;
61 | QueueDraw ();
62 | }
63 | get { return tileSpacing; }
64 | }
65 |
66 | /// Gets or sets the default number of Tiles per row.
67 | public int DefaultTilesPerRow
68 | {
69 | set
70 | {
71 | defaultTilesPerRow = value;
72 | QueueDraw ();
73 | }
74 | get { return defaultTilesPerRow; }
75 | }
76 |
77 | /// Gets or sets the selected Tile.
78 | public Tile SelectedTile
79 | {
80 | set
81 | {
82 | if(popup != null)
83 | {
84 | Grab.Remove(popup);
85 | Gdk.Pointer.Ungrab(0);
86 | Gdk.Keyboard.Ungrab(0);
87 |
88 | popup.Hide ();
89 | popup.Destroy();
90 | popup = null;
91 | }
92 |
93 | if(selectedTiles.Count > 0)
94 | {
95 | foreach(Tile t in selectedTiles) t.Selected = false;
96 | }
97 | selectedTiles.Clear ();
98 | selectedTiles.Add (value);
99 | if(value != null)
100 | {
101 | value.Selected = true;
102 |
103 | int idx = tiles.FindIndex (delegate (Tile t) { return t == value; });
104 | if(idx != -1)
105 | {
106 | firstDisplayedTileIndex = idx/defaultTilesPerRow*defaultTilesPerRow;
107 | lastDisplayedTileIndex = -1;
108 | UpdateTilesLayout ();
109 | QueueDraw ();
110 | }
111 | }
112 | }
113 | get { return selectedTiles.Count == 0 ? null : selectedTiles[selectedTiles.Count-1]; }
114 | }
115 |
116 | /// Gets the list of selected Tiles.
117 | public IList SelectedTiles
118 | {
119 | get { return selectedTiles.AsReadOnly (); }
120 | }
121 |
122 | /// Returns all Tiles.
123 | public IEnumerable Tiles
124 | {
125 | get
126 | {
127 | return tiles;
128 | }
129 | }
130 |
131 | /// Theme used to draw the widget.
132 | public Theme Theme
133 | {
134 | set
135 | {
136 | theme = value;
137 | QueueDraw ();
138 | }
139 | get { return theme; }
140 | }
141 |
142 | /// Default constructor.
143 | public Gallery()
144 | {
145 | this.SetFlag (WidgetFlags.NoWindow);
146 |
147 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
148 |
149 | this.tiles = new List ();
150 | this.selectedTiles = new List ();
151 |
152 | this.defaultTilesPerRow = 3;
153 | this.firstDisplayedTileIndex = 0;
154 | this.lastDisplayedTileIndex = -1;
155 | this.multiSelect = false;
156 |
157 | this.tileHeight = 56;
158 | this.tileWidth = 72;
159 | this.tileSpacing = 0;
160 | this.BorderWidth = 2;
161 |
162 | this.up = new Button ("\u25B2");
163 | this.up.Parent = this;
164 | this.up.Padding = 0;
165 | this.up.Clicked += up_Clicked;
166 |
167 | this.down = new Button ("\u25BC");
168 | this.down.Parent = this;
169 | this.down.Padding = 0;
170 | this.down.Clicked += down_Clicked;
171 |
172 | this.expand = new ToggleButton ("\u2193");
173 | this.expand.Parent = this;
174 | this.expand.Padding = 0;
175 | this.expand.ValueChanged += expand_ValueChanged;
176 | }
177 |
178 | /// Adds a tile before all existing tiles.
179 | /// The tile to add.
180 | public void PrependTile (Tile t)
181 | {
182 | InsertTile (t, 0);
183 | }
184 |
185 | /// Adds a tile after all existing tiles.
186 | /// The tile to add.
187 | public void AppendTile (Tile t)
188 | {
189 | InsertTile (t, -1);
190 | }
191 |
192 | /// Inserts a tile at the specified location.
193 | /// The tile to add.
194 | /// The index (starting at 0) at which the tile must be inserted, or -1 to insert the tile after all existing tiles.
195 | public void InsertTile (Tile t, int TileIndex)
196 | {
197 | if(TileIndex == -1 || TileIndex == tiles.Count)
198 | {
199 | tiles.Add (t);
200 | }
201 | else
202 | {
203 | tiles.Insert (TileIndex, t);
204 | }
205 |
206 | if (tiles.Count == 1)
207 | SelectedTile = t;
208 |
209 | //t.Parent = this;
210 | t.Visible = true;
211 | t.Clicked += Tile_Clicked;
212 | }
213 |
214 | /// Removes the tile at the specified index.
215 | /// Index of the tile to remove.
216 | public void RemoveTile (int TileIndex)
217 | {
218 | Tile t = tiles[TileIndex];
219 | t.Clicked -= Tile_Clicked;
220 | t.Unparent ();
221 | if(selectedTiles.Contains (t)) selectedTiles.Remove (t);
222 |
223 | tiles.RemoveAt (TileIndex);
224 | }
225 |
226 | private void up_Clicked(object Sender, EventArgs e)
227 | {
228 | MoveUp ();
229 | }
230 |
231 | private void down_Clicked(object Sender, EventArgs e)
232 | {
233 | MoveDown ();
234 | }
235 |
236 | private void expand_ValueChanged(object Sender, EventArgs e)
237 | {
238 | if(expand.Value)
239 | {
240 | popup = new GalleryPopupWindow (this);
241 | popup.Realized += delegate {
242 | int x, y;
243 | ParentWindow.GetOrigin (out x, out y);
244 | x += Allocation.X;
245 | y += Allocation.Y;
246 | popup.GdkWindow.Move (x, y);
247 | };
248 |
249 | popup.Hidden += delegate {
250 | expand.ValueChanged -= expand_ValueChanged;
251 | expand.Value = false;
252 | expand.QueueDraw ();
253 | expand.ValueChanged += expand_ValueChanged;
254 | };
255 | popup.Show ();
256 |
257 | popup.ButtonReleaseEvent += OnButtonReleased;
258 | popup.AddEvents ((int) Gdk.EventMask.ButtonPressMask);
259 | Grab.Add(popup);
260 |
261 | Gdk.GrabStatus grabbed = Gdk.Pointer.Grab(popup.GdkWindow, true, Gdk.EventMask.ButtonReleaseMask, null, null, 0);
262 | if(grabbed == Gdk.GrabStatus.Success) {
263 | grabbed = Gdk.Keyboard.Grab(popup.GdkWindow, true, 0);
264 |
265 | if(grabbed != Gdk.GrabStatus.Success)
266 | {
267 | Grab.Remove(popup);
268 | popup.Hide ();
269 | popup.Destroy();
270 | popup = null;
271 |
272 | return;
273 | }
274 | } else {
275 | Grab.Remove(popup);
276 | popup.Hide ();
277 | popup.Destroy();
278 | popup = null;
279 | }
280 | }
281 | else
282 | {
283 | if (popup != null)
284 | {
285 | Grab.Remove(popup);
286 | popup.Hide ();
287 | popup.Destroy();
288 | popup = null;
289 | }
290 | }
291 | }
292 |
293 | private void Tile_Clicked(object Sender, EventArgs e)
294 | {
295 | Tile selectedTile = (Tile)Sender;
296 |
297 | if(multiSelect)
298 | {
299 | selectedTile.Selected = !selectedTile.Selected;
300 | if(selectedTile.Selected)
301 | selectedTiles.Add (selectedTile);
302 | else
303 | selectedTiles.Remove (selectedTile);
304 | }
305 | else if(Sender != SelectedTile)
306 | {
307 | SelectedTile = selectedTile;
308 | }
309 |
310 | OnTileSelected (selectedTile);
311 | }
312 |
313 | private void MoveUp ()
314 | {
315 | if(firstDisplayedTileIndex > 0)
316 | {
317 | firstDisplayedTileIndex = -1;
318 | lastDisplayedTileIndex = firstDisplayedTileIndex - 1;
319 | }
320 | UpdateTilesLayout ();
321 | QueueDraw ();
322 | }
323 |
324 | private void MoveDown ()
325 | {
326 | if(lastDisplayedTileIndex < tiles.Count - 1)
327 | {
328 | firstDisplayedTileIndex = lastDisplayedTileIndex + 1;
329 | lastDisplayedTileIndex = -1;
330 | }
331 | UpdateTilesLayout ();
332 | QueueDraw ();
333 | }
334 |
335 | /// Fires the SelectedTile event.
336 | /// The Tile that has been selected.
337 | protected void OnTileSelected (Tile SelectedTile)
338 | {
339 | if(TileSelected != null) TileSelected (this, new TileSelectedEventArgs (SelectedTile));
340 | }
341 |
342 | private void OnButtonReleased(object o, ButtonReleaseEventArgs args)
343 | {
344 | if(popup != null) {
345 | Grab.Remove(popup);
346 | Gdk.Pointer.Ungrab(0);
347 | Gdk.Keyboard.Ungrab(0);
348 |
349 | popup.Hide ();
350 | popup.Destroy();
351 | popup = null;
352 | }
353 | }
354 |
355 | private void UpdateTilesLayout ()
356 | {
357 | Gdk.Rectangle tileAlloc;
358 | tileAlloc.X = tilesAlloc.X;
359 | tileAlloc.Y = tilesAlloc.Y;
360 | tileAlloc.Height = tilesAlloc.Height;
361 | tileAlloc.Width = tileWidth;
362 |
363 | int maxTiles = (tilesAlloc.Width + tileSpacing) / (tileWidth + tileSpacing);
364 |
365 | if(firstDisplayedTileIndex == -1)
366 | {
367 | firstDisplayedTileIndex = lastDisplayedTileIndex - maxTiles + 1;
368 | if(firstDisplayedTileIndex < 0)
369 | {
370 | lastDisplayedTileIndex -= firstDisplayedTileIndex;
371 | firstDisplayedTileIndex = 0;
372 | }
373 | }
374 | else if(lastDisplayedTileIndex == -1)
375 | {
376 | lastDisplayedTileIndex = firstDisplayedTileIndex + maxTiles - 1;
377 | }
378 |
379 | if(lastDisplayedTileIndex >= tiles.Count)
380 | {
381 | lastDisplayedTileIndex = tiles.Count - 1;
382 | }
383 |
384 | up.Enabled = firstDisplayedTileIndex > 0;
385 | down.Enabled = lastDisplayedTileIndex < tiles.Count - 1;
386 |
387 | for(int tileIndex = 0 ; tileIndex < firstDisplayedTileIndex ; ++tileIndex)
388 | {
389 | if(tiles[tileIndex].Parent != null) tiles[tileIndex].Unparent ();
390 | }
391 | for(int tileIndex = lastDisplayedTileIndex + 1 ; tileIndex < tiles.Count ; ++tileIndex)
392 | {
393 | if(tiles[tileIndex].Parent != null) tiles[tileIndex].Unparent ();
394 | }
395 |
396 | for(int tileIndex = firstDisplayedTileIndex ; tileIndex <= lastDisplayedTileIndex ; ++tileIndex)
397 | {
398 | Tile t = tiles[tileIndex];
399 |
400 | if(t.Parent == null) t.Parent = this;
401 |
402 | t.SizeRequest ();
403 |
404 | t.SizeAllocate (tileAlloc);
405 | tileAlloc.X += tileAlloc.Width + tileSpacing;
406 | }
407 | }
408 |
409 | protected override void ForAll (bool include_internals, Callback callback)
410 | {
411 | //if(include_internals)
412 | {
413 | callback (up);
414 | callback (down);
415 | callback (expand);
416 | }
417 |
418 | for(int i = firstDisplayedTileIndex ; i <= lastDisplayedTileIndex ; ++i)
419 | {
420 | callback (tiles[i]);
421 | }
422 | }
423 |
424 | protected override void OnSizeRequested (ref Requisition requisition)
425 | {
426 | base.OnSizeRequested (ref requisition);
427 |
428 | upReq = up.SizeRequest ();
429 | downReq = down.SizeRequest ();
430 | expandReq = expand.SizeRequest ();
431 |
432 | btnWidth = Math.Max (upReq.Width, Math.Max (downReq.Width, expandReq.Width));
433 | int btnHeight = upReq.Height + downReq.Height + expandReq.Height;
434 |
435 | int count = Math.Min (tiles.Count, defaultTilesPerRow);
436 | requisition.Width = btnWidth + (int)space + 2 * (int)lineWidth + count * tileWidth + (count + 1) * tileSpacing + 2 * (int)BorderWidth;
437 | requisition.Height = Math.Max (tileHeight + 2 * (tileSpacing + (int)lineWidth), btnHeight) + 2 * (int)BorderWidth;
438 |
439 | if(WidthRequest != -1) requisition.Width = WidthRequest;
440 | if(HeightRequest != -1) requisition.Height = HeightRequest;
441 | }
442 |
443 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
444 | {
445 | base.OnSizeAllocated (allocation);
446 |
447 | allocation.X += (int)BorderWidth;
448 | allocation.Y += (int)BorderWidth;
449 | allocation.Width -= 2 * (int)BorderWidth;
450 | allocation.Height -= 2 * (int)BorderWidth;
451 |
452 | Gdk.Rectangle btnAlloc;
453 | btnAlloc.Width = btnWidth;
454 | btnAlloc.X = allocation.X + allocation.Width - btnAlloc.Width + 1;
455 |
456 | btnAlloc.Y = allocation.Y;
457 | btnAlloc.Height = upReq.Height;
458 | up.SizeAllocate (btnAlloc);
459 |
460 | btnAlloc.Y += btnAlloc.Height;
461 | btnAlloc.Height = downReq.Height;
462 | down.SizeAllocate (btnAlloc);
463 |
464 | btnAlloc.Y += btnAlloc.Height;
465 | btnAlloc.Height = expandReq.Height;
466 | expand.SizeAllocate (btnAlloc);
467 |
468 | tilesAlloc.X = allocation.X + (int)lineWidth + tileSpacing;
469 | tilesAlloc.Y = allocation.Y + (int)lineWidth + tileSpacing;
470 | tilesAlloc.Width = btnAlloc.X - tilesAlloc.X - tileSpacing - (int)space - 2 * (int)lineWidth;
471 | tilesAlloc.Height = allocation.Height - 2 * (tileSpacing + (int)lineWidth);
472 |
473 | UpdateTilesLayout ();
474 | }
475 |
476 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
477 | {
478 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
479 |
480 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
481 | cr.Clip ();
482 | Draw (cr);
483 |
484 | ((IDisposable)cr.Target).Dispose ();
485 | ((IDisposable)cr).Dispose ();
486 |
487 | return base.OnExposeEvent (evnt);
488 | }
489 |
490 | protected void Draw (Context cr)
491 | {
492 | Rectangle alloc = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
493 | Rectangle tiles = new Rectangle (tilesAlloc.X - tileSpacing, tilesAlloc.Y - tileSpacing, tilesAlloc.Width + 2 * tileSpacing, tilesAlloc.Height + 2 * tileSpacing);
494 | theme.DrawGallery (cr, alloc, tiles, this);
495 | }
496 | }
497 | }
498 |
--------------------------------------------------------------------------------
/Ribbons/GalleryPopupWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Popup gallery.
8 | internal class GalleryPopupWindow : Window
9 | {
10 | private const int MAX_HEIGHT = 200;
11 | private const int SCROLLBAR_SIZE = 20;
12 |
13 | private Gallery underlyingGallery;
14 | private List tiles;
15 | private Dictionary mapping;
16 | private uint rows, columns;
17 | private Tile selectedTile;
18 |
19 | private ScrolledWindow internalWindow;
20 | private Table tileTable;
21 |
22 | /// Returns the underlying gallery.
23 | public Gallery UnderlyingGallery
24 | {
25 | get { return underlyingGallery; }
26 | }
27 |
28 | /// Default constructor.
29 | /// The underlying gallery.
30 | public GalleryPopupWindow (Gallery UnderlyingGallery) : base (WindowType.Popup)
31 | {
32 | this.underlyingGallery = UnderlyingGallery;
33 | this.tiles = new List ();
34 | this.mapping = new Dictionary ();
35 | foreach(Tile t in UnderlyingGallery.Tiles)
36 | {
37 | Tile copy = t.Copy ();
38 | copy.Show ();
39 | tiles.Add (copy);
40 |
41 | if(t == UnderlyingGallery.SelectedTile)
42 | {
43 | copy.Selected = true;
44 | selectedTile = t;
45 | }
46 |
47 | mapping.Add (copy, t);
48 | }
49 |
50 | int width = UnderlyingGallery.Allocation.Width;
51 |
52 | columns = (uint)(width / underlyingGallery.TileWidth);
53 | rows = (uint)Math.Ceiling ((double)tiles.Count / columns);
54 |
55 | this.tileTable = new Table (rows, columns, true);
56 | this.tileTable.Show ();
57 | this.tileTable.HeightRequest = (int)rows * UnderlyingGallery.TileHeight;
58 | this.tileTable.WidthRequest = (int)columns * UnderlyingGallery.TileWidth;
59 |
60 | Viewport vp = new Viewport ();
61 | vp.Show ();
62 | vp.Child = tileTable;
63 |
64 | this.internalWindow = new ScrolledWindow ();
65 | this.internalWindow.Show ();
66 | this.internalWindow.Child = vp;
67 | this.internalWindow.HeightRequest = Math.Min (this.tileTable.HeightRequest, MAX_HEIGHT) + SCROLLBAR_SIZE;
68 | this.internalWindow.WidthRequest = this.tileTable.WidthRequest + SCROLLBAR_SIZE;
69 |
70 | uint x = 0, y = 0;
71 | foreach(Tile t in tiles)
72 | {
73 | ExtraEventBox box = new ExtraEventBox ();
74 | box.Show ();
75 | box.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
76 | box.Child = t;
77 |
78 | tileTable.Attach (box, x, x+1, y, y+1);
79 | t.Clicked += tile_Clicked;
80 |
81 | if(++x == columns)
82 | {
83 | x = 0;
84 | ++y;
85 | }
86 | }
87 |
88 | this.Child = internalWindow;
89 | this.Child.ButtonPressEvent += delegate (object o, ButtonPressEventArgs args) {
90 | args.RetVal = true;
91 | };
92 | }
93 |
94 | private void tile_Clicked (object Sender, EventArgs e)
95 | {
96 | if(selectedTile != null) selectedTile.Selected = false;
97 | selectedTile = (Tile)Sender;
98 | selectedTile.Selected = true;
99 |
100 | underlyingGallery.SelectedTile = mapping[selectedTile];
101 |
102 | Hide ();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Ribbons/GroupStyle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | /// Position of a widget in a group of widget.
6 | public enum GroupStyle
7 | {
8 | Alone, Left, Center, Right
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Ribbons/GroupVariant.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Gtk;
3 |
4 | namespace Ribbons
5 | {
6 | public class GroupVariant
7 | {
8 | private Widget child;
9 | private int width;
10 |
11 | public Widget Child
12 | {
13 | get { return child; }
14 | }
15 |
16 | public int Width
17 | {
18 | get { return width; }
19 | }
20 |
21 | public GroupVariant (Widget Child)
22 | {
23 | this.child = Child;
24 | this.width = -1;
25 | }
26 |
27 | public void Measure (int Height)
28 | {
29 | child.HeightRequest = Height;
30 | Requisition req = child.SizeRequest ();
31 | width = req.Width;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Ribbons/KeyTip.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Gtk;
3 |
4 | namespace Ribbons
5 | {
6 | public class KeyTip
7 | {
8 | private Widget target;
9 | private string accelerator;
10 | private bool enabled;
11 | private Window win;
12 | private Theme theme = new Theme ();
13 |
14 | public Widget Target
15 | {
16 | get { return target; }
17 | set { target = value; }
18 | }
19 |
20 | public string Accelerator
21 | {
22 | get { return accelerator; }
23 | set { accelerator = value; }
24 | }
25 |
26 | public bool Enabled
27 | {
28 | get { return enabled; }
29 | set { enabled = value; }
30 | }
31 |
32 | public KeyTip ()
33 | {
34 |
35 | }
36 |
37 | public KeyTip (Widget Target, string Accelerator)
38 | {
39 | target = Target;
40 | accelerator = Accelerator;
41 | enabled = true;
42 | }
43 |
44 | public void ShowAt (int x, int y, double horizontal_align, double vertical_align)
45 | {
46 | if(win == null)
47 | {
48 | win = new Window (WindowType.Popup);
49 | }
50 |
51 | Pango.Layout layout = win.CreatePangoLayout (accelerator);
52 | int width, height;
53 | layout.GetPixelSize (out width, out height);
54 | width += 2;
55 | height += 2;
56 |
57 | x -= (int)(horizontal_align * width);
58 | y -= (int)(vertical_align * height);
59 |
60 | win.Show ();
61 | win.GdkWindow.Move (x, y);
62 | win.GdkWindow.Resize (width, height);
63 |
64 | win.ExposeEvent += delegate(object Sender, ExposeEventArgs Args)
65 | {
66 | Gdk.EventExpose evnt = Args.Event;
67 |
68 | Cairo.Context cr = Gdk.CairoHelper.Create (win.GdkWindow);
69 |
70 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
71 | cr.Clip ();
72 | theme.DrawKeyTip (cr, new Cairo.Point (win.Allocation.X, win.Allocation.Y), 0, 0, layout);
73 |
74 | ((IDisposable)cr.Target).Dispose ();
75 | ((IDisposable)cr).Dispose ();
76 | };
77 | }
78 |
79 | public void Hide ()
80 | {
81 | if(this.win == null) return;
82 |
83 | win.Hide ();
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Ribbons/PageAddedHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public delegate void PageAddedHandler(object Sender, PageEventArgs Args);
6 | }
7 |
--------------------------------------------------------------------------------
/Ribbons/PageEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public class PageEventArgs
6 | {
7 | private Ribbon.RibbonPage page;
8 |
9 | public Ribbon.RibbonPage Page
10 | {
11 | get { return this.page; }
12 | }
13 |
14 | public PageEventArgs (Ribbon.RibbonPage page)
15 | {
16 | this.page = page;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Ribbons/PageMovedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public class PageMovedEventArgs
6 | {
7 | private Ribbon.RibbonPage page;
8 |
9 | public Ribbon.RibbonPage page
10 | {
11 | get { return this.page; }
12 | }
13 |
14 | public PageMovedEventArgs (Ribbon.RibbonPage page)
15 | {
16 | this.page = page;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Ribbons/PageMovedHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public delegate void PageMovedHandler(object Sender, PageEventArgs Args);
6 | }
7 |
--------------------------------------------------------------------------------
/Ribbons/PageRemovedHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public delegate void PageRemovedHandler(object Sender, PageEventArgs Args);
6 | }
7 |
--------------------------------------------------------------------------------
/Ribbons/PageSelectedHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public delegate void PageSelectedHandler(object Sender, PageEventArgs Args);
6 | }
7 |
--------------------------------------------------------------------------------
/Ribbons/Position.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public enum Position
6 | {
7 | Top, Right, Bottom, Left
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Ribbons/QuickAccessToolbar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 | using Cairo;
5 |
6 | namespace Ribbons
7 | {
8 | ///
9 | /// Displays several widgets (typical shortcuts to common functionalities) next to the application button.
10 | ///
11 | public class QuickAccessToolbar : Container
12 | {
13 | private List widgets;
14 | private List keyTips;
15 | private int[] widths;
16 | private Theme theme = Theme.DefaultTheme;
17 |
18 | public QuickAccessToolbar()
19 | {
20 | // This is a No Window widget => it does not have its own Gdk Window => it can be transparent
21 | this.SetFlag (WidgetFlags.NoWindow);
22 |
23 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
24 |
25 | this.widgets = new List ();
26 | this.keyTips = new List ();
27 | }
28 |
29 | /// Adds a widget before all existing widgets.
30 | /// The widget to add.
31 | public void Prepend (Widget w)
32 | {
33 | Insert (w, 0);
34 | }
35 |
36 | /// Adds a widget after all existing widgets.
37 | /// The widget to add.
38 | public void Append (Widget w)
39 | {
40 | Insert (w, -1);
41 | }
42 |
43 | /// Inserts a widget at the specified location.
44 | /// The widget to add.
45 | /// The index (starting at 0) at which the widget must be inserted, or -1 to insert the widget after all existing widgets.
46 | public void Insert (Widget w, int WidgetIndex)
47 | {
48 | w.Parent = this;
49 | w.Visible = true;
50 |
51 | if(WidgetIndex == -1)
52 | widgets.Add (w);
53 | else
54 | widgets.Insert (WidgetIndex, w);
55 |
56 | ShowAll ();
57 | }
58 |
59 | /// Removes the widget at the specified index.
60 | /// Index of the widget to remove.
61 | public void Remove (int WidgetIndex)
62 | {
63 | if(WidgetIndex == -1) WidgetIndex = widgets.Count - 1;
64 |
65 | widgets[WidgetIndex].Parent = null;
66 | widgets.RemoveAt (WidgetIndex);
67 |
68 | ShowAll ();
69 | }
70 |
71 | public void AddKeyTip (KeyTip kt)
72 | {
73 | keyTips.Add (kt);
74 | }
75 |
76 | public void RemoveKeyTip (KeyTip kt)
77 | {
78 | keyTips.Remove (kt);
79 | }
80 |
81 | public void ClearKeyTips ()
82 | {
83 | keyTips.Clear ();
84 | }
85 |
86 | protected override void ForAll (bool include_internals, Callback callback)
87 | {
88 | foreach(Widget w in widgets)
89 | {
90 | if(w.Visible) callback (w);
91 | }
92 | }
93 |
94 | protected override void OnSizeRequested (ref Requisition requisition)
95 | {
96 | base.OnSizeRequested (ref requisition);
97 |
98 | if(widths == null || widths.Length != widgets.Count)
99 | {
100 | widths = new int[widgets.Count];
101 | }
102 |
103 | requisition.Height = 16;
104 | requisition.Width = 0;
105 |
106 | int i = 0;
107 | foreach(BaseButton b in widgets)
108 | {
109 | //b.HeightRequest = requisition.Height;
110 | Gtk.Requisition req = b.SizeRequest ();
111 | if(req.Height > requisition.Height) requisition.Height = req.Height;
112 | requisition.Width += req.Width;
113 | widths[i++] = req.Width;
114 | }
115 | if(HeightRequest != -1) requisition.Height = HeightRequest;
116 | if(WidthRequest != -1) requisition.Width = WidthRequest;
117 | }
118 |
119 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
120 | {
121 | base.OnSizeAllocated (allocation);
122 |
123 | int i = 0, x = allocation.X;
124 | foreach(BaseButton b in widgets)
125 | {
126 | Gdk.Rectangle r;
127 | r.X = x;
128 | r.Y = allocation.Y;
129 | r.Width = widths[i];
130 | r.Height = allocation.Height;
131 | b.SizeAllocate (r);
132 | x += r.Width;
133 | ++i;
134 | }
135 | }
136 |
137 | public void ShowKeyTips ()
138 | {
139 | int x, y;
140 | GdkWindow.GetOrigin (out x, out y);
141 | int lineY = y + Allocation.Y + (int)(0.66666 * Allocation.Height);
142 |
143 | foreach(KeyTip kt in keyTips)
144 | {
145 | Gdk.Rectangle alloc = kt.Target.Allocation;
146 | kt.ShowAt (x + alloc.X + (alloc.Width >> 1), lineY, 0.5, 0.0);
147 | }
148 | }
149 |
150 | public void HideKeyTips ()
151 | {
152 | foreach(KeyTip kt in keyTips)
153 | {
154 | kt.Hide ();
155 | }
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/Ribbons/Ribbon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Cairo;
4 | using Gtk;
5 |
6 | namespace Ribbons
7 | {
8 | /// Ribbon widget.
9 | public class Ribbon : Container
10 | {
11 | private enum KeyTipLevel { None, TopLevel, Tab };
12 |
13 | private static double borderWidth = 2.0;
14 | private static double space = 2.0;
15 | private static double pagePadding = 3.0;
16 | private static double tabPadding = 4.0;
17 | private static double minimalTabsHorizontalPosition = 8.0;
18 | private static double lineWidth = 1.0;
19 | private static double roundSize = 4.0;
20 |
21 | protected ColorScheme colorScheme = new ColorScheme ();
22 | protected Theme theme = Theme.DefaultTheme;
23 |
24 | protected List pages;
25 | protected int curPageIndex;
26 | protected ApplicationButton appButton;
27 | protected QuickAccessToolbar toolbar;
28 | protected Widget shortcuts;
29 | private Gdk.Rectangle bodyAllocation, pageAllocation;
30 |
31 | private Gtk.Requisition appButtonRequisition;
32 | private Gtk.Requisition toolbarRequisition;
33 | private Gtk.Requisition shortcutsRequisition;
34 | private Gtk.Requisition pageRequisition;
35 | private double headerHeight;
36 |
37 | private KeyTipLevel queuedKeyTipLevel = KeyTipLevel.None;
38 | private List tabKeyTips;
39 |
40 | public event PageSelectedHandler PageSelected;
41 | public event PageAddedHandler PageAdded;
42 | public event PageMovedHandler PageMoved;
43 | public event PageRemovedHandler PageRemoved;
44 |
45 | public ApplicationButton ApplicationButton
46 | {
47 | set
48 | {
49 | if(appButton != null) appButton.Unparent ();
50 | appButton = value;
51 | if(appButton != null)
52 | {
53 | appButton.Visible = true;
54 | appButton.Parent = this;
55 | }
56 | ShowAll ();
57 | }
58 | get
59 | {
60 | return appButton;
61 | }
62 | }
63 |
64 | public QuickAccessToolbar QuickAccessToolbar
65 | {
66 | set
67 | {
68 | if(toolbar != null) toolbar.Unparent ();
69 | toolbar = value;
70 | if(toolbar != null)
71 | {
72 | toolbar.Visible = true;
73 | toolbar.Parent = this;
74 | }
75 | ShowAll ();
76 | }
77 | get
78 | {
79 | return toolbar;
80 | }
81 | }
82 |
83 | /// Indix of the currently selected page.
84 | /// Returns -1 if no page is selected.
85 | public int CurrentPageIndex
86 | {
87 | set
88 | {
89 | if(curPageIndex != -1)
90 | {
91 | CurrentPage.Label.ModifyFg (StateType.Normal, theme.GetForecolorForRibbonTabs (false));
92 | CurrentPage.Page.Unparent ();
93 | }
94 | curPageIndex = value;
95 | if(curPageIndex != -1)
96 | {
97 | CurrentPage.Label.ModifyFg (StateType.Normal, theme.GetForecolorForRibbonTabs (true));
98 | CurrentPage.Page.Parent = this;
99 | }
100 |
101 | ShowAll ();
102 | QueueDraw ();
103 | }
104 | get
105 | {
106 | return curPageIndex;
107 | }
108 | }
109 |
110 | /// Currently selected page.
111 | public RibbonPage CurrentPage
112 | {
113 | get
114 | {
115 | int idx = curPageIndex;
116 | return idx == -1 ? null : pages[idx];
117 | }
118 | }
119 |
120 | /// Number of pages.
121 | public int NPages
122 | {
123 | get { return pages.Count; }
124 | }
125 |
126 | /// Shortcuts widget.
127 | /// The shortcuts widget is displayed next to the tabs.
128 | public Widget Shortcuts
129 | {
130 | set
131 | {
132 | if(shortcuts != null) shortcuts.Unparent ();
133 | shortcuts = value;
134 | if(shortcuts != null)
135 | {
136 | shortcuts.Visible = true;
137 | shortcuts.Parent = this;
138 | }
139 | QueueDraw ();
140 | }
141 | get { return shortcuts; }
142 | }
143 |
144 | /// Theme used to draw the widget.
145 | public Theme Theme
146 | {
147 | set
148 | {
149 | theme = value;
150 | QueueDraw ();
151 | }
152 | get { return theme; }
153 | }
154 |
155 | /// Default constructor.
156 | public Ribbon()
157 | {
158 | this.SetFlag (WidgetFlags.NoWindow);
159 |
160 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
161 |
162 | this.pages = new List ();
163 | this.tabKeyTips = new List ();
164 | this.curPageIndex = -1;
165 | }
166 |
167 | /// Adds a new page after all existing pages.
168 | /// The widget to use as the content of the page.
169 | /// The widget to use as the tab.
170 | public void AppendPage (Widget Child, Widget Label)
171 | {
172 | InsertPage (Child, Label, -1);
173 | }
174 |
175 | /// Adds a new page before all existing pages.
176 | /// The widget to use as the content of the page.
177 | /// The widget to use as the tab.
178 | public void PrependPage (Widget Child, Widget Label)
179 | {
180 | InsertPage (Child, Label, 0);
181 | }
182 |
183 | /// Adds a new page at the specified position.
184 | /// The widget to use as the content of the page.
185 | /// The widget to use as the tab.
186 | /// The index (starting at 0) at which the page must be inserted, or -1 to insert the page after all existing pages.
187 | public void InsertPage (Widget Child, Widget Label, int Position)
188 | {
189 | RibbonPage p = new RibbonPage (this, Child, Label);
190 |
191 | if(Position == -1)
192 | {
193 | pages.Add (p);
194 | }
195 | else
196 | {
197 | pages.Insert (Position, p);
198 |
199 | if(curPageIndex != -1)
200 | {
201 | if(Position <= curPageIndex)
202 | ++curPageIndex;
203 | }
204 | }
205 |
206 | if(pages.Count == 1)
207 | {
208 | CurrentPageIndex = 0;
209 | }
210 | else
211 | {
212 | Label.ModifyFg (StateType.Normal, theme.GetForecolorForRibbonTabs (false));
213 | }
214 |
215 | Label.ButtonPressEvent += delegate (object sender, ButtonPressEventArgs evnt)
216 | {
217 | this.SelectRibbonPage (p);
218 | };
219 |
220 | Label.EnterNotifyEvent += delegate (object sender, EnterNotifyEventArgs evnt)
221 | {
222 |
223 | };
224 |
225 | Label.LeaveNotifyEvent += delegate (object sender, LeaveNotifyEventArgs evnt)
226 | {
227 |
228 | };
229 |
230 | OnPageAdded (new PageEventArgs (p));
231 | for(int idx = Position + 1 ; idx < pages.Count ; ++idx)
232 | {
233 | OnPageSelected (new PageEventArgs (pages[idx]));
234 | }
235 | }
236 |
237 | /// Removes the specified page.
238 | /// Index of the page to remove.
239 | public void RemovePage (int PageNumber)
240 | {
241 | if(curPageIndex != -1)
242 | {
243 | if(PageNumber < curPageIndex)
244 | {
245 | --curPageIndex;
246 | }
247 | else if(PageNumber == curPageIndex)
248 | {
249 | curPageIndex = -1;
250 | }
251 | }
252 |
253 | RibbonPage p = pages[PageNumber];
254 | if(curPageIndex == -1)
255 | pages.RemoveAt (pages.Count - 1);
256 | else
257 | pages.RemoveAt (PageNumber);
258 |
259 | OnPageRemoved (new PageEventArgs (p));
260 | }
261 |
262 | /// Returns the index of the specified page given its content widget.
263 | /// The content of the page whose index must be returned.
264 | /// The index.
265 | public int PageNum (Widget Child)
266 | {
267 | // Since it is unlikely that the widget will containe more than
268 | // a dozen pages, it is just fine to do a linear search.
269 | for(int i = 0, i_up = pages.Count ; i < i_up ; ++i)
270 | if(pages[i].Page == Child)
271 | return i;
272 | return -1;
273 | }
274 |
275 | /// Returns the index of the specified page.
276 | /// The page whose index must be returned.
277 | /// The RibbonPage.
278 | public int RibbonPageNum (RibbonPage Page)
279 | {
280 | // Since it is unlikely that the widget will containe more than
281 | // a dozen pages, it is just fine to do a linear search.
282 | for(int i = 0, i_up = pages.Count ; i < i_up ; ++i)
283 | if(pages[i] == Page)
284 | return i;
285 | return -1;
286 | }
287 |
288 | /// Sets the label widget of the specified page.
289 | /// The content of the page whose label must be modified.
290 | /// The new label widget.
291 | public void SetPageLabel (Widget Child, Widget Label)
292 | {
293 | pages[PageNum (Child)].Label = Label;
294 | }
295 |
296 | /// Gets the label widget of the specified page.
297 | /// The content of the page whose label must be returned.
298 | /// The label widget.
299 | public Widget GetPageLabel (Widget Child)
300 | {
301 | return pages[PageNum (Child)].Label;
302 | }
303 |
304 | /// Returns the content widget of the n-th page.
305 | /// Index of the page whose content has to be returned.
306 | /// The n-th page.
307 | public Widget GetNthPage (int Position)
308 | {
309 | return pages[Position].Page;
310 | }
311 |
312 | /// Returns the n-th page.
313 | /// Index of the page to return.
314 | public RibbonPage GetNthRibbonPage (int Position)
315 | {
316 | return pages[Position];
317 | }
318 |
319 | /// Selects the specified page.
320 | /// The page to select.
321 | public void SelectRibbonPage (RibbonPage page)
322 | {
323 | int idx = RibbonPageNum (page);
324 | if(idx != -1) CurrentPageIndex = idx;
325 | OnPageSelected (new PageEventArgs (page));
326 | }
327 |
328 | /// Selects the previous page.
329 | public void PrevPage ()
330 | {
331 | int i = CurrentPageIndex;
332 | if(i > 0) CurrentPageIndex = i - 1;
333 | }
334 |
335 | /// Selects the next page.
336 | public void NextPage ()
337 | {
338 | int i = CurrentPageIndex;
339 | if(i < NPages - 1) CurrentPageIndex = i + 1;
340 | }
341 |
342 | public void AddTabKeyTip (KeyTip kt)
343 | {
344 | tabKeyTips.Add (kt);
345 | }
346 |
347 | public void RemoveTabKeyTip (KeyTip kt)
348 | {
349 | tabKeyTips.Remove (kt);
350 | }
351 |
352 | public void ClearTabKeyTips ()
353 | {
354 | tabKeyTips.Clear ();
355 | }
356 |
357 | protected override void ForAll (bool include_internals, Callback callback)
358 | {
359 | if(toolbar != null && toolbar.Visible)
360 | {
361 | callback (toolbar);
362 | }
363 |
364 | if(appButton != null && appButton.Visible)
365 | {
366 | callback (appButton);
367 | }
368 |
369 | if(Shortcuts != null && Shortcuts.Visible)
370 | {
371 | callback (Shortcuts);
372 | }
373 |
374 | foreach(RibbonPage p in pages) callback (p.Label);
375 |
376 | if(CurrentPage != null)
377 | {
378 | callback (CurrentPage.Page);
379 | }
380 | }
381 |
382 | protected override void OnSizeRequested (ref Requisition requisition)
383 | {
384 | base.OnSizeRequested (ref requisition);
385 | RibbonPage page = CurrentPage;
386 |
387 | double tabsWidth = 0, tabsHeight = 0;
388 | foreach(RibbonPage p in pages)
389 | {
390 | Gtk.Requisition req = p.Label.SizeRequest ();
391 | tabsWidth += req.Width;
392 | tabsHeight = Math.Max (tabsHeight, req.Height);
393 | p.LabelRequisition = req;
394 | }
395 | tabsWidth += pages.Count * 2 * tabPadding;
396 | tabsHeight += 2 * tabPadding;
397 |
398 | double headerWidth = tabsWidth;
399 |
400 | if(shortcuts != null && shortcuts.Visible)
401 | {
402 | shortcutsRequisition = shortcuts.SizeRequest ();
403 | double x = shortcutsRequisition.Width + space;
404 | headerWidth += Math.Max (x, minimalTabsHorizontalPosition);
405 | }
406 | else
407 | {
408 | shortcutsRequisition = new Gtk.Requisition ();
409 | headerWidth += minimalTabsHorizontalPosition;
410 | }
411 |
412 | headerHeight = Math.Max (tabsHeight, shortcutsRequisition.Height);
413 |
414 | bool showToolbar = toolbar != null && toolbar.Visible;
415 | bool showAppButton = appButton != null && appButton.Visible;
416 |
417 | if(showToolbar) toolbarRequisition = toolbar.SizeRequest ();
418 | if(showAppButton) appButtonRequisition = appButton.SizeRequest ();
419 |
420 | if(showToolbar)
421 | {
422 | headerHeight += 2 * space + toolbarRequisition.Height;
423 | }
424 |
425 | if(showAppButton)
426 | {
427 | headerHeight = Math.Max (headerHeight, space + appButtonRequisition.Height);
428 | }
429 |
430 | double pageWidth = 0, pageHeight = 0;
431 | if(page != null)
432 | {
433 | pageRequisition = page.Page.SizeRequest ();
434 | pageWidth = pageRequisition.Width + 2 * pagePadding;
435 | pageHeight = pageRequisition.Height + 2 * pagePadding;
436 | }
437 | else
438 | {
439 | pageRequisition = new Gtk.Requisition ();
440 | }
441 |
442 | double width = Math.Max (headerWidth, pageWidth);
443 | width = borderWidth + width + borderWidth;
444 | double height = borderWidth + headerHeight + pageHeight + borderWidth;
445 |
446 | requisition.Width = (int)Math.Ceiling (width - double.Epsilon);
447 | requisition.Height = (int)Math.Ceiling (height - double.Epsilon);
448 | }
449 |
450 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
451 | {
452 | base.OnSizeAllocated (allocation);
453 | RibbonPage page = CurrentPage;
454 |
455 | if(allocation.Height < headerHeight + borderWidth) return;
456 |
457 | double headerBottom = allocation.Y + borderWidth + headerHeight;
458 | double currentX = borderWidth;
459 |
460 | bool showToolbar = toolbar != null && toolbar.Visible;
461 | bool showAppButton = appButton != null && appButton.Visible;
462 |
463 | if(showAppButton)
464 | {
465 | Gdk.Rectangle alloc;
466 | alloc.X = (int)currentX;
467 | alloc.Y = (int)(allocation.Y + borderWidth);
468 | alloc.Width = Math.Min (appButtonRequisition.Width, (int)(allocation.Width - 2 * space));
469 | alloc.Height = appButtonRequisition.Height;
470 | appButton.SizeAllocate (alloc);
471 |
472 | currentX += alloc.Width + space;
473 | }
474 |
475 | if(showToolbar)
476 | {
477 | Gdk.Rectangle alloc;
478 | alloc.X = (int)currentX;
479 | alloc.Y = (int)(allocation.Y + space);
480 | alloc.Width = Math.Min (toolbarRequisition.Width, (int)(allocation.Width - (alloc.X - allocation.X) - space));
481 | alloc.Height = toolbarRequisition.Height;
482 | toolbar.SizeAllocate (alloc);
483 | }
484 |
485 | if(shortcuts != null && shortcuts.Visible)
486 | {
487 | Gdk.Rectangle alloc;
488 | alloc.X = (int)currentX;
489 | alloc.Y = (int)(headerBottom - shortcutsRequisition.Height);
490 | alloc.Width = shortcutsRequisition.Width;
491 | alloc.Height = shortcutsRequisition.Height;
492 | shortcuts.SizeAllocate (alloc);
493 | currentX += shortcutsRequisition.Width;
494 | }
495 | currentX += space;
496 | currentX = Math.Max (currentX, minimalTabsHorizontalPosition);
497 |
498 | foreach(RibbonPage p in pages)
499 | {
500 | Gdk.Rectangle alloc;
501 | alloc.X = (int)(currentX + tabPadding);
502 | alloc.Y = (int)(headerBottom - tabPadding - p.LabelRequisition.Height);
503 | alloc.Width = p.LabelRequisition.Width;
504 | alloc.Height = p.LabelRequisition.Height;
505 | p.Label.SizeAllocate (alloc);
506 |
507 | alloc.X = (int)currentX;
508 | alloc.Y = (int)(headerBottom - tabPadding - p.LabelRequisition.Height - tabPadding);
509 | alloc.Width = (int)(tabPadding + p.LabelRequisition.Width + tabPadding);
510 | alloc.Height = (int)(tabPadding + p.LabelRequisition.Height + tabPadding);
511 | p.SetLabelAllocation (alloc);
512 |
513 | currentX += p.LabelRequisition.Width + 2 * tabPadding;
514 | }
515 |
516 | bodyAllocation.X = allocation.X + (int)borderWidth;
517 | bodyAllocation.Y = (int)headerBottom;
518 | bodyAllocation.Width = allocation.Width - bodyAllocation.X - (int)borderWidth;
519 | bodyAllocation.Height = allocation.Height - bodyAllocation.Y - (int)borderWidth;
520 |
521 | if(page != null)
522 | {
523 | pageAllocation = bodyAllocation;
524 | int pad = (int)pagePadding;
525 | pageAllocation.Inflate (-pad, -pad);
526 | page.Page.SizeAllocate (pageAllocation);
527 | }
528 | else
529 | {
530 | pageAllocation = Gdk.Rectangle.Zero;
531 | }
532 | }
533 |
534 | public void ShowTopLevelKeyTips ()
535 | {
536 | queuedKeyTipLevel = KeyTipLevel.TopLevel;
537 |
538 | if(appButton != null) appButton.ShowKeyTips ();
539 | if(toolbar != null) toolbar.ShowKeyTips ();
540 |
541 | int x, y;
542 | GdkWindow.GetOrigin(out x, out y);
543 |
544 | int tabLineY = (int)(y + Allocation.Y + headerHeight);
545 | foreach(KeyTip kt in tabKeyTips)
546 | {
547 | kt.ShowAt (x + kt.Target.Allocation.X + (kt.Target.Allocation.Width >> 1), tabLineY, 0.5, 0.0);
548 | }
549 | }
550 |
551 | public void ShowTabLevelKeyTips ()
552 | {
553 | queuedKeyTipLevel = KeyTipLevel.Tab;
554 |
555 | }
556 |
557 | public void HideKeyTips ()
558 | {
559 | queuedKeyTipLevel = KeyTipLevel.None;
560 |
561 | if(appButton != null) appButton.HideKeyTips ();
562 | if(toolbar != null) toolbar.HideKeyTips ();
563 |
564 | foreach(KeyTip kt in tabKeyTips)
565 | {
566 | kt.Hide ();
567 | }
568 | }
569 |
570 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
571 | {
572 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
573 |
574 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
575 | cr.Clip ();
576 | Draw (cr);
577 |
578 | ((IDisposable)cr.Target).Dispose ();
579 | ((IDisposable)cr).Dispose ();
580 |
581 | return base.OnExposeEvent (evnt);
582 | }
583 |
584 | protected void Draw (Context cr)
585 | {
586 | bool showToolbar = toolbar != null && toolbar.Visible;
587 |
588 | Gdk.Rectangle menuBarAllocation;
589 | menuBarAllocation.X = Allocation.X;
590 | menuBarAllocation.Y = Allocation.Y;
591 | menuBarAllocation.Width = Allocation.Width;
592 |
593 | if(showToolbar)
594 | menuBarAllocation.Height = (int)(toolbar.Allocation.Height + 2 * space);
595 | else
596 | menuBarAllocation.Height = 0;
597 |
598 | theme.DrawRibbon (cr, menuBarAllocation, bodyAllocation, roundSize, lineWidth, this);
599 | }
600 |
601 | protected virtual void OnPageSelected (PageEventArgs args)
602 | {
603 | if(PageSelected != null) PageSelected (this, args);
604 | }
605 |
606 | protected virtual void OnPageAdded (PageEventArgs args)
607 | {
608 | if(PageAdded != null) PageAdded (this, args);
609 | }
610 |
611 | protected virtual void OnPageMoved (PageEventArgs args)
612 | {
613 | if(PageMoved != null) PageMoved (this, args);
614 | }
615 |
616 | protected virtual void OnPageRemoved (PageEventArgs args)
617 | {
618 | if(PageRemoved != null) PageRemoved (this, args);
619 | }
620 |
621 | /// Ribbon page.
622 | public class RibbonPage
623 | {
624 | private Ribbon parent;
625 | private Widget label, page;
626 | private Requisition labelReq;
627 | private Gdk.Rectangle labelAlloc;
628 | private List tabKeyTips;
629 |
630 | /// Label widget of the page.
631 | public Widget Label
632 | {
633 | set
634 | {
635 | if(label != null) label.Unparent ();
636 | label = value;
637 | if(label != null) label.Parent = parent;
638 | }
639 | get { return label; }
640 | }
641 |
642 | /// Widget used as the content of the page.
643 | public Widget Page
644 | {
645 | set { page = value; }
646 | get { return page; }
647 | }
648 |
649 | internal Requisition LabelRequisition
650 | {
651 | set { labelReq = value; }
652 | get { return labelReq; }
653 | }
654 |
655 | public Gdk.Rectangle LabelAllocation
656 | {
657 | get { return labelAlloc; }
658 | }
659 |
660 | public RibbonPage (Ribbon Parent, Widget Page, Widget Label)
661 | {
662 | this.parent = Parent;
663 | this.Label = Label;
664 | this.Page = Page;
665 | this.tabKeyTips = new List ();
666 | }
667 |
668 | public void SetLabelAllocation (Gdk.Rectangle r)
669 | {
670 | labelAlloc = r;
671 | }
672 | }
673 | }
674 | }
675 |
--------------------------------------------------------------------------------
/Ribbons/RibbonGroup.cs:
--------------------------------------------------------------------------------
1 | using Cairo;
2 | using Gtk;
3 | using System;
4 |
5 | namespace Ribbons
6 | {
7 | /// Ribbon group.
8 | public class RibbonGroup : Bin
9 | {
10 | protected Theme theme = Theme.DefaultTheme;
11 | protected string lbl;
12 | protected Pango.Layout lbl_layout;
13 | protected Button expandButton;
14 | protected EventHandler expandHandler;
15 |
16 | private double barHeight, barWidth;
17 |
18 | protected double childPadding = 1.0;
19 | protected double lineWidth = 1.0;
20 | protected double space = 2.0;
21 | protected Position labelPosition = Position.Bottom;
22 |
23 | /// Displayed label.
24 | public string Label
25 | {
26 | set
27 | {
28 | lbl = value;
29 |
30 | if(lbl == null)
31 | lbl_layout = null;
32 | else if(lbl_layout == null)
33 | lbl_layout = CreatePangoLayout (this.lbl);
34 | else
35 | lbl_layout.SetText (lbl);
36 |
37 | QueueDraw ();
38 | }
39 | get { return lbl; }
40 | }
41 |
42 | /// Expand event.
43 | /// Fired whenever the expand button is clicked.
44 | [GLib.Signal("expanded")]
45 | public event EventHandler Expand
46 | {
47 | add
48 | {
49 | expandHandler += value;
50 | expandButton.Visible = expandHandler != null;
51 | }
52 | remove
53 | {
54 | expandHandler -= value;
55 | expandButton.Visible = expandHandler != null;
56 | }
57 | }
58 |
59 | /// Theme used to draw the widget.
60 | public Theme Theme
61 | {
62 | set
63 | {
64 | theme = value;
65 | QueueDraw ();
66 | }
67 | get { return theme; }
68 | }
69 |
70 | /// Position of the label.
71 | public Position LabelPosition
72 | {
73 | set
74 | {
75 | labelPosition = value;
76 | QueueDraw ();
77 | }
78 | get { return labelPosition; }
79 | }
80 |
81 | /// Default constructor.
82 | public RibbonGroup ()
83 | {
84 | // This is a No Window widget => it does not have its own Gdk Window => it can be transparent
85 | this.SetFlag (WidgetFlags.NoWindow);
86 |
87 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
88 |
89 | Label = null;
90 | HeightRequest = 92;
91 |
92 | expandButton = new Button ("\u21F2");
93 | expandButton.Padding = 0;
94 | expandButton.Visible = false;
95 | expandButton.Parent = this;
96 | expandButton.Clicked += delegate (object Sender, EventArgs e)
97 | {
98 | OnExpand (e);
99 | };
100 | }
101 |
102 | public override void Dispose ()
103 | {
104 | base.Dispose ();
105 | if(lbl_layout != null) lbl_layout.Dispose ();
106 | }
107 |
108 | protected virtual void OnExpand (EventArgs e)
109 | {
110 | if(expandHandler != null) expandHandler (this, e);
111 | }
112 |
113 | protected override void ForAll (bool include_internals, Callback callback)
114 | {
115 | base.ForAll (include_internals, callback);
116 | if(expandButton != null && expandButton.Visible) callback (expandButton);
117 | }
118 |
119 | protected override void OnSizeRequested (ref Requisition requisition)
120 | {
121 | base.OnSizeRequested (ref requisition);
122 |
123 | int lw, lh;
124 |
125 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
126 | lbl_layout.GetPixelSize (out lw, out lh);
127 | else
128 | lbl_layout.GetPixelSize (out lh, out lw);
129 |
130 | double frameSize = 2*lineWidth + childPadding;
131 |
132 | barHeight = lh + 2 * space;
133 | barWidth = lw + 2 * space;
134 |
135 | if(expandButton != null && expandButton.Visible)
136 | {
137 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
138 | expandButton.SetSizeRequest (lh, lh);
139 | else
140 | expandButton.SetSizeRequest (lw, lw);
141 |
142 | expandButton.SizeRequest ();
143 |
144 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
145 | barWidth += expandButton.WidthRequest + (int)space;
146 | else
147 | barHeight += expandButton.HeightRequest + (int)space;
148 | }
149 |
150 | Requisition childRequisition = new Requisition ();
151 |
152 | if(Child != null && Child.Visible)
153 | {
154 | if(HeightRequest != -1)
155 | {
156 | int left = HeightRequest;
157 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
158 | left -= (int)(2 * frameSize + barHeight);
159 | else
160 | left -= (int)(2 * frameSize);
161 |
162 | Child.HeightRequest = left;
163 | }
164 | if(WidthRequest != -1)
165 | {
166 | int left = WidthRequest;
167 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
168 | left -= (int)(2 * frameSize);
169 | else
170 | left -= (int)(2 * frameSize + barWidth);
171 |
172 | Child.WidthRequest = left;
173 | }
174 | childRequisition = Child.SizeRequest ();
175 | }
176 |
177 | if(WidthRequest == -1)
178 | {
179 | if(Child != null && Child.Visible)
180 | {
181 | requisition.Width = childRequisition.Width + (int)(2 * frameSize);
182 |
183 | if(labelPosition == Position.Left || labelPosition == Position.Right)
184 | requisition.Width += (int)barWidth;
185 | }
186 | else
187 | {
188 | requisition.Width = (int)(2 * frameSize + barWidth);
189 | }
190 | }
191 |
192 | if(HeightRequest == -1)
193 | {
194 | if(Child != null && Child.Visible)
195 | {
196 | requisition.Height = childRequisition.Height + (int)(2 * frameSize);
197 |
198 | if(labelPosition == Position.Top || labelPosition == Position.Bottom)
199 | requisition.Height += (int)barHeight;
200 | }
201 | else
202 | {
203 | requisition.Height = (int)(2 * frameSize + barHeight);
204 | }
205 | }
206 | }
207 |
208 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
209 | {
210 | base.OnSizeAllocated (allocation);
211 |
212 | if(expandButton != null && expandButton.Visible)
213 | {
214 | double frameSize = 2*lineWidth + space;
215 | Gdk.Rectangle r;
216 | r.Height = expandButton.HeightRequest;
217 | r.Width = expandButton.WidthRequest;
218 |
219 | if(labelPosition == Position.Left)
220 | r.X = allocation.X + (int)frameSize;
221 | else
222 | r.X = allocation.X + allocation.Width - r.Width - (int)frameSize;
223 |
224 | if(labelPosition == Position.Top)
225 | r.Y = allocation.Y + (int)frameSize;
226 | else
227 | r.Y = allocation.Y + allocation.Height - r.Height - (int)frameSize;
228 |
229 | expandButton.SizeAllocate (r);
230 | }
231 |
232 | if(Child != null && Child.Visible)
233 | {
234 | double frameSize = 2*lineWidth + childPadding;
235 | int wi = allocation.Width - (int)(2 * frameSize);
236 | int he = allocation.Height - (int)(2 * frameSize);
237 |
238 | Gdk.Rectangle r = new Gdk.Rectangle (allocation.X + (int)frameSize, allocation.Y + (int)frameSize, wi, he);
239 |
240 | if(labelPosition == Position.Top)
241 | r.Y += (int)barHeight;
242 | else if(labelPosition == Position.Left)
243 | r.X += (int)barWidth;
244 |
245 | if(labelPosition == Position.Top || LabelPosition == Position.Bottom)
246 | r.Height -= (int)barHeight;
247 | else
248 | r.Width -= (int)barWidth;
249 |
250 | Child.SizeAllocate (r);
251 | }
252 | }
253 |
254 | protected void Draw (Context cr)
255 | {
256 | Rectangle rect = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
257 | theme.DrawGroup (cr, rect, 4.0, lineWidth, space, lbl_layout, expandButton, this);
258 | }
259 |
260 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
261 | {
262 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
263 |
264 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
265 | cr.Clip ();
266 | Draw (cr);
267 |
268 | ((IDisposable)cr.Target).Dispose ();
269 | ((IDisposable)cr).Dispose ();
270 |
271 | return base.OnExposeEvent (evnt);
272 | }
273 | }
274 | }
--------------------------------------------------------------------------------
/Ribbons/Ribbons.mdp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | Ribbons.RibbonButton
66 | Ribbons.Label
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Ribbons/SyntheticEventCrossing.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using Gdk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Managed EventCrossing implementation.
8 | [StructLayout(LayoutKind.Sequential)]
9 | internal struct SyntheticEventCrossing
10 | {
11 | [MarshalAs(UnmanagedType.SysInt)]
12 | private int type; // GdkEventType
13 | private IntPtr window; // GdkWindow
14 | private byte send_event;
15 | private IntPtr subwindow; // GdkWindow
16 | private UInt32 time;
17 | private double x;
18 | private double y;
19 | private double root_x;
20 | private double root_y;
21 | [MarshalAs(UnmanagedType.SysInt)]
22 | private int mode; // GdkCrossingMode
23 | [MarshalAs(UnmanagedType.SysInt)]
24 | private int detail; // GdkNotifyType
25 | [MarshalAs(UnmanagedType.SysInt)]
26 | private int focus; // gboolean
27 | [MarshalAs(UnmanagedType.SysUInt)]
28 | private uint state;
29 |
30 | public EventType Type
31 | {
32 | set { type = (int)value; }
33 | get { return (EventType)type; }
34 | }
35 |
36 | public Window Window
37 | {
38 | set { window = value == null ? IntPtr.Zero : value.Handle; }
39 | get { return window == IntPtr.Zero ? null : new Window (window); }
40 | }
41 |
42 | public bool SendEvent
43 | {
44 | set { send_event = value ? (byte)1 : (byte)0; }
45 | get { return send_event != 0; }
46 | }
47 |
48 | public Window Subwindow
49 | {
50 | set { subwindow = value == null ? IntPtr.Zero : value.Handle; }
51 | get { return subwindow == IntPtr.Zero ? null : new Window (subwindow); }
52 | }
53 |
54 | public UInt32 Time
55 | {
56 | set { time = value; }
57 | get { return time; }
58 | }
59 |
60 | public double X
61 | {
62 | set { x = value; }
63 | get { return x; }
64 | }
65 |
66 | public double Y
67 | {
68 | set { y = value; }
69 | get { return y; }
70 | }
71 |
72 | public double XRoot
73 | {
74 | set { root_x = value; }
75 | get { return root_x; }
76 | }
77 |
78 | public double YRoot
79 | {
80 | set { root_y = value; }
81 | get { return root_y; }
82 | }
83 |
84 | public CrossingMode Mode
85 | {
86 | set { mode = (int)value; }
87 | get { return (CrossingMode)mode; }
88 | }
89 |
90 | public NotifyType Detail
91 | {
92 | set { detail = (int)value; }
93 | get { return (NotifyType)detail; }
94 | }
95 |
96 | public bool Focus
97 | {
98 | set { focus = value ? 1 : 0; }
99 | get { return focus != 0; }
100 | }
101 |
102 | public ModifierType State
103 | {
104 | set { state = (uint)value; }
105 | get { return (ModifierType)state; }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Ribbons/SyntheticWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gdk;
4 | using Gtk;
5 |
6 | namespace Ribbons
7 | {
8 | /// Window generating synthetic events to window-less widgets.
9 | public class SyntheticWindow : Gtk.Window
10 | {
11 | private List lastHoveredWidgets;
12 |
13 | public SyntheticWindow (Gtk.WindowType type) : base (type)
14 | {
15 | lastHoveredWidgets = new List ();
16 | }
17 |
18 | protected override bool OnWidgetEvent (Gdk.Event evnt)
19 | {
20 | // This method is hooked to block the event as soon as possible if required
21 |
22 | if(evnt.Window.Equals (this.GdkWindow))
23 | {
24 | switch(evnt.Type)
25 | {
26 | case Gdk.EventType.ButtonPress:
27 | case Gdk.EventType.ButtonRelease:
28 | case Gdk.EventType.ThreeButtonPress:
29 | case Gdk.EventType.TwoButtonPress:
30 | Gdk.EventButton eb = new Gdk.EventButton (evnt.Handle);
31 | return PropagateEventGivenCoordinate (evnt, eb.X, eb.XRoot, eb.Y, eb.YRoot);
32 |
33 | case Gdk.EventType.MotionNotify:
34 | Gdk.EventMotion em = new Gdk.EventMotion (evnt.Handle);
35 | return PropagateEventGivenCoordinate (evnt, em.X, em.XRoot, em.Y, em.YRoot);
36 |
37 | case Gdk.EventType.LeaveNotify:
38 | foreach(Widget w in lastHoveredWidgets)
39 | {
40 | w.ProcessEvent (evnt);
41 | }
42 | lastHoveredWidgets.Clear();
43 | return base.OnWidgetEvent (evnt);
44 | }
45 | }
46 | return base.OnWidgetEvent (evnt);
47 | }
48 |
49 | private bool PropagateEventGivenCoordinate (Gdk.Event evnt, double X, double XRoot, double Y, double YRoot)
50 | {
51 | int x = (int)X, y = (int)Y;
52 | Container current = this; // Current container containing the coordinate
53 | Widget match = this; // Current match for the position
54 | int matchedPos = 0; // Current position in lastHoveredWidgets
55 |
56 | while(matchedPos < lastHoveredWidgets.Count)
57 | {
58 | Widget candidate = lastHoveredWidgets[matchedPos];
59 | if(candidate.Parent == current) // Is it still a child of the current container ?
60 | {
61 | Gdk.Rectangle alloc = candidate.Allocation;
62 | if(!alloc.Contains (x, y)) // Does it contain the coordinate ?
63 | {
64 | break;
65 | }
66 | }
67 | current = candidate as Container;
68 | match = candidate;
69 | ++matchedPos;
70 | }
71 |
72 | if(matchedPos < lastHoveredWidgets.Count) // Not all widgets match
73 | {
74 | // Send a leave notify
75 | SendSyntheticEvent (EventType.LeaveNotify, evnt, X, XRoot, Y, YRoot, lastHoveredWidgets, matchedPos);
76 |
77 | // Remove them
78 | lastHoveredWidgets.RemoveRange (matchedPos, lastHoveredWidgets.Count - matchedPos);
79 | }
80 |
81 | while (current != null)
82 | {
83 | Container next = null;
84 | foreach(Widget child in current.Children)
85 | {
86 | if(child.IsNoWindow)
87 | {
88 | Gdk.Rectangle alloc = child.Allocation;
89 | if(alloc.Contains (x, y))
90 | {
91 | lastHoveredWidgets.Add (child);
92 | match = child;
93 | next = child as Container;
94 | break;
95 | }
96 | }
97 | }
98 | current = next;
99 | }
100 |
101 | if(matchedPos < lastHoveredWidgets.Count) // New widgets have been found
102 | {
103 | // Send an enter notify
104 | SendSyntheticEvent (EventType.EnterNotify, evnt, X, XRoot, Y, YRoot, lastHoveredWidgets, matchedPos);
105 | }
106 |
107 | if(match == this) // No widget found, the window keeps the event
108 | {
109 | return base.OnWidgetEvent (evnt);
110 | }
111 | else // A widget has been found, let's send it the event
112 | {
113 | match.ProcessEvent (evnt);
114 | return true;
115 | }
116 | }
117 |
118 | private void SendSyntheticEvent (EventType Type, Event OriginalEvent, double X, double XRoot, double Y, double YRoot, IList Widgets, int Index)
119 | {
120 | SyntheticEventCrossing se = new SyntheticEventCrossing();
121 | se.Detail = NotifyType.Ancestor;
122 | se.Focus = false;
123 | se.Mode = CrossingMode.Normal;
124 | se.SendEvent = false;
125 | se.State = ModifierType.None;
126 | se.Subwindow = null;
127 | //se.Time = DateTime.Now.Ticks / 10000; // TODO: the real value shoud be the uptime I think
128 | se.Time = 0;
129 | se.Type = Type;
130 | se.Window = OriginalEvent.Window;
131 | se.X = X;
132 | se.XRoot = XRoot;
133 | se.Y = Y;
134 | se.YRoot = YRoot;
135 |
136 | unsafe
137 | {
138 | Event managedEvent = new Event(new IntPtr(&se));
139 |
140 | for(int i = Index ; i < Widgets.Count ; ++i)
141 | {
142 | Widgets[i].ProcessEvent (managedEvent);
143 | }
144 | }
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Ribbons/Tile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// The Tile widget.
8 | public abstract class Tile : Widget
9 | {
10 | protected Theme theme = new Theme ();
11 | private bool selected;
12 | private uint borderWidth;
13 |
14 | /// Gets or sets the width of the border.
15 | public uint BorderWidth
16 | {
17 | set
18 | {
19 | borderWidth = value;
20 | QueueDraw ();
21 | }
22 | get { return borderWidth; }
23 | }
24 |
25 | /// Gets or sets the state of the Tile.
26 | public bool Selected
27 | {
28 | set
29 | {
30 | selected = value;
31 | QueueDraw ();
32 | }
33 | get { return selected; }
34 | }
35 |
36 | /// Fired when the Tile has been clicked.
37 | public event EventHandler Clicked;
38 |
39 | /// Theme used to draw the widget.
40 | public Theme Theme
41 | {
42 | set
43 | {
44 | theme = value;
45 | QueueDraw ();
46 | }
47 | get { return theme; }
48 | }
49 |
50 | /// Default constructor.
51 | public Tile ()
52 | {
53 | this.SetFlag (WidgetFlags.NoWindow);
54 |
55 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
56 |
57 | this.selected = false;
58 | this.BorderWidth = 4;
59 | }
60 |
61 | /// Creates a carbon copy of the current Tile.
62 | public abstract Tile Copy ();
63 |
64 | /// Fires the Click event.
65 | public void Click ()
66 | {
67 | if(Clicked != null) Clicked (this, EventArgs.Empty);
68 | }
69 |
70 | protected override void OnSizeRequested (ref Requisition requisition)
71 | {
72 | base.OnSizeRequested (ref requisition);
73 | }
74 |
75 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
76 | {
77 | base.OnSizeAllocated (allocation);
78 | }
79 |
80 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
81 | {
82 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
83 |
84 | Cairo.Rectangle area = new Cairo.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
85 | Cairo.Rectangle allocation = new Cairo.Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
86 | Cairo.Rectangle contentArea = new Cairo.Rectangle (allocation.X + BorderWidth, allocation.Y + BorderWidth, allocation.Width - 2 * BorderWidth, allocation.Height - 2 * BorderWidth);
87 |
88 | cr.Rectangle (area);
89 | cr.Clip ();
90 | theme.DrawTile (cr, allocation, contentArea, this);
91 |
92 | DrawContent (cr, contentArea);
93 |
94 | ((IDisposable)cr.Target).Dispose ();
95 | ((IDisposable)cr).Dispose ();
96 |
97 | return base.OnExposeEvent (evnt);
98 | }
99 |
100 | ///
101 | /// Draws the content of the tile.
102 | ///
103 | /// Cairo context to be used to draw the content.
104 | /// Area that can be painted.
105 | public abstract void DrawContent (Cairo.Context Context, Cairo.Rectangle Area);
106 |
107 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
108 | {
109 | bool ret = base.OnButtonPressEvent (evnt);
110 |
111 | this.QueueDraw ();
112 | return ret;
113 | }
114 |
115 | protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
116 | {
117 | bool ret = base.OnButtonReleaseEvent (evnt);
118 | Click ();
119 | this.QueueDraw ();
120 | return ret;
121 | }
122 |
123 | protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
124 | {
125 | bool ret = base.OnEnterNotifyEvent (evnt);
126 |
127 | this.QueueDraw ();
128 | return ret;
129 | }
130 |
131 | protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
132 | {
133 | bool ret = base.OnLeaveNotifyEvent (evnt);
134 |
135 | this.QueueDraw ();
136 | return ret;
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/Ribbons/TileSelectedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public class TileSelectedEventArgs
6 | {
7 | private Tile selTile;
8 |
9 | /// The tile that has been selected.
10 | public Tile SelectedTile
11 | {
12 | get { return selTile; }
13 | }
14 |
15 | public TileSelectedEventArgs (Tile SelectedTile)
16 | {
17 | selTile = SelectedTile;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Ribbons/TileSelectedHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Ribbons
4 | {
5 | public delegate void TileSelectedHandler(object Sender, TileSelectedEventArgs e);
6 | }
7 |
--------------------------------------------------------------------------------
/Ribbons/ToggleButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// Toggle button to be used in Ribbons.
8 | public class ToggleButton : BaseButton
9 | {
10 | private bool value;
11 | private bool displayArrow;
12 |
13 | protected const double lineWidth = 1.0;
14 | protected const double arrowPadding = 2.0;
15 | protected const double arrowSize = 8.0;
16 |
17 | public event EventHandler ValueChanged;
18 |
19 | public bool Value
20 | {
21 | set
22 | {
23 | if(this.value != value)
24 | {
25 | this.value = value;
26 | OnValueChanged ();
27 | QueueDraw ();
28 | }
29 | }
30 | get { return value; }
31 | }
32 |
33 | public bool DisplayArrow
34 | {
35 | set
36 | {
37 | if(this.displayArrow != value)
38 | {
39 | this.displayArrow = value;
40 | OnValueChanged ();
41 | QueueDraw ();
42 | }
43 | }
44 | get { return displayArrow; }
45 | }
46 |
47 | /// Default constructor.
48 | public ToggleButton ()
49 | {
50 | this.SetFlag (WidgetFlags.NoWindow);
51 |
52 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
53 |
54 | this.Padding = 2;
55 | this.ImagePosition = PositionType.Top;
56 | this.isSmall = false;
57 | this.enable = true;
58 | this.value = false;
59 | }
60 |
61 | /// Constructor given a label to display.
62 | /// Label to display.
63 | public ToggleButton (string Label) : this ()
64 | {
65 | this.Label = Label;
66 | }
67 |
68 | /// Constructor given an image to display.
69 | /// Image to display
70 | public ToggleButton (Image Image) : this ()
71 | {
72 | this.Image = Image;
73 | }
74 |
75 | /// Constructor given a label and an image to display.
76 | /// Image to display.
77 | /// Label to display.
78 | public ToggleButton (Image Image, string Label) : this ()
79 | {
80 | this.Image = Image;
81 | this.Label = Label;
82 | }
83 |
84 | /// Constructs a Button from a stock.
85 | /// Name of the stock.
86 | /// true if the image should be large, false otherwise.
87 | public static ToggleButton FromStockIcon (string Name, bool Large)
88 | {
89 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
90 | ToggleButton btn = new ToggleButton (img);
91 | if(!Large) btn.ImagePosition = PositionType.Left;
92 | return btn;
93 | }
94 |
95 | /// Constructs a Button from a stock.
96 | /// Name of the stock.
97 | /// Label to display.
98 | /// true if the image should be large, false otherwise.
99 | public static ToggleButton FromStockIcon (string Name, string Label, bool Large)
100 | {
101 | Image img = new Image (Name, Large ? IconSize.LargeToolbar : IconSize.SmallToolbar);
102 | ToggleButton btn = new ToggleButton (img, Label);
103 | if(!Large) btn.ImagePosition = PositionType.Left;
104 | return btn;
105 | }
106 |
107 | protected override void BindedWidget_ButtonPressEvent (object sender, ButtonPressEventArgs evnt)
108 | {
109 | ProcessEvent (evnt.Event);
110 | }
111 |
112 | protected override void BindedWidget_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs evnt)
113 | {
114 | ProcessEvent (evnt.Event);
115 | Value = !Value;
116 | }
117 |
118 | protected override void OnSizeRequested (ref Requisition requisition)
119 | {
120 | base.OnSizeRequested (ref requisition);
121 |
122 | Requisition childRequisition = new Requisition ();
123 | if(Child != null && Child.Visible)
124 | {
125 | childRequisition = Child.SizeRequest ();
126 | }
127 |
128 | if(displayArrow)
129 | {
130 | int arrowSpace = (int)(arrowSize + 2 * (lineWidth + arrowPadding));
131 |
132 | if(imgPos == PositionType.Top || imgPos == PositionType.Bottom)
133 | {
134 | childRequisition.Height += arrowSpace;
135 | }
136 | else
137 | {
138 | childRequisition.Width += arrowSpace;
139 | }
140 | }
141 |
142 | if(HeightRequest == -1)
143 | {
144 | requisition.Height = childRequisition.Height + (int)(lineWidth * 4 + padding * 2);
145 | }
146 | if(WidthRequest == -1)
147 | {
148 | requisition.Width = childRequisition.Width + (int)(lineWidth * 4 + padding * 2);
149 | }
150 | }
151 |
152 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
153 | {
154 | base.OnSizeAllocated (allocation);
155 |
156 | allocation.X += (int)(lineWidth * 2 + padding);
157 | allocation.Y += (int)(lineWidth * 2 + padding);
158 | allocation.Height -= (int)(lineWidth * 4 + padding * 2);
159 | allocation.Width -= (int)(lineWidth * 4 + padding * 2);
160 |
161 | if(displayArrow)
162 | {
163 | int arrowSpace = (int)(arrowSize + 2 * (lineWidth + arrowPadding));
164 |
165 | if(imgPos == PositionType.Top || imgPos == PositionType.Bottom)
166 | {
167 | allocation.Height -= arrowSpace;
168 | }
169 | else
170 | {
171 | allocation.Width -= arrowSpace;
172 | }
173 | }
174 |
175 | if(allocation.Height < 0) allocation.Height = 0;
176 | if(allocation.Width < 0) allocation.Width = 0;
177 |
178 | if(Child != null && Child.Visible)
179 | {
180 | Child.SizeAllocate (allocation);
181 | }
182 | }
183 |
184 | protected override bool OnExposeEvent (Gdk.EventExpose evnt)
185 | {
186 | Context cr = Gdk.CairoHelper.Create (this.GdkWindow);
187 |
188 | cr.Rectangle (evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
189 | cr.Clip ();
190 | Draw (cr);
191 |
192 | ((IDisposable)cr.Target).Dispose ();
193 | ((IDisposable)cr).Dispose ();
194 |
195 | return base.OnExposeEvent (evnt);
196 | }
197 |
198 | protected void Draw (Context cr)
199 | {
200 | Rectangle rect = new Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
201 | double roundSize = isSmall ? 2.0 : 3.0;
202 | Theme.ButtonState s = this.state;
203 | if(this.value) s = Theme.ButtonState.Pressed;
204 | theme.DrawButton (cr, rect, s, roundSize, lineWidth, displayArrow ? arrowSize : 0, arrowPadding, false, this);
205 | }
206 |
207 | protected virtual void OnValueChanged ()
208 | {
209 | if(ValueChanged != null) ValueChanged (this, EventArgs.Empty);
210 | }
211 |
212 | protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
213 | {
214 | bool ret = base.OnButtonPressEvent (evnt);
215 | state = Theme.ButtonState.Pressed;
216 | if(!enable) state = Theme.ButtonState.Default;
217 | this.QueueDraw ();
218 | return ret;
219 | }
220 |
221 | protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
222 | {
223 | bool ret = base.OnButtonReleaseEvent (evnt);
224 | state = Theme.ButtonState.Hover;
225 | if(!enable) state = Theme.ButtonState.Default;
226 | this.QueueDraw ();
227 | return ret;
228 | }
229 |
230 | protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
231 | {
232 | bool ret = base.OnEnterNotifyEvent (evnt);
233 | state = Theme.ButtonState.Hover;
234 | if(!enable) state = Theme.ButtonState.Default;
235 | this.QueueDraw ();
236 | return ret;
237 | }
238 |
239 | protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing evnt)
240 | {
241 | bool ret = base.OnLeaveNotifyEvent (evnt);
242 | state = Theme.ButtonState.Default;
243 | this.QueueDraw ();
244 | return ret;
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/Ribbons/ToolBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | /// ToolBox containing several widgets displayed in rows.
8 | public class ToolBox : Container
9 | {
10 | private List widgets;
11 | private Gtk.Requisition[] requisitions;
12 | private int spacing;
13 |
14 | /// Gets or sets the spacing between children.
15 | public int Spacing
16 | {
17 | set
18 | {
19 | spacing = value;
20 | QueueDraw ();
21 | }
22 | get { return spacing; }
23 | }
24 |
25 | /// Default constructor.
26 | public ToolBox ()
27 | {
28 | this.widgets = new List ();
29 |
30 | this.SetFlag (WidgetFlags.NoWindow);
31 |
32 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
33 |
34 | spacing = 2;
35 | }
36 |
37 | /// Adds a widget before all existing widgets.
38 | /// The widget to add.
39 | public void Prepend (Widget w)
40 | {
41 | Insert (w, 0);
42 | }
43 |
44 | /// Adds a widget after all existing widgets.
45 | /// The widget to add.
46 | public void Append (Widget w)
47 | {
48 | Insert (w, -1);
49 | }
50 |
51 | /// Inserts a widget at the specified location.
52 | /// The widget to add.
53 | /// The index (starting at 0) at which the widget must be inserted, or -1 to insert the widget after all existing widgets.
54 | public void Insert (Widget w, int WidgetIndex)
55 | {
56 | w.Parent = this;
57 | w.Visible = true;
58 |
59 | if(WidgetIndex == -1)
60 | widgets.Add (w);
61 | else
62 | widgets.Insert (WidgetIndex, w);
63 |
64 | ShowAll ();
65 | }
66 |
67 | /// Removes the widget at the specified index.
68 | /// Index of the widget to remove.
69 | public void Remove (int WidgetIndex)
70 | {
71 | widgets[WidgetIndex].Parent = null;
72 |
73 | if(WidgetIndex == -1)
74 | widgets.RemoveAt (widgets.Count - 1);
75 | else
76 | widgets.RemoveAt (WidgetIndex);
77 |
78 | ShowAll ();
79 | }
80 |
81 | protected override void ForAll (bool include_internals, Callback callback)
82 | {
83 | foreach(Widget w in widgets)
84 | {
85 | if(w.Visible) callback (w);
86 | }
87 | }
88 |
89 | protected override void OnSizeRequested (ref Requisition requisition)
90 | {
91 | base.OnSizeRequested (ref requisition);
92 |
93 | if(requisitions == null || requisitions.Length != widgets.Count)
94 | {
95 | requisitions = new Gtk.Requisition[widgets.Count];
96 | }
97 |
98 | int totalWidth = 0, rowHeight = 0;
99 | foreach(Widget w in widgets)
100 | {
101 | if(w.Visible)
102 | {
103 | rowHeight = Math.Max (rowHeight, w.SizeRequest ().Height);
104 | }
105 | }
106 |
107 | int i = 0;
108 | foreach(Widget w in widgets)
109 | {
110 | if(w.Visible)
111 | {
112 | w.HeightRequest = rowHeight;
113 | requisitions[i] = w.SizeRequest ();
114 | totalWidth += requisitions[i].Width + spacing;
115 | }
116 | ++i;
117 | }
118 | totalWidth -= spacing;
119 |
120 | if(WidthRequest != -1 && HeightRequest != -1)
121 | {
122 | requisition.Width = WidthRequest;
123 | requisition.Height = HeightRequest;
124 | }
125 | else if(WidthRequest != -1)
126 | {
127 | int totalHeight = rowHeight, curWidth = 0;
128 | int availWidth = WidthRequest - 2*(int)BorderWidth;
129 |
130 | i = 0;
131 | foreach(Widget w in widgets)
132 | {
133 | if(w.Visible)
134 | {
135 | Gtk.Requisition r = requisitions[i];
136 |
137 | if(curWidth == 0 || curWidth + r.Width <= availWidth)
138 | { // Continue current line
139 | curWidth += r.Width;
140 | if(curWidth != 0) curWidth += spacing;
141 | }
142 | else
143 | { // Start new line
144 | totalHeight += rowHeight + spacing;
145 | curWidth = 0;
146 | }
147 | }
148 | ++i;
149 | }
150 |
151 | requisition.Width = WidthRequest;
152 | requisition.Height = totalHeight + 2*(int)BorderWidth;
153 | }
154 | else
155 | {
156 | int rowsLeft = (int)Math.Floor ((double)(HeightRequest + spacing) / (double)(rowHeight + spacing));
157 | if(rowsLeft == 0) rowsLeft = 1;
158 | int widthLeft = totalWidth;
159 | int curWidth = 0, maxWidth = 0;
160 | int minWidth = widthLeft / rowsLeft;
161 |
162 | i = 0;
163 | int currentWidgetCounter = 0;
164 | foreach(Widget w in widgets)
165 | {
166 | if(w.Visible)
167 | {
168 | Gtk.Requisition r = requisitions[i];
169 |
170 | widthLeft -= r.Width;
171 | curWidth += r.Width;
172 | ++currentWidgetCounter;
173 |
174 | if(curWidth >= minWidth)
175 | { // Start new line
176 | curWidth += (currentWidgetCounter - 1) * spacing;
177 | maxWidth = Math.Max (maxWidth, curWidth);
178 | curWidth = 0;
179 | --rowsLeft;
180 | if(rowsLeft == 0) break;
181 | minWidth = widthLeft / rowsLeft;
182 | currentWidgetCounter = 0;
183 | }
184 | }
185 | ++i;
186 | }
187 |
188 | requisition.Width = maxWidth + 2*(int)BorderWidth;
189 |
190 | if(HeightRequest == -1)
191 | requisition.Height = rowHeight;
192 | else
193 | requisition.Height = HeightRequest;
194 | }
195 | }
196 |
197 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
198 | {
199 | base.OnSizeAllocated (allocation);
200 |
201 | int right = allocation.X + allocation.Width - (int)BorderWidth;
202 | int left = allocation.X + (int)BorderWidth;
203 | int bottom = allocation.Y + allocation.Height - (int)BorderWidth;
204 | int x = left, rowY = allocation.Y + (int)BorderWidth;
205 | int maxHeight = 0;
206 |
207 | int i = 0;
208 | foreach(Widget w in widgets)
209 | {
210 | if(w.Visible)
211 | {
212 | Gdk.Rectangle r;
213 | r.Width = requisitions[i].Width;
214 | r.Height = requisitions[i].Height;
215 |
216 | if(x > left && x + r.Width > right)
217 | {
218 | rowY += maxHeight + spacing;
219 | maxHeight = 0;
220 | x = left;
221 | }
222 |
223 | r.X = x;
224 | r.Y = rowY;
225 | r.Width = Math.Min (right, r.X + r.Width) - r.X;
226 | r.Height = Math.Min (bottom, r.Y + r.Height) - r.Y;
227 | w.SizeAllocate (r);
228 |
229 | x += r.Width + spacing;
230 | maxHeight = Math.Max (maxHeight, r.Height);
231 | }
232 | ++i;
233 | }
234 | }
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/Ribbons/ToolPack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Cairo;
4 | using Gtk;
5 |
6 | namespace Ribbons
7 | {
8 | /// Set of ribbon buttons packed together.
9 | public class ToolPack : Container
10 | {
11 | private List buttons;
12 | private int[] widths;
13 |
14 | /// Default constructor.
15 | public ToolPack ()
16 | {
17 | this.buttons = new List ();
18 |
19 | this.SetFlag (WidgetFlags.NoWindow);
20 |
21 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
22 | }
23 |
24 | /// Adds a button before all existing buttons.
25 | /// The button to add.
26 | public void PrependButton (BaseButton Widget)
27 | {
28 | InsertButton (Widget, 0);
29 | }
30 |
31 | /// Adds a button after all existing buttons.
32 | /// The button to add.
33 | public void AppendButton (BaseButton Widget)
34 | {
35 | InsertButton (Widget, -1);
36 | }
37 |
38 | /// Inserts a button at the specified location.
39 | /// The button to add.
40 | /// The index (starting at 0) at which the button must be inserted, or -1 to insert the button after all existing buttons.
41 | public void InsertButton (BaseButton Widget, int ButtonIndex)
42 | {
43 | Widget.Parent = this;
44 | Widget.Visible = true;
45 |
46 | Widget.DrawBackground = true;
47 |
48 | if(ButtonIndex == -1 || ButtonIndex == buttons.Count)
49 | {
50 | if(buttons.Count == 0)
51 | {
52 | Widget.GroupStyle = GroupStyle.Alone;
53 | }
54 | else
55 | {
56 | Widget.GroupStyle = GroupStyle.Right;
57 |
58 | if(buttons.Count == 1)
59 | {
60 | buttons[buttons.Count - 1].GroupStyle = GroupStyle.Left;
61 | }
62 | else if(buttons.Count > 1)
63 | {
64 | buttons[buttons.Count - 1].GroupStyle = GroupStyle.Center;
65 | }
66 | }
67 | buttons.Add (Widget);
68 | }
69 | else
70 | {
71 | if(ButtonIndex == 0)
72 | {
73 | buttons[buttons.Count - 1].GroupStyle = GroupStyle.Left;
74 | if(buttons.Count == 1)
75 | {
76 | buttons[0].GroupStyle = GroupStyle.Right;
77 | }
78 | else
79 | {
80 | buttons[0].GroupStyle = GroupStyle.Center;
81 | }
82 | }
83 | buttons.Insert (ButtonIndex, Widget);
84 | }
85 |
86 | ShowAll ();
87 | }
88 |
89 | /// Removes the button at the specified index.
90 | /// Index of the button to remove.
91 | public void RemoveButton (int ButtonIndex)
92 | {
93 | buttons[ButtonIndex].Parent = null;
94 |
95 | if(ButtonIndex == 0)
96 | {
97 | if(buttons.Count > 1)
98 | {
99 | if(buttons.Count > 2)
100 | {
101 | buttons[0].GroupStyle = GroupStyle.Left;
102 | }
103 | else
104 | {
105 | buttons[0].GroupStyle = GroupStyle.Alone;
106 | }
107 | }
108 | }
109 | else if(ButtonIndex == buttons.Count - 1)
110 | {
111 | if(buttons.Count > 1)
112 | {
113 | if(buttons.Count > 2)
114 | {
115 | buttons[0].GroupStyle = GroupStyle.Right;
116 | }
117 | else
118 | {
119 | buttons[0].GroupStyle = GroupStyle.Alone;
120 | }
121 | }
122 | }
123 | buttons.RemoveAt (ButtonIndex);
124 |
125 | ShowAll ();
126 | }
127 |
128 | protected override void ForAll (bool include_internals, Callback callback)
129 | {
130 | foreach(BaseButton b in buttons)
131 | {
132 | if(b.Visible) callback (b);
133 | }
134 | }
135 |
136 | protected override void OnSizeRequested (ref Requisition requisition)
137 | {
138 | base.OnSizeRequested (ref requisition);
139 |
140 | if(widths == null || widths.Length != buttons.Count)
141 | {
142 | widths = new int[buttons.Count];
143 | }
144 |
145 | requisition.Height = requisition.Width = 0;
146 | int i = 0;
147 | foreach(BaseButton b in buttons)
148 | {
149 | Gtk.Requisition req = b.SizeRequest ();
150 | if(requisition.Height < req.Height) requisition.Height = req.Height;
151 | requisition.Width += req.Width;
152 | widths[i++] = req.Width;
153 | }
154 | if(HeightRequest != -1) requisition.Height = HeightRequest;
155 | if(WidthRequest != -1) requisition.Width = WidthRequest;
156 | }
157 |
158 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
159 | {
160 | base.OnSizeAllocated (allocation);
161 |
162 | int i = 0, x = allocation.X;
163 | foreach(BaseButton b in buttons)
164 | {
165 | Gdk.Rectangle r;
166 | r.X = x;
167 | r.Y = allocation.Y;
168 | r.Width = widths[i];
169 | r.Height = allocation.Height;
170 | b.SizeAllocate (r);
171 | x += r.Width;
172 | ++i;
173 | }
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/Ribbons/VariantsCombinaison.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | // Note: this widget shall display a button at the left and the right
8 | // to scroll groups when the allocated with is not enough.
9 |
10 | ///
11 | /// A set of widgets displayed horizontaly.
12 | ///
13 | ///
14 | /// On the contrary of a classical container, the VariantsCombinaison is only
15 | /// the parent of its children if it has a parent itself.
16 | ///
17 | public class VariantsCombinaison : Container
18 | {
19 | private List widgets;
20 | private Button left, right;
21 | private Gtk.Requisition[] requisitions;
22 | private int spacing;
23 |
24 | public VariantsCombinaison ()
25 | {
26 | Init ();
27 | }
28 |
29 | protected VariantsCombinaison (IntPtr raw) : base (raw)
30 | {
31 | Init ();
32 | }
33 |
34 | private void Init ()
35 | {
36 | this.widgets = new List ();
37 |
38 | this.SetFlag (WidgetFlags.NoWindow);
39 |
40 | this.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
41 |
42 | this.spacing = 2;
43 | }
44 |
45 | /*public void Measure (int Height)
46 | {
47 | width = 0;
48 | foreach(Widget variant in variants)
49 | {
50 | variant.Measure (Height);
51 | width += variant.Width;
52 | }
53 | }*/
54 |
55 | /// Gets or sets the spacing between children.
56 | public int Spacing
57 | {
58 | set
59 | {
60 | spacing = value;
61 | QueueDraw ();
62 | }
63 | get { return spacing; }
64 | }
65 |
66 | /// Adds a widget before all existing widgets.
67 | /// The widget to add.
68 | public void Prepend (Widget w)
69 | {
70 | Insert (w, 0);
71 | }
72 |
73 | /// Adds a widget after all existing widgets.
74 | /// The widget to add.
75 | public void Append (Widget w)
76 | {
77 | Insert (w, -1);
78 | }
79 |
80 | /// Inserts a widget at the specified location.
81 | /// The widget to add.
82 | /// The index (starting at 0) at which the widget must be inserted, or -1 to insert the widget after all existing widgets.
83 | public void Insert (Widget w, int WidgetIndex)
84 | {
85 | if(Parent != null) w.Parent = this;
86 | w.Visible = true;
87 |
88 | if(WidgetIndex == -1)
89 | widgets.Add (w);
90 | else
91 | widgets.Insert (WidgetIndex, w);
92 |
93 | ShowAll ();
94 | }
95 |
96 | /// Removes the widget at the specified index.
97 | /// Index of the widget to remove.
98 | public void Remove (int WidgetIndex)
99 | {
100 | if(Parent != null) widgets[WidgetIndex].Parent = null;
101 |
102 | if(WidgetIndex == -1)
103 | widgets.RemoveAt (widgets.Count - 1);
104 | else
105 | widgets.RemoveAt (WidgetIndex);
106 |
107 | ShowAll ();
108 | }
109 |
110 | protected override void OnParentSet (Widget previous_parent)
111 | {
112 | base.OnParentSet (previous_parent);
113 |
114 | if(Parent == null)
115 | {Console.WriteLine ("unparnet");
116 | foreach(Widget w in widgets) w.Unparent ();
117 | }
118 | else
119 | {Console.WriteLine ("ok");
120 | foreach(Widget w in widgets) w.Parent = this;
121 | }
122 | }
123 |
124 | protected override void ForAll (bool include_internals, Callback callback)
125 | {
126 | //if(Parent == null) return;
127 |
128 | foreach(Widget w in widgets)
129 | {
130 | if(w.Visible) callback (w);
131 | }
132 | }
133 |
134 | protected override void OnSizeRequested (ref Requisition requisition)
135 | {
136 | base.OnSizeRequested (ref requisition);
137 |
138 | if(requisitions == null || requisitions.Length != widgets.Count)
139 | {
140 | requisitions = new Gtk.Requisition[widgets.Count];
141 | }
142 |
143 | int totalWidth = 0, rowHeight = 0;
144 | if(HeightRequest == -1)
145 | {
146 | foreach(Widget w in widgets)
147 | {
148 | if(w.Visible)
149 | {
150 | rowHeight = Math.Max (rowHeight, w.SizeRequest ().Height);
151 | }
152 | }
153 | }
154 | else rowHeight = HeightRequest - 2*(int)BorderWidth;
155 |
156 | int i = 0;
157 | foreach(Widget w in widgets)
158 | {
159 | if(w.Visible)
160 | {
161 | w.HeightRequest = rowHeight;
162 | requisitions[i] = w.SizeRequest ();
163 | totalWidth += requisitions[i].Width + spacing;
164 | }
165 | ++i;
166 | }
167 | totalWidth -= spacing;
168 |
169 | requisition.Height = rowHeight;
170 | if(WidthRequest != -1)
171 | requisition.Width = WidthRequest;
172 | else
173 | requisition.Width = totalWidth;
174 | }
175 |
176 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
177 | {
178 | base.OnSizeAllocated (allocation);
179 |
180 | int right = allocation.X + allocation.Width - (int)BorderWidth;
181 | int left = allocation.X + (int)BorderWidth;
182 | int bottom = allocation.Y + allocation.Height - (int)BorderWidth;
183 | int x = left, y = allocation.Y + (int)BorderWidth;
184 |
185 | int i = 0;
186 | foreach(Widget w in widgets)
187 | {
188 | if(w.Visible)
189 | {
190 | Gdk.Rectangle r;
191 | r.X = x;
192 | r.Y = y;
193 | r.Width = Math.Min (right, r.X + requisitions[i].Width) - r.X;
194 | //r.Height = Math.Min (bottom, r.Y + requisitions[i].Height) - r.Y;
195 | r.Height = bottom - y;
196 | w.SizeAllocate (r);
197 |
198 | x += r.Width + spacing;
199 | }
200 | ++i;
201 | }
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/Ribbons/VariantsCombinaisonSwitcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Gtk;
4 |
5 | namespace Ribbons
6 | {
7 | ///
8 | /// Selects a certain VariantsCombinaison based on space constraints.
9 | ///
10 | public class VariantsCombinaisonSwitcher : Container
11 | {
12 | private List combinaisons;
13 | private int requestedWidth, requiredHeight;
14 | private VariantsCombinaison candidateCombinaison;
15 | private VariantsCombinaison selectedCombinaison;
16 |
17 | public int Count
18 | {
19 | get { return combinaisons.Count; }
20 | }
21 |
22 | public VariantsCombinaison this[int Index]
23 | {
24 | get { return combinaisons[Index]; }
25 | }
26 |
27 | public VariantsCombinaisonSwitcher ()
28 | {
29 | Init ();
30 | }
31 |
32 | protected VariantsCombinaisonSwitcher (IntPtr raw) : base (raw)
33 | {
34 | Init ();
35 | }
36 |
37 | private void Init ()
38 | {
39 | combinaisons = new List ();
40 |
41 | SetFlag (WidgetFlags.NoWindow);
42 |
43 | AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
44 | }
45 |
46 | public void AddCombinaison (VariantsCombinaison Combinaison)
47 | {
48 | combinaisons.Add (Combinaison);
49 | }
50 |
51 | public void RemoveCombinaison (VariantsCombinaison Combinaison)
52 | {
53 | combinaisons.Remove (Combinaison);
54 | }
55 |
56 | public void RemoveCombinaisonAt (int Index)
57 | {
58 | combinaisons.RemoveAt (Index);
59 | }
60 |
61 | protected override void ForAll (bool include_internals, Callback callback)
62 | {
63 | if(selectedCombinaison != null) callback (selectedCombinaison);
64 | }
65 | int counter = 0;
66 | protected override void OnSizeRequested (ref Requisition requisition)
67 | {
68 | Console.WriteLine ("TEST");
69 | base.OnSizeRequested (ref requisition);
70 |
71 | /*combinaisons[0].HeightRequest = HeightRequest;
72 | requisition = combinaisons[0].SizeRequest ();
73 | requiredHeight = requisition.Height;
74 | requestedWidth = requisition.Width;
75 | candidateCombinaison = combinaisons[0];
76 | return;*/
77 |
78 | candidateCombinaison = null;
79 | requiredHeight = HeightRequest;
80 |
81 | if(WidthRequest == -1)
82 | {
83 | int width = int.MaxValue;
84 |
85 | foreach(VariantsCombinaison combi in combinaisons)
86 | {
87 | //combi.HeightRequest = HeightRequest;
88 |
89 | Requisition req = combi.SizeRequest ();
90 |
91 | if(req.Width < width)
92 | {
93 | candidateCombinaison = combi;
94 | width = req.Width;
95 | requiredHeight = req.Height;
96 | }
97 | }
98 |
99 | requestedWidth = requisition.Width = width;
100 | }
101 | else if(HeightRequest == -1)
102 | {
103 | int width = -1;
104 |
105 | foreach(VariantsCombinaison combi in combinaisons)
106 | {
107 | combi.HeightRequest = -1;
108 |
109 | Requisition req = combi.SizeRequest ();
110 |
111 | if((req.Width <= WidthRequest && req.Width > width) || (width > WidthRequest && req.Width < width))
112 | {
113 | candidateCombinaison = combi;
114 | width = req.Width;
115 | requiredHeight = req.Height;
116 | }
117 | }
118 |
119 | requestedWidth = requisition.Width = WidthRequest;
120 | }
121 |
122 | if(HeightRequest == -1) requisition.Height = requiredHeight;
123 | else requisition.Height = HeightRequest;
124 |
125 | Console.WriteLine ("Switcher req: " + requisition.Width + " " + requisition.Height);
126 | }
127 |
128 | protected override void OnSizeAllocated (Gdk.Rectangle allocation)
129 | {Console.WriteLine (allocation.Width + " " + allocation.Height);
130 | base.OnSizeAllocated (allocation);
131 |
132 | if(requestedWidth != allocation.Width || requiredHeight != allocation.Height)
133 | {
134 | int width = -1;
135 | candidateCombinaison = null;
136 |
137 | foreach(VariantsCombinaison combi in combinaisons)
138 | {
139 | //combi.HeightRequest = allocation.Height;
140 |
141 | Requisition req = combi.SizeRequest ();
142 |
143 | if(req.Width <= allocation.Width && req.Width > width)
144 | {
145 | candidateCombinaison = combi;
146 | width = req.Width;
147 | }
148 | }
149 | }
150 |
151 | Select (candidateCombinaison);
152 |
153 | if(candidateCombinaison != null)
154 | {
155 | candidateCombinaison.SizeAllocate (allocation);
156 | }
157 | }
158 |
159 | private void Select (VariantsCombinaison combi)
160 | {Console.WriteLine ("Select: " + combi);
161 | if(selectedCombinaison != combi)
162 | {
163 | if(selectedCombinaison != null)
164 | {
165 | selectedCombinaison.Unparent ();
166 | }
167 |
168 | if(combi != null)
169 | {
170 | combi.Parent = this;
171 | }
172 |
173 | selectedCombinaison = combi;
174 | }
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/Ribbons/gtk-gui/generated.cs:
--------------------------------------------------------------------------------
1 | // ------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Mono Runtime Version: 2.0.50727.42
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | // ------------------------------------------------------------------------------
10 |
11 | namespace Stetic {
12 |
13 |
14 | internal class Gui {
15 |
16 | private static bool initialized;
17 |
18 | internal static void Initialize(Gtk.Widget iconRenderer) {
19 | if ((Stetic.Gui.initialized == false)) {
20 | Stetic.Gui.initialized = true;
21 | }
22 | }
23 | }
24 |
25 | internal class ActionGroups {
26 |
27 | public static Gtk.ActionGroup GetActionGroup(System.Type type) {
28 | return Stetic.ActionGroups.GetActionGroup(type.FullName);
29 | }
30 |
31 | public static Gtk.ActionGroup GetActionGroup(string name) {
32 | return null;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Ribbons/gtk-gui/gui.stetic:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Ribbons/gtk-gui/objects.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sample/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 |
4 | // Information about this assembly is defined by the following
5 | // attributes.
6 | //
7 | // change them to the information which is associated with the assembly
8 | // you compile.
9 |
10 | [assembly: AssemblyTitle("")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("")]
15 | [assembly: AssemblyCopyright("")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // The assembly version has following format :
20 | //
21 | // Major.Minor.Build.Revision
22 | //
23 | // You can specify all values by your own or you can build default build and revision
24 | // numbers with the '*' character (the default):
25 |
26 | [assembly: AssemblyVersion("1.0.*")]
27 |
28 | // The following attributes specify the key for the sign of your assembly. See the
29 | // .NET Framework documentation for more information about signing.
30 | // This is not required, if you don't want signing let these attributes like they're.
31 | [assembly: AssemblyDelaySign(false)]
32 | [assembly: AssemblyKeyFile("")]
33 |
--------------------------------------------------------------------------------
/Sample/ChangeLog:
--------------------------------------------------------------------------------
1 | 2008-08-18 Laurent Debacker
2 |
3 | * MainWindow.cs: Updated sample for key tips.
4 |
5 | 2008-08-15 Laurent Debacker
6 |
7 | * MainWindow.cs: Updated the main sample to integrate the sample developed
8 | in VariantsCombinaisonTest
9 |
10 | 2008-08-11 Laurent Debacker
11 |
12 | * DropdownGroupTest.cs: New test for drop down ribbon groups
13 | * VariantsCombinaisonTest.cs: New test for variants combinaisons
14 |
15 | 2008-07-11 Laurent Debacker
16 |
17 | * MainWindow.cs: Updated sample to show menu opening in app menu
18 |
19 | 2008-07-11 Laurent Debacker
20 |
21 | * MainWindow.cs: Update sample to showcase advance in app menu
22 | implementation
23 |
24 | 2008-07-07 Laurent Debacker
25 |
26 | * MainWindow.cs: Update sample
27 |
28 | 2008-06-30 Laurent Debacker
29 |
30 | * Sample/MainWindow.cs: Updated sample
31 | * Ribbons/Theme.cs: Quick Access Toolbar background
32 | * Ribbons/ApplicationMenu.cs: Initial stub API for application menu.
33 | * Ribbons/QuickAccessToolbar.cs: Take care of height requests from
34 | children widgets
35 |
36 | 2007-12-29 Laurent Debacker
37 |
38 |
39 |
40 | 2007-12-28 Laurent Debacker
41 |
42 | * MainWindow.cs, ChangeLog: Fixing calls to Dispose() and Destroy()
43 |
44 |
--------------------------------------------------------------------------------
/Sample/DropdownGroupTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 | using Ribbons;
5 |
6 | namespace Sample
7 | {
8 | public class DropdownGroupTest : SyntheticWindow
9 | {
10 | protected bool composeAvailable = false;
11 |
12 | protected Label pageLabel1;
13 |
14 | public DropdownGroupTest() : base (WindowType.Toplevel)
15 | {
16 | AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
17 |
18 | HBox master = new HBox ();
19 | master.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
20 |
21 | Title = "Ribbons Sample";
22 | AppPaintable = true;
23 |
24 | Ribbons.Button button0 = new Ribbons.Button ("Hello World");
25 |
26 | RibbonGroup group0 = new RibbonGroup ();
27 | group0.Label = "Summer of Code";
28 | group0.Child = button0;
29 | group0.Expand += onClick;
30 |
31 | DropdownRibbonGroup dropGroup0 = new DropdownRibbonGroup ();
32 | dropGroup0.Group = group0;
33 | dropGroup0.Label = "Drop 1";
34 |
35 | DropdownRibbonGroup dropGroup1 = new DropdownRibbonGroup ();
36 | dropGroup1.Group = group0;
37 | dropGroup1.Label = "Drop 2";
38 |
39 | master.PackStart (dropGroup0, false, false, 0);
40 | master.PackStart (dropGroup1, false, false, 0);
41 |
42 | Add (master);
43 |
44 | ScreenChanged += Window_OnScreenChanged;
45 | Window_OnScreenChanged (this, null);
46 | ExposeEvent += Window_OnExpose;
47 | DeleteEvent += Window_OnDelete;
48 |
49 | this.Resize (200, 200);
50 | this.ShowAll ();
51 | }
52 |
53 | private void onClick (object Sender, EventArgs e)
54 | {
55 | Dialog d = new Dialog ("Test", this, DialogFlags.DestroyWithParent);
56 | d.Modal = true;
57 | d.AddButton ("Close", ResponseType.Close);
58 | d.Run ();
59 | d.Destroy ();
60 | }
61 |
62 | [GLib.ConnectBefore]
63 | private void Window_OnExpose (object sender, ExposeEventArgs args)
64 | {
65 | Gdk.EventExpose evnt = args.Event;
66 | Context cr = Gdk.CairoHelper.Create (GdkWindow);
67 |
68 | /*if(composeAvailable)
69 | cr.SetSourceRGBA (0, 0, 0, 0.3);
70 | else*/
71 | cr.SetSourceRGB (0.3, 0.3, 0.3);
72 |
73 | //cr.SetSourceRGB (0.749, 0.859, 1.0);
74 |
75 | cr.Operator = Operator.Source;
76 | cr.Paint ();
77 |
78 | ((IDisposable)cr.Target).Dispose();
79 | ((IDisposable)cr).Dispose();
80 |
81 | args.RetVal = false;
82 | }
83 |
84 | private void Window_OnScreenChanged (object Send, ScreenChangedArgs args)
85 | {
86 | Gdk.Colormap cm = Screen.RgbaColormap;
87 | composeAvailable = cm != null; // FIX: Do not seem to detect compose support in all cases
88 |
89 | if(!composeAvailable) cm = Screen.RgbColormap;
90 | Colormap = cm;
91 |
92 | Console.WriteLine ("Compose Support: " + composeAvailable);
93 | }
94 |
95 | private void Window_OnDelete (object send, DeleteEventArgs args)
96 | {
97 | Application.Quit ();
98 | args.RetVal = true;
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Sample/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Gtk;
3 |
4 | namespace Sample
5 | {
6 | class MainClass
7 | {
8 | public static void Main(string[] args)
9 | {
10 | Console.WriteLine ("Starting ...");
11 | Application.Init ();
12 | MainWindow win = new MainWindow ();
13 | //VariantsCombinaisonTest win = new VariantsCombinaisonTest ();
14 | win.Show ();
15 | Application.Run ();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sample/MainWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 | using Ribbons;
5 |
6 | namespace Sample
7 | {
8 | public class MainWindow : SyntheticWindow
9 | {
10 | protected bool composeAvailable = false;
11 |
12 | protected Ribbon ribbon;
13 | protected RibbonGroup group0, group1, group2;
14 |
15 | protected Label pageLabel1;
16 |
17 | public MainWindow() : base (WindowType.Toplevel)
18 | {
19 | AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
20 |
21 | VBox master = new VBox ();
22 | master.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
23 |
24 | Title = "Ribbons Sample";
25 | AppPaintable = true;
26 |
27 | VariantsCombinaisonSwitcher page0 = new VariantsCombinaisonSwitcher ();
28 |
29 | RibbonGroup group0 = CreateGroup0 ();
30 | RibbonGroup group1 = CreateGroup1 ();
31 | RibbonGroup group2 = CreateGroup2 ();
32 | DropdownRibbonGroup dgroup0 = CreateDropdownGroup0 ();
33 | dgroup0.Group = group0;
34 | DropdownRibbonGroup dgroup1 = CreateDropdownGroup1 ();
35 | dgroup1.Group = group1;
36 | DropdownRibbonGroup dgroup2 = CreateDropdownGroup2 ();
37 | dgroup2.Group = group2;
38 |
39 | VariantsCombinaison combi0 = new VariantsCombinaison ();
40 | combi0.Append (group0);
41 | combi0.Append (group1);
42 | combi0.Append (group2);
43 | page0.AddCombinaison (combi0);
44 |
45 | VariantsCombinaison combi1 = new VariantsCombinaison ();
46 | combi1.Append (group0);
47 | combi1.Append (group1);
48 | combi1.Append (dgroup2);
49 | page0.AddCombinaison (combi1);
50 |
51 | VariantsCombinaison combi2 = new VariantsCombinaison ();
52 | combi2.Append (dgroup0);
53 | combi2.Append (dgroup1);
54 | combi2.Append (dgroup2);
55 | page0.AddCombinaison (combi2);
56 |
57 | HBox page1 = new HBox (false, 2);
58 | RibbonGroup group10 = new RibbonGroup ();
59 | group10.Label = "Welcome on the second page";
60 | page1.PackStart (group10, false, false, 0);
61 |
62 | HBox page2 = new HBox (false, 2);
63 |
64 | Label pageLabel0 = new Label ("Page 1");
65 | pageLabel1 = new Label ("Page 2");
66 | Label pageLabel2 = new Label ("Page 3");
67 |
68 | Ribbons.Button shortcuts = new Ribbons.Button ("Menu");
69 | shortcuts.Child.ModifyFg (Gtk.StateType.Normal, new Gdk.Color(255, 255, 255));
70 |
71 | Menu mainMenu = new Menu ();
72 | MenuItem mainMenu_quit = new MenuItem ("Quit");
73 | mainMenu_quit.Activated += delegate (object Sender, EventArgs e)
74 | {
75 | Application.Quit ();
76 | };
77 | mainMenu.Append (mainMenu_quit);
78 |
79 | shortcuts.Clicked += delegate (object Sender, EventArgs e)
80 | {
81 | mainMenu.Popup ();
82 | mainMenu.ShowAll ();
83 | };
84 |
85 | QuickAccessToolbar qat = new QuickAccessToolbar ();
86 | Ribbons.Button qatNew, qatSave;
87 | qat.Append (qatNew = Ribbons.Button.FromStockIcon (Gtk.Stock.New, false));
88 | qat.Append (qatSave = Ribbons.Button.FromStockIcon (Gtk.Stock.Save, false));
89 |
90 | ribbon = new Ribbon ();
91 | ribbon.ApplicationButton = new ApplicationButton ();
92 | ribbon.QuickAccessToolbar = qat;
93 | //ribbon.Shortcuts = shortcuts;
94 | ribbon.AppendPage (page0, pageLabel0);
95 | ribbon.AppendPage (page1, pageLabel1);
96 | ribbon.AppendPage (page2, pageLabel2);
97 | pageLabel1.AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
98 | pageLabel1.ButtonPressEvent += delegate (object sender, ButtonPressEventArgs e)
99 | {
100 | Console.WriteLine("label1 press");
101 | };
102 | pageLabel1.EnterNotifyEvent += delegate (object sender, EnterNotifyEventArgs e)
103 | {
104 | Console.WriteLine("label1 enter");
105 | };
106 | pageLabel1.LeaveNotifyEvent += delegate (object sender, LeaveNotifyEventArgs e)
107 | {
108 | Console.WriteLine("label1 leave");
109 | };
110 |
111 | ApplicationMenu appMenu = ribbon.ApplicationButton.Menu;
112 | TextView mnu = new TextView ();
113 | appMenu.DefaultMenu = mnu;
114 | mnu.Buffer.InsertAtCursor ("Default");
115 | ApplicationMenuItem mi = new ApplicationMenuItem ("Test 1");
116 | mnu = new TextView ();
117 | mi.Menu = mnu;
118 | mnu.Buffer.InsertAtCursor ("Test 1");
119 | appMenu.Append (mi);
120 | mi = new ApplicationMenuItem ("Test 2");
121 | appMenu.Append (mi);
122 | mi = new ApplicationMenuItem ("Test 3");
123 | appMenu.Append (mi);
124 |
125 | appMenu.OptionsButton = new Ribbons.Button ("Options");
126 | appMenu.ExitButton = new Ribbons.Button ("Exit");
127 |
128 | TextView txt = new TextView ();
129 |
130 | master.PackStart (ribbon, false, false, 0);
131 | master.PackStart (txt, true, true, 0);
132 |
133 | Add (master);
134 |
135 | ribbon.ApplicationButton.KeyTip = new KeyTip (appMenu, "A");
136 | qat.AddKeyTip (new KeyTip (qatNew, "B"));
137 | qat.AddKeyTip (new KeyTip (qatSave, "C"));
138 | ribbon.AddTabKeyTip (new KeyTip (pageLabel0, "D"));
139 | ribbon.AddTabKeyTip (new KeyTip (pageLabel1, "E"));
140 | ribbon.AddTabKeyTip (new KeyTip (pageLabel2, "F"));
141 |
142 | ScreenChanged += Window_OnScreenChanged;
143 | Window_OnScreenChanged (this, null);
144 | ExposeEvent += Window_OnExpose;
145 | DeleteEvent += Window_OnDelete;
146 |
147 | this.Resize (200, 200);
148 | this.ShowAll ();
149 | }
150 |
151 | private RibbonGroup CreateGroup0 ()
152 | {
153 | Ribbons.Button button0 = new Ribbons.Button ("Hello World");
154 |
155 | RibbonGroup group0 = new RibbonGroup ();
156 | group0.Label = "Summer of Code";
157 | group0.Child = button0;
158 | group0.Expand += onClick;
159 |
160 | return group0;
161 | }
162 |
163 | private DropdownRibbonGroup CreateDropdownGroup0 ()
164 | {
165 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
166 | ret.Label = "Summer of Code";
167 | return ret;
168 | }
169 |
170 | private RibbonGroup CreateGroup1 ()
171 | {
172 | Ribbons.Button button1 = new Ribbons.Button ("Menu Test");
173 | button1.Clicked += onClick;
174 | Menu button1_menu = new Menu ();
175 | MenuItem option1 = new MenuItem ("Option 1");
176 | button1_menu.Append (option1);
177 | button1.DropDownMenu = button1_menu;
178 |
179 | Menu openMenu = new Menu ();
180 | MenuItem abc_txt = new MenuItem ("abc.txt");
181 | openMenu.Append (abc_txt);
182 | MenuItem foo_txt = new MenuItem ("foo.txt");
183 | openMenu.Append (foo_txt);
184 |
185 | Ribbons.Button open = Ribbons.Button.FromStockIcon (Gtk.Stock.Open, "Open", false);
186 | open.DropDownMenu = openMenu;
187 | open.Clicked += onClick;
188 |
189 | Ribbons.ToolPack fileToolPack = new Ribbons.ToolPack ();
190 | fileToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.New, "New", false));
191 | fileToolPack.AppendButton (open);
192 | fileToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.Save, "Save", false));
193 |
194 | Ribbons.ToolPack printerToolPack = new Ribbons.ToolPack ();
195 | printerToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.Print, "Print", false));
196 |
197 | Ribbons.ToolPack fontToolPack = new Ribbons.ToolPack ();
198 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Bold, false));
199 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Italic, false));
200 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Underline, false));
201 |
202 | ComboBox font = new ComboBox (new string[] { "Arial", "Verdana" });
203 | font.Active = 0;
204 |
205 | Ribbons.ToolBox flow0 = new ToolBox ();
206 | flow0.Append (fileToolPack);
207 | flow0.Append (printerToolPack);
208 | flow0.Append (fontToolPack);
209 | flow0.Append (font);
210 |
211 | HBox btnFlowBox = new HBox (false, 2);
212 | btnFlowBox.Add (button1);
213 | btnFlowBox.Add (flow0);
214 |
215 | // Little hack because Gtk+ is not designed to support size negociations
216 | btnFlowBox.SizeAllocated += delegate(object Sender, SizeAllocatedArgs e)
217 | {
218 | flow0.HeightRequest = e.Allocation.Height;
219 | };
220 |
221 | RibbonGroup group1 = new RibbonGroup ();
222 | group1.Label = "I will be back";
223 | group1.Child = btnFlowBox;
224 |
225 | return group1;
226 | }
227 |
228 | private DropdownRibbonGroup CreateDropdownGroup1 ()
229 | {
230 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
231 | ret.Label = "I will be back";
232 | return ret;
233 | }
234 |
235 | private RibbonGroup CreateGroup2 ()
236 | {
237 | Gallery gallery = new Gallery ();
238 | gallery.AppendTile (new SampleTile ("1"));
239 | gallery.AppendTile (new SampleTile ("2"));
240 | gallery.AppendTile (new SampleTile ("3"));
241 | gallery.AppendTile (new SampleTile ("4"));
242 | gallery.AppendTile (new SampleTile ("5"));
243 |
244 | RibbonGroup group2 = new RibbonGroup ();
245 | group2.Label = "Gallery";
246 | group2.Child = gallery;
247 |
248 | return group2;
249 | }
250 |
251 | private DropdownRibbonGroup CreateDropdownGroup2 ()
252 | {
253 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
254 | ret.Label = "Gallery";
255 | return ret;
256 | }
257 |
258 | private void onClick (object Sender, EventArgs e)
259 | {
260 | Dialog d = new Dialog ("Test", this, DialogFlags.DestroyWithParent);
261 | d.Modal = true;
262 | d.AddButton ("Close", ResponseType.Close);
263 | d.Run ();
264 | d.Destroy ();
265 | }
266 |
267 | protected override bool OnKeyPressEvent (Gdk.EventKey evnt)
268 | {
269 | if(evnt.Key.ToString() == "Alt_L" || evnt.Key.ToString() == "ISO_Level3_Shift")
270 | {
271 | ribbon.ShowTopLevelKeyTips ();
272 | }
273 |
274 | return base.OnKeyPressEvent (evnt);
275 | }
276 |
277 | protected override bool OnKeyReleaseEvent (Gdk.EventKey evnt)
278 | {
279 | if(evnt.Key.ToString() == "Alt_L" || evnt.Key.ToString() == "ISO_Level3_Shift")
280 | {
281 | ribbon.HideKeyTips ();
282 | }
283 |
284 | return base.OnKeyReleaseEvent (evnt);
285 | }
286 |
287 | [GLib.ConnectBefore]
288 | private void Window_OnExpose (object sender, ExposeEventArgs args)
289 | {
290 | Gdk.EventExpose evnt = args.Event;
291 | Context cr = Gdk.CairoHelper.Create (GdkWindow);
292 |
293 | /*if(composeAvailable)
294 | cr.SetSourceRGBA (0, 0, 0, 0.3);
295 | else*/
296 | cr.SetSourceRGB (0.3, 0.3, 0.3);
297 |
298 | //cr.SetSourceRGB (0.749, 0.859, 1.0);
299 |
300 | cr.Operator = Operator.Source;
301 | cr.Paint ();
302 |
303 | ((IDisposable)cr.Target).Dispose();
304 | ((IDisposable)cr).Dispose();
305 |
306 | args.RetVal = false;
307 | }
308 |
309 | private void Window_OnScreenChanged (object Send, ScreenChangedArgs args)
310 | {
311 | Gdk.Colormap cm = Screen.RgbaColormap;
312 | composeAvailable = cm != null; // FIX: Do not seem to detect compose support in all cases
313 |
314 | if(!composeAvailable) cm = Screen.RgbColormap;
315 | Colormap = cm;
316 |
317 | Console.WriteLine ("Compose Support: " + composeAvailable);
318 | }
319 |
320 | private void Window_OnDelete (object send, DeleteEventArgs args)
321 | {
322 | Application.Quit ();
323 | args.RetVal = true;
324 | }
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/Sample/Sample.mdp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Sample/SampleTile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Ribbons;
4 |
5 | namespace Sample
6 | {
7 | public class SampleTile : Tile
8 | {
9 | private string txt;
10 | private Pango.Layout textLayout;
11 |
12 | public SampleTile (string Text)
13 | {
14 | txt = Text;
15 | textLayout = CreatePangoLayout (Text);
16 | }
17 |
18 | public override Tile Copy ()
19 | {
20 | return new SampleTile (txt);
21 | }
22 |
23 | public override void DrawContent (Cairo.Context Context, Cairo.Rectangle Area)
24 | {
25 | Context.Color = new Color (0, 0, 0);
26 | Pango.CairoHelper.UpdateLayout (Context, textLayout);
27 | Context.MoveTo (Area.X, Area.Y);
28 | Pango.CairoHelper.ShowLayout (Context, textLayout);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sample/VariantsCombinaisonTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Cairo;
3 | using Gtk;
4 | using Ribbons;
5 |
6 | namespace Sample
7 | {
8 | public class VariantsCombinaisonTest : SyntheticWindow
9 | {
10 | protected bool composeAvailable = false;
11 |
12 | protected Label pageLabel1;
13 |
14 | public VariantsCombinaisonTest() : base (WindowType.Toplevel)
15 | {
16 | AddEvents ((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask));
17 | Title = "Ribbons Sample";
18 | AppPaintable = true;
19 |
20 | VariantsCombinaisonSwitcher switcher = new VariantsCombinaisonSwitcher ();
21 |
22 | RibbonGroup group0 = CreateGroup0 ();
23 | RibbonGroup group1 = CreateGroup1 ();
24 | RibbonGroup group2 = CreateGroup2 ();
25 | DropdownRibbonGroup dgroup0 = CreateDropdownGroup0 ();
26 | dgroup0.Group = group0;
27 | DropdownRibbonGroup dgroup1 = CreateDropdownGroup1 ();
28 | dgroup1.Group = group1;
29 | DropdownRibbonGroup dgroup2 = CreateDropdownGroup2 ();
30 | dgroup2.Group = group2;
31 |
32 | VariantsCombinaison combi0 = new VariantsCombinaison ();
33 | combi0.Append (group0);
34 | combi0.Append (group1);
35 | combi0.Append (group2);
36 | switcher.AddCombinaison (combi0);
37 |
38 | VariantsCombinaison combi1 = new VariantsCombinaison ();
39 | combi1.Append (group0);
40 | combi1.Append (group1);
41 | combi1.Append (dgroup2);
42 | switcher.AddCombinaison (combi1);
43 |
44 | VariantsCombinaison combi2 = new VariantsCombinaison ();
45 | combi2.Append (dgroup0);
46 | combi2.Append (dgroup1);
47 | combi2.Append (dgroup2);
48 | switcher.AddCombinaison (combi2);
49 |
50 | Add (switcher);
51 |
52 | ScreenChanged += Window_OnScreenChanged;
53 | Window_OnScreenChanged (this, null);
54 | ExposeEvent += Window_OnExpose;
55 | DeleteEvent += Window_OnDelete;
56 |
57 | this.Resize (200, 200);
58 | this.ShowAll ();
59 | }
60 |
61 | private RibbonGroup CreateGroup0 ()
62 | {
63 | Ribbons.Button button0 = new Ribbons.Button ("Hello World");
64 |
65 | RibbonGroup group0 = new RibbonGroup ();
66 | group0.Label = "Summer of Code";
67 | group0.Child = button0;
68 | group0.Expand += onClick;
69 |
70 | return group0;
71 | }
72 |
73 | private DropdownRibbonGroup CreateDropdownGroup0 ()
74 | {
75 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
76 | ret.Label = "Summer of Code";
77 | return ret;
78 | }
79 |
80 | private RibbonGroup CreateGroup1 ()
81 | {
82 | Ribbons.Button button1 = new Ribbons.Button ("Menu Test");
83 | button1.Clicked += onClick;
84 | Menu button1_menu = new Menu ();
85 | MenuItem option1 = new MenuItem ("Option 1");
86 | button1_menu.Append (option1);
87 | button1.DropDownMenu = button1_menu;
88 |
89 | Menu openMenu = new Menu ();
90 | MenuItem abc_txt = new MenuItem ("abc.txt");
91 | openMenu.Append (abc_txt);
92 | MenuItem foo_txt = new MenuItem ("foo.txt");
93 | openMenu.Append (foo_txt);
94 |
95 | Ribbons.Button open = Ribbons.Button.FromStockIcon (Gtk.Stock.Open, "Open", false);
96 | open.DropDownMenu = openMenu;
97 | open.Clicked += onClick;
98 |
99 | Ribbons.ToolPack fileToolPack = new Ribbons.ToolPack ();
100 | fileToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.New, "New", false));
101 | fileToolPack.AppendButton (open);
102 | fileToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.Save, "Save", false));
103 |
104 | Ribbons.ToolPack printerToolPack = new Ribbons.ToolPack ();
105 | printerToolPack.AppendButton (Ribbons.Button.FromStockIcon (Gtk.Stock.Print, "Print", false));
106 |
107 | Ribbons.ToolPack fontToolPack = new Ribbons.ToolPack ();
108 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Bold, false));
109 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Italic, false));
110 | fontToolPack.AppendButton (Ribbons.ToggleButton.FromStockIcon (Gtk.Stock.Underline, false));
111 |
112 | ComboBox font = new ComboBox (new string[] { "Arial", "Verdana" });
113 | font.Active = 0;
114 |
115 | Ribbons.ToolBox flow0 = new ToolBox ();
116 | flow0.Append (fileToolPack);
117 | flow0.Append (printerToolPack);
118 | flow0.Append (fontToolPack);
119 | flow0.Append (font);
120 |
121 | HBox btnFlowBox = new HBox (false, 2);
122 | btnFlowBox.Add (button1);
123 | btnFlowBox.Add (flow0);
124 |
125 | // Little hack because Gtk+ is not designed to support size negociations
126 | btnFlowBox.SizeAllocated += delegate(object Sender, SizeAllocatedArgs e)
127 | {
128 | flow0.HeightRequest = e.Allocation.Height;
129 | };
130 |
131 | RibbonGroup group1 = new RibbonGroup ();
132 | group1.Label = "I will be back";
133 | group1.Child = btnFlowBox;
134 |
135 | return group1;
136 | }
137 |
138 | private DropdownRibbonGroup CreateDropdownGroup1 ()
139 | {
140 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
141 | ret.Label = "I will be back";
142 | return ret;
143 | }
144 |
145 | private RibbonGroup CreateGroup2 ()
146 | {
147 | Gallery gallery = new Gallery ();
148 | gallery.AppendTile (new SampleTile ("1"));
149 | gallery.AppendTile (new SampleTile ("2"));
150 | gallery.AppendTile (new SampleTile ("3"));
151 | gallery.AppendTile (new SampleTile ("4"));
152 | gallery.AppendTile (new SampleTile ("5"));
153 |
154 | RibbonGroup group2 = new RibbonGroup ();
155 | group2.Label = "Gallery";
156 | group2.Child = gallery;
157 |
158 | return group2;
159 | }
160 |
161 | private DropdownRibbonGroup CreateDropdownGroup2 ()
162 | {
163 | DropdownRibbonGroup ret = new DropdownRibbonGroup ();
164 | ret.Label = "Gallery";
165 | return ret;
166 | }
167 |
168 | private void onClick (object Sender, EventArgs e)
169 | {
170 | Dialog d = new Dialog ("Test", this, DialogFlags.DestroyWithParent);
171 | d.Modal = true;
172 | d.AddButton ("Close", ResponseType.Close);
173 | d.Run ();
174 | d.Destroy ();
175 | }
176 |
177 | [GLib.ConnectBefore]
178 | private void Window_OnExpose (object sender, ExposeEventArgs args)
179 | {
180 | Gdk.EventExpose evnt = args.Event;
181 | Context cr = Gdk.CairoHelper.Create (GdkWindow);
182 |
183 | /*if(composeAvailable)
184 | cr.SetSourceRGBA (0, 0, 0, 0.3);
185 | else*/
186 | cr.SetSourceRGB (0.6, 0.6, 0.6);
187 |
188 | //cr.SetSourceRGB (0.749, 0.859, 1.0);
189 |
190 | cr.Operator = Operator.Source;
191 | cr.Paint ();
192 |
193 | ((IDisposable)cr.Target).Dispose();
194 | ((IDisposable)cr).Dispose();
195 |
196 | args.RetVal = false;
197 | }
198 |
199 | private void Window_OnScreenChanged (object Send, ScreenChangedArgs args)
200 | {
201 | Gdk.Colormap cm = Screen.RgbaColormap;
202 | composeAvailable = cm != null; // FIX: Do not seem to detect compose support in all cases
203 |
204 | if(!composeAvailable) cm = Screen.RgbColormap;
205 | Colormap = cm;
206 |
207 | Console.WriteLine ("Compose Support: " + composeAvailable);
208 | }
209 |
210 | private void Window_OnDelete (object send, DeleteEventArgs args)
211 | {
212 | Application.Quit ();
213 | args.RetVal = true;
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/doc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ribbon Lib
4 | Widgets
5 | Ribbon
6 |
7 | - Ribbon: this is the main widget ribbon.
8 | - RibbonGroup: groups several widgets with common functionalities.
9 | - DropDownRibbonGroup (new 2008!): a toggle button replacing a ribbon group when space is too constrained.
10 |
11 | - QuickAccessToolbar (new 2008!): displays several widgets (typical shortcuts to common functionalities) next to the application button.
12 | - VariantsCombinaisonSwitcher (new 2008!): selects a certain VariantsCombinaison based on space constraints.
13 |
14 |
15 | Application Menu
16 |
17 | - ApplicationButton (new 2008!): a button used to display the application menu. This button has a theme different than all other buttons.
18 | - ApplicationMenu (new 2008!): the main menu of an application, displaying application-level commands, and documents list.
19 | - ApplicationMenuItem (new 2008!): single item to be displayed in the application menu.
20 |
21 | Common widgets
22 |
23 | - Button: a simple button with optional drop down menu.
24 | - ToggleButton: a button that remain pressed when activated by the user.
25 | - ToolPack: packs several buttons together.
26 | - ToolBox: displays several widgets in one or several rows depending on allocated space.
27 |
28 | - Gallery: displays several options to the user as thumbnails.
29 | - Tile: a single option made available by a gallery
30 |
31 | Issues
32 | Size negotiations
33 | The Gtk+ layout system processes in two passes: 1) size request 2) size allocation. However, in most widgets, it would be great to negotiate the size request based on size constraints (i.e. given a specific height constraint, return a width request). Currently, HeightRequest and WidthRequest properties are often used to bypass this.
34 | Transparency
35 | The Ribbon specification requires many widgets to be transparent. However, the Gtk+ officialy requires a 'composited' desktop to support this. Nevertheless, composited desktop is still rare. In addition, the implementation of key tips requires to be able to display tiny labels on top of all widgets, and regardless of widgets' boundaries (most key tip must be displayed between two adjacent widgets). This would require many small windows to be created, or a single transparent one to be created. Currently, all widgets are used in window-less mode. Consequently, they all share the same window. However, it also disrupts the dispatchs of Gtk+ events. That's why the Ribbon library contains the SyntheticWindow class, which takes care of dispatching events to window-less widgets.
36 | Key bindings
37 | The Ribbon library must be able to retrieve the keyboard shortcut of accelerators in order to display the key associated to each widget. The solution to this problem is still obscure.
38 | Windows' drop shadow
39 | We should have the ability to disable drop shadow on certain window because it breaks the visual style of the Ribbon.
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------