package org.drools.guvnor.client.util; import org.drools.guvnor.client.resources.Images; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.layout.client.Layout.Alignment; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.LayoutPanel; import com.google.gwt.user.client.ui.TabLayoutPanel; import com.google.gwt.user.client.ui.Widget; public class ScrollTabLayoutPanel extends TabLayoutPanel { private static Images images = GWT.create( Images.class ); private Image scrollLeft; private Image scrollRight; private FlowPanel tabBar = null; private LayoutPanel panel; private static final int ScrollLengh = 100; private double barHeight; private Unit barUnit; private boolean isScrollingEnabled = false; private HandlerRegistration windowResizeHandler; public ScrollTabLayoutPanel(double barHeight, Unit barUnit) { super( barHeight, barUnit ); this.barHeight = barHeight; this.barUnit = barUnit; this.panel = (LayoutPanel) getWidget(); for ( int i = 0; i < panel.getWidgetCount(); ++i ) { Widget widget = panel.getWidget( i ); if ( widget instanceof FlowPanel ) { tabBar = (FlowPanel) widget; break; } } } @Override public void add(Widget child, Widget tab) { super.add( child, tab ); checkIfScrollButtonsNecessary(); } @Override public boolean remove(Widget w) { boolean b = super.remove( w ); checkIfScrollButtonsNecessary(); return b; } @Override public boolean remove(int index) { boolean b = super.remove( index ); checkIfScrollButtonsNecessary(); return b; } @Override protected void onLoad() { super.onLoad(); if ( windowResizeHandler == null ) { windowResizeHandler = Window.addResizeHandler( new ResizeHandler() { public void onResize(ResizeEvent event) { checkIfScrollButtonsNecessary(); } } ); } } @Override protected void onUnload() { super.onUnload(); if ( windowResizeHandler != null ) { windowResizeHandler.removeHandler(); windowResizeHandler = null; } } private void enableScroll() { if ( !isScrollingEnabled ) { scrollRight = new Image( images.scrollRight() ); scrollLeft = new Image( images.scrollLeft() ); scrollLeft.addClickHandler( createScrollClickHandler( ScrollLengh ) ); scrollRight.addClickHandler( createScrollClickHandler( -ScrollLengh ) ); panel.setWidgetLeftRight( tabBar, 30, Unit.PX, 30, Unit.PX ); panel.setWidgetTopHeight( tabBar, 0, Unit.PX, barHeight, barUnit ); panel.setWidgetVerticalPosition( tabBar, Alignment.END ); panel.add( scrollRight ); panel.setWidgetRightWidth( scrollRight, 0, Unit.PX, 27, Unit.PX ); panel.setWidgetTopHeight( scrollRight, 0, Unit.PX, barHeight, barUnit ); panel.setWidgetVerticalPosition( scrollRight, Alignment.END ); panel.add( scrollLeft ); panel.setWidgetLeftWidth( scrollLeft, 0, Unit.PX, 27, Unit.PX ); panel.setWidgetTopHeight( scrollLeft, 0, Unit.PX, barHeight, barUnit ); panel.setWidgetVerticalPosition( scrollLeft, Alignment.END ); isScrollingEnabled = true; } } private void disableScroll() { if ( isScrollingEnabled ) { panel.remove( scrollRight ); panel.remove( scrollLeft ); panel.setWidgetLeftRight( tabBar, 0, Unit.PX, 0, Unit.PX ); panel.setWidgetTopHeight( tabBar, 0, Unit.PX, barHeight, barUnit ); panel.setWidgetVerticalPosition( tabBar, Alignment.END ); isScrollingEnabled = false; } } private void checkIfScrollButtonsNecessary() { // Defer size calculations until sizes are available, when calculating // immediately after add(), all size methods return zero Scheduler.get().scheduleDeferred( new Scheduler.ScheduledCommand() { public void execute() { boolean isScrolling = isScrollingNecessary(); if ( isScrolling ) { enableScroll(); } else { disableScroll(); } } } ); } private boolean isScrollingNecessary() { Widget lastTab = getLastTab(); if ( lastTab == null ) return false; return getRightOfWidget( lastTab ) > getTabBarWidth(); } private ClickHandler createScrollClickHandler(final int diff) { return new ClickHandler() { public void onClick(ClickEvent event) { Widget lastTab = getLastTab(); if ( lastTab == null ) return; int newLeft = parsePosition( tabBar.getElement().getStyle().getLeft() ) + diff; int rightOfLastTab = getRightOfWidget( lastTab ); // Prevent scrolling the last tab too far away form the right // border, or the first tab further than the left border position if ( newLeft <= 0 && (getTabBarWidth() - newLeft < (rightOfLastTab + ScrollLengh)) ) { scrollTo( newLeft ); } } }; } private void scrollTo(int pos) { tabBar.getElement().getStyle().setLeft( pos, Unit.PX ); } private int getRightOfWidget(Widget widget) { return widget.getElement().getOffsetLeft() + widget.getElement().getOffsetWidth(); } private int getTabBarWidth() { return tabBar.getElement().getParentElement().getClientWidth(); } private Widget getLastTab() { if ( tabBar.getWidgetCount() == 0 ) return null; return tabBar.getWidget( tabBar.getWidgetCount() - 1 ); } private static int parsePosition(String positionString) { int position; try { for ( int i = 0; i < positionString.length(); i++ ) { char c = positionString.charAt( i ); if ( c != '-' && !(c >= '0' && c <= '9') ) { positionString = positionString.substring( 0, i ); } } position = Integer.parseInt( positionString ); } catch ( NumberFormatException ex ) { position = 0; } return position; } }