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 }