diff options
Diffstat (limited to 'src/com/vaadin/ui')
-rw-r--r-- | src/com/vaadin/ui/Button.java | 8 | ||||
-rw-r--r-- | src/com/vaadin/ui/DateField.java | 42 | ||||
-rw-r--r-- | src/com/vaadin/ui/LoginForm.java | 4 | ||||
-rw-r--r-- | src/com/vaadin/ui/MenuBar.java | 162 | ||||
-rw-r--r-- | src/com/vaadin/ui/TabSheet.java | 108 | ||||
-rw-r--r-- | src/com/vaadin/ui/Upload.java | 2 | ||||
-rw-r--r-- | src/com/vaadin/ui/Window.java | 50 |
7 files changed, 315 insertions, 61 deletions
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java index 6801bfa176..3ed50b2d42 100644 --- a/src/com/vaadin/ui/Button.java +++ b/src/com/vaadin/ui/Button.java @@ -36,7 +36,7 @@ public class Button extends AbstractField { * */ public Button() { - setValue(new Boolean(false)); + setValue(Boolean.FALSE); setSwitchMode(false); } @@ -96,7 +96,7 @@ public class Button extends AbstractField { */ public Button(String caption, boolean initialState) { setCaption(caption); - setValue(new Boolean(initialState)); + setValue(Boolean.valueOf(initialState)); setSwitchMode(true); } @@ -167,7 +167,7 @@ public class Button extends AbstractField { // If the button is true for some reason, release it if (oldValue.booleanValue()) { - setValue(new Boolean(false)); + setValue(Boolean.FALSE); } } } @@ -194,7 +194,7 @@ public class Button extends AbstractField { if (!switchMode) { setImmediate(true); if (booleanValue()) { - setValue(new Boolean(false)); + setValue(Boolean.FALSE); } } } diff --git a/src/com/vaadin/ui/DateField.java b/src/com/vaadin/ui/DateField.java index 69d6108152..425040a016 100644 --- a/src/com/vaadin/ui/DateField.java +++ b/src/com/vaadin/ui/DateField.java @@ -116,6 +116,8 @@ public class DateField extends AbstractField { */ private String dateString; + private boolean lenient = false; + /* Constructors */ /** @@ -202,6 +204,10 @@ public class DateField extends AbstractField { target.addAttribute("format", dateFormat); } + if (!isLenient()) { + target.addAttribute("strict", true); + } + target.addAttribute("type", type); // Gets the calendar @@ -332,13 +338,13 @@ public class DateField extends AbstractField { newDate = cal.getTime(); } - if (newDate != oldDate + if (newDate == null && dateString != null && !"".equals(dateString) + && !dateString.equals(oldDateString)) { + setValue(handleUnparsableDateString(dateString)); + } else if (newDate != oldDate && (newDate == null || !newDate.equals(oldDate))) { setValue(newDate, true); // Don't require a repaint, client // updates itself - } else if (dateString != null && !"".equals(dateString) - && !dateString.equals(oldDateString)) { - setValue(handleUnparsableDateString(dateString)); } } } @@ -511,4 +517,32 @@ public class DateField extends AbstractField { return dateFormat; } + /** + * Specifies whether or not date/time interpretation in component is to be + * lenient. + * + * @see Calendar#setLenient(boolean) + * @see #isLenient() + * + * @param lenient + * true if the lenient mode is to be turned on; false if it is to + * be turned off. + */ + public void setLenient(boolean lenient) { + this.lenient = lenient; + requestRepaint(); + } + + /** + * Specifies whether or not date/time interpretation is to be lenient. + * + * @see #setLenient(boolean) + * + * @return true if the interpretation mode of this calendar is lenient; + * false otherwise. + */ + public boolean isLenient() { + return lenient; + } + } diff --git a/src/com/vaadin/ui/LoginForm.java b/src/com/vaadin/ui/LoginForm.java index 33ee670f4b..76c567dc5e 100644 --- a/src/com/vaadin/ui/LoginForm.java +++ b/src/com/vaadin/ui/LoginForm.java @@ -161,12 +161,14 @@ public class LoginForm extends CustomComponent { + "document.getElementsByTagName('head')[0].appendChild(stylesheet);\n" + "}" + "}\n" + + "function submitOnEnter(e) { var keycode = e.keyCode || e.which;" + + " if (keycode == 13) {document.forms[0].submit();} } \n" + "</script>" + "</head><body onload='setTarget();' style='margin:0;padding:0; background:transparent;' class=\"v-generated-body\">" + "<div class='v-app v-app-loginpage' style=\"background:transparent;\">" + "<iframe name='logintarget' style='width:0;height:0;" + "border:0;margin:0;padding:0;'></iframe>" - + "<form id='loginf' target='logintarget'>" + + "<form id='loginf' target='logintarget' onkeypress=\"submitOnEnter(event)\">" + "<div>Username</div><div >" + "<input class='v-textfield' style='display:block;' type='text' name='username'></div>" + "<div>Password</div>" diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java index 30049431d3..5715e230c4 100644 --- a/src/com/vaadin/ui/MenuBar.java +++ b/src/com/vaadin/ui/MenuBar.java @@ -29,8 +29,20 @@ public class MenuBar extends AbstractComponent { // Number of items in this menu private static int numberOfItems = 0; + /** + * @deprecated + * @see #setCollapse(boolean) + */ + @Deprecated private boolean collapseItems; + + /** + * @deprecated + * @see #setSubmenuIcon(Resource) + */ + @Deprecated private Resource submenuIcon; + private MenuItem moreItem; /** Paint (serialise) the component for the client. */ @@ -49,9 +61,7 @@ public class MenuBar extends AbstractComponent { target.addAttribute("submenuIcon", submenuIcon); } - target.addAttribute("collapseItems", collapseItems); - - if (collapseItems) { + if (getWidth() > -1) { target.startTag("moreItem"); target.addAttribute("text", moreItem.getText()); if (moreItem.getIcon() != null) { @@ -69,31 +79,43 @@ public class MenuBar extends AbstractComponent { while (itr.hasNext()) { MenuItem item = itr.next(); + if (!item.isVisible()) { + continue; + } target.startTag("item"); - - target.addAttribute("text", item.getText()); target.addAttribute("id", item.getId()); - Command command = item.getCommand(); - if (command != null) { - target.addAttribute("command", true); + if (item.isSeparator()) { + target.addAttribute("separator", true); + target.endTag("item"); } else { - target.addAttribute("command", false); - } + target.addAttribute("text", item.getText()); - Resource icon = item.getIcon(); - if (icon != null) { - target.addAttribute("icon", icon); - } + Command command = item.getCommand(); + if (command != null) { + target.addAttribute("command", true); + } + + Resource icon = item.getIcon(); + if (icon != null) { + target.addAttribute("icon", icon); + } + + if (!item.isEnabled()) { + target.addAttribute("disabled", true); + } - if (item.hasChildren()) { - iteratorStack.push(itr); // For later use + if (item.hasChildren()) { + iteratorStack.push(itr); // For later use + + // Go through the children + itr = item.getChildren().iterator(); + } else { + target.endTag("item"); // Item had no children, end + // description + } - // Go through the children - itr = item.getChildren().iterator(); - } else { - target.endTag("item"); // Item had no children, end description } // The end submenu. More than one submenu may end at once. @@ -101,7 +123,6 @@ public class MenuBar extends AbstractComponent { itr = iteratorStack.pop(); target.endTag("item"); } - } target.endTag("items"); @@ -138,7 +159,7 @@ public class MenuBar extends AbstractComponent { }// while // If we got the clicked item, launch the command. - if (found) { + if (found && tmpItem.isEnabled()) { tmpItem.getCommand().menuSelected(tmpItem); } }// if @@ -270,40 +291,46 @@ public class MenuBar extends AbstractComponent { * Set the icon to be used if a sub-menu has children. Defaults to null; * * @param icon + * @deprecated (since 6.2, will be removed in 7.0) Icon is set in theme, no + * need to worry about the visual representation here. */ + @Deprecated public void setSubmenuIcon(Resource icon) { submenuIcon = icon; requestRepaint(); } /** - * Get the icon used for sub-menus. Returns null if no icon is set. - * - * @return + * @deprecated + * @see #setSubmenuIcon(Resource) */ + @Deprecated public Resource getSubmenuIcon() { return submenuIcon; } /** * Enable or disable collapsing top-level items. Top-level items will - * collapse to if there is not enough room for them. Items that don't fit - * will be placed under the "More" menu item. + * collapse together if there is not enough room for them. Items that don't + * fit will be placed under the "More" menu item. * * Collapsing is enabled by default. * * @param collapse + * @deprecated (since 6.2, will be removed in 7.0) Collapsing is always + * enabled if the MenuBar has a specified width. */ + @Deprecated public void setCollapse(boolean collapse) { collapseItems = collapse; requestRepaint(); } /** - * Collapsing is enabled by default. - * - * @return true if the top-level items will be collapsed + * @see #setCollapse(boolean) + * @deprecated */ + @Deprecated public boolean getCollapse() { return collapseItems; } @@ -311,8 +338,9 @@ public class MenuBar extends AbstractComponent { /** * Set the item that is used when collapsing the top level menu. All * "overflowing" items will be added below this. The item command will be - * ignored. If set to null, the default item with the "More" text is be - * used. + * ignored. If set to null, the default item with a downwards arrow is used. + * + * The item command (if specified) is ignored. * * @param item */ @@ -320,7 +348,7 @@ public class MenuBar extends AbstractComponent { if (item != null) { moreItem = item; } else { - moreItem = new MenuItem("More", null, null); + moreItem = new MenuItem("", null, null); } requestRepaint(); } @@ -360,6 +388,9 @@ public class MenuBar extends AbstractComponent { private List<MenuItem> itsChildren; private Resource itsIcon; private MenuItem itsParent; + private boolean enabled = true; + private boolean visible = true; + private boolean isSeparator = false; /** * Constructs a new menu item that can optionally have an icon and a @@ -388,7 +419,27 @@ public class MenuBar extends AbstractComponent { * @return True if this item has children */ public boolean hasChildren() { - return itsChildren != null; + return !isSeparator() && itsChildren != null; + } + + /** + * Adds a separator to this menu. A separator is a way to visually group + * items in a menu, to make it easier for users to find what they are + * looking for in the menu. + * + * @author Jouni Koivuviita / IT Mill Ltd. + * @since 6.2.0 + */ + public MenuBar.MenuItem addSeparator() { + MenuItem item = addItem("", null, null); + item.setSeparator(true); + return item; + } + + public MenuBar.MenuItem addSeparatorBefore(MenuItem itemToAddBefore) { + MenuItem item = addItemBefore("", null, null, itemToAddBefore); + item.setSeparator(true); + return item; } /** @@ -417,8 +468,12 @@ public class MenuBar extends AbstractComponent { */ public MenuBar.MenuItem addItem(String caption, Resource icon, MenuBar.Command command) { + if (isSeparator()) { + throw new UnsupportedOperationException( + "Cannot add items to a separator"); + } if (caption == null) { - throw new IllegalArgumentException("caption cannot be null"); + throw new IllegalArgumentException("Caption cannot be null"); } if (itsChildren == null) { @@ -461,7 +516,6 @@ public class MenuBar extends AbstractComponent { newItem = new MenuItem(caption, icon, command); newItem.setParent(this); itsChildren.add(index, newItem); - } else { newItem = addItem(caption, icon, command); } @@ -524,7 +578,10 @@ public class MenuBar extends AbstractComponent { * @return The number of child items */ public int getSize() { - return itsChildren.size(); + if (itsChildren != null) { + return itsChildren.size(); + } + return -1; } /** @@ -582,8 +639,8 @@ public class MenuBar extends AbstractComponent { if (itsChildren.isEmpty()) { itsChildren = null; } + requestRepaint(); } - requestRepaint(); } /** @@ -593,8 +650,8 @@ public class MenuBar extends AbstractComponent { if (itsChildren != null) { itsChildren.clear(); itsChildren = null; + requestRepaint(); } - requestRepaint(); } /** @@ -607,6 +664,33 @@ public class MenuBar extends AbstractComponent { itsParent = parent; } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + requestRepaint(); + } + + public boolean isEnabled() { + return enabled; + } + + public void setVisible(boolean visible) { + this.visible = visible; + requestRepaint(); + } + + public boolean isVisible() { + return visible; + } + + private void setSeparator(boolean isSeparator) { + this.isSeparator = isSeparator; + requestRepaint(); + } + + public boolean isSeparator() { + return isSeparator; + } + }// class MenuItem }// class MenuBar diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java index ed81fdb655..b58e7be7bf 100644 --- a/src/com/vaadin/ui/TabSheet.java +++ b/src/com/vaadin/ui/TabSheet.java @@ -35,7 +35,7 @@ public class TabSheet extends AbstractComponentContainer implements /** * Linked list of component tabs. */ - private final LinkedList components = new LinkedList(); + private final LinkedList<Component> components = new LinkedList<Component>(); /** * Map containing information related to the tabs (caption, icon etc). @@ -54,7 +54,9 @@ public class TabSheet extends AbstractComponentContainer implements */ private boolean tabsHidden; - private LinkedList paintedTabs = new LinkedList(); + private LinkedList<Component> paintedTabs = new LinkedList<Component>(); + + private CloseHandler closeHandler; /** * Constructs a new Tabsheet. Tabsheet is immediate by default. @@ -64,6 +66,11 @@ public class TabSheet extends AbstractComponentContainer implements // expand horizontally by default setWidth(100, UNITS_PERCENTAGE); setImmediate(true); + setCloseHandler(new CloseHandler() { + public void onTabClose(TabSheet tabsheet, Component c) { + tabsheet.removeComponent(c); + } + }); } /** @@ -72,7 +79,7 @@ public class TabSheet extends AbstractComponentContainer implements * * @return the Iterator of the components inside the container. */ - public Iterator getComponentIterator() { + public Iterator<Component> getComponentIterator() { return java.util.Collections.unmodifiableList(components).iterator(); } @@ -93,7 +100,7 @@ public class TabSheet extends AbstractComponentContainer implements if (components.isEmpty()) { selected = null; } else { - selected = (Component) components.getFirst(); + selected = components.getFirst(); fireSelectedTabChange(); } } @@ -168,8 +175,9 @@ public class TabSheet extends AbstractComponentContainer implements */ @Override public void moveComponentsFrom(ComponentContainer source) { - for (final Iterator i = source.getComponentIterator(); i.hasNext();) { - final Component c = (Component) i.next(); + for (final Iterator<Component> i = source.getComponentIterator(); i + .hasNext();) { + final Component c = i.next(); String caption = null; Resource icon = null; if (TabSheet.class.isAssignableFrom(source.getClass())) { @@ -199,8 +207,8 @@ public class TabSheet extends AbstractComponentContainer implements target.startTag("tabs"); - for (final Iterator i = getComponentIterator(); i.hasNext();) { - final Component component = (Component) i.next(); + for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) { + final Component component = i.next(); Tab tab = tabs.get(component); /* @@ -236,6 +244,10 @@ public class TabSheet extends AbstractComponentContainer implements target.addAttribute("hidden", true); } + if (tab.isClosable()) { + target.addAttribute("closable", true); + } + final Resource icon = tab.getIcon(); if (icon != null) { target.addAttribute("icon", icon); @@ -417,6 +429,13 @@ public class TabSheet extends AbstractComponentContainer implements setSelectedTab((Component) keyMapper.get((String) variables .get("selected"))); } + if (variables.containsKey("close")) { + final Component tab = (Component) keyMapper.get((String) variables + .get("close")); + if (tab != null) { + closeHandler.onTabClose(this, tab); + } + } } /* Documented in superclass */ @@ -453,8 +472,8 @@ public class TabSheet extends AbstractComponentContainer implements int oldLocation = -1; int newLocation = -1; int location = 0; - for (final Iterator i = components.iterator(); i.hasNext();) { - final Component component = (Component) i.next(); + for (final Iterator<Component> i = components.iterator(); i.hasNext();) { + final Component component = i.next(); if (component == oldComponent) { oldLocation = location; @@ -636,6 +655,23 @@ public class TabSheet extends AbstractComponentContainer implements public void setVisible(boolean visible); /** + * Returns the closability status for the tab. + * + * @return true if the tab is allowed to be closed by the end user, + * false for not allowing closing + */ + public boolean isClosable(); + + /** + * Sets the closability status for the tab. + * + * @param visible + * true if the end user is allowed to close the tab, false + * for not allowing to close. Should default to false. + */ + public void setClosable(boolean closable); + + /** * Returns the enabled status for the tab. * * @return true for enabled, false for disabled @@ -710,6 +746,7 @@ public class TabSheet extends AbstractComponentContainer implements private Resource icon = null; private boolean enabled = true; private boolean visible = true; + private boolean closable = false; private String description = null; private ErrorMessage componentError = null; @@ -760,6 +797,19 @@ public class TabSheet extends AbstractComponentContainer implements requestRepaint(); } + public boolean isClosable() { + return closable; + } + + public void setClosable(boolean closable) { + this.closable = closable; + requestRepaint(); + } + + public void close() { + + } + public String getDescription() { return description; } @@ -777,6 +827,44 @@ public class TabSheet extends AbstractComponentContainer implements this.componentError = componentError; requestRepaint(); } + } + + /** + * CloseHandler is used to process tab closing events. Default behavior is + * to remove the tab from the TabSheet. + * + * @author Jouni Koivuviita / IT Mill Ltd. + * @since 6.2.0 + * + */ + public interface CloseHandler { + /** + * Called when a user has pressed the close icon of a tab in the client + * side widget. + * + * @param tabsheet + * the TabSheet to which the tab belongs to + * @param tabContent + * the component that corresponds to the tab whose close + * button was clicked + */ + void onTabClose(final TabSheet tabsheet, final Component tabContent); + } + + /** + * Provide a custom {@link CloseHandler} for this TabSheet if you wish to + * perform some additional tasks when a user clicks on a tabs close button, + * e.g. show a confirmation dialogue before removing the tab. + * + * To remove the tab, if you provide your own close handler, you must call + * {@link #removeComponent(Component)} yourself. + * + * The default CloseHandler for TabSheet will only remove the tab. + * + * @param handler + */ + public void setCloseHandler(CloseHandler handler) { + closeHandler = handler; } } diff --git a/src/com/vaadin/ui/Upload.java b/src/com/vaadin/ui/Upload.java index dfbbbfc103..e3512a4795 100644 --- a/src/com/vaadin/ui/Upload.java +++ b/src/com/vaadin/ui/Upload.java @@ -244,8 +244,6 @@ public class Upload extends AbstractComponent implements Component.Focusable { target.addAttribute("buttoncaption", buttonCaption); - target.addVariable(this, "fake", true); - target.addUploadStreamVariable(this, "stream"); } diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java index dc1bf7e18f..d234f7aaac 100644 --- a/src/com/vaadin/ui/Window.java +++ b/src/com/vaadin/ui/Window.java @@ -8,6 +8,7 @@ import java.io.Serializable; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; @@ -119,6 +120,8 @@ public class Window extends Panel implements URIHandler, ParameterHandler { private Focusable pendingFocus; + private ArrayList<String> jsExecQueue = null; + /* ********************************************************************* */ /** @@ -381,7 +384,7 @@ public class Window extends Panel implements URIHandler, ParameterHandler { if (getParent() != null) { // this is subwindow Window mainWindow = (Window) getParent(); - mainWindow.addParameterHandler(handler); + mainWindow.removeParameterHandler(handler); } else { if (handler == null || parameterHandlerList == null) { return; @@ -520,6 +523,16 @@ public class Window extends Panel implements URIHandler, ParameterHandler { // Contents of the window panel is painted super.paintContent(target); + // Add executable javascripts if needed + if (jsExecQueue != null) { + for (String script : jsExecQueue) { + target.startTag("execJS"); + target.addAttribute("script", script); + target.endTag("execJS"); + } + jsExecQueue = null; + } + // Window position target.addVariable(this, "positionx", getPositionX()); target.addVariable(this, "positiony", getPositionY()); @@ -1632,4 +1645,39 @@ public class Window extends Panel implements URIHandler, ParameterHandler { } } + /** + * Executes JavaScript in this window. + * + * <p> + * This method allows one to inject javascript from the server to client. A + * client implementation is not required to implement this functionality, + * but currently all web-based clients do implement this. + * </p> + * + * <p> + * Executing javascript this way often leads to cross-browser compatibility + * issues and regressions that are hard to resolve. Use of this method + * should be avoided and instead it is recommended to create new widgets + * with GWT. For more info on creating own, reusable client-side widgets in + * Java, read the corresponding chapter in Book of Vaadin. + * </p> + * + * @param script + * JavaScript snippet that will be executed. + */ + public void executeJavaScript(String script) { + + if (getParent() != null) { + throw new UnsupportedOperationException( + "Only application level windows can execute javascript."); + } + + if (jsExecQueue == null) { + jsExecQueue = new ArrayList<String>(); + } + + jsExecQueue.add(script); + + requestRepaint(); + } } |