Esempio n. 1
0
        /// <summary>
        ///     This method will create and show the destination picker menu
        /// </summary>
        /// <param name="addDynamics">Boolean if the dynamic values also need to be added</param>
        /// <param name="surface">The surface which can be exported</param>
        /// <param name="captureDetails">Details for the surface</param>
        /// <param name="destinations">The list of destinations to show</param>
        /// <returns></returns>
        protected ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable <IDestination> destinations)
        {
            var menu = new ContextMenuStrip
            {
                Tag      = null,
                TopLevel = true
            };
            var dpiHandler         = menu.AttachDpiHandler();
            var bitmapScaleHandler = BitmapScaleHandler.Create <IDestination>(
                dpiHandler,
                (destination, dpi) => destination.GetDisplayIcon(dpi),
                (bitmap, d) => bitmap.ScaleIconForDisplaying(d));

            dpiHandler.OnDpiChanged.Subscribe(dpi =>
            {
                var width             = DpiHandler.ScaleWithDpi(CoreConfiguration.IconSize.Width, dpi);
                var size              = new Size(width, width);
                menu.ImageScalingSize = size;
            });

            // Generate an empty ExportInformation object, for when nothing was selected.
            var exportInformation = new ExportInformation("", GreenshotLanguage.SettingsDestinationPicker);

            menu.Closing += (source, eventArgs) =>
            {
                Log.Debug().WriteLine("Close reason: {0}", eventArgs.CloseReason);
                switch (eventArgs.CloseReason)
                {
                case ToolStripDropDownCloseReason.AppFocusChange:
                    if (menu.Tag == null)
                    {
                        // Do not allow the close if the tag is not set, this means the user clicked somewhere else.
                        eventArgs.Cancel = true;
                    }
                    else
                    {
                        Log.Debug().WriteLine("Letting the menu 'close' as the tag is set to '{0}'", menu.Tag);
                    }
                    break;

                case ToolStripDropDownCloseReason.ItemClicked:
                case ToolStripDropDownCloseReason.CloseCalled:
                    // The ContextMenuStrip can be "closed" for these reasons.
                    break;

                case ToolStripDropDownCloseReason.Keyboard:
                    // Dispose as the close is clicked
                    if (!captureDetails.HasDestination("Editor"))
                    {
                        surface.Dispose();
                        surface = null;
                    }
                    break;

                default:
                    eventArgs.Cancel = true;
                    break;
                }
            };
            menu.MouseEnter += (sender, args) =>
            {
                // in case the menu has been unfocused, focus again so that dropdown menus will still open on mouseenter
                if (!menu.ContainsFocus)
                {
                    menu.Focus();
                }
            };
            foreach (var destination in destinations)
            {
                // Fix foreach loop variable for the delegate
                var item = destination.GetMenuItem(addDynamics, menu,
                                                   async(sender, e) =>
                {
                    var toolStripMenuItem  = sender as ToolStripMenuItem;
                    var clickedDestination = (IDestination)toolStripMenuItem?.Tag;
                    if (clickedDestination == null)
                    {
                        return;
                    }
                    menu.Tag = clickedDestination.Designation;
                    // Export
                    exportInformation = await clickedDestination.ExportCaptureAsync(true, surface, captureDetails);
                    if (exportInformation != null && exportInformation.ExportMade)
                    {
                        Log.Info().WriteLine("Export to {0} success, closing menu", exportInformation.DestinationDescription);
                        // close menu
                        menu.Close();
                        menu.Dispose();
                        // Cleanup surface, only if there is no editor in the destinations and we didn't export to the editor
                        if (!captureDetails.HasDestination("Editor") && !"Editor".Equals(clickedDestination.Designation))
                        {
                            surface.Dispose();
                            surface = null;
                        }
                    }
                    else
                    {
                        Log.Info().WriteLine("Export cancelled or failed, showing menu again");

                        // Make sure a click besides the menu don't close it.
                        menu.Tag = null;

                        // This prevents the problem that the context menu shows in the task-bar
                        ShowMenuAtCursor(menu);
                    }
                }, bitmapScaleHandler
                                                   );
                if (item != null)
                {
                    menu.Items.Add(item);
                }
            }
            // Close
            menu.Items.Add(new ToolStripSeparator());
            var closeItem = new ToolStripMenuItem(GreenshotLanguage.Close)
            {
                Image = GreenshotResources.GetBitmap("Close.Image")
            };

            closeItem.Click += (sender, args) =>
            {
                // This menu entry is the close itself, we can dispose the surface
                menu.Close();
                menu.Dispose();
                // Only dispose if there is a destination which keeps the capture
                if (captureDetails.HasDestination("Editor"))
                {
                    return;
                }

                surface.Dispose();
                surface = null;
            };
            menu.Items.Add(closeItem);

            ShowMenuAtCursor(menu);
            return(exportInformation);
        }