public bool Run(SelectFileDialogData data) { using (var panel = CreatePanel(data, out var saveState)) { if (panel.RunModal() == 0) { DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); return(false); } data.SelectedFiles = GetSelectedFiles(panel); DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); return(true); } }
public bool Run(AddFileDialogData data) { using (var panel = CreatePanel(data, out NSPopUpButton popup)) { if (panel.RunModal() == 0) { DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); return(false); } data.SelectedFiles = MacSelectFileDialogHandler.GetSelectedFiles(panel); var idx = popup.IndexOfSelectedItem - 2; if (idx >= 0) { data.OverrideAction = data.BuildActions[idx]; } DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); return(true); } }
public bool Run(OpenFileDialogData data) { try { using (var panel = CreatePanel(data, out var state)) { bool pathAlreadySet = false; panel.DidChangeToDirectory += (sender, e) => { var directoryPath = e.NewDirectoryUrl?.AbsoluteString; if (string.IsNullOrEmpty(directoryPath)) { return; } var selectedPath = data.OnDirectoryChanged(this, directoryPath); if (selectedPath.IsNull) { return; } data.SelectedFiles = new FilePath [] { selectedPath }; pathAlreadySet = true; // We need to call Cancel on 1ms delay so it's executed after DidChangeToDirectory event handler is finished // this is needed because it's possible that DidChangeToDirectory event is executed while dialog is opening // in that case calling .Cancel() leaves dialog in weird state... // Fun fact: DidChangeToDirectory event is called from Open on 10.12 but not on 10.13 System.Threading.Tasks.Task.Delay(1).ContinueWith(delegate { panel.Cancel(panel); }, Runtime.MainTaskScheduler); }; panel.SelectionDidChange += delegate { var selection = MacSelectFileDialogHandler.GetSelectedFiles(panel); bool slnViewerSelected = false; if (state.ViewerSelector != null) { slnViewerSelected = FillViewers(state.CurrentViewers, state.ViewerSelector, state.CloseSolutionButton, selection); if (state.CloseSolutionButton != null) { state.CloseSolutionButton.Enabled = slnViewerSelected; state.CloseSolutionButton.State = slnViewerSelected ? NSCellStateValue.On : NSCellStateValue.Off; } } if (state.EncodingSelector != null) { state.EncodingSelector.Enabled = !slnViewerSelected; } }; if (panel.RunModal() == 0 && !pathAlreadySet) { DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); return(false); } if (!pathAlreadySet) { data.SelectedFiles = MacSelectFileDialogHandler.GetSelectedFiles(panel); } if (state.EncodingSelector != null) { data.Encoding = state.EncodingSelector.SelectedEncodingId > 0 ? Encoding.GetEncoding(state.EncodingSelector.SelectedEncodingId) : null; } if (state.ViewerSelector != null) { if (state.CloseSolutionButton != null) { data.CloseCurrentWorkspace = state.CloseSolutionButton.State != NSCellStateValue.Off; } data.SelectedViewer = state.ViewerSelector.IndexOfSelectedItem >= 0 ? state.CurrentViewers [(int)state.ViewerSelector.IndexOfSelectedItem] : null; } DesktopService.FocusWindow(data.TransientFor ?? MessageService.RootWindow); } } catch (Exception ex) { LoggingService.LogInternalError("Error in Open File dialog", ex); } return(true); }
public bool Run(AlertDialogData data) { using (var alert = new NSAlert()) { alert.Window.Title = data.Title ?? BrandingService.ApplicationName; IdeTheme.ApplyTheme(alert.Window); bool stockIcon; if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Error || data.Message.Icon == Gtk.Stock.DialogError) { alert.AlertStyle = NSAlertStyle.Critical; stockIcon = true; } else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Warning || data.Message.Icon == Gtk.Stock.DialogWarning) { alert.AlertStyle = NSAlertStyle.Critical; stockIcon = true; } else { alert.AlertStyle = NSAlertStyle.Informational; stockIcon = data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information; } if (!stockIcon && !string.IsNullOrEmpty(data.Message.Icon)) { var img = ImageService.GetIcon(data.Message.Icon, Gtk.IconSize.Dialog); // HACK: The icon is not rendered in dark mode (VibrantDark or DarkAqua) correctly. // Use light variant and reder it here. // TODO: Recheck rendering issues with DarkAqua on final Mojave if (IdeTheme.UserInterfaceTheme == Theme.Dark) { alert.Icon = img.WithStyles("-dark").ToBitmap(GtkWorkarounds.GetScaleFactor()).ToNSImage(); } else { alert.Icon = img.ToNSImage(); } } else { //for some reason the NSAlert doesn't pick up the app icon by default alert.Icon = NSApplication.SharedApplication.ApplicationIconImage; } alert.MessageText = data.Message.Text; int accessoryViewItemsCount = data.Options.Count; string secondaryText = data.Message.SecondaryText ?? string.Empty; if (TryGetMessageView(secondaryText, out NSView messageView)) { accessoryViewItemsCount++; } else { alert.InformativeText = secondaryText; } var accessoryViews = accessoryViewItemsCount > 0 ? new NSView [accessoryViewItemsCount] : null; int accessoryViewsIndex = 0; if (messageView != null) { accessoryViews [accessoryViewsIndex++] = messageView; } var buttons = data.Buttons.Reverse().ToList(); for (int i = 0; i < buttons.Count - 1; i++) { if (i == data.Message.DefaultButton) { var next = buttons[i]; for (int j = buttons.Count - 1; j >= i; j--) { var tmp = buttons[j]; buttons[j] = next; next = tmp; } break; } } var wrappers = new List <AlertButtonWrapper> (buttons.Count); foreach (var button in buttons) { var label = button.Label; if (button.IsStockButton) { label = Gtk.Stock.Lookup(label).Label; } label = label.Replace("_", ""); //this message seems to be a standard Mac message since alert handles it specially if (button == AlertButton.CloseWithoutSave) { label = GettextCatalog.GetString("Don't Save"); } var nsbutton = alert.AddButton(label); var wrapperButton = new AlertButtonWrapper(nsbutton, data.Message, button, alert); wrappers.Add(wrapperButton); nsbutton.Target = wrapperButton; nsbutton.Action = new ObjCRuntime.Selector("buttonActivatedAction"); } NSButton [] optionButtons = null; if (data.Options.Count > 0) { optionButtons = new NSButton [data.Options.Count]; for (int i = data.Options.Count - 1; i >= 0; i--) { var option = data.Options[i]; var button = new NSButton { Title = option.Text, Tag = i, State = option.Value? NSCellStateValue.On : NSCellStateValue.Off, }; button.SetButtonType(NSButtonType.Switch); button.SizeToFit(); optionButtons [i] = button; accessoryViews [accessoryViewsIndex++] = button; } } var accessoryView = ArrangeAccessoryViews(accessoryViews); if (accessoryView != null) { alert.AccessoryView = accessoryView; } NSButton applyToAllCheck = null; if (data.Message.AllowApplyToAll) { alert.ShowsSuppressionButton = true; applyToAllCheck = alert.SuppressionButton; applyToAllCheck.Title = GettextCatalog.GetString("Apply to all"); } // Hack up a slightly wider than normal alert dialog. I don't know how to do this in a nicer way // as the min size constraints are apparently ignored. var frame = alert.Window.Frame; alert.Window.SetFrame(new CGRect(frame.X, frame.Y, NMath.Max(frame.Width, 600), frame.Height), true); alert.Layout(); bool completed = false; if (data.Message.CancellationToken.CanBeCanceled) { data.Message.CancellationToken.Register(delegate { alert.InvokeOnMainThread(() => { if (!completed) { if (alert.Window.IsSheet && alert.Window.SheetParent != null) { alert.Window.SheetParent.EndSheet(alert.Window); } else { NSApplication.SharedApplication.AbortModal(); } } }); }); } int response = -1000; var parent = data.TransientFor ?? IdeApp.Workbench.RootWindow; NSWindow nativeParent; try { nativeParent = parent; } catch (NotSupportedException) { nativeParent = null; } if (!data.Message.CancellationToken.IsCancellationRequested) { // sheeting is broken on High Sierra with dark NSAppearance var sheet = IdeTheme.UserInterfaceTheme != Theme.Dark || MacSystemInformation.OsVersion != MacSystemInformation.HighSierra; // We have an issue with accessibility when using sheets, so disable it here sheet &= !DesktopService.AccessibilityInUse; if (!sheet || nativeParent == null) { // Force the alert window to be focused for accessibility NSApplication.SharedApplication.AccessibilityFocusedWindow = alert.Window; alert.Window.AccessibilityFocused = true; if (nativeParent != null) { nativeParent.AccessibilityFocused = false; } alert.Window.ReleasedWhenClosed = true; response = (int)alert.RunModal(); // Focus the old window NSApplication.SharedApplication.AccessibilityFocusedWindow = nativeParent; } else { alert.BeginSheet(nativeParent, (modalResponse) => { response = (int)modalResponse; NSApplication.SharedApplication.StopModal(); }); NSApplication.SharedApplication.RunModalForWindow(alert.Window); } } var result = response - (long)(int)NSAlertButtonReturn.First; completed = true; if (result >= 0 && result < buttons.Count) { data.ResultButton = buttons [(int)result]; } else { data.ResultButton = null; } if (data.ResultButton == null || data.Message.CancellationToken.IsCancellationRequested) { data.SetResultToCancelled(); } if (optionButtons != null) { foreach (var button in optionButtons) { var option = data.Options[(int)button.Tag]; data.Message.SetOptionValue(option.Id, button.State != 0); } } if (applyToAllCheck != null && applyToAllCheck.State != 0) { data.ApplyToAll = true; } if (nativeParent != null) { nativeParent.MakeKeyAndOrderFront(nativeParent); } else { DesktopService.FocusWindow(parent); } } return(true); }