Alexander Wels has uploaded a new change for review.

Change subject: webadmin: main tab bar scrollable
......................................................................

webadmin: main tab bar scrollable

- Make the main tab bar scrollable so we can resize the screen to
  be smaller.

Change-Id: I63dddb3c0026ea3a5c13c3d18daebd02e13b1043
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=818051
Signed-off-by: Alexander Wels <[email protected]>
---
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.ui.xml
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.ui.xml
4 files changed, 287 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/16/21716/1

diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.java
index 1276718..4f875e4 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.java
@@ -6,6 +6,7 @@
 import org.ovirt.engine.ui.webadmin.ApplicationConstants;
 import org.ovirt.engine.ui.webadmin.ApplicationDynamicMessages;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.HeaderPresenterWidget;
+import org.ovirt.engine.ui.webadmin.widget.tab.ScrollableTabBar;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Style.Unit;
@@ -15,7 +16,6 @@
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.HTMLPanel;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.IsWidget;
@@ -67,7 +67,7 @@
     HTMLPanel mainTabBarPanel;
 
     @UiField
-    FlowPanel mainTabContainer;
+    ScrollableTabBar mainTabContainer;
 
     @UiField
     HTMLPanel feedbackImagePanel;
@@ -114,7 +114,7 @@
 
     @Override
     public void removeTabWidget(Widget tabWidget) {
-        mainTabContainer.getElement().removeChild(tabWidget.getElement());
+        mainTabContainer.remove(tabWidget);
     }
 
     @Override
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.ui.xml
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.ui.xml
index e895ff2..a12deee 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.ui.xml
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/HeaderView.ui.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
-<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" 
xmlns:g="urn:import:com.google.gwt.user.client.ui">
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" 
xmlns:g="urn:import:com.google.gwt.user.client.ui"
+    xmlns:ovirt="urn:import:org.ovirt.engine.ui.webadmin.widget.tab">
 
     <ui:with field='constants' 
type='org.ovirt.engine.ui.webadmin.ApplicationConstants' />
 
@@ -52,10 +53,6 @@
             height: 28px;
         }
 
-        .mainTabContainer {
-            min-width: 800px;
-        }
-
         .headerLabelStyle {
             font-weight: bold;
             color: white;
@@ -104,7 +101,7 @@
                 <g:SimplePanel ui:field="searchPanelContainer" 
addStyleNames="{style.searchPanel}" />
 
                 <g:HTMLPanel ui:field="mainTabBarPanel" 
addStyleNames="{style.mainTabBar}">
-                    <g:FlowPanel ui:field="mainTabContainer" 
addStyleNames="{style.mainTabContainer}"/>
+                    <ovirt:ScrollableTabBar ui:field="mainTabContainer" />
                     <div style="clear: both;" />
                 </g:HTMLPanel>
             </g:HTMLPanel>
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.java
new file mode 100644
index 0000000..2f4f287
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.java
@@ -0,0 +1,249 @@
+package org.ovirt.engine.ui.webadmin.widget.tab;
+
+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.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.FocusPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+public class ScrollableTabBar extends Composite {
+    interface WidgetUiBinder extends UiBinder<Widget, ScrollableTabBar> {
+        WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class);
+    }
+
+//    private static final String SCROLL_BUTTON_STYLE = "tab-scroll-button"; 
//$NON-NLS-1$
+    private static final int SCROLL_INTERVAL = 60;
+    private static final String MIN_WIDTH_STYLE = "minWidth"; //$NON-NLS-1$
+    private static final String MAX_WIDTH_STYLE = "maxWidth"; //$NON-NLS-1$
+
+    /**
+     * The tab bar.
+     */
+    @UiField
+    FlowPanel widgetBar;
+
+    @UiField
+    FlowPanel scrollPanel;
+
+    /**
+     * The left scroll button.
+     */
+    @UiField
+    FocusPanel scrollLeftButton;
+    /**
+     * The right scroll button.
+     */
+    @UiField
+    FocusPanel scrollRightButton;
+
+    public ScrollableTabBar() {
+        super();
+        initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this));
+        initScrollButtons();
+        //Since this is singleton, don't need to worry about leaking handlers
+        Window.addResizeHandler(new ResizeHandler() {
+            @Override
+            public void onResize(ResizeEvent resizeEvent) {
+                showScrollButtons();
+            }
+        });
+    }
+
+    public void insert(Widget tabWidget, int index) {
+        widgetBar.insert(tabWidget, index);
+        recalculateWidgetBarMinWidth();
+        showScrollButtons();
+    }
+
+    public boolean remove(Widget tabWidget) {
+        boolean result = widgetBar.remove(tabWidget);
+        recalculateWidgetBarMinWidth();
+        showScrollButtons();
+        return result;
+    }
+
+    private void recalculateWidgetBarMinWidth() {
+        //Set the minimum width.
+        widgetBar.getElement().getStyle().setProperty(MIN_WIDTH_STYLE, 
getWidgetMinWidthNeeded(), Unit.PX);
+    }
+
+    private int getWidgetMinWidthNeeded() {
+        int minWidth = 0;
+        if (widgetBar.getWidgetCount() > 0) {
+            for(int i = 0; i < widgetBar.getWidgetCount(); i++) {
+                Widget widget = widgetBar.getWidget(i);
+                if(widget.isVisible()) {
+                    minWidth += widget.getElement().getOffsetWidth();
+                }
+            }
+        }
+        return minWidth;
+    }
+    private void recalculateScrollPanelMaxWidth() {
+        int minWidgetBarWidth = Math.max(getMaxWidth(), 
getWidgetMinWidthNeeded());
+        widgetBar.getElement().getStyle().setProperty("width", 
minWidgetBarWidth + 15, Unit.PX); //$NON-NLS-1$
+        scrollPanel.getElement().getStyle().setProperty(MAX_WIDTH_STYLE, 
getMaxWidth(), Unit.PX);
+    }
+
+    private int getMaxWidth() {
+        int leftArrowWidth = scrollLeftButton.isVisible() ? 
scrollLeftButton.getWidget().getOffsetWidth() : 0;
+        int rightArrowWidth = scrollRightButton.isVisible() ? 
scrollRightButton.getWidget().getOffsetWidth() : 0;
+        return this.getElement().getOffsetWidth() - leftArrowWidth - 
rightArrowWidth;
+    }
+
+    @Override
+    public void onAttach() {
+        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
+
+            @Override
+            public void execute() {
+                recalculateWidgetBarMinWidth();
+                recalculateScrollPanelMaxWidth();
+                recalculateWidgetBarMinWidth();
+            }
+        });
+    }
+
+    /**
+     * Create and attach the scroll button images with a click handler
+     */
+    private void initScrollButtons()
+    {
+
+//        scrollLeftButton.setStyleName(SCROLL_BUTTON_STYLE);
+//        buttonContainer.insert(scrollLeftButton, 0);
+//        buttonContainer.setWidgetTopHeight(scrollLeftButton, 0, Unit.PX, 
scrollLeftButtonImage.getHeight(), Unit.PX);
+//        buttonContainer.setWidgetLeftWidth(scrollLeftButton, 0, Unit.PX, 
leftArrowWidth, Unit.PX);
+
+        
scrollLeftButton.addDomHandler(createScrollClickHandler(SCROLL_INTERVAL), 
ClickEvent.getType());
+        scrollLeftButton.setVisible(false);
+
+//        scrollRightButton.setStyleName(SCROLL_BUTTON_STYLE);
+//        buttonContainer.insert(scrollRightButton, 1);
+//        buttonContainer.setWidgetTopHeight(scrollRightButton, 0, Unit.PX, 
scrollRightButtonImage.getHeight(), Unit.PX);
+//        buttonContainer.setWidgetRightWidth(scrollRightButton, 0, Unit.PX, 
rightArrowWidth, Unit.PX);
+
+        
scrollRightButton.addDomHandler(createScrollClickHandler(-SCROLL_INTERVAL), 
ClickEvent.getType());
+        scrollRightButton.setVisible(false);
+
+//        Element parent = tabBar.getElement().getParentElement().cast();
+//        parent.getStyle().setMarginLeft(leftArrowWidth, Unit.PX);
+//        parent.getStyle().setMarginRight(rightArrowWidth, Unit.PX);
+        scrollTo(0);
+    }
+
+    private void showScrollButtons() {
+        // Defer size calculations until sizes are available.
+        // When calculating immediately after add(), all size methods return 
zero.
+        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
+
+            @Override
+            public void execute() {
+                recalculateScrollPanelMaxWidth();
+                boolean isScrolling = isScrollingNecessary();
+                if (scrollRightButton.isVisible()) {
+                    if (!isScrolling) {
+                        // The scroll buttons are being hidden, reset the 
scroll position to zero to avoid
+                        // having tabs starting in the middle of the window!
+                        scrollTo(0);
+                    } else {
+                        // Resizing or adding / removing tabs, recompute the 
scroll
+                        adjustScroll(0);
+                    }
+                }
+                scrollRightButton.setVisible(isScrolling);
+                scrollLeftButton.setVisible(isScrolling);
+            }
+        });
+    }
+
+    private ClickHandler createScrollClickHandler(final int diff) {
+        return new ClickHandler() {
+            @Override
+            public void onClick(ClickEvent event) {
+                adjustScroll(diff);
+            }
+        };
+    }
+
+    private boolean isScrollingNecessary() {
+        int minWidth = getWidgetMinWidthNeeded();
+        return minWidth > 0 && getMaxWidth() > 0 && getMaxWidth() <= minWidth;
+    }
+
+    private void adjustScroll(int diff) {
+        Widget lastTab = getLastTab();
+        if (lastTab == null) {
+            return;
+        }
+
+        int newLeft = 
parsePosition(widgetBar.getElement().getStyle().getLeft()) + diff;
+        int rightOfLastTab = getRightPosition(lastTab);
+
+        // Don't scroll for a positive newLeft
+        if (newLeft <= 0) {
+            // If we are about to scroll too far away from the right border, 
adjust back
+            int gap = rightOfLastTab - getTabBarWidth();
+            if (gap < -newLeft) {
+                newLeft += -newLeft - gap;
+            }
+            scrollTo(newLeft);
+        } else {
+            scrollTo(0);
+        }
+    }
+
+    private void scrollTo(int pos) {
+        widgetBar.getElement().getStyle().setLeft(pos, Unit.PX);
+    }
+
+    private Widget getLastTab() {
+        Widget result = null;
+        if (widgetBar.getWidgetCount() > 0) {
+            for(int i = widgetBar.getWidgetCount() - 1; i > 1; i--) {
+                Widget tab = widgetBar.getWidget(i);
+                if(tab.isVisible()) {
+                    result = tab;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    private int parsePosition(String positionString) {
+        int position = 0;
+        int sign = -1;
+        int i = 0;
+        if (positionString.charAt(0) == '-') {
+            sign = -1;
+            i++;
+        }
+        for (; i < positionString.length(); i++) {
+            char c = positionString.charAt(i);
+            if (c < '0' || c > '9') {
+                break;
+            }
+            position = 10 * position + c - '0';
+        }
+
+        return sign * position;
+    }
+
+    private int getRightPosition(Widget widget) {
+        return widget.getElement().getOffsetLeft() + 
widget.getElement().getOffsetWidth();
+    }
+
+    private int getTabBarWidth() {
+        return widgetBar.getElement().getParentElement().getClientWidth();
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.ui.xml
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.ui.xml
new file mode 100644
index 0000000..3284358
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/tab/ScrollableTabBar.ui.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" 
xmlns:g="urn:import:com.google.gwt.user.client.ui">
+    <ui:with field='resources' 
type='org.ovirt.engine.ui.common.CommonApplicationResources' />
+
+    <ui:style>
+        .scrollButton {
+            float: left;
+        }
+        .scrollPanel {
+            float: left;
+            overflow: hidden;
+        }
+        .widgetBar {
+            overflow-y: scroll;
+        }
+    </ui:style>
+
+    <g:HTMLPanel>
+        <g:FocusPanel ui:field="scrollLeftButton" 
addStyleNames="{style.scrollButton}">
+            <g:Image resource='{resources.refreshButtonImage}' />
+        </g:FocusPanel>
+        <g:FlowPanel ui:field="scrollPanel" 
addStyleNames="{style.scrollPanel}">
+            <g:FlowPanel ui:field="widgetBar" 
addStyleNames="{style.widgetBar}">
+            </g:FlowPanel>
+        </g:FlowPanel>
+        <g:FocusPanel ui:field="scrollRightButton" 
addStyleNames="{style.scrollButton}">
+            <g:Image resource='{resources.refreshButtonImage}' />
+        </g:FocusPanel>
+    </g:HTMLPanel>
+
+</ui:UiBinder>


-- 
To view, visit http://gerrit.ovirt.org/21716
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I63dddb3c0026ea3a5c13c3d18daebd02e13b1043
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Alexander Wels <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to