/** * */ package org.sinnlabs.dbvim.ui.db; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.sinnlabs.dbvim.db.Value; import org.sinnlabs.dbvim.db.model.DBField; import org.sinnlabs.dbvim.db.model.IDBField; import org.sinnlabs.dbvim.form.FormFieldResolver; import org.sinnlabs.dbvim.menu.MenuItem; import org.sinnlabs.dbvim.menu.MenuResolver; import org.sinnlabs.dbvim.menu.MenuResolverFactory; import org.sinnlabs.dbvim.ui.IField; import org.sinnlabs.dbvim.ui.events.MenuSelectEvent; import org.sinnlabs.dbvim.ui.events.VimEvents; import org.sinnlabs.dbvim.zk.model.IFormComposer; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.CreateEvent; import org.zkoss.zk.ui.event.DropEvent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.InputEvent; import org.zkoss.zk.ui.event.KeyEvent; import org.zkoss.zk.ui.event.MouseEvent; import org.zkoss.zk.ui.select.Selectors; import org.zkoss.zk.ui.select.annotation.Wire; import org.zkoss.zul.Button; import org.zkoss.zul.Idspace; import org.zkoss.zul.Label; import org.zkoss.zul.Menupopup; import org.zkoss.zul.Space; import org.zkoss.zul.impl.InputElement; /** * Class implements basic db field logic * @author peter.liverovsky * */ public abstract class BaseField<T, E extends InputElement> extends Idspace implements IField<T>, IDBField { /** * */ private static final long serialVersionUID = -8390813627874916864L; protected DBField dbField; protected String map; protected String formName; protected String menu; @Wire protected Label label; @Wire protected E value; @Wire protected Space space; @Wire protected Button btnMenu; protected IFormComposer composer; protected boolean isChildable = true; protected Menupopup popup; protected MenuResolver menuResolver = null; private boolean readOnly; private boolean displayOnly = false; private boolean clientUpdate = false; protected BaseField(String zulUrl, DBField field) { super(); isChildable = true; dbField = field; // initialize component after all attributes are loaded addEventListener(Events.ON_CREATE, new EventListener<CreateEvent>() { @Override public void onEvent(CreateEvent e) throws Exception { onCreate(e.getArg()); } }); /* Create the ui */ Executions.createComponents(zulUrl, this, null); Selectors.wireComponents(this, this, false); // lock the component to avoid to create new child elements. isChildable = false; readOnly = value.isReadonly(); final BaseField<T, E> t = this; /* init event listeners */ value.addEventListener(Events.ON_CHANGE, new EventListener<InputEvent>() { @Override public void onEvent(InputEvent e) throws Exception { InputEvent ie = new InputEvent(e.getName(), t, e.getValue(), e.getPreviousValue()); Events.postEvent(ie); } }); value.addEventListener(Events.ON_FOCUS, new EventListener<Event>() { @Override public void onEvent(Event e) throws Exception { Event ne = new Event(e.getName(), t, e.getData()); Events.postEvent(ne); } }); value.addEventListener(Events.ON_BLUR, new EventListener<Event>() { @Override public void onEvent(Event e) throws Exception { Event ne = new Event(e.getName(), t, e.getData()); Events.postEvent(ne); } }); value.addEventListener(Events.ON_OK, new EventListener<KeyEvent>() { @Override public void onEvent(KeyEvent e) throws Exception { KeyEvent ne = new KeyEvent(e.getName(), t, e.getKeyCode(), e.isCtrlKey(), e.isShiftKey(), e.isAltKey(), e.getReference()); Events.postEvent(ne); } }); value.addEventListener(Events.ON_CTRL_KEY, new EventListener<KeyEvent>() { @Override public void onEvent(KeyEvent e) throws Exception { KeyEvent ne = new KeyEvent(e.getName(), t, e.getKeyCode(), e.isCtrlKey(), e.isShiftKey(), e.isAltKey(), e.getReference()); Events.postEvent(ne); } }); value.addEventListener(Events.ON_DROP, new EventListener<DropEvent>() { @Override public void onEvent(DropEvent e) throws Exception { DropEvent ne = new DropEvent(e.getName(), t, e.getDragged(), e.getX(), e.getY(), e.getPageX(), e.getPageY(), e.getKeys()); Events.postEvent(ne); } }); if (btnMenu != null) { btnMenu.addEventListener(Events.ON_CLICK, new EventListener<MouseEvent>() { @Override public void onEvent(MouseEvent arg0) throws Exception { if (popup != null) popup.open(btnMenu); } }); } } /** * Initialize menu items * @throws Exception */ private void initMenu() throws Exception { if (menuResolver != null) { popup = new Menupopup(); popup.setStyle("overflow: auto; max-height: 100vh;"); for(MenuItem i : menuResolver.getItems()) { // Add items to the popup menu FieldMenuItem item = new FieldMenuItem(i); item.setLabel(i.getLabel().toString()); /** Add item event listener **/ item.addEventListener(Events.ON_CLICK, new EventListener<MouseEvent>() { @Override public void onEvent(MouseEvent evnt) throws Exception { if (evnt.getTarget() != null) { FieldMenuItem item = (FieldMenuItem) evnt.getTarget(); // if user defined the event listener onMenuSelect // then we do not take default action // User must implement logic manually if (Events.isListened(BaseField.this, VimEvents.ON_MENUSELECTED, false)) { Event e = new MenuSelectEvent( VimEvents.ON_MENUSELECTED, BaseField.this, item.getItem()); Events.postEvent(e); } else { // if event listener is not defined // then we just set the field value // if value is a String if (item.getItem().getValue() instanceof String) BaseField.this.fromString((String) item.getItem().getValue()); else BaseField.this.setDBValue(fromObject(item.getItem().getValue())); } } } }); popup.appendChild(item); } // add popup to the field isChildable = true; this.appendChild(popup); isChildable = false; } } /* (non-Javadoc) * @see com.asd.dbuibuilder.db.model.IDBField#getName() */ @Override public String getName() { return dbField.getName(); } @Override public String getTableName() { return dbField.getTableName(); } @Override public String getCatalogName() { return dbField.getCatalogName(); } @Override public String getFullName() { return dbField.getFullName(); } /* (non-Javadoc) * @see com.asd.dbuibuilder.db.model.IDBField#getDBTypeName() */ @Override public String getDBTypeName() { return dbField.getDBTypeName(); } /* (non-Javadoc) * @see com.asd.dbuibuilder.db.model.IDBField#getDBType() */ @Override public int getDBType() { return dbField.getDBType(); } /* (non-Javadoc) * @see org.sinnlabs.dbvim.ui.IField#setDBField(com.asd.dbuibuilder.db.model.DBField) */ @Override public void setDBField(DBField field) { dbField = field; if (field != null) { label.setValue(field.getName()); if (field.isGenerated()) { value.setReadonly(true); } map = field.getName(); } } /* (non-Javadoc) * @see org.sinnlabs.dbvim.ui.IField#getMapping() */ @Override public String getMapping() { return map; } /* (non-Javadoc) * @see org.sinnlabs.dbvim.ui.IField#setMapping(java.lang.String) */ @Override public void setMapping(String map) { this.map = map; } @Override public String getForm() { return formName; } @Override public void setForm(String form) { formName = form; } /** * Returns attached menu name * @return null if menu not attached, otherwise attached menu name */ public String getMenu() { return menu; } /** * Attach menu to the field. * @param menu Menu name or null to detach menu. * @throws Exception */ public void setMenu(String menu) throws Exception { this.menu = menu; if (btnMenu != null && StringUtils.isNotEmpty(menu)) { btnMenu.setVisible(true); } } /* (non-Javadoc) * @see org.sinnlabs.dbvim.ui.IField#setDBValue(com.asd.dbuibuilder.db.Value) */ @Override public void setDBValue(Value<T> v) { value.setRawValue(v.getValue()); } /* (non-Javadoc) * @see org.sinnlabs.dbvim.ui.IField#getDBValue() */ @SuppressWarnings("unchecked") @Override public Value<T> getDBValue() { return new Value<T>((T)value.getRawValue(), dbField); } @Override public void setValue(T val) { value.setRawValue(val); } @Override public void setValueFromString(String v) { Value<T> val = fromString(v); setDBValue(val); } @SuppressWarnings("unchecked") @Override public T getValue() { return (T)value.getRawValue(); } /** * Returns field label */ public String getLabel() { return label.getValue(); } /** * Sets field label * @param l field label */ public void setLabel(String l) { label.setValue(l); } /** * Idicates that field is ReadOnly * @return True if field is read only, otherwise false */ public boolean isReadonly() { return value.isReadonly(); } /** * Sets field read only flag * @param val True if field is read only, otherwise false */ public void setReadonly(boolean val) { value.setReadonly(val); readOnly = val; } /** * Returns space between field label and field value */ public String getSpace() { return space.getSpacing(); } /** * Sets space between field label and field value */ public void setSpace(String sp) { space.setSpacing(sp); } public void setHflex(String flex) { value.setHflex(flex); } public String getHflex() { return value.getHflex(); } @Override public boolean isGenerated() { return dbField.isGenerated(); } @Override public boolean isNullable() { return dbField.isNullable(); } @Override public void setErrorMessage(String err) { value.setErrorMessage(err); } @Override public void clearErrorMessage() { value.clearErrorMessage(); } @Override protected boolean isChildable() { return isChildable; } @Override public void setFieldMode(int mode) { if (mode == IField.MODE_SEARCH) { value.setReadonly(false); } else if (mode == IField.MODE_MODIFY) { value.setReadonly(readOnly); } } @Override public DBField getDBField() { return dbField; } @Override public boolean isDisplayOnly() { return displayOnly; } @Override public void setDisplayOnly(boolean val) { displayOnly = val; } /** * Returns whether this field can update from client. * @return True if client side update is enabled, otherwise false */ public boolean isClientUpdate() { return clientUpdate; } /** * Sets the client update flag * @param val true if client update enabled, otherwise false */ public void setClientUpdate(boolean val) { this.setAttribute("org.zkoss.zk.ui.updateByClient", val); clientUpdate = val; } /** * @return Returns menu resolver or null if menu is not set */ public MenuResolver getMenuResolver() { return menuResolver; } @Override public void onCreate(Map<?,?> args) throws Exception { if (args != null) { if (!displayOnly) { FormFieldResolver f = (FormFieldResolver) args.get("resolver"); if (f != null) { dbField = f.getFieldByMapping(formName, map); } } Object c = args.get("composer"); if (c!= null) { composer = (IFormComposer) c; if (StringUtils.isNotBlank(menu)) { menuResolver = MenuResolverFactory.getMenuResolver(menu, composer); if (btnMenu != null) { btnMenu.setVisible(true); } initMenu(); if (menuResolver == null) { throw new IllegalStateException("Field menu does not exists: " + menu); } } } } } }