package com.jcommerce.gwt.client.panels; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import com.extjs.gxt.ui.client.Style.HorizontalAlignment; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.CheckBox; import com.extjs.gxt.ui.client.widget.form.CheckBoxGroup; import com.extjs.gxt.ui.client.widget.form.ComboBox; import com.extjs.gxt.ui.client.widget.form.DateField; import com.extjs.gxt.ui.client.widget.form.Field; import com.extjs.gxt.ui.client.widget.form.FormPanel; import com.extjs.gxt.ui.client.widget.form.HiddenField; import com.extjs.gxt.ui.client.widget.form.HtmlEditor; import com.extjs.gxt.ui.client.widget.form.ListField; import com.extjs.gxt.ui.client.widget.form.MultiField; import com.extjs.gxt.ui.client.widget.form.NumberField; import com.extjs.gxt.ui.client.widget.form.Radio; import com.extjs.gxt.ui.client.widget.form.RadioGroup; import com.extjs.gxt.ui.client.widget.form.TextArea; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.layout.FormData; import com.extjs.gxt.ui.client.widget.layout.FormLayout; import com.google.gwt.user.client.Window; import com.jcommerce.gwt.client.ContentWidget; import com.jcommerce.gwt.client.PageState; import com.jcommerce.gwt.client.form.BeanObject; import com.jcommerce.gwt.client.form.SimpleOptionData; import com.jcommerce.gwt.client.model.IModelObject; import com.jcommerce.gwt.client.resources.Resources; import com.jcommerce.gwt.client.service.CreateService; import com.jcommerce.gwt.client.service.ReadService; import com.jcommerce.gwt.client.service.UpdateService; import com.jcommerce.gwt.client.util.FormUtils; import com.jcommerce.gwt.client.widgets.SimpleStaticComboBox; public abstract class BaseEntityEditPanel extends ContentWidget { public abstract static class State extends PageState { public static final String ISEDIT = "isedit"; public static final String ID = "Id"; public abstract String getPageClassName(); public void setIsEdit(boolean isEdit){ setValue(ISEDIT, String.valueOf(isEdit)); } public boolean getIsEdit() { return Boolean.valueOf((String)getValue(ISEDIT)).booleanValue(); } public void setId(Long gtid) { setValue(ID, gtid); } public Long getId() { return (Long)getValue(ID); } } protected abstract State getCurState(); protected abstract void setupPanelLayout(); protected abstract String getEntityClassName(); Button btnNew = new Button(); Button btnReset = new Button(); // protected void onRender(Element parent, int index) { // super.onRender(parent, index); @Override protected void afterRender() { super.afterRender(); // add(formPanel); super.add(formPanel); // formPanel.setBodyBorder(false); //formPanel.setWidth(800); FormLayout fl = new FormLayout(); fl.setLabelWidth(150); fl.setLabelPad(50); formPanel.setLayout(fl); formPanel.setWidth("100%"); setupPanelLayout(); btnNew.setText(Resources.constants.ok()); btnReset.setText(Resources.constants.reset()); // panel.add(btnNew); // panel.add(btnCancel); formPanel.setButtonAlign(HorizontalAlignment.CENTER); formPanel.addButton(btnNew); formPanel.addButton(btnReset); btnNew.addSelectionListener(selectionListener); btnReset.addSelectionListener( new SelectionListener<ButtonEvent>() { public void componentSelected(ButtonEvent sender) { formPanel.reset(); } } ); } // get the setting for long field public FormData lfd() { FormData fd = new FormData(500, -1); return fd; } // get the setting for short field public FormData sfd() { FormData fd = new FormData(300, -1); return fd; } // get the setting for tiny field public FormData tfd() { FormData fd = new FormData(100, -1); return fd; } protected SelectionListener<ButtonEvent> selectionListener = new SelectionListener<ButtonEvent>() { public void componentSelected(ButtonEvent sender) { // log("on Submit: formPanel="+formPanel); try { if(!formPanel.isValid()) { Window.alert("Please check input before submit."); return; } String error = validateForm(); if(error!=null && error.length()>0) { Window.alert("Please check input before submit, error is: "+error); return; } if(!formPanel.isDirty()) { // TODO this is optimisitic. should change it to based on a strategy configuration? Window.alert("the form is not changed!!!"); gotoSuccessPanel(); return; } submit(); } catch (Exception e) { e.printStackTrace(); } } }; protected String validateForm() { return null; } protected void submit() { // default implementation is thru GWT-RPC Map<String, String> props = FormUtils.getPropsFromForm(formPanel); BeanObject form = new BeanObject(getEntityClassName(), (Map)props); if (getCurState().getIsEdit()) { Long id = getCurState().getId(); new UpdateService().updateBean(id, form, new UpdateService.Listener() { public synchronized void onSuccess(Boolean success) { gotoSuccessPanel(); } public void onFailure(Throwable caught) { // TODO a point to define common behavior } }); }else { new CreateService().createBean(form, new CreateService.Listener() { public synchronized void onSuccess(String id) { log("new onSuccess( "+id); getCurState().setId(Long.valueOf(id)); gotoSuccessPanel(); } }); } } protected FormPanel formPanel = new FormPanel(); public abstract void gotoSuccessPanel(); protected abstract void postSuperRefresh(); public void refresh() { try { formPanel.clear(); } catch (Exception ex) { ex.printStackTrace(); } if(getCurState().getIsEdit()) { retrieveEntity(); } else { obj = new BeanObject(); postSuperRefresh(); } } // get called when refresh(), if isEdit protected void retrieveEntity() { new ReadService().getBean(getEntityClassName(), getCurState().getId(), new ReadService.Listener() { public void onSuccess(BeanObject bean) { obj = bean; // populate those statically rendered fields populateFields(); // sub-class should populate those "dynamic" fields including combox/list, etc postSuperRefresh(); } }); } public void log(String s) { // StringBuffer buf = new StringBuffer(); // buf.append("[").append(this.getClass().getName()).append("]:").append(s); // Logger.getClientLogger().log(buf.toString()); // System.out.println(buf.toString()); } public BeanObject getEntity() { return obj; } public void populateField(Field field) { Map<String, Object> mapAttribute = obj.getProperties(); String name = field.getName(); Object value = mapAttribute.get(name); log("[populateField]: name:"+name+", value:"+(value==null?"null":value.toString()+", valueclass: "+value.getClass().getName())); populateField(field, value); } public void populateField(Field field, Object value) { if(field instanceof CheckBoxGroup) { List<Field<?>> boxes = (List<Field<?>>)((CheckBoxGroup)field).getAll(); for(Field b:boxes) { CheckBox box = (CheckBox)b; populateField(box); } return; } if(field instanceof RadioGroup) { // go on, to avoid going into MultiField(see below) } else if(field instanceof MultiField) { List<Field<?>> subFields = ((MultiField)field).getAll(); for(Field subField:subFields) { populateField(subField); } return; } if(value==null) { return; } if(field instanceof SimpleStaticComboBox) { SimpleStaticComboBox<BeanObject> box = (SimpleStaticComboBox<BeanObject>)field; ListStore<BeanObject> store = box.getStore(); List<BeanObject> selection = new ArrayList<BeanObject>(); BeanObject bo = store.findModel(SimpleOptionData.VALUE, value); if(bo!=null) { selection.add(bo); } box.setSelection(selection); } else if(field instanceof ComboBox) { ComboBox<BeanObject> box = (ComboBox<BeanObject>)field; ListStore<BeanObject> store = box.getStore(); List<BeanObject> selection = new ArrayList<BeanObject>(); // store may not have been initialized with dyna data yet. skip it if(store.getCount()>0) { BeanObject bo = store.findModel(IModelObject.ID, value); if(bo!=null) { selection.add(bo); } box.setSelection(selection); } } else if(field instanceof ListField){ ListField<BeanObject> lf = (ListField<BeanObject>)field; ListStore<BeanObject> store = lf.getStore(); Collection<String> v = (Collection<String>)value; List<BeanObject> selection = new ArrayList<BeanObject>(); if(store.getCount()>0) { for(String vv:v) { BeanObject bo = store.findModel(IModelObject.ID, vv); if(bo!=null) { selection.add(bo); } } lf.setSelection(selection); } } else if(field instanceof DateField) { log("TODO: convert date format?? using gxt-DateTimePropertyEditor"); DateField df = ((DateField)field); if(value instanceof Long) { df.setValue(new Date((Long)value)); } else if(value instanceof Date){ df.setValue((Date)value); } } else if(field instanceof TextField || field instanceof TextArea || field instanceof HtmlEditor) { field.setOriginalValue(value); field.setValue(value); } else if (field instanceof CheckBox) { ((CheckBox)field).setValue((Boolean)value); } else if (field instanceof HiddenField) { ((HiddenField)field).setValue(value); } else if(field instanceof NumberField) { ((NumberField)field).setOriginalValue((Number)value); ((NumberField)field).setValue((Number)value); } else if(field instanceof RadioGroup) { RadioGroup rg = (RadioGroup)field; List<Field<?>> radios = (List<Field<?>>)rg.getAll(); for(Field<?> r:radios) { Radio radio = (Radio)r; if(value.toString().equals(radio.getValueAttribute())) { radio.setValue(true); // radio.setRawValue("true"); } else { radio.setValue(false); // radio.setRawValue("false"); } } } else if(field instanceof CheckBox) { CheckBox box = (CheckBox)field; if(value.toString().equals(box.getValueAttribute())) { box.setRawValue("true"); } else { box.setRawValue("false"); } } } public void populateFields() { List<Field<?>> fields = formPanel.getFields(); for(Field field:fields) { populateField(field); } } protected BeanObject obj; }