2
// CompactToolboxView.cs
5
// Mike Krüger <mkrueger@novell.com>
7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
using System.Collections;
31
using System.Collections.Generic;
35
namespace MonoDevelop.DesignerSupport.Toolbox
37
public class ToolboxObject
43
public Gdk.Pixbuf Icon {
70
public ToolboxObject (Gdk.Pixbuf icon, string text, object tag)
77
public bool FilterItem (string filter)
79
return !String.IsNullOrEmpty (filter) && Text.ToUpper ().IndexOf (filter.ToUpper ()) < 0;
83
public class ToolboxCategory
86
List<ToolboxObject> items = new List<ToolboxObject> ();
97
public List<ToolboxObject> Items {
103
public ToolboxCategory (string name)
108
public bool ContainsIcons (string filter)
110
foreach (ToolboxObject item in Items)
111
if (!item.FilterItem (filter))
117
public class CompactWidget : Gtk.DrawingArea
119
ToolboxObject selectedItem = null;
120
List<ToolboxCategory> categories = new List<ToolboxCategory> ();
122
bool showCategories = true;
123
bool realSizeRequest;
124
const int spacing = 4;
125
const int categoryHeaderSize = 22;
127
public bool ShowCategories {
129
return showCategories;
132
if (this.showCategories != value) {
133
this.showCategories = value;
138
public string Filter {
143
if (filter != value) {
149
public IEnumerable<ToolboxObject> AllItems {
151
foreach (ToolboxCategory category in this.categories) {
152
foreach (ToolboxObject item in category.Items) {
159
public int ItemCount {
162
foreach (ToolboxCategory category in this.categories)
163
result += category.Items.Count;
168
public List<ToolboxCategory> Categories {
174
public ToolboxObject SelectedItem {
179
if (this.selectedItem != value) {
180
this.selectedItem = value;
182
OnSelectedItemChanged (EventArgs.Empty);
187
protected virtual void OnSelectedItemChanged (EventArgs e)
189
if (SelectedItemChanged != null)
190
SelectedItemChanged (this, e);
193
public event EventHandler SelectedItemChanged;
195
public CompactWidget ()
197
this.Events = EventMask.ExposureMask |
198
EventMask.EnterNotifyMask |
199
EventMask.LeaveNotifyMask |
200
EventMask.ButtonPressMask |
201
EventMask.ButtonReleaseMask |
202
EventMask.PointerMotionMask
206
public ToolboxCategory GetCategory (string name)
208
foreach (ToolboxCategory category in this.categories)
209
if (category.Name == name)
211
ToolboxCategory result = new ToolboxCategory (name);
212
this.categories.Add (result);
216
System.Drawing.Size IconSize {
220
foreach (ToolboxObject item in this.AllItems) {
221
width = Math.Max (width, item.Icon.Width);
222
height = Math.Max (height, item.Icon.Height);
224
return new System.Drawing.Size (width, height);
228
protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing e)
230
// Don't clear the selection when clicking on a button
231
if (e.Detail != NotifyType.Ancestor || e.Mode != Gdk.CrossingMode.Grab)
232
ClearMouseOverItem ();
234
//return OnLeaveNotifyEvent (e);
237
protected override void OnSizeRequested (ref Requisition req)
239
if (!realSizeRequest) {
240
// Request a minimal width, to size recalculation infinite loops with
241
// small widths, due to the vscrollbar being shown and hidden.
248
Iterate (ref xpos, ref ypos, null, null);
253
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
255
base.OnSizeAllocated (allocation);
256
if (!realSizeRequest) {
257
realSizeRequest = true;
261
realSizeRequest = false;
264
protected override bool OnButtonPressEvent (Gdk.EventButton e)
266
SelectedItem = mouseOverItem;
267
return base.OnButtonPressEvent (e);
270
ToolboxObject mouseOverItem;
272
delegate void CategoryAction (ToolboxCategory category);
273
delegate void Action (ToolboxObject item);
274
void IterateIcons (IEnumerable<ToolboxObject> collection, ref int xpos, ref int ypos, Action action)
276
foreach (ToolboxObject item in collection) {
277
if (item.FilterItem (filter))
279
if (xpos + IconSize.Width + spacing >= this.GdkWindow.VisibleRegion.Clipbox.Width) {
281
ypos += IconSize.Height + spacing;
285
xpos += IconSize.Width + spacing;
287
ypos += IconSize.Height + spacing;
289
void Iterate (ref int xpos, ref int ypos, CategoryAction catAction, Action action)
291
if (this.showCategories) {
292
foreach (ToolboxCategory category in this.Categories) {
293
if (!category.ContainsIcons (filter))
296
if (catAction != null)
297
catAction (category);
298
ypos += categoryHeaderSize;
299
IterateIcons (category.Items, ref xpos, ref ypos, action);
302
IterateIcons (this.AllItems, ref xpos, ref ypos, action);
306
void ClearMouseOverItem ()
308
if (mouseOverItem != null) {
309
mouseOverItem = null;
310
HideTooltipWindow ();
315
CustomTooltipWindow tooltipWindow = null;
316
public void HideTooltipWindow ()
318
if (tooltipWindow != null) {
319
tooltipWindow.Destroy ();
320
tooltipWindow = null;
323
public void ShowTooltip (string text, int x, int y, int iconWidth)
325
HideTooltipWindow ();
326
tooltipWindow = new CustomTooltipWindow ();
327
tooltipWindow.Tooltip = text;
329
this.GdkWindow.GetOrigin (out ox, out oy);
330
int w = tooltipWindow.Child.SizeRequest().Width;
331
tooltipWindow.Move (ox + x - (w - iconWidth)/2, oy + y);
332
tooltipWindow.ShowAll ();
335
protected override bool OnMotionNotifyEvent (Gdk.EventMotion e)
340
Iterate (ref xpos, ref ypos, null, delegate (ToolboxObject item) {
341
if (xpos <= e.X && e.X <= xpos + IconSize.Width + spacing &&
342
ypos <= e.Y && e.Y <= ypos + IconSize.Height + spacing) {
344
if (mouseOverItem != item) {
345
mouseOverItem = item;
346
ShowTooltip (item.Text, xpos - 2, ypos + IconSize.Height + 3, IconSize.Width + 4);
352
ClearMouseOverItem ();
354
return base.OnMotionNotifyEvent (e);
357
protected override bool OnExposeEvent (Gdk.EventExpose e)
359
Gdk.Window win = e.Window;
360
Gdk.Rectangle area = e.Area;
361
win.DrawRectangle (Style.BaseGC (StateType.Normal), true, area);
365
Iterate (ref xpos, ref ypos,
366
delegate (ToolboxCategory category) {
367
Pango.Layout layout = new Pango.Layout (this.PangoContext);
368
layout.Width = Pango.Units.FromPixels (320);
369
layout.Wrap = Pango.WrapMode.Word;
370
layout.Alignment = Pango.Alignment.Left;
371
layout.FontDescription = Pango.FontDescription.FromString ("Ahafoni CLM Bold 10");
372
layout.SetMarkup (category.Name);
374
win.DrawLayout (Style.ForegroundGC (StateType.Normal), xpos, ypos, layout);
376
delegate (ToolboxObject item) {
377
if (item == selectedItem) {
378
win.DrawRectangle (Style.BaseGC (StateType.Selected),
380
new Gdk.Rectangle (xpos - 1,
383
IconSize.Height + 2));
385
win.DrawPixbuf (this.Style.ForegroundGC (StateType.Normal),
387
xpos + 1 + (IconSize.Width - item.Icon.Width) / 2,
388
ypos + 1 + (IconSize.Height - item.Icon.Height) / 2,
389
item.Icon.Width, item.Icon.Height, Gdk.RgbDither.None, 0, 0);
391
if (item == mouseOverItem) {
392
win.DrawRectangle (Style.DarkGC (StateType.Prelight),
394
new Gdk.Rectangle (xpos - 2,
397
IconSize.Height + 3));
404
public class CompactToolboxView : Gtk.ScrolledWindow
406
CompactWidget compactWidget;
408
public object CurrentlySelected {
410
return compactWidget.SelectedItem != null ? compactWidget.SelectedItem.Tag : null;
414
public bool ShowCategories {
416
return compactWidget.ShowCategories;
419
compactWidget.ShowCategories = value;
422
public string Filter {
424
return compactWidget.Filter;
427
compactWidget.Filter = value;
431
public CompactToolboxView()
433
compactWidget = new CompactWidget ();
435
compactWidget.SelectedItemChanged += delegate {
436
OnSelectionChanged (EventArgs.Empty);
439
this.ShadowType = ShadowType.None;
440
Viewport v = new Viewport ();
442
v.ShadowType = ShadowType.None;
443
v.Add (compactWidget);
444
this.HscrollbarPolicy = PolicyType.Never;
445
this.VscrollbarPolicy = PolicyType.Automatic;
448
public void SetNodes (ICollection nodes)
450
compactWidget.Categories.Clear ();
451
foreach (BaseToolboxNode node in nodes) {
452
ToolboxObject newItem = new ToolboxObject (node.ViewIcon, node.Label, node);
453
if (node is ItemToolboxNode) {
454
ToolboxCategory category = compactWidget.GetCategory (((ItemToolboxNode)node).Category);
455
category.Items.Add (newItem);
461
protected virtual void OnSelectionChanged (EventArgs e)
463
if (this.SelectionChanged != null)
464
this.SelectionChanged (this, e);
467
public event EventHandler SelectionChanged;
470
public class CustomTooltipWindow : Gtk.Window
473
public string Tooltip {
479
label.Markup = tooltip;
483
Label label = new Label ();
484
public CustomTooltipWindow () : base (Gtk.WindowType.Popup)
486
Name = "gtk-tooltips";
493
protected override bool OnExposeEvent (Gdk.EventExpose ev)
495
base.OnExposeEvent (ev);
496
Gtk.Requisition req = SizeRequest ();
497
Gtk.Style.PaintFlatBox (this.Style,
499
Gtk.StateType.Normal,
502
this, "tooltip", 0, 0, req.Width, req.Height);