60
61
internal const int DataItemColumn = 3;
61
62
internal const int BuilderChainColumn = 4;
62
63
internal const int FilledColumn = 5;
64
internal const int ShowPopupColumn = 6;
64
66
NodeBuilder[] builders;
65
67
Dictionary<Type, NodeBuilder[]> builderChains = new Dictionary<Type, NodeBuilder[]> ();
66
68
NodeHashtable nodeHash = new NodeHashtable ();
68
70
ExtensibleTreeViewTree tree;
69
71
Gtk.TreeStore store;
70
internal Gtk.TreeViewColumn complete_column;
71
internal ZoomableCellRendererPixbuf pix_render;
72
internal Gtk.CellRendererText text_render;
72
Gtk.TreeViewColumn complete_column;
73
ZoomableCellRendererPixbuf pix_render;
74
CustomCellRendererText text_render;
73
75
TreeBuilderContext builderContext;
74
76
Hashtable callbacks = new Hashtable ();
75
77
bool editingText = false;
76
int customFontSize = -1;
78
bool showSelectionPopupButton;
79
Gtk.TreeIter? lastPopupButtonIter;
78
81
TreePadOption[] options;
79
82
TreeOptions globalOptions;
120
123
Initialize (builders, options);
123
void CustomFontPropertyChanged (object sender, MonoDevelop.Core.PropertyChangedEventArgs prop)
126
void CustomFontPropertyChanged (object sender, EventArgs a)
125
string val = (string)prop.NewValue;
126
string name = !string.IsNullOrEmpty (val) ? val : tree.Style.FontDescription.ToString ();
127
UpdateCustomFont (name);
130
void UpdateCustomFont (string name)
132
Pango.FontDescription customFont = Pango.FontDescription.FromString (name);
133
customFontSize = customFont.Size;
135
customFont.Size = (int) (((double) customFont.Size) * Zoom);
136
text_render.Family = customFont.Family;
137
text_render.Size = customFont.Size;
138
customFont.Dispose ();
133
text_render.CustomFont = IdeApp.Preferences.CustomPadFont ?? tree.Style.FontDescription;
139
134
tree.ColumnsAutosize ();
142
137
protected override void OnStyleSet (Gtk.Style previous_style)
144
139
base.OnStyleSet (previous_style);
145
UpdateCustomFont (IdeApp.Preferences.CustomPadFont ?? tree.Style.FontDescription.ToString ());
148
143
public void Initialize (NodeBuilder[] builders, TreePadOption[] options)
404
394
return foundHandler;
398
void HandleButtonPressEvent (object o, Gtk.ButtonPressEventArgs args)
400
if (ShowSelectionPopupButton && text_render.PointerInButton ((int)args.Event.XRoot, (int)args.Event.YRoot)) {
401
text_render.Pushed = true;
403
var menu = CreateContextMenu ();
405
menu.Hidden += HandleMenuHidden;
406
GtkWorkarounds.ShowContextMenu (menu, tree, text_render.PopupAllocation);
412
void HandleMotionNotifyEvent (object o, Gtk.MotionNotifyEventArgs args)
414
if (ShowSelectionPopupButton) {
415
text_render.PointerPosition = new Gdk.Point ((int)args.Event.XRoot, (int)args.Event.YRoot);
417
if (tree.GetPathAtPos ((int)args.Event.X, (int)args.Event.Y, out path)) {
418
var area = tree.GetCellArea (path, tree.Columns[0]);
419
tree.QueueDrawArea (area.X, area.Y, area.Width, area.Height);
425
void HandleLeaveNotifyEvent (object o, Gtk.LeaveNotifyEventArgs args)
430
void HandleMenuHidden (object sender, EventArgs e)
432
((Gtk.Menu)sender).Hidden -= HandleMenuHidden;
433
text_render.Pushed = false;
407
437
internal void LockUpdates ()
409
439
if (++updateLockCount == 1)
1680
1782
opset.AddItem (ViewCommands.TreeDisplayOptionList);
1681
1783
opset.AddItem (Command.Separator);
1682
1784
opset.AddItem (ViewCommands.ResetTreeDisplayOptions);
1683
IdeApp.CommandService.ShowContextMenu (this, evt, opset, this);
1785
return IdeApp.CommandService.CreateMenu (opset, this);
1686
1789
ExtensionContext ctx = AddinManager.CreateExtensionContext ();
1687
1790
ctx.RegisterCondition ("ItemType", new ItemTypeCondition (tnav.DataItem.GetType (), contextMenuTypeNameAliases));
1688
1791
CommandEntrySet eset = IdeApp.CommandService.CreateCommandEntrySet (ctx, menuPath);
1690
1793
eset.AddItem (Command.Separator);
1691
CommandEntrySet opset = eset.AddItemSet (GettextCatalog.GetString ("Display Options"));
1692
opset.AddItem (ViewCommands.TreeDisplayOptionList);
1693
opset.AddItem (Command.Separator);
1694
opset.AddItem (ViewCommands.ResetTreeDisplayOptions);
1695
opset.AddItem (ViewCommands.RefreshTree);
1696
opset.AddItem (ViewCommands.CollapseAllTreeNodes);
1697
IdeApp.CommandService.ShowContextMenu (this, evt, eset, this);
1794
if (!tnav.Clone ().MoveToParent ()) {
1795
CommandEntrySet opset = eset.AddItemSet (GettextCatalog.GetString ("Display Options"));
1796
opset.AddItem (ViewCommands.TreeDisplayOptionList);
1797
opset.AddItem (Command.Separator);
1798
opset.AddItem (ViewCommands.ResetTreeDisplayOptions);
1799
// opset.AddItem (ViewCommands.CollapseAllTreeNodes);
1801
eset.AddItem (ViewCommands.RefreshTree);
1802
return IdeApp.CommandService.CreateMenu (eset, this);
1701
1806
[CommandUpdateHandler (ViewCommands.TreeDisplayOptionList)]
1702
1807
protected void BuildTreeOptionsMenu (CommandArrayInfo info)
1704
ITreeNavigator tnav = GetSelectedNode ();
1705
1809
foreach (TreePadOption op in options) {
1706
1810
CommandInfo ci = new CommandInfo (op.Label);
1707
1811
ci.Checked = globalOptions [op.Id];
1713
1817
protected void OptionToggled (string optionId)
1715
1819
globalOptions [optionId] = !globalOptions [optionId];
1719
1823
[CommandHandler (ViewCommands.ResetTreeDisplayOptions)]
1720
1824
protected void ResetOptions ()
1722
foreach (TreeNodeNavigator node in GetSelectedNodes ()) {
1723
Gtk.TreeIter it = node.CurrentPosition._iter;
1724
if (store.IterIsValid (it)) {
1725
ITreeBuilder tb = CreateBuilder (it);
1731
[CommandHandler (ViewCommands.RefreshTree)]
1826
foreach (TreePadOption op in options)
1827
globalOptions [op.Id] = op.DefaultValue;
1832
void RefreshRoots ()
1835
if (!store.GetIterFirst (out it))
1838
ITreeBuilder tb = CreateBuilder (it);
1840
} while (store.IterNext (ref it));
1732
1843
protected void RefreshTree ()
1734
1845
foreach (TreeNodeNavigator node in GetSelectedNodes ()) {
1826
1945
ActivateCurrentItem ();
1948
void UpdateSelectionPopupButton ()
1953
if (lastPopupButtonIter != null) {
1954
if (store.IterIsValid (lastPopupButtonIter.Value))
1955
tree.Model.SetValue (lastPopupButtonIter.Value, ShowPopupColumn, false);
1956
lastPopupButtonIter = null;
1959
if (showSelectionPopupButton) {
1960
var sel = Tree.Selection.GetSelectedRows ();
1961
if (sel.Length > 0) {
1963
if (store.GetIter (out it, sel[0])) {
1964
lastPopupButtonIter = it;
1965
tree.Model.SetValue (it, ShowPopupColumn, true);
1829
1971
protected virtual void OnSelectionChanged (object sender, EventArgs args)
1973
UpdateSelectionPopupButton ();
1831
1975
TreeNodeNavigator node = (TreeNodeNavigator) GetSelectedNode ();
1832
1976
if (node != null) {
1833
1977
NodeBuilder[] chain = node.NodeBuilderChain;
2241
class CustomCellRendererText: Gtk.CellRendererText
2244
Pango.Layout layout;
2245
Pango.FontDescription scaledFont, customFont;
2247
static Gdk.Pixbuf popupIcon;
2248
static Gdk.Pixbuf popupIconDown;
2249
static Gdk.Pixbuf popupIconHover;
2251
ExtensibleTreeView parent;
2252
Gdk.Rectangle buttonScreenRect;
2253
Gdk.Rectangle buttonAllocation;
2256
public bool Pushed { get; set; }
2258
//using this instead of FontDesc property, FontDesc seems to be broken
2259
public Pango.FontDescription CustomFont {
2264
if (scaledFont != null) {
2265
scaledFont.Dispose ();
2272
static CustomCellRendererText ()
2274
popupIcon = Gdk.Pixbuf.LoadFromResource ("tree-popup-button.png");
2275
popupIconDown = Gdk.Pixbuf.LoadFromResource ("tree-popup-button-down.png");
2276
popupIconHover = Gdk.Pixbuf.LoadFromResource ("tree-popup-button-hover.png");
2279
[GLib.Property ("text-markup")]
2280
public string TextMarkup {
2281
get { return markup; }
2282
set { Markup = markup = value; }
2285
[GLib.Property ("show-popup-button")]
2286
public bool ShowPopupButton { get; set; }
2288
public CustomCellRendererText (ExtensibleTreeView parent)
2290
this.parent = parent;
2293
protected override void Render (Gdk.Drawable window, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, Gtk.CellRendererState flags)
2295
Gtk.StateType st = Gtk.StateType.Normal;
2296
if ((flags & Gtk.CellRendererState.Prelit) != 0)
2297
st = Gtk.StateType.Prelight;
2298
if ((flags & Gtk.CellRendererState.Focused) != 0)
2299
st = Gtk.StateType.Normal;
2300
if ((flags & Gtk.CellRendererState.Insensitive) != 0)
2301
st = Gtk.StateType.Insensitive;
2302
if ((flags & Gtk.CellRendererState.Selected) != 0)
2303
st = widget.HasFocus ? Gtk.StateType.Selected : Gtk.StateType.Active;
2305
if (scaledFont == null) {
2306
if (scaledFont != null)
2307
scaledFont.Dispose ();
2308
scaledFont = (customFont ?? parent.Style.FontDesc).Copy ();
2309
scaledFont.Size = (int)(customFont.Size * Zoom);
2311
layout.FontDescription = scaledFont;
2314
if (layout == null || layout.Context != widget.PangoContext) {
2317
layout = new Pango.Layout (widget.PangoContext);
2318
layout.FontDescription = scaledFont;
2321
layout.SetMarkup (TextMarkup);
2324
layout.GetPixelSize (out w, out h);
2326
int tx = cell_area.X + (int) Xpad;
2327
int ty = cell_area.Y + (cell_area.Height - h) / 2;
2329
window.DrawLayout (widget.Style.TextGC (st), tx, ty, layout);
2331
if (ShowPopupButton) {
2334
((Gtk.ScrolledWindow)widget.Parent).Hadjustment.ValueChanged += delegate {
2335
foreach (var r in parent.Tree.Selection.GetSelectedRows ()) {
2336
var rect = parent.Tree.GetCellArea (r, parent.Tree.Columns[0]);
2337
parent.Tree.QueueDrawArea (rect.X, rect.Y, rect.Width, rect.Height);
2342
if ((flags & Gtk.CellRendererState.Selected) != 0) {
2343
var icon = Pushed ? popupIconDown : popupIcon;
2344
var dy = (cell_area.Height - icon.Height) / 2;
2345
var y = cell_area.Y + dy;
2346
var x = cell_area.X + cell_area.Width - icon.Width - dy;
2348
var sw = (Gtk.ScrolledWindow) widget.Parent;
2350
sw.GdkWindow.GetOrigin (out ox, out oy);
2351
sw.GdkWindow.GetSize (out ow, out oh);
2352
ox += sw.Allocation.X;
2353
oy += sw.Allocation.Y;
2354
if (sw.VScrollbar.Visible)
2355
ow -= sw.VScrollbar.Allocation.Width;
2358
((Gdk.Window)window).GetOrigin (out cx, out cy);
2359
((Gdk.Window)window).GetSize (out cw, out ch);
2360
cx += widget.Allocation.X;
2361
cy += widget.Allocation.Y;
2364
int diff = rp - (cx + cw);
2368
if (x < cell_area.X + 20)
2369
x = cell_area.X + 20;
2372
buttonScreenRect = new Gdk.Rectangle (cx + x, cy + y, popupIcon.Width, popupIcon.Height);
2374
buttonAllocation = new Gdk.Rectangle (x, y, popupIcon.Width, popupIcon.Height);
2375
buttonAllocation = GtkUtil.ToScreenCoordinates (widget, ((Gdk.Window)window), buttonAllocation);
2376
buttonAllocation = GtkUtil.ToWindowCoordinates (widget, widget.GdkWindow, buttonAllocation);
2378
bool mouseOver = (flags & Gtk.CellRendererState.Prelit) != 0 && buttonScreenRect.Contains (PointerPosition);
2379
if (mouseOver && !Pushed)
2380
icon = popupIconHover;
2382
using (var ctx = Gdk.CairoHelper.Create (window)) {
2383
Gdk.CairoHelper.SetSourcePixbuf (ctx, icon, x, y);
2390
public double Zoom {
2395
if (scaledFont != null) {
2396
scaledFont.Dispose ();
2403
public bool PointerInButton (int px, int py)
2405
return buttonScreenRect.Contains (px, py);
2408
public Gdk.Point PointerPosition { get; set; }
2410
public Gdk.Rectangle PopupAllocation {
2411
get { return buttonAllocation; }
2414
protected override void OnDestroyed ()
2416
base.OnDestroyed ();
2417
if (scaledFont != null)
2418
scaledFont.Dispose ();
2080
2425
class NodeCommandTargetChain: ICommandDelegatorRouter