2

I have written my own PopupPanel in GWT. I want to show the popup relative to an other widget. My implementation of the class looks like the following:

public class Popover extends PopupPanel implements PositionCallback {

    private static final Binder binder = GWT.create(Binder.class);
    private UIObject relative;

    interface Binder extends UiBinder<Widget, Popover> {
    }

    public Popover() {
        setWidget(binder.createAndBindUi(this));
        setStylePrimaryName("popover");
    }

    public void show(UIObject relative) {

        this.relative = relative;
        setPopupPositionAndShow(this);

    }

    public void setPosition(int offsetWidth, int offsetHeight) {

        if (relative != null) {

            int left = relative.getAbsoluteLeft();
            int top = relative.getAbsoluteTop();
            int width = relative.getOffsetWidth();
            int height = relative.getOffsetHeight();

            int topCenter = top + height / 2 - offsetHeight / 2;


            if (offsetWidth < left) {
                setPopupPosition(left - offsetWidth, topCenter);
            } else {
                setPopupPosition(left + width, topCenter);

            }
        }
    }

}

The problem is that offsetWidth and offsetHeight is always 10?

My Popover.ui.xml looks like the following:

<g:FlowPanel stylePrimaryName="popover">
    <g:FlowPanel stylePrimaryName="arrow" />
    <g:FlowPanel stylePrimaryName="inner">
        <g:Label stylePrimaryName="title" text="New Label" />
        <g:FlowPanel stylePrimaryName="content">
            <g:Label text="Hallo" />
        </g:FlowPanel>
    </g:FlowPanel>
</g:FlowPanel>
enrybo
  • 1,787
  • 1
  • 12
  • 20

2 Answers2

6

To solve this issue, I followed the steps used by PopupPanel's setPopupPositionAndShow(), but I made the positioning step a deferred command. My code didn't extend PopupPanel, hence the popupPanel variable:

popupPanel.setVisible(false);
popupPanel.show();

// Pausing until the event loop is clear appears to give the browser
// sufficient time to apply CSS styling.  We use the popup's offset
// width and height to calculate the display position, but those
// dimensions are not accurate until styling has been applied.
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
   @Override
   public void execute() {
      yourMethodToSetPositionGoesHere(popupPanel);
      popupPanel.setVisible(true);
   }
});
enrybo
  • 1,787
  • 1
  • 12
  • 20
dimalinux
  • 839
  • 8
  • 8
1

getOffsetWidth() and getOffsetHeight() only work if the DOM is fully constructed and the container for which you want to get the value is visible and attached.

Why don't you use the showRelativeTo() function of the PopupPanel?

popup.showRelativeTo(SomeWidget);
CassOnMars
  • 6,153
  • 2
  • 32
  • 47
Ümit
  • 17,379
  • 7
  • 55
  • 74
  • The position of popup.showRelativeTo(SomeWidget); is not as i want it to. Most of my popups must be shown left or right of the relativeWidget. The showRelativeTo method displays the PopupPanel nearly always under the relativeWidget =(. –  Nov 09 '11 at 12:35
  • ok I see. Did you try to specify explicit sizes for your FlowPanels? – Ümit Nov 09 '11 at 12:47
  • FYI: popup.showRelativeTo(SomeWidget) still ends up calling getOffsetWidth(). – Glen Pierce Oct 06 '16 at 21:49