]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add isUserOriginated to SelectedTabChangeEvent (#9580)
authorArtur <artur@vaadin.com>
Thu, 29 Jun 2017 06:06:24 +0000 (09:06 +0300)
committerHenri Sara <henri.sara@gmail.com>
Thu, 29 Jun 2017 06:06:24 +0000 (09:06 +0300)
Fixes #9545

server/src/main/java/com/vaadin/data/HasUserOriginated.java [new file with mode: 0644]
server/src/main/java/com/vaadin/data/HasValue.java
server/src/main/java/com/vaadin/ui/TabSheet.java
server/src/test/java/com/vaadin/tests/server/component/tabsheet/TabSheetTest.java

diff --git a/server/src/main/java/com/vaadin/data/HasUserOriginated.java b/server/src/main/java/com/vaadin/data/HasUserOriginated.java
new file mode 100644 (file)
index 0000000..e7d6d12
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.data;
+
+import java.io.Serializable;
+
+/**
+ * Marker for events which provides information of the event origin.
+ *
+ * @since
+ */
+public interface HasUserOriginated extends Serializable {
+    /**
+     * Returns whether this event was triggered by user interaction, on the
+     * client side, or programmatically, on the server side.
+     *
+     * @return {@code true} if this event originates from the client,
+     *         {@code false} otherwise.
+     */
+    public boolean isUserOriginated();
+
+}
index de2f86550f1a22877f5f799b6635f6dbe39fd75e..b2ce098f6f686a4bd834cdef7882e04cb38064e6 100644 (file)
@@ -47,7 +47,8 @@ public interface HasValue<V> extends Serializable {
      * @param <V>
      *            the value type
      */
-    public class ValueChangeEvent<V> extends EventObject {
+    public class ValueChangeEvent<V> extends EventObject
+            implements HasUserOriginated {
 
         private final boolean userOriginated;
         private final Component component;
@@ -101,7 +102,7 @@ public interface HasValue<V> extends Serializable {
         /**
          * Returns the value of the source before this value change event
          * occurred.
-         * 
+         *
          * @return the value previously held by the source of this event
          */
         public V getOldValue() {
@@ -117,13 +118,7 @@ public interface HasValue<V> extends Serializable {
             return value;
         }
 
-        /**
-         * Returns whether this event was triggered by user interaction, on the
-         * client side, or programmatically, on the server side.
-         *
-         * @return {@code true} if this event originates from the client,
-         *         {@code false} otherwise.
-         */
+        @Override
         public boolean isUserOriginated() {
             return userOriginated;
         }
@@ -224,7 +219,7 @@ public interface HasValue<V> extends Serializable {
      * Returns the current value of this object, wrapped in an {@code Optional}.
      * <p>
      * The {@code Optional} will be empty if the value is {@code null} or
-     * {@code isEmpty()} returns {@code true}. 
+     * {@code isEmpty()} returns {@code true}.
      *
      * @return the current value, wrapped in an {@code Optional}
      */
index ec018e5fbfdc5558feaef279635601c6ad983e2d..550c5fc8cac0d4f5ac98a81e1528d1051fe352f3 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.jsoup.nodes.Attributes;
 import org.jsoup.nodes.Element;
 
+import com.vaadin.data.HasUserOriginated;
 import com.vaadin.event.FieldEvents.BlurEvent;
 import com.vaadin.event.FieldEvents.BlurListener;
 import com.vaadin.event.FieldEvents.BlurNotifier;
@@ -87,7 +88,7 @@ public class TabSheet extends AbstractComponentContainer
 
         @Override
         public void setSelected(String key) {
-            setSelectedTab(keyMapper.get(key));
+            setSelectedTab(keyMapper.get(key), true);
         }
 
         @Override
@@ -120,7 +121,7 @@ public class TabSheet extends AbstractComponentContainer
      * Mapper between server-side component instances (tab contents) and keys
      * given to the client that identify tabs.
      */
-    private final KeyMapper<Component> keyMapper = new KeyMapper<>();
+    protected final KeyMapper<Component> keyMapper = new KeyMapper<>();
 
     /**
      * Handler to be called when a tab is closed.
@@ -227,7 +228,7 @@ public class TabSheet extends AbstractComponentContainer
 
                     // select the first enabled and visible tab, if any
                     updateSelection();
-                    fireSelectedTabChange();
+                    fireSelectedTabChange(false);
                 }
             }
         }
@@ -389,7 +390,7 @@ public class TabSheet extends AbstractComponentContainer
 
             if (selected == null) {
                 setSelected(tabComponent);
-                fireSelectedTabChange();
+                fireSelectedTabChange(false);
             }
 
             super.addComponent(tabComponent);
@@ -525,17 +526,17 @@ public class TabSheet extends AbstractComponentContainer
     }
 
     /**
-     * Returns the {@link Tab} (metadata) for a component. The {@link Tab}
+     * Returns the {@link Tab} (metadata) with the given index. The {@link Tab}
      * object can be used for setting caption,icon, etc for the tab.
      *
-     * @param position
-     *            the position of the tab
-     * @return The tab in the given position, or null if the position is out of
+     * @param index
+     *            the index of the tab
+     * @return The tab with the given index, or null if the index is out of
      *         bounds.
      */
-    public Tab getTab(int position) {
-        if (position >= 0 && position < getComponentCount()) {
-            return getTab(components.get(position));
+    public Tab getTab(int index) {
+        if (index >= 0 && index < getComponentCount()) {
+            return getTab(components.get(index));
         } else {
             return null;
         }
@@ -545,13 +546,29 @@ public class TabSheet extends AbstractComponentContainer
      * Sets the selected tab. The tab is identified by the tab content
      * component. Does nothing if the tabsheet doesn't contain the component.
      *
-     * @param c
+     * @param component
+     *            the component of the tab to select
      */
-    public void setSelectedTab(Component c) {
-        if (c != null && components.contains(c) && !c.equals(selected)) {
-            setSelected(c);
+    public void setSelectedTab(Component component) {
+        setSelectedTab(component, false);
+    }
+
+    /**
+     * Sets the selected tab. The tab is identified by the tab content
+     * component. Does nothing if the tabsheet doesn't contain the component.
+     *
+     * @param component
+     *            the component of the tab to select
+     * @param userOriginated
+     *            <code>true</code> if the event originates from the client
+     *            side, <code>false</code> otherwise
+     */
+    public void setSelectedTab(Component component, boolean userOriginated) {
+        if (component != null && components.contains(component)
+                && !component.equals(selected)) {
+            setSelected(component);
             updateSelection();
-            fireSelectedTabChange();
+            fireSelectedTabChange(userOriginated);
             markAsDirty();
             getRpcProxy(TabsheetClientRpc.class).revertToSharedStateSelection();
         }
@@ -593,21 +610,23 @@ public class TabSheet extends AbstractComponentContainer
      * the given tab.
      *
      * @param tab
+     *            the tab to select
      */
     public void setSelectedTab(Tab tab) {
         if (tab != null) {
-            setSelectedTab(tab.getComponent());
+            setSelectedTab(tab.getComponent(), false);
         }
     }
 
     /**
-     * Sets the selected tab, identified by its position. Does nothing if the
+     * Sets the selected tab, identified by its index. Does nothing if the
      * position is out of bounds.
      *
-     * @param position
+     * @param index
+     *            the index of the tab to select
      */
-    public void setSelectedTab(int position) {
-        setSelectedTab(getTab(position));
+    public void setSelectedTab(int index) {
+        setSelectedTab(getTab(index));
     }
 
     /**
@@ -742,7 +761,7 @@ public class TabSheet extends AbstractComponentContainer
                 // is changed.
                 // Other cases are handled implicitly by removeComponent() and
                 // addComponent()addTab()
-                fireSelectedTabChange();
+                fireSelectedTabChange(false);
             }
 
             // Tab associations are not changed, but metadata is swapped between
@@ -779,26 +798,39 @@ public class TabSheet extends AbstractComponentContainer
      * @author Vaadin Ltd.
      * @since 3.0
      */
-    public static class SelectedTabChangeEvent extends Component.Event {
+    public static class SelectedTabChangeEvent extends Component.Event
+            implements HasUserOriginated {
+
+        private final boolean userOriginated;
 
         /**
-         * New instance of selected tab change event
+         * Creates a new instance of the event.
          *
          * @param source
-         *            the Source of the event.
+         *            the source of the event
+         * @param userOriginated
+         *            <code>true</code> if the event originates from the client
+         *            side, <code>false</code> otherwise
          */
-        public SelectedTabChangeEvent(Component source) {
+        public SelectedTabChangeEvent(Component source,
+                boolean userOriginated) {
             super(source);
+            this.userOriginated = userOriginated;
         }
 
         /**
-         * TabSheet where the event occurred.
+         * The TabSheet where the event occurred.
          *
-         * @return the Source of the event.
+         * @return the TabSheet where the event occurred
          */
         public TabSheet getTabSheet() {
             return (TabSheet) getSource();
         }
+
+        @Override
+        public boolean isUserOriginated() {
+            return userOriginated;
+        }
     }
 
     /**
@@ -857,10 +889,27 @@ public class TabSheet extends AbstractComponentContainer
     }
 
     /**
-     * Sends an event that the currently selected tab has changed.
+     * Sends an event originating from the server, telling that the currently
+     * selected tab has changed.
+     *
+     * @deprecated use {@link #fireSelectedTabChange(boolean)} to indicate the
+     *             origin of the event
      */
+    @Deprecated
     protected void fireSelectedTabChange() {
-        fireEvent(new SelectedTabChangeEvent(this));
+        fireSelectedTabChange(false);
+    }
+
+    /**
+     * Sends an event that the currently selected tab has changed.
+     *
+     * @param userOriginated
+     *            <code>true</code> if the event originates from the client
+     *            side, <code>false</code> otherwise
+     * @since
+     */
+    protected void fireSelectedTabChange(boolean userOriginated) {
+        fireEvent(new SelectedTabChangeEvent(this, userOriginated));
     }
 
     /**
@@ -1200,7 +1249,7 @@ public class TabSheet extends AbstractComponentContainer
             tabState.enabled = enabled;
 
             if (updateSelection()) {
-                fireSelectedTabChange();
+                fireSelectedTabChange(false);
             }
             markAsDirty();
         }
@@ -1215,7 +1264,7 @@ public class TabSheet extends AbstractComponentContainer
             tabState.visible = visible;
 
             if (updateSelection()) {
-                fireSelectedTabChange();
+                fireSelectedTabChange(false);
             }
             markAsDirty();
         }
@@ -1519,7 +1568,7 @@ public class TabSheet extends AbstractComponentContainer
             boolean selected = DesignAttributeHandler.readAttribute("selected",
                     attr, Boolean.class);
             if (selected) {
-                this.setSelectedTab(tab.getComponent());
+                this.setSelectedTab(tab.getComponent(), false);
             }
         }
     }
index b48a3477ab9c06623059c0926b356182e1b24113..91cfe7712a243cec586c6f89e09f4dd54e83dab6 100644 (file)
@@ -6,11 +6,17 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
 import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.junit.Assert;
 import org.junit.Test;
 
+import com.vaadin.shared.ui.tabsheet.TabsheetServerRpc;
+import com.vaadin.shared.ui.tabsheet.TabsheetState;
+import com.vaadin.ui.Button;
 import com.vaadin.ui.Component;
+import com.vaadin.ui.ComponentTest;
 import com.vaadin.ui.Label;
 import com.vaadin.ui.TabSheet;
 import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
@@ -284,4 +290,50 @@ public class TabSheetTest {
         listener.assertActualComponentIs(lbl3);
         assertEquals(lbl3, tabSheet.getSelectedTab());
     }
+
+    public static class TestTabsheet extends TabSheet {
+        public TestTabsheet(Component... components) {
+            super(components);
+        }
+
+        public String getKey(Component c) {
+            return keyMapper.key(c);
+        }
+
+        @Override
+        public TabsheetState getState() {
+            return super.getState();
+        }
+    }
+
+    @Test
+    public void userOriginatedForSelectionEvent() {
+        AtomicBoolean userOriginated = new AtomicBoolean(false);
+        AtomicReference<Component> selected = new AtomicReference<>();
+
+        Button b1 = new Button("b1");
+        Button b2 = new Button("b2");
+        Button b3 = new Button("b3");
+        Button b4 = new Button("b4");
+        TestTabsheet tabsheet = new TestTabsheet(b1, b2, b3, b4);
+        tabsheet.addSelectedTabChangeListener(e -> {
+            userOriginated.set(e.isUserOriginated());
+            selected.set(e.getTabSheet().getSelectedTab());
+        });
+
+        tabsheet.setSelectedTab(b2);
+        Assert.assertFalse(userOriginated.get());
+        Assert.assertEquals(b2, selected.get());
+
+        TabsheetServerRpc rpc = ComponentTest.getRpcProxy(tabsheet,
+                TabsheetServerRpc.class);
+        rpc.setSelected(tabsheet.getKey(b1));
+        Assert.assertTrue(userOriginated.get());
+        Assert.assertEquals(b1, selected.get());
+
+        tabsheet.setSelectedTab(tabsheet.getTab(b4));
+        Assert.assertFalse(userOriginated.get());
+        Assert.assertEquals(b4, selected.get());
+
+    }
 }