コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }