Skip to content

Commit

Permalink
Add Mac implementation for DropDownToolItem
Browse files Browse the repository at this point in the history
- Add ShowDropArrow for all platforms, and ensure it updates at runtime
- Mac has two implementations, one that uses NSSegmentedControl (10.14 and earlier) and another that uses NSMenuToolbarItem (10.15 and later)
  • Loading branch information
cwensley committed Sep 21, 2022
1 parent 80bff28 commit 56c893b
Show file tree
Hide file tree
Showing 17 changed files with 356 additions and 50 deletions.
2 changes: 1 addition & 1 deletion lib/monomac
Submodule monomac updated 1 files
+25 −0 src/appkit.cs
31 changes: 24 additions & 7 deletions src/Eto.Gtk/Forms/ToolBar/DropDownToolItemHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,23 @@ public class DropDownToolItemHandler : ToolItemHandler<Gtk.ToggleToolButton, Dro
// add a drop arrow to the button text.

private Gtk.Menu dropMenu;

bool showDropArrow = true;

public DropDownToolItemHandler()
{
dropMenu = new Gtk.Menu();
}

#region IToolBarButton Members


#endregion

public override void CreateControl(ToolBarHandler handler, int index)
{
Gtk.Toolbar tb = handler.Control;

var buttonText = ShowDropArrow ? Text + "" : Text;
Control = new Gtk.ToggleToolButton();
Control.Label = buttonText;
Control.IconWidget = GtkImage;
Control.IsImportant = true;
Control.Sensitive = Enabled;
Expand All @@ -42,12 +41,30 @@ public override void CreateControl(ToolBarHandler handler, int index)
tb.Insert(Control, index);
Control.Clicked += HandleClicked;
dropMenu.Hidden += HandleMenuClosed;
SetText();
}

protected override void SetText()
{
if (Control != null)
Control.Label = ShowDropArrow ? Text + "" : Text;
}

/// <summary>
/// Gets or sets whether the drop arrow is shown on the button.
/// </summary>
public bool ShowDropArrow { get; set; } = true;
public bool ShowDropArrow
{
get => showDropArrow;
set
{
if (showDropArrow != value)
{
showDropArrow = value;
SetText();
}
}
}

#if GTKCORE
private void HandleClicked(object sender, EventArgs e)
Expand Down Expand Up @@ -108,7 +125,7 @@ public void HandleClicked(object sender, EventArgs e)
public void AddMenu(int index, MenuItem item)
{
dropMenu.Insert((Gtk.Widget)item.ControlObject, index);
var handler = item.Handler as Menu.IMenuHandler;
var handler = item.Handler as Menu.IMenuHandler;
//SetChildAccelGroup(item);
}

Expand Down
42 changes: 39 additions & 3 deletions src/Eto.Gtk/Forms/ToolBar/ToolItemHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,56 @@ public interface IToolBarItemHandler
}

public abstract class ToolItemHandler<TControl, TWidget> : WidgetHandler<TControl, TWidget>, ToolItem.IHandler, IToolBarItemHandler
where TControl: Gtk.Widget
where TControl: Gtk.ToolItem
where TWidget: ToolItem
{
bool enabled = true;
bool visible = true;
string text;
string toolTip;
Image image;

protected Gtk.Image GtkImage { get; set; }

public abstract void CreateControl(ToolBarHandler handler, int index);

public string Text { get; set; }
public string Text
{
get => text;
set
{
if (text != value)
{
text = value;
SetText();
}
}
}

public virtual string ToolTip
{
get => toolTip;
set
{
if (toolTip != value)
{
toolTip = value;
SetToolTip();
}
}
}

protected virtual void SetText()
{
if (Control is Gtk.ToolButton button)
button.Label = Text;
}

public string ToolTip { get; set; }
protected virtual void SetToolTip()
{
if (Control is Gtk.ToolButton button)
button.TooltipText = ToolTip;
}

public Image Image
{
Expand Down
1 change: 1 addition & 0 deletions src/Eto.Mac/Eto.Mac64.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ You do not need to use any of the classes of this assembly (unless customizing t
<Using Include="System.Double" Alias="nfloat" />
<Using Include="System.Int64" Alias="nint" />
<Using Include="System.UInt64" Alias="nuint" />
<Using Include="System.IntPtr" Alias="NativeHandle" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions src/Eto.Mac/Eto.XamMac2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<Using Include="CoreFoundation" />
<Using Include="ImageIO" />
<Using Include="CoreText" />
<Using Include="System.IntPtr" Alias="NativeHandle" />
</ItemGroup>

<PropertyGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/Eto.Mac/Forms/Controls/SegmentedButtonHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,9 @@ public void InsertItem(int index, SegmentedItem item)
static readonly IntPtr selSetShowsMenuIndicator = Selector.GetHandle("setShowsMenuIndicator:forSegment:");

// 10.13+
static readonly bool supportsTooltip = ObjCExtensions.InstancesRespondToSelector<NSSegmentedCell>(selSetToolTipForSegment);
static readonly bool supportsMenuIndicator = ObjCExtensions.InstancesRespondToSelector<NSSegmentedControl>(selSetShowsMenuIndicator);

internal static readonly bool supportsTooltip = ObjCExtensions.InstancesRespondToSelector<NSSegmentedCell>(selSetToolTipForSegment);
internal static readonly bool supportsMenuIndicator = ObjCExtensions.InstancesRespondToSelector<NSSegmentedControl>(selSetShowsMenuIndicator);
public void SetItem(int index, SegmentedItem item)
{
Control.SetLabel(item.Text ?? string.Empty, index);
Expand Down
9 changes: 9 additions & 0 deletions src/Eto.Mac/Forms/Menu/MenuHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public interface IMenuHandler
public class EtoMenu : NSMenu
{
public bool WorksWhenModal { get; set; }

public EtoMenu()
{
}

public EtoMenu(NativeHandle handle)
: base(handle)
{
}
}

static class MenuHandler
Expand Down
85 changes: 85 additions & 0 deletions src/Eto.Mac/Forms/ToolBar/DropDownToolItemHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using Eto.Drawing;
using Eto.Forms;

namespace Eto.Mac.Forms.ToolBar
{
public class DropDownToolItemHandler : ToolItemHandler<NSMenuToolbarItem, DropDownToolItem>, DropDownToolItem.IHandler
{
NSMenu menu;

protected override bool UseButtonStyle => false;
protected override bool UseAction => false;

#if MACOS || XAMMAC2
static readonly IntPtr selInitWithItemIdentifier_Handle = Selector.GetHandle("initWithItemIdentifier:");

// constructor with identifier isn't available in the version of macOS workload we need yet..
class EtoMenuToolbarItem : NSMenuToolbarItem
{
public EtoMenuToolbarItem()
{
}

[Export ("initWithItemIdentifier:")]
public EtoMenuToolbarItem (string itemIdentifier)
: base (NSObjectFlag.Empty)
{
NSApplication.EnsureUIThread ();
if (itemIdentifier == null)
throw new ArgumentNullException ("itemIdentifier");
#if USE_CFSTRING
var nsitemIdentifier = CFString.CreateNative(itemIdentifier);
#else
var nsitemIdentifier = NSString.CreateNative(itemIdentifier);
#endif

if (IsDirectBinding) {
Handle = Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, selInitWithItemIdentifier_Handle, nsitemIdentifier);
} else {
Handle = Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, selInitWithItemIdentifier_Handle, nsitemIdentifier);
}
NSString.ReleaseNative (nsitemIdentifier);

}
}

protected override NSMenuToolbarItem CreateControl() => new EtoMenuToolbarItem(Identifier);
#else
protected override NSMenuToolbarItem CreateControl() => new NSMenuToolbarItem(Identifier);
#endif

public bool ShowDropArrow
{
get => Control.ShowsIndicator;
set => Control.ShowsIndicator = value;
}

protected override void Initialize()
{
base.Initialize();
Control.ShowsIndicator = true;
menu = new NSMenu();
menu.AutoEnablesItems = true;
menu.ShowsStateColumn = true;
Control.Menu = menu;
// first item is never shown, it's the "title" of the pull down?? weird.
menu.InsertItem(new NSMenuItem(string.Empty), 0);
}

public void AddMenu(int index, MenuItem item)
{
menu.InsertItem((NSMenuItem)item.ControlObject, index + 1);
}

public void RemoveMenu(MenuItem item)
{
menu.RemoveItem((NSMenuItem)item.ControlObject);
}

public void Clear()
{
menu.RemoveAllItems();
}
}
}
84 changes: 84 additions & 0 deletions src/Eto.Mac/Forms/ToolBar/DropDownToolItemPreCatalinaHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using Eto.Drawing;
using Eto.Forms;
using Eto.Mac.Forms.Controls;
using Eto.Mac.Forms.Menu;

namespace Eto.Mac.Forms.ToolBar
{
/// <summary>
/// Drop down handler pre-catalina. This could probably be done a little better.
/// </summary>
public class DropDownToolItemPreCatalinaHandler : ToolItemHandler<NSToolbarItem, DropDownToolItem>, DropDownToolItem.IHandler
{
ContextMenu contextMenu;
MenuSegmentedItem menuItem;
SegmentedButton segmentedButton;
bool showDropArrow = true;
protected override bool UseButtonStyle => false;

protected override bool IsButton => true;

protected override bool UseAction => false;

public bool ShowDropArrow
{
get => showDropArrow;
set
{
showDropArrow = value;
if (SegmentedButtonHandler.supportsMenuIndicator)
{
var nssegmentedControl = SegmentedButtonHandler.GetControl(segmentedButton);
nssegmentedControl.SetShowsMenuIndicator(value, 0);
}
}
}

protected override void Initialize()
{
contextMenu = new ContextMenu();

menuItem = new MenuSegmentedItem { Menu = contextMenu };

segmentedButton = new SegmentedButton();
segmentedButton.Items.Add(menuItem);

Control.View = segmentedButton.ToNative(true);

base.Initialize();
}

protected override NSMenuItem CreateMenuFormRepresentation()
{
var menu = base.CreateMenuFormRepresentation();
menu.Submenu = contextMenu.ToNS();
return menu;
}

public void AddMenu(int index, MenuItem item)
{
contextMenu.Items.Insert(index, item);
}

public void RemoveMenu(MenuItem item)
{
contextMenu.Items.Remove(item);
}

public void Clear()
{
contextMenu.Items.Clear();
}

protected override void SetImage()
{
base.SetImage();
if (Image is Bitmap bmp)
menuItem.Image = bmp.WithSize(ImageSize, ImageSize);
else if (Image is Icon icon)
menuItem.Image = icon.WithSize(ImageSize, ImageSize);
}

}
}
2 changes: 2 additions & 0 deletions src/Eto.Mac/Forms/ToolBar/SeparatorToolItemHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class SeparatorToolItemHandler : ToolItemHandler<NSToolbarItem, Separator

protected override bool IsButton => false;

protected override bool UseButtonStyle => false;

public override string Identifier
{
get
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Mac/Forms/ToolBar/ToolBarHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ internal int GetIndex(ToolItem item, bool forInsert = false, bool checkVisible =
else if (curitem.Visible)
{
var nativeItem = nativeItems[idx];
if (nativeItem.Identifier == GetIdentifier(curitem))
if (nativeItem.Identifier == GetIdentifier(curitem) || object.Equals(nativeItem, curitem.ControlObject))
idx++;
}
}
Expand Down
Loading

0 comments on commit 56c893b

Please sign in to comment.