GWT: Why isn't my Cell's FieldUpdater working? - java

I have a GWT CellTable that I have just moved from a PopupPresenter to a regular nested PresenterWidget. I am using GWTP.
Since moving it, the FieldUpdater on my ButtonCell is not calling the update() method at all. I have tried a test button and the same thing happens.
// edit offer
Column<OfferDto, String> buttonColumn = new Column<OfferDto, String>(new ButtonCell(IconType.PLUS, ButtonType.SUCCESS))
{
#Override
public String getValue(OfferDto object)
{
return "View/Edit";
}
};
buttonColumn.setFieldUpdater(new FieldUpdater<OfferDto, String>()
{
#Override
public void update(int index, OfferDto object, String value)
{
// NOTHING IN HERE IS BEING CALLED
System.out.println("Update called in setFieldUpdater...");
getUiHandlers().onAddCommsClick(index, object);
}
});
table.addColumn(buttonColumn);
I'm at a loss as to what could be causing it. Other regular buttons in the same View still work OK, it's just the CellTable.

Related

GWT Java - CellTable - ButtonCell - how to make it respond to a click

I have the following ButtonCell. How do I make it respond to a click please (e.g., addClickHandler)? I have tried a number of ways I have found yet none work. None of the Window.alert return a response.
ButtonCell selectButton = new ButtonCell();
Column <HikingMeals,String> update = new Column <HikingMeals,String>(selectButton){
#Override
public String getValue(HikingMeals selectButton)
{
return "Select";
}
public void execute(HikingMeals selectButton) {
// EDIT CODE
Window.alert("Pressed");
}
//#Override
public void update(int index, HikingMeals object, String value) {
// The user clicked on the button for the passed auction.
Window.alert("Pressed2");
}
};
table.addColumn(update, "Select");
You just need to set a FieldUpdater on the update column:
update.setFieldUpdater(new FieldUpdater<HikingMeals, String>() {
#Override
public void update(int index, HikingMeals object, String value) {
Window.alert("Pressed");
}
});

How to add a hook to save event for existing DataObject in NetBeans?

I want to make some processing every time when a particular DataObject is saved. If I understand NetBeans IDE API correctly, there is an Savable interface that can be used to implement saving options for custom editors. The problem here is that I do not want to implement my own editor, nor DataObject. I have a MIME type that is edited by a default Gsf editor (the common scripting language api) and has a GsfDataObject (I expect with the DOSavable). I want to keep all that way, just to add a hook, maybe a callback method or something, that would be called every time a save is done upon a given GsfDataObject (and I want a default save action be called, I dont want to override it).
So far I came to this simple solution but it seems ugly (it is more or less inspired by http://wiki.netbeans.org/DevFaqListenForSaveEvents ):
// I have a FileObject fobj
final DataObject dobj = DataObject.find(fobj);
dobj.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(DataObject.PROP_MODIFIED)) {
if (!((Boolean) evt.getOldValue()) & ((Boolean) evt.getNewValue())) {
System.out.println(">>>> here it gets modified");
} else {
System.out.println(">>>> here the data object gets saved");
}
}
}
});
However, this is not called only when the save is done, but also when the file gets modified, but then the modifications are reverted by Ctrl + Z. It only checks whether the data object changes its state from modified to unmodified. Is there a way to hook to a save event only?
P.S.: I tried to call new SJDOSavable(dobj).add(); in the moment when the DataObject gets modified and then to remove it in the other branch. However, the handleSave method does not get called. SJDOSavable class is a simple Savable implemented according to DOSavable from the DataSystems API:
private static final class SJDOSavable extends AbstractSavable implements Icon {
final DataObject obj;
public SJDOSavable(DataObject obj) {
this.obj = obj;
}
#Override
public String findDisplayName() {
return obj.getNodeDelegate().getDisplayName();
}
#Override
protected void handleSave() throws IOException {
System.out.println(">>>>> but this does not get called");
}
#Override
public boolean equals(Object other) {
if (other instanceof SJDOSavable) {
SJDOSavable dos = (SJDOSavable) other;
return obj.equals(dos.obj);
}
return false;
}
#Override
public int hashCode() {
return obj.hashCode();
}
final void remove() {
unregister();
}
final void add() {
register();
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
icon().paintIcon(c, g, x, y);
}
#Override
public int getIconWidth() {
return icon().getIconWidth();
}
#Override
public int getIconHeight() {
return icon().getIconHeight();
}
private Icon icon() {
return ImageUtilities.image2Icon(obj.getNodeDelegate().getIcon(BeanInfo.ICON_COLOR_16x16));
}
}
Did you try this ?
http://wiki.netbeans.org/DevFaqListenForSaveEvents
Also if you want to listen to global Save events, it seems you can do that now.
https://netbeans.org/bugzilla/show_bug.cgi?id=140719

How to handle Datagrid column's events from Presenter?

I am using GWT MVP and I would like to handle events in columns of DataGrid from Presenter.
From GWT DataGrid ShowCase ...
// First name.
Column<ContactInfo, String> firstNameColumn =
new Column<ContactInfo, String>(new EditTextCell()) {
#Override
public String getValue(ContactInfo object) {
return object.getFirstName();
}
};
firstNameColumn.setSortable(true);
sortHandler.setComparator(firstNameColumn, new Comparator<ContactInfo>() {
#Override
public int compare(ContactInfo o1, ContactInfo o2) {
return o1.getFirstName().compareTo(o2.getFirstName());
}
});
dataGrid.addColumn(firstNameColumn, constants.cwDataGridColumnFirstName());
firstNameColumn.setFieldUpdater(new FieldUpdater<ContactInfo, String>() {
#Override
public void update(int index, ContactInfo object, String value) {
// Here I would like to call RPC methods
}
});
dataGrid.setColumnWidth(firstNameColumn, 20, Unit.PCT);
Above example , this code is writing in View side and it just really example. As mvp pattern , I just need to call rpc request to update database. This can't be done in View side but I have no idea how to set FieldUpdater from my presenter. Please help me how can I figure it out ? Thanks greatly .
There are two ways to do this (MVP I or MVP II way):
MVP 1 style:
http://www.gwtproject.org/articles/mvp-architecture.html
Create a setter on your View (i.e. setFieldUpdater(FieldUpdater<ContactInfo, String>)) that takes a FieldUpdater and adds it to the column. From the Presenter you can call (provided that view is the reference to your View).
Presenter:
view.setFieldUpdater(new FieldUpdater<ContactInfo, String>() {
#Override
public void update(int index, ContactInfo object, String value) {
// Make the RPC call
}
});
MVP2 style:
http://www.gwtproject.org/articles/mvp-architecture-2.html
If you have a reference from your View back to your Presenter. Then you can call a function on your Presenter.
View:
firstNameColumn.setFieldUpdater(new FieldUpdater<ContactInfo, String>() {
#Override
public void update(int index, ContactInfo object, String value) {
getPresenter().onUpdate(info,value);
}
});

GWT Editors - how to add N sub-editors of the same type based on a Collection

I have an object, Supply, that can either be an ElecSupply or GasSupply (see related question).
Regardless of which subclass is being edited, they all have a list of BillingPeriods.
I now need to instantiate N number of BillingPeriodEditors based on the contents of that list, and am pretty baffled as to how I should do it.
I am using GWTP. Here is the code of the SupplyEditor I have just got working:
public class SupplyEditor extends Composite implements ValueAwareEditor<Supply>
{
private static SupplyEditorUiBinder uiBinder = GWT.create(SupplyEditorUiBinder.class);
interface SupplyEditorUiBinder extends UiBinder<Widget, SupplyEditor>
{
}
#Ignore
final ElecSupplyEditor elecSupplyEditor = new ElecSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor> elecSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor>(
elecSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof ElecSupply);
if(!(value instanceof ElecSupply))
{
showGasFields();
}
else
{
showElecFields();
}
}
};
#Ignore
final GasSupplyEditor gasSupplyEditor = new GasSupplyEditor();
#Path("")
final AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor> gasSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor>(
gasSupplyEditor)
{
#Override
public void setValue(final Supply value)
{
setValue(value, value instanceof GasSupply);
if(!(value instanceof GasSupply))
{
showElecFields();
}
else
{
showGasFields();
}
}
};
#UiField
Panel elecPanel, gasPanel, unitSection;
public SupplyEditor()
{
initWidget(uiBinder.createAndBindUi(this));
gasPanel.add(gasSupplyEditor);
elecPanel.add(elecSupplyEditor);
}
// functions to show and hide depending on which type...
#Override
public void setValue(Supply value)
{
if(value instanceof ElecSupply)
{
showElecFields();
}
else if(value instanceof GasSupply)
{
showGasFields();
}
else
{
showNeither();
}
}
}
Now, as the list of BillingPeriods is a part of any Supply, I presume the logic for this should be in the SupplyEditor.
I got some really good help on the thread How to access PresenterWidget fields when added dynamically, but that was before I had implemented the Editor Framework at all, so I think the logic is in the wrong places.
Any help greatly appreciated. I can post more code (Presenter and View) but I didn't want to make it too hard to read and all they do is get the Supply from the datastore and call edit() on the View.
I have had a look at some examples of ListEditor but I don't really get it!
You need a ListEditor
It depends of how you want to present them in your actual view, but the same idea apply:
public class BillingPeriodListEditor implements isEditor<ListEditor<BillingPeriod,BillingPeriodEditor>>, HasRequestContext{
private class BillingPeriodEditorSource extends EditorSource<BillingPeriodEditor>{
#Override
public EmailsItemEditor create(final int index) {
// called each time u add or retrive new object on the list
// of the #ManyToOne or #ManyToMany
}
#Override
public void dispose(EmailsItemEditor subEditor) {
// called each time you remove the object from the list
}
#Override
public void setIndex(EmailsItemEditor editor, int index) {
// i would suggest track the index of the subeditor.
}
}
private ListEditor<BillingPeriod, BillingPeriodEditor> listEditor = ListEditor.of(new BillingPeriodEditorSource ());
// on add new one ...
// apply or request factory
// you must implement the HasRequestContext to
// call the create.(Proxy.class)
public void createNewBillingPeriod(){
// create a new one then add to the list
listEditor.getList().add(...)
}
}
public class BillingPeriodEditor implements Editor<BillingPeriod>{
// edit you BillingPeriod object
}
Then in you actual editor edit as is in the path Example getBillingPeriods();
BillingPeriodListEditor billingPeriods = new BillingPeriodListEditor ();
// latter on the clickhandler
billingPeriods.createNewBillingPeriod()
You are done now.

ComboBoxModel events not working

I seem not to grasp the concept of Events and such. After reading a while on how to implement the listeners and such I came across the Java tutorial saying I should extend AbstractListModel to get the data event firing. For some reason it still doesn't work.
Is there anything I'm doing wrong?
And what kind of code is expected at addListDataListener(ListDataListener l) for it to work? Since I don't understand that either.
public class CarComboBox extends AbstractListModel<Object> implements ComboBoxModel<Object> {
private JdbcRowSet jdbc;
private int size = 0;
private String selection;
public CarComboBox() {
try {
jdbc = new Query().getCarInfo();
jdbc.beforeFirst();
while (jdbc.next()) {
size++;
}
jdbc.beforeFirst();
}
catch (SQLException ex) {
System.err.println(ex.toString());
}
}
#Override
public void setSelectedItem(Object anItem) {
selection = (String) anItem;
}
#Override
public Object getSelectedItem() {
return selection;
}
#Override
public void addListDataListener(ListDataListener l) {
}
#Override
public void removeListDataListener(ListDataListener l) {
}
#Override
public int getSize() {
return size;
}
#Override
public String getElementAt(int index) {
try {
jdbc.absolute(index + 1);
return jdbc.getString(2);
}
catch (SQLException ex) {
System.out.println(ex.toString());
}
return null;
}
}
And to add a listener to the CarComboBox I do:
CarComboBox ccb = new CarComboBox();
ccb.addListDataListener(new ListDataListener()
I'm guessing that you are using the official tutorial.
However you should not touch ListModel and ComboBoxModel. Those are more advanced features you probably do not need.
The 4 examples in the tutorial do NOT use ListModel and ComboBoxModel.
If you use a standard JComboBox (no ListModel or ComboBoxModel), what happens is that when someone makes a selection, an ActionEvent is fired. This event is magically fired by Swing; you don't have to worry about how it is generated. However what is your responsibility is to have some (zero, one or more) objects being able to receive and do something about the ActionEvent:
public class MyClass implements ActionListener {
JComboBox comboBox = ...;
...
// You must register explicitly every ActionListener that you
// want to receive ActionEvent's from comboBox.
// Here we register this instance of MyClass.
comboBox.addActionListener(this);
...
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JComboBox) {
System.out.println("MyClass registered an ActionEvent from a JComboBox.");
System.out.println("Selected: " +
((JComboBox) e.getSource()).getSelectedItem());
}
}
}
Note that if you don't have any other ActionEvent's fired by different Swing components you
can skip the if (e.getSource() instanceof JComboBox) since you know your ActionEvent always comes from a JComboBox.
In my example the JComboBox is inside MyClass, but it does not have to be:
JComboBox comboBox = ...;
MyClass myClass = ...;
comboBox.addActionListener(myClass);
...
comboBox.addActionListener(someOtherActionListener);
You don't need to override addListDataListener() and removeListDataListener() method. The AbstractListModel already take care of the listeners. Here is the implementation of AbstractListModel.addListDataListener():
public void addListDataListener(ListDataListener l) {
listenerList.add(ListDataListener.class, l);
}
The idea of abstract classes is that they do most of the work for you. Usually you only need to implement abstract methods.
XXListener and XXModel are different sides of the coin: the former is the observer to the latter which is the observable. The listener registers itself to the model when it wants to get notified on changes. It's the responsibility of the model to
manage its listeners (that's typically handled already by the AbstractXXModel, as already explained by #userWhateverNumber ;)
fire the notifications if appropirate: that's the part a custom model must take over, in your case
like
#Override
public void setSelectedItem(Object item) {
selection = item;
fireContentChanged(this, -1, -1);
}
Arguably (there are personal preferences around :-) you often don't need custom model implementations but can just as well re-use the provided DefaultXXModels. In your context and assuming the content of the resultset is immutable it might be an option to fill the default model with the data at construction time, like
DefaultComboBoxModel model = new DefaultComboBoxModel();
forEachRowInResultSet {
model.addElement(resultSet.getString(2));
}
If, on the other hand, the content changes then your model implementation is invalid anyway: the model must notify its listeners whenever something had changed
Object one = model.getElementAt(index);
Object other = model.getElementAt(index)
if (!one.equals(other)) {
listener must have received a contentsChanged
}

Categories