001package com.hfg.html.custom;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005import java.util.List;
006import java.awt.*;
007
008import com.hfg.html.Div;
009import com.hfg.html.HTMLTag;
010import com.hfg.html.Span;
011import com.hfg.html.Table;
012import com.hfg.html.Td;
013import com.hfg.html.Tr;
014import com.hfg.html.HTML;
015import com.hfg.xml.XMLTag;
016import com.hfg.xml.XMLUtil;
017import com.hfg.graphics.ColorUtil;
018import com.hfg.util.Orientation;
019
020//------------------------------------------------------------------------------
021/**
022 Convenience class for constructing a tabbed pane set.
023 <div>
024 See <a href='doc-files/TabbedPaneTest.html' target='_parent'>this page</a> for examples.
025 </div>
026 <div>
027 Example:
028 <pre>
029     HTMLDoc doc = new HTMLDoc();
030     HTML html = new HTML();
031     doc.setRootTag(html);
032
033     // Add the CSS classes needed for the tabs
034     html.getHead().addStyle(TabbedPaneSet.generateCSS());
035     // Add the javascript needed for the tabs
036     html.getHead().addJavascript(TabbedPaneSet.generateJavascript());
037
038     TabbedPaneSet tabSet1 = new TabbedPaneSet();
039     tabSet1.addTab("Tab 1", new InputButton("Button 1"));
040     tabSet1.addTab("Tab 2", new InputText("foo", "bar"));
041     tabSet1.addTab("Tab 3", new Span("pane3");
042
043     Body body = html.getBody();
044     // Set the onload to initialize the tabs
045     body.setOnLoad(tabSet1.generateOnLoad());
046
047     body.addSubtag(tabSet1);
048
049 </pre>
050 </div>
051 @author J. Alex Taylor, hairyfatguy.com
052 */
053//------------------------------------------------------------------------------
054// com.hfg XML/HTML Coding Library
055//
056// This library is free software; you can redistribute it and/or
057// modify it under the terms of the GNU Lesser General Public
058// License as published by the Free Software Foundation; either
059// version 2.1 of the License, or (at your option) any later version.
060//
061// This library is distributed in the hope that it will be useful,
062// but WITHOUT ANY WARRANTY; without even the implied warranty of
063// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
064// Lesser General Public License for more details.
065//
066// You should have received a copy of the GNU Lesser General Public
067// License along with this library; if not, write to the Free Software
068// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
069//
070// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
071// jataylor@hairyfatguy.com
072//------------------------------------------------------------------------------
073
074public class TabbedPaneSet extends Div
075{
076   private String      mSetId;
077   private Table       mLabelTable;
078   private Div         mPaneDiv;
079   private String      mSelectedTabId;
080   private Orientation mOrientation;
081   private boolean     mRoundedTabs = true;
082
083   private static Font   sDefaultLabelFont = new Font("Ariel", Font.PLAIN, 10);
084   private static Color  sDefaultSelectedTabColor = Color.decode("#6666ff");
085   private static Color  sDefaultUnselectedTabColor = Color.decode("#c0c0ff");
086   private static Color  sDefaultSelectedTabFontColor = Color.decode("#ffffff");
087   private static Color  sDefaultUnselectedTabFontColor = Color.decode("#2b4353");
088   private static Orientation sDefaultOrientation = Orientation.HORIZONAL;
089   private static int    sSetCount = 0;
090   private static int    sTabCount = 0;
091
092   // CSS classes
093   private static final String TAB_PANE_SET = "tabPaneSet";
094   private static final String TAB_LABELS   = "tabLabels";
095   private static final String TAB_PANES    = "tabPanes";
096   private static final String HORIZ_TAB    = "tab tab-horiz";
097   private static final String VERT_TAB     = "";
098
099   //##########################################################################
100   // CONSTRUCTORS
101   //##########################################################################
102
103   //--------------------------------------------------------------------------
104   public TabbedPaneSet()
105   {
106      this(sDefaultOrientation);
107   }
108
109   //--------------------------------------------------------------------------
110   public TabbedPaneSet(Orientation inOrientation)
111   {
112      super();
113
114      mOrientation = inOrientation;
115
116      sSetCount++;
117      mSetId = "tabPaneSet" + sSetCount + "_" + (horizontal() ? "h" : "v");
118      setId(mSetId);
119
120      // The enclosing table keeps the panes from expanding the width too far.
121      Table enclosingTable = addTable().setClass(TAB_PANE_SET);
122      Tr row  = enclosingTable.addRow();
123      Td cell = row.addCell();
124
125
126      mLabelTable = cell.addTable().setClass(TAB_LABELS).setId(mSetId + '_' + TAB_LABELS);
127      if (horizontal())
128      {
129         mLabelTable.addRow();
130         mPaneDiv = cell.addDiv().setClass(TAB_PANES);
131      }
132      else
133      {
134         mPaneDiv = row.addCell().addDiv().setClass(TAB_PANES).addDiv();
135      }
136
137      mPaneDiv.setId(mSetId + "_" + TAB_PANES);
138   }
139
140   //##########################################################################
141   // PUBLIC METHODS
142   //##########################################################################
143
144
145   //--------------------------------------------------------------------------
146   public static void setDefaultLabelFont(Font inValue)
147   {
148      sDefaultLabelFont = inValue;
149   }
150
151   //--------------------------------------------------------------------------
152   public static void setDefaultSelectedTabColor(Color inValue)
153   {
154      sDefaultSelectedTabColor = inValue;
155   }
156
157   //--------------------------------------------------------------------------
158   public static void setDefaultUnselectedTabColor(Color inValue)
159   {
160      sDefaultUnselectedTabColor = inValue;
161   }
162
163   //--------------------------------------------------------------------------
164   public static void setDefaultSelectedTabFontColor(Color inValue)
165   {
166      sDefaultSelectedTabFontColor = inValue;
167   }
168
169   //--------------------------------------------------------------------------
170   public static void setDefaultUnselectedTabFontColor(Color inValue)
171   {
172      sDefaultUnselectedTabFontColor = inValue;
173   }
174
175   //--------------------------------------------------------------------------
176   public static String generateCSS()
177   {
178      StringBuffer css = new StringBuffer("\n");
179
180      css.append(".tab {\n"
181                 + "   background-color: #" + ColorUtil.colorToHex(sDefaultUnselectedTabColor) + ";\n"
182                 + "   color: #" + ColorUtil.colorToHex(sDefaultUnselectedTabFontColor) + ";\n"
183                 + "   text-decoration: none;\n"
184                 + "   cursor: default;\n"
185                 + "   border-right:1px solid #" + ColorUtil.colorToHex(sDefaultSelectedTabColor) + ";\n"
186                 + "   padding: 2px 4px 1px 4px;\n"
187                 + "   margin: 0px 1px;\n"
188                 + "   display: block;\n"
189                 + "   }\n\n");
190
191      css.append(".tab-horiz {\n"
192                 + "   margin: 0px 1px;\n"
193                 + "   }\n\n");
194
195      css.append(".tab-vert {\n"
196                 + "   margin: 0px 0px;\n"
197                 + "   }\n\n");
198
199      css.append(".tab-selected {\n"
200                 + "   background-color: #" + ColorUtil.colorToHex(sDefaultSelectedTabColor) + ";\n"
201                 + "   color: #" + ColorUtil.colorToHex(sDefaultSelectedTabFontColor) + ";\n"
202                 + "   }\n\n");
203
204
205      css.append(".tab:hover {\n"
206                 + "   color: #" + ColorUtil.colorToHex(sDefaultSelectedTabFontColor) + ";\n"
207                 + "   }\n\n");
208
209
210      css.append("table." + TAB_PANE_SET + " {\n"
211                 + "   padding: 0px;\n"
212                 + "   border-collapse: collapse;\n"
213            //     + "   table-layout: fixed;\n"
214                 + "   }\n\n");
215
216      css.append("table." + TAB_PANE_SET + " td {\n"
217                 + "   padding: 0px;\n"
218                 + "   vertical-align: top\n"
219                 + "   }\n\n");
220
221
222      css.append("table." + TAB_LABELS + " {\n"
223                 + "   font-family: '" + sDefaultLabelFont.getName()
224                                       + (!sDefaultLabelFont.getName().equals(sDefaultLabelFont.getFamily()) ? "', '" + sDefaultLabelFont.getFamily() : "")
225                                       + "', sans-serif;\n"
226                 + "   font-size: " + sDefaultLabelFont.getSize() + "pt;\n"
227                 + "   padding: 0px;\n"
228                 + "   border-collapse: collapse\n"
229                 + "   }\n\n");
230
231      css.append("table." + TAB_LABELS + " td {\n"
232                 + "   padding: 0px;\n"
233                 + "   }\n\n");
234
235
236      css.append("." + TAB_PANES + " {\n"
237                 + "   border: solid #" + ColorUtil.colorToHex(sDefaultUnselectedTabColor) + ";\n"
238                 + "   border-width: 1px;\n"
239                 + "   padding: 3px;\n"
240                 + "   }\n\n");
241
242      // For rounding the corners of the tabs.
243      css.append(".rndS1, .rndS2, .rndS3, .rndS4, .rndU1, .rndU2, .rndU3, .rndU4 {\n"
244                 + "   border: 0px;\n"
245                 + "   border-right:1px solid #" + ColorUtil.colorToHex(sDefaultSelectedTabColor) + ";\n"
246                 + "   height: 1px;\n"
247                 + "   padding: 0px;\n"
248                 + "   display: block;\n"  /////////////
249                 + "   overflow: hidden;\n"  /////////////
250                 + "   }\n\n"
251                 + ".rndS1, .rndS2, .rndS3, .rndS4 {\n"
252                 + "   background-color: #" + ColorUtil.colorToHex(sDefaultSelectedTabColor) + ";\n"
253                 + "   }\n\n"
254                 + ".rndU1, .rndU2, .rndU3, .rndU4 {\n"
255                 + "   background-color: #" + ColorUtil.colorToHex(sDefaultUnselectedTabColor) + ";\n"
256                 + "   }\n\n"
257                 + ".rndHzS4, .rndHzU4 { margin: 0px 1px; height: 1px; }\n"
258                 + ".rndHzS3, .rndHzU3 { margin: 0px 2px; }\n"
259                 + ".rndHzS2, .rndHzU2 { margin: 0px 3px; }\n"
260                 + ".rndHzS1, .rndHzU1 { margin: 0px 5px; }\n"
261                 + ".rndVertS4, .rndVertU4 { margin: 0px 0px 0px 1px; height: 1px; }\n"
262                 + ".rndVertS3, .rndVertU3 { margin: 0px 0px 0px 2px; }\n"
263                 + ".rndVertS2, .rndVertU2 { margin: 0px 0px 0px 3px; }\n"
264                 + ".rndVertS1, .rndVertU1 { margin: 0px 0px 0px 5px; }\n\n");
265
266
267      // Work around for IE margin issues
268      // Kinda kludgy but so is IE.
269      XMLTag styleTag = new XMLTag(HTML.STYLE);
270      styleTag.setAttribute(HTML.TYPE, "text/css");
271
272      css.append(XMLUtil.composeEndTag(styleTag.getTagName())
273                 + "\n\n<!--[if IE]>\n"
274                 + XMLUtil.composeStartTag(styleTag.getTagName(), styleTag.getAttributes()) + "\n"
275                 + ".rndS1, .rndS2, .rndS3, .rndS4, .rndU1, .rndU2, .rndU3, .rndU4 {\n"
276                 + "   margin-bottom: -2px;\n"
277                 + "   }\n"
278                 + XMLUtil.composeEndTag(styleTag.getTagName()) + "\n"
279                 + "<![endif]-->\n\n"
280                 + XMLUtil.composeStartTag(styleTag.getTagName(), styleTag.getAttributes()));
281
282
283      return css.toString();
284   }
285
286
287   //--------------------------------------------------------------------------
288   public static String generateJavascript()
289   {
290      StringBuffer js = new StringBuffer();
291
292      js.append("var tabPaneSets = new Array();\n\n");
293
294      js.append("function TabPaneSet()\n"
295                + "{\n"
296                + "  this.labels = new Array();\n"
297                + "  this.labelEdges = new Array();\n" // Div's for rounded corners
298                + "  this.panes = new Array();\n"
299                + "  this.orientation;\n"
300                + "  this.paneDiv;\n" // Div holding the content panes
301                + "}\n\n");
302
303        js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
304                + "TabPaneSet.prototype.adjustSize = function()\n"
305                + "{\n"
306                + "  var maxHeight = 0;\n"
307                + "  var maxWidth  = 0;\n"
308                // Force a recalculation of the nax natural content size
309                + "  this.paneDiv.style.height = null;\n"
310                + "  this.paneDiv.style.width  = null;\n"
311                + "  \n"
312                + "  for (var paneIndex=0; paneIndex < this.panes.length; paneIndex++)\n"
313                + "  {\n"
314                + "    var pane = this.panes[paneIndex];\n"
315                + "    var hiding = false;\n"
316                + "    if (pane.style.display == 'none')\n"
317                + "    {\n"
318                + "      hiding = true;\n"
319                + "      pane.style.visibility = 'hidden';\n"
320                + "      pane.style.display    = 'block';\n"
321                + "    }\n"
322                + "    if (pane.offsetHeight > maxHeight) maxHeight = pane.offsetHeight;\n"
323                + "    if (pane.offsetWidth > maxWidth) maxWidth = pane.offsetWidth;\n"
324//                + "alert('offsetWidth: ' + pane.offsetWidth + ', pixelWidth: ' + pane.pixelWidth + ', clientWidth: ' + pane.clientWidth);\n"//////////////////////////////
325                + "    if (hiding)\n"
326                + "    {\n"
327                + "      pane.style.display    = 'none';\n"
328                + "      pane.style.visibility = 'visible';\n"
329                + "    }\n"
330                + "  }\n"
331                + "  \n"
332                + "  this.paneDiv.style.height = maxHeight + 'px';\n"
333                + "  this.paneDiv.style.width  = maxWidth + 'px';\n"
334                + "}\n");
335
336        js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
337                + "TabPaneSet.prototype.switchTab = function(inPaneId)\n"
338                + "{\n"
339                + "  // First, hide the unselected panes.\n"
340                + "  for (var paneIndex=0; paneIndex < this.panes.length; paneIndex++)\n"
341                + "  {\n"
342                + "    var pane = this.panes[paneIndex];\n"
343                + "    if (pane.id != 'pane' + inPaneId) pane.style.display = 'none';\n"
344                + "  }\n"
345                + "  \n"
346                + "  // Now display the selected pane.\n"
347                + "  for (var paneIndex=0; paneIndex < this.panes.length; paneIndex++)\n"
348                + "  {\n"
349                + "    var pane = this.panes[paneIndex];\n"
350                + "    if (pane.id == 'pane' + inPaneId) pane.style.display = 'block';\n"
351                + "  }\n"
352                + "  \n"
353                + "  for (var labelIndex=0; labelIndex < this.labels.length; labelIndex++)\n"
354                + "  {\n"
355                + "    var label = this.labels[labelIndex];\n"
356                + "    label.className = (label.id == 'tab' + inPaneId ? 'tab tab-selected' : 'tab')\n"
357                + "                      + (this.orientation == 'horiz' ? ' tab-horiz' : ' tab-vert');\n"
358                + "    for (var i = 0; i < this.labelEdges[labelIndex].length; i++)\n"
359                + "    {\n"
360                + "       var suffix = this.labelEdges[labelIndex][i].className.charAt(this.labelEdges[labelIndex][i].className.length - 1);\n"
361                + "       this.labelEdges[labelIndex][i].className = 'rnd' + (label.id == 'tab' + inPaneId ? 'S': 'U') + suffix\n"
362                + "                                                        + ' rnd' + (this.orientation == 'horiz' ? 'Hz' : 'Vert')\n"
363                + "                                                        + (label.id == 'tab' + inPaneId ? 'S': 'U') + suffix;\n"
364                + "    }\n"
365                + "  }\n"
366                + "}\n\n");
367
368      js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
369                + "function setupTabPaneSet(inSetId, inSelectedTabId)\n"
370                + "{\n"
371                + "  var tabPaneSet = new TabPaneSet();\n"
372                + "  tabPaneSets[inSetId] = tabPaneSet;\n"
373                + "  tabPaneSet.orientation = (inSetId.match(/_h$/) ? 'horiz' : 'vert');\n"
374                + "  \n"
375                + "  // Extract the labels\n"
376                + "  var labelTable = document.getElementById(inSetId + '_" + TAB_LABELS + "');\n"
377                + "  var cells = labelTable.getElementsByTagName('td');\n"
378                + "  for (var cellIndex = 0; cellIndex < cells.length; cellIndex++)\n"
379                + "  {\n"
380                + "     var cell = cells[cellIndex];\n"
381                + "     var labels = cell.getElementsByTagName('span');\n"
382                + "     for (var i=0; i < labels.length; i++)\n"
383                + "     {\n"
384                + "        var label = labels[i];\n"
385                + "        if (label.id && label.id.indexOf('tab') == 0)\n"
386                + "        {\n"
387                + "           tabPaneSet.labels[tabPaneSet.labels.length] = label;\n"
388                + "           tabPaneSet.labelEdges[tabPaneSet.labelEdges.length] = cell.getElementsByTagName('div');\n"
389                + "        }\n"
390                + "     }\n"
391                + "  }\n"
392                + "  \n"
393                + "  // Extract the panes\n"
394                + "  tabPaneSet.paneDiv = document.getElementById(inSetId + '_" + TAB_PANES + "');\n"
395                + "  var panes = tabPaneSet.paneDiv.getElementsByTagName('div');\n"
396                + "  for (var paneIndex=0; paneIndex < panes.length; paneIndex++)\n"
397                + "  {\n"
398                + "    var pane = panes[paneIndex];\n"
399                + "    if (pane.parentNode != tabPaneSet.paneDiv || !pane.id || !pane.id.match(/^pane/)) continue;\n"
400                + "    tabPaneSet.panes[tabPaneSet.panes.length] = pane;\n"
401                + "  }\n"
402                + "  \n"
403                + "  tabPaneSet.adjustSize();\n" // TabbedPaneSet needs to be large enough to accomodate the largest pane.
404                + "  \n"
405                + "  document.getElementById(inSelectedTabId).parentNode.onclick();\n"
406                + "}\n\n");
407
408      js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
409                + "function switchTab(inPaneSetId, inPaneId)\n"
410                + "{\n"
411                + "  var tabPaneSet = tabPaneSets[inPaneSetId];\n"
412                + "  if (!tabPaneSet)\n"
413                + "  {\n"
414                + "     alert('Programming Error!\\ngenerateOnLoad() for this tab pane set was not added to the body.onLoad() during html generation!\\nSee the example in the javadoc.');\n"
415                + "     return;\n"
416                + "  }\n"
417                + "  \n"
418                + "  tabPaneSet.switchTab(inPaneId);\n"
419                + "  \n"
420                + "}\n\n");
421
422      js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
423                + "function resizeTabPanes(inPaneSetId)\n"
424                + "{\n"
425                + "  var tabPaneSet = tabPaneSets[inPaneSetId];\n"
426                + "  if (!tabPaneSet)\n"
427                + "  {\n"
428                + "     alert('Programming Error!\\ngenerateOnLoad() for this tab pane set was not added to the body.onLoad() during html generation!\\nSee the example in the javadoc.');\n"
429                + "     return;\n"
430                + "  }\n"
431                + "  \n"
432                + "  tabPaneSet.adjustSize();\n"
433                + "  \n"
434                + "}\n\n");
435
436
437      return js.toString();
438   }
439
440   //--------------------------------------------------------------------------
441   @Override
442   public String getId()
443   {
444      return mSetId;
445   }
446
447   //--------------------------------------------------------------------------
448   /**
449    Tabs are rounded by default. Must be set before addTab() is called.
450    */
451   public TabbedPaneSet useRoundedTabs(boolean inValue)
452   {
453      mRoundedTabs = inValue;
454      return this;
455   }
456
457   //--------------------------------------------------------------------------
458   /**
459    * Createds the javascript for the body's onload() that is necessary to
460    * initialize the tabbed pane set (and any tabbed pane sets contained within it).
461    */
462   public String generateOnLoad()
463   {
464      StringBuffer buffer = new StringBuffer();
465
466      List<TabbedPaneSet> tabPaneSets = new ArrayList<TabbedPaneSet>();
467      tabPaneSets.add(this);
468
469      findNestedTabPaneSets(mPaneDiv, tabPaneSets);
470
471      for (int i = tabPaneSets.size() - 1; i >= 0; i--)
472      {
473         TabbedPaneSet paneSet = tabPaneSets.get(i);
474         buffer.append("setupTabPaneSet('" + paneSet.mSetId + "', '" + paneSet.mSelectedTabId + "');");
475      }
476
477      return buffer.toString();
478   }
479
480   //--------------------------------------------------------------------------
481   public void addTab(String inLabel, HTMLTag inPaneContent)
482   {
483      addTab(inLabel, inPaneContent, false);
484   }
485
486   //--------------------------------------------------------------------------
487   public void addTab(HTMLTag inLabel, HTMLTag inPaneContent)
488   {
489      addTab(inLabel, inPaneContent, false);
490   }
491
492   //--------------------------------------------------------------------------
493   public void addTab(String inLabel, HTMLTag inPaneContent, boolean inIsSelected)
494   {
495      addTab(new Span(inLabel), inPaneContent, inIsSelected);
496   }
497
498   //--------------------------------------------------------------------------
499   public void addTab(String inLabel, HTMLTag inPaneContent, boolean inIsSelected, String inOnClick)
500   {
501      addTab(new Span(inLabel), inPaneContent, inIsSelected, inOnClick);
502   }
503
504   //--------------------------------------------------------------------------
505   public void addTab(HTMLTag inLabel, HTMLTag inPaneContent, boolean inIsSelected)
506   {
507      addTab(new Span(inLabel), inPaneContent, inIsSelected, null);
508   }
509
510   //--------------------------------------------------------------------------
511   public void addTab(HTMLTag inLabel, HTMLTag inPaneContent, boolean inIsSelected, String inOnClick)
512   {
513      sTabCount++;
514
515      Td cell = null;
516      if (horizontal())
517      {
518         cell = mLabelTable.getRows().get(0).addCell();
519      }
520      else // VERTICAL
521      {
522         cell = mLabelTable.addRow().addCell();
523      }
524
525      // Runs thru the switchTab function to get a better error msg if generateOnLoad() wasn't done.
526      cell.setOnClick((inOnClick != null ? inOnClick + ";" : "")
527                      + "switchTab('" + mSetId + "', '" + sTabCount + "');");
528
529      if (mRoundedTabs)
530      {
531/*      Wanted to use hr but stoopid IE gives them some crazy unalterable vertical margins.
532         cell.addSubtag(new Hr().setClass("u1"));
533         cell.addSubtag(new Hr().setClass("u2"));
534         cell.addSubtag(new Hr().setClass("u3"));
535         cell.addSubtag(new Hr().setClass("u4"));
536*/
537         // For some reason the empty tag renders differently (wrong) compared to the empty tag pair
538         cell.addDiv().setClass("rndU1 " + (horizontal() ? "rndHzU1" : "rndVertU1")).setContent("");
539         cell.addDiv().setClass("rndU2 " + (horizontal() ? "rndHzU2" : "rndVertU2")).setContent("");
540         cell.addDiv().setClass("rndU3 " + (horizontal() ? "rndHzU3" : "rndVertU3")).setContent("");
541         cell.addDiv().setClass("rndU4 " + (horizontal() ? "rndHzU4" : "rndVertU4")).setContent("");
542
543      }
544
545      Span tab = cell.addSpan(inLabel);
546      String tabId = "tab" + sTabCount;
547      tab.setId(tabId);
548      tab.setClass(horizontal() ? HORIZ_TAB : VERT_TAB);
549
550      if (mRoundedTabs
551          && !horizontal())
552      {
553         // For some reason the empty tag renders differently (wrong) compared to the empty tag pair
554         cell.addDiv().setClass("rndU4 rndVertU4").setContent("");
555         cell.addDiv().setClass("rndU3 rndVertU3").setContent("");
556         cell.addDiv().setClass("rndU2 rndVertU2").setContent("");
557         cell.addDiv().setClass("rndU1 rndVertU1").setStyle("border-bottom:1px solid #" + ColorUtil.colorToHex(sDefaultSelectedTabColor)).setContent("");
558      }
559
560      mPaneDiv.addDiv(inPaneContent).setId("pane" + sTabCount);
561
562      if (null == mSelectedTabId || inIsSelected) mSelectedTabId = tabId;
563   }
564
565   //##########################################################################
566   // PRIVATE METHODS
567   //##########################################################################
568
569   //--------------------------------------------------------------------------
570   private boolean horizontal()
571   {
572      return mOrientation == Orientation.HORIZONAL;
573   }
574
575   //--------------------------------------------------------------------------
576   private void findNestedTabPaneSets(XMLTag inCurrentTag, List inTabPaneSetList)
577   {
578      // Find any nested tabpane sets
579      Iterator iter = inCurrentTag.getSubtags().iterator();
580      while (iter.hasNext())
581      {
582         XMLTag tag = (XMLTag) iter.next();
583         if (tag instanceof TabbedPaneSet)
584         {
585            inTabPaneSetList.add(tag);
586         }
587         findNestedTabPaneSets(tag, inTabPaneSetList);
588      }
589   }
590
591}