/**
*
*/
package org.sinnlabs.dbvim.zk.model;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.sinnlabs.dbvim.config.Configurator;
import org.sinnlabs.dbvim.rules.engine.RulesEngine;
import org.sinnlabs.dbvim.ui.DesignerCanvas;
import org.sinnlabs.dbvim.ui.DesignerTree;
import org.sinnlabs.dbvim.ui.DesignerTreeItem;
import org.sinnlabs.dbvim.ui.events.TreeOnDropEventListener;
import org.sinnlabs.dbvim.zk.IDisposable;
import org.zkoss.idom.Element;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Image;
import org.zkoss.zul.Label;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Treerow;
/**
* Class that performs synchronization
* between the model displayed on the
* designer Canvas and the designer Tree.
*
* @author peter.liverovsky
*
*/
public class CanvasTreeSynchronizer implements IDisposable {
/**
* The Tree level that is being processed
*/
private int nCurrentLevel = 0;
/**
*
*/
private HashMap<String, Treechildren> mapTreechildren = null;
/**
* Drag-and-drop target Treeitem
*/
private String targetTreeitemId = "";
/**
* DeveloperStudio instance
*/
private IDeveloperStudio developer = null;
// Getters / Setters
public void setTargetTreeitem(String targetTreeitemId) { this.targetTreeitemId = targetTreeitemId; }
public String getTargetTreeitem() { return targetTreeitemId; }
/**
* Default constructor
*/
public CanvasTreeSynchronizer(IDeveloperStudio developer)
{
this.developer = developer;
}
/**
* Synchronizes the Tree with the component model
* that is displayed on the canvas
* @param root The root component of the Canvas
*/
public void synchronizeTreeWithCanvas(DesignerCanvas wndCanvas)
{
if ((wndCanvas == null))
return;
// get the Tree window
DesignerTree wndTree = developer.getDesignerTree();
if (wndTree == null)
return;
// get the Tree component
Tree tree = wndTree.getTree();
// remove all Tree items
tree.clear();
// reset indices
nCurrentLevel = 0;
if (mapTreechildren != null)
{
mapTreechildren.clear();
mapTreechildren = null;
}
// set the canvas window height to 100%
// in order to accommodate smoothly all the
// components
wndCanvas.setHeight("100%");
// parse the Component model displayed on the canvas
// and display it on the Tree
parseComponentModel(wndCanvas, tree);
}
/**
* Parses input Component model that is
* currently displayed on the designer canvas
* and displays each discreet UI component as
* a Tree item on the designer Tree.
* @param wndCanvas designer Canvas
* @param tree designer Tree
*/
protected void parseComponentModel(Component canvasComponent,
Tree tree)
{
if ((canvasComponent == null) || (tree == null))
return;
if (mapTreechildren == null)
mapTreechildren = new HashMap<String, Treechildren>();
// if component still has an auto-Id assigned fix it
//canvasComponent.setId(ComponentFactory.fixAutoId(canvasComponent.getId()));
// check if component's children should be displayed
// onto the model treeview. If not, exit now
if (! RulesEngine.getComponentFlag(canvasComponent, RulesEngine.FLAG_SHOW_CHILDREN))
{
// decrease the current Tree level
if (nCurrentLevel > 0)
nCurrentLevel--;
return;
}
// get component's children
List<?> listChildren = canvasComponent.getChildren();
if ((listChildren == null) || (listChildren.size() == 0))
{
// decrease current Tree level
if (nCurrentLevel > 0)
nCurrentLevel--;
return;
}
// loop through all component's children
Iterator<?> iter = listChildren.iterator();
while (iter.hasNext())
{
// get next component in the list
Component child = (Component) iter.next();
if (child == null)
continue;
// if component still has an auto-Id assigned fix it
// child.setId(ComponentFactory.fixAutoId(child.getUuid()));
// add Component to the designer Tree
addComponentToTree(tree, child);
// increase current Tree level
nCurrentLevel++;
/*** RECURSION ***/
parseComponentModel(child, tree);
}
// decrease current Tree level
if (nCurrentLevel > 0)
nCurrentLevel--;
}
/**
* Adds a canvas Component description on the
* designer Tree
* @param tree
* @param canvasComponent
* @param parent
*/
public void addComponentToTree(Tree tree,
Component canvasComponent)
{
if ((tree == null) || (canvasComponent == null))
return;
try
{
// create a new Treeitem based on the
// specified canvas Component's properties
Treeitem item = createTreeitem(canvasComponent, tree);
if (item == null)
return;
// get parent Treeitems collection from the Tree
Collection<Treeitem> clItems = tree.getItems();
// get parent Treeitem from the Treeitem collection
Treechildren treeChildren = null;
// format key for the map
String sKey = canvasComponent.getUuid() + "_" + String.valueOf(nCurrentLevel);
// if component has any children,
// create and attach to it a Treechildren
// object and keep a reference to it
// add Treechildren object to the Hashmap
// and use as a key to the current Tree level
// (but only if it doesn't exist in the map)
if (mapTreechildren.get(sKey) == null)
{
if (canvasComponent.getChildren().size() > 0)
{
treeChildren = new Treechildren();
item.appendChild(treeChildren);
mapTreechildren.put(sKey, treeChildren);
}
}
// if Tree size is 0, then...
if (clItems.size() == 0)
{
// if size is 0, we have to add the item to
// the ROOT Treechildren collection
treeChildren = (Treechildren) tree.getTreechildren();
if (treeChildren != null)
treeChildren.appendChild(item);
// add Treechildren object to the map
if (mapTreechildren.get(sKey) == null)
mapTreechildren.put(sKey, treeChildren);
}
else
{
// get Treechildren object where this item should
// be appended to
// get Treechildren object from the map that
// is attached to the component's parent
sKey = canvasComponent.getParent().getUuid() + "_" + String.valueOf(nCurrentLevel - 1);
treeChildren = (Treechildren) mapTreechildren.get(sKey);
// append child Treeitem to its parent
if (treeChildren != null)
treeChildren.appendChild(item);
else {
treeChildren = (Treechildren) tree.getTreechildren();
if (treeChildren != null)
treeChildren.appendChild(item);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Creates a new Treeitem based on properties
* of the given canvas Component.
* @param canvasComponent Specified Canvas Component
* @return new Treeitem
*/
public Treeitem createTreeitem(Component canvasComponent,
Tree tree)
{
try
{
// create a new Treeitem to be appended to
// the designer Tree
DesignerTreeItem item = new DesignerTreeItem(canvasComponent.getUuid());
// set the item's Id, by using the Component's
// Id plus prefix 'id_'
item.setId("id_" + canvasComponent.getUuid());
// create a new Treerow that will contain
// the Component's Id with a small-scale image
// of the component's type
Treerow row = new Treerow();
item.appendChild(row);
// create Id cell
Treecell cell = new Treecell();
row.appendChild(cell);
Label lbl = new Label(canvasComponent.getId() + " [" + ComponentFactory.getSimpleClassName(canvasComponent) + "]");
cell.appendChild(lbl);
item.setDraggable("true");
item.setDroppable("true");
item.addEventListener(Events.ON_DROP, new TreeOnDropEventListener(developer));
//row.setDraggable("treeItem");
//row.setDroppable("treeItem, toolkitComponent");
//TODO: tree event listener
//row.addEventListener("onDrop", new TreeEventListener());
// create image cell
Treecell cell2 = new Treecell();
/*** Try to load the 16x16 image from the XML configuration file ***/
/*** ***/
Image img16x16 = null;
// get active configurator instance
Configurator config = null; /* DesignerToolkit.getComponentsConfigurator(); */
if (config != null)
{
// get iDOM description of the component, using the class
// name as a filter
Element domComponent = config.getElement("class", canvasComponent.getClass().getName(), null);
if (domComponent != null)
{
// retrieve 16x16 image URL
Element domImage16 = config.getElement("image16", (Element) domComponent.getParent());
// create image from the specified URL source
//if (domImage16 != null)
//img16x16 = ComponentFactory.createImage(canvasComponent.getClass().getName(),
// domImage16.getText());
}
}
if (img16x16 == null)
{
// if the image couldn't be created, assign the
// component 'Unknown' image
//img16x16 = ComponentFactory.createImage(getClass().getName(),
// "images/designer/components/unknown16.png");
}
if (img16x16 != null)
cell2.appendChild(img16x16);
/*** ***/
/*** Try to load the 16x16 image from the XML configuration file ***/
// row.appendChild(cell2);
// return the new Treeitem
return item;
}
catch (Exception e)
{
}
return null;
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
}