From 103bb78c2982bd6f0c3025988e8839cf1d667732 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 8 May 2009 07:00:04 +0000 Subject: [PATCH] Fixed #2659 and #2846 - TabSheet and Accordion now internally keeps caption/icon/enabled/visibility information for each tab and do not use/modify the component. Modified sampler samples to work with the new API. Modified test cases to work with the new API. svn changeset:7664/svn branch:6.0 --- .../accordions/AccordionDisabledExample.java | 24 +- .../tabsheets/TabSheetDisabledExample.java | 18 +- .../terminal/gwt/client/ui/IAccordion.java | 13 +- .../terminal/gwt/client/ui/ITabsheet.java | 9 +- .../components/tabsheet/TabSheetCaptions.java | 17 +- .../tabsheet/TabSheetDisabling.java | 7 +- src/com/itmill/toolkit/ui/TabSheet.java | 392 ++++++++++++++---- 7 files changed, 362 insertions(+), 118 deletions(-) diff --git a/src/com/itmill/toolkit/demo/sampler/features/accordions/AccordionDisabledExample.java b/src/com/itmill/toolkit/demo/sampler/features/accordions/AccordionDisabledExample.java index 705a857fd7..14d089809c 100644 --- a/src/com/itmill/toolkit/demo/sampler/features/accordions/AccordionDisabledExample.java +++ b/src/com/itmill/toolkit/demo/sampler/features/accordions/AccordionDisabledExample.java @@ -8,6 +8,7 @@ import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.VerticalLayout; import com.itmill.toolkit.ui.Button.ClickEvent; import com.itmill.toolkit.ui.TabSheet.SelectedTabChangeEvent; +import com.itmill.toolkit.ui.TabSheet.Tab; public class AccordionDisabledExample extends VerticalLayout implements Accordion.SelectedTabChangeListener, Button.ClickListener { @@ -18,6 +19,9 @@ public class AccordionDisabledExample extends VerticalLayout implements private Label l1; private Label l2; private Label l3; + private Tab t1; + private Tab t2; + private Tab t3; private static final ThemeResource icon1 = new ThemeResource( "icons/action_save.gif"); @@ -36,9 +40,9 @@ public class AccordionDisabledExample extends VerticalLayout implements a = new Accordion(); a.setHeight("300px"); a.setWidth("400px"); - a.addTab(l1, "Saved actions", icon1); - a.addTab(l2, "Notes", icon2); - a.addTab(l3, "Issues", icon3); + t1 = a.addTab(l1, "Saved actions", icon1); + t2 = a.addTab(l2, "Notes", icon2); + t3 = a.addTab(l3, "Issues", icon3); a.addListener(this); b1 = new Button("Disable 'Notes' tab"); @@ -56,25 +60,25 @@ public class AccordionDisabledExample extends VerticalLayout implements } public void selectedTabChange(SelectedTabChangeEvent event) { - String c = a.getTabCaption(event.getTabSheet().getSelectedTab()); + String c = a.getTab(event.getTabSheet().getSelectedTab()).getCaption(); getWindow().showNotification("Selected tab: " + c); } public void buttonClick(ClickEvent event) { if (b1.equals(event.getButton())) { // b1 clicked - if (l2.isEnabled()) { - l2.setEnabled(false); + if (t2.isEnabled()) { + t2.setEnabled(false); b1.setCaption("Enable 'Notes' tab"); } else { - l2.setEnabled(true); + t2.setEnabled(true); b1.setCaption("Disable 'Notes' tab"); } } else { // b2 clicked - if (l3.isVisible()) { - l3.setVisible(false); + if (t3.isVisible()) { + t3.setVisible(false); b2.setCaption("Show 'Issues' tab"); } else { - l3.setVisible(true); + t3.setVisible(true); b2.setCaption("Hide 'Issues' tab"); } } diff --git a/src/com/itmill/toolkit/demo/sampler/features/tabsheets/TabSheetDisabledExample.java b/src/com/itmill/toolkit/demo/sampler/features/tabsheets/TabSheetDisabledExample.java index 12ad969e71..13c292772e 100644 --- a/src/com/itmill/toolkit/demo/sampler/features/tabsheets/TabSheetDisabledExample.java +++ b/src/com/itmill/toolkit/demo/sampler/features/tabsheets/TabSheetDisabledExample.java @@ -8,6 +8,7 @@ import com.itmill.toolkit.ui.TabSheet; import com.itmill.toolkit.ui.VerticalLayout; import com.itmill.toolkit.ui.Button.ClickEvent; import com.itmill.toolkit.ui.TabSheet.SelectedTabChangeEvent; +import com.itmill.toolkit.ui.TabSheet.Tab; public class TabSheetDisabledExample extends VerticalLayout implements TabSheet.SelectedTabChangeListener, Button.ClickListener { @@ -24,6 +25,7 @@ public class TabSheetDisabledExample extends VerticalLayout implements private VerticalLayout l1; private VerticalLayout l2; private VerticalLayout l3; + private Tab t1, t2, t3; public TabSheetDisabledExample() { setSpacing(true); @@ -44,9 +46,9 @@ public class TabSheetDisabledExample extends VerticalLayout implements t = new TabSheet(); t.setHeight("200px"); t.setWidth("400px"); - t.addTab(l1, "Saved actions", icon1); - t.addTab(l2, "Notes", icon2); - t.addTab(l3, "Issues", icon3); + t1 = t.addTab(l1, "Saved actions", icon1); + t2 = t.addTab(l2, "Notes", icon2); + t3 = t.addTab(l3, "Issues", icon3); t.addListener(this); toggleEnabled = new Button("Disable 'Notes' tab"); @@ -65,21 +67,21 @@ public class TabSheetDisabledExample extends VerticalLayout implements } public void selectedTabChange(SelectedTabChangeEvent event) { - String c = t.getTabCaption(event.getTabSheet().getSelectedTab()); + String c = t.getTab(event.getTabSheet().getSelectedTab()).getCaption(); getWindow().showNotification("Selected tab: " + c); } public void buttonClick(ClickEvent event) { if (toggleEnabled.equals(event.getButton())) { // toggleEnabled clicked - l2.setEnabled(!l2.isEnabled()); - toggleEnabled.setCaption((l2.isEnabled() ? "Disable" : "Enable") + t2.setEnabled(!t2.isEnabled()); + toggleEnabled.setCaption((t2.isEnabled() ? "Disable" : "Enable") + " 'Notes' tab"); } else { // toggleVisible clicked - l3.setVisible(!l3.isVisible()); - toggleVisible.setCaption((l3.isVisible() ? "Hide" : "Show") + t3.setVisible(!t3.isVisible()); + toggleVisible.setCaption((t3.isVisible() ? "Hide" : "Show") + " 'Issues' tab"); } 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 1ed82d51d4..e924dfab6b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java @@ -582,18 +582,7 @@ public class IAccordion extends ITabsheetBase implements } public void updateCaption(Paintable component, UIDL uidl) { - for (Widget w : getChildren()) { - StackItem si = (StackItem) w; - if (si.getPaintable() == component) { - boolean visible = si.isVisible(); - si.updateCaption(uidl); - if (si.isCaptionVisible() != visible) { - si.setVisible(si.isCaptionVisible()); - } - - return; - } - } + /* Accordion does not render its children's captions */ } public boolean requestLayout(Set child) { 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 e40b6ac0a8..f1a61edc1c 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java @@ -763,14 +763,7 @@ public class ITabsheet extends ITabsheetBase { } public void updateCaption(Paintable component, UIDL uidl) { - int i = tp.getWidgetIndex((Widget) component); - ICaption c = captions.get("" + i); - boolean visible = c.isVisible(); - c.updateCaption(uidl); - if (c.isVisible() != visible) { - tb.setVisible(i, c.isVisible()); - c.setWidth(c.getRequiredWidth() + "px"); - } + /* Tabsheet does not render its children's captions */ } public boolean requestLayout(Set child) { diff --git a/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetCaptions.java b/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetCaptions.java index be9cfaafbb..d1b13ca00d 100644 --- a/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetCaptions.java +++ b/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetCaptions.java @@ -1,5 +1,7 @@ package com.itmill.toolkit.tests.components.tabsheet; +import java.util.Date; + import com.itmill.toolkit.tests.components.TestBase; import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.Label; @@ -25,20 +27,29 @@ public class TabSheetCaptions extends TestBase { protected void setup() { final TabSheet tabSheet = new TabSheet(); - panel1 = new Panel("tab 1"); + panel1 = new Panel("Panel initial caption (should also be tab caption)"); panel1.setSizeFull(); panel1.getLayout().setSizeFull(); - panel1.addComponent(new Label("This is first panel")); + panel1.addComponent(new Label("This is a panel")); tabSheet.addTab(panel1); Button button = new Button("Update tab caption"); button.addListener(new Button.ClickListener() { public void buttonClick(ClickEvent event) { - tabSheet.setTabCaption(panel1, "This is a new caption"); + tabSheet.setTabCaption(panel1, "This is a new tab caption " + + new Date()); + } + }); + + Button button2 = new Button("Update panel caption"); + button2.addListener(new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + panel1.setCaption("This is a new panel caption " + new Date()); } }); addComponent(tabSheet); addComponent(button); + addComponent(button2); } } diff --git a/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetDisabling.java b/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetDisabling.java index f934cb0689..ecac170c3c 100644 --- a/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetDisabling.java +++ b/src/com/itmill/toolkit/tests/components/tabsheet/TabSheetDisabling.java @@ -21,7 +21,8 @@ public class TabSheetDisabling extends TestBase { new ClickListener() { public void buttonClick(ClickEvent event) { - event.getButton().setEnabled(false); + Button b = event.getButton(); + tabSheet.getTab(b).setEnabled(false); } @@ -30,8 +31,8 @@ public class TabSheetDisabling extends TestBase { buttons[i] = new Button("Hide this tab", new ClickListener() { public void buttonClick(ClickEvent event) { - event.getButton().setVisible(false); - + Button b = event.getButton(); + tabSheet.getTab(b).setVisible(false); } }); diff --git a/src/com/itmill/toolkit/ui/TabSheet.java b/src/com/itmill/toolkit/ui/TabSheet.java index 5d2e9ac57f..b66ab60e5e 100644 --- a/src/com/itmill/toolkit/ui/TabSheet.java +++ b/src/com/itmill/toolkit/ui/TabSheet.java @@ -6,10 +6,12 @@ package com.itmill.toolkit.ui; import java.io.Serializable; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; +import com.itmill.toolkit.terminal.ErrorMessage; import com.itmill.toolkit.terminal.KeyMapper; import com.itmill.toolkit.terminal.PaintException; import com.itmill.toolkit.terminal.PaintTarget; @@ -31,7 +33,12 @@ public class TabSheet extends AbstractComponentContainer implements /** * Linked list of component tabs. */ - private final LinkedList tabs = new LinkedList(); + private final LinkedList components = new LinkedList(); + + /** + * Map containing information related to the tabs (caption, icon etc). + */ + private final HashMap tabs = new HashMap(); /** * Selected tab. @@ -64,7 +71,7 @@ public class TabSheet extends AbstractComponentContainer implements * @return the Iterator of the components inside the container. */ public Iterator getComponentIterator() { - return java.util.Collections.unmodifiableList(tabs).iterator(); + return java.util.Collections.unmodifiableList(components).iterator(); } /** @@ -75,15 +82,16 @@ public class TabSheet extends AbstractComponentContainer implements */ @Override public void removeComponent(Component c) { - if (c != null && tabs.contains(c)) { + if (c != null && components.contains(c)) { super.removeComponent(c); keyMapper.remove(c); + components.remove(c); tabs.remove(c); if (c.equals(selected)) { - if (tabs.isEmpty()) { + if (components.isEmpty()) { selected = null; } else { - selected = (Component) tabs.getFirst(); + selected = (Component) components.getFirst(); fireSelectedTabChange(); } } @@ -114,16 +122,23 @@ public class TabSheet extends AbstractComponentContainer implements * @param icon * the icon to be set for the component and used rendered in tab * bar + * @return the created tab */ - public void addTab(Component c, String caption, Resource icon) { + public Tab addTab(Component c, String caption, Resource icon) { if (c != null) { - if (caption != null) { - c.setCaption(caption); - } - if (icon != null) { - c.setIcon(icon); + components.addLast(c); + Tab tab = new TabSheetTabImpl(caption, icon); + + tabs.put(c, tab); + if (selected == null) { + selected = c; + fireSelectedTabChange(); } - addTab(c); + super.addComponent(c); + requestRepaint(); + return tab; + } else { + return null; } } @@ -133,17 +148,13 @@ public class TabSheet extends AbstractComponentContainer implements * * @param c * the component to be added onto tab. + * @return the created tab */ - public void addTab(Component c) { + public Tab addTab(Component c) { if (c != null) { - tabs.addLast(c); - if (selected == null) { - selected = c; - fireSelectedTabChange(); - } - super.addComponent(c); - requestRepaint(); + return addTab(c, c.getCaption(), c.getIcon()); } + return null; } /** @@ -197,54 +208,70 @@ public class TabSheet extends AbstractComponentContainer implements target.startTag("tabs"); for (final Iterator i = getComponentIterator(); i.hasNext();) { - final Component c = (Component) i.next(); + final Component component = (Component) i.next(); + Tab tab = tabs.get(component); /* * If we have no selection, if the current selection is invisible or * if the current selection is disabled (but the whole component is * not) we select this tab instead */ - if (selected == null || !selected.isVisible() - || (!selected.isEnabled() && isEnabled())) { - selected = c; + Tab selectedTabInfo = null; + if (selected != null) { + selectedTabInfo = tabs.get(selected); + } + if (selected == null || selectedTabInfo == null + || !selectedTabInfo.isVisible() + || !selectedTabInfo.isEnabled()) { + + // The current selection is not valid so we need to change it + if (tab.isEnabled() && tab.isVisible()) { + selected = component; + } else { + /* + * The current selection is not valid but this tab cannot be + * selected either. + */ + selected = null; + } } target.startTag("tab"); - if (!c.isEnabled() && c.isVisible()) { + if (!tab.isEnabled() && tab.isVisible()) { target.addAttribute("disabled", true); } - if (!c.isVisible()) { + if (!tab.isVisible()) { target.addAttribute("hidden", true); } - final Resource icon = getTabIcon(c); + final Resource icon = tab.getIcon(); if (icon != null) { target.addAttribute("icon", icon); } - final String caption = getTabCaption(c); + final String caption = tab.getCaption(); 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); - } + final String description = tab.getDescription(); + if (description != null) { + target.addAttribute("description", description); } - target.addAttribute("key", keyMapper.key(c)); - if (c.equals(selected)) { + final ErrorMessage componentError = tab.getComponentError(); + if (componentError != null) { + componentError.paint(target); + } + + target.addAttribute("key", keyMapper.key(component)); + if (component.equals(selected)) { target.addAttribute("selected", true); - c.paint(target); - paintedTabs.add(c); - } else if (paintedTabs.contains(c)) { - c.paint(target); + component.paint(target); + paintedTabs.add(component); + } else if (paintedTabs.contains(component)) { + component.paint(target); } else { - c.requestRepaintRequests(); + component.requestRepaintRequests(); } target.endTag("tab"); } @@ -281,12 +308,16 @@ public class TabSheet extends AbstractComponentContainer implements * * @param c * the component. + * @deprecated Use {@link #getTab(Component)} and {@link Tab#getCaption()} + * instead. */ + @Deprecated public String getTabCaption(Component c) { - if (c.getCaption() == null) { + Tab info = tabs.get(c); + if (info == null) { return ""; } else { - return c.getCaption(); + return info.getCaption(); } } @@ -297,10 +328,15 @@ public class TabSheet extends AbstractComponentContainer implements * the component. * @param caption * the caption to set. + * @deprecated Use {@link #getTab(Component)} and + * {@link Tab#setCaption(String)} instead. */ + @Deprecated public void setTabCaption(Component c, String caption) { - if (tabs.contains(c)) { - c.setCaption(caption); + Tab info = tabs.get(c); + if (info != null) { + info.setCaption(caption); + requestRepaint(); } } @@ -309,32 +345,59 @@ public class TabSheet extends AbstractComponentContainer implements * * @param c * the component. + * @deprecated Use {@link #getTab(Component)} and {@link Tab#getIcon()} + * instead. */ + @Deprecated public Resource getTabIcon(Component c) { - return c.getIcon(); + Tab info = tabs.get(c); + if (info == null) { + return null; + } else { + return info.getIcon(); + } } /** - * Sets overridden icon for given component. + * Sets icon for the given component. * * Normally TabSheet uses icon from component * * @param c + * the component * @param icon + * the icon to set + * @deprecated Use {@link #getTab(Component)} and + * {@link Tab#setIcon(Resource)} instead. */ + @Deprecated public void setTabIcon(Component c, Resource icon) { - if (tabs.contains(c)) { - c.setIcon(icon); + Tab info = tabs.get(c); + if (info != null) { + info.setIcon(icon); + requestRepaint(); } } + /** + * Returns the Tab for the component. The Tab object can be used for setting + * caption,icon, etc for the tab. + * + * @param c + * the component + * @return + */ + public Tab getTab(Component c) { + return tabs.get(c); + } + /** * Sets the selected tab. * * @param c */ public void setSelectedTab(Component c) { - if (c != null && tabs.contains(c) && !selected.equals(c)) { + if (c != null && components.contains(c) && !selected.equals(c)) { selected = c; fireSelectedTabChange(); requestRepaint(); @@ -372,17 +435,33 @@ public class TabSheet extends AbstractComponentContainer implements selected = newComponent; } + Tab newTab = tabs.get(newComponent); + Tab oldTab = tabs.get(oldComponent); + // Gets the captions - final String oldCaption = getTabCaption(oldComponent); - final Resource oldIcon = getTabIcon(oldComponent); - final String newCaption = getTabCaption(newComponent); - final Resource newIcon = getTabIcon(newComponent); + String oldCaption = null; + Resource oldIcon = null; + String newCaption = null; + Resource newIcon = null; + + if (oldTab != null) { + oldCaption = oldTab.getCaption(); + oldIcon = oldTab.getIcon(); + } + + if (newTab != null) { + newCaption = newTab.getCaption(); + newIcon = newTab.getIcon(); + } else { + newCaption = newComponent.getCaption(); + newIcon = newComponent.getIcon(); + } // Gets the locations int oldLocation = -1; int newLocation = -1; int location = 0; - for (final Iterator i = tabs.iterator(); i.hasNext();) { + for (final Iterator i = components.iterator(); i.hasNext();) { final Component component = (Component) i.next(); if (component == oldComponent) { @@ -400,27 +479,34 @@ public class TabSheet extends AbstractComponentContainer implements } else if (newLocation == -1) { removeComponent(oldComponent); keyMapper.remove(oldComponent); - addComponent(newComponent); - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); - setTabCaption(newComponent, oldCaption); - setTabIcon(newComponent, oldIcon); + newTab = addTab(newComponent); + components.remove(newComponent); + components.add(oldLocation, newComponent); + newTab.setCaption(oldCaption); + newTab.setIcon(oldIcon); } else { if (oldLocation > newLocation) { - tabs.remove(oldComponent); - tabs.add(newLocation, oldComponent); - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); + components.remove(oldComponent); + components.add(newLocation, oldComponent); + components.remove(newComponent); + components.add(oldLocation, newComponent); } else { - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); - tabs.remove(oldComponent); - tabs.add(newLocation, oldComponent); + components.remove(newComponent); + components.add(oldLocation, newComponent); + components.remove(oldComponent); + components.add(newLocation, oldComponent); + } + + if (newTab != null) { + // This should always be true + newTab.setCaption(oldCaption); + newTab.setIcon(oldIcon); + } + if (oldTab != null) { + // This should always be true + oldTab.setCaption(newCaption); + oldTab.setIcon(newIcon); } - setTabCaption(newComponent, oldCaption); - setTabIcon(newComponent, oldIcon); - setTabCaption(oldComponent, newCaption); - setTabIcon(oldComponent, newIcon); requestRepaint(); } @@ -538,4 +624,162 @@ public class TabSheet extends AbstractComponentContainer implements paintedTabs.clear(); } + /** + * + */ + public interface Tab extends Serializable { + /** + * Returns the visible status for the tab. + * + * @return true for visible, false for hidden + */ + public boolean isVisible(); + + /** + * Sets the visible status for the tab. + * + * @param visible + * true for visible, false for hidden + */ + public void setVisible(boolean visible); + + /** + * Returns the enabled status for the tab. + * + * @return true for enabled, false for disabled + */ + public boolean isEnabled(); + + /** + * Sets the enabled status for the tab. + * + * @param enabled + * true for enabled, false for disabled + */ + public void setEnabled(boolean enabled); + + /** + * Sets the caption for the tab. + * + * @param caption + * the caption to set + */ + public void setCaption(String caption); + + /** + * Gets the caption for the tab. + * + */ + public String getCaption(); + + /** + * Gets the icon for the tab. + * + */ + public Resource getIcon(); + + /** + * Sets the icon for the tab. + * + * @param icon + * the icon to set + */ + public void setIcon(Resource icon); + + /** + * Gets the description for the tab. The description can be used to + * briefly describe the state of the tab to the user. + * + * @return the description for the tab + */ + public String getDescription(); + + /** + * Sets the description for the tab. + * + * @param description + * the new description string for the tab. + */ + public void setDescription(String description); + + public void setComponentError(ErrorMessage componentError); + + public ErrorMessage getComponentError(); + + } + + /** + * TabSheet's implementation of Tab + * + */ + public class TabSheetTabImpl implements Tab { + + private String caption = ""; + private Resource icon = null; + private boolean enabled = true; + private boolean visible = true; + private String description = null; + private ErrorMessage componentError = null; + + public TabSheetTabImpl(String caption, Resource icon) { + if (caption == null) { + caption = ""; + } + this.caption = caption; + this.icon = icon; + } + + /** + * Returns the tab caption. Can never be null. + */ + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Resource getIcon() { + return icon; + } + + public void setIcon(Resource icon) { + this.icon = icon; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + + } + + public ErrorMessage getComponentError() { + return componentError; + } + + public void setComponentError(ErrorMessage componentError) { + this.componentError = componentError; + } + + } } -- 2.39.5