From c60eaceb7543ba31a64e77fff6d496e90003bbe5 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Thu, 13 Mar 2008 11:23:46 +0000 Subject: [PATCH] fixes multiple issues with tabsheet, accordion, table etc svn changeset:4033/svn branch:trunk --- .../toolkit/terminal/gwt/client/Caption.java | 9 ++ .../terminal/gwt/client/ui/IAccordion.java | 103 +++++++++--------- .../terminal/gwt/client/ui/IScrollTable.java | 21 ++++ .../terminal/gwt/client/ui/ITabsheet.java | 76 +++++-------- .../terminal/gwt/client/ui/ITabsheetBase.java | 6 +- .../gwt/client/ui/ITabsheetPanel.java | 12 +- .../public/default/accordion/accordion.css | 9 -- .../gwt/public/default/button/button.css | 4 +- .../gwt/public/default/caption/caption.css | 7 ++ .../gwt/public/default/common/common.css | 4 +- .../gwt/public/default/tabsheet/tabsheet.css | 20 ++-- src/com/itmill/toolkit/ui/TabSheet.java | 77 ++++++++++--- 12 files changed, 203 insertions(+), 145 deletions(-) diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java index e92fb7ba82..e303cccae3 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java @@ -26,6 +26,13 @@ public class Caption extends HTML { private final ApplicationConnection client; + /** + * + * @param component + * optional owner of caption. If not set, getOwner will + * return null + * @param client + */ public Caption(Paintable component, ApplicationConnection client) { super(); this.client = client; @@ -133,6 +140,8 @@ public class Caption extends HTML { default: break; } + } else { + super.onBrowserEvent(event); } } 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 fa58eb3fcc..238be8c0ca 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java @@ -6,10 +6,11 @@ import com.google.gwt.user.client.Command; 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.SimplePanel; +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.Caption; import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener; import com.itmill.toolkit.terminal.gwt.client.Paintable; import com.itmill.toolkit.terminal.gwt.client.UIDL; @@ -51,11 +52,11 @@ public class IAccordion extends ITabsheetBase implements return (StackItem) stack.get(activeTabIndex); } - protected void renderTab(UIDL contentUidl, String caption, int index, - boolean selected) { + 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(caption); + + StackItem item = new StackItem(tabUidl); if (stack.size() == 0) { item.addStyleDependentName("first"); @@ -66,18 +67,18 @@ public class IAccordion extends ITabsheetBase implements if (selected) { item.open(); - item.setContent(contentUidl); + item.setContent(tabUidl.getChildUIDL(0)); } } protected void selectTab(final int index, final UIDL contentUidl) { + StackItem item = (StackItem) stack.get(index); if (index != activeTabIndex) { activeTabIndex = index; - StackItem item = (StackItem) stack.get(index); item.open(); iLayout(); - item.setContent(contentUidl); } + item.setContent(contentUidl); } public void onSelectTab(StackItem item) { @@ -119,7 +120,7 @@ public class IAccordion extends ITabsheetBase implements if (height != null && height != "") { // Detach visible widget from document flow for a while to calculate // used height correctly - Widget w = item.getWidget(); + Widget w = item.getPaintable(); String originalPositioning = ""; if (w != null) { originalPositioning = DOM.getStyleAttribute(w.getElement(), @@ -158,19 +159,25 @@ public class IAccordion extends ITabsheetBase implements Util.runDescendentsLayout(this); } - protected class StackItem extends SimplePanel { + /** + * TODO Caption widget not properly attached + */ + protected class StackItem extends ComplexPanel implements ClickListener { - private String caption; - private Element captionNode; + private Caption caption; private boolean open = false; private Element content; + private Element captionNode; + private Paintable paintable; - protected StackItem() { + public StackItem(UIDL tabUidl) { setElement(DOM.createDiv()); - captionNode = DOM.createDiv(); + caption = new Caption(null, client); + caption.addClickListener(this); content = DOM.createDiv(); - // Additional SPAN element for styling - DOM.appendChild(captionNode, DOM.createSpan()); + captionNode = DOM.createDiv(); + super.add(caption, captionNode); + DOM.appendChild(captionNode, caption.getElement()); DOM.appendChild(getElement(), captionNode); DOM.appendChild(getElement(), content); setStylePrimaryName(CLASSNAME + "-item"); @@ -184,37 +191,36 @@ public class IAccordion extends ITabsheetBase implements if (Util.isIE6()) { DOM.setStyleAttribute(content, "zoom", "1"); } - sinkEvents(Event.ONCLICK); - } - public StackItem(String caption) { - this(); - setCaption(caption); + caption.updateCaption(tabUidl); } - public StackItem(String caption, UIDL contentUidl) { - this(); - setCaption(caption); - setContent(contentUidl); - } - - public void setCaption(String caption) { - this.caption = caption; - DOM.setInnerText(DOM.getFirstChild(captionNode), caption); + public Element getContainerElement() { + return content; } - public String getCaption() { - return caption; + public Widget getPaintable() { + if (getWidgetCount() > 1) { + return getWidget(1); + } else { + return null; + } } public void open() { open = true; DOM.setStyleAttribute(content, "display", ""); addStyleDependentName("open"); + if (getPaintable() != null) { + add(getPaintable(), content); + } } public void close() { open = false; + if (getPaintable() != null) { + remove(getPaintable()); + } DOM.setStyleAttribute(content, "display", "none"); removeStyleDependentName("open"); } @@ -224,32 +230,21 @@ public class IAccordion extends ITabsheetBase implements } public void setContent(UIDL contentUidl) { - final Paintable content = client.getPaintable(contentUidl); - if (content != getWidget()) { - client.unregisterPaintable((Paintable) getWidget()); + final Paintable newPntbl = client.getPaintable(contentUidl); + if (getPaintable() == null) { + add((Widget) newPntbl, content); + } else if (getPaintable() != newPntbl) { + client.unregisterPaintable((Paintable) getWidget(1)); + remove(1); + add((Widget) newPntbl, content); } - setWidget((Widget) content); - content.updateFromUIDL(contentUidl, client); - } - - public Element getContainerElement() { - return content; + paintable = newPntbl; + paintable.updateFromUIDL(contentUidl, client); } - public Element getCaptionElement() { - return captionNode; + public void onClick(Widget sender) { + onSelectTab(this); } - - public void onBrowserEvent(Event evt) { - if (DOM.eventGetType(evt) == Event.ONCLICK) { - Element target = DOM.eventGetTarget(evt); - if (DOM.compare(target, captionNode) - || DOM.compare(target, DOM.getFirstChild(captionNode))) { - ((IAccordion) getParent()).onSelectTab(this); - } - } - } - } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IScrollTable.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IScrollTable.java index 111a209edc..bacfaa5039 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IScrollTable.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IScrollTable.java @@ -2122,4 +2122,25 @@ public class IScrollTable extends Composite implements Table, ScrollListener, // NOP size handled internally } + /* + * Overridden due Table might not survive of visibility change (scroll pos + * lost). Example ITabPanel just set contained components invisible and back + * when changing tabs. + */ + public void setVisible(boolean visible) { + if (isVisible() != visible) { + super.setVisible(visible); + if (initializedAndAttached) { + if (visible) { + DeferredCommand.addCommand(new Command() { + public void execute() { + bodyContainer.setScrollPosition(firstRowInViewPort + * tBody.getRowHeight()); + } + }); + } + } + } + } + } 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 9fde75cd11..13566d84f1 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java @@ -14,6 +14,7 @@ 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; import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener; import com.itmill.toolkit.terminal.gwt.client.Paintable; import com.itmill.toolkit.terminal.gwt.client.UIDL; @@ -125,13 +126,14 @@ public class ITabsheet extends ITabsheetBase implements } - protected void renderTab(final UIDL contentUidl, String caption, int index, - boolean selected) { + 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) - tb.addTab("" + caption + "", true); + Caption c = new Caption(null, client); + c.updateCaption(tabUidl); + tb.addTab(c); if (selected) { - renderContent(contentUidl); + renderContent(tabUidl.getChildUIDL(0)); tb.selectTab(index); } // Add place-holder content @@ -141,17 +143,30 @@ public class ITabsheet extends ITabsheetBase implements protected void selectTab(int index, final UIDL contentUidl) { if (index != activeTabIndex) { activeTabIndex = index; - renderContent(contentUidl); } + renderContent(contentUidl); } private void renderContent(final UIDL contentUIDL) { DeferredCommand.addCommand(new Command() { public void execute() { final Paintable content = client.getPaintable(contentUIDL); - tp.remove(activeTabIndex); - tp.insert((Widget) content, activeTabIndex); + if (tp.getWidgetCount() > activeTabIndex) { + Widget old = tp.getWidget(activeTabIndex); + if (old != content) { + tp.remove(activeTabIndex); + if (old instanceof Paintable) { + client.unregisterPaintable((Paintable) old); + } + tp.insert((Widget) content, activeTabIndex); + } + } else { + tp.add((Widget) content); + } + tp.showWidget(activeTabIndex); + + ITabsheet.this.iLayout(); (content).updateFromUIDL(contentUIDL, client); ITabsheet.this.removeStyleDependentName("loading"); if (previousVisibleWidget != null) { @@ -159,7 +174,6 @@ public class ITabsheet extends ITabsheetBase implements "visibility", ""); previousVisibleWidget = null; } - ITabsheet.this.iLayout(); } }); } @@ -210,50 +224,16 @@ public class ITabsheet extends ITabsheetBase implements public void iLayout() { if (height != null && height != "") { - - // Save scroll position - int scrollTop = DOM.getElementPropertyInt(contentNode, "scrollTop"); - int scrollLeft = DOM.getElementPropertyInt(contentNode, - "scrollLeft"); - - // Take content out of flow for a while - final String originalPositioning = DOM.getStyleAttribute(tp - .getElement(), "position"); - DOM.setStyleAttribute(tp.getElement(), "position", "absolute"); - - // Set defaults for content element - DOM.setStyleAttribute(contentNode, "overflow", "hidden"); - DOM.setStyleAttribute(contentNode, "height", ""); - - // Calculate target height super.setHeight(height); - final int targetHeight = getOffsetHeight(); - - // Calculate used height - super.setHeight(""); - final int usedHeight = DOM.getElementPropertyInt(deco, "offsetTop") - + DOM.getElementPropertyInt(deco, "offsetHeight") - - DOM.getElementPropertyInt(getElement(), "offsetTop"); - - // Calculate needed content area height - int newHeight = targetHeight - usedHeight; - if (newHeight < 0) { - newHeight = 0; - } - // Set proper values for content element - DOM.setStyleAttribute(contentNode, "height", newHeight + "px"); - tp.setHeight("100%"); + final int contentHeight = getOffsetHeight() + - DOM.getElementPropertyInt(deco, "offsetHeight") + - tb.getOffsetHeight(); + // Set proper values for content element + DOM.setStyleAttribute(contentNode, "height", contentHeight + "px"); DOM.setStyleAttribute(contentNode, "overflow", "auto"); - - // Restore content to normal flow - DOM.setStyleAttribute(tp.getElement(), "position", - originalPositioning); - - // Restore scroll position - DOM.setElementPropertyInt(contentNode, "scrollTop", scrollTop); - DOM.setElementPropertyInt(contentNode, "scrollLeft", scrollLeft); + tp.setHeight("100%"); } else { DOM.setStyleAttribute(contentNode, "height", ""); 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 044daf7162..b4f123ff0b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetBase.java @@ -69,7 +69,7 @@ abstract class ITabsheetBase extends FlowPanel implements Paintable { if (selected) { activeTabIndex = index; } - renderTab(tab.getChildUIDL(0), caption, index, selected); + renderTab(tab, index, selected); index++; } } @@ -92,8 +92,8 @@ abstract class ITabsheetBase extends FlowPanel implements Paintable { * Implement in extending classes. This method should render needed elements * and set the visibility of the tab according to the 'selected' parameter. */ - protected abstract void renderTab(final UIDL contentUidl, String caption, - int index, boolean selected); + protected abstract void renderTab(final UIDL tabUidl, int index, + boolean selected); /* * Implement in extending classes. This method should render any previously 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 8211ed6362..01ac63645e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java @@ -84,12 +84,14 @@ public class ITabsheetPanel extends ComplexPanel { */ public void showWidget(int index) { checkIndexBoundsForAccess(index); - - if (visibleWidget != null) { - visibleWidget.setVisible(false); + Widget newVisible = getWidget(index); + if (visibleWidget != newVisible) { + if (visibleWidget != null) { + visibleWidget.setVisible(false); + } + visibleWidget = newVisible; + visibleWidget.setVisible(true); } - visibleWidget = getWidget(index); - visibleWidget.setVisible(true); } /** diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/accordion/accordion.css b/src/com/itmill/toolkit/terminal/gwt/public/default/accordion/accordion.css index 21173b9940..05ef651b56 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/accordion/accordion.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/accordion/accordion.css @@ -16,11 +16,6 @@ cursor: pointer; } -.i-accordion-item-caption span { - padding-left: 16px; - background: transparent url(img/collapsed-icon.png) no-repeat 0 50%; -} - .i-accordion-item-open .i-accordion-item-caption { color: #3b4b57; background: #d5dee2 url(img/selected-bg.png); @@ -30,10 +25,6 @@ text-shadow: #fafafa 1px 1px 0; } -.i-accordion-item-open .i-accordion-item-caption span { - background: transparent url(img/expanded-icon.png) no-repeat 0 55%; -} - .i-accordion-item-content { border-top: 1px solid #c8cccd; } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/button/button.css b/src/com/itmill/toolkit/terminal/gwt/public/default/button/button.css index d52e6f51c9..2f8ffe0d28 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/button/button.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/button/button.css @@ -8,11 +8,11 @@ } .i-button-link { - border: 0px; + border: none; text-align: left; text-decoration: underline; background: none; - padding-left: 0px; + padding: 0; } .i-button-link span { text-decoration: underline; diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/caption/caption.css b/src/com/itmill/toolkit/terminal/gwt/public/default/caption/caption.css index ddea358265..22dad5bd31 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/caption/caption.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/caption/caption.css @@ -9,9 +9,16 @@ .i-errorindicator { width: 16px; height: 16px; + padding-right:2px; display: block; float:left; background: transparent url(../icons/16/error.png) no-repeat; + vertical-align: middle; +} + +.i-caption .i-icon { + padding-right:2px; + vertical-align: middle; } .i-error { diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/common/common.css b/src/com/itmill/toolkit/terminal/gwt/public/default/common/common.css index 1581d9060c..079f7f2f56 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/common/common.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/common/common.css @@ -105,7 +105,9 @@ cursor:pointer; } - +.i-label { + overflow: hidden; +} /* Loading indicator states */ diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/tabsheet/tabsheet.css b/src/com/itmill/toolkit/terminal/gwt/public/default/tabsheet/tabsheet.css index c1d395e6e0..565117e1fd 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/tabsheet/tabsheet.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/tabsheet/tabsheet.css @@ -12,6 +12,16 @@ height: 48px; background: transparent url(img/tabs-bg.png) repeat-x bottom left; width: 100%; + overflow:hidden; +} + +.i-tabsheet-tabs .i-caption { + white-space: nowrap; +} + +/* for IE (does not inherit) */ +.i-tabsheet-tabs .i-caption span { + white-space: nowrap; } .i-tabsheet-tabs .gwt-TabBarFirst { @@ -65,17 +75,11 @@ .i-tabsheet-content { border: 1px solid #babfc0; - border-top: none; - border-bottom: none; background-color: #fff; + border-bottom: none; + border-top: none; } -.i-tabsheet-tabsheetpanel { - border-top: 1px solid transparent; - border-bottom: 1px solid white; - margin-bottom: -1px; -} - .i-tabsheet-deco { height: 9px; background: transparent url(../panel/img/bottom-right.png) repeat-x right top; diff --git a/src/com/itmill/toolkit/ui/TabSheet.java b/src/com/itmill/toolkit/ui/TabSheet.java index 27ddabd9d7..2343b5452a 100644 --- a/src/com/itmill/toolkit/ui/TabSheet.java +++ b/src/com/itmill/toolkit/ui/TabSheet.java @@ -14,6 +14,7 @@ import com.itmill.toolkit.terminal.KeyMapper; import com.itmill.toolkit.terminal.PaintException; import com.itmill.toolkit.terminal.PaintTarget; import com.itmill.toolkit.terminal.Resource; +import com.itmill.toolkit.terminal.Paintable.RepaintRequestListener; /** * Tabsheet component. @@ -23,7 +24,8 @@ import com.itmill.toolkit.terminal.Resource; * @VERSION@ * @since 3.0 */ -public class TabSheet extends AbstractComponentContainer { +public class TabSheet extends AbstractComponentContainer implements + RepaintRequestListener { /** * Linked list of component tabs. @@ -90,44 +92,60 @@ public class TabSheet extends AbstractComponentContainer { fireSelectedTabChange(); } } + c.removeListener(this); requestRepaint(); } } /** - * Adds the component into this container. The component is added as a tab - * where its default tab-caption is the caption of the component. + * Adds a new tab into TabSheet. Components caption and icon are rendered + * into tab. * * @param c * the component to be added. */ public void addComponent(Component c) { - addTab(c, c.getCaption(), getIcon()); + addTab(c); } /** - * Adds the new tab into TabSheet. + * Adds a new tab into TabSheet with overridden caption and icon. * * @param c * the component to be added onto tab. * @param caption - * the caption of the tab. + * the caption of the tab to be used instead of components + * own. * @param icon - * the Set the icon of the tab. + * the icon of the tab to be used instead of components own. */ public void addTab(Component c, String caption, Resource icon) { if (c != null) { - tabs.addLast(c); tabCaptions.put(c, caption != null ? caption : ""); if (icon != null) { tabIcons.put(c, icon); } + addTab(c); + } + } + + /** + * Adds a new tab into TabSheet. Components caption and icon are rendered + * into tab. + * + * @param c + * the component to be added onto tab. + */ + public void addTab(Component c) { + if (c != null) { + tabs.addLast(c); if (selected == null) { selected = c; fireSelectedTabChange(); } super.addComponent(c); requestRepaint(); + c.addListener(this); } } @@ -184,18 +202,28 @@ public class TabSheet extends AbstractComponentContainer { continue; } target.startTag("tab"); + if (!c.isEnabled()) { + target.addAttribute("disabled", true); + } final Resource icon = getTabIcon(c); if (icon != null) { target.addAttribute("icon", icon); } final String caption = getTabCaption(c); - if (!c.isEnabled()) { - target.addAttribute("disabled", true); - } - if (caption != null && caption.length() > 0) { target.addAttribute("caption", caption); } + + if (c instanceof AbstractComponent) { + AbstractComponent ac = (AbstractComponent) c; + if (ac.getDescription() != null) { + target.addAttribute("description", ac.getDescription()); + } + if (ac.getComponentError() != null) { + ac.getComponentError().paint(target); + } + } + target.addAttribute("key", keyMapper.key(c)); if (c.equals(selected)) { target.addAttribute("selected", true); @@ -239,6 +267,9 @@ public class TabSheet extends AbstractComponentContainer { */ public String getTabCaption(Component c) { String caption = (String) tabCaptions.get(c); + if (caption == null) { + caption = c.getCaption(); + } if (caption == null) { caption = ""; } @@ -246,7 +277,9 @@ public class TabSheet extends AbstractComponentContainer { } /** - * Sets the caption for a component. + * Sets overridden tab caption for given component. + * + * Normally TabSheet uses caption from component * * @param c * the component. @@ -265,11 +298,17 @@ public class TabSheet extends AbstractComponentContainer { * the component. */ public Resource getTabIcon(Component c) { - return (Resource) tabIcons.get(c); + if (tabIcons.containsKey(c)) { + return (Resource) tabIcons.get(c); + } else { + return c.getIcon(); + } } /** - * ] Sets the icon for a component. + * Sets overridden icon for given component. + * + * Normally TabSheet uses icon from component * * @param c * @param icon @@ -480,4 +519,12 @@ public class TabSheet extends AbstractComponentContainer { fireEvent(new SelectedTabChangeEvent(this)); } + /* + * We need to repaint on child repaint due the way captions and icons are + * handled + */ + public void repaintRequested(RepaintRequestEvent event) { + requestRepaint(); + } + } -- 2.39.5