package org.ovirt.engine.ui.common.presenter; import org.ovirt.engine.ui.common.system.HeaderOffsetChangeEvent; import org.ovirt.engine.ui.common.widget.tab.TabAccessibleChangeEvent; import org.ovirt.engine.ui.common.widget.tab.TabWidgetHandler; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.IsWidget; import com.google.inject.Inject; import com.google.web.bindery.event.shared.EventBus; import com.gwtplatform.mvp.client.PresenterWidget; import com.gwtplatform.mvp.client.View; /** * Scroll-able tab bar widget that presents scrolling buttons when the window is not large enough to contain all the * tabs. The scroll buttons allow the user to scroll so they can see tabs that they could not see otherwise. The * widget also provide a drop down menu list of all the tabs. */ public class ScrollableTabBarPresenterWidget extends PresenterWidget<ScrollableTabBarPresenterWidget.ViewDef> implements TabWidgetHandler { /** * View definition. */ public interface ViewDef extends View, TabWidgetHandler { /** * recalculate the needed sizes. */ void recalculateSize(); /** * Show/hide the scroll buttons. */ void showScrollButtons(); /** * Allow the caller to set the offset of the {@code ScrollableTabBar} relative to its container. * @param left How far to the left in pixels. * @param wantsLeft If the left offset needs to be added to the container. */ void setOffset(int left, boolean wantsLeft); /** * Set how many pixels the scroll panel should scroll when a button is clicked. * @param scrollDistance The distance in pixels. */ void setScrollDistance(int scrollDistance); } /** * The default number of pixels the scrollbar will scroll. */ public static final int DEFAULT_SCROLL_DISTANCE = 20; //pixels. private HandlerRegistration resizeHandlerRegistration; private boolean wantsOffset = true; private boolean scheduled = false; /** * Constructor. * @param eventBus The GWT event bus. * @param view The view associated with this presenter widget. */ @Inject public ScrollableTabBarPresenterWidget(EventBus eventBus, ScrollableTabBarPresenterWidget.ViewDef view) { super(eventBus, view); setScrollDistance(DEFAULT_SCROLL_DISTANCE); } @Override protected void onBind() { super.onBind(); //This handler is called when tab accessibility changes. registerHandler(getEventBus().addHandler(TabAccessibleChangeEvent.getType(), event -> onTabAccessibleChanged())); //This handler is called when tab accessibility changes. registerHandler(getEventBus().addHandler(SetDynamicTabAccessibleEvent.getType(), event -> onTabAccessibleChanged())); registerHandler(getEventBus().addHandler(HeaderOffsetChangeEvent.getType(), event -> { getView().setOffset(event.getWidth(), wantsOffset); //This may seem a little strange, removing the handler for the resize event after the first //offset change event. But the splitter also generates a resize event. So we would be handling the //same thing twice. Until the offset events are properly registered and working, we need the resize //event to calculate the proper sizes. Once it is working, we don't need to handle the resize events //anymore as the splitter will generate offset events based on window resizes. if (resizeHandlerRegistration != null) { resizeHandlerRegistration.removeHandler(); resizeHandlerRegistration = null; } })); resizeHandlerRegistration = Window.addResizeHandler(resizeEvent -> redraw()); } @Override protected void onReveal() { super.onReveal(); redraw(); } @Override public void addTabWidget(IsWidget tabWidget, int index) { getView().addTabWidget(tabWidget, index); } @Override public void removeTabWidget(IsWidget tabWidget) { getView().removeTabWidget(tabWidget); } /** * Allow the caller to set the offset of the {@code ScrollableTabBar} relative to its container. * @param left How far to the left in pixels. */ public void setOffset(int left) { getView().setOffset(left, wantsOffset); } /** * Set how many pixels the scroll panel should scroll when a button is clicked. * @param scrollDistance The distance in pixels. */ public void setScrollDistance(int scrollDistance) { getView().setScrollDistance(scrollDistance); } /** * Lets the presenter know if we should pass offsets to the scrollablle tab bar. * @param wantsOffset true if you want offsets passed, false otherwise. */ public void setWantsOffset(boolean wantsOffset) { this.wantsOffset = wantsOffset; } private void redraw() { getView().recalculateSize(); getView().showScrollButtons(); } private void onTabAccessibleChanged() { if (!scheduled) { Scheduler.get().scheduleDeferred(() -> { redraw(); scheduled = false; }); scheduled = true; } } }