From 3e4a244e5a5623fbda7da9a07ade7253fe11148d Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Mon, 11 Aug 2008 07:58:18 +0000 Subject: [PATCH] caption and icon setters to Paintable interface, major tabsheet refactoring, client side caption handling for layouts svn changeset:5161/svn branch:trunk --- WebContent/ITMILL/themes/default/styles.css | 45 ++-- .../themes/default/tabsheet/tabsheet.css | 45 ++-- .../terminal/gwt/client/ui/IAccordion.java | 80 ++++--- .../terminal/gwt/client/ui/ICustomLayout.java | 5 +- .../terminal/gwt/client/ui/IExpandLayout.java | 3 +- .../toolkit/terminal/gwt/client/ui/IForm.java | 2 +- .../terminal/gwt/client/ui/IFormLayout.java | 2 +- .../terminal/gwt/client/ui/IGridLayout.java | 2 +- .../gwt/client/ui/IOrderedLayout.java | 2 +- .../terminal/gwt/client/ui/ITabsheet.java | 200 +++++++++++++----- .../terminal/gwt/client/ui/ITabsheetBase.java | 110 +++------- .../gwt/client/ui/ITabsheetPanel.java | 67 ++++-- .../ui/absolutegrid/ISizeableGridLayout.java | 2 +- src/com/itmill/toolkit/ui/Component.java | 19 ++ src/com/itmill/toolkit/ui/TabSheet.java | 70 +++--- 15 files changed, 374 insertions(+), 280 deletions(-) diff --git a/WebContent/ITMILL/themes/default/styles.css b/WebContent/ITMILL/themes/default/styles.css index c7a31d2d2c..0df4710565 100644 --- a/WebContent/ITMILL/themes/default/styles.css +++ b/WebContent/ITMILL/themes/default/styles.css @@ -1852,16 +1852,29 @@ i-orderedlayout-margin-top { text-align: left /* Force default alignment */ } - .i-tabsheet-tabs { empty-cells: hide; border-collapse: collapse; + margin:0; + padding:0; + border:0; height: 38px; background: transparent url(tabsheet/img/tabs-bg.png) repeat-x bottom left; width: 100%; overflow:hidden; } +.i-tabsheet-tabs td { + margin:0; + padding:0; +} + +.i-tabsheet-tabs .i-tabsheet-spacertd { + width: 100%; + height: 37px; + border: 1px solid #b6bbbc; +} + .i-tabsheet-hidetabs .i-tabsheet-tabcontainer { display: none; } @@ -1919,17 +1932,7 @@ i-orderedlayout-margin-top { white-space: nowrap; } -.i-tabsheet-tabs .gwt-TabBarFirst { - display: none; -} - -.i-tabsheet-tabs .gwt-TabBarRest { - border: 1px solid #b6bbbc; - background: #f8f9f9 url(tabsheet/img/tab-bg.png); - height: 37px; -} - -.i-tabsheet-tabs .gwt-TabBarItem { +.i-tabsheet-tabs .i-tabsheet-tabitem { border: 1px solid #b6bbbc; border-right: none; height: 20px; @@ -1942,7 +1945,7 @@ i-orderedlayout-margin-top { cursor: pointer; } -.i-tabsheet-tabs .gwt-TabBarItem-selected { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: none; background: transparent url(panel/img/top-left.png) no-repeat; margin: 0; @@ -1952,15 +1955,15 @@ i-orderedlayout-margin-top { color: #ee5311; } -.i-tabsheet-tabs .gwt-TabBarItem:hover { +.i-tabsheet-tabs .i-tabsheet-tabitem:hover { color: #4b5257; } -.i-tabsheet-tabs .gwt-TabBarItem-selected:hover { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected:hover { color: #ee5311; } -.i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent url(panel/img/top-right.png) repeat-x right top; margin: 0 -1px 0 9px; height: 18px; @@ -1997,7 +2000,7 @@ i-orderedlayout-margin-top { /* Progress indication */ -.i-tabsheet-loading .i-tabsheet-tabs .gwt-TabBarItem-selected span{ +.i-tabsheet-loading .i-tabsheet-tabs .i-tabsheet-tabitem-selected span{ background: transparent url(common/img/ajax-loader.gif) no-repeat; display: block; margin-left: -10px; @@ -2023,7 +2026,7 @@ i-orderedlayout-margin-top { height: 46px; } -* html .i-tabsheet-tabs .gwt-TabBarItem-selected { +* html .i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: 1px solid #babfc0; border-bottom: none; background: #fff; @@ -2033,7 +2036,7 @@ i-orderedlayout-margin-top { cursor: default; color: #ee5311; } -*+html .i-tabsheet-tabs .gwt-TabBarItem-selected { +*+html .i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: 1px solid #babfc0; border-bottom: none; background: #fff; @@ -2044,12 +2047,12 @@ i-orderedlayout-margin-top { color: #ee5311; } -* html .i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +* html .i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent; padding: 0; margin: 0; } -*+html .i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +*+html .i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent; padding: 0; margin: 0; diff --git a/WebContent/ITMILL/themes/default/tabsheet/tabsheet.css b/WebContent/ITMILL/themes/default/tabsheet/tabsheet.css index c9194476ff..9be11e7dca 100644 --- a/WebContent/ITMILL/themes/default/tabsheet/tabsheet.css +++ b/WebContent/ITMILL/themes/default/tabsheet/tabsheet.css @@ -5,16 +5,29 @@ text-align: left /* Force default alignment */ } - .i-tabsheet-tabs { empty-cells: hide; border-collapse: collapse; + margin:0; + padding:0; + border:0; height: 38px; background: transparent url(img/tabs-bg.png) repeat-x bottom left; width: 100%; overflow:hidden; } +.i-tabsheet-tabs td { + margin:0; + padding:0; +} + +.i-tabsheet-tabs .i-tabsheet-spacertd { + width: 100%; + height: 37px; + border: 1px solid #b6bbbc; +} + .i-tabsheet-hidetabs .i-tabsheet-tabcontainer { display: none; } @@ -72,17 +85,7 @@ white-space: nowrap; } -.i-tabsheet-tabs .gwt-TabBarFirst { - display: none; -} - -.i-tabsheet-tabs .gwt-TabBarRest { - border: 1px solid #b6bbbc; - background: #f8f9f9 url(img/tab-bg.png); - height: 37px; -} - -.i-tabsheet-tabs .gwt-TabBarItem { +.i-tabsheet-tabs .i-tabsheet-tabitem { border: 1px solid #b6bbbc; border-right: none; height: 20px; @@ -95,7 +98,7 @@ cursor: pointer; } -.i-tabsheet-tabs .gwt-TabBarItem-selected { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: none; background: transparent url(../panel/img/top-left.png) no-repeat; margin: 0; @@ -105,15 +108,15 @@ color: #ee5311; } -.i-tabsheet-tabs .gwt-TabBarItem:hover { +.i-tabsheet-tabs .i-tabsheet-tabitem:hover { color: #4b5257; } -.i-tabsheet-tabs .gwt-TabBarItem-selected:hover { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected:hover { color: #ee5311; } -.i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +.i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent url(../panel/img/top-right.png) repeat-x right top; margin: 0 -1px 0 9px; height: 18px; @@ -150,7 +153,7 @@ /* Progress indication */ -.i-tabsheet-loading .i-tabsheet-tabs .gwt-TabBarItem-selected span{ +.i-tabsheet-loading .i-tabsheet-tabs .i-tabsheet-tabitem-selected span{ background: transparent url(../common/img/ajax-loader.gif) no-repeat; display: block; margin-left: -10px; @@ -176,7 +179,7 @@ height: 46px; } -* html .i-tabsheet-tabs .gwt-TabBarItem-selected { +* html .i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: 1px solid #babfc0; border-bottom: none; background: #fff; @@ -186,7 +189,7 @@ cursor: default; color: #ee5311; } -*+html .i-tabsheet-tabs .gwt-TabBarItem-selected { +*+html .i-tabsheet-tabs .i-tabsheet-tabitem-selected { border: 1px solid #babfc0; border-bottom: none; background: #fff; @@ -197,12 +200,12 @@ color: #ee5311; } -* html .i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +* html .i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent; padding: 0; margin: 0; } -*+html .i-tabsheet-tabs .gwt-TabBarItem-selected .i-caption { +*+html .i-tabsheet-tabs .i-tabsheet-tabitem-selected .i-caption { background: transparent; padding: 0; margin: 0; diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java index bd591bd229..af2cc4a0d6 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java @@ -13,6 +13,7 @@ import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; +import com.itmill.toolkit.terminal.gwt.client.BrowserInfo; import com.itmill.toolkit.terminal.gwt.client.Caption; import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener; import com.itmill.toolkit.terminal.gwt.client.Paintable; @@ -33,7 +34,7 @@ public class IAccordion extends ITabsheetBase implements public IAccordion() { super(CLASSNAME); // IE6 needs this to calculate offsetHeight correctly - if (Util.isIE6()) { + if (BrowserInfo.get().isIE6()) { DOM.setStyleAttribute(getElement(), "zoom", "1"); } } @@ -51,25 +52,24 @@ public class IAccordion extends ITabsheetBase implements } protected void renderTab(UIDL tabUidl, int index, boolean selected) { - // TODO check indexes, now new tabs get placed last (changing tab order - // is not supported from server-side) - - StackItem item = new StackItem(tabUidl); - - if (stack.size() == 0) { - item.addStyleDependentName("first"); + StackItem item; + if (stack.size() <= index) { + item = new StackItem(tabUidl); + if (stack.size() == 0) { + item.addStyleDependentName("first"); + } + stack.add(item); + add(item, getElement()); + } else { + item = (StackItem) stack.get(index); + item.updateCaption(tabUidl); } - stack.add(item); - add(item, getElement()); - if (selected) { item.open(); item.setContent(tabUidl.getChildUIDL(0)); } else if (tabUidl.getChildCount() > 0) { - // updating a drawn child on hidden tab - Paintable paintable = client.getPaintable(tabUidl.getChildUIDL(0)); - paintable.updateFromUIDL(tabUidl.getChildUIDL(0), client); + item.setContent(tabUidl.getChildUIDL(0)); } } @@ -169,16 +169,14 @@ public class IAccordion extends ITabsheetBase implements private Caption caption; private boolean open = false; - private Element content; - private Element captionNode; + private Element content = DOM.createDiv(); + private Element captionNode = DOM.createDiv(); private Paintable paintable; public StackItem(UIDL tabUidl) { setElement(DOM.createDiv()); caption = new Caption(null, client); caption.addClickListener(this); - content = DOM.createDiv(); - captionNode = DOM.createDiv(); super.add(caption, captionNode); DOM.appendChild(captionNode, caption.getElement()); DOM.appendChild(getElement(), captionNode); @@ -189,13 +187,13 @@ public class IAccordion extends ITabsheetBase implements DOM.setElementProperty(captionNode, "className", CLASSNAME + "-item-caption"); DOM.setStyleAttribute(content, "overflow", "auto"); - DOM.setStyleAttribute(content, "display", "none"); // Force 'hasLayout' in IE6 (prevents layout problems) - if (Util.isIE6()) { + if (BrowserInfo.get().isIE6()) { DOM.setStyleAttribute(content, "zoom", "1"); } + close(); - caption.updateCaption(tabUidl); + updateCaption(tabUidl); } public Element getContainerElement() { @@ -212,7 +210,11 @@ public class IAccordion extends ITabsheetBase implements public void open() { open = true; - DOM.setStyleAttribute(content, "display", ""); + if (getPaintable() != null) { + remove(getPaintable()); + } + DOM.setStyleAttribute(content, "visibility", ""); + DOM.setStyleAttribute(content, "position", ""); addStyleDependentName("open"); if (getPaintable() != null) { add(getPaintable(), content); @@ -221,10 +223,8 @@ public class IAccordion extends ITabsheetBase implements public void close() { open = false; - if (getPaintable() != null) { - remove(getPaintable()); - } - DOM.setStyleAttribute(content, "display", "none"); + DOM.setStyleAttribute(content, "visibility", "hidden"); + DOM.setStyleAttribute(content, "position", "absolute"); removeStyleDependentName("open"); } @@ -234,8 +234,6 @@ public class IAccordion extends ITabsheetBase implements public void setContent(UIDL contentUidl) { final Paintable newPntbl = client.getPaintable(contentUidl); - // due hack #1 in ITabsheetBase - ((Widget) newPntbl).setVisible(true); if (getPaintable() == null) { add((Widget) newPntbl, content); paintables.add(newPntbl); @@ -253,6 +251,10 @@ public class IAccordion extends ITabsheetBase implements public void onClick(Widget sender) { onSelectTab(this); } + + public void updateCaption(UIDL uidl) { + caption.updateCaption(uidl); + } } protected void clearPaintables() { @@ -264,4 +266,26 @@ public class IAccordion extends ITabsheetBase implements return paintables.iterator(); } + public boolean hasChildComponent(Widget component) { + if (paintables.contains(component)) { + return true; + } else { + return false; + } + } + + public void replaceChildComponent(Widget oldComponent, Widget newComponent) { + // TODO Auto-generated method stub + } + + public void updateCaption(Paintable component, UIDL uidl) { + for (Iterator iterator = stack.iterator(); iterator.hasNext();) { + StackItem si = (StackItem) iterator.next(); + if (si.getPaintable() == component) { + si.updateCaption(uidl); + return; + } + } + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java index 366257fcaa..8b7349d187 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java @@ -109,12 +109,11 @@ public class ICustomLayout extends ComplexPanel implements Paintable, /** Update the layout from UIDL */ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { this.client = client; - // Client manages general cases - if (client.updateComponent(this, uidl, false)) { + // ApplicationConnection manages generic component features + if (client.updateComponent(this, uidl, true)) { return; } - // Update PID pid = uidl.getId(); if (!hasTemplate()) { // Update HTML template only once diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java index e4f86ec1cb..7c2f61e4fa 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java @@ -616,8 +616,7 @@ public class IExpandLayout extends ComplexPanel implements // Modify layout margins handleMargins(uidl); - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java index 6722e1e421..8613f0bfde 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java @@ -54,7 +54,7 @@ public class IForm extends ComplexPanel implements Paintable, } public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java index a476e263d9..beb7c82b9a 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java @@ -34,7 +34,7 @@ public class IFormLayout extends FlexTable implements Container { public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { this.client = client; - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java index d62f630000..c1a9b0dee3 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java @@ -70,7 +70,7 @@ public class IGridLayout extends SimplePanel implements Paintable, Container, public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } final MarginInfo margins = new MarginInfo(uidl diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java index f6ec503857..3bd5a469e2 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java @@ -212,7 +212,7 @@ public class IOrderedLayout extends Panel implements Container, updateMarginAndSpacingSizesFromCSS(uidl); // Update sizes, ... - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java index 3c76cbd47b..64fb4fccd6 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java @@ -4,6 +4,7 @@ package com.itmill.toolkit.terminal.gwt.client.ui; +import java.util.HashMap; import java.util.Iterator; import com.google.gwt.user.client.Command; @@ -11,10 +12,9 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.SourcesTabEvents; -import com.google.gwt.user.client.ui.TabBar; -import com.google.gwt.user.client.ui.TabListener; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; import com.itmill.toolkit.terminal.gwt.client.Caption; @@ -26,6 +26,77 @@ import com.itmill.toolkit.terminal.gwt.client.Util; public class ITabsheet extends ITabsheetBase implements ContainerResizedListener { + class TabBar extends ComplexPanel implements ClickListener { + + private Element tr = DOM.createTR(); + + private Element spacerTd = DOM.createTD(); + + TabBar() { + Element el = DOM.createTable(); + Element tbody = DOM.createTBody(); + DOM.appendChild(el, tbody); + DOM.appendChild(tbody, tr); + setStyleName(spacerTd, CLASSNAME + "-spacertd"); + DOM.appendChild(tr, spacerTd); + setElement(el); + } + + protected Element getContainerElement() { + return tr; + } + + private Widget oldSelected; + + public int getTabCount() { + return getWidgetCount(); + } + + public void addTab(Caption c) { + Element td = DOM.createTD(); + setStyleName(td, CLASSNAME + "-tabitemcell"); + Element div = DOM.createTD(); + setStyleName(div, CLASSNAME + "-tabitem"); + DOM.appendChild(td, div); + DOM.insertBefore(tr, td, spacerTd); + c.addClickListener(this); + add(c, div); + } + + public void onClick(Widget sender) { + int index = getWidgetIndex(sender); + onTabSelected(index); + } + + public void selectTab(int index) { + Widget newSelected = getWidget(index); + Widget.setStyleName(DOM.getParent(newSelected.getElement()), + CLASSNAME + "-tabitem-selected", true); + if (oldSelected != null) { + Widget.setStyleName(DOM.getParent(oldSelected.getElement()), + CLASSNAME + "-tabitem-selected", false); + } + oldSelected = newSelected; + } + + public void removeTab(int i) { + remove(i); + } + + public boolean remove(Widget w) { + ((Caption) w).removeClickListener(this); + return super.remove(w); + } + + public Caption getTab(int index) { + if (index >= getWidgetCount()) { + return null; + } + return (Caption) getWidget(index); + } + + } + public static final String CLASSNAME = "i-tabsheet"; public static final String TABS_CLASSNAME = "i-tabsheet-tabcontainer"; @@ -40,6 +111,8 @@ public class ITabsheet extends ITabsheetBase implements private final ITabsheetPanel tp; private final Element contentNode, deco; + private final HashMap captions = new HashMap(); + private String height; private String width; @@ -52,41 +125,31 @@ public class ITabsheet extends ITabsheetBase implements */ private Widget previousVisibleWidget; - private final TabListener tl = new TabListener() { - - public void onTabSelected(SourcesTabEvents sender, final int tabIndex) { - if (client != null && activeTabIndex != tabIndex) { - addStyleDependentName("loading"); - // run updating variables in deferred command to bypass some - // FF - // optimization issues - DeferredCommand.addCommand(new Command() { - public void execute() { - previousVisibleWidget = tp.getWidget(tp - .getVisibleWidget()); - DOM.setStyleAttribute(previousVisibleWidget - .getElement(), "visibility", "hidden"); - client.updateVariable(id, "selected", tabKeys.get( - tabIndex).toString(), true); - } - }); - waitingForResponse = true; - } + private void onTabSelected(final int tabIndex) { + if (disabled || waitingForResponse) { + return; } - - public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) { - if (disabled || waitingForResponse) { - return false; - } - final Object tabKey = tabKeys.get(tabIndex); - if (disabledTabKeys.contains(tabKey)) { - return false; - } - - return true; + final Object tabKey = tabKeys.get(tabIndex); + if (disabledTabKeys.contains(tabKey)) { + return; } - - }; + if (client != null && activeTabIndex != tabIndex) { + addStyleDependentName("loading"); + // run updating variables in deferred command to bypass some + // FF + // optimization issues + DeferredCommand.addCommand(new Command() { + public void execute() { + previousVisibleWidget = tp.getWidget(tp.getVisibleWidget()); + DOM.setStyleAttribute(previousVisibleWidget.getElement(), + "visibility", "hidden"); + client.updateVariable(id, "selected", tabKeys.get(tabIndex) + .toString(), true); + } + }); + waitingForResponse = true; + } + } public ITabsheet() { super(CLASSNAME); @@ -133,11 +196,9 @@ public class ITabsheet extends ITabsheetBase implements DOM.appendChild(tabs, scroller); - tb.addTabListener(tl); - // TODO Use for Safari only. Fix annoying 1px first cell in TabBar. - DOM.setStyleAttribute(DOM.getFirstChild(DOM.getFirstChild(DOM - .getFirstChild(tb.getElement()))), "display", "none"); + // DOM.setStyleAttribute(DOM.getFirstChild(DOM.getFirstChild(DOM + // .getFirstChild(tb.getElement()))), "display", "none"); } @@ -217,21 +278,30 @@ public class ITabsheet extends ITabsheetBase implements } protected void renderTab(final UIDL tabUidl, int index, boolean selected) { - // TODO check indexes, now new tabs get placed last (changing tab order - // is not supported from server-side) - Caption c = new Caption(null, client); + Caption c = tb.getTab(index); + if (c == null) { + c = new Caption(null, client); + tb.addTab(c); + } c.updateCaption(tabUidl); - tb.addTab(c); + captions.put("" + index, c); if (selected) { renderContent(tabUidl.getChildUIDL(0)); tb.selectTab(index); - } else if (tabUidl.getChildCount() > 0) { - // updating a drawn child on hidden tab - Paintable paintable = client.getPaintable(tabUidl.getChildUIDL(0)); - paintable.updateFromUIDL(tabUidl.getChildUIDL(0), client); + } else { + if (tabUidl.getChildCount() > 0) { + // updating a drawn child on hidden tab + Paintable paintable = client.getPaintable(tabUidl + .getChildUIDL(0)); + + if (tp.getWidgetIndex((Widget) paintable) < 0) { + tp.insert((Widget) paintable, index); + } + paintable.updateFromUIDL(tabUidl.getChildUIDL(0), client); + } else if (tp.getWidgetCount() <= index) { + tp.add(new Label("")); + } } - // Add place-holder content - tp.add(new Label("")); } protected void selectTab(int index, final UIDL contentUidl) { @@ -347,9 +417,9 @@ public class ITabsheet extends ITabsheetBase implements private void showAllTabs() { scrollerIndex = 0; + Element tr = DOM.getFirstChild(DOM.getFirstChild(tb.getElement())); for (int i = 0; i < tb.getTabCount(); i++) { - DOM.setStyleAttribute(DOM.getChild(DOM.getFirstChild(DOM - .getFirstChild(tb.getElement())), i + 1), "display", ""); + DOM.setStyleAttribute(DOM.getChild(tr, i), "display", ""); } } @@ -369,15 +439,29 @@ public class ITabsheet extends ITabsheetBase implements } tp.clear(); - // Get rid of unnecessary 100% cell heights in TabBar (really ugly hack) - final Element tr = DOM.getChild(DOM.getChild(tb.getElement(), 0), 0); - final Element rest = DOM.getChild(DOM.getChild(tr, DOM - .getChildCount(tr) - 1), 0); - DOM.removeElementAttribute(rest, "style"); - } protected Iterator getPaintableIterator() { return tp.iterator(); } + + public boolean hasChildComponent(Widget component) { + if (tp.getWidgetIndex(component) < 0) { + return false; + } else { + return true; + } + } + + public void replaceChildComponent(Widget oldComponent, Widget newComponent) { + int widgetIndex = tp.getWidgetIndex(oldComponent); + tp.remove(oldComponent); + tp.insert(newComponent, widgetIndex); + } + + public void updateCaption(Paintable component, UIDL uidl) { + int i = tp.getWidgetIndex((Widget) component); + Caption c = (Caption) captions.get("" + i); + c.updateCaption(uidl); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java index 05a77cfaf2..65e1a1f07e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java @@ -9,16 +9,16 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; +import com.itmill.toolkit.terminal.gwt.client.Container; import com.itmill.toolkit.terminal.gwt.client.Paintable; import com.itmill.toolkit.terminal.gwt.client.UIDL; -abstract class ITabsheetBase extends ComplexPanel implements Paintable { +abstract class ITabsheetBase extends ComplexPanel implements Container { String id; ApplicationConnection client; protected final ArrayList tabKeys = new ArrayList(); - protected final ArrayList captions = new ArrayList(); protected int activeTabIndex = 0; protected boolean disabled; protected boolean readonly; @@ -43,73 +43,46 @@ abstract class ITabsheetBase extends ComplexPanel implements Paintable { // Render content final UIDL tabs = uidl.getChildUIDL(0); - if (keepCurrentTabs(uidl)) { - int index = 0; - for (final Iterator it = tabs.getChildIterator(); it.hasNext();) { - final UIDL tab = (UIDL) it.next(); - final boolean selected = tab.getBooleanAttribute("selected"); - if (selected) { - selectTab(index, tab.getChildUIDL(0)); - } else if (tab.getChildCount() > 0) { - // updating a drawn child on hidden tab - Paintable paintable = client.getPaintable(tab - .getChildUIDL(0)); - // TODO widget may flash on screen - paintable.updateFromUIDL(tab.getChildUIDL(0), client); - // Hack #1 in ITabsheetBase: due ITabsheets content has no - // wrappers for each tab, we need to hide the actual widgets - ((Widget) paintable).setVisible(false); - } - index++; - } - } else { + ArrayList oldPaintables = new ArrayList(); + for (Iterator iterator = getPaintableIterator(); iterator.hasNext();) { + oldPaintables.add(iterator.next()); + } - ArrayList oldPaintables = new ArrayList(); - for (Iterator iterator = getPaintableIterator(); iterator.hasNext();) { - oldPaintables.add(iterator.next()); - } + // Clear previous values + tabKeys.clear(); + disabledTabKeys.clear(); - // Clear previous values - tabKeys.clear(); - captions.clear(); - disabledTabKeys.clear(); - - clearPaintables(); - - int index = 0; - for (final Iterator it = tabs.getChildIterator(); it.hasNext();) { - final UIDL tab = (UIDL) it.next(); - final String key = tab.getStringAttribute("key"); - final boolean selected = tab.getBooleanAttribute("selected"); - String caption = tab.getStringAttribute("caption"); - if (caption == null) { - caption = " "; - } + int index = 0; + for (final Iterator it = tabs.getChildIterator(); it.hasNext();) { + final UIDL tab = (UIDL) it.next(); + final String key = tab.getStringAttribute("key"); + final boolean selected = tab.getBooleanAttribute("selected"); - if (tab.getBooleanAttribute("disabled")) { - disabledTabKeys.add(key); - } + if (tab.getBooleanAttribute("disabled")) { + disabledTabKeys.add(key); + } - captions.add(caption); - tabKeys.add(key); + tabKeys.add(key); - if (selected) { - activeTabIndex = index; - } - if (tab.getChildCount() > 0) { - Paintable p = client.getPaintable(tab.getChildUIDL(0)); - oldPaintables.remove(p); - } - renderTab(tab, index, selected); - index++; + if (selected) { + activeTabIndex = index; + } + if (tab.getChildCount() > 0) { + Paintable p = client.getPaintable(tab.getChildUIDL(0)); + oldPaintables.remove(p); } + renderTab(tab, index, selected); + index++; + } - for (Iterator iterator = oldPaintables.iterator(); iterator - .hasNext();) { - Object oldPaintable = iterator.next(); - if (oldPaintable instanceof Paintable) { - client.unregisterPaintable((Paintable) oldPaintable); + for (Iterator iterator = oldPaintables.iterator(); iterator.hasNext();) { + Object oldPaintable = iterator.next(); + if (oldPaintable instanceof Paintable) { + Widget w = (Widget) oldPaintable; + if (w.isAttached()) { + w.removeFromParent(); } + client.unregisterPaintable((Paintable) oldPaintable); } } @@ -125,21 +98,6 @@ abstract class ITabsheetBase extends ComplexPanel implements Paintable { */ abstract protected void clearPaintables(); - protected boolean keepCurrentTabs(UIDL uidl) { - final UIDL tabs = uidl.getChildUIDL(0); - boolean retval = tabKeys.size() == tabs.getNumberOfChildren(); - for (int i = 0; retval && i < tabKeys.size(); i++) { - String key = (String) tabKeys.get(i); - UIDL tabUIDL = tabs.getChildUIDL(i); - retval = key.equals(tabUIDL.getStringAttribute("key")) - && captions.get(i).equals( - tabUIDL.getStringAttribute("caption")) - && (tabUIDL.hasAttribute("disabled") == disabledTabKeys - .contains(key)); - } - return retval; - } - /** * Implement in extending classes. This method should render needed elements * and set the visibility of the tab according to the 'selected' parameter. diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java index 01ac63645e..d07d720f9c 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java @@ -5,13 +5,14 @@ package com.itmill.toolkit.terminal.gwt.client.ui; import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; /** * A panel that displays all of its child widgets in a 'deck', where only one * can be visible at a time. It is used by - * {@link com.itmill.toolkit.terminal.gwt.client.ui.ITabsheetPanel}. + * {@link com.itmill.toolkit.terminal.gwt.client.ui.ITabsheet}. * * This class has the same basic functionality as the GWT DeckPanel * {@link com.google.gwt.user.client.ui.DeckPanel}, with the exception that it @@ -20,6 +21,7 @@ import com.google.gwt.user.client.ui.Widget; public class ITabsheetPanel extends ComplexPanel { private Widget visibleWidget; + private boolean fullheight = false; /** * Creates an empty tabsheet panel. @@ -35,8 +37,15 @@ public class ITabsheetPanel extends ComplexPanel { * the widget to be added */ public void add(Widget w) { - super.add(w, getElement()); - initChildWidget(w); + Element el = createContainerElement(); + DOM.appendChild(getElement(), el); + super.add(w, el); + } + + private Element createContainerElement() { + Element el = DOM.createDiv(); + hide(el); + return el; } /** @@ -59,18 +68,21 @@ public class ITabsheetPanel extends ComplexPanel { * if beforeIndex is out of range */ public void insert(Widget w, int beforeIndex) { - super.insert(w, getElement(), beforeIndex, true); - initChildWidget(w); + Element el = createContainerElement(); + DOM.insertChild(getElement(), el, beforeIndex); + super.insert(w, el, beforeIndex, false); } public boolean remove(Widget w) { + final int index = getWidgetIndex(w); final boolean removed = super.remove(w); if (removed) { - resetChildWidget(w); - if (visibleWidget == w) { visibleWidget = null; } + Element child = DOM.getChild(getElement(), index); + DOM.removeChild(getElement(), child); + unHide(child); } return removed; } @@ -87,26 +99,39 @@ public class ITabsheetPanel extends ComplexPanel { Widget newVisible = getWidget(index); if (visibleWidget != newVisible) { if (visibleWidget != null) { - visibleWidget.setVisible(false); + hide(DOM.getParent(visibleWidget.getElement())); } visibleWidget = newVisible; - visibleWidget.setVisible(true); + unHide(DOM.getParent(visibleWidget.getElement())); } } - /** - * Make the widget invisible, and set its width and height to full. - */ - private void initChildWidget(Widget w) { - w.setVisible(false); + public void setHeight(String height) { + super.setHeight(height); + if ("100%".equals(height) && !fullheight) { + int childCount = DOM.getChildCount(getElement()); + for (int i = 0; i < childCount; i++) { + DOM.setStyleAttribute(DOM.getChild(getElement(), i), "height", + "100%"); + } + fullheight = true; + } else if (fullheight) { + int childCount = DOM.getChildCount(getElement()); + for (int i = 0; i < childCount; i++) { + DOM.setStyleAttribute(DOM.getChild(getElement(), i), "height", + ""); + } + fullheight = false; + } } - /** - * Make the widget visible, and clear the widget's width and height - * attributes. This is done so that any changes to the visibility, height, - * or width of the widget that were done by the panel are undone. - */ - private void resetChildWidget(Widget w) { - w.setVisible(true); + private void hide(Element e) { + DOM.setStyleAttribute(e, "visibility", "hidden"); + DOM.setStyleAttribute(e, "position", "absolute"); + } + + private void unHide(Element e) { + DOM.setStyleAttribute(e, "visibility", ""); + DOM.setStyleAttribute(e, "position", ""); } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java index f149fea15d..6b515765e1 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java @@ -37,7 +37,7 @@ public class ISizeableGridLayout extends AbsoluteGrid implements Paintable, public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { this.client = client; - if (client.updateComponent(this, uidl, false)) { + if (client.updateComponent(this, uidl, true)) { return; } diff --git a/src/com/itmill/toolkit/ui/Component.java b/src/com/itmill/toolkit/ui/Component.java index e500d17255..08628ddf5b 100644 --- a/src/com/itmill/toolkit/ui/Component.java +++ b/src/com/itmill/toolkit/ui/Component.java @@ -168,6 +168,16 @@ public interface Component extends Paintable, VariableOwner, Sizeable { */ public String getCaption(); + /** + * Sets the component's caption String. Caption is the + * visible name of the component. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param caption + * the new caption String for the component. + */ + public void setCaption(String caption); + /** * Gets the component's icon. A component may have a graphical icon * associated with it, this method retrieves it if it is defined. @@ -176,6 +186,15 @@ public interface Component extends Paintable, VariableOwner, Sizeable { */ public Resource getIcon(); + /** + * Sets the component's icon. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param icon + * the icon to be shown with the component's caption. + */ + public void setIcon(Resource icon); + /** * Gets the component's parent window. If the component does not yet belong * to a window null is returned. diff --git a/src/com/itmill/toolkit/ui/TabSheet.java b/src/com/itmill/toolkit/ui/TabSheet.java index 8aeed7c169..80cbb7a97d 100644 --- a/src/com/itmill/toolkit/ui/TabSheet.java +++ b/src/com/itmill/toolkit/ui/TabSheet.java @@ -5,7 +5,6 @@ package com.itmill.toolkit.ui; import java.lang.reflect.Method; -import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; @@ -32,16 +31,6 @@ public class TabSheet extends AbstractComponentContainer implements */ private final LinkedList tabs = new LinkedList(); - /** - * Tab -> caption mapping. - */ - private final Hashtable tabCaptions = new Hashtable(); - - /** - * Tab -> icon mapping . - */ - private final Hashtable tabIcons = new Hashtable(); - /** * Selected tab. */ @@ -85,7 +74,6 @@ public class TabSheet extends AbstractComponentContainer implements super.removeComponent(c); keyMapper.remove(c); tabs.remove(c); - tabCaptions.remove(c); if (c.equals(selected)) { if (tabs.isEmpty()) { selected = null; @@ -94,7 +82,6 @@ public class TabSheet extends AbstractComponentContainer implements fireSelectedTabChange(); } } - c.removeListener(this); requestRepaint(); } } @@ -111,21 +98,24 @@ public class TabSheet extends AbstractComponentContainer implements } /** - * Adds a new tab into TabSheet with overridden caption and icon. + * Adds a new tab into TabSheet. * * @param c * the component to be added onto tab. * @param caption - * the caption of the tab to be used instead of components - * own. + * the caption to be set for the component and used rendered + * in tab bar * @param icon - * the icon of the tab to be used instead of components own. + * the icon to be set for the component and used rendered in + * tab bar */ public void addTab(Component c, String caption, Resource icon) { if (c != null) { - tabCaptions.put(c, caption != null ? caption : ""); + if (caption != null) { + c.setCaption(caption); + } if (icon != null) { - tabIcons.put(c, icon); + c.setIcon(icon); } addTab(c); } @@ -147,7 +137,6 @@ public class TabSheet extends AbstractComponentContainer implements } super.addComponent(c); requestRepaint(); - c.addListener(this); } } @@ -273,20 +262,15 @@ public class TabSheet extends AbstractComponentContainer implements * the component. */ public String getTabCaption(Component c) { - String caption = (String) tabCaptions.get(c); - if (caption == null) { - caption = c.getCaption(); - } - if (caption == null) { - caption = ""; + if (c.getCaption() == null) { + return ""; + } else { + return c.getCaption(); } - return caption; } /** - * Sets overridden tab caption for given component. - * - * Normally TabSheet uses caption from component + * Sets tabs captions. * * @param c * the component. @@ -294,8 +278,9 @@ public class TabSheet extends AbstractComponentContainer implements * the caption to set. */ public void setTabCaption(Component c, String caption) { - tabCaptions.put(c, caption); - requestRepaint(); + if (tabs.contains(c)) { + c.setCaption(caption); + } } /** @@ -305,11 +290,7 @@ public class TabSheet extends AbstractComponentContainer implements * the component. */ public Resource getTabIcon(Component c) { - if (tabIcons.containsKey(c)) { - return (Resource) tabIcons.get(c); - } else { - return c.getIcon(); - } + return c.getIcon(); } /** @@ -321,12 +302,9 @@ public class TabSheet extends AbstractComponentContainer implements * @param icon */ public void setTabIcon(Component c, Resource icon) { - if (icon == null) { - tabIcons.remove(c); - } else { - tabIcons.put(c, icon); + if (tabs.contains(c)) { + c.setIcon(icon); } - requestRepaint(); } /** @@ -527,11 +505,13 @@ public class TabSheet extends AbstractComponentContainer implements } /* - * We need to repaint on child repaint due the way captions and icons are - * handled + * If child is not rendered on the client we need to repaint on child + * repaint due the way captions and icons are handled. */ public void repaintRequested(RepaintRequestEvent event) { - requestRepaint(); + if (!paintedTabs.contains(event.getPaintable())) { + requestRepaint(); + } } public void detach() { -- 2.39.5