From fe60cb2e249b9ccba2ae19d3919a1ac1eb2eb7c3 Mon Sep 17 00:00:00 2001 From: Jouni Koivuviita Date: Fri, 8 May 2009 12:41:04 +0000 Subject: [PATCH] Merges from 6.0 branch. svn changeset:7682/svn branch:theme_2009_03 --- .../accordions/AccordionDisabledExample.java | 24 +- .../tabsheets/TabSheetDisabledExample.java | 18 +- .../terminal/gwt/client/ComponentLocator.java | 36 +- .../terminal/gwt/client/ui/IAccordion.java | 13 +- .../terminal/gwt/client/ui/IContextMenu.java | 45 +- .../terminal/gwt/client/ui/ITabsheet.java | 9 +- .../toolkit/terminal/gwt/client/ui/IView.java | 30 +- .../AbsoluteLayoutClipping.java | 42 ++ .../components/tabsheet/TabSheetCaptions.java | 17 +- .../tabsheet/TabSheetDisabling.java | 7 +- .../layouts/AbsoluteLayoutAddRemove.java | 50 +++ src/com/itmill/toolkit/ui/AbsoluteLayout.java | 1 + src/com/itmill/toolkit/ui/Label.java | 4 +- src/com/itmill/toolkit/ui/TabSheet.java | 397 ++++++++++++++---- 14 files changed, 561 insertions(+), 132 deletions(-) create mode 100644 src/com/itmill/toolkit/tests/components/absolutelayout/AbsoluteLayoutClipping.java create mode 100644 src/com/itmill/toolkit/tests/layouts/AbsoluteLayoutAddRemove.java 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/ComponentLocator.java b/src/com/itmill/toolkit/terminal/gwt/client/ComponentLocator.java index c4f44c9440..da4aea74e3 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ComponentLocator.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ComponentLocator.java @@ -1,5 +1,6 @@ package com.itmill.toolkit.terminal.gwt.client; +import java.util.ArrayList; import java.util.Iterator; import com.google.gwt.user.client.DOM; @@ -7,6 +8,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.ui.IView; +import com.itmill.toolkit.terminal.gwt.client.ui.IWindow; import com.itmill.toolkit.terminal.gwt.client.ui.SubPartAware; /** @@ -64,6 +66,15 @@ public class ComponentLocator { } if (e == null || pid == null) { + + // Still test for context menu option + String subPartName = client.getContextMenu().getSubPartName( + targetElement); + if (subPartName != null) { + // IContextMenu, singleton attached directly to rootpanel + return "/IContextMenu[0]" + SUBPART_SEPARATOR + subPartName; + + } return null; } @@ -217,6 +228,12 @@ public class ComponentLocator { if (w instanceof IView) { return ""; + } else if (w instanceof IWindow) { + IWindow win = (IWindow) w; + ArrayList subWindowList = client.getView() + .getSubWindowList(); + int indexOfSubWindow = subWindowList.indexOf(win); + return PARENTCHILD_SEPARATOR + "IWindow[" + indexOfSubWindow + "]"; } Widget parent = w.getParent(); @@ -225,7 +242,7 @@ public class ComponentLocator { String simpleName = Util.getSimpleName(w); - Iterator i = ((HasWidgets) parent).iterator(); + Iterator i = ((HasWidgets) parent).iterator(); int pos = 0; while (i.hasNext()) { Object child = i.next(); @@ -262,12 +279,19 @@ public class ComponentLocator { } else if (w instanceof HasWidgets) { HasWidgets parent = (HasWidgets) w; - String simpleName = Util.getSimpleName(parent); + String[] split = part.split("\\["); - Iterator i = parent.iterator(); + Iterator i; + String widgetClassName = split[0]; + if (widgetClassName.equals("IWindow")) { + i = client.getView().getSubWindowList().iterator(); + } else if (widgetClassName.equals("IContextMenu")) { + return client.getContextMenu(); + } else { + i = parent.iterator(); + } boolean ok = false; - String[] split = part.split("\\["); int pos = Integer.parseInt(split[1].substring(0, split[1] .length() - 1)); // ApplicationConnection.getConsole().log( @@ -275,10 +299,10 @@ public class ComponentLocator { while (i.hasNext()) { // ApplicationConnection.getConsole().log("- child found"); - Widget child = (Widget) i.next(); + Widget child = i.next(); String simpleName2 = Util.getSimpleName(child); - if (split[0].equals(simpleName2)) { + if (widgetClassName.equals(simpleName2)) { if (pos == 0) { w = child; ok = true; 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/IContextMenu.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IContextMenu.java index 411e646a0c..ba7f5b509b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IContextMenu.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IContextMenu.java @@ -4,12 +4,17 @@ package com.itmill.toolkit.terminal.gwt.client.ui; +import com.google.gwt.dom.client.NodeList; +import com.google.gwt.dom.client.TableRowElement; +import com.google.gwt.dom.client.TableSectionElement; +import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.PopupPanel; +import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; -public class IContextMenu extends IToolkitOverlay { +public class IContextMenu extends IToolkitOverlay implements SubPartAware { private ActionOwner actionOwner; @@ -112,4 +117,42 @@ public class IContextMenu extends IToolkitOverlay { * super.onBrowserEvent(event); } */ } + + public Element getSubPartElement(String subPart) { + int index = Integer.parseInt(subPart.substring(6)); + ApplicationConnection.getConsole().log( + "Searching element for selection index " + index); + Element wrapperdiv = menu.getElement(); + com.google.gwt.dom.client.TableSectionElement tBody = (TableSectionElement) wrapperdiv + .getFirstChildElement().getFirstChildElement(); + TableRowElement item = tBody.getRows().getItem(index); + com.google.gwt.dom.client.Element clickableDivElement = item + .getFirstChildElement().getFirstChildElement(); + return clickableDivElement.cast(); + } + + public String getSubPartName(Element subElement) { + if (getElement().isOrHasChild(subElement)) { + com.google.gwt.dom.client.Element e = subElement; + { + while (e != null && !e.getTagName().toLowerCase().equals("tr")) { + e = e.getParentElement(); + ApplicationConnection.getConsole().log("Found row"); + } + } + com.google.gwt.dom.client.TableSectionElement parentElement = (TableSectionElement) e + .getParentElement(); + NodeList rows = parentElement.getRows(); + for (int i = 0; i < rows.getLength(); i++) { + if (rows.getItem(i) == e) { + ApplicationConnection.getConsole().log( + "Found index for row" + 1); + return "option" + i; + } + } + return null; + } else { + return null; + } + } } 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/terminal/gwt/client/ui/IView.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java index 0c22da4a1e..b30a1eb8af 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java @@ -4,8 +4,10 @@ package com.itmill.toolkit.terminal.gwt.client.ui; +import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.Set; import com.google.gwt.dom.client.DivElement; @@ -44,7 +46,7 @@ public class IView extends SimplePanel implements Container, private Paintable layout; - private final HashSet subWindows = new HashSet(); + private final LinkedHashSet subWindows = new LinkedHashSet(); private String id; @@ -231,7 +233,8 @@ public class IView extends SimplePanel implements Container, layout.updateFromUIDL(childUidl, client); // Update subwindows - final HashSet removedSubWindows = new HashSet(subWindows); + final HashSet removedSubWindows = new HashSet( + subWindows); // Open new windows while ((childUidl = uidl.getChildUIDL(childIndex++)) != null) { @@ -240,7 +243,7 @@ public class IView extends SimplePanel implements Container, if (subWindows.contains(w)) { removedSubWindows.remove(w); } else { - subWindows.add(w); + subWindows.add((IWindow) w); } w.updateFromUIDL(childUidl, client); } else if ("actions".equals(childUidl.getTag())) { @@ -282,8 +285,9 @@ public class IView extends SimplePanel implements Container, } // Close old windows - for (final Iterator rem = removedSubWindows.iterator(); rem.hasNext();) { - final IWindow w = (IWindow) rem.next(); + for (final Iterator rem = removedSubWindows.iterator(); rem + .hasNext();) { + final IWindow w = rem.next(); client.unregisterPaintable(w); subWindows.remove(w); w.hide(); @@ -551,7 +555,21 @@ public class IView extends SimplePanel implements Container, } public void updateCaption(Paintable component, UIDL uidl) { - // TODO Auto-generated method stub + // NOP Subwindows never draw caption for their first child (layout) + } + + /** + * Return an iterator for current subwindows. This method is meant for + * testing purposes only. + * + * @return + */ + public ArrayList getSubWindowList() { + ArrayList windows = new ArrayList(subWindows.size()); + for (IWindow widget : subWindows) { + windows.add(widget); + } + return windows; } } diff --git a/src/com/itmill/toolkit/tests/components/absolutelayout/AbsoluteLayoutClipping.java b/src/com/itmill/toolkit/tests/components/absolutelayout/AbsoluteLayoutClipping.java new file mode 100644 index 0000000000..b43d005274 --- /dev/null +++ b/src/com/itmill/toolkit/tests/components/absolutelayout/AbsoluteLayoutClipping.java @@ -0,0 +1,42 @@ +package com.itmill.toolkit.tests.components.absolutelayout; + +import com.itmill.toolkit.tests.components.TestBase; +import com.itmill.toolkit.ui.AbsoluteLayout; +import com.itmill.toolkit.ui.Label; + +public class AbsoluteLayoutClipping extends TestBase { + + @Override + protected void setup() { + setTheme("tests-tickets"); + AbsoluteLayout abs = new AbsoluteLayout(); + abs.setStyleName("borders"); + abs.setWidth("100px"); + abs.setHeight("100px"); + + Label l = new Label("This should be clipped at 100px"); + l.setSizeUndefined(); + abs.addComponent(l, "top:50px;left:50px"); + + Label l2 = new Label("This should not be visible"); + l2.setSizeUndefined(); + abs.addComponent(l2, "top:80px;left:150px"); + + Label l3 = new Label("This should be clipped vertically at 100px"); + l3.setWidth("50px"); + abs.addComponent(l3, "top:20px;left:0px"); + + addComponent(abs); + } + + @Override + protected String getDescription() { + return "An AbsoluteLayout with fixed size should clip at its borders. Nothing outside the black square should be visible."; + } + + @Override + protected Integer getTicketNumber() { + return 2913; + } + +} 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/tests/layouts/AbsoluteLayoutAddRemove.java b/src/com/itmill/toolkit/tests/layouts/AbsoluteLayoutAddRemove.java new file mode 100644 index 0000000000..14702a75ff --- /dev/null +++ b/src/com/itmill/toolkit/tests/layouts/AbsoluteLayoutAddRemove.java @@ -0,0 +1,50 @@ +package com.itmill.toolkit.tests.layouts; + +import com.itmill.toolkit.tests.components.TestBase; +import com.itmill.toolkit.ui.AbsoluteLayout; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.Button.ClickEvent; + +public class AbsoluteLayoutAddRemove extends TestBase { + + @Override + protected String getDescription() { + return "Tests that addComponent() and removeComponent() works"; + } + + @Override + protected Integer getTicketNumber() { + return 2915; + } + + @Override + protected void setup() { + Layout main = getLayout(); + + final Label l = new Label("A Label"); + final AbsoluteLayout al = new AbsoluteLayout(); + al.setWidth("300px"); + al.setHeight("200px"); + main.addComponent(al); + + final Button b = new Button("Add", new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + if (l.getParent() == null) { + al.addComponent(l); + event.getButton().setCaption("Remove"); + } else { + al.removeComponent(l); + event.getButton().setCaption("Add"); + } + + } + + }); + main.addComponent(b); + + } + +} diff --git a/src/com/itmill/toolkit/ui/AbsoluteLayout.java b/src/com/itmill/toolkit/ui/AbsoluteLayout.java index fd5e72aff6..fbac344932 100644 --- a/src/com/itmill/toolkit/ui/AbsoluteLayout.java +++ b/src/com/itmill/toolkit/ui/AbsoluteLayout.java @@ -52,6 +52,7 @@ public class AbsoluteLayout extends AbstractLayout { public void removeComponent(Component c) { components.remove(c); super.removeComponent(c); + requestRepaint(); } public void addComponent(Component c, String cssPosition) { diff --git a/src/com/itmill/toolkit/ui/Label.java b/src/com/itmill/toolkit/ui/Label.java index 4a272ed1d1..26d4d16963 100644 --- a/src/com/itmill/toolkit/ui/Label.java +++ b/src/com/itmill/toolkit/ui/Label.java @@ -372,8 +372,10 @@ public class Label extends AbstractComponent implements Property, * the New content mode of the label. */ public void setContentMode(int contentMode) { - if (contentMode >= CONTENT_TEXT && contentMode <= CONTENT_RAW) { + if (contentMode != this.contentMode && contentMode >= CONTENT_TEXT + && contentMode <= CONTENT_RAW) { this.contentMode = contentMode; + requestRepaint(); } } diff --git a/src/com/itmill/toolkit/ui/TabSheet.java b/src/com/itmill/toolkit/ui/TabSheet.java index 5d2e9ac57f..510cf99d73 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,167 @@ 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; + requestRepaint(); + } + + public Resource getIcon() { + return icon; + } + + public void setIcon(Resource icon) { + this.icon = icon; + requestRepaint(); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + requestRepaint(); + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + requestRepaint(); + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + requestRepaint(); + } + + public ErrorMessage getComponentError() { + return componentError; + } + + public void setComponentError(ErrorMessage componentError) { + this.componentError = componentError; + requestRepaint(); + } + + } } -- 2.39.5