001: /*
002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003: *
004: * "The contents of this file are subject to the Mozilla Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
011: * License for the specific language governing rights and limitations under
012: * the License.
013: *
014: * The Original Code is ICEfaces 1.5 open source software code, released
015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
018: *
019: * Contributor(s): _____________________.
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
023: * License), in which case the provisions of the LGPL License are
024: * applicable instead of those above. If you wish to allow use of your
025: * version of this file only under the terms of the LGPL License and not to
026: * allow others to use your version of this file under the MPL, indicate
027: * your decision by deleting the provisions above and replace them with
028: * the notice and other provisions required by the LGPL License. If you do
029: * not delete the provisions above, a recipient may use your version of
030: * this file under either the MPL or the LGPL License."
031: *
032: */
033:
034: package com.icesoft.faces.component.paneltabset;
035:
036: import com.icesoft.faces.component.CSS_DEFAULT;
037: import com.icesoft.faces.component.ext.taglib.Util;
038: import com.icesoft.faces.component.panelseries.UISeries;
039: import com.icesoft.faces.component.util.CustomComponentUtils;
040: import com.icesoft.faces.context.DOMContext;
041: import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer;
042: import com.icesoft.faces.renderkit.dom_html_basic.FormRenderer;
043: import com.icesoft.faces.renderkit.dom_html_basic.HTML;
044: import com.icesoft.faces.util.CoreUtils;
045: import com.icesoft.faces.util.DOMUtils;
046: import org.apache.commons.logging.Log;
047: import org.apache.commons.logging.LogFactory;
048: import org.w3c.dom.Element;
049: import org.w3c.dom.Text;
050:
051: import javax.faces.FacesException;
052: import javax.faces.component.NamingContainer;
053: import javax.faces.component.UIComponent;
054: import javax.faces.component.UIForm;
055: import javax.faces.component.UINamingContainer;
056: import javax.faces.component.UIParameter;
057: import javax.faces.component.UIViewRoot;
058: import javax.faces.context.FacesContext;
059: import java.beans.Beans;
060: import java.io.IOException;
061: import java.util.HashMap;
062: import java.util.Iterator;
063: import java.util.List;
064: import java.util.Map;
065:
066: /**
067: * <p>PanelTabSetRenderer extends DomBasicRenderer and is responsible for
068: * rendering PanelTabSet and PanelTab components.</p>
069: */
070: public class PanelTabSetRenderer extends DomBasicRenderer
071:
072: {
073: // hidden field for the tab links
074: private static final String HIDDEN_FIELD_NAME = "cl";
075:
076: private static final Log log = LogFactory
077: .getLog(PanelTabSetRenderer.class);
078: private static final String SPACER_IMG = "/xmlhttp/css/xp/css-images/spacer.gif";
079:
080: /* (non-Javadoc)
081: * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
082: */
083: public void encodeBegin(FacesContext facesContext,
084: UIComponent uiComponent) throws IOException {
085: }
086:
087: /* (non-Javadoc)
088: * @see javax.faces.render.Renderer#getRendersChildren()
089: */
090: public boolean getRendersChildren() {
091: return true;
092: }
093:
094: /* (non-Javadoc)
095: * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
096: */
097: public void encodeChildren(FacesContext facescontext,
098: UIComponent uicomponent) throws IOException {
099: }
100:
101: /* (non-Javadoc)
102: * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
103: */
104: public void encodeEnd(FacesContext facesContext,
105: UIComponent uiComponent) throws IOException {
106: validateParameters(facesContext, uiComponent, PanelTabSet.class);
107: // get DOMContext using DOMContext static method getDOMContext
108: DOMContext domContext = DOMContext.attachDOMContext(
109: facesContext, uiComponent);
110: // if the domContext has not been initialized
111: // initialize it, create the Root Element
112: if (!domContext.isInitialized()) {
113: Element table = domContext
114: .createRootElement(HTML.TABLE_ELEM);
115: table.setAttribute(HTML.CELLPADDING_ATTR, "0");
116: table.setAttribute(HTML.CELLSPACING_ATTR, "0");
117: setRootElementId(facesContext, table, uiComponent);
118: }
119:
120: FormRenderer.addHiddenField(facesContext,
121: deriveCommonHiddenFieldName(facesContext, uiComponent));
122:
123: PanelTabSet tabSet = (PanelTabSet) uiComponent;
124: String baseClass = tabSet.getStyleClass();
125:
126: int selectedIndex = tabSet.getSelectedIndex();
127:
128: // get the parentForm
129: UIComponent parentForm = findForm(tabSet);
130: // if there is no parent form - ERROR
131: if (parentForm == null) {
132: if (log.isErrorEnabled()) {
133: log.error(" TabbedPane::must be in a FORM");
134: }
135: return;
136: }
137:
138: if (tabSet.getValue() != null) {
139: if (tabSet.getChildCount() < 1) {
140: if (log.isErrorEnabled()) {
141: log
142: .error(" TabbedPane:a panelTab element is required");
143: }
144: return;
145: }
146:
147: if (tabSet.getChildCount() > 1
148: || !(tabSet.getChildren().get(0) instanceof PanelTab)) {
149: if (log.isErrorEnabled()) {
150: log
151: .error(" TabbedPane::only one panelTab element allowed when using value atttibute");
152: }
153: return;
154: }
155: }
156:
157: // get table
158: Element table = (Element) domContext.getRootNode();
159: // render table pass thru attributes
160: for (int i = 0; i < HTML.TABLE_PASSTHROUGH_ATTRIBUTES.length; i++) {
161: if (HTML.TABLE_PASSTHROUGH_ATTRIBUTES[i]
162: .equalsIgnoreCase("styleClass")) {
163: renderAttribute(tabSet, table,
164: HTML.TABLE_PASSTHROUGH_ATTRIBUTES[i],
165: HTML.CLASS_ATTR);
166: } else {
167: renderAttribute(tabSet, table,
168: HTML.TABLE_PASSTHROUGH_ATTRIBUTES[i],
169: HTML.TABLE_PASSTHROUGH_ATTRIBUTES[i]);
170: }
171: }
172:
173: // table.removeAttribute(HTML.BGCOLOR_ATTR);
174:
175: // clean out children
176: DOMContext.removeChildrenByTagName(table, HTML.TR_ELEM);
177: // create a new table row for the Tab Header Cell
178: Element headerRow = domContext.createElement(HTML.TR_ELEM);
179:
180: // Create Tab headers
181: int tabIdx = 0;
182: int visibleTabCount = 0;
183: List children = tabSet.getChildren();
184:
185: // check tabPlacement
186: // default is Top
187: // if tabPlacement is Bottom
188: // render Tab Cell first then Tab Header
189:
190: List tabList = null;
191: if (tabSet.getValue() != null) {
192: tabList = (List) tabSet.getValue();
193: }
194: if (tabSet.getTabPlacement().equalsIgnoreCase(
195: PanelTabSet.TABPLACEMENT_BOTTOM)) {
196:
197: if (tabList != null) {
198: visibleTabCount = tabList.size();
199: } else {
200: // determine visibleTabCount
201: for (int i = 0, len = children.size(); i < len; i++) {
202: UIComponent child = getUIComponent((UIComponent) children
203: .get(i));
204: if (child instanceof PanelTab) {
205: if (child.isRendered()) {
206: visibleTabCount++;
207: }
208: }
209: }
210: }
211: // Create Tab Cells
212: // create a new table row Element for the Tab Content Cells
213: Element contentRow = domContext.createElement(HTML.TR_ELEM);
214: // append the tab content table row Element to the table
215: table.appendChild(contentRow);
216: table.appendChild(headerRow);
217: Element headerTd = domContext.createElement(HTML.TD_ELEM);
218: headerRow.appendChild(headerTd);
219: Element tabsTable = domContext
220: .createElement(HTML.TABLE_ELEM);
221: tabsTable.setAttribute(HTML.CELLPADDING_ATTR, "0");
222: tabsTable.setAttribute(HTML.CELLSPACING_ATTR, "0");
223: headerTd.appendChild(tabsTable);
224: Element tabsTableRow = domContext
225: .createElement(HTML.TR_ELEM);
226: tabsTable.appendChild(tabsTableRow);
227:
228: contentRow.setAttribute(HTML.HEIGHT_ATTR, "100%");
229: // call the writeTabCell method
230: // pass in the new table row Element tr3
231: writeTabCell(domContext, facesContext, tabSet,
232: visibleTabCount, selectedIndex, contentRow, tabSet);
233: if (tabSet.getValue() != null) {
234: int rowIndex = tabSet.getFirst();
235: int rowsToBeDisplayed = tabSet.getRows();
236: int rowsDisplayed = 0;
237: tabSet.setRowIndex(rowIndex);
238:
239: while (tabSet.isRowAvailable()) {
240: if (rowsToBeDisplayed > 0
241: && rowsDisplayed >= rowsToBeDisplayed) {
242: break;
243: }
244:
245: UIComponent child = getUIComponent((UIComponent) tabSet
246: .getChildren().get(0));
247: if (child instanceof PanelTab) {
248: if (child.isRendered()) {
249: // append the header table row Element to the table
250:
251: // call the writeHeaderCell method
252: // pass in the new header table row Element
253: writeHeaderCell(domContext, facesContext,
254: tabSet, (PanelTab) child, tabIdx,
255: tabIdx == selectedIndex,
256: ((PanelTab) child).isDisabled(),
257: tabsTableRow);
258: visibleTabCount++;
259: }
260: tabIdx++;
261: }
262: rowsDisplayed++;
263: rowIndex++;
264: tabSet.setRowIndex(rowIndex);
265: }
266: tabSet.setRowIndex(-1);
267: } else {
268:
269: for (int i = 0, len = children.size(); i < len; i++) {
270: UIComponent child = getUIComponent((UIComponent) children
271: .get(i));
272: if (child instanceof PanelTab) {
273: if (child.isRendered()) {
274: // append the header table row Element to the table
275: // call the writeHeaderCell method
276: // pass in the new header table row Element
277: writeHeaderCell(domContext, facesContext,
278: tabSet, (PanelTab) child, tabIdx,
279: tabIdx == selectedIndex,
280: ((PanelTab) child).isDisabled(),
281: tabsTableRow);
282: visibleTabCount++;
283: }
284: tabIdx++;
285: }
286: }
287: }
288: // Empty tab cell on the right for better look
289: // create a new table data for the empty TextNode
290: Element td = domContext.createElement(HTML.TD_ELEM);
291: String className = tabSet.getSpacerClass();
292: td.setAttribute(HTML.CLASS_ATTR, className);
293: Text text = null;
294: if (domContext.isStreamWriting()) {
295: text = domContext.createTextNode(" ");
296: } else {
297: text = domContext.createTextNode(" ");
298: }
299: td.appendChild(text);
300: // append the empty TextNode table data to our table row Element tr1
301: tabsTableRow.appendChild(td);
302:
303: domContext.streamWrite(facesContext, tabSet);
304: // steps to the position where the next sibling should be rendered
305: domContext.stepOver();
306:
307: } else { // for now it's either Top or Bottom
308: table.appendChild(headerRow);
309: Element headerTd = domContext.createElement(HTML.TD_ELEM);
310: headerRow.appendChild(headerTd);
311: Element tabsTable = domContext
312: .createElement(HTML.TABLE_ELEM);
313: tabsTable.setAttribute(HTML.CELLPADDING_ATTR, "0");
314: tabsTable.setAttribute(HTML.CELLSPACING_ATTR, "0");
315: headerTd.appendChild(tabsTable);
316: Element tabsTableRow = domContext
317: .createElement(HTML.TR_ELEM);
318: tabsTable.appendChild(tabsTableRow);
319: if (tabSet.getValue() != null) {
320: int rowIndex = tabSet.getFirst();
321: int rowsToBeDisplayed = tabSet.getRows();
322: int rowsDisplayed = 0;
323: tabSet.setRowIndex(rowIndex);
324:
325: while (tabSet.isRowAvailable()) {
326: if (rowsToBeDisplayed > 0
327: && rowsDisplayed >= rowsToBeDisplayed) {
328: break;
329: }
330:
331: UIComponent child = getUIComponent((UIComponent) tabSet
332: .getChildren().get(0));
333: if (child instanceof PanelTab) {
334: if (child.isRendered()) {
335: // append the header table row Element to the table
336: // call the writeHeaderCell method
337: // pass in the new header table row Element
338: writeHeaderCell(domContext, facesContext,
339: tabSet, (PanelTab) child, tabIdx,
340: tabIdx == selectedIndex,
341: ((PanelTab) child).isDisabled(),
342: tabsTableRow);
343: visibleTabCount++;
344: }
345: tabIdx++;
346: }
347: rowsDisplayed++;
348: rowIndex++;
349: tabSet.setRowIndex(rowIndex);
350: }
351: tabSet.setRowIndex(-1);
352: } else {
353: for (int i = 0, len = children.size(); i < len; i++) {
354: UIComponent child = getUIComponent((UIComponent) children
355: .get(i));
356: if (child instanceof PanelTab) {
357: if (child.isRendered()) {
358: // append the header table row Element to the table
359: // call the writeHeaderCell method
360: // pass in the new header table row Element
361: writeHeaderCell(domContext, facesContext,
362: tabSet, (PanelTab) child, tabIdx,
363: tabIdx == selectedIndex,
364: ((PanelTab) child).isDisabled(),
365: tabsTableRow);
366: visibleTabCount++;
367: }
368: tabIdx++;
369: }
370: }
371: }
372: // Empty tab cell on the right for better look
373: // create a new table data for the empty TextNode
374: Element td = domContext.createElement(HTML.TD_ELEM);
375:
376: String className = tabSet.getSpacerClass();
377: td.setAttribute(HTML.CLASS_ATTR, className);
378: Text text;
379: if (domContext.isStreamWriting()) {
380: text = domContext.createTextNode(" ");
381: } else {
382: text = domContext.createTextNode(" ");
383: }
384:
385: td.appendChild(text);
386: // append the empty TextNode table data to our table row Element tr1
387: tabsTableRow.appendChild(td);
388:
389: // Create Tab Cells
390: // create a new table row Element for the Tab Cells
391: Element contentRow = domContext.createElement(HTML.TR_ELEM);
392: contentRow.setAttribute(HTML.HEIGHT_ATTR, "100%");
393: // append the table row Element to the table
394: table.appendChild(contentRow);
395: // call the writeTabCell method
396: // pass in the new table row Element tr3
397: writeTabCell(domContext, facesContext, tabSet,
398: visibleTabCount, selectedIndex, contentRow, tabSet);
399:
400: // steps to the position where the next sibling should be rendered
401: domContext.stepOver();
402: domContext.streamWrite(facesContext, tabSet);
403:
404: }
405: }
406:
407: /* (non-Javadoc)
408: * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
409: */
410: public void decode(FacesContext facesContext,
411: UIComponent uiComponent) {
412: validateParameters(facesContext, uiComponent, PanelTabSet.class);
413:
414: PanelTabSet tabSet = (PanelTabSet) uiComponent;
415: Map paramMap = facesContext.getExternalContext()
416: .getRequestParameterMap();
417: int tabIdx = 0;
418: String paramName;
419: String paramValue;
420: if (tabSet.getValue() != null) {
421: int rowIndex = tabSet.getFirst();
422: tabSet.setRowIndex(rowIndex);
423: int rowsToBeDisplayed = tabSet.getRows();
424: int rowsDisplayed = 0;
425: UIComponent child = getUIComponent((UIComponent) tabSet
426: .getChildren().get(0));
427: while (tabSet.isRowAvailable()) {
428: if (rowsToBeDisplayed > 0
429: && rowsDisplayed >= rowsToBeDisplayed) {
430: break;
431: }
432: if (child instanceof PanelTab) {
433: paramName = tabSet.getClientId(facesContext) + "."
434: + tabIdx;
435: paramValue = (String) paramMap.get(paramName);
436: if (paramValue != null && paramValue.length() > 0) {
437: tabSet.queueEvent(new TabChangeEvent(tabSet,
438: tabSet.getSelectedIndex(), tabIdx));
439: return;
440: }
441: tabIdx++;
442: }
443: rowsDisplayed++;
444: rowIndex++;
445: tabSet.setRowIndex(rowIndex);
446: }
447: tabSet.setRowIndex(-1);
448: } else {
449: List children = tabSet.getChildren();
450: for (int i = 0, len = children.size(); i < len; i++) {
451: UIComponent child = getUIComponent((UIComponent) children
452: .get(i));
453: if (child instanceof PanelTab) {
454: paramName = tabSet.getClientId(facesContext) + "."
455: + tabIdx;
456: paramValue = (String) paramMap.get(paramName);
457: if (paramValue != null && paramValue.length() > 0) {
458: tabSet.queueEvent(new TabChangeEvent(tabSet,
459: tabSet.getSelectedIndex(), tabIdx));
460: return;
461: }
462: tabIdx++;
463: }
464: }
465: }
466: }
467:
468: /**
469: * writeHeaderCell is a DOM-enabled version of the MyFaces writeHeaderCell
470: * implementation. Calls to the ResponseWriter have been substituted with
471: * DOMContext and w3c DOM API calls.
472: *
473: * @param domContext
474: * @param facesContext
475: * @param tabSet
476: * @param tab
477: * @param tabIndex
478: * @param active
479: * @param disabled
480: * @param tr
481: * @throws IOException
482: */
483: protected void writeHeaderCell(DOMContext domContext,
484: FacesContext facesContext, PanelTabSet tabSet,
485: PanelTab tab, int tabIndex, boolean active,
486: boolean disabled, Element tr) throws IOException {
487: String baseClass = tabSet.getStyleClass();
488: // create a new table data Element using the DOMContext API
489: Element td = domContext.createElement(HTML.TD_ELEM);
490: td.setAttribute(HTML.ID_ATTR, tabSet.getClientId(facesContext)
491: + "ht" + tabIndex);
492: // append the td to the tr
493: tr.appendChild(td);
494:
495: String styleClass = tab.getStyleClass();
496:
497: String label = tab.getLabel();
498:
499: if (label == null || label.length() == 0) {
500: label = "Tab " + tabIndex;
501: }
502:
503: label = DOMUtils.escapeAnsi(label);
504:
505: String tabPlacement = "";
506: if (tabSet.getTabPlacement().equalsIgnoreCase(
507: PanelTabSet.TABPLACEMENT_BOTTOM)) {
508: tabPlacement = CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_BOTTOM;
509: }
510:
511: // create a table for the tab
512: Element table = domContext.createElement(HTML.TABLE_ELEM);
513: // append the table to the td
514: td.appendChild(table);
515:
516: table.setAttribute(HTML.CELLPADDING_ATTR, "0");
517: table.setAttribute(HTML.CELLSPACING_ATTR, "0");
518:
519: // table will have 3 rows
520: Element tr_top = domContext.createElement(HTML.TR_ELEM);
521: Element tr_mid = domContext.createElement(HTML.TR_ELEM);
522: Element tr_bot = domContext.createElement(HTML.TR_ELEM);
523:
524: // each row will have 3 columns
525: Element td_top_left = domContext.createElement(HTML.TD_ELEM);
526: Element td_top_mid = domContext.createElement(HTML.TD_ELEM);
527: Element td_top_right = domContext.createElement(HTML.TD_ELEM);
528: this .renderSpacerImage(domContext, td_top_left);
529: this .renderSpacerImage(domContext, td_top_mid);
530: this .renderSpacerImage(domContext, td_top_right);
531:
532: Element td_mid_left = domContext.createElement(HTML.TD_ELEM);
533: // the command link will go in this td
534: Element td_mid_mid = domContext.createElement(HTML.TD_ELEM);
535: Element td_mid_right = domContext.createElement(HTML.TD_ELEM);
536: this .renderSpacerImage(domContext, td_mid_left);
537: this .renderSpacerImage(domContext, td_mid_right);
538:
539: Element td_bot_left = domContext.createElement(HTML.TD_ELEM);
540: Element td_bot_mid = domContext.createElement(HTML.TD_ELEM);
541: Element td_bot_right = domContext.createElement(HTML.TD_ELEM);
542: this .renderSpacerImage(domContext, td_bot_left);
543: this .renderSpacerImage(domContext, td_bot_mid);
544: this .renderSpacerImage(domContext, td_bot_right);
545:
546: String disableStyleClassSuffix;
547:
548: if (disabled) {
549: disableStyleClassSuffix = "-dis";
550: Text text = domContext.createTextNode(label);
551: td_mid_mid.appendChild(text);
552: } else {
553: disableStyleClassSuffix = "";
554: // Build a command link
555: Element link = domContext.createElement(HTML.ANCHOR_ELEM);
556: link.setAttribute(HTML.NAME_ATTR, tabSet
557: .getClientId(facesContext)
558: + "." + tabIndex);
559: link.setAttribute(HTML.ID_ATTR, tabSet
560: .getClientId(facesContext)
561: + "." + tabIndex);
562: link.setAttribute(HTML.HREF_ATTR, "#");
563: // set focus handler
564: link.setAttribute(HTML.ONFOCUS_ATTR, "setFocus(this.id);");
565: link.setAttribute(HTML.ONBLUR_ATTR, "setFocus('');");
566: td_mid_mid.appendChild(link);
567: renderLinkText(label, domContext, link, tab, tabSet);
568:
569: Map parameterMap = getParameterMap(facesContext, tab);
570: renderOnClick(facesContext, tabSet, tab, link, parameterMap);
571:
572: Iterator parameterKeys = parameterMap.keySet().iterator();
573: String nextKey;
574: while (parameterKeys.hasNext()) {
575: nextKey = (String) parameterKeys.next();
576: FormRenderer.addHiddenField(facesContext, nextKey);
577: }
578:
579: }
580: String tabStyleClass;
581: // set style class attributes
582: if (active) {
583: tabStyleClass = tab.getTabOnClass(tabPlacement);
584: table.setAttribute(HTML.CLASS_ATTR, tabStyleClass);
585: } else // inactive style with mouse over and out
586: {
587: tabStyleClass = tab.getTabOffClass(tabPlacement);
588: table.setAttribute(HTML.CLASS_ATTR, tabStyleClass);
589: if (!disabled) {
590: table.setAttribute(HTML.ONMOUSEOVER_ATTR,
591: "this.className='"
592: + tab.getTabOverClass(tabPlacement)
593: + "';");
594: table.setAttribute(HTML.ONMOUSEOUT_ATTR,
595: "this.className='"
596: + tab.getTabOffClass(tabPlacement)
597: + "';");
598: } else {
599: table.removeAttribute(HTML.ONMOUSEOVER_ATTR);
600: table.removeAttribute(HTML.ONMOUSEOUT_ATTR);
601: }
602: }
603:
604: td_top_left.setAttribute(HTML.CLASS_ATTR,
605: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_LEFT
606: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_TOP
607: + disableStyleClassSuffix);
608: td_top_mid.setAttribute(HTML.CLASS_ATTR,
609: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
610: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_TOP
611: + disableStyleClassSuffix);
612: td_top_right.setAttribute(HTML.CLASS_ATTR,
613: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_RIGHT
614: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_TOP
615: + disableStyleClassSuffix);
616:
617: td_mid_left.setAttribute(HTML.CLASS_ATTR,
618: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_LEFT
619: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
620: + disableStyleClassSuffix);
621: td_mid_mid.setAttribute(HTML.CLASS_ATTR,
622: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
623: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
624: + disableStyleClassSuffix);
625: td_mid_right.setAttribute(HTML.CLASS_ATTR,
626: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_RIGHT
627: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
628: + disableStyleClassSuffix);
629:
630: td_bot_left.setAttribute(HTML.CLASS_ATTR,
631: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_LEFT
632: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_BOTTOM
633: + disableStyleClassSuffix);
634: td_bot_mid.setAttribute(HTML.CLASS_ATTR,
635: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_MIDDLE
636: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_BOTTOM
637: + disableStyleClassSuffix);
638: td_bot_right.setAttribute(HTML.CLASS_ATTR,
639: CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_RIGHT
640: + CSS_DEFAULT.PANEL_TAB_SET_DEFAULT_BOTTOM
641: + disableStyleClassSuffix);
642:
643: tr_top.appendChild(td_top_left);
644: tr_top.appendChild(td_top_mid);
645: tr_top.appendChild(td_top_right);
646: table.appendChild(tr_top);
647:
648: tr_mid.appendChild(td_mid_left);
649: tr_mid.appendChild(td_mid_mid);
650: tr_mid.appendChild(td_mid_right);
651: table.appendChild(tr_mid);
652:
653: tr_bot.appendChild(td_bot_left);
654: tr_bot.appendChild(td_bot_mid);
655: tr_bot.appendChild(td_bot_right);
656: table.appendChild(tr_bot);
657:
658: // TODO: test passthru attributes
659: //PassThruAttributeRenderer.renderAttributes(facesContext, tab, new String[] { "onclick" });
660:
661: // append Elements using the w3c DOM API appendChild
662: if (styleClass != null) {
663: td.setAttribute(HTML.CLASS_ATTR, styleClass);
664: }
665:
666: if (tab.getTitle() != null) {
667: td.setAttribute(HTML.TITLE_ATTR, tab.getTitle());
668: }
669: }
670:
671: protected static String deriveCommonHiddenFieldName(
672: FacesContext facesContext, UIComponent uiComponent) {
673: if (Beans.isDesignTime()) {
674: return "";
675: }
676: try {
677: UIComponent parentNamingContainer = findNamingContainer(uiComponent);
678: String parentClientId = parentNamingContainer
679: .getClientId(facesContext);
680: return parentClientId + NamingContainer.SEPARATOR_CHAR
681: + UIViewRoot.UNIQUE_ID_PREFIX + HIDDEN_FIELD_NAME;
682: } catch (NullPointerException e) {
683: throw new RuntimeException(
684: "Panel Tab Set must be in a <ice:form>", e);
685: }
686: }
687:
688: /**
689: * @param linkText
690: * @param domContext
691: * @param link
692: * @param tab
693: * @param tabSet
694: */
695: private void renderLinkText(String linkText, DOMContext domContext,
696: Element link, PanelTab tab, PanelTabSet tabSet) {
697:
698: // create a new or update the old text node for the label
699: if (linkText != null && linkText.length() != 0) {
700: Text labelNode = (Text) link.getFirstChild();
701: if (labelNode == null) {
702: labelNode = domContext.getDocument().createTextNode(
703: linkText);
704: tab.addHeaderText(domContext, link, labelNode, tabSet);
705: } else {
706: labelNode.setData(linkText);
707: }
708: }
709: }
710:
711: /**
712: * This method is defined in the DomBasicRenderer with a default package
713: * visiblity. TODO: modify visiblity to public in DomBasicRenderer and
714: * remove from PanelTabSetRenderer Due to the behaviour of the UIParameter
715: * class, the names in the name-value pairs of the Map returned by this
716: * method are guaranteed to be Strings
717: *
718: * @param facesContext
719: * @param uiComponent
720: * @return map
721: */
722: static Map getParameterMap(FacesContext facesContext,
723: UIComponent uiComponent) {
724: Map parameterMap = new HashMap();
725: Iterator children = uiComponent.getChildren().iterator();
726: UIComponent nextChild;
727: UIParameter uiParam;
728: while (children.hasNext()) {
729: nextChild = (UIComponent) children.next();
730: if (nextChild instanceof UIParameter) {
731: uiParam = (UIParameter) nextChild;
732: parameterMap.put(uiParam.getName(), uiParam.getValue());
733: }
734: }
735: return parameterMap;
736: }
737:
738: /**
739: * @param facesContext
740: * @param root
741: * @param parameters
742: */
743: private void renderOnClick(FacesContext facesContext,
744: UIComponent tabSet, PanelTab tab, Element root,
745: Map parameters) {
746: UIComponent uiForm = findForm(tabSet);
747: if (uiForm == null) {
748: throw new FacesException(
749: "CommandLink must be contained in a form");
750: }
751: String uiFormClientId = uiForm.getClientId(facesContext);
752: String onclick = "";
753: if (tab.getOnclick() != null) {
754: onclick = tab.getOnclick();
755: }
756: root.setAttribute("onclick", onclick
757: + getJavaScriptOnClickString(facesContext, tabSet,
758: uiFormClientId, parameters)); // replaced command w/component
759: }
760:
761: private String getJavaScriptOnClickString(
762: FacesContext facesContext, UIComponent uiComponent,
763: String formClientId, Map parameters) {
764: return getJavascriptHiddenFieldSetters(facesContext,
765: uiComponent, formClientId, parameters)
766: + "iceSubmitPartial("
767: + " document.forms['"
768: + formClientId
769: + "'],"
770: + " this,event); "
771: + "return false;";
772: }
773:
774: /**
775: * @param facesContext
776: * @param uiComponent
777: * @param formClientId
778: * @param parameters
779: * @return string representing hidden field setters for this tabset
780: */
781: private String getJavascriptHiddenFieldSetters(
782: FacesContext facesContext, UIComponent uiComponent,
783: String formClientId, Map parameters) {
784: StringBuffer buffer;
785: buffer = new StringBuffer("document.forms['" + formClientId
786: + "']['");
787: buffer.append(deriveCommonHiddenFieldName(facesContext,
788: uiComponent));
789: buffer.append("'].value='");
790: buffer.append(uiComponent.getClientId(facesContext));
791: buffer.append("';");
792: Iterator parameterKeys = parameters.keySet().iterator();
793: String nextParamName;
794: Object nextParamValue;
795: while (parameterKeys.hasNext()) {
796: nextParamName = (String) parameterKeys.next();
797: nextParamValue = parameters.get(nextParamName);
798: buffer.append("document.forms['");
799: buffer.append(formClientId);
800: buffer.append("']['");
801: buffer.append(nextParamName);
802: buffer.append("'].value='");
803: buffer.append((String) nextParamValue);
804: buffer.append("';");
805: }
806: return buffer.toString();
807: }
808:
809: /**
810: * @param domContext
811: * @param td
812: */
813: private void renderSpacerImage(DOMContext domContext, Element td) {
814:
815: // create a dummy image to load into given td
816: Element img = domContext.createElement(HTML.IMG_ELEM);
817: img.setAttribute(HTML.SRC_ATTR, CoreUtils.resolveResourceURL(
818: FacesContext.getCurrentInstance(), SPACER_IMG));
819: img.setAttribute(HTML.HEIGHT_ATTR, "1");
820: img.setAttribute(HTML.WIDTH_ATTR, "4");
821: img.setAttribute(HTML.ALT_ATTR, "");
822:
823: td.appendChild(img);
824: }
825:
826: /**
827: * writeTabCell is a DOM-enabled version of the MyFaces writeTabCell
828: * implementation. Calls to the ResponseWriter have been substituted with
829: * DOMContext and w3c DOM API calls.
830: *
831: * @param domContext
832: * @param facesContext
833: * @param tabSet
834: * @param tabCount
835: * @param selectedIndex
836: * @param tr
837: * @param uiList
838: * @throws IOException
839: */
840: protected void writeTabCell(DOMContext domContext,
841: FacesContext facesContext, PanelTabSet tabSet,
842: int tabCount, int selectedIndex, Element tr, UISeries uiList)
843: throws IOException {
844: // create a new table data Element
845: Element td = domContext.createElement(HTML.TD_ELEM);
846: td.setAttribute(HTML.ID_ATTR, tabSet.getClientId(facesContext)
847: + "td" + tabCount);
848: // append the new table data Element to the table row
849: tr.appendChild(td);
850:
851: // set the table data attributes
852: //extra column for Safari table bug
853: // td.setAttribute(HTML.COLSPAN_ATTR, Integer.toString(tabCount + 2 ));
854: td.setAttribute(HTML.CLASS_ATTR, tabSet.getContentClass());
855:
856: // set the cursor parent to the new table data Element
857: // this will cause the renderChild method to append the child nodes
858: // to the new table data Element
859: domContext.setCursorParent(td);
860: domContext.streamWrite(facesContext, tabSet, domContext
861: .getRootNode(), td);
862: int tabIdx = 0;
863: if (uiList.getValue() != null) {
864: int rowIndex = uiList.getFirst();
865: uiList.setRowIndex(rowIndex);
866: int rowsToBeDisplayed = uiList.getRows();
867: int rowsDisplayed = 0;
868: UIComponent child = getUIComponent((UIComponent) tabSet
869: .getChildren().get(0));
870: while (uiList.isRowAvailable()) {
871: if (rowsToBeDisplayed > 0
872: && rowsDisplayed >= rowsToBeDisplayed) {
873: break;
874: }
875: if (child instanceof PanelTab) {
876: if (tabIdx == selectedIndex) {
877: CustomComponentUtils.renderChild(facesContext,
878: child);
879: }
880: tabIdx++;
881: }
882: rowsDisplayed++;
883: rowIndex++;
884: uiList.setRowIndex(rowIndex);
885: }
886: uiList.setRowIndex(-1);
887: } else {
888: List children = tabSet.getChildren();
889: UIComponent child;
890: for (int i = 0, len = children.size(); i < len; i++) {
891: child = getUIComponent((UIComponent) children.get(i));
892: if (child instanceof PanelTab) {
893: if (tabIdx == selectedIndex) {
894: CustomComponentUtils.renderChild(facesContext,
895: child);
896: }
897: tabIdx++;
898: } else {
899: CustomComponentUtils.renderChild(facesContext,
900: child);
901: }
902: }
903: }
904: }
905:
906: private UIComponent getUIComponent(UIComponent uiComponent) {
907: if (uiComponent instanceof UIForm
908: || uiComponent instanceof UINamingContainer) {
909: List children = uiComponent.getChildren();
910: for (int i = 0, len = children.size(); i < len; i++) {
911: uiComponent = getUIComponent((UIComponent) children
912: .get(i));
913: }
914: }
915: return uiComponent;
916: }
917: }
|