void SetVisibleCells(params int [] ids) { VisibleCellIds = ids; LastSelectedCell = ids [0]; var visibleCells = new NSPathComponentCell [ids.Length]; for (int n = 0; n < ids.Length; n++) { var cellData = Cells [ids [n]]; // on HighSierra cells can't be reused without breaking the rendering if (MacSystemInformation.OsVersion >= MacSystemInformation.HighSierra || cellData.Cell == null) { cellData.Cell = new NSPathComponentCellFocusable(); } visibleCells [n] = cellData.Cell; switch (ids[n]) { case RunConfigurationIdx: cellData.Cell.AccessibilityTitle = GettextCatalog.GetString("Startup project"); cellData.Cell.AccessibilityHelp = cellData.ToolTip; break; case ConfigurationIdx: cellData.Cell.AccessibilityTitle = GettextCatalog.GetString("Run configuration"); cellData.Cell.AccessibilityHelp = cellData.ToolTip; break; case RuntimeIdx: cellData.Cell.AccessibilityTitle = GettextCatalog.GetString("Runtime"); cellData.Cell.AccessibilityHelp = cellData.ToolTip; break; } } // On HighSierra the NSPathControl doesn't render correctly without a valid URL and // it won't remeasure cells with updated titles, hence we must always update the whole path if (MacSystemInformation.OsVersion >= MacSystemInformation.HighSierra) { var url = string.Empty; for (int n = 0; n < ids.Length; n++) { url += Cells [ids [n]].Title + "/"; } // we need to encode the url, to ensure that NSUrl.FromString doesn't fail for certain configuration names // NOTE: we must use NSString encoding with percent escapes here, System.Uri encoding is different and does not work // in some corner cases. var escapedUri = new NSString("md://configuration/" + url).CreateStringByAddingPercentEscapes(NSStringEncoding.UTF8); Url = NSUrl.FromString(escapedUri); // path items must match the cells, including images for (int n = 0; n < ids.Length; n++) { Cells [ids [n]].UpdatePathItem(PathItems [n]); } } PathComponentCells = visibleCells; UpdateStyle(); AccessibilityChildren = visibleCells; }
void PopupMenuForCell(NSPathComponentCell item) { var componentRect = ((NSPathCell)Cell).GetRect(item, Frame, this); int i = 0; NSMenuItem selectedItem = null; var menu = new NSMenu { AutoEnablesItems = false, ShowsStateColumn = true, Font = NSFont.MenuFontOfSize(12), }; if (item.Identifier == RunConfigurationIdentifier) { if (ActiveRunConfiguration == null) { return; } foreach (var configuration in RunConfigurationModel) { var _configuration = configuration; var menuitem = new NSMenuItem(configuration.DisplayString, (o2, e2) => { ActiveRunConfiguration = runConfigurationModel.First(c => c.OriginalId == _configuration.OriginalId); }) { Enabled = true, IndentationLevel = 1, }; menu.AddItem(menuitem); if (selectedItem == null && configuration.OriginalId == ActiveRunConfiguration.OriginalId) { selectedItem = menuitem; } } } else if (item.Identifier == ConfigurationIdentifier) { if (ActiveConfiguration == null) { return; } foreach (var configuration in ConfigurationModel) { var _configuration = configuration; var menuitem = new NSMenuItem(configuration.DisplayString, (o2, e2) => { ActiveConfiguration = configurationModel.First(c => c.OriginalId == _configuration.OriginalId); }) { Enabled = true, IndentationLevel = 1, }; menu.AddItem(menuitem); if (selectedItem == null && configuration.OriginalId == ActiveConfiguration.OriginalId) { selectedItem = menuitem; } } } else if (item.Identifier == RuntimeIdentifier) { if (ActiveRuntime == null) { return; } using (var activeMutableModel = ActiveRuntime.GetMutableModel()) { foreach (var runtime in RuntimeModel) { NSMenuItem menuitem = null; if (runtime.IsSeparator) { menu.AddItem(NSMenuItem.SeparatorItem); } else { menuitem = CreateMenuItem(menu, runtime); } using (var mutableModel = runtime.GetMutableModel()) { if (selectedItem == null && menuitem != null && mutableModel.DisplayString == activeMutableModel.DisplayString) { selectedItem = menuitem; } } ++i; } } } else { throw new NotSupportedException(); } LastSelectedCell = IndexFromIdentifier(item.Identifier); if (menu.Count > 1) { var offs = new CGPoint(componentRect.Left + 3, componentRect.Top + 3); if (Window?.Screen?.BackingScaleFactor == 2) { offs.Y += 0.5f; // fine tune menu position on retinas } menu.PopUpMenu(selectedItem, offs, this); } }