aboutsummaryrefslogtreecommitdiffstats
path: root/compatibility-client
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-26 10:56:51 +0300
committerArtur Signell <artur@vaadin.com>2016-08-26 11:40:12 +0300
commit50f294513f929fcd0e6a519283d5a88e09331081 (patch)
treebe0020a78238a9bbd8e32714a9ae78b4d4e2115e /compatibility-client
parentf183804846fa39067a79a199df5c929f94aa3624 (diff)
downloadvaadin-framework-50f294513f929fcd0e6a519283d5a88e09331081.tar.gz
vaadin-framework-50f294513f929fcd0e6a519283d5a88e09331081.zip
Move VOptionGroup and dependants to the compatibility package
Change-Id: I49f272480c1d109f7c8fda16e7a05765f46026c5
Diffstat (limited to 'compatibility-client')
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VListSelect.java192
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VNativeSelect.java155
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroup.java322
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroupBase.java209
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTwinColSelect.java632
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/listselect/ListSelectConnector.java2
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/nativeselect/NativeSelectConnector.java2
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupBaseConnector.java2
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupConnector.java2
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/twincolselect/TwinColSelectConnector.java2
10 files changed, 1515 insertions, 5 deletions
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VListSelect.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VListSelect.java
new file mode 100644
index 0000000000..6264561954
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VListSelect.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.v7.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.user.client.ui.ListBox;
+import com.vaadin.client.UIDL;
+import com.vaadin.shared.util.SharedUtil;
+
+public class VListSelect extends VOptionGroupBase {
+
+ public static final String CLASSNAME = "v-select";
+
+ private static final int VISIBLE_COUNT = 10;
+
+ protected ListBox select;
+
+ private int lastSelectedIndex = -1;
+
+ public VListSelect() {
+ super(new ListBox(true), CLASSNAME);
+ select = getOptionsContainer();
+ select.addChangeHandler(this);
+ select.addClickHandler(this);
+ select.setVisibleItemCount(VISIBLE_COUNT);
+ setStyleName(CLASSNAME);
+
+ updateEnabledState();
+ }
+
+ @Override
+ public void setStyleName(String style) {
+ super.setStyleName(style);
+ updateStyleNames();
+ }
+
+ @Override
+ public void setStylePrimaryName(String style) {
+ super.setStylePrimaryName(style);
+ updateStyleNames();
+ }
+
+ protected void updateStyleNames() {
+ container.setStyleName(getStylePrimaryName());
+ select.setStyleName(getStylePrimaryName() + "-select");
+ }
+
+ protected ListBox getOptionsContainer() {
+ return (ListBox) optionsContainer;
+ }
+
+ @Override
+ public void buildOptions(UIDL uidl) {
+ select.setMultipleSelect(isMultiselect());
+
+ Set<String> previousKeys = new HashSet<String>();
+ for (int i = 0; i < select.getItemCount(); i++) {
+ previousKeys.add(select.getValue(i));
+ }
+
+ int nextIndex = 0;
+ if (!isMultiselect() && isNullSelectionAllowed()
+ && !isNullSelectionItemAvailable()) {
+ // can't unselect last item in singleselect mode
+ updateOrCreateItem("", "null", nextIndex++, previousKeys);
+ select.addItem("", (String) null);
+
+ // Null select item can't be selected programmatically, but will
+ // remain selected if it was selected by the user. There's no
+ // need to deselect when something else is selected since it's only
+ // used in single select mode.
+ }
+ for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
+ final UIDL optionUidl = (UIDL) i.next();
+ updateOrCreateItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"), nextIndex,
+ previousKeys);
+ if (optionUidl.hasAttribute("selected")) {
+ select.setItemSelected(nextIndex, true);
+ lastSelectedIndex = nextIndex;
+ } else {
+ select.setItemSelected(nextIndex, false);
+ }
+ nextIndex++;
+ }
+
+ // Remove any trailing items not in the UIDL
+ while (select.getItemCount() > nextIndex) {
+ select.removeItem(nextIndex);
+ }
+
+ if (getRows() > 0) {
+ select.setVisibleItemCount(getRows());
+ }
+ }
+
+ private void updateOrCreateItem(String caption, String key, int index,
+ Set<String> previousKeys) {
+ if (previousKeys.remove(key)) {
+ while (select.getItemCount() >= index) {
+ String keyAtIndex = select.getValue(index);
+ if (SharedUtil.equals(key, keyAtIndex)) {
+ select.setItemText(index, caption);
+ return;
+ } else {
+ // Assume the item we're looking at has simply been removed
+ // and that the next item will match our key
+ select.removeItem(index);
+ previousKeys.remove(keyAtIndex);
+ }
+ }
+ }
+
+ // We end up here for new items or if we removed all following items
+ // while looking for a match
+ select.insertItem(caption, key, index);
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ final ArrayList<String> selectedItemKeys = new ArrayList<String>();
+ for (int i = 0; i < select.getItemCount(); i++) {
+ if (select.isItemSelected(i)) {
+ selectedItemKeys.add(select.getValue(i));
+ }
+ }
+ return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
+ }
+
+ @Override
+ public void onChange(ChangeEvent event) {
+ final int si = select.getSelectedIndex();
+ if (si == -1 && !isNullSelectionAllowed()) {
+ select.setSelectedIndex(lastSelectedIndex);
+ } else {
+ lastSelectedIndex = si;
+ if (isMultiselect()) {
+ client.updateVariable(paintableId, "selected",
+ getSelectedItems(), isImmediate());
+ } else {
+ client.updateVariable(paintableId, "selected",
+ new String[] { "" + getSelectedItem() }, isImmediate());
+ }
+ }
+ }
+
+ @Override
+ public void setHeight(String height) {
+ select.setHeight(height);
+ super.setHeight(height);
+ }
+
+ @Override
+ public void setWidth(String width) {
+ select.setWidth(width);
+ super.setWidth(width);
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ getOptionsContainer().setTabIndex(tabIndex);
+ }
+
+ @Override
+ protected void updateEnabledState() {
+ select.setEnabled(isEnabled() && !isReadonly());
+ }
+
+ @Override
+ public void focus() {
+ select.setFocus(true);
+ }
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VNativeSelect.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VNativeSelect.java
new file mode 100644
index 0000000000..7f8b268880
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VNativeSelect.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.v7.client.ui;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.user.client.ui.ListBox;
+import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.UIDL;
+import com.vaadin.client.ui.Field;
+
+public class VNativeSelect extends VOptionGroupBase implements Field {
+
+ public static final String CLASSNAME = "v-select";
+
+ protected ListBox select;
+
+ private boolean firstValueIsTemporaryNullItem = false;
+
+ public VNativeSelect() {
+ super(new ListBox(false), CLASSNAME);
+ select = getOptionsContainer();
+ select.setVisibleItemCount(1);
+ select.addChangeHandler(this);
+ select.setStyleName(CLASSNAME + "-select");
+
+ updateEnabledState();
+ }
+
+ protected ListBox getOptionsContainer() {
+ return (ListBox) optionsContainer;
+ }
+
+ @Override
+ public void buildOptions(UIDL uidl) {
+ select.clear();
+ firstValueIsTemporaryNullItem = false;
+
+ if (isNullSelectionAllowed() && !isNullSelectionItemAvailable()) {
+ // can't unselect last item in singleselect mode
+ select.addItem("", (String) null);
+ }
+ boolean selected = false;
+ for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
+ final UIDL optionUidl = (UIDL) i.next();
+ select.addItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"));
+ if (optionUidl.hasAttribute("selected")) {
+ select.setItemSelected(select.getItemCount() - 1, true);
+ selected = true;
+ }
+ }
+ if (!selected && !isNullSelectionAllowed()) {
+ // null-select not allowed, but value not selected yet; add null and
+ // remove when something is selected
+ select.insertItem("", (String) null, 0);
+ select.setItemSelected(0, true);
+ firstValueIsTemporaryNullItem = true;
+ }
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ final ArrayList<String> selectedItemKeys = new ArrayList<String>();
+ for (int i = 0; i < select.getItemCount(); i++) {
+ if (select.isItemSelected(i)) {
+ selectedItemKeys.add(select.getValue(i));
+ }
+ }
+ return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
+ }
+
+ @Override
+ public void onChange(ChangeEvent event) {
+
+ if (select.isMultipleSelect()) {
+ client.updateVariable(paintableId, "selected", getSelectedItems(),
+ isImmediate());
+ } else {
+ client.updateVariable(paintableId, "selected",
+ new String[] { "" + getSelectedItem() }, isImmediate());
+ }
+ if (firstValueIsTemporaryNullItem) {
+ // remove temporary empty item
+ select.removeItem(0);
+ firstValueIsTemporaryNullItem = false;
+ /*
+ * Workaround to achrome bug that may cause value change event not
+ * to fire when selection is done with keyboard.
+ *
+ * http://dev.vaadin.com/ticket/10109
+ *
+ * Problem is confirmed to exist only on Chrome-Win, but just
+ * execute in for all webkits. Probably exists also in other
+ * webkits/blinks on windows.
+ */
+ if (BrowserInfo.get().isWebkit()) {
+ select.getElement().blur();
+ select.getElement().focus();
+ }
+
+ }
+ }
+
+ @Override
+ public void setHeight(String height) {
+ select.setHeight(height);
+ super.setHeight(height);
+ }
+
+ @Override
+ public void setWidth(String width) {
+ select.setWidth(width);
+ super.setWidth(width);
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ getOptionsContainer().setTabIndex(tabIndex);
+ }
+
+ @Override
+ protected void updateEnabledState() {
+ select.setEnabled(isEnabled() && !isReadonly());
+ }
+
+ @Override
+ public void focus() {
+ select.setFocus(true);
+ }
+
+ /**
+ * @return the root select widget
+ */
+ public ListBox getSelect() {
+ return getOptionsContainer();
+ }
+
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroup.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroup.java
new file mode 100644
index 0000000000..632944c48b
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroup.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.v7.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.aria.client.Roles;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FocusWidget;
+import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.HasEnabled;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.RadioButton;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.StyleConstants;
+import com.vaadin.client.UIDL;
+import com.vaadin.client.Util;
+import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.ui.Icon;
+import com.vaadin.client.ui.VCheckBox;
+import com.vaadin.shared.EventId;
+import com.vaadin.shared.ui.optiongroup.OptionGroupConstants;
+
+public class VOptionGroup extends VOptionGroupBase
+ implements FocusHandler, BlurHandler {
+
+ public static final String CLASSNAME = "v-select-optiongroup";
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public final Panel panel;
+
+ private final Map<CheckBox, String> optionsToKeys;
+
+ private final Map<CheckBox, Boolean> optionsEnabled;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean sendFocusEvents = false;
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean sendBlurEvents = false;
+ /** For internal use only. May be removed or replaced in the future. */
+ public List<HandlerRegistration> focusHandlers = null;
+ /** For internal use only. May be removed or replaced in the future. */
+ public List<HandlerRegistration> blurHandlers = null;
+
+ private final LoadHandler iconLoadHandler = new LoadHandler() {
+ @Override
+ public void onLoad(LoadEvent event) {
+ Util.notifyParentOfSizeChange(VOptionGroup.this, true);
+ }
+ };
+
+ /**
+ * used to check whether a blur really was a blur of the complete
+ * optiongroup: if a control inside this optiongroup gains focus right after
+ * blur of another control inside this optiongroup (meaning: if onFocus
+ * fires after onBlur has fired), the blur and focus won't be sent to the
+ * server side as only a focus change inside this optiongroup occured
+ */
+ private boolean blurOccured = false;
+
+ private boolean htmlContentAllowed = false;
+
+ private boolean wasHtmlContentAllowed = false;
+ private boolean wasMultiselect = false;
+
+ public VOptionGroup() {
+ super(CLASSNAME);
+ panel = (Panel) optionsContainer;
+ optionsToKeys = new HashMap<CheckBox, String>();
+ optionsEnabled = new HashMap<CheckBox, Boolean>();
+
+ wasMultiselect = isMultiselect();
+ }
+
+ /*
+ * Try to update content of existing elements, rebuild panel entirely
+ * otherwise
+ */
+ @Override
+ public void buildOptions(UIDL uidl) {
+ /*
+ * In order to retain focus, we need to update values rather than
+ * recreate panel from scratch (#10451). However, the panel will be
+ * rebuilt (losing focus) if number of elements or their order is
+ * changed.
+ */
+ HashMap<String, CheckBox> keysToOptions = new HashMap<String, CheckBox>();
+ for (Map.Entry<CheckBox, String> entry : optionsToKeys.entrySet()) {
+ keysToOptions.put(entry.getValue(), entry.getKey());
+ }
+ ArrayList<Widget> existingwidgets = new ArrayList<Widget>();
+ ArrayList<Widget> newwidgets = new ArrayList<Widget>();
+
+ // Get current order of elements
+ for (Widget wid : panel) {
+ existingwidgets.add(wid);
+ }
+
+ optionsEnabled.clear();
+
+ if (isMultiselect()) {
+ Roles.getGroupRole().set(getElement());
+ } else {
+ Roles.getRadiogroupRole().set(getElement());
+ }
+
+ for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) {
+ final UIDL opUidl = (UIDL) it.next();
+
+ String itemHtml = opUidl.getStringAttribute("caption");
+ if (!isHtmlContentAllowed()) {
+ itemHtml = WidgetUtil.escapeHTML(itemHtml);
+ }
+
+ String iconUrl = opUidl.getStringAttribute("icon");
+ if (iconUrl != null && iconUrl.length() != 0) {
+ Icon icon = client.getIcon(iconUrl);
+ itemHtml = icon.getElement().getString() + itemHtml;
+ }
+
+ String key = opUidl.getStringAttribute("key");
+ CheckBox op = keysToOptions.get(key);
+
+ // Need to recreate object if isMultiselect is changed (#10451)
+ // OR if htmlContentAllowed changed due to Safari 5 issue
+ if ((op == null)
+ || (isHtmlContentAllowed() != wasHtmlContentAllowed)
+ || (isMultiselect() != wasMultiselect)) {
+ // Create a new element
+ if (isMultiselect()) {
+ op = new VCheckBox();
+ } else {
+ op = new RadioButton(paintableId);
+ op.setStyleName("v-radiobutton");
+ }
+ if (iconUrl != null && iconUrl.length() != 0) {
+ WidgetUtil.sinkOnloadForImages(op.getElement());
+ op.addHandler(iconLoadHandler, LoadEvent.getType());
+ }
+
+ op.addStyleName(CLASSNAME_OPTION);
+ op.addClickHandler(this);
+
+ optionsToKeys.put(op, key);
+ }
+
+ op.setHTML(itemHtml);
+ op.setValue(opUidl.getBooleanAttribute("selected"));
+ boolean optionEnabled = !opUidl.getBooleanAttribute(
+ OptionGroupConstants.ATTRIBUTE_OPTION_DISABLED);
+ boolean enabled = optionEnabled && !isReadonly() && isEnabled();
+ op.setEnabled(enabled);
+ optionsEnabled.put(op, optionEnabled);
+
+ setStyleName(op.getElement(), StyleConstants.DISABLED,
+ !(optionEnabled && isEnabled()));
+
+ newwidgets.add(op);
+ }
+
+ if (!newwidgets.equals(existingwidgets)) {
+ // Rebuild the panel, losing focus
+ panel.clear();
+ for (Widget wid : newwidgets) {
+ panel.add(wid);
+ }
+ }
+
+ wasHtmlContentAllowed = isHtmlContentAllowed();
+ wasMultiselect = isMultiselect();
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ return selectedKeys.toArray(new String[selectedKeys.size()]);
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ super.onClick(event);
+ if (event.getSource() instanceof CheckBox) {
+ CheckBox source = (CheckBox) event.getSource();
+ if (!source.isEnabled()) {
+ // Click events on the text are received even though the
+ // checkbox is disabled
+ return;
+ }
+ if (BrowserInfo.get().isWebkit()) {
+ // Webkit does not focus non-text input elements on click
+ // (#11854)
+ source.setFocus(true);
+ }
+
+ final boolean selected = source.getValue();
+ final String key = optionsToKeys.get(source);
+ if (!isMultiselect()) {
+ selectedKeys.clear();
+ }
+ if (selected) {
+ selectedKeys.add(key);
+ } else {
+ selectedKeys.remove(key);
+ }
+ client.updateVariable(paintableId, "selected", getSelectedItems(),
+ isImmediate());
+ }
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ for (Iterator<Widget> iterator = panel.iterator(); iterator
+ .hasNext();) {
+ FocusWidget widget = (FocusWidget) iterator.next();
+ widget.setTabIndex(tabIndex);
+ }
+ }
+
+ @Override
+ protected void updateEnabledState() {
+ boolean optionGroupEnabled = isEnabled() && !isReadonly();
+ // sets options enabled according to the widget's enabled,
+ // readonly and each options own enabled
+ for (Widget w : panel) {
+ if (w instanceof HasEnabled) {
+ HasEnabled hasEnabled = (HasEnabled) w;
+ Boolean isOptionEnabled = optionsEnabled.get(w);
+ if (isOptionEnabled == null) {
+ hasEnabled.setEnabled(optionGroupEnabled);
+ setStyleName(w.getElement(), StyleConstants.DISABLED,
+ !isEnabled());
+ } else {
+ hasEnabled
+ .setEnabled(isOptionEnabled && optionGroupEnabled);
+ setStyleName(w.getElement(), StyleConstants.DISABLED,
+ !(isOptionEnabled && isEnabled()));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void focus() {
+ Iterator<Widget> iterator = panel.iterator();
+ if (iterator.hasNext()) {
+ ((Focusable) iterator.next()).setFocus(true);
+ }
+ }
+
+ @Override
+ public void onFocus(FocusEvent arg0) {
+ if (!blurOccured) {
+ // no blur occured before this focus event
+ // panel was blurred => fire the event to the server side if
+ // requested by server side
+ if (sendFocusEvents) {
+ client.updateVariable(paintableId, EventId.FOCUS, "", true);
+ }
+ } else {
+ // blur occured before this focus event
+ // another control inside the panel (checkbox / radio box) was
+ // blurred => do not fire the focus and set blurOccured to false, so
+ // blur will not be fired, too
+ blurOccured = false;
+ }
+ }
+
+ @Override
+ public void onBlur(BlurEvent arg0) {
+ blurOccured = true;
+ if (sendBlurEvents) {
+ Scheduler.get().scheduleDeferred(new Command() {
+ @Override
+ public void execute() {
+ // check whether blurOccured still is true and then send the
+ // event out to the server
+ if (blurOccured) {
+ client.updateVariable(paintableId, EventId.BLUR, "",
+ true);
+ blurOccured = false;
+ }
+ }
+ });
+ }
+ }
+
+ public boolean isHtmlContentAllowed() {
+ return htmlContentAllowed;
+ }
+
+ public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+ this.htmlContentAllowed = htmlContentAllowed;
+ }
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroupBase.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroupBase.java
new file mode 100644
index 0000000000..596828ecd5
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VOptionGroupBase.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.v7.client.ui;
+
+import java.util.Set;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HasEnabled;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.Focusable;
+import com.vaadin.client.UIDL;
+import com.vaadin.client.ui.Field;
+import com.vaadin.client.ui.VNativeButton;
+import com.vaadin.client.v7.ui.VLegacyTextField;
+
+public abstract class VOptionGroupBase extends Composite implements Field,
+ ClickHandler, ChangeHandler, KeyPressHandler, Focusable, HasEnabled {
+
+ public static final String CLASSNAME_OPTION = "v-select-option";
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public ApplicationConnection client;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public String paintableId;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public Set<String> selectedKeys;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean immediate;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean multiselect;
+
+ private boolean enabled;
+
+ private boolean readonly;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public int rows = 0;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean nullSelectionAllowed = true;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean nullSelectionItemAvailable = false;
+
+ /**
+ * Widget holding the different options (e.g. ListBox or Panel for radio
+ * buttons) (optional, fallbacks to container Panel)
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public Widget optionsContainer;
+
+ /**
+ * Panel containing the component.
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public final Panel container;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public VLegacyTextField newItemField;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public VNativeButton newItemButton;
+
+ public VOptionGroupBase(String classname) {
+ container = new FlowPanel();
+ initWidget(container);
+ optionsContainer = container;
+ container.setStyleName(classname);
+ immediate = false;
+ multiselect = false;
+ }
+
+ /*
+ * Call this if you wish to specify your own container for the option
+ * elements (e.g. SELECT)
+ */
+ public VOptionGroupBase(Widget w, String classname) {
+ this(classname);
+ optionsContainer = w;
+ container.add(optionsContainer);
+ }
+
+ protected boolean isImmediate() {
+ return immediate;
+ }
+
+ protected boolean isMultiselect() {
+ return multiselect;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ protected boolean isNullSelectionAllowed() {
+ return nullSelectionAllowed;
+ }
+
+ protected boolean isNullSelectionItemAvailable() {
+ return nullSelectionItemAvailable;
+ }
+
+ /**
+ * For internal use only. May be removed or replaced in the future.
+ *
+ * @return "rows" specified in uidl, 0 if not specified
+ */
+ public int getRows() {
+ return rows;
+ }
+
+ public abstract void setTabIndex(int tabIndex);
+
+ @Override
+ public void onClick(ClickEvent event) {
+ if (event.getSource() == newItemButton
+ && !newItemField.getText().equals("")) {
+ client.updateVariable(paintableId, "newitem",
+ newItemField.getText(), true);
+ newItemField.setText("");
+ }
+ }
+
+ @Override
+ public void onChange(ChangeEvent event) {
+ if (multiselect) {
+ client.updateVariable(paintableId, "selected", getSelectedItems(),
+ immediate);
+ } else {
+ client.updateVariable(paintableId, "selected",
+ new String[] { "" + getSelectedItem() }, immediate);
+ }
+ }
+
+ @Override
+ public void onKeyPress(KeyPressEvent event) {
+ if (event.getSource() == newItemField
+ && event.getCharCode() == KeyCodes.KEY_ENTER) {
+ newItemButton.click();
+ }
+ }
+
+ public void setReadonly(boolean readonly) {
+ if (this.readonly != readonly) {
+ this.readonly = readonly;
+ updateEnabledState();
+ }
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (this.enabled != enabled) {
+ this.enabled = enabled;
+ updateEnabledState();
+ }
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public abstract void buildOptions(UIDL uidl);
+
+ protected abstract String[] getSelectedItems();
+
+ protected abstract void updateEnabledState();
+
+ protected String getSelectedItem() {
+ final String[] sel = getSelectedItems();
+ if (sel.length > 0) {
+ return sel[0];
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTwinColSelect.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTwinColSelect.java
new file mode 100644
index 0000000000..c11dd7b569
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTwinColSelect.java
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.v7.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickHandler;
+import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.Panel;
+import com.vaadin.client.StyleConstants;
+import com.vaadin.client.UIDL;
+import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.ui.SubPartAware;
+import com.vaadin.client.ui.VButton;
+import com.vaadin.shared.ui.twincolselect.TwinColSelectConstants;
+
+public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler,
+ MouseDownHandler, DoubleClickHandler, SubPartAware {
+
+ public static final String CLASSNAME = "v-select-twincol";
+
+ private static final int VISIBLE_COUNT = 10;
+
+ private static final int DEFAULT_COLUMN_COUNT = 10;
+
+ private final DoubleClickListBox options;
+
+ private final DoubleClickListBox selections;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public FlowPanel captionWrapper;
+
+ private HTML optionsCaption = null;
+
+ private HTML selectionsCaption = null;
+
+ private final VButton add;
+
+ private final VButton remove;
+
+ private final FlowPanel buttons;
+
+ private final Panel panel;
+
+ /**
+ * A ListBox which catches double clicks
+ *
+ */
+ public class DoubleClickListBox extends ListBox
+ implements HasDoubleClickHandlers {
+ public DoubleClickListBox(boolean isMultipleSelect) {
+ super(isMultipleSelect);
+ }
+
+ public DoubleClickListBox() {
+ super();
+ }
+
+ @Override
+ public HandlerRegistration addDoubleClickHandler(
+ DoubleClickHandler handler) {
+ return addDomHandler(handler, DoubleClickEvent.getType());
+ }
+ }
+
+ public VTwinColSelect() {
+ super(CLASSNAME);
+
+ captionWrapper = new FlowPanel();
+
+ options = new DoubleClickListBox();
+ options.addClickHandler(this);
+ options.addDoubleClickHandler(this);
+ options.setVisibleItemCount(VISIBLE_COUNT);
+ options.setStyleName(CLASSNAME + "-options");
+
+ selections = new DoubleClickListBox();
+ selections.addClickHandler(this);
+ selections.addDoubleClickHandler(this);
+ selections.setVisibleItemCount(VISIBLE_COUNT);
+ selections.setStyleName(CLASSNAME + "-selections");
+
+ buttons = new FlowPanel();
+ buttons.setStyleName(CLASSNAME + "-buttons");
+ add = new VButton();
+ add.setText(">>");
+ add.addClickHandler(this);
+ remove = new VButton();
+ remove.setText("<<");
+ remove.addClickHandler(this);
+
+ panel = ((Panel) optionsContainer);
+
+ panel.add(captionWrapper);
+ captionWrapper.getElement().getStyle().setOverflow(Overflow.HIDDEN);
+ // Hide until there actually is a caption to prevent IE from rendering
+ // extra empty space
+ captionWrapper.setVisible(false);
+
+ panel.add(options);
+ buttons.add(add);
+ final HTML br = new HTML("<span/>");
+ br.setStyleName(CLASSNAME + "-deco");
+ buttons.add(br);
+ buttons.add(remove);
+ panel.add(buttons);
+ panel.add(selections);
+
+ options.addKeyDownHandler(this);
+ options.addMouseDownHandler(this);
+
+ selections.addMouseDownHandler(this);
+ selections.addKeyDownHandler(this);
+
+ updateEnabledState();
+ }
+
+ public HTML getOptionsCaption() {
+ if (optionsCaption == null) {
+ optionsCaption = new HTML();
+ optionsCaption.setStyleName(CLASSNAME + "-caption-left");
+ optionsCaption.getElement().getStyle()
+ .setFloat(com.google.gwt.dom.client.Style.Float.LEFT);
+ captionWrapper.add(optionsCaption);
+ }
+
+ return optionsCaption;
+ }
+
+ public HTML getSelectionsCaption() {
+ if (selectionsCaption == null) {
+ selectionsCaption = new HTML();
+ selectionsCaption.setStyleName(CLASSNAME + "-caption-right");
+ selectionsCaption.getElement().getStyle()
+ .setFloat(com.google.gwt.dom.client.Style.Float.RIGHT);
+ captionWrapper.add(selectionsCaption);
+ }
+
+ return selectionsCaption;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void updateCaptions(UIDL uidl) {
+ String leftCaption = (uidl
+ .hasAttribute(TwinColSelectConstants.ATTRIBUTE_LEFT_CAPTION)
+ ? uidl.getStringAttribute(
+ TwinColSelectConstants.ATTRIBUTE_LEFT_CAPTION)
+ : null);
+ String rightCaption = (uidl
+ .hasAttribute(TwinColSelectConstants.ATTRIBUTE_RIGHT_CAPTION)
+ ? uidl.getStringAttribute(
+ TwinColSelectConstants.ATTRIBUTE_RIGHT_CAPTION)
+ : null);
+
+ boolean hasCaptions = (leftCaption != null || rightCaption != null);
+
+ if (leftCaption == null) {
+ removeOptionsCaption();
+ } else {
+ getOptionsCaption().setText(leftCaption);
+
+ }
+
+ if (rightCaption == null) {
+ removeSelectionsCaption();
+ } else {
+ getSelectionsCaption().setText(rightCaption);
+ }
+
+ captionWrapper.setVisible(hasCaptions);
+ }
+
+ private void removeOptionsCaption() {
+ if (optionsCaption == null) {
+ return;
+ }
+
+ if (optionsCaption.getParent() != null) {
+ captionWrapper.remove(optionsCaption);
+ }
+
+ optionsCaption = null;
+ }
+
+ private void removeSelectionsCaption() {
+ if (selectionsCaption == null) {
+ return;
+ }
+
+ if (selectionsCaption.getParent() != null) {
+ captionWrapper.remove(selectionsCaption);
+ }
+
+ selectionsCaption = null;
+ }
+
+ @Override
+ public void buildOptions(UIDL uidl) {
+ options.setMultipleSelect(isMultiselect());
+ selections.setMultipleSelect(isMultiselect());
+ options.clear();
+ selections.clear();
+ for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
+ final UIDL optionUidl = (UIDL) i.next();
+ if (optionUidl.hasAttribute("selected")) {
+ selections.addItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"));
+ } else {
+ options.addItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"));
+ }
+ }
+
+ if (getRows() > 0) {
+ options.setVisibleItemCount(getRows());
+ selections.setVisibleItemCount(getRows());
+
+ }
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ final ArrayList<String> selectedItemKeys = new ArrayList<String>();
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selectedItemKeys.add(selections.getValue(i));
+ }
+ return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
+ }
+
+ private boolean[] getSelectionBitmap(ListBox listBox) {
+ final boolean[] selectedIndexes = new boolean[listBox.getItemCount()];
+ for (int i = 0; i < listBox.getItemCount(); i++) {
+ if (listBox.isItemSelected(i)) {
+ selectedIndexes[i] = true;
+ } else {
+ selectedIndexes[i] = false;
+ }
+ }
+ return selectedIndexes;
+ }
+
+ private void addItem() {
+ Set<String> movedItems = moveSelectedItems(options, selections);
+ selectedKeys.addAll(movedItems);
+
+ client.updateVariable(paintableId, "selected",
+ selectedKeys.toArray(new String[selectedKeys.size()]),
+ isImmediate());
+ }
+
+ private void removeItem() {
+ Set<String> movedItems = moveSelectedItems(selections, options);
+ selectedKeys.removeAll(movedItems);
+
+ client.updateVariable(paintableId, "selected",
+ selectedKeys.toArray(new String[selectedKeys.size()]),
+ isImmediate());
+ }
+
+ private Set<String> moveSelectedItems(ListBox source, ListBox target) {
+ final boolean[] sel = getSelectionBitmap(source);
+ final Set<String> movedItems = new HashSet<String>();
+ int lastSelected = 0;
+ for (int i = 0; i < sel.length; i++) {
+ if (sel[i]) {
+ final int optionIndex = i
+ - (sel.length - source.getItemCount());
+ movedItems.add(source.getValue(optionIndex));
+
+ // Move selection to another column
+ final String text = source.getItemText(optionIndex);
+ final String value = source.getValue(optionIndex);
+ target.addItem(text, value);
+ target.setItemSelected(target.getItemCount() - 1, true);
+ source.removeItem(optionIndex);
+
+ if (source.getItemCount() > 0) {
+ lastSelected = optionIndex > 0 ? optionIndex - 1 : 0;
+ }
+ }
+ }
+
+ if (source.getItemCount() > 0) {
+ source.setSelectedIndex(lastSelected);
+ }
+
+ // If no items are left move the focus to the selections
+ if (source.getItemCount() == 0) {
+ target.setFocus(true);
+ } else {
+ source.setFocus(true);
+ }
+
+ return movedItems;
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ super.onClick(event);
+ if (event.getSource() == add) {
+ addItem();
+
+ } else if (event.getSource() == remove) {
+ removeItem();
+
+ } else if (event.getSource() == options) {
+ // unselect all in other list, to avoid mistakes (i.e wrong button)
+ final int c = selections.getItemCount();
+ for (int i = 0; i < c; i++) {
+ selections.setItemSelected(i, false);
+ }
+ } else if (event.getSource() == selections) {
+ // unselect all in other list, to avoid mistakes (i.e wrong button)
+ final int c = options.getItemCount();
+ for (int i = 0; i < c; i++) {
+ options.setItemSelected(i, false);
+ }
+ }
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void clearInternalHeights() {
+ selections.setHeight("");
+ options.setHeight("");
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setInternalHeights() {
+ int captionHeight = WidgetUtil.getRequiredHeight(captionWrapper);
+ int totalHeight = getOffsetHeight();
+
+ String selectHeight = (totalHeight - captionHeight) + "px";
+
+ selections.setHeight(selectHeight);
+ options.setHeight(selectHeight);
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void clearInternalWidths() {
+ int cols = DEFAULT_COLUMN_COUNT;
+
+ if (cols >= 0) {
+ String colWidth = cols + "em";
+ String containerWidth = (2 * cols + 4) + "em";
+ // Caption wrapper width == optionsSelect + buttons +
+ // selectionsSelect
+ String captionWrapperWidth = (2 * cols + 4 - 0.5) + "em";
+
+ options.setWidth(colWidth);
+ if (optionsCaption != null) {
+ optionsCaption.setWidth(colWidth);
+ }
+ selections.setWidth(colWidth);
+ if (selectionsCaption != null) {
+ selectionsCaption.setWidth(colWidth);
+ }
+ buttons.setWidth("3.5em");
+ optionsContainer.setWidth(containerWidth);
+ captionWrapper.setWidth(captionWrapperWidth);
+ }
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setInternalWidths() {
+ getElement().getStyle().setPosition(Position.RELATIVE);
+ int bordersAndPaddings = WidgetUtil
+ .measureHorizontalPaddingAndBorder(buttons.getElement(), 0);
+
+ int buttonWidth = WidgetUtil.getRequiredWidth(buttons);
+ int totalWidth = getOffsetWidth();
+
+ int spaceForSelect = (totalWidth - buttonWidth - bordersAndPaddings)
+ / 2;
+
+ options.setWidth(spaceForSelect + "px");
+ if (optionsCaption != null) {
+ optionsCaption.setWidth(spaceForSelect + "px");
+ }
+
+ selections.setWidth(spaceForSelect + "px");
+ if (selectionsCaption != null) {
+ selectionsCaption.setWidth(spaceForSelect + "px");
+ }
+ captionWrapper.setWidth("100%");
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ options.setTabIndex(tabIndex);
+ selections.setTabIndex(tabIndex);
+ add.setTabIndex(tabIndex);
+ remove.setTabIndex(tabIndex);
+ }
+
+ @Override
+ public void updateEnabledState() {
+ boolean enabled = isEnabled() && !isReadonly();
+ options.setEnabled(enabled);
+ selections.setEnabled(enabled);
+ add.setEnabled(enabled);
+ remove.setEnabled(enabled);
+ add.setStyleName(StyleConstants.DISABLED, !enabled);
+ remove.setStyleName(StyleConstants.DISABLED, !enabled);
+ }
+
+ @Override
+ public void focus() {
+ options.setFocus(true);
+ }
+
+ /**
+ * Get the key that selects an item in the table. By default it is the Enter
+ * key but by overriding this you can change the key to whatever you want.
+ *
+ * @return
+ */
+ protected int getNavigationSelectKey() {
+ return KeyCodes.KEY_ENTER;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
+ * .event.dom.client.KeyDownEvent)
+ */
+ @Override
+ public void onKeyDown(KeyDownEvent event) {
+ int keycode = event.getNativeKeyCode();
+
+ // Catch tab and move between select:s
+ if (keycode == KeyCodes.KEY_TAB && event.getSource() == options) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Remove current selections
+ for (int i = 0; i < options.getItemCount(); i++) {
+ options.setItemSelected(i, false);
+ }
+
+ // Focus selections
+ selections.setFocus(true);
+ }
+
+ if (keycode == KeyCodes.KEY_TAB && event.isShiftKeyDown()
+ && event.getSource() == selections) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Remove current selections
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selections.setItemSelected(i, false);
+ }
+
+ // Focus options
+ options.setFocus(true);
+ }
+
+ if (keycode == getNavigationSelectKey()) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Decide which select the selection was made in
+ if (event.getSource() == options) {
+ // Prevents the selection to become a single selection when
+ // using Enter key
+ // as the selection key (default)
+ options.setFocus(false);
+
+ addItem();
+
+ } else if (event.getSource() == selections) {
+ // Prevents the selection to become a single selection when
+ // using Enter key
+ // as the selection key (default)
+ selections.setFocus(false);
+
+ removeItem();
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google
+ * .gwt.event.dom.client.MouseDownEvent)
+ */
+ @Override
+ public void onMouseDown(MouseDownEvent event) {
+ // Ensure that items are deselected when selecting
+ // from a different source. See #3699 for details.
+ if (event.getSource() == options) {
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selections.setItemSelected(i, false);
+ }
+ } else if (event.getSource() == selections) {
+ for (int i = 0; i < options.getItemCount(); i++) {
+ options.setItemSelected(i, false);
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.DoubleClickHandler#onDoubleClick(com.
+ * google.gwt.event.dom.client.DoubleClickEvent)
+ */
+ @Override
+ public void onDoubleClick(DoubleClickEvent event) {
+ if (event.getSource() == options) {
+ addItem();
+ options.setSelectedIndex(-1);
+ options.setFocus(false);
+ } else if (event.getSource() == selections) {
+ removeItem();
+ selections.setSelectedIndex(-1);
+ selections.setFocus(false);
+ }
+
+ }
+
+ private static final String SUBPART_OPTION_SELECT = "leftSelect";
+ private static final String SUBPART_OPTION_SELECT_ITEM = SUBPART_OPTION_SELECT
+ + "-item";
+ private static final String SUBPART_SELECTION_SELECT = "rightSelect";
+ private static final String SUBPART_SELECTION_SELECT_ITEM = SUBPART_SELECTION_SELECT
+ + "-item";
+ private static final String SUBPART_LEFT_CAPTION = "leftCaption";
+ private static final String SUBPART_RIGHT_CAPTION = "rightCaption";
+ private static final String SUBPART_ADD_BUTTON = "add";
+ private static final String SUBPART_REMOVE_BUTTON = "remove";
+
+ @Override
+ public com.google.gwt.user.client.Element getSubPartElement(
+ String subPart) {
+ if (SUBPART_OPTION_SELECT.equals(subPart)) {
+ return options.getElement();
+ } else if (subPart.startsWith(SUBPART_OPTION_SELECT_ITEM)) {
+ String idx = subPart.substring(SUBPART_OPTION_SELECT_ITEM.length());
+ return (com.google.gwt.user.client.Element) options.getElement()
+ .getChild(Integer.parseInt(idx));
+ } else if (SUBPART_SELECTION_SELECT.equals(subPart)) {
+ return selections.getElement();
+ } else if (subPart.startsWith(SUBPART_SELECTION_SELECT_ITEM)) {
+ String idx = subPart
+ .substring(SUBPART_SELECTION_SELECT_ITEM.length());
+ return (com.google.gwt.user.client.Element) selections.getElement()
+ .getChild(Integer.parseInt(idx));
+ } else if (optionsCaption != null
+ && SUBPART_LEFT_CAPTION.equals(subPart)) {
+ return optionsCaption.getElement();
+ } else if (selectionsCaption != null
+ && SUBPART_RIGHT_CAPTION.equals(subPart)) {
+ return selectionsCaption.getElement();
+ } else if (SUBPART_ADD_BUTTON.equals(subPart)) {
+ return add.getElement();
+ } else if (SUBPART_REMOVE_BUTTON.equals(subPart)) {
+ return remove.getElement();
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getSubPartName(
+ com.google.gwt.user.client.Element subElement) {
+ if (optionsCaption != null
+ && optionsCaption.getElement().isOrHasChild(subElement)) {
+ return SUBPART_LEFT_CAPTION;
+ } else if (selectionsCaption != null
+ && selectionsCaption.getElement().isOrHasChild(subElement)) {
+ return SUBPART_RIGHT_CAPTION;
+ } else if (options.getElement().isOrHasChild(subElement)) {
+ if (options.getElement() == subElement) {
+ return SUBPART_OPTION_SELECT;
+ } else {
+ int idx = WidgetUtil.getChildElementIndex(subElement);
+ return SUBPART_OPTION_SELECT_ITEM + idx;
+ }
+ } else if (selections.getElement().isOrHasChild(subElement)) {
+ if (selections.getElement() == subElement) {
+ return SUBPART_SELECTION_SELECT;
+ } else {
+ int idx = WidgetUtil.getChildElementIndex(subElement);
+ return SUBPART_SELECTION_SELECT_ITEM + idx;
+ }
+ } else if (add.getElement().isOrHasChild(subElement)) {
+ return SUBPART_ADD_BUTTON;
+ } else if (remove.getElement().isOrHasChild(subElement)) {
+ return SUBPART_REMOVE_BUTTON;
+ }
+
+ return null;
+ }
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/listselect/ListSelectConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/listselect/ListSelectConnector.java
index 5f515f5570..78f06ed9cd 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/listselect/ListSelectConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/listselect/ListSelectConnector.java
@@ -16,8 +16,8 @@
package com.vaadin.v7.client.ui.listselect;
-import com.vaadin.client.ui.VListSelect;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.v7.client.ui.VListSelect;
import com.vaadin.v7.client.ui.optiongroup.OptionGroupBaseConnector;
import com.vaadin.v7.ui.ListSelect;
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/nativeselect/NativeSelectConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/nativeselect/NativeSelectConnector.java
index 49bdce4baf..08a8753eb8 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/nativeselect/NativeSelectConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/nativeselect/NativeSelectConnector.java
@@ -17,8 +17,8 @@
package com.vaadin.v7.client.ui.nativeselect;
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
-import com.vaadin.client.ui.VNativeSelect;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.v7.client.ui.VNativeSelect;
import com.vaadin.v7.client.ui.optiongroup.OptionGroupBaseConnector;
import com.vaadin.v7.ui.NativeSelect;
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupBaseConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupBaseConnector.java
index e24ae92742..483abbc32b 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupBaseConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupBaseConnector.java
@@ -21,10 +21,10 @@ import com.vaadin.client.Paintable;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.UIDL;
import com.vaadin.client.ui.VNativeButton;
-import com.vaadin.client.ui.VOptionGroupBase;
import com.vaadin.client.v7.ui.VLegacyTextField;
import com.vaadin.shared.ui.select.AbstractSelectState;
import com.vaadin.v7.client.ui.AbstractFieldConnector;
+import com.vaadin.v7.client.ui.VOptionGroupBase;
public abstract class OptionGroupBaseConnector extends AbstractFieldConnector
implements Paintable {
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupConnector.java
index d648115447..172c872772 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/optiongroup/OptionGroupConnector.java
@@ -23,10 +23,10 @@ import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.UIDL;
-import com.vaadin.client.ui.VOptionGroup;
import com.vaadin.shared.EventId;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.optiongroup.OptionGroupState;
+import com.vaadin.v7.client.ui.VOptionGroup;
import com.vaadin.v7.ui.OptionGroup;
@Connect(OptionGroup.class)
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/twincolselect/TwinColSelectConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/twincolselect/TwinColSelectConnector.java
index 218792fc89..62084366d8 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/twincolselect/TwinColSelectConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/twincolselect/TwinColSelectConnector.java
@@ -19,9 +19,9 @@ package com.vaadin.v7.client.ui.twincolselect;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.DirectionalManagedLayout;
import com.vaadin.client.UIDL;
-import com.vaadin.client.ui.VTwinColSelect;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.twincolselect.TwinColSelectState;
+import com.vaadin.v7.client.ui.VTwinColSelect;
import com.vaadin.v7.client.ui.optiongroup.OptionGroupBaseConnector;
import com.vaadin.v7.ui.TwinColSelect;