Added TabBar.setTabEnabled() option to disable tabs in a TabBar.

Patch by: jlabanca
Review by: ecc
Issue: 2527



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3671 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/TabBar.java b/user/src/com/google/gwt/user/client/ui/TabBar.java
index f7065fe..33df6ab 100644
--- a/user/src/com/google/gwt/user/client/ui/TabBar.java
+++ b/user/src/com/google/gwt/user/client/ui/TabBar.java
@@ -39,6 +39,10 @@
  * tabs } </li>
  * <li>.gwt-TabBar .gwt-TabBarItem-wrapper-selected { table cell around
  * selected tab }</li>
+ * <li>.gwt-TabBar .gwt-TabBarItem-disabled { additional style for disabled
+ * tabs } </li>
+ * <li>.gwt-TabBar .gwt-TabBarItem-wrapper-disabled { table cell around
+ * disabled tab }</li>
  * </ul>
  * <p>
  * <h3>Example</h3>
@@ -57,6 +61,7 @@
     private SimplePanel focusablePanel;
     private ClickListener clickDelegate;
     private KeyboardListener keyDelegate;
+    private boolean enabled = true;
 
     ClickDelegatePanel(Widget child, ClickListener cDelegate,
         KeyboardListener kDelegate) {
@@ -80,8 +85,16 @@
       return focusablePanel;
     }
 
+    public boolean isEnabled() {
+      return enabled;
+    }
+
     @Override
     public void onBrowserEvent(Event event) {
+      if (!enabled) {
+        return;
+      }
+      
       // No need for call to super.
       switch (DOM.eventGetType(event)) {
 
@@ -95,6 +108,10 @@
           break;
       }
     }
+
+    public void setEnabled(boolean enabled) {
+      this.enabled = enabled;
+    }
   }
 
   private static final String STYLENAME_DEFAULT = "gwt-TabBarItem";
@@ -252,6 +269,19 @@
     insertTabWidget(widget, beforeIndex);
   }
 
+  /**
+   * Check if a tab is enabled or disabled.  If disabled, the user cannot
+   * select the tab.
+   * 
+   * @param index the index of the tab
+   * @return true if the tab is enabled, false if disabled
+   */
+  public boolean isTabEnabled(int index) {
+    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";
+    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
+    return delPanel.isEnabled();
+  }
+
   public void onClick(Widget sender) {
     selectTabByTabWidget(sender);
   }
@@ -324,6 +354,23 @@
   }
 
   /**
+   * Enable or disable a tab.  When disabled, users cannot select the tab.
+   * 
+   * @param index the index of the tab to enable or disable
+   * @param enabled true to enable, false to disable
+   */
+  public void setTabEnabled(int index, boolean enabled) {
+    assert (index >= 0) && (index < getTabCount()) : "Tab index out of bounds";
+
+    // Style the wrapper
+    ClickDelegatePanel delPanel = (ClickDelegatePanel) panel.getWidget(index + 1);
+    delPanel.setEnabled(enabled);
+    setStyleName(delPanel.getElement(), "gwt-TabBarItem-disabled", !enabled);
+    setStyleName(delPanel.getElement().getParentElement(),
+        "gwt-TabBarItem-wrapper-disabled", !enabled);
+  }
+
+  /**
    * Sets a tab's contents via HTML.
    * 
    * Use care when setting an object's HTML; it is an easy way to expose
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
index c9c95ab..c109008 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
@@ -881,6 +881,10 @@
   cursor: default;
   background: #bcbcbc;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #999999;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -990,6 +994,10 @@
   background: #bcbcbc url(images/hborder.png) repeat-x 0px -2511px;
   color: white;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #999999;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
index f6b3ed3..3e46467 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
@@ -881,6 +881,10 @@
   cursor: default;
   background: #bcbcbc;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #999999;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -990,6 +994,10 @@
   background: #bcbcbc url(images/hborder.png) repeat-x 0px -2511px;
   color: white;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #999999;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
index 7be80e9..8e38b61 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
@@ -783,6 +783,10 @@
   color: black;
   background: #00CCFF;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #777777;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -891,6 +895,10 @@
   color: black;
   background: #00CCFF;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #777777;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
index 8a27178..4c27422 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
@@ -783,6 +783,10 @@
   color: black;
   background: #00CCFF;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #777777;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -891,6 +895,10 @@
   color: black;
   background: #00CCFF;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #777777;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
index 256d82a..aecc9f8 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
@@ -881,6 +881,10 @@
   cursor: default;
   background: #92c1f0;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #999999;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -989,6 +993,10 @@
   cursor: default;
   background: #92c1f0;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #999999;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
index c0d076e..6cecc14 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
@@ -881,6 +881,10 @@
   cursor: default;
   background: #92c1f0;
 } 
+.gwt-TabBar .gwt-TabBarItem-disabled {
+  cursor: default;
+  color: #999999;
+}
 .gwt-TabPanel {
 }
 .gwt-TabPanelBottom {
@@ -989,6 +993,10 @@
   cursor: default;
   background: #92c1f0;
 }
+.gwt-DecoratedTabBar .gwt-TabBarItem-disabled .tabMiddleCenter {
+  cursor: default;
+  color: #999999;
+}
 
 .gwt-TextArea {
   padding: 2px;
diff --git a/user/test/com/google/gwt/user/client/ui/TabBarTest.java b/user/test/com/google/gwt/user/client/ui/TabBarTest.java
index 9b99077..0c4bed9 100644
--- a/user/test/com/google/gwt/user/client/ui/TabBarTest.java
+++ b/user/test/com/google/gwt/user/client/ui/TabBarTest.java
@@ -54,6 +54,19 @@
     UIObjectTest.assertDebugId("myBar-tab-wrapper2", DOM.getChild(tr, 3));
   }
 
+  public void testEnableDisable() {
+    final TabBar bar = createTabBar();
+    bar.addTab("foo");
+    bar.addTab("bar");
+    bar.addTab("baz");
+
+    assertTrue(bar.isTabEnabled(1));
+    bar.setTabEnabled(1, false);
+    assertFalse(bar.isTabEnabled(1));
+    bar.setTabEnabled(1, true);
+    assertTrue(bar.isTabEnabled(1));
+  }
+
   public void testSelect() {
     // Create a tab bar with three items.
     final TabBar bar = createTabBar();