From cc3d673ad83b048a838a8db3198066cad7bd7ab1 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Thu, 26 Jan 2012 14:33:28 +0200 Subject: [PATCH] Split VScrollTable, VTreeTable and VMenuBar into paintable and widget classes. Improved VAbstractPaintable --- .../gwt/client/ApplicationConnection.java | 41 +- .../vaadin/terminal/gwt/client/Container.java | 4 +- src/com/vaadin/terminal/gwt/client/Util.java | 18 + .../terminal/gwt/client/VPaintable.java | 57 ++- .../terminal/gwt/client/VPaintableMap.java | 11 +- .../terminal/gwt/client/VPaintableWidget.java | 3 +- .../gwt/client/ui/ShortcutActionHandler.java | 9 +- .../client/ui/VAbstractPaintableWidget.java | 41 +- .../gwt/client/ui/VDragAndDropWrapper.java | 11 +- .../terminal/gwt/client/ui/VMenuBar.java | 145 +------ .../gwt/client/ui/VMenuBarPaintable.java | 161 ++++++++ .../terminal/gwt/client/ui/VScrollTable.java | 386 +++++------------- .../gwt/client/ui/VScrollTablePaintable.java | 251 ++++++++++++ .../terminal/gwt/client/ui/VTreeTable.java | 92 +---- .../gwt/client/ui/VTreeTablePaintable.java | 98 +++++ .../terminal/gwt/client/ui/VUpload.java | 2 +- .../terminal/gwt/client/ui/label/VLabel.java | 7 +- .../gwt/client/ui/label/VLabelPaintable.java | 22 +- src/com/vaadin/ui/MenuBar.java | 3 +- src/com/vaadin/ui/Table.java | 3 +- src/com/vaadin/ui/TreeTable.java | 7 +- 21 files changed, 809 insertions(+), 563 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index f8ca0a6959..9b756382f3 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -36,6 +36,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; import com.vaadin.terminal.gwt.client.RenderInformation.Size; import com.vaadin.terminal.gwt.client.ui.Field; +import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.VNotification; import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent; @@ -1586,9 +1587,10 @@ public class ApplicationConnection { * * @return Returns true iff no further painting is needed by caller */ - public boolean updateComponent(Widget component, UIDL uidl, + @Deprecated + public boolean updateComponent(VPaintableWidget paintable, UIDL uidl, boolean manageCaption) { - VPaintableWidget paintable = paintableMap.getPaintable(component); + Widget component = paintable.getWidgetForPaintable(); String pid = paintableMap.getPid(paintable); if (pid == null) { @@ -2029,6 +2031,10 @@ public class ApplicationConnection { if (!paintableMap.hasPaintable(pid)) { // Create and register a new paintable if no old was found VPaintableWidget p = widgetSet.createWidget(uidl, configuration); + if (p instanceof VAbstractPaintableWidget) { + ((VAbstractPaintableWidget) p).setConnection(this); + ((VAbstractPaintableWidget) p).init(); + } paintableMap.registerPaintable(pid, p); } return (VPaintableWidget) paintableMap.getPaintable(pid); @@ -2192,7 +2198,7 @@ public class ApplicationConnection { } }; - private VPaintableMap paintableMap = new VPaintableMap(); + private VPaintableMap paintableMap = GWT.create(VPaintableMap.class); /** * Components can call this function to run all layout functions. This is @@ -2275,7 +2281,7 @@ public class ApplicationConnection { * @return true if at least one listener has been registered on server side * for the event identified by eventIdentifier. */ - public boolean hasEventListeners(VPaintable paintable, + public boolean hasEventListeners(VPaintableWidget paintable, String eventIdentifier) { return paintableMap.hasEventListeners(paintable, eventIdentifier); } @@ -2330,4 +2336,31 @@ public class ApplicationConnection { paintableMap.unregisterPaintable(p); } + public VTooltip getVTooltip() { + return tooltip; + } + + @Deprecated + public void handleWidgetTooltipEvent(Event event, Widget owner, Object key) { + handleTooltipEvent(event, getPaintableMap().getPaintable(owner), key); + + } + + @Deprecated + public void handleWidgetTooltipEvent(Event event, Widget owner) { + handleTooltipEvent(event, getPaintableMap().getPaintable(owner)); + + } + + @Deprecated + public void registerWidgetTooltip(Widget owner, Object key, TooltipInfo info) { + registerTooltip(getPaintableMap().getPaintable(owner), key, info); + } + + @Deprecated + public boolean hasWidgetEventListeners(Widget widget, String eventIdentifier) { + return hasEventListeners(getPaintableMap().getPaintable(widget), + eventIdentifier); + } + } diff --git a/src/com/vaadin/terminal/gwt/client/Container.java b/src/com/vaadin/terminal/gwt/client/Container.java index 7c92bc261b..db6bbf0ee4 100644 --- a/src/com/vaadin/terminal/gwt/client/Container.java +++ b/src/com/vaadin/terminal/gwt/client/Container.java @@ -42,12 +42,12 @@ public interface Container extends VPaintableWidget { * must provide service for it's childen to show those elements for them. *

* - * @param component + * @param paintable * Child component for which service is requested. * @param uidl * UIDL of the child component. */ - void updateCaption(VPaintableWidget component, UIDL uidl); + void updateCaption(VPaintableWidget paintable, UIDL uidl); /** * Called when a child components size has been updated in the rendering diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index 597ca3d49c..2a3fc07195 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -829,6 +829,24 @@ public class Util { } }-*/; + /** + * Helper method to find the nearest parent paintable instance by traversing + * the DOM upwards from given element. + * + * @param element + * the element to start from + */ + public static VPaintableWidget findPaintable(ApplicationConnection client, + Element element) { + Widget widget = Util.findWidget(element, null); + VPaintableMap vPaintableMap = VPaintableMap.get(client); + while (widget != null && !vPaintableMap.isPaintable(widget)) { + widget = widget.getParent(); + } + return vPaintableMap.getPaintable(widget); + + } + /** * Helper method to find first instance of given Widget type found by * traversing DOM upwards from given element. diff --git a/src/com/vaadin/terminal/gwt/client/VPaintable.java b/src/com/vaadin/terminal/gwt/client/VPaintable.java index 02b529b428..d85c6d33e2 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintable.java @@ -4,8 +4,13 @@ package com.vaadin.terminal.gwt.client; /** - * TODO + * Interface implemented by all client side classes that can be communicate with + * the server. Classes implementing this interface are initialized by the + * framework when needed and have the ability to communicate with the server. * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 */ public interface VPaintable { /** @@ -16,4 +21,54 @@ public interface VPaintable { */ public void updateFromUIDL(UIDL uidl, ApplicationConnection client); + // /** + // * Returns the id for this VPaintable. This must always be what has been + // set + // * using {@link #setId(String)}. + // * + // * @return The id for the VPaintable. + // */ + // public String getId(); + // + // /** + // * Sets the id for the VPaintable. This method is called once by the + // * framework when the VPaintable is initialized and should never be called + // * otherwise. + // *

+ // * The VPaintable id is used to map the server and the client paintables + // * together. It is unique in this root and assigned by the framework. + // *

+ // * + // * @param id + // * The id of the paintable. + // */ + // public void setId(String id); + + /** + * Gets ApplicationConnection instance that created this VPaintable. + * + * @return The ApplicationConnection as set by + * {@link #setConnection(ApplicationConnection)} + */ + // public ApplicationConnection getConnection(); + + /** + * Sets the reference to ApplicationConnection. This method is called by the + * framework when the VPaintable is created and should never be called + * otherwise. + * + * @param connection + * The ApplicationConnection that created this VPaintable + */ + // public void setConnection(ApplicationConnection connection); + + /** + * Tests whether the component is enabled or not. A user can not interact + * with disabled components. Disabled components are rendered in a style + * that indicates the status, usually in gray color. Children of a disabled + * component are also disabled. + * + * @return true if the component is enabled, false otherwise + */ + // public boolean isEnabled(); } diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java index ef355d3cad..f21d85558c 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java @@ -335,7 +335,7 @@ public class VPaintableMap { } - private ComponentDetail getComponentDetail(VPaintable paintable) { + private ComponentDetail getComponentDetail(VPaintableWidget paintable) { return idToComponentDetail.get(getPid(paintable)); } @@ -344,7 +344,7 @@ public class VPaintableMap { } /** - * FIXME: Should not be here + * FIXME: Should be moved to VAbstractPaintableWidget * * @param paintable * @return @@ -354,6 +354,11 @@ public class VPaintableMap { return getComponentDetail(paintable).getTooltipInfo(key); } + @Deprecated + public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) { + return getTooltipInfo(getPaintable(widget), key); + } + public Collection getPaintables() { return Collections.unmodifiableCollection(paintableToId.keySet()); } @@ -378,7 +383,7 @@ public class VPaintableMap { * @return */ @Deprecated - public boolean hasEventListeners(VPaintable paintable, + public boolean hasEventListeners(VPaintableWidget paintable, String eventIdentifier) { return getComponentDetail(paintable).hasEventListeners(eventIdentifier); } diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java index 9171fdceda..2f0cae1cc1 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java @@ -17,7 +17,8 @@ import com.google.gwt.user.client.ui.Widget; public interface VPaintableWidget extends VPaintable { /** - * TODO: Renamed to getWidget + * TODO: Rename to getWidget */ public Widget getWidgetForPaintable(); + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java index 38f7878ba4..2bd578a45d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java @@ -15,13 +15,11 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.KeyboardListener; import com.google.gwt.user.client.ui.KeyboardListenerCollection; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea; @@ -137,12 +135,7 @@ public class ShortcutActionHandler { VPaintableWidget target) { final Element et = DOM.eventGetTarget(event); if (target == null) { - Widget w = Util.findWidget(et, null); - VPaintableMap paintableMap = VPaintableMap.get(client); - while (w != null && !paintableMap.isPaintable(w)) { - w = w.getParent(); - } - target = paintableMap.getPaintable(w); + target = Util.findPaintable(client, et); } final VPaintableWidget finalTarget = target; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java index dff5a286ba..d4c8f79467 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java @@ -1,12 +1,16 @@ package com.vaadin.terminal.gwt.client.ui; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.VPaintableWidget; public abstract class VAbstractPaintableWidget implements VPaintableWidget { private Widget widget; + private ApplicationConnection connection; + + /* State variables */ +// private boolean enabled = true; /** * Default constructor @@ -14,15 +18,19 @@ public abstract class VAbstractPaintableWidget implements VPaintableWidget { public VAbstractPaintableWidget() { } + /** + * Called after the application connection reference has been set up + */ + public void init() { + } + /** * Creates and returns the widget for this VPaintableWidget. This method * should only be called once when initializing the paintable. * * @return */ - protected Widget createWidget() { - return GWT.create(getWidgetClass()); - } + protected abstract Widget createWidget(); /** * Returns the widget associated with this paintable. The widget returned by @@ -38,12 +46,27 @@ public abstract class VAbstractPaintableWidget implements VPaintableWidget { return widget; } - /** - * Returns the class of the widget for this paintable. Used to instansiate - * the widget. + /* + * (non-Javadoc) + * + * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection() + */ + public final ApplicationConnection getConnection() { + return connection; + } + + /* + * (non-Javadoc) * - * @return The widget class. + * @see + * com.vaadin.terminal.gwt.client.VPaintable#setConnection(com.vaadin.terminal + * .gwt.client.ApplicationConnection) */ - protected abstract Class getWidgetClass(); + public final void setConnection(ApplicationConnection connection) { + this.connection = connection; + } +// public boolean isEnabled() { +// return enabled; +// } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java index da916f262e..3251a03d6a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java @@ -113,14 +113,9 @@ public class VDragAndDropWrapper extends VCustomComponent implements VTransferable transferable = new VTransferable(); transferable.setDragSource(VDragAndDropWrapper.this); - Widget widget = Util.findWidget((Element) event.getEventTarget() - .cast(), null); - VPaintableMap vPaintableMap = VPaintableMap.get(client); - while (widget != null && !vPaintableMap.isPaintable(widget)) { - widget = widget.getParent(); - } - VPaintableWidget paintable = vPaintableMap.getPaintable(widget); - + VPaintableWidget paintable = Util.findPaintable(client, + (Element) event.getEventTarget().cast()); + Widget widget = paintable.getWidgetForPaintable(); transferable.setData("component", paintable); VDragEvent dragEvent = VDragAndDropManager.get().startDrag( transferable, event, true); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java index 306086e357..372ddf25d2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java @@ -4,9 +4,7 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.Stack; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; @@ -35,14 +33,12 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ContainerResizedListener; -import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; -public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, +public class VMenuBar extends SimpleFocusablePanel implements CloseHandler, ContainerResizedListener, KeyPressHandler, KeyDownHandler, FocusHandler, SubPartAware { @@ -82,7 +78,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, protected VMenuBar parentMenu; protected CustomMenuItem selected; - private boolean enabled = true; + boolean enabled = true; private String width = "notinited"; @@ -94,9 +90,9 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, } }); - private boolean openRootOnHover; + boolean openRootOnHover; - private boolean htmlContentAllowed; + boolean htmlContentAllowed; public VMenuBar() { // Create an empty horizontal menubar @@ -167,133 +163,6 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, } } - /** - * This method must be implemented to update the client-side component from - * UIDL data received from server. - * - * This method is called when the page is loaded for the first time, and - * every time UI changes in the component are received from the server. - */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // This call should be made first. Ensure correct implementation, - // and let the containing layout manage caption, etc. - if (client.updateComponent(this, uidl, true)) { - return; - } - - htmlContentAllowed = uidl.hasAttribute(HTML_CONTENT_ALLOWED); - - openRootOnHover = uidl.getBooleanAttribute(OPEN_ROOT_MENU_ON_HOWER); - - enabled = !uidl.getBooleanAttribute("disabled"); - - // For future connections - this.client = client; - uidlId = uidl.getId(); - - // Empty the menu every time it receives new information - if (!getItems().isEmpty()) { - clearItems(); - } - - UIDL options = uidl.getChildUIDL(0); - - if (uidl.hasAttribute("width")) { - UIDL moreItemUIDL = options.getChildUIDL(0); - StringBuffer itemHTML = new StringBuffer(); - - if (moreItemUIDL.hasAttribute("icon")) { - itemHTML.append("\"\""); - } - - String moreItemText = moreItemUIDL.getStringAttribute("text"); - if ("".equals(moreItemText)) { - moreItemText = "►"; - } - itemHTML.append(moreItemText); - - moreItem = GWT.create(CustomMenuItem.class); - moreItem.setHTML(itemHTML.toString()); - moreItem.setCommand(emptyCommand); - - collapsedRootItems = new VMenuBar(true, (VMenuBar) VPaintableMap - .get(client).getPaintable(uidlId)); - moreItem.setSubMenu(collapsedRootItems); - moreItem.addStyleName(CLASSNAME + "-more-menuitem"); - } - - UIDL uidlItems = uidl.getChildUIDL(1); - Iterator itr = uidlItems.getChildIterator(); - Stack> iteratorStack = new Stack>(); - Stack menuStack = new Stack(); - VMenuBar currentMenu = this; - - while (itr.hasNext()) { - UIDL item = (UIDL) itr.next(); - CustomMenuItem currentItem = null; - - final int itemId = item.getIntAttribute("id"); - - boolean itemHasCommand = item.hasAttribute("command"); - boolean itemIsCheckable = item.hasAttribute(ATTRIBUTE_CHECKED); - - String itemHTML = buildItemHTML(item); - - Command cmd = null; - if (!item.hasAttribute("separator")) { - if (itemHasCommand || itemIsCheckable) { - // Construct a command that fires onMenuClick(int) with the - // item's id-number - cmd = new Command() { - public void execute() { - hostReference.onMenuClick(itemId); - } - }; - } - } - - currentItem = currentMenu.addItem(itemHTML.toString(), cmd); - currentItem.updateFromUIDL(item, client); - - if (item.getChildCount() > 0) { - menuStack.push(currentMenu); - iteratorStack.push(itr); - itr = item.getChildIterator(); - currentMenu = new VMenuBar(true, currentMenu); - if (uidl.hasAttribute("style")) { - for (String style : uidl.getStringAttribute("style").split( - " ")) { - currentMenu.addStyleDependentName(style); - } - } - currentItem.setSubMenu(currentMenu); - } - - while (!itr.hasNext() && !iteratorStack.empty()) { - boolean hasCheckableItem = false; - for (CustomMenuItem menuItem : currentMenu.getItems()) { - hasCheckableItem = hasCheckableItem - || menuItem.isCheckable(); - } - if (hasCheckableItem) { - currentMenu.addStyleDependentName("check-column"); - } else { - currentMenu.removeStyleDependentName("check-column"); - } - - itr = iteratorStack.pop(); - currentMenu = menuStack.pop(); - } - }// while - - iLayout(false); - - }// updateFromUIDL - /** * Build the HTML content for a menu item. * @@ -473,7 +342,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, // Handle tooltips if (targetItem == null && client != null) { // Handle root menubar tooltips - client.handleTooltipEvent(e, this); + client.handleWidgetTooltipEvent(e, this); } else if (targetItem != null) { // Handle item tooltips targetItem.onBrowserEvent(e); @@ -1051,7 +920,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, TooltipInfo info = new TooltipInfo(description); VMenuBar root = findRootMenu(); - client.registerTooltip(root, this, info); + client.registerWidgetTooltip(root, this, info); } } @@ -1059,7 +928,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget, public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, findRootMenu(), this); + client.handleWidgetTooltipEvent(event, findRootMenu(), this); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java new file mode 100644 index 0000000000..38b3cac358 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java @@ -0,0 +1,161 @@ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Iterator; +import java.util.Stack; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.ui.VMenuBar.CustomMenuItem; + +public class VMenuBarPaintable extends VAbstractPaintableWidget { + /** + * This method must be implemented to update the client-side component from + * UIDL data received from server. + * + * This method is called when the page is loaded for the first time, and + * every time UI changes in the component are received from the server. + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // This call should be made first. Ensure correct implementation, + // and let the containing layout manage caption, etc. + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().htmlContentAllowed = uidl + .hasAttribute(VMenuBar.HTML_CONTENT_ALLOWED); + + getWidgetForPaintable().openRootOnHover = uidl + .getBooleanAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER); + + getWidgetForPaintable().enabled = !uidl.getBooleanAttribute("disabled"); + + // For future connections + getWidgetForPaintable().client = client; + getWidgetForPaintable().uidlId = uidl.getId(); + + // Empty the menu every time it receives new information + if (!getWidgetForPaintable().getItems().isEmpty()) { + getWidgetForPaintable().clearItems(); + } + + UIDL options = uidl.getChildUIDL(0); + + if (uidl.hasAttribute("width")) { + UIDL moreItemUIDL = options.getChildUIDL(0); + StringBuffer itemHTML = new StringBuffer(); + + if (moreItemUIDL.hasAttribute("icon")) { + itemHTML.append("\"\""); + } + + String moreItemText = moreItemUIDL.getStringAttribute("text"); + if ("".equals(moreItemText)) { + moreItemText = "►"; + } + itemHTML.append(moreItemText); + + getWidgetForPaintable().moreItem = GWT.create(CustomMenuItem.class); + getWidgetForPaintable().moreItem.setHTML(itemHTML.toString()); + getWidgetForPaintable().moreItem + .setCommand(getWidgetForPaintable().emptyCommand); + + getWidgetForPaintable().collapsedRootItems = new VMenuBar(true, + (VMenuBar) VPaintableMap.get(client).getPaintable( + getWidgetForPaintable().uidlId)); + getWidgetForPaintable().moreItem + .setSubMenu(getWidgetForPaintable().collapsedRootItems); + getWidgetForPaintable().moreItem.addStyleName(VMenuBar.CLASSNAME + + "-more-menuitem"); + } + + UIDL uidlItems = uidl.getChildUIDL(1); + Iterator itr = uidlItems.getChildIterator(); + Stack> iteratorStack = new Stack>(); + Stack menuStack = new Stack(); + VMenuBar currentMenu = getWidgetForPaintable(); + + while (itr.hasNext()) { + UIDL item = (UIDL) itr.next(); + CustomMenuItem currentItem = null; + + final int itemId = item.getIntAttribute("id"); + + boolean itemHasCommand = item.hasAttribute("command"); + boolean itemIsCheckable = item + .hasAttribute(VMenuBar.ATTRIBUTE_CHECKED); + + String itemHTML = getWidgetForPaintable().buildItemHTML(item); + + Command cmd = null; + if (!item.hasAttribute("separator")) { + if (itemHasCommand || itemIsCheckable) { + // Construct a command that fires onMenuClick(int) with the + // item's id-number + cmd = new Command() { + public void execute() { + getWidgetForPaintable().hostReference + .onMenuClick(itemId); + } + }; + } + } + + currentItem = currentMenu.addItem(itemHTML.toString(), cmd); + currentItem.updateFromUIDL(item, client); + + if (item.getChildCount() > 0) { + menuStack.push(currentMenu); + iteratorStack.push(itr); + itr = item.getChildIterator(); + currentMenu = new VMenuBar(true, currentMenu); + if (uidl.hasAttribute("style")) { + for (String style : uidl.getStringAttribute("style").split( + " ")) { + currentMenu.addStyleDependentName(style); + } + } + currentItem.setSubMenu(currentMenu); + } + + while (!itr.hasNext() && !iteratorStack.empty()) { + boolean hasCheckableItem = false; + for (CustomMenuItem menuItem : currentMenu.getItems()) { + hasCheckableItem = hasCheckableItem + || menuItem.isCheckable(); + } + if (hasCheckableItem) { + currentMenu.addStyleDependentName("check-column"); + } else { + currentMenu.removeStyleDependentName("check-column"); + } + + itr = iteratorStack.pop(); + currentMenu = menuStack.pop(); + } + }// while + + getWidgetForPaintable().iLayout(false); + + }// updateFromUIDL + + @Override + protected Widget createWidget() { + return GWT.create(VMenuBar.class); + } + + @Override + public VMenuBar getWidgetForPaintable() { + return (VMenuBar) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 736635ecd0..41b7efcf02 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -52,6 +52,7 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.UIObject; @@ -103,17 +104,31 @@ import com.vaadin.terminal.gwt.client.ui.label.VLabel; * * TODO implement unregistering for child components in Cells */ -public class VScrollTable extends FlowPanel implements Table, ScrollHandler, - VHasDropHandler, FocusHandler, BlurHandler, Focusable, ActionOwner { +public class VScrollTable extends FlowPanel implements HasWidgets, + ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable, + ActionOwner { - public static final String ATTRIBUTE_PAGEBUFFER_FIRST = "pb-ft"; - public static final String ATTRIBUTE_PAGEBUFFER_LAST = "pb-l"; + public enum SelectMode { + NONE(0), SINGLE(1), MULTI(2); + private int id; + + private SelectMode(int id) { + this.id = id; + } + + public int getId() { + return id; + } + } private static final String ROW_HEADER_COLUMN_KEY = "0"; public static final String CLASSNAME = "v-table"; public static final String CLASSNAME_SELECTION_FOCUS = CLASSNAME + "-focus"; + public static final String ATTRIBUTE_PAGEBUFFER_FIRST = "pb-ft"; + public static final String ATTRIBUTE_PAGEBUFFER_LAST = "pb-l"; + public static final String ITEM_CLICK_EVENT_ID = "itemClick"; public static final String HEADER_CLICK_EVENT_ID = "handleHeaderClick"; public static final String FOOTER_CLICK_EVENT_ID = "handleFooterClick"; @@ -162,10 +177,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, protected ApplicationConnection client; protected String paintableId; - private boolean immediate; + boolean immediate; private boolean nullSelectionAllowed = true; - private int selectMode = Table.SELECT_MODE_NONE; + private SelectMode selectMode = SelectMode.NONE; private final HashSet selectedRowKeys = new HashSet(); @@ -178,15 +193,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, /* * These are used when jumping between pages when pressing Home and End */ - private boolean selectLastItemInNextRender = false; - private boolean selectFirstItemInNextRender = false; - private boolean focusFirstItemInNextRender = false; - private boolean focusLastItemInNextRender = false; + boolean selectLastItemInNextRender = false; + boolean selectFirstItemInNextRender = false; + boolean focusFirstItemInNextRender = false; + boolean focusLastItemInNextRender = false; /* * The currently focused row */ - private VScrollTableRow focusedRow; + VScrollTableRow focusedRow; /* * Helper to store selection range start in when using the keyboard @@ -197,7 +212,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * Flag for notifying when the selection has changed and should be sent to * the server */ - private boolean selectionChanged = false; + boolean selectionChanged = false; /* * The speed (in pixels) which the scrolling scrolls vertically/horizontally @@ -206,7 +221,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private Timer scrollingVelocityTimer = null; - private String[] bodyActionKeys; + String[] bodyActionKeys; private boolean enableDebug = false; @@ -282,19 +297,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private final HashSet selectedRowRanges = new HashSet(); - private boolean initializedAndAttached = false; + boolean initializedAndAttached = false; /** * Flag to indicate if a column width recalculation is needed due update. */ - private boolean headerChangedDuringUpdate = false; + boolean headerChangedDuringUpdate = false; protected final TableHead tHead = new TableHead(); - private final TableFooter tFoot = new TableFooter(); + final TableFooter tFoot = new TableFooter(); - private final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel( - true); + final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true); private KeyPressHandler navKeyPressHandler = new KeyPressHandler() { public void onKeyPress(KeyPressEvent keyPressEvent) { @@ -383,12 +397,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } }; - private int totalRows; + int totalRows; private Set collapsedColumns; - private final RowRequestHandler rowRequestHandler; - private VScrollTableBody scrollBody; + final RowRequestHandler rowRequestHandler; + VScrollTableBody scrollBody; private int firstvisible = 0; private boolean sortAscending; private String sortColumn; @@ -403,9 +417,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private String[] visibleColOrder; private boolean initialContentReceived = false; private Element scrollPositionElement; - private boolean enabled; - private boolean showColHeaders; - private boolean showColFooters; + boolean enabled; + boolean showColHeaders; + boolean showColFooters; /** flag to indicate that table body has changed */ private boolean isNewBody = true; @@ -420,15 +434,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private final ArrayList lazyUnregistryBag = new ArrayList(); private String height; private String width = ""; - private boolean rendering = false; + boolean rendering = false; private boolean hasFocus = false; private int dragmode; private int multiselectmode; - private int tabIndex; + int tabIndex; private TouchScrollDelegate touchScrollDelegate; - private int lastRenderedHeight; + int lastRenderedHeight; /** * Values (serverCacheFirst+serverCacheLast) sent by server that tells which @@ -442,8 +456,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * scrolling in the client will cause empty buttons to be rendered * (cached=true request for non-existing components) */ - private int serverCacheFirst = -1; - private int serverCacheLast = -1; + int serverCacheFirst = -1; + int serverCacheLast = -1; public VScrollTable() { setMultiSelectMode(MULTISELECT_MODE_DEFAULT); @@ -810,211 +824,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return KeyCodes.KEY_END; } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal - * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - - if (uidl.hasAttribute(ATTRIBUTE_PAGEBUFFER_FIRST)) { - serverCacheFirst = uidl.getIntAttribute(ATTRIBUTE_PAGEBUFFER_FIRST); - serverCacheLast = uidl.getIntAttribute(ATTRIBUTE_PAGEBUFFER_LAST); - } else { - serverCacheFirst = -1; - serverCacheLast = -1; - } - /* - * We need to do this before updateComponent since updateComponent calls - * this.setHeight() which will calculate a new body height depending on - * the space available. - */ - if (uidl.hasAttribute("colfooters")) { - showColFooters = uidl.getBooleanAttribute("colfooters"); - } - - tFoot.setVisible(showColFooters); - - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - - enabled = !uidl.hasAttribute("disabled"); - - if (BrowserInfo.get().isIE8() && !enabled) { - /* - * The disabled shim will not cover the table body if it is relative - * in IE8. See #7324 - */ - scrollBodyPanel.getElement().getStyle() - .setPosition(Position.STATIC); - } else if (BrowserInfo.get().isIE8()) { - scrollBodyPanel.getElement().getStyle() - .setPosition(Position.RELATIVE); - } - - this.client = client; - paintableId = uidl.getStringAttribute("id"); - immediate = uidl.getBooleanAttribute("immediate"); - - int previousTotalRows = totalRows; - updateTotalRows(uidl); - boolean totalRowsChanged = (totalRows != previousTotalRows); - - updateDragMode(uidl); - - updateSelectionProperties(uidl); - - if (uidl.hasAttribute("alb")) { - bodyActionKeys = uidl.getStringArrayAttribute("alb"); - } else { - // Need to clear the actions if the action handlers have been - // removed - bodyActionKeys = null; - } - - setCacheRateFromUIDL(uidl); - - recalcWidths = uidl.hasAttribute("recalcWidths"); - if (recalcWidths) { - tHead.clear(); - tFoot.clear(); - } - - updatePageLength(uidl); - - updateFirstVisibleAndScrollIfNeeded(uidl); - - showRowHeaders = uidl.getBooleanAttribute("rowheaders"); - showColHeaders = uidl.getBooleanAttribute("colheaders"); - - updateSortingProperties(uidl); - - boolean keyboardSelectionOverRowFetchInProgress = selectSelectedRows(uidl); - - updateActionMap(uidl); - - updateColumnProperties(uidl); - - UIDL ac = uidl.getChildByTagName("-ac"); - if (ac == null) { - if (dropHandler != null) { - // remove dropHandler if not present anymore - dropHandler = null; - } - } else { - if (dropHandler == null) { - dropHandler = new VScrollTableDropHandler(); - } - dropHandler.updateAcceptRules(ac); - } - - UIDL partialRowAdditions = uidl.getChildByTagName("prows"); - UIDL partialRowUpdates = uidl.getChildByTagName("urows"); - if (partialRowUpdates != null || partialRowAdditions != null) { - // we may have pending cache row fetch, cancel it. See #2136 - rowRequestHandler.cancel(); - - updateRowsInBody(partialRowUpdates); - addAndRemoveRows(partialRowAdditions); - } else { - UIDL rowData = uidl.getChildByTagName("rows"); - if (rowData != null) { - // we may have pending cache row fetch, cancel it. See #2136 - rowRequestHandler.cancel(); - - if (!recalcWidths && initializedAndAttached) { - updateBody(rowData, uidl.getIntAttribute("firstrow"), - uidl.getIntAttribute("rows")); - if (headerChangedDuringUpdate) { - triggerLazyColumnAdjustment(true); - } else if (!isScrollPositionVisible() - || totalRowsChanged - || lastRenderedHeight != scrollBody - .getOffsetHeight()) { - // webkits may still bug with their disturbing scrollbar - // bug, see #3457 - // Run overflow fix for the scrollable area - // #6698 - If there's a scroll going on, don't abort it - // by changing overflows as the length of the contents - // *shouldn't* have changed (unless the number of rows - // or the height of the widget has also changed) - Scheduler.get().scheduleDeferred(new Command() { - public void execute() { - Util.runWebkitOverflowAutoFix(scrollBodyPanel - .getElement()); - } - }); - } - } else { - initializeRows(uidl, rowData); - } - } - } - - if (!isSelectable()) { - scrollBody.addStyleName(CLASSNAME + "-body-noselection"); - } else { - scrollBody.removeStyleName(CLASSNAME + "-body-noselection"); - } - - hideScrollPositionAnnotation(); - purgeUnregistryBag(); - - // selection is no in sync with server, avoid excessive server visits by - // clearing to flag used during the normal operation - if (!keyboardSelectionOverRowFetchInProgress) { - selectionChanged = false; - } - - /* - * This is called when the Home or page up button has been pressed in - * selectable mode and the next selected row was not yet rendered in the - * client - */ - if (selectFirstItemInNextRender || focusFirstItemInNextRender) { - selectFirstRenderedRowInViewPort(focusFirstItemInNextRender); - selectFirstItemInNextRender = focusFirstItemInNextRender = false; - } - - /* - * This is called when the page down or end button has been pressed in - * selectable mode and the next selected row was not yet rendered in the - * client - */ - if (selectLastItemInNextRender || focusLastItemInNextRender) { - selectLastRenderedRowInViewPort(focusLastItemInNextRender); - selectLastItemInNextRender = focusLastItemInNextRender = false; - } - multiselectPending = false; - - if (focusedRow != null) { - if (!focusedRow.isAttached() && !rowRequestHandler.isRunning()) { - // focused row has been orphaned, can't focus - focusRowFromBody(); - } - } - - tabIndex = uidl.hasAttribute("tabindex") ? uidl - .getIntAttribute("tabindex") : 0; - setProperTabIndex(); - - resizeSortedColumnForSortIndicator(); - - // Remember this to detect situations where overflow hack might be - // needed during scrolling - lastRenderedHeight = scrollBody.getOffsetHeight(); - - rendering = false; - headerChangedDuringUpdate = false; - - } - - private void initializeRows(UIDL uidl, UIDL rowData) { + void initializeRows(UIDL uidl, UIDL rowData) { if (scrollBody != null) { scrollBody.removeFromParent(); lazyUnregistryBag.add(scrollBody); @@ -1037,7 +847,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, scrollBody.restoreRowVisibility(); } - private void updateColumnProperties(UIDL uidl) { + void updateColumnProperties(UIDL uidl) { updateColumnOrder(uidl); updateCollapsedColumns(uidl); @@ -1072,7 +882,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private boolean selectSelectedRows(UIDL uidl) { + boolean selectSelectedRows(UIDL uidl) { boolean keyboardSelectionOverRowFetchInProgress = false; if (uidl.hasVariable("selected")) { @@ -1109,7 +919,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return keyboardSelectionOverRowFetchInProgress; } - private void updateSortingProperties(UIDL uidl) { + void updateSortingProperties(UIDL uidl) { oldSortColumn = sortColumn; if (uidl.hasVariable("sortascending")) { sortAscending = uidl.getBooleanVariable("sortascending"); @@ -1117,7 +927,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private void resizeSortedColumnForSortIndicator() { + void resizeSortedColumnForSortIndicator() { // Force recalculation of the captionContainer element inside the header // cell to accomodate for the size of the sort arrow. HeaderCell sortedHeader = tHead.getHeaderCell(sortColumn); @@ -1132,7 +942,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) { + void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) { firstvisible = uidl.hasVariable("firstvisible") ? uidl .getIntVariable("firstvisible") : 0; if (firstvisible != lastRequestedFirstvisible && scrollBody != null) { @@ -1147,7 +957,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return (int) (rowIx * scrollBody.getRowHeight()); } - private void updatePageLength(UIDL uidl) { + void updatePageLength(UIDL uidl) { int oldPageLength = pageLength; if (uidl.hasAttribute("pagelength")) { pageLength = uidl.getIntAttribute("pagelength"); @@ -1162,7 +972,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private void updateSelectionProperties(UIDL uidl) { + void updateSelectionProperties(UIDL uidl) { setMultiSelectMode(uidl.hasAttribute("multiselectmode") ? uidl .getIntAttribute("multiselectmode") : MULTISELECT_MODE_DEFAULT); @@ -1171,18 +981,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, if (uidl.hasAttribute("selectmode")) { if (uidl.getBooleanAttribute("readonly")) { - selectMode = Table.SELECT_MODE_NONE; + selectMode = SelectMode.NONE; } else if (uidl.getStringAttribute("selectmode").equals("multi")) { - selectMode = Table.SELECT_MODE_MULTI; + selectMode = SelectMode.MULTI; } else if (uidl.getStringAttribute("selectmode").equals("single")) { - selectMode = Table.SELECT_MODE_SINGLE; + selectMode = SelectMode.SINGLE; } else { - selectMode = Table.SELECT_MODE_NONE; + selectMode = SelectMode.NONE; } } } - private void updateDragMode(UIDL uidl) { + void updateDragMode(UIDL uidl) { dragmode = uidl.hasAttribute("dragmode") ? uidl .getIntAttribute("dragmode") : 0; if (BrowserInfo.get().isIE()) { @@ -1219,7 +1029,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return totalRows; } - private void focusRowFromBody() { + void focusRowFromBody() { if (selectedRowKeys.size() == 1) { // try to focus a row currently selected and in viewport String selectedRowKey = selectedRowKeys.iterator().next(); @@ -1247,7 +1057,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * @param focusOnly * Should the focus only be moved to the last row */ - private void selectLastRenderedRowInViewPort(boolean focusOnly) { + void selectLastRenderedRowInViewPort(boolean focusOnly) { int index = firstRowInViewPort + getFullyVisibleRowCount(); VScrollTableRow lastRowInViewport = scrollBody.getRowByRowIndex(index); if (lastRowInViewport == null) { @@ -1272,7 +1082,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * @param focusOnly * Should the focus only be moved to the first row */ - private void selectFirstRenderedRowInViewPort(boolean focusOnly) { + void selectFirstRenderedRowInViewPort(boolean focusOnly) { int index = firstRowInViewPort; VScrollTableRow firstInViewport = scrollBody.getRowByRowIndex(index); if (firstInViewport == null) { @@ -1286,7 +1096,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private void setCacheRateFromUIDL(UIDL uidl) { + void setCacheRateFromUIDL(UIDL uidl) { setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr") : CACHE_RATE_DEFAULT); } @@ -1303,7 +1113,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * IScrollTableRows). This is done lazily as Table must survive from * "subtreecaching" logic. */ - private void purgeUnregistryBag() { + void purgeUnregistryBag() { for (Iterator iterator = lazyUnregistryBag.iterator(); iterator .hasNext();) { VPaintableMap.get(client) @@ -1312,7 +1122,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, lazyUnregistryBag.clear(); } - private void updateActionMap(UIDL mainUidl) { + void updateActionMap(UIDL mainUidl) { UIDL actionsUidl = mainUidl.getChildByTagName("actions"); if (actionsUidl == null) { return; @@ -1414,7 +1224,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * @param reqRows * amount of rows in data set */ - private void updateBody(UIDL uidl, int firstRow, int reqRows) { + void updateBody(UIDL uidl, int firstRow, int reqRows) { if (uidl == null || reqRows < 1) { // container is empty, remove possibly existing rows if (firstRow <= 0) { @@ -1431,7 +1241,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, discardRowsOutsideCacheWindow(); } - private void updateRowsInBody(UIDL partialRowUpdates) { + void updateRowsInBody(UIDL partialRowUpdates) { if (partialRowUpdates == null) { return; } @@ -1564,20 +1374,20 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } private boolean isMultiSelectModeSimple() { - return selectMode == Table.SELECT_MODE_MULTI + return selectMode == SelectMode.MULTI && multiselectmode == MULTISELECT_MODE_SIMPLE; } private boolean isSingleSelectMode() { - return selectMode == Table.SELECT_MODE_SINGLE; + return selectMode == SelectMode.SINGLE; } private boolean isMultiSelectModeAny() { - return selectMode == Table.SELECT_MODE_MULTI; + return selectMode == SelectMode.MULTI; } private boolean isMultiSelectModeDefault() { - return selectMode == Table.SELECT_MODE_MULTI + return selectMode == SelectMode.MULTI && multiselectmode == MULTISELECT_MODE_DEFAULT; } @@ -1593,7 +1403,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } protected boolean isSelectable() { - return selectMode > Table.SELECT_MODE_NONE; + return selectMode.getId() > SelectMode.NONE.getId(); } private boolean isCollapsedColumn(String colKey) { @@ -1769,7 +1579,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } client.updateVariable(paintableId, "columnorder", columnOrder, false); - if (client.hasEventListeners(this, COLUMN_REORDER_EVENT_ID)) { + if (client.hasWidgetEventListeners(this, COLUMN_REORDER_EVENT_ID)) { client.sendPendingVariableChanges(); } } @@ -2108,19 +1918,19 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, style.setDisplay(Display.BLOCK); } - private void hideScrollPositionAnnotation() { + void hideScrollPositionAnnotation() { if (scrollPositionElement != null) { DOM.setStyleAttribute(scrollPositionElement, "display", "none"); } } - private boolean isScrollPositionVisible() { + boolean isScrollPositionVisible() { return scrollPositionElement != null && !scrollPositionElement.getStyle().getDisplay() .equals(Display.NONE.toString()); } - private class RowRequestHandler extends Timer { + class RowRequestHandler extends Timer { private int reqFirstRow = 0; private int reqRows = 0; @@ -2512,7 +2322,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * The click event */ private void fireHeaderClickedEvent(Event event) { - if (client.hasEventListeners(VScrollTable.this, + if (client.hasWidgetEventListeners(VScrollTable.this, HEADER_CLICK_EVENT_ID)) { MouseEventDetails details = new MouseEventDetails(event); client.updateVariable(paintableId, "headerClickEvent", @@ -3543,7 +3353,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * The click event */ private void fireFooterClickedEvent(Event event) { - if (client.hasEventListeners(VScrollTable.this, + if (client.hasWidgetEventListeners(VScrollTable.this, FOOTER_CLICK_EVENT_ID)) { MouseEventDetails details = new MouseEventDetails(event); client.updateVariable(paintableId, "footerClickEvent", @@ -4295,12 +4105,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows .get(index); // Unregister row tooltip - client.registerTooltip(VScrollTable.this, toBeRemoved.getElement(), - null); + client.registerWidgetTooltip(VScrollTable.this, + toBeRemoved.getElement(), null); for (int i = 0; i < toBeRemoved.getElement().getChildCount(); i++) { // Unregister cell tooltips Element td = toBeRemoved.getElement().getChild(i).cast(); - client.registerTooltip(VScrollTable.this, td, null); + client.registerWidgetTooltip(VScrollTable.this, td, null); } lazyUnregistryBag.add(toBeRemoved); tBodyElement.removeChild(toBeRemoved.getElement()); @@ -4559,10 +4369,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, String rowDescription = uidl.getStringAttribute("rowdescr"); if (rowDescription != null && !rowDescription.equals("")) { TooltipInfo info = new TooltipInfo(rowDescription); - client.registerTooltip(VScrollTable.this, rowElement, info); + client.registerWidgetTooltip(VScrollTable.this, rowElement, + info); } else { // Remove possibly previously set tooltip - client.registerTooltip(VScrollTable.this, rowElement, null); + client.registerWidgetTooltip(VScrollTable.this, rowElement, + null); } tHead.getColumnAlignments(); @@ -4797,10 +4609,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, if (description != null && !description.equals("")) { TooltipInfo info = new TooltipInfo(description); - client.registerTooltip(VScrollTable.this, td, info); + client.registerWidgetTooltip(VScrollTable.this, td, info); } else { // Remove possibly previously set tooltip - client.registerTooltip(VScrollTable.this, td, null); + client.registerWidgetTooltip(VScrollTable.this, td, null); } td.appendChild(container); @@ -4879,7 +4691,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, */ private boolean handleClickEvent(Event event, Element targetTdOrTr, boolean immediate) { - if (!client.hasEventListeners(VScrollTable.this, + if (!client.hasWidgetEventListeners(VScrollTable.this, ITEM_CLICK_EVENT_ID)) { // Don't send an event if nobody is listening return false; @@ -4923,22 +4735,24 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, if (!containsWidget) { // Only text nodes has tooltips - if (client.getTooltipTitleInfo(VScrollTable.this, - target) != null) { + if (VPaintableMap.get(client).getWidgetTooltipInfo( + VScrollTable.this, target) != null) { // Cell has description, use it - client.handleTooltipEvent(event, VScrollTable.this, - target); + client.handleWidgetTooltipEvent(event, + VScrollTable.this, target); } else { // Cell might have row description, use row // description - client.handleTooltipEvent(event, VScrollTable.this, + client.handleWidgetTooltipEvent(event, + VScrollTable.this, target.getParentElement()); } } } else { // Table row (tr) - client.handleTooltipEvent(event, VScrollTable.this, target); + client.handleWidgetTooltipEvent(event, VScrollTable.this, + target); } } @@ -4954,7 +4768,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, showContextMenu(event); if (enabled && (actionKeys != null || client - .hasEventListeners(VScrollTable.this, + .hasWidgetEventListeners( + VScrollTable.this, ITEM_CLICK_EVENT_ID))) { /* * Prevent browser context menu only if there are @@ -5243,7 +5058,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, Element targetTdOrTr) { mDown = true; VTransferable transferable = new VTransferable(); - transferable.setDragSource(VScrollTable.this); + transferable.setDragSource(VPaintableMap.get(client) + .getPaintable(VScrollTable.this)); transferable.setData("itemId", "" + rowKey); NodeList cells = rowElement.getCells(); for (int i = 0; i < cells.getLength(); i++) { @@ -5972,9 +5788,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private int contentAreaBorderHeight = -1; private int scrollLeft; private int scrollTop; - private VScrollTableDropHandler dropHandler; + VScrollTableDropHandler dropHandler; private boolean navKeyDown; - private boolean multiselectPending; + boolean multiselectPending; /** * @return border top + border bottom of the scrollable area of table @@ -6315,7 +6131,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public VPaintableWidget getPaintable() { - return VScrollTable.this; + return VPaintableMap.get(client).getPaintable(VScrollTable.this); } public ApplicationConnection getApplicationConnection() { @@ -6752,7 +6568,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * actions may need focus. * */ - private void setProperTabIndex() { + void setProperTabIndex() { int storedScrollTop = 0; int storedScrollLeft = 0; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java new file mode 100644 index 0000000000..c747a29a21 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java @@ -0,0 +1,251 @@ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; + +public class VScrollTablePaintable extends VAbstractPaintableWidget { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal + * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + + if (uidl.hasAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST)) { + getWidgetForPaintable().serverCacheFirst = uidl + .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST); + getWidgetForPaintable().serverCacheLast = uidl + .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST); + } else { + getWidgetForPaintable().serverCacheFirst = -1; + getWidgetForPaintable().serverCacheLast = -1; + } + /* + * We need to do this before updateComponent since updateComponent calls + * this.setHeight() which will calculate a new body height depending on + * the space available. + */ + if (uidl.hasAttribute("colfooters")) { + getWidgetForPaintable().showColFooters = uidl + .getBooleanAttribute("colfooters"); + } + + getWidgetForPaintable().tFoot + .setVisible(getWidgetForPaintable().showColFooters); + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + + getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled"); + + if (BrowserInfo.get().isIE8() && !getWidgetForPaintable().enabled) { + /* + * The disabled shim will not cover the table body if it is relative + * in IE8. See #7324 + */ + getWidgetForPaintable().scrollBodyPanel.getElement().getStyle() + .setPosition(Position.STATIC); + } else if (BrowserInfo.get().isIE8()) { + getWidgetForPaintable().scrollBodyPanel.getElement().getStyle() + .setPosition(Position.RELATIVE); + } + + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getStringAttribute("id"); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + + int previousTotalRows = getWidgetForPaintable().totalRows; + getWidgetForPaintable().updateTotalRows(uidl); + boolean totalRowsChanged = (getWidgetForPaintable().totalRows != previousTotalRows); + + getWidgetForPaintable().updateDragMode(uidl); + + getWidgetForPaintable().updateSelectionProperties(uidl); + + if (uidl.hasAttribute("alb")) { + getWidgetForPaintable().bodyActionKeys = uidl + .getStringArrayAttribute("alb"); + } else { + // Need to clear the actions if the action handlers have been + // removed + getWidgetForPaintable().bodyActionKeys = null; + } + + getWidgetForPaintable().setCacheRateFromUIDL(uidl); + + getWidgetForPaintable().recalcWidths = uidl + .hasAttribute("recalcWidths"); + if (getWidgetForPaintable().recalcWidths) { + getWidgetForPaintable().tHead.clear(); + getWidgetForPaintable().tFoot.clear(); + } + + getWidgetForPaintable().updatePageLength(uidl); + + getWidgetForPaintable().updateFirstVisibleAndScrollIfNeeded(uidl); + + getWidgetForPaintable().showRowHeaders = uidl + .getBooleanAttribute("rowheaders"); + getWidgetForPaintable().showColHeaders = uidl + .getBooleanAttribute("colheaders"); + + getWidgetForPaintable().updateSortingProperties(uidl); + + boolean keyboardSelectionOverRowFetchInProgress = getWidgetForPaintable() + .selectSelectedRows(uidl); + + getWidgetForPaintable().updateActionMap(uidl); + + getWidgetForPaintable().updateColumnProperties(uidl); + + UIDL ac = uidl.getChildByTagName("-ac"); + if (ac == null) { + if (getWidgetForPaintable().dropHandler != null) { + // remove dropHandler if not present anymore + getWidgetForPaintable().dropHandler = null; + } + } else { + if (getWidgetForPaintable().dropHandler == null) { + getWidgetForPaintable().dropHandler = getWidgetForPaintable().new VScrollTableDropHandler(); + } + getWidgetForPaintable().dropHandler.updateAcceptRules(ac); + } + + UIDL partialRowAdditions = uidl.getChildByTagName("prows"); + UIDL partialRowUpdates = uidl.getChildByTagName("urows"); + if (partialRowUpdates != null || partialRowAdditions != null) { + // we may have pending cache row fetch, cancel it. See #2136 + getWidgetForPaintable().rowRequestHandler.cancel(); + + getWidgetForPaintable().updateRowsInBody(partialRowUpdates); + getWidgetForPaintable().addAndRemoveRows(partialRowAdditions); + } else { + UIDL rowData = uidl.getChildByTagName("rows"); + if (rowData != null) { + // we may have pending cache row fetch, cancel it. See #2136 + getWidgetForPaintable().rowRequestHandler.cancel(); + + if (!getWidgetForPaintable().recalcWidths + && getWidgetForPaintable().initializedAndAttached) { + getWidgetForPaintable().updateBody(rowData, + uidl.getIntAttribute("firstrow"), + uidl.getIntAttribute("rows")); + if (getWidgetForPaintable().headerChangedDuringUpdate) { + getWidgetForPaintable().triggerLazyColumnAdjustment( + true); + } else if (!getWidgetForPaintable() + .isScrollPositionVisible() + || totalRowsChanged + || getWidgetForPaintable().lastRenderedHeight != getWidgetForPaintable().scrollBody + .getOffsetHeight()) { + // webkits may still bug with their disturbing scrollbar + // bug, see #3457 + // Run overflow fix for the scrollable area + // #6698 - If there's a scroll going on, don't abort it + // by changing overflows as the length of the contents + // *shouldn't* have changed (unless the number of rows + // or the height of the widget has also changed) + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + Util.runWebkitOverflowAutoFix(getWidgetForPaintable().scrollBodyPanel + .getElement()); + } + }); + } + } else { + getWidgetForPaintable().initializeRows(uidl, rowData); + } + } + } + + if (!getWidgetForPaintable().isSelectable()) { + getWidgetForPaintable().scrollBody + .addStyleName(VScrollTable.CLASSNAME + "-body-noselection"); + } else { + getWidgetForPaintable().scrollBody + .removeStyleName(VScrollTable.CLASSNAME + + "-body-noselection"); + } + + getWidgetForPaintable().hideScrollPositionAnnotation(); + getWidgetForPaintable().purgeUnregistryBag(); + + // selection is no in sync with server, avoid excessive server visits by + // clearing to flag used during the normal operation + if (!keyboardSelectionOverRowFetchInProgress) { + getWidgetForPaintable().selectionChanged = false; + } + + /* + * This is called when the Home or page up button has been pressed in + * selectable mode and the next selected row was not yet rendered in the + * client + */ + if (getWidgetForPaintable().selectFirstItemInNextRender + || getWidgetForPaintable().focusFirstItemInNextRender) { + getWidgetForPaintable().selectFirstRenderedRowInViewPort( + getWidgetForPaintable().focusFirstItemInNextRender); + getWidgetForPaintable().selectFirstItemInNextRender = getWidgetForPaintable().focusFirstItemInNextRender = false; + } + + /* + * This is called when the page down or end button has been pressed in + * selectable mode and the next selected row was not yet rendered in the + * client + */ + if (getWidgetForPaintable().selectLastItemInNextRender + || getWidgetForPaintable().focusLastItemInNextRender) { + getWidgetForPaintable().selectLastRenderedRowInViewPort( + getWidgetForPaintable().focusLastItemInNextRender); + getWidgetForPaintable().selectLastItemInNextRender = getWidgetForPaintable().focusLastItemInNextRender = false; + } + getWidgetForPaintable().multiselectPending = false; + + if (getWidgetForPaintable().focusedRow != null) { + if (!getWidgetForPaintable().focusedRow.isAttached() + && !getWidgetForPaintable().rowRequestHandler.isRunning()) { + // focused row has been orphaned, can't focus + getWidgetForPaintable().focusRowFromBody(); + } + } + + getWidgetForPaintable().tabIndex = uidl.hasAttribute("tabindex") ? uidl + .getIntAttribute("tabindex") : 0; + getWidgetForPaintable().setProperTabIndex(); + + getWidgetForPaintable().resizeSortedColumnForSortIndicator(); + + // Remember this to detect situations where overflow hack might be + // needed during scrolling + getWidgetForPaintable().lastRenderedHeight = getWidgetForPaintable().scrollBody + .getOffsetHeight(); + + getWidgetForPaintable().rendering = false; + getWidgetForPaintable().headerChangedDuringUpdate = false; + + } + + @Override + protected Widget createWidget() { + return GWT.create(VScrollTable.class); + } + + @Override + public VScrollTable getWidgetForPaintable() { + return (VScrollTable) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java index 77dd1cc39e..0eddca0ed3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java @@ -24,21 +24,19 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComputedStyle; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow; import com.vaadin.terminal.gwt.client.ui.VTreeTable.VTreeTableScrollBody.VTreeTableRow; public class VTreeTable extends VScrollTable { - private static class PendingNavigationEvent { - private final int keycode; - private final boolean ctrl; - private final boolean shift; + static class PendingNavigationEvent { + final int keycode; + final boolean ctrl; + final boolean shift; public PendingNavigationEvent(int keycode, boolean ctrl, boolean shift) { this.keycode = keycode; @@ -59,82 +57,14 @@ public class VTreeTable extends VScrollTable { } } - public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci"; - private boolean collapseRequest; + boolean collapseRequest; private boolean selectionPending; - private int colIndexOfHierarchy; - private String collapsedRowKey; - private VTreeTableScrollBody scrollBody; - private boolean animationsEnabled; - private LinkedList pendingNavigationEvents = new LinkedList(); - private boolean focusParentResponsePending; - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - FocusableScrollPanel widget = null; - int scrollPosition = 0; - if (collapseRequest) { - widget = (FocusableScrollPanel) getWidget(1); - scrollPosition = widget.getScrollPosition(); - } - animationsEnabled = uidl.getBooleanAttribute("animate"); - colIndexOfHierarchy = uidl - .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl - .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0; - int oldTotalRows = getTotalRows(); - super.updateFromUIDL(uidl, client); - if (collapseRequest) { - if (collapsedRowKey != null && scrollBody != null) { - VScrollTableRow row = getRenderedRowByKey(collapsedRowKey); - if (row != null) { - setRowFocus(row); - focus(); - } - } - - int scrollPosition2 = widget.getScrollPosition(); - if (scrollPosition != scrollPosition2) { - widget.setScrollPosition(scrollPosition); - } - - // check which rows are needed from the server and initiate a - // deferred fetch - onScroll(null); - } - // Recalculate table size if collapse request, or if page length is zero - // (not sent by server) and row count changes (#7908). - if (collapseRequest - || (!uidl.hasAttribute("pagelength") && getTotalRows() != oldTotalRows)) { - /* - * Ensure that possibly removed/added scrollbars are considered. - * Triggers row calculations, removes cached rows etc. Basically - * cleans up state. Be careful if touching this, you will break - * pageLength=0 if you remove this. - */ - triggerLazyColumnAdjustment(true); - - collapseRequest = false; - } - if (uidl.hasAttribute("focusedRow")) { - String key = uidl.getStringAttribute("focusedRow"); - setRowFocus(getRenderedRowByKey(key)); - focusParentResponsePending = false; - } else if (uidl.hasAttribute("clearFocusPending")) { - // Special case to detect a response to a focusParent request that - // does not return any focusedRow because the selected node has no - // parent - focusParentResponsePending = false; - } - - while (!collapseRequest && !focusParentResponsePending - && !pendingNavigationEvents.isEmpty()) { - // Keep replaying any queued events as long as we don't have any - // potential content changes pending - PendingNavigationEvent event = pendingNavigationEvents - .removeFirst(); - handleNavigation(event.keycode, event.ctrl, event.shift); - } - } + int colIndexOfHierarchy; + String collapsedRowKey; + VTreeTableScrollBody scrollBody; + boolean animationsEnabled; + LinkedList pendingNavigationEvents = new LinkedList(); + boolean focusParentResponsePending; @Override protected VScrollTableBody createScrollBody() { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java new file mode 100644 index 0000000000..8fec0558ec --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java @@ -0,0 +1,98 @@ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow; +import com.vaadin.terminal.gwt.client.ui.VTreeTable.PendingNavigationEvent; + +public class VTreeTablePaintable extends VScrollTablePaintable { + public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci"; + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + FocusableScrollPanel widget = null; + int scrollPosition = 0; + if (getWidgetForPaintable().collapseRequest) { + widget = (FocusableScrollPanel) getWidgetForPaintable() + .getWidget(1); + scrollPosition = widget.getScrollPosition(); + } + getWidgetForPaintable().animationsEnabled = uidl + .getBooleanAttribute("animate"); + getWidgetForPaintable().colIndexOfHierarchy = uidl + .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl + .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0; + int oldTotalRows = getWidgetForPaintable().getTotalRows(); + super.updateFromUIDL(uidl, client); + if (getWidgetForPaintable().collapseRequest) { + if (getWidgetForPaintable().collapsedRowKey != null + && getWidgetForPaintable().scrollBody != null) { + VScrollTableRow row = getWidgetForPaintable() + .getRenderedRowByKey( + getWidgetForPaintable().collapsedRowKey); + if (row != null) { + getWidgetForPaintable().setRowFocus(row); + getWidgetForPaintable().focus(); + } + } + + int scrollPosition2 = widget.getScrollPosition(); + if (scrollPosition != scrollPosition2) { + widget.setScrollPosition(scrollPosition); + } + + // check which rows are needed from the server and initiate a + // deferred fetch + getWidgetForPaintable().onScroll(null); + } + // Recalculate table size if collapse request, or if page length is zero + // (not sent by server) and row count changes (#7908). + if (getWidgetForPaintable().collapseRequest + || (!uidl.hasAttribute("pagelength") && getWidgetForPaintable() + .getTotalRows() != oldTotalRows)) { + /* + * Ensure that possibly removed/added scrollbars are considered. + * Triggers row calculations, removes cached rows etc. Basically + * cleans up state. Be careful if touching this, you will break + * pageLength=0 if you remove this. + */ + getWidgetForPaintable().triggerLazyColumnAdjustment(true); + + getWidgetForPaintable().collapseRequest = false; + } + if (uidl.hasAttribute("focusedRow")) { + String key = uidl.getStringAttribute("focusedRow"); + getWidgetForPaintable().setRowFocus( + getWidgetForPaintable().getRenderedRowByKey(key)); + getWidgetForPaintable().focusParentResponsePending = false; + } else if (uidl.hasAttribute("clearFocusPending")) { + // Special case to detect a response to a focusParent request that + // does not return any focusedRow because the selected node has no + // parent + getWidgetForPaintable().focusParentResponsePending = false; + } + + while (!getWidgetForPaintable().collapseRequest + && !getWidgetForPaintable().focusParentResponsePending + && !getWidgetForPaintable().pendingNavigationEvents.isEmpty()) { + // Keep replaying any queued events as long as we don't have any + // potential content changes pending + PendingNavigationEvent event = getWidgetForPaintable().pendingNavigationEvents + .removeFirst(); + getWidgetForPaintable().handleNavigation(event.keycode, event.ctrl, + event.shift); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VTreeTable.class); + } + + @Override + public VTreeTable getWidgetForPaintable() { + return (VTreeTable) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java index 3d49b8d9d1..66894417f3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java @@ -24,9 +24,9 @@ import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VConsole; +import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; /** diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java index 09f435227d..8828582b57 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java @@ -34,15 +34,10 @@ public class VLabel extends HTML { public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (event.getTypeInt() == Event.ONLOAD) { - // FIXME: Should not be here but in paintable Util.notifyParentOfSizeChange(this, true); - event.cancelBubble(true); + event.stopPropagation(); return; } - // FIXME: Move to paintable - // if (client != null) { - // client.handleTooltipEvent(event, this); - // } } @Override diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java index 796bce265e..269afde25d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java @@ -6,27 +6,21 @@ package com.vaadin.terminal.gwt.client.ui.label; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.PreElement; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VPaintableWidget; - -public class VLabelPaintable implements VPaintableWidget { - - private VLabel widget = GWT.create(VLabel.class); - private ApplicationConnection client; +import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; +public class VLabelPaintable extends VAbstractPaintableWidget { public VLabelPaintable() { } public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (client.updateComponent(getWidgetForPaintable(), uidl, true)) { + if (client.updateComponent(this, uidl, true)) { return; } - this.client = client; - boolean sinkOnloads = false; final String mode = uidl.getStringAttribute("mode"); @@ -64,8 +58,14 @@ public class VLabelPaintable implements VPaintableWidget { } } + @Override + protected Widget createWidget() { + return GWT.create(VLabel.class); + } + + @Override public VLabel getWidgetForPaintable() { - return widget; + return (VLabel) super.getWidgetForPaintable(); } } diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java index 7ed432a12b..54a094a4e7 100644 --- a/src/com/vaadin/ui/MenuBar.java +++ b/src/com/vaadin/ui/MenuBar.java @@ -14,6 +14,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; import com.vaadin.terminal.gwt.client.ui.VMenuBar; +import com.vaadin.terminal.gwt.client.ui.VMenuBarPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -24,7 +25,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; *

*/ @SuppressWarnings("serial") -@ClientWidget(value = VMenuBar.class, loadStyle = LoadStyle.LAZY) +@ClientWidget(value = VMenuBarPaintable.class, loadStyle = LoadStyle.LAZY) public class MenuBar extends AbstractComponent { // Items of the top-level menu diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 8b9dc3ef81..ec620ddcd5 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -47,6 +47,7 @@ import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.ui.VScrollTable; +import com.vaadin.terminal.gwt.client.ui.VScrollTablePaintable; import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers; /** @@ -73,7 +74,7 @@ import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers; * @since 3.0 */ @SuppressWarnings({ "deprecation" }) -@ClientWidget(VScrollTable.class) +@ClientWidget(VScrollTablePaintable.class) public class Table extends AbstractSelect implements Action.Container, Container.Ordered, Container.Sortable, ItemClickSource, ItemClickNotifier, DragSource, DropTarget { diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 43bc7a80fe..09417e1e16 100644 --- a/src/com/vaadin/ui/TreeTable.java +++ b/src/com/vaadin/ui/TreeTable.java @@ -22,7 +22,7 @@ import com.vaadin.data.util.HierarchicalContainer; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.VTreeTable; +import com.vaadin.terminal.gwt.client.ui.VTreeTablePaintable; import com.vaadin.ui.Tree.CollapseEvent; import com.vaadin.ui.Tree.CollapseListener; import com.vaadin.ui.Tree.ExpandEvent; @@ -48,7 +48,7 @@ import com.vaadin.ui.treetable.HierarchicalContainerOrderedWrapper; * share UI state in the container. */ @SuppressWarnings({ "serial" }) -@ClientWidget(VTreeTable.class) +@ClientWidget(VTreeTablePaintable.class) public class TreeTable extends Table implements Hierarchical { private static final Logger logger = Logger.getLogger(TreeTable.class @@ -454,7 +454,8 @@ public class TreeTable extends Table implements Hierarchical { Object object = visibleColumns2[i]; if (hierarchyColumnId.equals(object)) { target.addAttribute( - VTreeTable.ATTRIBUTE_HIERARCHY_COLUMN_INDEX, i); + VTreeTablePaintable.ATTRIBUTE_HIERARCHY_COLUMN_INDEX, + i); break; } } -- 2.39.5