PDA

View Full Version : EditorGrid and DateTime beanmodel



yopiyop
10 Aug 2009, 1:25 AM
Hello,

How to add a date picker and a timepicker to a sortable editorGrid (Sort by day, date and time) ?

http://www.freetab.free.fr//Ext.ux.TreeTaskNode/2009-08-10_111501.gif

I want to share the java.util.Date model between the date column and the time column.

I have successfully sort the columns but when I pick a date, the time is reset and the time Picker doesn't work ...


Thx for ideas and help.


public void onModuleLoad() {

List<Record> l= new ArrayList<Record>();
l.add(new Record(new Date(2009-1900, 5, 22, 11, 10)));
l.add(new Record(new Date(2009-1900, 5, 20, 10, 10)));
l.add(new Record(new Date(2009-1900, 5, 22, 4, 12)));
l.add(new Record(new Date(2009-1900, 5, 22, 05, 55)));
l.add(new Record(new Date(2009-1900, 5, 23, 10, 10)));
l.add(new Record(new Date(2009-1900, 5, 5, 4, 12)));
l.add(new Record(new Date(2009-1900, 5, 1, 18, 30)));

MemoryProxy<List<Record>> proxy = new MemoryProxy<List<Record>>(l);
BeanModelReader reader = new BeanModelReader();
ListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);
final ListStore<BeanModel> store = new ListStore<BeanModel>(loader);

//----------------------------
List<ColumnConfig> columns = new ArrayList<ColumnConfig>();

ColumnConfig cc = new ColumnConfig("day", "Day", 60); //@see javabean getDay()
cc.setRenderer(new GridCellRenderer<ModelData>(){
public Object render(ModelData model, String property
, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return
DateTimeFormat.getFormat("EEEEE").format((Date) model.get("date"));
}
});
columns.add(cc);

cc = new ColumnConfig("date","Date" , 90);
cc.setDateTimeFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
DateField dateField = new DateField();
dateField.getPropertyEditor().setFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
cc.setEditor(new CellEditor(dateField) );
columns.add(cc);

cc = new ColumnConfig("time","Time" , 45);//@see javabean getTime()
cc.setDateTimeFormat(DateTimeFormat.getFormat("HH:mm"));
cc.setRenderer(new GridCellRenderer<ModelData>(){
public Object render(ModelData model, String property
, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return
DateTimeFormat.getFormat("HH:mm").format((Date) model.get("date"));
}
});
// TimeField timeField = new TimeField();
// timeField.setFormat(DateTimeFormat.getFormat("HH:mm"));
// cc.setEditor(new CellEditor(timeField));
columns.add(cc);

ColumnModel cm = new ColumnModel(columns);

final EditorGrid<BeanModel> grid = new EditorGrid<BeanModel>(store, cm);
grid.setLoadMask(true);
ContentPanel p = new ContentPanel(new FitLayout());
p.setSize(400, 300);
p.setHeading("Try Order by Day, date and time, edit date, time...with a unique Date model");
p.add(grid);
RootPanel.get().add(p);
loader.load();
}
@SuppressWarnings("serial")
public class Record implements BeanModelTag,Serializable{
private Date date;
public Record() {}
public Record(Date date) {
super();
this.date = date;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getDay(){
return date.getDay();
}
public int getTime(){
return date.getHours()*60*60+date.getMinutes()*60;
}
}

yopiyop
13 Aug 2009, 4:14 AM
Nobody on How to resolve this common problem ?

Arno.Nyhm
13 Aug 2009, 7:06 AM
if you digg to the java code of Celleditor and EditorSupport then this codesnippet gives can give you a hint:


protected void onEditComplete(CellEditor ed, Object value, Object startValue) {
editing = false;
activeEditor = null;
ed.removeListener(Events.SpecialKey, editorListener);
ed.removeListener(Events.Complete, editorListener);
ed.removeListener(Events.CancelEdit, editorListener);
Record r = activeRecord;
String field = cm.getDataIndex(ed.col);
if ((value == null && startValue != null)
|| (value != null && !value.equals(startValue))) {
GridEvent<M> ge = new GridEvent<M>(grid);
ge.setRecord(r);
ge.setProperty(field);
ge.setValue(value);
ge.setStartValue(startValue);
ge.setRowIndex(ed.row);
ge.setColIndex(ed.col);

if (grid.fireEvent(Events.ValidateEdit, ge)) { // <---- look here
r.set(ge.getProperty(), ge.getValue()); // <---- and here
r.setValid(ge.getProperty(), ed.getField().isValid(true));
grid.fireEvent(Events.AfterEdit, ge);
}
}

grid.getView().focusCell(ed.row, ed.col, false);
}if you look for this event:


grid.fireEvent(Events.ValidateEdit, ge)then this GridEvent has the record and the new value. you can overwrite the value and add the time to this, because later its used by this command

r.set(ge.getProperty(), ge.getValue());PS: its just a gues... i dont try it.


PS2: it is a small cosmetic problem? the class name n gxt is EditorSupport but on many other places it is called only editsupport

Arno.Nyhm
13 Aug 2009, 8:58 AM
with this listener you can get it working properly with the date column:



grid.addListener(Events.ValidateEdit, new Listener<GridEvent>() {

public void handleEvent(GridEvent be) {
if (be.getType() == Events.ValidateEdit) {
final String property = be.getProperty();
if ("date".equals(property)) {
Date date_new = (Date) be.getValue();
Date date_old = (Date) be.getRecord().get("date");
// i added only hours and minutes because in table also only HH:mm
Date date_combined = new DateWrapper(date_new)
.add(DateWrapper.Unit.HOUR, date_old.getHours())
.add(DateWrapper.Unit.MINUTE, date_old.getMinutes()).asDate();
be.setValue(date_combined);
}
}
}
});


with the second column (Time) it is more complicated, because the getTime need to bee type of Time and in the Record you need also a setTime(Time newTime) which combines the things

Time getTime(){ return new Time(date); }

Arno.Nyhm
13 Aug 2009, 9:28 AM
this works:




/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.yournamehere.client.forum.code.snippets;

import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.MemoryProxy;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.DateWrapper;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.extjs.gxt.ui.client.widget.form.TimeField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.RootPanel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
*
* @author anonym
*/
public class ForumThread77108 implements EntryPoint {

public void onModuleLoad() {

List<ForumThread77108Record> l = new ArrayList<ForumThread77108Record>();
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 22, 11, 10)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 20, 10, 10)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 22, 4, 12)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 22, 05, 55)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 23, 10, 10)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 5, 4, 12)));
l.add(new ForumThread77108Record(new Date(2009 - 1900, 5, 1, 18, 30)));

MemoryProxy<List<ForumThread77108Record>> proxy = new MemoryProxy<List<ForumThread77108Record>>(l);
BeanModelReader reader = new BeanModelReader();
ListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);
final ListStore<BeanModel> store = new ListStore<BeanModel>(loader);

//----------------------------
List<ColumnConfig> columns = new ArrayList<ColumnConfig>();

ColumnConfig cc = new ColumnConfig("day", "Day", 60);
//@see javabean getDay()
cc.setRenderer(new GridCellRenderer<ModelData>() {

public Object render(ModelData model, String property, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return DateTimeFormat.getFormat("EEEEE").format((Date) model.get("date"));
}
});
columns.add(cc);

cc = new ColumnConfig("date", "Date", 90);
cc.setDateTimeFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
DateField dateField = new DateField();
dateField.getPropertyEditor().setFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
cc.setEditor(new CellEditor(dateField));
columns.add(cc);

cc = new ColumnConfig("time", "Time", 80);//@see javabean getTime()
cc.setDateTimeFormat(DateTimeFormat.getFormat("HH:mm"));
cc.setRenderer(new GridCellRenderer<ModelData>() {

public Object render(ModelData model, String property, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return DateTimeFormat.getFormat("HH:mm").format(((Time) model.get("time")).getDate());
}
});
TimeField timeField = new TimeField();
timeField.setFormat(DateTimeFormat.getFormat("HH:mm"));
cc.setEditor(new CellEditor(timeField));
columns.add(cc);

ColumnModel cm = new ColumnModel(columns);

final EditorGrid<BeanModel> grid = new EditorGrid<BeanModel>(store, cm);
grid.setLoadMask(true);
ContentPanel p = new ContentPanel(new FitLayout());
p.setSize(400, 300);
p.setHeading("Try Order by Day, date and time, edit date, time...with a unique Date model");
p.add(grid);

grid.addListener(Events.ValidateEdit, new Listener<GridEvent>() {

public void handleEvent(GridEvent be) {
if (be.getType() == Events.ValidateEdit) {
final String property = be.getProperty();
if ("date".equals(property)) {
Date date_new = (Date) be.getValue();
Date date_old = (Date) be.getRecord().get("date");
Date date_combined = new Date(
date_new.getYear(),
date_new.getMonth(),
date_new.getDate(),
date_old.getHours(),
date_old.getMinutes());

GWT.log("Date new: " + date_new, null);
GWT.log("Date old: " + date_old, null);
GWT.log("Date com: " + date_combined, null);
be.setValue(date_combined);

} else if ("time".equals(property)) {
// it can be null if you click and not select an date
if (be.getValue() != null) {
Date date_new = ((Time) be.getValue()).getDate();
Date date_old = (Date) be.getRecord().get("date");
Date date_combined = new Date(
date_old.getYear(),
date_old.getMonth(),
date_old.getDate(),
date_new.getHours(),
date_new.getMinutes());
GWT.log("Date new: " + date_new, null);
GWT.log("Date old: " + date_old, null);
GWT.log("Date com: " + date_combined, null);
be.setValue(date_combined);
}
}
}
}
});

loader.load();
RootPanel.get().add(p);
}
}
and here the records


package org.yournamehere.client.forum.code.snippets;

import com.extjs.gxt.ui.client.data.BeanModelTag;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.google.gwt.core.client.GWT;
import java.io.Serializable;
import java.util.Date;

@SuppressWarnings(value = "serial")
public class ForumThread77108Record implements BeanModelTag, Serializable {

private Date date;

public ForumThread77108Record() {
super();
}

public ForumThread77108Record(Date date) {
super();
this.date = date;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public int getDay() {
return date.getDay();
}

// public int getTime() {
// return date.getHours() * 60 * 60 + date.getMinutes() * 60;
// }

public Time getTime() {
return new Time(date);
}

// This not works? Why? ClassCast Exception: "cannot cast From Date to Time"
// public void setTime(Time time) {
// Date date_new = time.getDate();
// ...

public void setTime(Date date_new) {
Date date_old = date;
Date date_combined = new Date(
date_old.getYear(),
date_old.getMonth(),
date_old.getDate(),
date_new.getHours(),
date_new.getMinutes());
GWT.log("set Date new: " + date_new, null);
GWT.log("set Date old: " + date_old, null);
GWT.log("set Date com: " + date_combined, null);
date = date_combined;

}
}





but there are also open questions:

- the previous date is not selected if i click on the TimePicker (if it is 03:11 != 03:15 then i could understand this. but it is also if the time matches the TimePicker Time 03:15 => 03:15)
- why i need in the bean a setTime(Date date) instead of setTime(Time time) if i have a Time getTime()?

yopiyop
14 Aug 2009, 1:15 AM
Thanks for helping

there is a lot of code design issue in the GXT lib with Time !
the sort by Time doesn't work with your code, it is a store sorter problem.
A new method columnConfig.setSorter(new MyComparator) is needed.

My current solution :



@SuppressWarnings("serial")
public class Record implements BeanModelTag,Serializable{
private Date date;
public Record() {}
public Record(Date date) {
super();
this.date = date;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getDay(){
return date.getDay();
}

public Time getTime() {
return new Time(date);//Order BY NOT OK
}
// design issue ?
public void setTime(Date time) {
if(time==null) return;
date.setHours(time.getHours());
date.setMinutes(time.getMinutes());
}

}


public void onModuleLoad() {

List<Record> l= new ArrayList<Record>();
l.add(new Record(new Date(2009-1900, 5, 22, 11, 10)));
l.add(new Record(new Date(2009-1900, 5, 20, 10, 10)));
l.add(new Record(new Date(2009-1900, 5, 22, 4, 12)));
l.add(new Record(new Date(2009-1900, 5, 22, 05, 55)));
l.add(new Record(new Date(2009-1900, 5, 23, 10, 10)));
l.add(new Record(new Date(2009-1900, 5, 5, 4, 12)));
l.add(new Record(new Date(2009-1900, 5, 1, 18, 30)));

MemoryProxy<List<Record>> proxy = new MemoryProxy<List<Record>>(l);
BeanModelReader reader = new BeanModelReader();
ListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);
final ListStore<BeanModel> store = new ListStore<BeanModel>(loader);
store.setStoreSorter(new StoreSorter<BeanModel>(){
public int compare(Store<BeanModel> store, BeanModel m1, BeanModel m2, String property) {
if("time".equals(property)){
Time t1 = ((Time)m1.get("time"));
Time t2 = ((Time)m2.get("time"));
return (t1.getHour()*60+t1.getMinutes()) - (t2.getHour()*60+t2.getMinutes());
}else
return super.compare(store, m1, m2, property);
}

});
//----------------------------
List<ColumnConfig> columns = new ArrayList<ColumnConfig>();

ColumnConfig cc = new ColumnConfig("day", "Day", 60); //@see javabean getDay()
cc.setRenderer(new GridCellRenderer<ModelData>(){
public Object render(ModelData model, String property
, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return
DateTimeFormat.getFormat("EEEEE").format((Date) model.get("date"));
}
});
columns.add(cc);

cc = new ColumnConfig("date","Date" , 90);
cc.setDateTimeFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
DateField dateField = new DateField();
dateField.getPropertyEditor().setFormat(DateTimeFormat.getFormat("dd/MM/yyyy"));
cc.setEditor(new CellEditor(dateField) );
columns.add(cc);

cc = new ColumnConfig("time","Time" , 65);//@see javabean getTime()
cc.setDateTimeFormat(DateTimeFormat.getFormat("HH:mm"));
cc.setRenderer(new GridCellRenderer<ModelData>(){
public Object render(ModelData model, String property
, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return
DateTimeFormat.getFormat("HH:mm").format(((Time)model.get(property)).getDate());
}
});
TimeField timeField = new TimeField();
timeField.setFormat(DateTimeFormat.getFormat("HH:mm"));
cc.setEditor(new CellEditor(timeField));
columns.add(cc);

ColumnModel cm = new ColumnModel(columns);

final EditorGrid<BeanModel> grid = new EditorGrid<BeanModel>(store, cm);
grid.setLoadMask(true);
ContentPanel p = new ContentPanel(new FitLayout());
p.setSize(400, 300);
p.setHeading("Try Order by Day, date and time, edit date, time...with a unique Date model");
p.add(grid);

grid.addListener(Events.ValidateEdit, new Listener<GridEvent<ModelData>>() {
public void handleEvent(GridEvent<ModelData> be) {
if (be.getType() == Events.ValidateEdit) {
GWT.log("-- OLD Date: " + ((Date) be.getRecord().get("date")), null);
final String property = be.getProperty();
if ("date".equals(property)) {
DateWrapper w = new DateWrapper((Date) be.getValue());
w = w.clearTime();
w = w.addHours(((Date) be.getRecord().get("date")).getHours());
w = w.addMinutes(((Date) be.getRecord().get("date")).getMinutes());
be.setValue(w.asDate());
GWT.log("-- NEW Date: " + w.asDate(), null);
} else if ("time".equals(property)) {
// it can be null if you click and not select an date
if (be.getValue() == null) return;
DateWrapper w = new DateWrapper((Date) be.getRecord().get("date"));
w = w.clearTime();
w = w.addHours(((Time) be.getValue()).getHour());
w = w.addMinutes(((Time) be.getValue()).getMinutes());
be.setValue(w.asDate());
GWT.log("-- NEW Date: " + w.asDate(), null);
}
}
}
});


RootPanel.get().add(p);
loader.load();

}



but there are also open questions:

- the previous date is not selected if i click on the TimePicker (if it is 03:11 != 03:15 then i could understand this. but it is also if the time matches the TimePicker Time 03:15 => 03:15)
- why i need in the bean a setTime(Date date) instead of setTime(Time time) if i have a Time getTime()?

Yes, il seems to be design issue...

Also, my feature request are:

- Datepicker (seems ok)
-Timepicker (exist but some issues)
- DateTimePicker (1 editor field with date and time)
- MonthPicker
- WeekPicker
- Simple default configuration with grid and editorGrid
- Default Comparator for Time BeanModel
- new methods in ColumnConfig : setFormatter, setSorter