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 }