// Smartgwt does not currently offer the ability to hide a Tab (why!) so we fake it here.  This
  // allows us to keep
  // the Tab structure in place while removing it from the TabSet
  public void setTabHidden(TwoLevelTab tab, boolean hidden) {
    if (hidden) {
      if (hiddenTabs.containsKey(tab.getLocatorId())) {
        return;
      }

      TwoLevelTab visiblePrevious = findClosestVisiblePredecessor(tab);
      if (visiblePrevious == null) {
        // if visiblePrevious is null then that means we are updating
        // then head. Note that as of now (02/21/2012), the visible head,
        // the summary tab, is fixed, so we don't really need to worry
        // about updating the head; however, doing so will make it easier
        // to support things like hiding arbitrary tabs or reordering tabs.
        head = tab.getVisibleNext();

      } else {
        visiblePrevious.setVisibleNext(tab.getVisibleNext());
        // check to see if the tail needs to be updated. If the
        // following check is true, then that means visiblePrevious is
        // now the tail.
        if (visiblePrevious.getVisibleNext() == null) {
          tail = visiblePrevious;
        }
      }
      tab.setVisibleNext(null);
      // Note that removing the tab does *not* destroy its content pane
      // since we set the destroyPanes property to false in the
      removeTab(tab);
      hiddenTabs.put(tab.getLocatorId(), tab);
    } else {
      if (!hiddenTabs.containsKey(tab.getLocatorId())) {
        return;
      }

      hiddenTabs.remove(tab.getLocatorId());
      TwoLevelTab successor = findClosestVisibleSuccessor(tab);
      if (successor == null) {
        // if successor is null then that means we are updating the tail
        tail.setVisibleNext(tab);
        tail = tab;
        addTab(tab);
      } else {
        TwoLevelTab visiblePrevious = findClosestVisiblePredecessor(successor);
        tab.setVisibleNext(visiblePrevious.getVisibleNext());
        visiblePrevious.setVisibleNext(tab);
        addTab(tab, (getTabNumber(visiblePrevious.getID()) + 1));
      }
    }
  }
 /**
  * This method initializes the head and tail pointers. Then it initializes the {@link
  * TwoLevelTab#getActualNext actualNext} and {@link TwoLevelTab#getVisibleNext visibleNext}
  * properties of each tab. This list is built so that when hiding and showing tabs, the tab order
  * remains consistent. The order of the list is the same as the order of the tabs passed to {@link
  * #setTabs(TwoLevelTab...)}
  */
 private void buildTabList() {
   TwoLevelTab[] tabs = getTabs();
   head = tabs[0];
   tail = tabs[tabs.length - 1];
   TwoLevelTab current = head;
   for (int i = 1; i < tabs.length; ++i) {
     current.setActualNext(tabs[i]);
     current.setVisibleNext(tabs[i]);
     current = tabs[i];
   }
 }