Как получить всплывающее меню GWT, чтобы оно оставалось в окне браузера? - PullRequest
2 голосов
/ 13 октября 2010

Мое приложение GWT использует DockLayoutPanel для основного макета, а сама страница не прокручивается.У меня есть PopupPanel с MenuBar, и иногда, когда выбирается MenuItem, строка подменю внезапно уходит из нижней части экрана, вызывая новую полосу прокрутки в браузере и портя макет.

Как мне получитьвсплывающее меню, которое ведет себя хорошо и перемещается вверх, когда позиционирование по умолчанию выводит его из окна просмотра браузера (как работает позиционирование PopupPanel.showRelativeTo (uiTarget))?

При взгляде на источник MenuBar, оноПохоже, что все макеты сделаны в приватных методах, поэтому я не могу исправить это в подклассе, и я не вижу событий, которые я могу прослушать, которые позволили бы мне сделать репозицию самостоятельно.

Ответы [ 3 ]

3 голосов
/ 14 октября 2010

Взгляните на http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/6185225fec64c091/4954d91d1461c71f?lnk=gst&q=context+menu#4954d91d1461c71f.

Мы уже довольно успешно используем эту стратегию.

Обновление: есть еще кое-что сделать. В частности:

  • Создать метод reposition (), который:

    • Определяет максимальную ширину всех пунктов меню
    • Проверяет левый край меню + максимальную ширину; если больше ширины окна, используйте «DOM.setStyleAttribute (elem,« left », left +« px »);» переместить меню
    • Получить высоту меню; если верх меню + высота меню> высота окна, используйте "DOM.setStyleAttribute (elem," top ", top +" px ");" переместить его вверх.
  • В методе onAttach () используйте отложенную команду для вызова метода reposition ().

1 голос
/ 02 мая 2013

Вы можете перехватить всплывающее окно непосредственно перед его отображением, но после того, как его размер был создан. Таким образом, у вас есть ширина всплывающего окна и вы можете переместить его в другую позицию:

@Override
public void onContextMenu(ContextMenuEvent evt) {
    int x = evt.getNativeEvent().getClientX();
    int y = evt.getNativeEvent().getClientY();

    popupMenu.setPopupPositionAndShow(new PositionCallback() {
        @Override
        public void setPosition(int offsetWidth, int offsetHeight) {
            if (x + offsetWidth > Window.getClientWidth()) {
                x = Window.getClientWidth() - offsetWidth;
            }

            //use same technique for height if you want for y, then
            setPosition(x, y);
        }
    });
}

(я знаю, что это старый вопрос, но он все еще возникает, если вы ищете его, поэтому я подумал о том, чтобы предложить настоящее решение)

0 голосов
/ 03 августа 2012

Эмм ...

Это интересный вопрос ...

Глядя на MenuBar исходный код ... особенно метод openPopup

 private void openPopup(final MenuItem item) {
    // Only the last popup to be opened should preview all event
    if (parentMenu != null && parentMenu.popup != null) {
      parentMenu.popup.setPreviewingAllNativeEvents(false);
    }

    // Create a new popup for this item, and position it next to
    // the item (below if this is a horizontal menu bar, to the
    // right if it's a vertical bar).
    popup = new DecoratedPopupPanel(true, false, "menuPopup") {
      {
        setWidget(item.getSubMenu());
        setPreviewingAllNativeEvents(true);
        item.getSubMenu().onShow();
      }

      @Override
      protected void onPreviewNativeEvent(NativePreviewEvent event) {
        // Hook the popup panel's event preview. We use this to keep it from
        // auto-hiding when the parent menu is clicked.
        if (!event.isCanceled()) {

          switch (event.getTypeInt()) {
            case Event.ONMOUSEDOWN:
              // If the event target is part of the parent menu, suppress the
              // event altogether.
              EventTarget target = event.getNativeEvent().getEventTarget();
              Element parentMenuElement = item.getParentMenu().getElement();
              if (parentMenuElement.isOrHasChild(Element.as(target))) {
                event.cancel();
                return;
              }
              super.onPreviewNativeEvent(event);
              if (event.isCanceled()) {
                selectItem(null);
              }
              return;
          }
        }
        super.onPreviewNativeEvent(event);
      }
    };
    popup.setAnimationType(AnimationType.ONE_WAY_CORNER);
    popup.setAnimationEnabled(isAnimationEnabled);
    popup.setStyleName(STYLENAME_DEFAULT + "Popup");
    String primaryStyleName = getStylePrimaryName();
    if (!STYLENAME_DEFAULT.equals(primaryStyleName)) {
      popup.addStyleName(primaryStyleName + "Popup");
    }
    popup.addPopupListener(this);

    shownChildMenu = item.getSubMenu();
    item.getSubMenu().parentMenu = this;

    // Show the popup, ensuring that the menubar's event preview remains on top
    // of the popup's.
    popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {

      public void setPosition(int offsetWidth, int offsetHeight) {

        // depending on the bidi direction position a menu on the left or right
        // of its base item
        if (LocaleInfo.getCurrentLocale().isRTL()) {
          if (vertical) {
            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth
                + 1, item.getAbsoluteTop());
          } else {
            popup.setPopupPosition(item.getAbsoluteLeft()
                + item.getOffsetWidth() - offsetWidth,
                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
                    - 1);
          }
        } else {
          if (vertical) {
            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft()
                + MenuBar.this.getOffsetWidth() - 1, item.getAbsoluteTop());
          } else {
            popup.setPopupPosition(item.getAbsoluteLeft(),
                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
                    - 1);
          }
        }
      }
    });
  }

Интересно указать фрагмент как

...
popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {

      public void setPosition(int offsetWidth, int offsetHeight) {

        // depending on the bidi direction position a menu on the left or right
        // of its base item
        if (LocaleInfo.getCurrentLocale().isRTL()) {
          if (vertical) {
            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth
                + 1, item.getAbsoluteTop());
          } else {
            popup.setPopupPosition(item.getAbsoluteLeft()
                + item.getOffsetWidth() - offsetWidth,
                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
                    - 1);
          }
        } else {
          if (vertical) {
            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft()
                + MenuBar.this.getOffsetWidth() - 1, item.getAbsoluteTop());
          } else {
            popup.setPopupPosition(item.getAbsoluteLeft(),
                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
                    - 1);
          }
        }
      }
    });

...

... поэтому я могу предположить, что есть смысл поиграть с объектом MenuItem, особенно с его наследуемыми методами UIObject, такими какgetAbsoluteLeft () и getAbsoluteTop (), конечно ...

Я бы порекомендовал расширить MenuItem таким образом

    //not tested
    public class MyMenuItem extends MenuItem
    {

    private MenuBar aSubMenuBar;//ItemMenu's submenu

    //...


    @Override
        public int getAbsoluteTop() {
            // TODO Auto-generated method stub
            return super.getAbsoluteTop()+movePopupTo();
        }


        private int movePopupTo()
    {
        int moveTo=0;

        int bottom=RootPanel.getBodyElement().getAbsoluteBottom();
        int rest=bottom -(super.getAbsoluteTop()+this.getaSubMenuBar().getOffsetHeight());
        if(rest<0)
        {
            moveTo=rest;
        }

        return moveTo;



    }



    public MenuBar getaSubMenuBar() {
            return aSubMenuBar;
        }

        public void setaSubMenuBar(MenuBar aSubMenuBar) {
            this.aSubMenuBar = aSubMenuBar;
        }


   //...

    }

Это не окончательное решение, а базовая концепция.


Сообщите, помогло ли это

Удачи

...