-
GXT and EditorDriver
I'm trying to use the GWT editor driver to reduce boilerplate code. I've been able to get it to work pretty well on TextFields and checkboxes but I haven't been able to get it to work with ComboBoxes or my stateful Icon buttons. I'm guessing that this is because they don't directly match up with GWT's paradigm. I can't prove this but since the bean is holding the ID of the correct ComboBox value rather than the value itself, I think the editor is trying to set the wrong value. I suspect a similar problem with my icon buttons since they have a setValue method but don't extend Field.
My question is how can I special case this? Where do I add methods to say "for these two widgets handle them like this?"
I'm using SimpleBeanEditorDriver and my view implements Editor. Can anyone tell me how to massage the editor to work with the data correctly?
-
GXT3 combo box work well with GWT editor
Could you post some code to find the error.
-
Can you be more specific? What wiring are you trying to do with a combobox or icon button? As far as adding additional methods to better detail the editing process, you can use the ValueAwareEditor<T>, CompositeEditor<T>, HasEditorDelegate<T>, etc interfaces to get more details about the editing process, same as if you are using standard GWT widgets. Beyond that, I'd need to know what you are trying to do.
A ComboBox is a natural for a field - if a bean has a 'size' property, where the value can be 'small', 'medium', or 'large', the ComboBox can be populated with those values. When the user changes the ComboBox and driver.flush() is invoked, the user's selection will be pushed into the bean.
I'm not sure how you want an IconButton to behave as an Editor<T> in a form - can you describe how you would expect that to work?
-
Sorry about the lack of code. The relevant portions of the class look like this:
Code:
public class Node implements Serializable, IsSerializable
{
private int ID;
private int appId;
private String name;
private int sequence;
private int masterId;
private int shardId;
private boolean readEnabled;
private boolean writeEnabled;
private boolean failOver;
private int serverId;
private int failOverPriority;
private TreeNodeStatus status;
public TreeNodeStatus getStatus() {
return status;
}
public void setStatus(TreeNodeStatus status) {
this.status = status;
}
public int getFailOverPriority() {
return failOverPriority;
}
public void setFailOverPriority(int failOverPriority) {
this.failOverPriority = failOverPriority;
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public int getShardId() {
return shardId;
}
public void setShardId(int shardId) {
this.shardId = shardId;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSequence() {
return sequence;
}
public void setSequence(int sequence) {
this.sequence = sequence;
}
public int getMasterId() {
return masterId;
}
public void setMasterId(int master) {
this.masterId = master;
}
public boolean isReadEnabled() {
return readEnabled;
}
public void setReadEnabled(boolean readEnabled) {
this.readEnabled = readEnabled;
}
public boolean isWriteEnabled() {
return writeEnabled;
}
public void setWriteEnabled(boolean writeEnabled) {
this.writeEnabled = writeEnabled;
}
public boolean isFailOver() {
return failOver;
}
public void setFailOver(boolean failOver) {
this.failOver = failOver;
}
public int getServerId() {
return serverId;
}
public void setServerId(int server) {
this.serverId = server;
}
}
public class EditNodeView extends BaseEditWindow implements ViewActions, Editor<Node>
{
@Path("name")
TextField name;
@Path("failOverPriority")
private NumberField<Integer> failOverOrder;
//private PasswordField password;
@Ignore
private TextButton cancel;
@Ignore
private TextButton save;
@Ignore
private Node record;
@Ignore
private String mainSchema;
@Ignore
private CheckBox hasData;
@Path("serverId")
private ComboBox<Server> combo;
@Ignore
private ListStore<Server> store;
@Path("readEnabled")
ParameterButton readable;
@Path("writeEnabled")
ParameterButton writeable;
@Path("failOver")
ParameterButton failover;
private NodeDriver driver;
@Ignore
private TextButton addNew;
public EditNodeView(Window win)
{
super("editNodeView");
setWindow(win);
ScaleBaseLayoutHelper.bindWindow(this, win);
ScaleBaseComboItem serverItem = new ScaleBaseComboItem();
serverItem.setName(properties.general_server());
serverItem.setType(ScaleBaseFormType.REFERENCE);
serverItem.setLabel(new LabelProvider<Server>(){
@Override
public String getLabel(Server item)
{
if(item.getName() != null && item.getName().trim().length() != 0)
return item.getName();
else
return PropertiesWrapper.properties.general_server()+":" + item.getPort();
}});
serverItem.setModel(new ModelKeyProvider<Server>(){
@Override
public String getKey(Server item) {
return ""+item.getID();
}});
combo = (ComboBox<Server>) ScaleBaseFormLayout.createGenericWidget(serverItem, isPopup());
store = combo.getStore();
ScaleBaseFormItem nameItem = new ScaleBaseFormItem();
nameItem.setType(ScaleBaseFormType.STRING);
nameItem.setName(properties.general_name());
nameItem.setDescription(properties.node_name_desc());
name = (TextField) ScaleBaseFormLayout.createGenericWidgit(nameItem, isPopup());
ScaleBaseFormItem readItem = new ScaleBaseFormItem();
readItem.setType(ScaleBaseFormType.BOOLEAN);
readItem.setName(properties.node_readable());
readItem.setDescription(properties.node_readable_desc());
readable = (ParameterButton) ScaleBaseFormLayout.createGenericWidgit(readItem, isPopup());
ScaleBaseFormItem writeItem = new ScaleBaseFormItem();
writeItem.setType(ScaleBaseFormType.BOOLEAN);
writeItem.setName(properties.node_writable());
writeItem.setDescription(properties.node_writable_desc());
writeable = (ParameterButton) ScaleBaseFormLayout.createGenericWidgit(writeItem, isPopup());
writeable.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event) {
if(failover.getValue() && writeable.getValue() == false)
{
failOverOrder.enable();
}
else
{
failOverOrder.disable();
failOverOrder.setValue(10);
}
}});
ScaleBaseFormItem failItem = new ScaleBaseFormItem();
failItem.setType(ScaleBaseFormType.BOOLEAN);
failItem.setName(properties.node_failover());
failItem.setDescription(properties.node_failover_desc());
failover = (ParameterButton) ScaleBaseFormLayout.createGenericWidgit(failItem, isPopup());
failover.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event) {
if(failover.getValue() && writeable.getValue() == false)
{
failOverOrder.enable();
}
else
{
failOverOrder.disable();
failOverOrder.setValue(10);
}
}});
ScaleBaseFormItem priorityItem = new ScaleBaseFormItem();
priorityItem.setType(ScaleBaseFormType.INTEGER);
priorityItem.setName(properties.node_failoverOrder());
priorityItem.setDescription(properties.node_failoverOrder_desc());
failOverOrder = (NumberField<Integer>) ScaleBaseFormLayout.createGenericWidgit(priorityItem, isPopup());
failOverOrder.setAllowNegative(false);
HorizontalLayoutContainer comboButtonLayout = new HorizontalLayoutContainer();
ScaleBaseFormLayout comboLayout = new ScaleBaseFormLayout(serverItem, isPopup());
comboButtonLayout.add(comboLayout);
addNew = new TextButton("Add New Server");
addNew.setStyleName("AddNewServerButton");
addNew.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event) {
EditServerView view = ServerPage.getEditServer();
view.setRecord(null);
view.show();
}});
Margins m = new Margins(10,10,10,10);
comboButtonLayout.add(addNew, new HorizontalLayoutData(-1,-1,m));
if(isPopup())
add(comboButtonLayout, new VerticalLayoutData(1, .2));
else
add(comboButtonLayout, new VerticalLayoutData(1, .1));
ScaleBaseFormLayout nameLayout = new ScaleBaseFormLayout(nameItem, isPopup());
add(nameLayout);
ScaleBaseFormLayout readLayout = new ScaleBaseFormLayout(readItem, isPopup());
add(readLayout);
ScaleBaseFormLayout writeLayout = new ScaleBaseFormLayout(writeItem, isPopup());
add(writeLayout);
ScaleBaseFormLayout failLayout = new ScaleBaseFormLayout(failItem, isPopup());
add(failLayout);
ScaleBaseFormLayout priorityLayout = new ScaleBaseFormLayout(priorityItem, isPopup());
add(priorityLayout);
StandardFooter footer = new StandardFooter(win, this){
@Override
public void save() {
getLogic().save();
}};
add(footer, new VerticalLayoutData(-1, -1));
save = footer.getSave();
cancel = footer.getCancel();
setButton(save);
driver = GWT.create(NodeDriver.class);
driver.initialize(this);
}
public void setRecord(Object o)
{
Node r = (Node) o;
setButton(save);
this.record = r;
store.clear();
store.addAll(GlobalData.servers);
store.commitChanges();
if(record != null)
{
this.setAdd(false);
addNew.hide();
driver.edit(record);
combo.setValue(store.findModelWithKey(""+record.getServerId()));
readable.setValue(r.isReadEnabled());
writeable.setValue(r.isWriteEnabled());
failover.setValue(r.isFailOver());
}
else
{
addNew.show();
this.setAdd(true);
driver.edit(new Node());
combo.clear();
readable.setValue(true);
writeable.setValue(false);
failover.setValue(false);
}
if(record == null || record.getFailOverPriority() == 0)
failOverOrder.setValue(10);
else
failOverOrder.setValue(record.getFailOverPriority());
if(failover.getValue() && writeable.getValue() == false)
failOverOrder.enable();
else
failOverOrder.disable();
//does the license allow failover
if(GlobalData.license.getFailover() == 0)
{
failOverOrder.setValue(0);
failOverOrder.disable();
failover.setValue(false);
failover.disable();
}
}
@Override
public boolean isDirty()
{
return driver.isDirty();
}
@Ignore
public TextField getNameField()
{
return name;
}
@Ignore
public ComboBox<Server> getCombo() {
return combo;
}
public void setCombo(ComboBox<Server> combo) {
this.combo = combo;
}
@Ignore
public NumberField<Integer> getFailOverOrder() {
return failOverOrder;
}
public void setFailOverOrder(NumberField<Integer> failOverOrder) {
this.failOverOrder = failOverOrder;
}
@Ignore
public ParameterButton getReadable() {
return readable;
}
public void setReadable(ParameterButton readable) {
this.readable = readable;
}
@Ignore
public ParameterButton getWriteable() {
return writeable;
}
public void setWriteable(ParameterButton writeable) {
this.writeable = writeable;
}
@Ignore
public ParameterButton getFailover() {
return failover;
}
public void setFailover(ParameterButton failover) {
this.failover = failover;
}
@Ignore
public String getMainSchema() {
return mainSchema;
}
public void setMainSchema(String mainSchema) {
this.mainSchema = mainSchema;
}
@Ignore
public TextButton getSaveButton()
{
return save;
}
@Ignore
public TextButton getCancelButton()
{
return cancel;
}
@Ignore
public CheckBox getHasData() {
return hasData;
}
public void setHasData(CheckBox hasData) {
this.hasData = hasData;
}
@Override
public Object getRecord()
{
return record;
}
@Override
public Object getNewRecord()
{
Node n = driver.flush();
if(record == null)
{
n.setShardId(ContextBus.getClusterNode().getRawID());
}
else
{
n.setShardId(record.getShardId());
n.setID(record.getID());
}
n.setServerId(combo.getValue().getID());
n.setReadEnabled(readable.getValue());
n.setWriteEnabled(writeable.getValue());
n.setFailOver(failover.getValue());
n.setFailOverPriority(failOverOrder.getValue());
return n;
}
@Override
public void handleAjax(AjaxResult crud)
{
ActionResult result = crud.getResult();
if(result == ActionResult.NOT_UNIQUE_NAME)
{
this.markField(name.getId(), name, PropertiesWrapper.properties.general_friendlyname_not_unique());
return;
}
}
@Override
public void setWindowSize(Window w) {
w.setPixelSize(540, 270);
}
@Override
public void eventReceived(EventType type) {
if(type == EventType.RELOAD_SERVERS)
{
store.clear();
store.addAll(GlobalData.servers);
store.commitChanges();
combo.setValue(store.get(store.size()-1));
}
}
@Ignore
public TextButton getAddNew() {
return addNew;
}
public void setAddNew(TextButton addNew) {
this.addNew = addNew;
}
}
public class ParameterButton extends IconButton
{
private Parameter p;
private boolean value;
public ParameterButton(Parameter ph)
{
super("foo");
this.p = ph;
if(ph.getValue().equals("1"))
value = true;
else
value = false;
//value = Boolean.parseBoolean(p.getValue());
this.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event)
{
value = !value;
update(value);
p.setModified(true);
}});
this.update(value);
}
public ParameterButton(boolean b)
{
super("foo");
this.p = null;
value = b;
this.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event)
{
value = !value;
update(value);
if(p != null)
p.setModified(true);
}});
this.update(b);
}
public ParameterButton()
{
super("foo");
this.p = null;
value = false;
this.addSelectHandler(new SelectHandler(){
@Override
public void onSelect(SelectEvent event)
{
value = !value;
update(value);
if(p != null)
p.setModified(true);
}});
this.update(false);
}
public void update(boolean value)
{
if(p != null)
this.p.setValue(""+value);
this.value = value;
this.removeStyleName(this.getStyleName());
if(value)
{
this.changeStyle("parameterButtonOn");
}
else
{
this.changeStyle("parameterButtonOff");
}
}
public boolean isValue() {
return value;
}
public boolean getValue() {
return value;
}
public void setValue(boolean v) {
update(v);
}
}
package com.scalebase.api.dto.configuration;
import java.io.Serializable;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.scalebase.api.dto.TreeNodeStatus;
public class Server implements Serializable, IsSerializable
{
private int ID;
private String name;
private int port;
private String userName;
private String password;
private int hostId;
private TreeNodeStatus status;
public TreeNodeStatus getStatus() {
return status;
}
public void setStatus(TreeNodeStatus status) {
this.status = status;
}
public int getHostId() {
return hostId;
}
public void setHostId(int host) {
this.hostId = host;
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
The relevant parts are the constructor and the method called setRecord. That's where the relevant Node object is passed in and all values assigned. I do driver.edit but also wind up doing a lot of it manually because the ParameterButtons and comboBox don't seem to populate properly. It's not a runnable version because to run it you'd need a ton of our base classes, we have a pretty complex hierarchy of classes.
I suspect one of the issues deals with the comboBox being of type server rather than of type Node. I'm not sure what's wrong with the ParameterButtons. The ScaleBaseFormLayout is just a class of helper methods which create FieldItems of various types with consolidated and reused code (we were trying to make it easy to modify our stylenames, margins, align, etc). I know we would normally do this just by modifying CSS but after a requirement change had me scurry through our codebase and change every single FieldLabel we had I resolved never to go through that again.
The basic idea here is in EditNodeView when I call edit on the driver, I want it to take the serverId from the Node object and use it to set the ComboBox. This doesn't seem to be working.
Our ParameterButtons are our company's replacement for checkboxes. They take in a boolean value (either in the constructor or in setValue) and based on that they change their style which changes their icon. Basically they are a button that say "On" or "Off"
-
In the class Node I see
Code:
public class Node {
private int serverId;
}
In EditNodeView
Code:
public class EditNodeView implements Editor<Node> {
@Path("serverId")
private ComboBox<Server> combo;
}
@Path("serverId") //is of type int.
ComboBox<Server> //is for store objects of type Server
you should have something like this
Code:
public class Node {
private Server server;
}
Code:
public class EditNodeView implements Editor<Node> {
@Path("server")
private ComboBox<Server> combo;
}
A small runnable project with your ParameterButtons without custom classes could be helpful to give you some advice. You can upload to github or in zip file.
-
yeah I thought the bug might be something like that. So my question is how to write a method that will special case it. I want to add the glue that will tell the ComboBox to take that int as an Id but I was trying to put it into the Driver class.
Thanks
-
You can provide an implementation of com.sencha.gxt.data.shared.Converter<N, O> to specify that you want to turn a N in the bean to a O in the field. For example, you would make a Converter<Server, Integer> to allow a ComboBox<Integer> to edit a `Integer getServer()`/`void setServer(Integer server)` property.
Then, pass this and the comboBox itself to a ConverterEditorAdapter. It must be package protected or greater, like a normal editor, and it will wrap up the ComboBox (which must be @Ignored then to prevent it from binding to something that doesnt make sense).
In cases like this, where the editor doesn't directly match the property, you should get errors when you run the app in dev mode or when you compile it - are you not getting those?
One last note: You are putting @Ignored on lots of things that probably don't need it. If something doesn't implement either Editor or IsEditor, it won' t be treated as an editor, and doesn't need to be ignored. Also, if something is private, it isn't visible anyway, and doesn't need to be ignored.