Alexander Wels has uploaded a new change for review. Change subject: webadmin: Double click collapse system tree ......................................................................
webadmin: Double click collapse system tree - Added quick way to collapse the system tree with a double click - Added ability for the client to remember the system tree width state. - Added a collapse button to quickly collapse the tree. - Added an expand button to expand the tree if it is hidden. Change-Id: Ida98ac456d9dd325ba1bf5676671bf53b5c3173e Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=999713 Signed-off-by: Alexander Wels <aw...@redhat.com> --- A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/css/TabbedSplitLayout.css M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.java A frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/main/TabbedSplitLayoutPanel.java A frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/collapse_splitter.png A frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/expand_splitter.png 5 files changed, 324 insertions(+), 5 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/21/23521/1 diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/css/TabbedSplitLayout.css b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/css/TabbedSplitLayout.css new file mode 100644 index 0000000..e0700d9 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/css/TabbedSplitLayout.css @@ -0,0 +1,10 @@ +.sliderButton { + border: 0px; + background: transparent; + width: 8px; + height: 16px; + z-index: 2; + padding: 0px 0px 0px 0px; + margin: 7px 0px 0px 0px; + position: absolute; +} \ No newline at end of file diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.java index 166a283..f9082f2 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.java @@ -23,10 +23,13 @@ import org.ovirt.engine.ui.webadmin.uicommon.model.TaskModelProvider; import org.ovirt.engine.ui.webadmin.widget.bookmark.BookmarkList; import org.ovirt.engine.ui.webadmin.widget.footer.AlertsEventsFooterView; +import org.ovirt.engine.ui.webadmin.widget.main.TabbedSplitLayoutPanel; import org.ovirt.engine.ui.webadmin.widget.tags.TagList; import org.ovirt.engine.ui.webadmin.widget.tree.SystemTree; import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.SelectionEvent; @@ -45,6 +48,7 @@ public class MainSectionView extends AbstractView implements MainSectionPresenter.ViewDef { private static final int BOOKMARK_INDEX = 1; + private static final int SPLITTER_THICKNESS = 4; interface ViewUiBinder extends UiBinder<Widget, MainSectionView> { ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class); @@ -100,8 +104,8 @@ ClientStorage clientStorage, CommonApplicationConstants commonConstants) { westStackPanel = createWestStackPanel(treeModelProvider, bookmarkModelProvider, tagModelProvider); - verticalSplitLayoutPanel = new SplitLayoutPanel(4); - horizontalSplitLayoutPanel = new SplitLayoutPanel(4); + verticalSplitLayoutPanel = new SplitLayoutPanel(SPLITTER_THICKNESS); + horizontalSplitLayoutPanel = new TabbedSplitLayoutPanel(SPLITTER_THICKNESS, clientStorage); initWidget(ViewUiBinder.uiBinder.createAndBindUi(this)); initHeaders(constants); @@ -121,6 +125,17 @@ clientStorage, constants); headerPanel.getElement().getParentElement().getStyle().setOverflow(Overflow.VISIBLE); + //Enable double clicking to collapse/expand the stack panel (with the treeview). + horizontalSplitLayoutPanel.setWidgetToggleDisplayAllowed(westStackPanel, true); + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + @Override + public void execute() { + //Manually call onResize() so the tabs at the top are positioned correctly. For some reason + //doing setWidgetSize doesn't trigger the onResize event. Also this need to be deferred + //otherwise the handlers haven't been added yet, and the resize won't do anything. + westStackPanel.onResize(); + } + }); } private void initHeaders(ApplicationConstants constants) { @@ -135,9 +150,9 @@ @Override public void onResize() { super.onResize(); - - if (uiHandlers != null) { - uiHandlers.setMainTabBarOffset(getOffsetWidth()); + Double westStackWidth = horizontalSplitLayoutPanel.getWidgetSize(westStackPanel); + if (uiHandlers != null && westStackWidth != null) { + uiHandlers.setMainTabBarOffset(westStackWidth.intValue()); } } }; diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/main/TabbedSplitLayoutPanel.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/main/TabbedSplitLayoutPanel.java new file mode 100644 index 0000000..6b23be3 --- /dev/null +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/main/TabbedSplitLayoutPanel.java @@ -0,0 +1,294 @@ +package org.ovirt.engine.ui.webadmin.widget.main; + +import org.ovirt.engine.ui.common.system.ClientStorage; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +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.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.LayoutPanel; +import com.google.gwt.user.client.ui.PushButton; +import com.google.gwt.user.client.ui.SplitLayoutPanel; +import com.google.gwt.user.client.ui.Widget; + +public class TabbedSplitLayoutPanel extends SplitLayoutPanel { + + /** + * Style sheet interface. + */ + public interface TabbedSplitLayoutCss extends CssResource { + String sliderButton(); + } + + /** + * Tabbed Split Layout panel resources interface. + */ + public interface TabbedSplitLayoutResources extends ClientBundle { + @Source("org/ovirt/engine/ui/common/css/TabbedSplitLayout.css") + TabbedSplitLayoutCss taggedSplitLayoutCss(); + + @Source("org/ovirt/engine/ui/webadmin/images/collapse_splitter.png") + ImageResource collapeSplitterButton(); + + @Source("org/ovirt/engine/ui/webadmin/images/expand_splitter.png") + ImageResource expandSplitterButton(); + } + + private static final String WEST_SPLITTER_KEY = "MAIN_WEST_SPLITTER_WIDTH"; //$NON-NLS-1$ + private static final Double DEFAULT_STACK_PANEL_WIDTH = 235.0; + + /** + * Tabbed Split Layout panel resources. + */ + private static final TabbedSplitLayoutResources SPLIT_LAYOUT_RESOURCES = + GWT.create(TabbedSplitLayoutResources.class); + + /** + * The style. + */ + private final TabbedSplitLayoutCss style; + + /** + * Collapse button. + */ + private final PushButton collapseLeft; + /** + * Expand button. + */ + private final PushButton expandLeft; + + /** + * {@code ScheduleCommand} that forces a layout when resizing the panel. + */ + private ScheduledCommand layoutCommand; + + /** + * Inserted WEST panel, that will contain the collapse button. + */ + private LayoutPanel westPanel = null; + /** + * Inserted CENTER panel, that will contain the expand button. + */ + private LayoutPanel centerPanel = null; + + /** + * Client storage to store the current west panel width in. + */ + final ClientStorage clientStorage; + + /** + * Constructor + * @param splitterSize Size width of the splitter bar. + */ + public TabbedSplitLayoutPanel(int splitterSize, ClientStorage storage) { + super(splitterSize); + clientStorage = storage; + style = SPLIT_LAYOUT_RESOURCES.taggedSplitLayoutCss(); + style.ensureInjected(); + collapseLeft = createButton(SPLIT_LAYOUT_RESOURCES.collapeSplitterButton()); + expandLeft = createButton(SPLIT_LAYOUT_RESOURCES.expandSplitterButton()); + } + + /** + * If the direction is WEST and the west panel has not been inserted yet, then create a new {@code LayoutPanel}, + * and insert the passed in {@code Widget} into that panel, and insert the panel into the {@code SplitLayoutPanel}. + * If the direction is CENTER and the center panel has not been inserted yet, then create a new {@code LayoutPanel}, + * and insert the passed in {@code Widget} into that panel, and insert the panel into the {@code SplitLayoutPanel}. + */ + @Override + public void insert(Widget child, Direction direction, double size, Widget before) { + Widget insertedWidget = child; + if (direction == Direction.WEST) { + if (westPanel == null) { + westPanel = new LayoutPanel(); + collapseLeft.setVisible(true); + westPanel.add(collapseLeft); + size = getStoredStackPanelWidth(); + } + westPanel.add(child); + insertedWidget = westPanel; + } else if (direction == Direction.CENTER) { + if (centerPanel == null) { + centerPanel = new LayoutPanel(); + centerPanel.add(expandLeft); + } + centerPanel.add(child); + insertedWidget = centerPanel; + } + super.insert(insertedWidget, direction, size, before); + } + + /** + * Create a new expand/collapse button. + * @param imageResource The {@code ImageResource} to use to style the button. + * @return A new {@code PushButton}. + */ + private PushButton createButton(ImageResource imageResource) { + PushButton result = new PushButton(new Image(imageResource), new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + toggleVisibleWestPanel(); + } + + }); + result.setVisible(false); + result.addStyleName(style.sliderButton()); + return result; + } + + /** + * Toggle the west panel. If it is visible, hide it and vice versa. + */ + private void toggleVisibleWestPanel() { + LayoutData layout = (LayoutData) westPanel.getLayoutData(); + if (layout.size == 0) { + double size = layout.oldSize; + if (size == 0) { + //The old size is 0, so we should restore the default size. + size = DEFAULT_STACK_PANEL_WIDTH; + } + // Restore the old size. + setWestPanelSize(size); + } else { + //Collapse to size 0. + layout.oldSize = layout.size; + setWestPanelSize(0); + } + } + + /** + * Set the west panel size. + * @param size The new size. + */ + private void setWestPanelSize(double size) { + LayoutData layout = (LayoutData) westPanel.getLayoutData(); + if (size == layout.size) { + return; + } + + layout.size = size; + // Defer actually updating the layout, so that if we receive many + // mouse events before layout/paint occurs, we'll only update once. + if (layoutCommand == null) { + layoutCommand = new ScheduledCommand() { + @Override + public void execute() { + layoutCommand = null; + forceLayout(); + } + }; + Scheduler.get().scheduleDeferred(layoutCommand); + } + } + + /** + * After load, set the the position of the collapse and expand buttons. Including visibility. + */ + @Override + public void onLoad() { + super.onLoad(); + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + + @Override + public void execute() { + determineButtonVisiblity(); + positionLeftCollapseButton(); + } + }); + } + + @Override + public void onResize() { + super.onResize(); + double currentWidth = westPanel.getOffsetWidth(); + setStoredSplitterWidth(currentWidth); + determineButtonVisiblity(); + positionLeftCollapseButton(); + } + + /** + * Determine if the expand or collapse button should be visible. + */ + private void determineButtonVisiblity() { + if (westPanel.getOffsetWidth() == 0) { // Completely collapsed. + expandLeft.setVisible(true); + collapseLeft.setVisible(false); + } else { + expandLeft.setVisible(false); + collapseLeft.setVisible(true); + } + } + + /** + * Position the collapse button to be proper in relation to the splitter bar. + */ + private void positionLeftCollapseButton() { + collapseLeft.getElement().getStyle().setLeft( + westPanel.getOffsetWidth() - collapseLeft.getOffsetWidth(), Unit.PX); + } + + @Override + public void setWidgetToggleDisplayAllowed(Widget widget, boolean allowed) { + super.setWidgetToggleDisplayAllowed(getActualWidget(widget), allowed); + } + + @Override + public void setWidgetSize(Widget widget, double size) { + super.setWidgetSize(getActualWidget(widget), size); + } + + @Override + public Double getWidgetSize(Widget widget) { + return super.getWidgetSize(getActualWidget(widget)); + } + + /** + * Determine if the passed in widget is part of the west or center panel, if so return the center or west panel + * as the widget, so the super class will handle the operation properly. + * @param widget The {@code Widget} to use to determine if we should return the panel or the widget. + * @return A {@code Widget} that is either the original, or a panel that contains the widget. + */ + private Widget getActualWidget(Widget widget) { + Widget checkedWidget = widget; + if (westPanel != null && widget.getParent() == westPanel) { + checkedWidget = westPanel; + } else if (centerPanel != null && widget.getParent() == centerPanel) { + checkedWidget = centerPanel; + } + return checkedWidget; + } + + /** + * Retrieve the stored stack panel width. + * @return The west stack panel width as a {@code double} + */ + private double getStoredStackPanelWidth() { + String widthString = clientStorage.getLocalItem(WEST_SPLITTER_KEY); + double width = DEFAULT_STACK_PANEL_WIDTH; //In case there was no stored width, use the default. + try { + if (widthString != null) { + width = Double.valueOf(widthString); + } + } catch (NumberFormatException nfe) { + //Do nothing. + } + return width; + } + + /** + * Store the current width in the {@code ClientStorage} of the browser so we can recall it when we log in. + * @param width The current width in pixels. + */ + private void setStoredSplitterWidth(Double width) { + clientStorage.setLocalItem(WEST_SPLITTER_KEY, width.toString()); + } + + +} diff --git a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/collapse_splitter.png b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/collapse_splitter.png new file mode 100644 index 0000000..feebe9f --- /dev/null +++ b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/collapse_splitter.png Binary files differ diff --git a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/expand_splitter.png b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/expand_splitter.png new file mode 100644 index 0000000..d61dd4a --- /dev/null +++ b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/webadmin/images/expand_splitter.png Binary files differ -- To view, visit http://gerrit.ovirt.org/23521 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ida98ac456d9dd325ba1bf5676671bf53b5c3173e Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.4 Gerrit-Owner: Alexander Wels <aw...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches