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