001 package org.apache.myfaces.tobago.component;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 import org.apache.commons.logging.Log;
021 import org.apache.commons.logging.LogFactory;
022 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_COLUMNS;
023 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_DIRECT_LINK_COUNT;
024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_FIRST;
025 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INNER_WIDTH;
026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LAYOUT_WIDTH;
027 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ROWS;
028 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SELECTABLE;
029 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SELECTED_LIST_STRING;
030 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SHOW_DIRECT_LINKS;
031 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SHOW_HEADER;
032 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SHOW_PAGE_RANGE;
033 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SHOW_ROW_RANGE;
034 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STATE;
035 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_WIDTH_LIST_STRING;
036 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_OUT;
037 import org.apache.myfaces.tobago.ajax.api.AjaxComponent;
038 import org.apache.myfaces.tobago.ajax.api.AjaxPhaseListener;
039 import org.apache.myfaces.tobago.ajax.api.AjaxUtils;
040 import org.apache.myfaces.tobago.event.PageActionEvent;
041 import org.apache.myfaces.tobago.event.SheetStateChangeEvent;
042 import org.apache.myfaces.tobago.event.SheetStateChangeListener;
043 import org.apache.myfaces.tobago.event.SheetStateChangeSource;
044 import org.apache.myfaces.tobago.event.SortActionEvent;
045 import org.apache.myfaces.tobago.event.SortActionSource;
046 import org.apache.myfaces.tobago.model.SheetState;
047 import org.apache.myfaces.tobago.renderkit.LayoutInformationProvider;
048 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase;
049 import org.apache.myfaces.tobago.renderkit.SheetRendererWorkaround;
050 import org.apache.myfaces.tobago.util.LayoutInfo;
051 import org.apache.myfaces.tobago.util.LayoutUtil;
052 import org.apache.myfaces.tobago.util.StringUtil;
053
054 import javax.faces.component.UIColumn;
055 import javax.faces.component.UIComponent;
056 import javax.faces.context.FacesContext;
057 import javax.faces.el.EvaluationException;
058 import javax.faces.el.MethodBinding;
059 import javax.faces.el.ValueBinding;
060 import javax.faces.event.AbortProcessingException;
061 import javax.faces.event.FacesEvent;
062 import javax.faces.event.PhaseId;
063 import java.io.IOException;
064 import java.util.ArrayList;
065 import java.util.List;
066 import java.util.Map;
067
068 public class UIData extends javax.faces.component.UIData
069 implements SheetStateChangeSource, SortActionSource, AjaxComponent {
070
071 private static final Log LOG = LogFactory.getLog(UIData.class);
072
073 public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Data";
074
075 public static final String FACET_SORTER = "sorter";
076 public static final String SORTER_ID = "sorter";
077 public static final String ATTR_SCROLL_POSITION = "attrScrollPosition";
078
079 public static final String NONE = "none";
080 public static final String SINGLE = "single";
081 public static final String MULTI = "multi";
082 public static final int DEFAULT_DIRECT_LINK_COUNT = 9;
083 public static final int DEFAULT_ROW_COUNT = 100;
084 public static final String ROW_IDX_REGEX = "^\\d+" + SEPARATOR_CHAR + ".*";
085 private static final String DEFAULT_SELECTABLE = MULTI;
086
087 private MethodBinding stateChangeListener;
088 private List<Integer> widthList;
089 private MethodBinding sortActionListener;
090 private SheetState sheetState;
091 private Boolean showHeader;
092 private String showRowRange;
093 private String showPageRange;
094 private String showDirectLinks;
095 private String columns;
096 private Integer directLinkCount;
097 private Integer rows;
098
099 private String selectable;
100
101 private transient LayoutTokens columnLayout;
102
103 public void encodeBegin(FacesContext facesContext) throws IOException {
104 UILayout.prepareDimension(facesContext, this);
105 SheetState state = getSheetState(facesContext);
106 if (state.getFirst() > -1 && state.getFirst() < getRowCount()) {
107 ValueBinding valueBinding = getValueBinding(ATTR_FIRST);
108 if (valueBinding != null) {
109 valueBinding.setValue(facesContext, state.getFirst());
110 } else {
111 setFirst(state.getFirst());
112 }
113 }
114 super.encodeBegin(facesContext);
115 }
116
117 public void encodeEnd(FacesContext facesContext) throws IOException {
118 setupState(facesContext);
119 prepareDimensions(facesContext);
120 super.encodeEnd(facesContext);
121 }
122
123 public String getShowRowRange() {
124 if (showRowRange != null) {
125 return showRowRange;
126 }
127 ValueBinding vb = getValueBinding(ATTR_SHOW_ROW_RANGE);
128 if (vb != null) {
129 return (String) vb.getValue(getFacesContext());
130 } else {
131 return NONE;
132 }
133 }
134
135 public void setShowRowRange(String showRowRange) {
136 this.showRowRange = showRowRange;
137 }
138
139 public String getShowPageRange() {
140 if (showPageRange != null) {
141 return showPageRange;
142 }
143 ValueBinding vb = getValueBinding(ATTR_SHOW_PAGE_RANGE);
144 if (vb != null) {
145 return (String) vb.getValue(getFacesContext());
146 } else {
147 return NONE;
148 }
149 }
150
151 public void setShowPageRange(String showPageRange) {
152 this.showPageRange = showPageRange;
153 }
154
155 public String getColumns() {
156 if (columns != null) {
157 return columns;
158 }
159 ValueBinding vb = getValueBinding(ATTR_COLUMNS);
160 if (vb != null) {
161 return (String) vb.getValue(getFacesContext());
162 } else {
163 return null;
164 }
165 }
166
167 public void setColumns(String columns) {
168 this.columns = columns;
169 }
170
171 public String getShowDirectLinks() {
172 if (showDirectLinks != null) {
173 return showDirectLinks;
174 }
175 ValueBinding vb = getValueBinding(ATTR_SHOW_DIRECT_LINKS);
176 if (vb != null) {
177 return (String) vb.getValue(getFacesContext());
178 } else {
179 return NONE;
180 }
181 }
182
183 public void setShowDirectLinks(String showDirectLinks) {
184 this.showDirectLinks = showDirectLinks;
185 }
186
187 public String getSelectable() {
188 if (selectable != null) {
189 return selectable;
190 }
191 ValueBinding vb = getValueBinding(ATTR_SELECTABLE);
192 if (vb != null) {
193 return (String) vb.getValue(getFacesContext());
194 } else {
195 return DEFAULT_SELECTABLE;
196 }
197 }
198
199 public void setSelectable(String selectable) {
200 this.selectable = selectable;
201 }
202
203 public Integer getDirectLinkCount() {
204 if (directLinkCount != null) {
205 return directLinkCount;
206 }
207 ValueBinding vb = getValueBinding(ATTR_DIRECT_LINK_COUNT);
208 if (vb != null) {
209 return (Integer) vb.getValue(getFacesContext());
210 } else {
211 return DEFAULT_DIRECT_LINK_COUNT;
212 }
213 }
214
215 public void setDirectLinkCount(Integer directLinkCount) {
216 this.directLinkCount = directLinkCount;
217 }
218
219 private void setupState(FacesContext facesContext) {
220 SheetState state = getSheetState(facesContext);
221 ensureColumnWidthList(facesContext, state);
222 }
223
224 public void setState(SheetState state) {
225 this.sheetState = state;
226 }
227
228 public SheetState getSheetState(FacesContext facesContext) {
229 if (sheetState != null) {
230 return sheetState;
231 } else {
232 ValueBinding stateBinding = getValueBinding(ATTR_STATE);
233 if (stateBinding != null) {
234 SheetState state = (SheetState) stateBinding.getValue(facesContext);
235 if (state == null) {
236 state = new SheetState();
237 stateBinding.setValue(facesContext, state);
238 }
239 return state;
240 } else {
241 sheetState = new SheetState();
242 return sheetState;
243 }
244 }
245 }
246
247 public LayoutTokens getColumnLayout() {
248 if (columnLayout == null) {
249 String columns = getColumns();
250 if (columns != null) {
251 columnLayout = LayoutTokens.parse(columns);
252 }
253 }
254 return columnLayout;
255 }
256
257 private void ensureColumnWidthList(FacesContext facesContext, SheetState state) {
258 List<Integer> currentWidthList = null;
259 List<UIColumn> rendererdColumns = getRenderedColumns();
260
261 final Map attributes = getAttributes();
262 String widthListString = null;
263
264 if (state != null) {
265 widthListString = state.getColumnWidths();
266 }
267 if (widthListString == null) {
268 widthListString = (String) attributes.get(ATTR_WIDTH_LIST_STRING);
269 }
270
271 if (widthListString != null) {
272 currentWidthList = StringUtil.parseIntegerList(widthListString);
273 }
274 if (currentWidthList != null && currentWidthList.size() != rendererdColumns.size()) {
275 currentWidthList = null;
276 }
277
278
279 if (currentWidthList == null) {
280 LayoutTokens tokens = getColumnLayout();
281 List<UIColumn> allColumns = getAllColumns();
282 LayoutTokens newTokens = new LayoutTokens();
283 if (allColumns.size() > 0) {
284 for (int i = 0; i < allColumns.size(); i++) {
285 UIColumn column = allColumns.get(i);
286 if (column.isRendered()) {
287 if (tokens == null) {
288 if (column instanceof org.apache.myfaces.tobago.component.UIColumn) {
289 newTokens.addToken(
290 LayoutTokens.parseToken(((org.apache.myfaces.tobago.component.UIColumn) column).getWidth()));
291 } else {
292 newTokens.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
293 }
294 } else {
295 if (i < tokens.getSize()) {
296 newTokens.addToken(tokens.get(i));
297 } else {
298 newTokens.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
299 }
300 }
301 }
302 }
303 }
304
305
306 int space = LayoutUtil.getInnerSpace(facesContext, this, true);
307 SheetRendererWorkaround renderer
308 = (SheetRendererWorkaround) ComponentUtil.getRenderer(facesContext, this);
309 space -= renderer.getContentBorder(facesContext, this);
310 if (renderer.needVerticalScrollbar(facesContext, this)) {
311 space -= renderer.getScrollbarWidth(facesContext, this);
312 }
313 LayoutInfo layoutInfo = new LayoutInfo(newTokens.getSize(), space, newTokens, getClientId(facesContext), false);
314 parseFixedWidth(facesContext, layoutInfo, rendererdColumns);
315 layoutInfo.parseColumnLayout(space);
316 currentWidthList = layoutInfo.getSpaceList();
317 }
318
319 if (currentWidthList != null) {
320 if (rendererdColumns.size() != currentWidthList.size()) {
321 LOG.warn("widthList.size() = " + currentWidthList.size()
322 + " != columns.size() = " + rendererdColumns.size() + " widthList : "
323 + LayoutInfo.listToTokenString(currentWidthList));
324 } else {
325 this.widthList = currentWidthList;
326 }
327 }
328 }
329
330 private void parseFixedWidth(FacesContext facesContext, LayoutInfo layoutInfo, List<UIColumn> rendereredColumns) {
331 LayoutTokens tokens = layoutInfo.getLayoutTokens();
332 for (int i = 0; i < tokens.getSize(); i++) {
333 LayoutToken token = tokens.get(i);
334 if (token instanceof FixedLayoutToken) {
335 int width = 0;
336 if (!rendereredColumns.isEmpty()) {
337 if (i < rendereredColumns.size()) {
338 UIColumn column = rendereredColumns.get(i);
339 if (column instanceof UIColumnSelector) {
340 LayoutInformationProvider renderer
341 = ComponentUtil.getRenderer(facesContext, column);
342 if (renderer == null) {
343 LOG.warn("can't find renderer for " + column.getClass().getName());
344 renderer = ComponentUtil.getRenderer(facesContext, UIPanel.COMPONENT_FAMILY, RENDERER_TYPE_OUT);
345 }
346 width = renderer.getFixedWidth(facesContext, column);
347
348 } else {
349 for (UIComponent component : (List<UIComponent>) column.getChildren()) {
350 LayoutInformationProvider renderer
351 = ComponentUtil.getRenderer(facesContext, component);
352 width += renderer.getFixedWidth(facesContext, component);
353 }
354 }
355 layoutInfo.update(width, i);
356 } else {
357 layoutInfo.update(0, i);
358 if (LOG.isWarnEnabled()) {
359 LOG.warn("More LayoutTokens found than rows! skipping!");
360 }
361 }
362 }
363 if (LOG.isDebugEnabled()) {
364 LOG.debug("set column " + i + " from fixed to with " + width);
365 }
366 }
367 }
368 }
369
370
371 private void prepareDimensions(FacesContext facesContext) {
372 // prepare width's in column's children components
373
374 List<Integer> columnWidths = getWidthList();
375 int i = 0;
376 for (UIColumn column : getRenderedColumns()) {
377 if (i < columnWidths.size()) {
378 Integer width = columnWidths.get(i);
379 if (!(column instanceof UIColumnSelector)) {
380 if (column.getChildCount() == 1) {
381 UIComponent child = (UIComponent) column.getChildren().get(0);
382 int cellPaddingWidth = ((LayoutableRendererBase) getRenderer(facesContext))
383 .getConfiguredValue(facesContext, this, "cellPaddingWidth");
384 child.getAttributes().put(
385 ATTR_LAYOUT_WIDTH, width - cellPaddingWidth);
386 child.getAttributes().remove(ATTR_INNER_WIDTH);
387 } else {
388 LOG.warn("More or less than 1 child in column! "
389 + "Can't set width for column " + i + " to " + width);
390 }
391 }
392 } else {
393 LOG.warn("More columns than columnSizes! "
394 + "Can't set width for column " + i);
395 }
396 i++;
397 }
398 }
399
400 public int getLast() {
401 int last = getFirst() + getRows();
402 return last < getRowCount() ? last : getRowCount();
403 }
404
405 public int getPage() {
406 int first = getFirst() + 1;
407 int rows = getRows();
408 if (rows == 0) {
409 // avoid division by zero
410 return 0;
411 }
412 if ((first % rows) > 0) {
413 return (first / rows) + 1;
414 } else {
415 return (first / rows);
416 }
417 }
418
419 public int getPages() {
420 int rows = getRows();
421 if (rows == 0) {
422 return 0;
423 }
424 return getRowCount() / rows + (getRowCount() % rows == 0 ? 0 : 1);
425 }
426
427 public List<UIComponent> getRenderedChildrenOf(UIColumn column) {
428 List<UIComponent> children = new ArrayList<UIComponent>();
429 for (Object o : column.getChildren()) {
430 UIComponent kid = (UIComponent) o;
431 if (kid.isRendered()) {
432 children.add(kid);
433 }
434 }
435 return children;
436 }
437
438 public boolean isAtBeginning() {
439 return getFirst() == 0;
440 }
441
442 public boolean hasRowCount() {
443 return getRowCount() != -1;
444 }
445
446 public boolean isAtEnd() {
447 if (!hasRowCount()) {
448 setRowIndex(getFirst() + getRows() + 1);
449 return !isRowAvailable();
450 } else {
451 return getFirst() >= getLastPageIndex();
452 }
453 }
454
455 public int getLastPageIndex() {
456 int rows = getRows();
457 if (rows == 0) {
458 // avoid division by zero
459 return 0;
460 }
461 int rowCount = getRowCount();
462 int tail = rowCount % rows;
463 return rowCount - (tail != 0 ? tail : rows);
464 }
465
466 public void processUpdates(FacesContext context) {
467 super.processUpdates(context);
468 updateSheetState(context);
469 }
470
471 private void updateSheetState(FacesContext facesContext) {
472 SheetState state = getSheetState(facesContext);
473 if (state != null) {
474 // ensure sortActionListener
475 // getSortActionListener();
476 // state.setSortedColumn(sortActionListener != null ? sortActionListener.getColumn() : -1);
477 // state.setAscending(sortActionListener != null && sortActionListener.isAscending());
478 Map attributes = getAttributes();
479 //noinspection unchecked
480 state.setSelectedRows((List<Integer>) attributes.get(ATTR_SELECTED_LIST_STRING));
481 state.setColumnWidths((String) attributes.get(ATTR_WIDTH_LIST_STRING));
482 state.setScrollPosition((Integer[]) attributes.get(ATTR_SCROLL_POSITION));
483 attributes.remove(ATTR_SELECTED_LIST_STRING);
484 attributes.remove(ATTR_SCROLL_POSITION);
485 }
486 }
487
488
489 public Object saveState(FacesContext context) {
490 Object[] saveState = new Object[12];
491 saveState[0] = super.saveState(context);
492 saveState[1] = sheetState;
493 saveState[2] = saveAttachedState(context, sortActionListener);
494 saveState[3] = saveAttachedState(context, stateChangeListener);
495 saveState[4] = showHeader;
496 saveState[5] = showRowRange;
497 saveState[6] = showPageRange;
498 saveState[7] = showDirectLinks;
499 saveState[8] = directLinkCount;
500 saveState[9] = selectable;
501 saveState[10] = columns;
502 saveState[11] = rows;
503 return saveState;
504 }
505
506 public void restoreState(FacesContext context, Object savedState) {
507 Object[] values = (Object[]) savedState;
508 super.restoreState(context, values[0]);
509 sheetState = (SheetState) values[1];
510 sortActionListener = (MethodBinding) restoreAttachedState(context, values[2]);
511 stateChangeListener = (MethodBinding) restoreAttachedState(context, values[3]);
512 showHeader = (Boolean) values[4];
513 showRowRange = (String) values[5];
514 showPageRange = (String) values[6];
515 showDirectLinks = (String) values[7];
516 directLinkCount = (Integer) values[8];
517 selectable = (String) values[9];
518 columns = (String) values[10];
519 rows = (Integer) values[11];
520 }
521
522
523 public List<UIColumn> getAllColumns() {
524 List<UIColumn> columns = new ArrayList<UIColumn>();
525 for (UIComponent kid : (List<UIComponent>) getChildren()) {
526 if (kid instanceof UIColumn && !(kid instanceof UIColumnEvent)) {
527 columns.add((UIColumn) kid);
528 }
529 }
530 return columns;
531 }
532
533 public List<UIColumn> getRenderedColumns() {
534 List<UIColumn> columns = new ArrayList<UIColumn>();
535 for (UIComponent kid : (List<UIComponent>) getChildren()) {
536 if (kid instanceof UIColumn && kid.isRendered() && !(kid instanceof UIColumnEvent)) {
537 columns.add((UIColumn) kid);
538 }
539 }
540 return columns;
541 }
542
543 public MethodBinding getSortActionListener() {
544 if (sortActionListener != null) {
545 return sortActionListener;
546 } else {
547 return new Sorter();
548 }
549 }
550
551 public void setSortActionListener(MethodBinding sortActionListener) {
552 this.sortActionListener = sortActionListener;
553 }
554
555 public void queueEvent(FacesEvent facesEvent) {
556 UIComponent parent = getParent();
557 if (parent == null) {
558 throw new IllegalStateException(
559 "component is not a descendant of a UIViewRoot");
560 }
561
562 if (facesEvent.getComponent() == this
563 && (facesEvent instanceof SheetStateChangeEvent
564 || facesEvent instanceof PageActionEvent)) {
565 facesEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
566 LOG.info("queueEvent = \"" + facesEvent + "\"");
567 parent.queueEvent(facesEvent);
568 } else {
569 UIComponent source = facesEvent.getComponent();
570 UIComponent sourceParent = source.getParent();
571 if (sourceParent.getParent() == this
572 && source.getId() != null && source.getId().endsWith(SORTER_ID)) {
573 facesEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
574 parent.queueEvent(new SortActionEvent(this, (UIColumn) sourceParent));
575 } else {
576 super.queueEvent(facesEvent);
577 }
578 }
579 }
580
581 public void broadcast(FacesEvent facesEvent) throws AbortProcessingException {
582 super.broadcast(facesEvent);
583 if (facesEvent instanceof SheetStateChangeEvent) {
584 invokeMethodBinding(getStateChangeListener(), facesEvent);
585 } else if (facesEvent instanceof PageActionEvent) {
586 invokeMethodBinding(new Pager(), facesEvent);
587 invokeMethodBinding(getStateChangeListener(), new SheetStateChangeEvent(this));
588 } else if (facesEvent instanceof SortActionEvent) {
589 getSheetState(getFacesContext()).updateSortState((SortActionEvent) facesEvent);
590 invokeMethodBinding(getSortActionListener(), facesEvent);
591 }
592 }
593
594 private void invokeMethodBinding(MethodBinding methodBinding, FacesEvent event) {
595 if (methodBinding != null && event != null) {
596 try {
597 Object[] objects = new Object[]{event};
598 methodBinding.invoke(getFacesContext(), objects);
599 } catch (EvaluationException e) {
600 Throwable cause = e.getCause();
601 if (cause instanceof AbortProcessingException) {
602 throw (AbortProcessingException) cause;
603 } else {
604 throw e;
605 }
606 }
607 }
608 }
609
610 public void addStateChangeListener(SheetStateChangeListener listener) {
611 addFacesListener(listener);
612 }
613
614 public SheetStateChangeListener[] getStateChangeListeners() {
615 return (SheetStateChangeListener[]) getFacesListeners(SheetStateChangeListener.class);
616 }
617
618 public void removeStateChangeListener(SheetStateChangeListener listener) {
619 removeFacesListener(listener);
620 }
621
622 public MethodBinding getStateChangeListener() {
623 return stateChangeListener;
624 }
625
626 public void setStateChangeListener(MethodBinding stateChangeListener) {
627 this.stateChangeListener = stateChangeListener;
628 }
629
630 public List<Integer> getWidthList() {
631 return widthList;
632 }
633
634 public int getRows() {
635 if (rows != null) {
636 return rows;
637 }
638 ValueBinding vb = getValueBinding(ATTR_ROWS);
639 if (vb != null) {
640 return (Integer) vb.getValue(getFacesContext());
641 } else {
642 return DEFAULT_ROW_COUNT;
643 }
644 }
645
646 public void setRows(int rows) {
647 this.rows = rows;
648 }
649
650 public boolean isShowHeader() {
651 if (showHeader != null) {
652 return showHeader;
653 }
654 ValueBinding vb = getValueBinding(ATTR_SHOW_HEADER);
655 if (vb != null) {
656 return (!Boolean.FALSE.equals(vb.getValue(getFacesContext())));
657 } else {
658 return true;
659 }
660 }
661
662 public void setShowHeader(boolean showHeader) {
663 this.showHeader = showHeader;
664 }
665
666 public void encodeAjax(FacesContext facesContext) throws IOException {
667 setupState(facesContext);
668 prepareDimensions(facesContext);
669 // TODO neets more testing!!!
670 //if (!facesContext.getRenderResponse() && !ComponentUtil.hasErrorMessages(facesContext)) {
671 // in encodeBegin of superclass is some logic which clears the DataModel
672 // this must here also done.
673 // in RI and myfaces this could done via setValue(null)
674 ValueBinding binding = getValueBinding("value");
675 if (binding != null) {
676 setValue(null);
677 } else {
678 setValue(getValue());
679 }
680 //}
681 AjaxUtils.encodeAjaxComponent(facesContext, this);
682 }
683
684 public void processAjax(FacesContext facesContext) throws IOException {
685 final String ajaxId = (String) facesContext.getExternalContext()
686 .getRequestParameterMap().get(AjaxPhaseListener.AJAX_COMPONENT_ID);
687 if (ajaxId.equals(getClientId(facesContext))) {
688 AjaxUtils.processActiveAjaxComponent(facesContext, this);
689 } else {
690 AjaxUtils.processAjaxOnChildren(facesContext, this);
691 }
692 }
693
694 public Integer[] getScrollPosition() {
695 Integer[] scrollPosition = (Integer[]) getAttributes().get(ATTR_SCROLL_POSITION);
696 if (scrollPosition == null) {
697 scrollPosition = getSheetState(FacesContext.getCurrentInstance()).getScrollPosition();
698 }
699 return scrollPosition;
700 }
701
702
703 public UIComponent findComponent(String searchId) {
704 if (searchId.matches(ROW_IDX_REGEX)) {
705 searchId = searchId.substring(searchId.indexOf(SEPARATOR_CHAR) + 1);
706 }
707 return super.findComponent(searchId);
708 }
709 }