001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry.contrib.tree.components; 016 017 import org.apache.commons.logging.Log; 018 import org.apache.commons.logging.LogFactory; 019 import org.apache.tapestry.BaseComponent; 020 import org.apache.tapestry.IAsset; 021 import org.apache.tapestry.IBinding; 022 import org.apache.tapestry.IMarkupWriter; 023 import org.apache.tapestry.IRender; 024 import org.apache.tapestry.IRequestCycle; 025 import org.apache.tapestry.contrib.tree.model.ITreeModelSource; 026 import org.apache.tapestry.contrib.tree.model.ITreeRowSource; 027 import org.apache.tapestry.contrib.tree.model.ITreeStateListener; 028 import org.apache.tapestry.contrib.tree.model.ITreeStateModel; 029 import org.apache.tapestry.contrib.tree.model.TreeRowObject; 030 import org.apache.tapestry.contrib.tree.model.TreeStateEvent; 031 import org.apache.tapestry.contrib.tree.simple.SimpleNodeRenderFactory; 032 import org.apache.tapestry.engine.IPageLoader; 033 import org.apache.tapestry.event.PageDetachListener; 034 import org.apache.tapestry.event.PageEvent; 035 import org.apache.tapestry.spec.ComponentSpecification; 036 import org.apache.tapestry.util.ComponentAddress; 037 038 /** 039 * @author tsveltin? 040 */ 041 public abstract class TreeNodeView extends BaseComponent implements PageDetachListener 042 { 043 private static final Log LOG = LogFactory.getLog(TreeNodeView.class); 044 045 private IBinding m_objNodeRenderFactoryBinding; 046 047 private IBinding m_objShowNodeImagesBinding; 048 049 private IBinding m_objMakeNodeDirectBinding; 050 051 private Boolean m_objNodeState; 052 053 private Boolean m_objShowNodeImages; 054 055 private Boolean m_objMakeNodeDirect; 056 057 private INodeRenderFactory m_objNodeRenderFactory; 058 059 private IAsset m_objOpenNodeImage; 060 061 private IAsset m_objCloseNodeImage; 062 063 private int m_CurrentForeachConnectImageValue = TreeRowObject.LINE_CONN_IMG; 064 065 public TreeNodeView() 066 { 067 super(); 068 initialize(); 069 } 070 071 private void initialize() 072 { 073 m_objNodeState = null; 074 m_objShowNodeImages = null; 075 m_objNodeRenderFactory = null; 076 m_objMakeNodeDirect = null; 077 m_CurrentForeachConnectImageValue = TreeRowObject.LINE_CONN_IMG; 078 } 079 080 public IRender getCurrentRenderer() 081 { 082 INodeRenderFactory objRenderFactory = getNodeRenderFactory(); 083 ITreeRowSource objTreeRowSource = getTreeRowSource(); 084 return objRenderFactory.getRender( 085 objTreeRowSource.getTreeRow().getTreeNode(), 086 getTreeModelSource(), 087 getPage().getRequestCycle()); 088 } 089 090 public Object[] getNodeContext() 091 { 092 ITreeModelSource objModelSource = getTreeModelSource(); 093 ComponentAddress objModelSourceAddress = new ComponentAddress(objModelSource); 094 ITreeRowSource objTreeRowSource = getTreeRowSource(); 095 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 096 Object objValueUID = objTreeRowObject.getTreeNodeUID(); 097 if (LOG.isDebugEnabled()) 098 { 099 LOG.debug("getNodeContext objValueUID = " + objValueUID); 100 } 101 102 return new Object[] 103 { objValueUID, new Boolean(isNodeOpen()), objModelSourceAddress }; 104 } 105 106 /** 107 * Called when a node in the tree is clicked by the user. If the node is expanded, it will be 108 * collapsed, and vice-versa, that is, the tree state model is retrieved, and it is told to 109 * collapse or expand the node. 110 * 111 * @param cycle 112 * The Tapestry request cycle object. 113 */ 114 public void nodeExpandCollaps(IRequestCycle cycle) 115 { 116 Object context[] = cycle.getListenerParameters(); 117 Object objValueUID = null; 118 if (context != null && context.length > 0) 119 { 120 objValueUID = context[0]; 121 } 122 ComponentAddress objModelSourceAddress = (ComponentAddress) context[2]; 123 ITreeModelSource objTreeModelSource = (ITreeModelSource) objModelSourceAddress 124 .findComponent(cycle); 125 //ITreeModelSource objTreeModelSource = getTreeModelSource(); 126 ITreeStateModel objStateModel = objTreeModelSource.getTreeModel().getTreeStateModel(); 127 boolean bState = objStateModel.isUniqueKeyExpanded(objValueUID); 128 129 if (bState) 130 { 131 objStateModel.collapse(objValueUID); 132 fireNodeCollapsed(objValueUID, objTreeModelSource); 133 } 134 else 135 { 136 objStateModel.expandPath(objValueUID); 137 fireNodeExpanded(objValueUID, objTreeModelSource); 138 } 139 } 140 141 /** 142 * Called when a node in the tree is selected by the user. the tree state model is retrieved, 143 * and it is told to select the node. 144 * 145 * @param cycle 146 * The Tapestry request cycle object. 147 */ 148 public void nodeSelect(IRequestCycle cycle) 149 { 150 Object context[] = cycle.getListenerParameters(); 151 Object objValueUID = null; 152 if (context != null && context.length > 0) 153 { 154 objValueUID = context[0]; 155 } 156 ComponentAddress objModelSourceAddress = (ComponentAddress) context[2]; 157 ITreeModelSource objTreeModelSource = (ITreeModelSource) objModelSourceAddress 158 .findComponent(cycle); 159 //ITreeModelSource objTreeModelSource = getTreeModelSource(); 160 ITreeStateModel objStateModel = objTreeModelSource.getTreeModel().getTreeStateModel(); 161 Object objSelectedNodeInState = objStateModel.getSelectedNode(); 162 163 if (objValueUID.equals(objSelectedNodeInState)) 164 { 165 //do nothing, the selected node in UI is the same as the selected in 166 //state model. The user should use refresh of back button. 167 return; 168 } 169 170 objStateModel.setSelectedNode(objValueUID); 171 fireNodeSelected(objValueUID, objTreeModelSource); 172 } 173 174 private void fireNodeSelected(Object objValueUID, ITreeModelSource objTreeModelSource) 175 { 176 deliverEvent(TreeStateEvent.SELECTED_NODE_CHANGED, objValueUID, objTreeModelSource); 177 } 178 179 private void fireNodeCollapsed(Object objValueUID, ITreeModelSource objTreeModelSource) 180 { 181 deliverEvent(TreeStateEvent.NODE_COLLAPSED, objValueUID, objTreeModelSource); 182 } 183 184 private void fireNodeExpanded(Object objValueUID, ITreeModelSource objTreeModelSource) 185 { 186 deliverEvent(TreeStateEvent.NODE_EXPANDED, objValueUID, objTreeModelSource); 187 } 188 189 private void deliverEvent(int nEventUID, Object objValueUID, ITreeModelSource objTreeModelSource) 190 { 191 ITreeStateListener objListener = objTreeModelSource.getTreeStateListener(); 192 if (objListener != null) 193 { 194 TreeStateEvent objEvent = new TreeStateEvent(nEventUID, objValueUID, objTreeModelSource 195 .getTreeModel().getTreeStateModel()); 196 objListener.treeStateChanged(objEvent); 197 } 198 199 } 200 201 public void pageDetached(PageEvent arg0) 202 { 203 initialize(); 204 } 205 206 public void finishLoad(IRequestCycle objCycle, IPageLoader arg0, ComponentSpecification arg1) 207 { 208 super.finishLoad(objCycle, arg0, arg1); 209 getPage().addPageDetachListener(this); 210 211 m_objOpenNodeImage = getAsset("_openNodeImage"); 212 m_objCloseNodeImage = getAsset("_closeNodeImage"); 213 } 214 215 public boolean isNodeOpen() 216 { 217 if (m_objNodeState == null) 218 { 219 ITreeRowSource objTreeRowSource = getTreeRowSource(); 220 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 221 Object objValueUID = objTreeRowObject.getTreeNodeUID(); 222 ITreeModelSource objTreeModelSource = getTreeModelSource(); 223 ITreeStateModel objStateModel = objTreeModelSource.getTreeModel().getTreeStateModel(); 224 boolean bState = objStateModel.isUniqueKeyExpanded(objValueUID); 225 m_objNodeState = new Boolean(bState); 226 } 227 return m_objNodeState.booleanValue(); 228 } 229 230 /** 231 * Returns the openNodeImage. 232 * 233 * @return IAsset 234 */ 235 public IAsset getNodeImage() 236 { 237 IAsset objResult = null; 238 ITreeRowSource objRowSource = getTreeRowSource(); 239 boolean bLeaf = objRowSource.getTreeRow().getLeaf(); 240 int nRowType = objRowSource.getTreeRow().getTreeRowPossiotionType(); 241 if (!bLeaf) 242 { 243 if (isNodeOpen()) 244 { 245 switch (nRowType) 246 { 247 case TreeRowObject.FIRST_LAST_ROW: 248 { 249 objResult = getAsset("_topLastOpenNodeImage"); 250 break; 251 } 252 253 case TreeRowObject.FIRST_ROW: 254 { 255 objResult = getAsset("_topOpenNodeImage"); 256 break; 257 } 258 259 case TreeRowObject.MIDDLE_ROW: 260 { 261 objResult = getAsset("_middleOpenNodeImage"); 262 break; 263 } 264 265 case TreeRowObject.LAST_ROW: 266 { 267 objResult = getAsset("_bottomOpenNodeImage"); 268 break; 269 } 270 271 default: 272 { 273 objResult = getAsset("_openNodeImage"); 274 break; 275 } 276 } 277 } 278 else 279 { 280 switch (nRowType) 281 { 282 case TreeRowObject.FIRST_LAST_ROW: 283 { 284 objResult = getAsset("_topLastCloseNodeImage"); 285 break; 286 } 287 288 case TreeRowObject.FIRST_ROW: 289 { 290 objResult = getAsset("_topCloseNodeImage"); 291 break; 292 } 293 294 case TreeRowObject.MIDDLE_ROW: 295 { 296 objResult = getAsset("_middleCloseNodeImage"); 297 break; 298 } 299 300 case TreeRowObject.LAST_ROW: 301 { 302 objResult = getAsset("_bottomCloseNodeImage"); 303 break; 304 } 305 306 default: 307 { 308 objResult = getAsset("_closeNodeImage"); 309 break; 310 } 311 } 312 } 313 } 314 else 315 { 316 switch (nRowType) 317 { 318 case TreeRowObject.FIRST_LAST_ROW: 319 { 320 objResult = getAsset("_topLineImage"); 321 break; 322 } 323 324 case TreeRowObject.FIRST_ROW: 325 { 326 objResult = getAsset("_topLineImage"); 327 break; 328 } 329 330 case TreeRowObject.MIDDLE_ROW: 331 { 332 objResult = getAsset("_middleCrossLineImage"); 333 break; 334 } 335 336 case TreeRowObject.LAST_ROW: 337 { 338 objResult = getAsset("_bottomLineImage"); 339 break; 340 } 341 342 default: 343 { 344 objResult = getAsset("_bottomLineImage"); 345 break; 346 } 347 } 348 349 } 350 return objResult; 351 } 352 353 public IAsset getNodeImageOld() 354 { 355 if (isNodeOpen()) 356 { 357 if (m_objOpenNodeImage == null) 358 { 359 m_objOpenNodeImage = getAsset("_openNodeImage"); 360 } 361 return m_objOpenNodeImage; 362 } 363 364 if (m_objCloseNodeImage == null) 365 { 366 m_objCloseNodeImage = getAsset("_closeNodeImage"); 367 } 368 return m_objCloseNodeImage; 369 } 370 371 /** 372 * Returns the closeNodeImage. 373 * 374 * @return IAsset 375 */ 376 public IAsset getCloseNodeImage() 377 { 378 return m_objCloseNodeImage; 379 } 380 381 /** 382 * Returns the openNodeImage. 383 * 384 * @return IAsset 385 */ 386 public IAsset getOpenNodeImage() 387 { 388 return m_objOpenNodeImage; 389 } 390 391 /** 392 * Sets the closeNodeImage. 393 * 394 * @param closeNodeImage 395 * The closeNodeImage to set 396 */ 397 public void setCloseNodeImage(IAsset closeNodeImage) 398 { 399 m_objCloseNodeImage = closeNodeImage; 400 } 401 402 /** 403 * Sets the openNodeImage. 404 * 405 * @param openNodeImage 406 * The openNodeImage to set 407 */ 408 public void setOpenNodeImage(IAsset openNodeImage) 409 { 410 m_objOpenNodeImage = openNodeImage; 411 } 412 413 /** 414 * @see org.apache.tapestry.AbstractComponent#renderComponent(IMarkupWriter, IRequestCycle) 415 */ 416 protected void renderComponent(IMarkupWriter arg0, IRequestCycle arg1) 417 { 418 super.renderComponent(arg0, arg1); 419 m_objNodeState = null; 420 } 421 422 /** 423 * Returns the ShowNodeImagesBinding. 424 * 425 * @return IBinding 426 */ 427 public IBinding getShowNodeImagesBinding() 428 { 429 return m_objShowNodeImagesBinding; 430 } 431 432 /** 433 * Sets the ShowNodeImagesBinding. 434 * 435 * @param ShowNodeImagesBinding 436 * The ShowNodeImagesBinding to set 437 */ 438 public void setShowNodeImagesBinding(IBinding ShowNodeImagesBinding) 439 { 440 m_objShowNodeImagesBinding = ShowNodeImagesBinding; 441 } 442 443 /** 444 * Returns the ShowNodeImages. 445 * 446 * @return Boolean 447 */ 448 public Boolean isShowNodeImages() 449 { 450 if (m_objShowNodeImages == null) 451 { 452 if (getNodeRenderFactoryBinding() == null) 453 { 454 m_objShowNodeImages = Boolean.TRUE; 455 } 456 else 457 { 458 if (m_objShowNodeImagesBinding != null) 459 { 460 m_objShowNodeImages = (Boolean) m_objShowNodeImagesBinding.getObject(); 461 } 462 else 463 { 464 m_objShowNodeImages = Boolean.TRUE; 465 } 466 } 467 } 468 return m_objShowNodeImages; 469 } 470 471 public boolean getShowImages() 472 { 473 boolean bResult = isShowNodeImages().booleanValue(); 474 return bResult; 475 } 476 477 public boolean getShowWithoutImages() 478 { 479 boolean bResult = !isShowNodeImages().booleanValue(); 480 return bResult; 481 } 482 483 public String getOffsetStyle() 484 { 485 //return "width: " + getTreeDataView().getTreeDeep() * 15; 486 ITreeRowSource objTreeRowSource = getTreeRowSource(); 487 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 488 int nTreeRowDepth = 0; 489 if (objTreeRowObject != null) 490 { 491 nTreeRowDepth = objTreeRowObject.getTreeRowDepth(); 492 if (nTreeRowDepth != 0) 493 nTreeRowDepth = nTreeRowDepth - 1; 494 } 495 return "padding-left: " + nTreeRowDepth * 19 + "px"; 496 } 497 498 /** 499 * Returns the nodeRenderFactoryBinding. 500 * 501 * @return IBinding 502 */ 503 public IBinding getNodeRenderFactoryBinding() 504 { 505 return m_objNodeRenderFactoryBinding; 506 } 507 508 /** 509 * Sets the nodeRenderFactoryBinding. 510 * 511 * @param nodeRenderFactoryBinding 512 * The nodeRenderFactoryBinding to set 513 */ 514 public void setNodeRenderFactoryBinding(IBinding nodeRenderFactoryBinding) 515 { 516 m_objNodeRenderFactoryBinding = nodeRenderFactoryBinding; 517 } 518 519 public INodeRenderFactory getNodeRenderFactory() 520 { 521 if (m_objNodeRenderFactory == null) 522 { 523 IBinding objBinding = getNodeRenderFactoryBinding(); 524 if (objBinding != null) 525 { 526 m_objNodeRenderFactory = (INodeRenderFactory) objBinding.getObject(); 527 } 528 else 529 { 530 m_objNodeRenderFactory = new SimpleNodeRenderFactory(); 531 } 532 } 533 return m_objNodeRenderFactory; 534 } 535 536 /** 537 * Returns the makeNodeDirectBinding. 538 * 539 * @return IBinding 540 */ 541 public IBinding getMakeNodeDirectBinding() 542 { 543 return m_objMakeNodeDirectBinding; 544 } 545 546 /** 547 * Sets the makeNodeDirectBinding. 548 * 549 * @param makeNodeDirectBinding 550 * The makeNodeDirectBinding to set 551 */ 552 public void setMakeNodeDirectBinding(IBinding makeNodeDirectBinding) 553 { 554 m_objMakeNodeDirectBinding = makeNodeDirectBinding; 555 } 556 557 /** 558 * Returns the makeNodeDirect. 559 * 560 * @return Boolean 561 */ 562 public boolean getMakeNodeDirect() 563 { 564 if (m_objMakeNodeDirect == null) 565 { 566 IBinding objBinding = getMakeNodeDirectBinding(); 567 if (objBinding != null) 568 { 569 m_objMakeNodeDirect = (Boolean) objBinding.getObject(); 570 } 571 else 572 { 573 m_objMakeNodeDirect = Boolean.TRUE; 574 } 575 } 576 return m_objMakeNodeDirect.booleanValue(); 577 } 578 579 public boolean getMakeNodeNoDirect() 580 { 581 return !getMakeNodeDirect(); 582 } 583 584 public String getCleanSelectedID() 585 { 586 return getSelectedNodeID(); 587 } 588 589 public String getSelectedID() 590 { 591 ITreeRowSource objTreeRowSource = getTreeRowSource(); 592 ITreeModelSource objTreeModelSource = getTreeModelSource(); 593 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 594 Object objNodeValueUID = objTreeRowObject.getTreeNodeUID(); 595 Object objSelectedNode = objTreeModelSource.getTreeModel().getTreeStateModel() 596 .getSelectedNode(); 597 if (objNodeValueUID.equals(objSelectedNode)) 598 { 599 return getSelectedNodeID(); 600 } 601 return ""; 602 } 603 604 private String getSelectedNodeID() 605 { 606 //return getTreeDataView().getTreeView().getSelectedNodeID(); 607 return "tree"; 608 } 609 610 public String getNodeStyleClass() 611 { 612 ITreeRowSource objTreeRowSource = getTreeRowSource(); 613 ITreeModelSource objTreeModelSource = getTreeModelSource(); 614 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 615 boolean bResult = false; 616 if (objTreeRowObject != null) 617 { 618 Object objNodeValueUID = objTreeRowObject.getTreeNodeUID(); 619 Object objSelectedNode = objTreeModelSource.getTreeModel().getTreeStateModel() 620 .getSelectedNode(); 621 bResult = objNodeValueUID.equals(objSelectedNode); 622 } 623 if (bResult) 624 { 625 return "selectedNodeViewClass"; 626 } 627 628 return "notSelectedNodeViewClass"; 629 } 630 631 public ITreeRowSource getTreeRowSource() 632 { 633 ITreeRowSource objSource = (ITreeRowSource) getPage().getRequestCycle().getAttribute( 634 ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE); 635 return objSource; 636 } 637 638 public ITreeModelSource getTreeModelSource() 639 { 640 ITreeModelSource objSource = (ITreeModelSource) getPage().getRequestCycle().getAttribute( 641 ITreeModelSource.TREE_MODEL_SOURCE_ATTRIBUTE); 642 return objSource; 643 } 644 645 public boolean getShowConnectImage() 646 { 647 ITreeRowSource objRowSource = getTreeRowSource(); 648 int nRowType = objRowSource.getTreeRow().getTreeRowPossiotionType(); 649 if (TreeRowObject.MIDDLE_ROW == nRowType) 650 return true; 651 return false; 652 } 653 654 public int[] getForeachConnectImageList() 655 { 656 ITreeRowSource objTreeRowSource = getTreeRowSource(); 657 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 658 return objTreeRowObject.getLineConnImages(); 659 } 660 661 public boolean getDisableLink() 662 { 663 ITreeRowSource objRowSource = getTreeRowSource(); 664 boolean bLeaf = objRowSource.getTreeRow().getLeaf(); 665 return bLeaf; 666 } 667 668 /** 669 * Returns the openNodeImage. 670 * 671 * @return IAsset nevalidno neshto 672 */ 673 public IAsset getConnectImage() 674 { 675 IAsset objResult = null; 676 int nConnectImageType = getCurrentForeachConnectImageValue(); 677 switch (nConnectImageType) 678 { 679 case TreeRowObject.EMPTY_CONN_IMG: 680 { 681 objResult = getAsset("_whiteSpaceImage"); 682 break; 683 } 684 685 case TreeRowObject.LINE_CONN_IMG: 686 { 687 objResult = getAsset("_middleLineImage"); 688 break; 689 } 690 691 default: 692 { 693 objResult = getAsset("_whiteSpaceImage"); 694 break; 695 } 696 } 697 return objResult; 698 } 699 700 /** 701 * @return Returns the m_CurrentForeachConnectImageValue. 702 */ 703 public int getCurrentForeachConnectImageValue() 704 { 705 return m_CurrentForeachConnectImageValue; 706 } 707 708 /** 709 * @param currentForeachConnectImageValue 710 * The m_CurrentForeachConnectImageValue to set. 711 */ 712 public void setCurrentForeachConnectImageValue(int currentForeachConnectImageValue) 713 { 714 m_CurrentForeachConnectImageValue = currentForeachConnectImageValue; 715 } 716 }