예제 #1
0
		public bool Run (AlertDialogData data)
		{
			using (var alert = new NSAlert ()) {
				alert.Window.Title = data.Title ?? BrandingService.ApplicationName;

				if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information) {
					alert.AlertStyle = NSAlertStyle.Critical;
				} else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Warning) {
					alert.AlertStyle = NSAlertStyle.Warning;
				} else { //if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information) {
					alert.AlertStyle = NSAlertStyle.Informational;
				}
				
				//FIXME: use correct size so we don't get horrible scaling?
				if (!string.IsNullOrEmpty (data.Message.Icon)) {
					var pix = ImageService.GetPixbuf (data.Message.Icon, Gtk.IconSize.Dialog);
					byte[] buf = pix.SaveToBuffer ("tiff");
					unsafe {
						fixed (byte* b = buf) {
							alert.Icon = new NSImage (NSData.FromBytes ((IntPtr)b, (uint)buf.Length));
						}
					}
				} 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;
				alert.InformativeText = data.Message.SecondaryText ?? "";
				
				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;
					}
				}
				
				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");

					alert.AddButton (label);
				}
				
				
				NSButton[] optionButtons = null;
				if (data.Options.Count > 0) {
					var box = new MDBox (LayoutDirection.Vertical, 2, 2);
					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);
						optionButtons[i] = button;
						box.Add (new MDAlignment (button, true) { XAlign = LayoutAlign.Begin });
					}
					
					box.Layout ();
					alert.AccessoryView = box.View;
				}
				
				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 = ((NSPanel) alert.Window).Frame;
				((NSPanel) alert.Window).SetFrame (new RectangleF (frame.X, frame.Y, Math.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) {
								NSApplication.SharedApplication.AbortModal ();
							}
						});
					});
				}
				
				if (!data.Message.CancellationToken.IsCancellationRequested) {
					int result = alert.RunModal () - (int)NSAlertButtonReturn.First;
					completed = true;
					if (result >= 0 && result < buttons.Count) {
						data.ResultButton = buttons [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[button.Tag];
						data.Message.SetOptionValue (option.Id, button.State != 0);
					}
				}
				
				if (applyToAllCheck != null && applyToAllCheck.State != 0)
					data.ApplyToAll = true;
				
				GtkQuartz.FocusWindow (data.TransientFor ?? MessageService.RootWindow);
			}
			
			return true;
		}
예제 #2
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: VK The icon is not rendered in dark style correctly
                    //       Use light variant and reder it here
                    //       as long as NSAppearance.NameVibrantDark is broken
                    if (IdeTheme.UserInterfaceSkin == Skin.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;
                alert.InformativeText = data.Message.SecondaryText ?? "";

                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)
                {
                    var box = new MDBox(LayoutDirection.Vertical, 2, 2);
                    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);
                        optionButtons[i] = button;
                        box.Add(new MDAlignment(button, true)
                        {
                            XAlign = LayoutAlign.Begin
                        });
                    }

                    box.Layout();
                    alert.AccessoryView = box.View;
                }

                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)
                            {
                                NSApplication.SharedApplication.AbortModal();
                            }
                        });
                    });
                }

                if (!data.Message.CancellationToken.IsCancellationRequested)
                {
                    var result = (int)alert.RunModal() - (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;
                }



                GtkQuartz.FocusWindow(data.TransientFor ?? MessageService.RootWindow);
            }

            return(true);
        }
예제 #3
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)
                {
                    if (accessoryViews?[0] == messageView)
                    {
                        accessoryView.SetCustomSpacing(accessoryView.Spacing * 2, messageView);
                        var size = accessoryView.Frame.Size;
                        size.Height += accessoryView.Spacing;
                        accessoryView.SetFrameSize(size);
                    }
                    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;
                if (parent == null && IdeApp.Workbench?.RootWindow?.Visible == true)
                {
                    parent = 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 &= !IdeServices.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
                {
                    IdeServices.DesktopService.FocusWindow(parent);
                }
            }

            return(true);
        }
예제 #4
0
        public bool Run(AlertDialogData data)
        {
            using (var alert = new NSAlert()) {
                if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information)
                {
                    alert.AlertStyle = NSAlertStyle.Critical;
                }
                else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Warning)
                {
                    alert.AlertStyle = NSAlertStyle.Warning;
                }
                else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information)
                {
                    alert.AlertStyle = NSAlertStyle.Informational;
                }

                //FIXME: use correct size so we don't get horrible scaling?
                if (!string.IsNullOrEmpty(data.Message.Icon))
                {
                    var    pix = ImageService.GetPixbuf(data.Message.Icon, Gtk.IconSize.Dialog);
                    byte[] buf = pix.SaveToBuffer("tiff");
                    unsafe
                    {
                        fixed(byte *b = buf)
                        {
                            alert.Icon = new NSImage(NSData.FromBytes((IntPtr)b, (uint)buf.Length));
                        }
                    }
                }

                alert.MessageText     = data.Message.Text;
                alert.InformativeText = data.Message.SecondaryText ?? "";

                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;
                    }
                }

                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");
                    }

                    alert.AddButton(label);
                }


                NSButton[] optionButtons = null;
                if (data.Options.Count > 0)
                {
                    var box = new MDBox(LayoutDirection.Vertical, 2, 2);
                    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);
                        optionButtons[i] = button;
                        box.Add(new MDAlignment(button, true)
                        {
                            XAlign = LayoutAlign.Begin
                        });
                    }

                    box.Layout();
                    alert.AccessoryView = box.View;
                }

                NSButton applyToAllCheck = null;
                if (data.Message.AllowApplyToAll)
                {
                    alert.ShowsSuppressionButton = true;
                    applyToAllCheck       = alert.SuppressionButton;
                    applyToAllCheck.Title = GettextCatalog.GetString("Apply to all");
                }

                alert.Layout();

                int result = alert.RunModal() - (int)NSAlertButtonReturn.First;

                data.ResultButton = buttons [result];

                if (optionButtons != null)
                {
                    foreach (var button in optionButtons)
                    {
                        var option = data.Options[button.Tag];
                        data.Message.SetOptionValue(option.Id, button.State != 0);
                    }
                }

                if (applyToAllCheck != null && applyToAllCheck.State != 0)
                {
                    data.ApplyToAll = true;
                }

                GtkQuartz.FocusWindow(data.TransientFor ?? MessageService.RootWindow);
            }

            return(true);
        }
		public bool Run (AlertDialogData data)
		{
			using (var alert = new NSAlert ()) {
				
				if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information) {
					alert.AlertStyle = NSAlertStyle.Critical;
				} else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Warning) {
					alert.AlertStyle = NSAlertStyle.Warning;
				} else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information) {
					alert.AlertStyle = NSAlertStyle.Informational;
				}
				
				//FIXME: use correct size so we don't get horrible scaling?
				if (!string.IsNullOrEmpty (data.Message.Icon)) {
					var pix = ImageService.GetPixbuf (data.Message.Icon, Gtk.IconSize.Dialog);
					byte[] buf = pix.SaveToBuffer ("tiff");
					unsafe {
						fixed (byte* b = buf) {
							alert.Icon = new NSImage (NSData.FromBytes ((IntPtr)b, (uint)buf.Length));
						}
					}
				}
				
				alert.MessageText = data.Message.Text;
				alert.InformativeText = data.Message.SecondaryText ?? "";
				
				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;
					}
				}
				
				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");
					
					alert.AddButton (label);
				}
				
				
				NSButton[] optionButtons = null;
				if (data.Options.Count > 0) {
					var box = new MDBox (LayoutDirection.Vertical, 2, 2);
					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);
						optionButtons[i] = button;
						box.Add (new MDAlignment (button, true) { XAlign = LayoutAlign.Begin });
					}
					
					box.Layout ();
					alert.AccessoryView = box.View;
				}
				
				NSButton applyToAllCheck = null;
				if (data.Message.AllowApplyToAll) {
					alert.ShowsSuppressionButton = true;
					applyToAllCheck = alert.SuppressionButton;
					applyToAllCheck.Title = GettextCatalog.GetString ("Apply to all");
				}
				
				alert.Layout ();
				
				int result = alert.RunModal () - (int)NSAlertButtonReturn.First;
				
				data.ResultButton = buttons [result];
				
				if (optionButtons != null) {
					foreach (var button in optionButtons) {
						var option = data.Options[button.Tag];
						data.Message.SetOptionValue (option.Id, button.State != 0);
					}
				}
				
				if (applyToAllCheck != null && applyToAllCheck.State != 0)
					data.ApplyToAll = true;
				
				GtkQuartz.FocusWindow (data.TransientFor ?? MessageService.RootWindow);
			}
			
			return true;
		}
예제 #6
0
        public bool Run(AlertDialogData data)
        {
            using (var alert = new NSAlert()) {
                alert.Window.Title = data.Title ?? BrandingService.ApplicationName;

                if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information)
                {
                    alert.AlertStyle = NSAlertStyle.Critical;
                }
                else if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Warning)
                {
                    alert.AlertStyle = NSAlertStyle.Warning;
                }
                else                     //if (data.Message.Icon == MonoDevelop.Ide.Gui.Stock.Information) {
                {
                    alert.AlertStyle = NSAlertStyle.Informational;
                }

                //FIXME: use correct size so we don't get horrible scaling?
                if (!string.IsNullOrEmpty(data.Message.Icon))
                {
                    var    pix = ImageService.GetPixbuf(data.Message.Icon, Gtk.IconSize.Dialog);
                    byte[] buf = pix.SaveToBuffer("tiff");
                    unsafe
                    {
                        fixed(byte *b = buf)
                        {
                            alert.Icon = new NSImage(NSData.FromBytes((IntPtr)b, (uint)buf.Length));
                        }
                    }
                }
                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;
                alert.InformativeText = data.Message.SecondaryText ?? "";

                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;
                    }
                }

                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");
                    }

                    alert.AddButton(label);
                }


                NSButton[] optionButtons = null;
                if (data.Options.Count > 0)
                {
                    var box = new MDBox(LayoutDirection.Vertical, 2, 2);
                    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);
                        optionButtons[i] = button;
                        box.Add(new MDAlignment(button, true)
                        {
                            XAlign = LayoutAlign.Begin
                        });
                    }

                    box.Layout();
                    alert.AccessoryView = box.View;
                }

                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 = ((NSPanel)alert.Window).Frame;
                ((NSPanel)alert.Window).SetFrame(new RectangleF(frame.X, frame.Y, Math.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)
                            {
                                NSApplication.SharedApplication.AbortModal();
                            }
                        });
                    });
                }

                if (!data.Message.CancellationToken.IsCancellationRequested)
                {
                    int result = alert.RunModal() - (int)NSAlertButtonReturn.First;
                    completed = true;
                    if (result >= 0 && result < buttons.Count)
                    {
                        data.ResultButton = buttons [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[button.Tag];
                        data.Message.SetOptionValue(option.Id, button.State != 0);
                    }
                }

                if (applyToAllCheck != null && applyToAllCheck.State != 0)
                {
                    data.ApplyToAll = true;
                }

                GtkQuartz.FocusWindow(data.TransientFor ?? MessageService.RootWindow);
            }

            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: VK The icon is not rendered in dark style correctly
					//       Use light variant and reder it here
					//       as long as NSAppearance.NameVibrantDark is broken
					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;
				alert.InformativeText = data.Message.SecondaryText ?? "";
				
				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) {
					var box = new MDBox (LayoutDirection.Vertical, 2, 2);
					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);
						optionButtons[i] = button;
						box.Add (new MDAlignment (button, true) { XAlign = LayoutAlign.Begin });
					}
					
					box.Layout ();
					alert.AccessoryView = box.View;
				}
				
				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) {
								NSApplication.SharedApplication.AbortModal ();
							}
						});
					});
				}
				
				if (!data.Message.CancellationToken.IsCancellationRequested) {

					var result = (int)alert.RunModal () - (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;



				GtkQuartz.FocusWindow (data.TransientFor ?? MessageService.RootWindow);
			}
			
			return true;
		}