Ejemplo n.º 1
0
        /// <summary>
        /// Create a dropdown menu under the text.
        /// </summary>
        public override void showEditor_(bool opt_quietInput)
        {
            WidgetDiv.show(this, this.sourceBlock_.RTL, null);
            var thisField = this;

            var callback = new Action <goog.events.Event>((e) => {
                var menuItem = (goog.ui.MenuItem)e.target;
                if (menuItem != null)
                {
                    var value = menuItem.getValue();
                    if (thisField.sourceBlock_ != null)
                    {
                        // Call any validation function, and allow it to override.
                        value = thisField.callValidator(value);
                    }
                    if (value != null)
                    {
                        thisField.setValue(value);
                    }
                }
                WidgetDiv.hideIfOwner(thisField);
            });

            var menu = new goog.ui.Menu();

            menu.setRightToLeft(this.sourceBlock_.RTL);
            var options = this.getOptions_();

            for (var i = 0; i < options.Length; i++)
            {
                var text     = options[i].text;              // Human-readable text.
                var value    = options[i].value;             // Language-neutral value.
                var menuItem = new goog.ui.MenuItem(text);
                menuItem.setRightToLeft(this.sourceBlock_.RTL);
                menuItem.setValue(value);
                menuItem.setCheckable(true);
                menu.addChild(menuItem, true);
                menuItem.setChecked(value == this.value_);
            }
            // Listen for mouse/keyboard events.
            goog.events.listen(menu, goog.ui.Component.EventType.ACTION, callback);
            // Listen for touch events (why doesn't Closure handle this already?).
            var callbackTouchStart = new Action <goog.events.BrowserEvent>((e) => {
                var control = menu.getOwnerControl((Node)e.target);
                // Highlight the menu item.
                control.handleMouseDown(e);
            });
            var callbackTouchEnd = new Action <goog.events.Event>((e) => {
                var control = menu.getOwnerControl((Node)e.target);
                // Activate the menu item.
                control.performActionInternal(e);
            });

            menu.getHandler().listen(menu.getElement(), goog.events.EventType.TOUCHSTART,
                                     callbackTouchStart);
            menu.getHandler().listen(menu.getElement(), goog.events.EventType.TOUCHEND,
                                     callbackTouchEnd);

            // Record windowSize and scrollOffset before adding menu.
            var windowSize   = goog.dom.getViewportSize();
            var scrollOffset = goog.style.getViewportPageOffset(Document.Instance);
            var xy           = this.getAbsoluteXY_();
            var borderBBox   = this.getScaledBBox_();
            var div          = WidgetDiv.DIV;

            menu.render(div);
            var menuDom = menu.getElement();

            Core.addClass_(menuDom, "blocklyDropdownMenu");
            // Record menuSize after adding menu.
            var menuSize = goog.style.getSize(menuDom);

            // Recalculate height for the total content, not only box height.
            menuSize.height = menuDom.ScrollHeight;

            // Position the menu.
            // Flip menu vertically if off the bottom.
            if (xy.y + menuSize.height + borderBBox.height >=
                windowSize.height + scrollOffset.y)
            {
                xy.y -= menuSize.height + 2;
            }
            else
            {
                xy.y += borderBBox.height;
            }
            if (this.sourceBlock_.RTL)
            {
                xy.x += borderBBox.width;
                xy.x += FieldDropdown.CHECKMARK_OVERHANG;
                // Don't go offscreen left.
                if (xy.x < scrollOffset.x + menuSize.width)
                {
                    xy.x = scrollOffset.x + menuSize.width;
                }
            }
            else
            {
                xy.x -= FieldDropdown.CHECKMARK_OVERHANG;
                // Don't go offscreen right.
                if (xy.x > windowSize.width + scrollOffset.x - menuSize.width)
                {
                    xy.x = windowSize.width + scrollOffset.x - menuSize.width;
                }
            }
            WidgetDiv.position(xy.x, xy.y, windowSize, scrollOffset,
                               this.sourceBlock_.RTL);
            menu.setAllowAutoFocus(true);
            menuDom.Focus();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Construct the menu based on the list of options and show the menu.
        /// </summary>
        /// <param name="e">Mouse event.</param>
        /// <param name="options">Array of menu options.</param>
        /// <param name="rtl">True if RTL, false if LTR.</param>
        public static void show(MouseEvent e, ContextMenuOption[] options, bool rtl)
        {
            WidgetDiv.show(Core.ContextMenu, rtl, null);
            if (options.Length == 0)
            {
                ContextMenu.hide();
                return;
            }

            /* Here's what one option object looks like:
             * {text: 'Make It So',
             * enabled: true,
             * callback: Blockly.MakeItSo}
             */
            var menu = new goog.ui.Menu();

            menu.setRightToLeft(rtl);
            foreach (var option in options)
            {
                var menuItem = new goog.ui.MenuItem(option.text);
                menuItem.setRightToLeft(rtl);
                menu.addChild(menuItem, true);
                menuItem.setEnabled(option.enabled);
                if (option.enabled)
                {
                    goog.events.listen(menuItem, goog.ui.Component.EventType.ACTION,
                                       option.callback);
                }
            }
            goog.events.listen(menu, goog.ui.Component.EventType.ACTION,
                               new Action <goog.events.Event>((ev) => ContextMenu.hide()));
            // Record windowSize and scrollOffset before adding menu.
            var windowSize   = goog.dom.getViewportSize();
            var scrollOffset = goog.style.getViewportPageOffset(Document.Instance);
            var div          = WidgetDiv.DIV;

            menu.render(div);
            var menuDom = menu.getElement();

            Core.addClass_(menuDom, "blocklyContextMenu");
            // Prevent system context menu when right-clicking a Blockly context menu.
            Core.bindEventWithChecks_(menuDom, "contextmenu", null, new Action <Event>(Core.noEvent));
            // Record menuSize after adding menu.
            var menuSize = goog.style.getSize(menuDom);

            // Position the menu.
            var x = e.ClientX + scrollOffset.x;
            var y = e.ClientY + scrollOffset.y;

            // Flip menu vertically if off the bottom.
            if (e.ClientY + menuSize.height >= windowSize.height)
            {
                y -= menuSize.height;
            }
            // Flip menu horizontally if off the edge.
            if (rtl)
            {
                if (menuSize.width >= e.ClientX)
                {
                    x += menuSize.width;
                }
            }
            else
            {
                if (e.ClientX + menuSize.width >= windowSize.width)
                {
                    x -= menuSize.width;
                }
            }
            WidgetDiv.position(x, y, windowSize, scrollOffset, rtl);

            menu.setAllowAutoFocus(true);
            // 1ms delay is required for focusing on context menus because some other
            // mouse event is still waiting in the queue and clears focus.
            Window.SetTimeout(() => { menuDom.Focus(); }, 1);
            ContextMenu.currentBlock = null;              // May be set by Blockly.Block.
        }