/**
*
*/
package org.sinnlabs.dbvim.ui;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.sinnlabs.dbvim.rules.engine.RulesEngine;
import org.sinnlabs.dbvim.ui.events.PropertiesOnOkEventListener;
import org.sinnlabs.dbvim.zk.model.ComponentFactory;
import org.sinnlabs.dbvim.zk.model.DeveloperFactory;
import org.sinnlabs.dbvim.zk.model.IDeveloperStudio;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Groupbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Row;
import org.zkoss.zul.Textbox;
/**
* @author peter.liverovsky
*
*/
public class DesignerProperties extends Groupbox implements IdSpace {
/**
*
*/
private static final long serialVersionUID = 1453994780710911695L;
/**
* Current component
*/
protected Component current = null;
/**
* A map that contains all the Properties values
*/
protected HashMap<Component, String> mapProps = null;
protected IDeveloperStudio developer;
@Wire("#gridProperties")
protected Grid gridProperties;
public DesignerProperties() {
developer = DeveloperFactory.getInstance();
// create the ui
Executions.createComponents("/components/ComponentProperties.zul", this, null);
Selectors.wireComponents(this, this, false);
setClosable(false);
// Clear properties list
clear();
}
protected void clear() {
gridProperties.getRows().getChildren().clear();
}
/**
* Set the component to display the properties
* @param comp - reference to the component
*/
public void setCurrent(Component comp) {
current = comp;
buildProperties();
}
protected void buildProperties() {
if (current == null)
return;
// clear properties
clear();
// set the window's title to display the Component's class
this.setTitle(ComponentFactory.getSimpleClassName(current) + " Properties");
// get the propery descriptors of the Component class
PropertyDescriptor[] arrDescriptors = ComponentFactory.getComponentProperties(current);
String[] customProps = RulesEngine.getComponentAttributes(current,
RulesEngine.ATTRIBUTES_CUSTOM_PROPERTIES);
if (ArrayUtils.isEmpty(arrDescriptors))
return;
// create a new map to hold all the property values
mapProps = new HashMap<Component, String>();
// create property event listener
PropertiesOnOkEventListener listener = new PropertiesOnOkEventListener(developer);
// loop through the component property descriptors
for (int i = 0; i < arrDescriptors.length; i++)
{
try
{
// get the next property descriptor
PropertyDescriptor descriptor = arrDescriptors[i];
if (descriptor == null)
continue;
// get the name of the object property
String sName = descriptor.getName();
Object value = null;
try
{
// get the Property's value
value = BeanUtils.getProperty(current, descriptor.getName());
}
catch (Exception e)
{
e.printStackTrace();
}
// create a new Grid row
Row row = new Row();
// add the Property name at the 1st column
Label lblName = new Label();
lblName.setValue(sName);
row.appendChild(lblName);
// add the Property value at the 2nd column
// generic Component object
Component cmpValue = null;
/*** Custom property ***/
if ((descriptor.getPropertyType() != String.class) &&
(descriptor.getPropertyType() != String[].class) &&
(descriptor.getPropertyType() != boolean.class) &&
(descriptor.getPropertyType() != int.class) &&
(descriptor.getPropertyType() != long.class))
{
cmpValue = RulesEngine.getSpecialProperty(current, sName, developer);
row.appendChild(cmpValue);
}
else if (ArrayUtils.isNotEmpty(customProps) &&
ArrayUtils.contains(customProps, descriptor.getName())) {
cmpValue = RulesEngine.getSpecialProperty(current, sName, developer);
row.appendChild(cmpValue);
}
/*** Boolean Values ***/
else if (descriptor.getPropertyType() == boolean.class)
{
// for boolean properties, display
// a list box with the 'True' or 'False'
// list items
Listbox list = new Listbox();
list.setMold("select");
list.setWidth("90%");
row.appendChild(list);
Listitem itemTrue = new Listitem("true");
list.appendChild(itemTrue);
Listitem itemFalse = new Listitem("false");
list.appendChild(itemFalse);
// display the current property value
// on the combobox
boolean bValue = true;
if (value != null)
bValue = Boolean.valueOf((String) value).booleanValue();
if (bValue)
list.setSelectedItem(itemTrue);
else
list.setSelectedItem(itemFalse);
cmpValue = list;
}
else
{
/*** Rest of data types ***/
// convert the value Object into the correct
// data type for display
String sValue = "";
if (value == null)
value = "";
if (value instanceof String)
sValue = (String) value;
else
sValue = String.valueOf(value);
// for any other property type, display a
// textbox component
Textbox textbox = new Textbox();
textbox.setWidth("95%");
textbox.setMaxlength(1000);
// if the size of the value string is > 50 chars,
// set the Textbox to multiline, so that the value
// is visible
if (sValue.length() > 50)
textbox.setMultiline(true);
// display the value on the Textbox
textbox.setValue(sValue);
row.appendChild(textbox);
cmpValue = textbox;
}
// add the Textbox objects to the Hashmap,
// using their Ids as the key
if (cmpValue != null)
{
gridProperties.getRows().appendChild(row);
mapProps.put(cmpValue, sName);
cmpValue.addEventListener(Events.ON_OK, listener);
cmpValue.addEventListener(Events.ON_CHANGE, listener);
cmpValue.addEventListener(Events.ON_SELECT, listener);
}
}
catch (Exception e)
{
continue;
}
}// for
}// buildProperties
public void updateProperty(Component cmp) {
String propName = mapProps.get(cmp);
if( StringUtils.isEmpty(propName) ) {
return;
}
// get the descriptor for this property
PropertyDescriptor descr;
try {
descr = PropertyUtils.getPropertyDescriptor(current, propName);
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return;
}
// Return if descriptor is null
if (descr == null) {
System.err.println("Unable to update property: Property does not exists (" +
propName + ") for component " + cmp);
return;
}
// set the new Property values, depending on
// the property type
if (cmp.getClass().getSimpleName().equals("Textbox"))
{
/*** Textbox property control ***/
// get the property value from the textbox
String sValue = ((Textbox) cmp).getValue();
// get the property's argument class
Class<?> clazzProp = descr.getPropertyType();
// cast the component to its runtime class first
// and then set its value
try {
if ((clazzProp == String.class))
PropertyUtils.setProperty(current, propName, sValue);
else if (clazzProp == int.class)
PropertyUtils.setProperty(current, propName, Integer.valueOf(sValue));
else if (clazzProp == long.class)
PropertyUtils.setProperty(current, propName, Long.valueOf(sValue));
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (cmp.getClass().getSimpleName().equals("Listbox"))
{
/*** Combobox property control ***/
// get the Listbox
Listbox list = (Listbox) cmp;
// get the selected item from the Listbox
Listitem item = list.getSelectedItem();
Boolean bValue = new Boolean((String) item.getLabel());
// set the new value
try {
PropertyUtils.setProperty(current, propName, bValue);
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
developer.getSynchronizer().synchronizeTreeWithCanvas(developer.getDesignerCanvas());
}
}