-ITabsheet refactored: new superclass for different kinds of tabs, ITabsheetBase. Use this when you want to create some sort of tabbable component.
svn changeset:3242/svn branch:trunk
<stylesheet src="default/progressindicator/progressindicator.css"/>
<stylesheet src="default/expandlayout/expandlayout.css"/>
<stylesheet src="default/orderedlayout/orderedlayout.css"/>
+ <stylesheet src="default/accordion/accordion.css"/>
</module>
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ui.IAccordion;
import com.itmill.toolkit.terminal.gwt.client.ui.IButton;
import com.itmill.toolkit.terminal.gwt.client.ui.ICheckBox;
import com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout;
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.richtextarea.IRichTextArea"
.equals(className)) {
return new IRichTextArea();
+ } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IAccordion"
+ .equals(className)) {
+ return new IAccordion();
}
return new IUnknownComponent();
return "com.itmill.toolkit.terminal.gwt.client.ui.IPanel";
} else if ("tabsheet".equals(tag)) {
return "com.itmill.toolkit.terminal.gwt.client.ui.ITabsheet";
+ } else if ("accordion".equals(tag)) {
+ return "com.itmill.toolkit.terminal.gwt.client.ui.IAccordion";
} else if ("embedded".equals(tag)) {
return "com.itmill.toolkit.terminal.gwt.client.ui.IEmbedded";
} else if ("customlayout".equals(tag)) {
--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+
+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.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener;
+import com.itmill.toolkit.terminal.gwt.client.Paintable;
+import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.Util;
+
+public class IAccordion extends ITabsheetBase implements
+ ContainerResizedListener {
+
+ public static final String CLASSNAME = "i-accordion";
+
+ private ArrayList stack;
+
+ private String height;
+
+ public IAccordion() {
+ super(CLASSNAME);
+ stack = new ArrayList();
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ super.updateFromUIDL(uidl, client);
+
+ iLayout();
+ }
+
+ public void clear() {
+ super.clear();
+ stack.clear();
+ }
+
+ private StackItem getSelectedStack() {
+ return (StackItem) stack.get(activeTabIndex);
+ }
+
+ protected void renderTab(UIDL contentUidl, String caption, 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);
+ if (selected) {
+ item.setContent(new StackContent(contentUidl));
+ item.open();
+ } else {
+ item.setContent(new StackContent());
+ }
+
+ if (stack.size() == 0) {
+ item.addStyleDependentName("first");
+ }
+
+ stack.add(item);
+ add(item);
+ }
+
+ protected void selectTab(final int index, final UIDL contentUidl) {
+ if (index != activeTabIndex) {
+ activeTabIndex = index;
+ StackItem item = (StackItem) stack.get(index);
+ item.setContent(new StackContent(contentUidl));
+ item.open();
+ }
+ }
+
+ public void onSelectTab(StackItem item) {
+ final int index = stack.indexOf(item);
+ if (index != activeTabIndex && !disabled && !readonly) {
+ getSelectedStack().close();
+ addStyleDependentName("loading");
+ // run updating variables in deferred command to bypass some FF
+ // optimization issues
+ DeferredCommand.addCommand(new Command() {
+ public void execute() {
+ client.updateVariable(id, "selected", ""
+ + tabKeys.get(index), true);
+ }
+ });
+ }
+ }
+
+ public void setWidth(String width) {
+ if (width.equals("100%")) {
+ super.setWidth("");
+ } else {
+ super.setWidth(width);
+ }
+ }
+
+ public void setHeight(String height) {
+ this.height = height;
+ }
+
+ public void iLayout() {
+ if (height != null && height != "") {
+ // TODO
+ } else {
+ // getVisibleContent().getContent().setHeight("");
+ }
+ Util.runDescendentsLayout(this);
+ }
+
+ protected class StackItem extends Widget {
+
+ private String caption;
+ private Element captionNode;
+ private boolean open = false;
+ private StackContent content;
+
+ protected StackItem() {
+ setElement(DOM.createDiv());
+ captionNode = DOM.createDiv();
+ // Additional SPAN element for styling
+ DOM.appendChild(captionNode, DOM.createSpan());
+ DOM.appendChild(getElement(), captionNode);
+ setStylePrimaryName(CLASSNAME + "-item");
+ DOM.setElementProperty(captionNode, "className", CLASSNAME
+ + "-item-caption");
+ sinkEvents(Event.ONCLICK);
+ }
+
+ public StackItem(String caption) {
+ this();
+ setCaption(caption);
+ }
+
+ public StackItem(String caption, UIDL contentUidl) {
+ this();
+ setCaption(caption);
+ setContent(new StackContent(contentUidl));
+ }
+
+ public void setCaption(String caption) {
+ this.caption = caption;
+ DOM.setInnerText(DOM.getFirstChild(captionNode), caption);
+ }
+
+ public String getCaption() {
+ return caption;
+ }
+
+ public void open() {
+ open = true;
+ content.show();
+ addStyleDependentName("open");
+ }
+
+ public void close() {
+ open = false;
+ content.hide();
+ removeStyleDependentName("open");
+ }
+
+ public boolean isOpen() {
+ return open;
+ }
+
+ public StackContent getContent() {
+ return content;
+ }
+
+ public void setContent(StackContent content) {
+ if (this.content != null) {
+ // Remove old content
+ DOM.removeChild(getElement(), getContent().getElement());
+ }
+ this.content = content;
+ DOM.appendChild(getElement(), getContent().getElement());
+ }
+
+ 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);
+ }
+ }
+ }
+
+ }
+
+ protected class StackContent extends UIObject {
+
+ protected StackContent() {
+ setElement(DOM.createDiv());
+ setVisible(false);
+ setStyleName(CLASSNAME + "-item-content");
+ }
+
+ protected StackContent(UIDL contentUidl) {
+ this();
+ renderContent(contentUidl);
+ }
+
+ public void show() {
+ setVisible(true);
+ }
+
+ public void hide() {
+ setVisible(false);
+ }
+
+ private void renderContent(UIDL contentUidl) {
+ final Paintable content = client.getPaintable(contentUidl);
+ DOM.appendChild(getElement(), ((Widget) content).getElement());
+ (content).updateFromUIDL(contentUidl, client);
+ }
+
+ }
+
+}
package com.itmill.toolkit.terminal.gwt.client.ui;
-import java.util.ArrayList;
-import java.util.Iterator;
-
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.ui.FlowPanel;
+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.itmill.toolkit.terminal.gwt.client.UIDL;
import com.itmill.toolkit.terminal.gwt.client.Util;
-public class ITabsheet extends FlowPanel implements Paintable,
+public class ITabsheet extends ITabsheetBase implements
ContainerResizedListener {
public static final String CLASSNAME = "i-tabsheet";
- String id;
- ApplicationConnection client;
-
- private final ArrayList tabKeys = new ArrayList();
- private final ArrayList captions = new ArrayList();
- int activeTabIndex = 0;
private final TabBar tb;
private final ITabsheetPanel tp;
private final Element contentNode, deco;
- private boolean disabled;
+
+ private String height;
private final TabListener tl = new TabListener() {
};
- private String height;
-
public ITabsheet() {
- setStyleName(CLASSNAME);
+ super(CLASSNAME);
tb = new TabBar();
tp = new ITabsheetPanel();
tb.addTabListener(tl);
- clearTabs();
+ clear();
// TODO Use for Safari only. Fix annoying 1px first cell in TabBar.
DOM.setStyleAttribute(DOM.getFirstChild(DOM.getFirstChild(DOM
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- this.client = client;
- id = uidl.getId();
+ super.updateFromUIDL(uidl, client);
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
-
- disabled = uidl.hasAttribute("disabled");
-
- // Add proper stylenames for all elements
+ // Add proper stylenames for all elements (easier to prevent unwanted
+ // style inheritance)
if (uidl.hasAttribute("style")) {
final String[] styles = uidl.getStringAttribute("style").split(" ");
final String contentBaseClass = "CLASSNAME" + "-content";
DOM.setElementProperty(deco, "className", CLASSNAME + "-deco");
}
- // Adjust width and height
- if (uidl.hasAttribute("height")) {
- setHeight(uidl.getStringAttribute("height"));
- } else {
- setHeight("");
- }
- if (uidl.hasAttribute("width")) {
- setWidth(uidl.getStringAttribute("width"));
- } else {
- setWidth("");
- }
+ }
- // Render content
- final UIDL tabs = uidl.getChildUIDL(0);
- boolean keepCurrentTabs = tabKeys.size() == tabs.getNumberOfChildren();
- for (int i = 0; keepCurrentTabs && i < tabKeys.size(); i++) {
- keepCurrentTabs = tabKeys.get(i).equals(
- tabs.getChildUIDL(i).getStringAttribute("key"))
- && captions.get(i).equals(
- tabs.getChildUIDL(i).getStringAttribute("caption"));
- }
- if (keepCurrentTabs) {
- int index = 0;
- for (final Iterator it = tabs.getChildIterator(); it.hasNext();) {
- final UIDL tab = (UIDL) it.next();
- if (tab.getBooleanAttribute("selected")) {
- activeTabIndex = index;
- renderContent(tab.getChildUIDL(0));
- }
- index++;
- }
- } else {
- tabKeys.clear();
- captions.clear();
- clearTabs();
-
- int index = 0;
- for (final Iterator it = tabs.getChildIterator(); it.hasNext();) {
- final UIDL tab = (UIDL) it.next();
- final String key = tab.getStringAttribute("key");
- String caption = tab.getStringAttribute("caption");
- if (caption == null) {
- caption = " ";
- }
-
- captions.add(caption);
- tabKeys.add(key);
-
- // Add new tab (additional SPAN-element for loading indication)
- tb.insertTab("<span>" + caption + "</span>", true, tb
- .getTabCount());
-
- // Add placeholder content
- tp.add(new ILabel(""));
-
- if (tab.getBooleanAttribute("selected")) {
- activeTabIndex = index;
- renderContent(tab.getChildUIDL(0));
- }
- index++;
- }
+ protected void renderTab(final UIDL contentUidl, String caption, 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);
+ if (selected) {
+ renderContent(contentUidl);
+ tb.selectTab(index);
}
+ // Add place-holder content
+ tp.add(new Label(""));
+ }
- // Open selected tab, if there's something to show
- if (tabKeys.size() > 0) {
- tb.selectTab(activeTabIndex);
+ protected void selectTab(int index, final UIDL contentUidl) {
+ if (index != activeTabIndex) {
+ activeTabIndex = index;
+ renderContent(contentUidl);
}
-
}
private void renderContent(final UIDL contentUIDL) {
ITabsheet.this.iLayout();
}
});
-
}
- private void clearTabs() {
+ public void clear() {
int i = tb.getTabCount();
while (i > 0) {
tb.removeTab(--i);
--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.Paintable;
+import com.itmill.toolkit.terminal.gwt.client.UIDL;
+
+abstract class ITabsheetBase extends FlowPanel implements Paintable {
+
+ 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;
+
+ public ITabsheetBase(String classname) {
+ setStylePrimaryName(classname);
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+
+ // Ensure correct implementation and let ApplicationConnection handle
+ // component caption
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ // Update member references
+ this.client = client;
+ id = uidl.getId();
+ disabled = uidl.hasAttribute("disabled");
+
+ // Adjust width and height
+ if (uidl.hasAttribute("height")) {
+ setHeight(uidl.getStringAttribute("height"));
+ } else {
+ setHeight("");
+ }
+ if (uidl.hasAttribute("width")) {
+ setWidth(uidl.getStringAttribute("width"));
+ } else {
+ setWidth("");
+ }
+
+ // 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));
+ }
+ index++;
+ }
+ } else {
+ // Clear previous values
+ tabKeys.clear();
+ captions.clear();
+ clear();
+
+ 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 = " ";
+ }
+
+ captions.add(caption);
+ tabKeys.add(key);
+
+ if (selected) {
+ activeTabIndex = index;
+ }
+ renderTab(tab.getChildUIDL(0), caption, index, selected);
+ index++;
+ }
+ }
+
+ }
+
+ 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++) {
+ retval = tabKeys.get(i).equals(
+ tabs.getChildUIDL(i).getStringAttribute("key"))
+ && captions.get(i).equals(
+ tabs.getChildUIDL(i).getStringAttribute("caption"));
+ }
+ return retval;
+ }
+
+ /*
+ * 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);
+
+ /*
+ * Implement in extending classes. This method should render any previously
+ * non-cached content and set the activeTabIndex property to the specified
+ * index.
+ */
+ protected abstract void selectTab(int index, final UIDL contentUidl);
+
+}
--- /dev/null
+.i-accordion {
+ outline: none;
+ border-bottom: 1px solid #c8cccd;
+}
+
+.i-accordion-item-caption {
+ height: 25px;
+ padding: 6px 0 0 18px;
+ overflow: hidden;
+ white-space: nowrap;
+ background: #edf0f0 url(../tabsheet/img/tab-bg.png);
+ font-size: 15px;
+ color: #656d73;
+ border-top: 1px solid #c8cccd;
+}
+
+.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);
+ border-top-color: #cbd7de;
+ border-bottom-color: #bfc9d4;
+}
+
+.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
--- /dev/null
+package com.itmill.toolkit.ui;
+
+public class Accordion extends TabSheet {
+
+ public String getTag() {
+ return "accordion";
+ }
+
+}
/**
*
- * @return true if spacing layout leaves space between components
+ * @return true if spacing, layout leaves space between components
*/
public boolean isSpacingEnabled() {
return spacing;