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.IMarkupWriter; 022 import org.apache.tapestry.IRender; 023 import org.apache.tapestry.IRequestCycle; 024 import org.apache.tapestry.contrib.tree.model.ITreeModelSource; 025 import org.apache.tapestry.contrib.tree.model.ITreeRowSource; 026 import org.apache.tapestry.contrib.tree.model.ITreeStateListener; 027 import org.apache.tapestry.contrib.tree.model.ITreeStateModel; 028 import org.apache.tapestry.contrib.tree.model.TreeRowObject; 029 import org.apache.tapestry.contrib.tree.model.TreeStateEvent; 030 import org.apache.tapestry.contrib.tree.simple.SimpleNodeRenderFactory; 031 import org.apache.tapestry.engine.IPageLoader; 032 import org.apache.tapestry.event.PageDetachListener; 033 import org.apache.tapestry.event.PageEvent; 034 import org.apache.tapestry.spec.ComponentSpecification; 035 import org.apache.tapestry.util.ComponentAddress; 036 037 /** 038 * @author tsveltin? 039 */ 040 public abstract class TreeNodeView extends BaseComponent implements 041 PageDetachListener 042 { 043 044 private static final Log LOG = LogFactory.getLog(TreeNodeView.class); 045 046 private Boolean m_objNodeState; 047 048 private Boolean m_objShowNodeImages; 049 050 private INodeRenderFactory m_objNodeRenderFactory; 051 052 private IAsset m_objOpenNodeImage; 053 054 private IAsset m_objCloseNodeImage; 055 056 private int m_currentForeachConnectImageValue = TreeRowObject.LINE_CONN_IMG; 057 058 /** 059 * Creates tree . 060 * 061 */ 062 public TreeNodeView() 063 { 064 super(); 065 initialize(); 066 } 067 068 public abstract INodeRenderFactory getNodeRenderFactoryParameter(); 069 070 public abstract Boolean getShowNodeImages(); 071 072 private void initialize() 073 { 074 m_objNodeState = null; 075 m_objShowNodeImages = null; 076 m_objNodeRenderFactory = 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(objTreeRowSource.getTreeRow() 085 .getTreeNode(), getTreeModelSource(), getPage() 086 .getRequestCycle()); 087 } 088 089 public Object[] getNodeContext() 090 { 091 ITreeModelSource objModelSource = getTreeModelSource(); 092 ComponentAddress objModelSourceAddress = new ComponentAddress( 093 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[] { objValueUID, new Boolean(isNodeOpen()), 103 objModelSourceAddress }; 104 } 105 106 /** 107 * Called when a node in the tree is clicked by the user. If the node is 108 * expanded, it will be collapsed, and vice-versa, that is, the tree state 109 * model is retrieved, and it is told to 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() 127 .getTreeStateModel(); 128 boolean bState = objStateModel.isUniqueKeyExpanded(objValueUID); 129 130 if (bState) 131 { 132 objStateModel.collapse(objValueUID); 133 fireNodeCollapsed(objValueUID, objTreeModelSource); 134 } 135 else 136 { 137 objStateModel.expandPath(objValueUID); 138 fireNodeExpanded(objValueUID, objTreeModelSource); 139 } 140 } 141 142 /** 143 * Called when a node in the tree is selected by the user. the tree state 144 * model is retrieved, and it is told to select the node. 145 * 146 * @param cycle 147 * The Tapestry request cycle object. 148 */ 149 public void nodeSelect(IRequestCycle cycle) 150 { 151 Object[] context = cycle.getListenerParameters(); 152 Object objValueUID = null; 153 if (context != null && context.length > 0) 154 { 155 objValueUID = context[0]; 156 } 157 ComponentAddress objModelSourceAddress = (ComponentAddress) context[2]; 158 ITreeModelSource objTreeModelSource = (ITreeModelSource) objModelSourceAddress 159 .findComponent(cycle); 160 // ITreeModelSource objTreeModelSource = getTreeModelSource(); 161 ITreeStateModel objStateModel = objTreeModelSource.getTreeModel() 162 .getTreeStateModel(); 163 Object objSelectedNodeInState = objStateModel.getSelectedNode(); 164 165 if (objValueUID.equals(objSelectedNodeInState)) 166 { 167 // do nothing, the selected node in UI is the same as the selected 168 // in 169 // state model. The user should use refresh of back button. 170 return; 171 } 172 173 objStateModel.setSelectedNode(objValueUID); 174 fireNodeSelected(objValueUID, objTreeModelSource); 175 } 176 177 private void fireNodeSelected(Object objValueUID, 178 ITreeModelSource objTreeModelSource) 179 { 180 deliverEvent(TreeStateEvent.SELECTED_NODE_CHANGED, objValueUID, 181 objTreeModelSource); 182 } 183 184 private void fireNodeCollapsed(Object objValueUID, 185 ITreeModelSource objTreeModelSource) 186 { 187 deliverEvent(TreeStateEvent.NODE_COLLAPSED, objValueUID, 188 objTreeModelSource); 189 } 190 191 private void fireNodeExpanded(Object objValueUID, 192 ITreeModelSource objTreeModelSource) 193 { 194 deliverEvent(TreeStateEvent.NODE_EXPANDED, objValueUID, 195 objTreeModelSource); 196 } 197 198 private void deliverEvent(int nEventUID, Object objValueUID, 199 ITreeModelSource objTreeModelSource) 200 { 201 ITreeStateListener objListener = objTreeModelSource 202 .getTreeStateListener(); 203 if (objListener != null) 204 { 205 TreeStateEvent objEvent = new TreeStateEvent(nEventUID, 206 objValueUID, objTreeModelSource.getTreeModel() 207 .getTreeStateModel()); 208 objListener.treeStateChanged(objEvent); 209 } 210 211 } 212 213 public void pageDetached(PageEvent arg0) 214 { 215 initialize(); 216 } 217 218 public void finishLoad(IRequestCycle objCycle, IPageLoader arg0, 219 ComponentSpecification arg1) 220 { 221 super.finishLoad(objCycle, arg0, arg1); 222 getPage().addPageDetachListener(this); 223 224 m_objOpenNodeImage = getAsset("_openNodeImage"); 225 m_objCloseNodeImage = getAsset("_closeNodeImage"); 226 } 227 228 public boolean isNodeOpen() 229 { 230 if (m_objNodeState == null) 231 { 232 ITreeRowSource objTreeRowSource = getTreeRowSource(); 233 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 234 Object objValueUID = objTreeRowObject.getTreeNodeUID(); 235 ITreeModelSource objTreeModelSource = getTreeModelSource(); 236 ITreeStateModel objStateModel = objTreeModelSource.getTreeModel() 237 .getTreeStateModel(); 238 boolean bState = objStateModel.isUniqueKeyExpanded(objValueUID); 239 m_objNodeState = new Boolean(bState); 240 } 241 return m_objNodeState.booleanValue(); 242 } 243 244 /** 245 * Returns the openNodeImage. 246 * 247 * @return IAsset 248 */ 249 public IAsset getNodeImage() 250 { 251 IAsset objResult = null; 252 ITreeRowSource objRowSource = getTreeRowSource(); 253 boolean bLeaf = objRowSource.getTreeRow().getLeaf(); 254 int nRowType = objRowSource.getTreeRow().getTreeRowPossiotionType(); 255 if (!bLeaf) 256 { 257 if (isNodeOpen()) 258 { 259 switch(nRowType) 260 { 261 case TreeRowObject.FIRST_LAST_ROW: 262 { 263 objResult = getAsset("_topLastOpenNodeImage"); 264 break; 265 } 266 267 case TreeRowObject.FIRST_ROW: 268 { 269 objResult = getAsset("_topOpenNodeImage"); 270 break; 271 } 272 273 case TreeRowObject.MIDDLE_ROW: 274 { 275 objResult = getAsset("_middleOpenNodeImage"); 276 break; 277 } 278 279 case TreeRowObject.LAST_ROW: 280 { 281 objResult = getAsset("_bottomOpenNodeImage"); 282 break; 283 } 284 285 default: 286 { 287 objResult = getAsset("_openNodeImage"); 288 break; 289 } 290 } 291 } 292 else 293 { 294 switch(nRowType) 295 { 296 case TreeRowObject.FIRST_LAST_ROW: 297 { 298 objResult = getAsset("_topLastCloseNodeImage"); 299 break; 300 } 301 302 case TreeRowObject.FIRST_ROW: 303 { 304 objResult = getAsset("_topCloseNodeImage"); 305 break; 306 } 307 308 case TreeRowObject.MIDDLE_ROW: 309 { 310 objResult = getAsset("_middleCloseNodeImage"); 311 break; 312 } 313 314 case TreeRowObject.LAST_ROW: 315 { 316 objResult = getAsset("_bottomCloseNodeImage"); 317 break; 318 } 319 320 default: 321 { 322 objResult = getAsset("_closeNodeImage"); 323 break; 324 } 325 } 326 } 327 } 328 else 329 { 330 switch(nRowType) 331 { 332 case TreeRowObject.FIRST_LAST_ROW: 333 { 334 objResult = getAsset("_topLineImage"); 335 break; 336 } 337 338 case TreeRowObject.FIRST_ROW: 339 { 340 objResult = getAsset("_topLineImage"); 341 break; 342 } 343 344 case TreeRowObject.MIDDLE_ROW: 345 { 346 objResult = getAsset("_middleCrossLineImage"); 347 break; 348 } 349 350 case TreeRowObject.LAST_ROW: 351 { 352 objResult = getAsset("_bottomLineImage"); 353 break; 354 } 355 356 default: 357 { 358 objResult = getAsset("_bottomLineImage"); 359 break; 360 } 361 } 362 363 } 364 return objResult; 365 } 366 367 public IAsset getNodeImageOld() 368 { 369 if (isNodeOpen()) 370 { 371 if (m_objOpenNodeImage == null) 372 { 373 m_objOpenNodeImage = getAsset("_openNodeImage"); 374 } 375 return m_objOpenNodeImage; 376 } 377 378 if (m_objCloseNodeImage == null) 379 { 380 m_objCloseNodeImage = getAsset("_closeNodeImage"); 381 } 382 return m_objCloseNodeImage; 383 } 384 385 /** 386 * Returns the closeNodeImage. 387 * 388 * @return IAsset 389 */ 390 public IAsset getCloseNodeImage() 391 { 392 return m_objCloseNodeImage; 393 } 394 395 /** 396 * Returns the openNodeImage. 397 * 398 * @return IAsset 399 */ 400 public IAsset getOpenNodeImage() 401 { 402 return m_objOpenNodeImage; 403 } 404 405 /** 406 * Sets the closeNodeImage. 407 * 408 * @param closeNodeImage 409 * The closeNodeImage to set 410 */ 411 public void setCloseNodeImage(IAsset closeNodeImage) 412 { 413 m_objCloseNodeImage = closeNodeImage; 414 } 415 416 /** 417 * Sets the openNodeImage. 418 * 419 * @param openNodeImage 420 * The openNodeImage to set 421 */ 422 public void setOpenNodeImage(IAsset openNodeImage) 423 { 424 m_objOpenNodeImage = openNodeImage; 425 } 426 427 /** 428 * @see org.apache.tapestry.AbstractComponent#renderComponent(IMarkupWriter, 429 * IRequestCycle) 430 */ 431 protected void renderComponent(IMarkupWriter arg0, IRequestCycle arg1) 432 { 433 super.renderComponent(arg0, arg1); 434 m_objNodeState = null; 435 } 436 437 /** 438 * Returns the ShowNodeImages. 439 * 440 * @return Boolean 441 */ 442 public Boolean isShowNodeImages() 443 { 444 if (m_objShowNodeImages == null) 445 { 446 if (isParameterBound("nodeRenderFactory")) 447 { 448 m_objShowNodeImages = getShowNodeImages(); 449 } 450 else 451 { 452 m_objShowNodeImages = Boolean.TRUE; 453 } 454 455 } 456 return m_objShowNodeImages; 457 } 458 459 public boolean getShowImages() 460 { 461 boolean bResult = isShowNodeImages().booleanValue(); 462 return bResult; 463 } 464 465 public boolean getShowWithoutImages() 466 { 467 boolean bResult = !isShowNodeImages().booleanValue(); 468 return bResult; 469 } 470 471 public String getOffsetStyle() 472 { 473 // return "width: " + getTreeDataView().getTreeDeep() * 15; 474 ITreeRowSource objTreeRowSource = getTreeRowSource(); 475 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 476 int nTreeRowDepth = 0; 477 if (objTreeRowObject != null) 478 { 479 nTreeRowDepth = objTreeRowObject.getTreeRowDepth(); 480 if (nTreeRowDepth != 0) nTreeRowDepth = nTreeRowDepth - 1; 481 } 482 return "padding-left: " + nTreeRowDepth * 19 + "px"; 483 } 484 485 public INodeRenderFactory getNodeRenderFactory() 486 { 487 if (m_objNodeRenderFactory == null) 488 { 489 if (isParameterBound("nodeRenderFactory")) 490 m_objNodeRenderFactory = getNodeRenderFactoryParameter(); 491 else m_objNodeRenderFactory = new SimpleNodeRenderFactory(); 492 } 493 return m_objNodeRenderFactory; 494 } 495 496 public abstract boolean getMakeNodeDirect(); 497 498 public boolean getMakeNodeNoDirect() 499 { 500 return !getMakeNodeDirect(); 501 } 502 503 public String getCleanSelectedID() 504 { 505 return getSelectedNodeID(); 506 } 507 508 public String getSelectedID() 509 { 510 ITreeRowSource objTreeRowSource = getTreeRowSource(); 511 ITreeModelSource objTreeModelSource = getTreeModelSource(); 512 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 513 Object objNodeValueUID = objTreeRowObject.getTreeNodeUID(); 514 Object objSelectedNode = objTreeModelSource.getTreeModel() 515 .getTreeStateModel().getSelectedNode(); 516 if (objNodeValueUID.equals(objSelectedNode)) { return getSelectedNodeID(); } 517 return ""; 518 } 519 520 private String getSelectedNodeID() 521 { 522 // return getTreeDataView().getTreeView().getSelectedNodeID(); 523 return "tree"; 524 } 525 526 public String getNodeStyleClass() 527 { 528 ITreeRowSource objTreeRowSource = getTreeRowSource(); 529 ITreeModelSource objTreeModelSource = getTreeModelSource(); 530 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 531 boolean bResult = false; 532 if (objTreeRowObject != null) 533 { 534 Object objNodeValueUID = objTreeRowObject.getTreeNodeUID(); 535 Object objSelectedNode = objTreeModelSource.getTreeModel() 536 .getTreeStateModel().getSelectedNode(); 537 bResult = objNodeValueUID.equals(objSelectedNode); 538 } 539 if (bResult) { return "selectedNodeViewClass"; } 540 541 return "notSelectedNodeViewClass"; 542 } 543 544 public ITreeRowSource getTreeRowSource() 545 { 546 ITreeRowSource objSource = (ITreeRowSource) getPage().getRequestCycle() 547 .getAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE); 548 return objSource; 549 } 550 551 public ITreeModelSource getTreeModelSource() 552 { 553 ITreeModelSource objSource = (ITreeModelSource) getPage() 554 .getRequestCycle().getAttribute( 555 ITreeModelSource.TREE_MODEL_SOURCE_ATTRIBUTE); 556 return objSource; 557 } 558 559 public boolean getShowConnectImage() 560 { 561 ITreeRowSource objRowSource = getTreeRowSource(); 562 int nRowType = objRowSource.getTreeRow().getTreeRowPossiotionType(); 563 if (TreeRowObject.MIDDLE_ROW == nRowType) return true; 564 return false; 565 } 566 567 public int[] getForeachConnectImageList() 568 { 569 ITreeRowSource objTreeRowSource = getTreeRowSource(); 570 TreeRowObject objTreeRowObject = objTreeRowSource.getTreeRow(); 571 return objTreeRowObject.getLineConnImages(); 572 } 573 574 public boolean getDisableLink() 575 { 576 ITreeRowSource objRowSource = getTreeRowSource(); 577 boolean bLeaf = objRowSource.getTreeRow().getLeaf(); 578 return bLeaf; 579 } 580 581 /** 582 * Returns the openNodeImage. 583 * 584 * @return IAsset nevalidno neshto 585 */ 586 public IAsset getConnectImage() 587 { 588 IAsset objResult = null; 589 int nConnectImageType = getCurrentForeachConnectImageValue(); 590 switch(nConnectImageType) 591 { 592 case TreeRowObject.EMPTY_CONN_IMG: 593 { 594 objResult = getAsset("_whiteSpaceImage"); 595 break; 596 } 597 598 case TreeRowObject.LINE_CONN_IMG: 599 { 600 objResult = getAsset("_middleLineImage"); 601 break; 602 } 603 604 default: 605 { 606 objResult = getAsset("_whiteSpaceImage"); 607 break; 608 } 609 } 610 return objResult; 611 } 612 613 /** 614 * @return Returns the m_CurrentForeachConnectImageValue. 615 */ 616 public int getCurrentForeachConnectImageValue() 617 { 618 return m_currentForeachConnectImageValue; 619 } 620 621 /** 622 * @param currentForeachConnectImageValue 623 * The m_CurrentForeachConnectImageValue to set. 624 */ 625 public void setCurrentForeachConnectImageValue( 626 int currentForeachConnectImageValue) 627 { 628 m_currentForeachConnectImageValue = currentForeachConnectImageValue; 629 } 630 }