Cannot understand ComboBoxTableCell in a TableView - javafx-8

I have read everything available on this site and others; I have cut and pasted every line of code ever written on this subject ( am willing to bet). This is what the result is:
final class Books extends Group {
private TableView table = new TableView();
private ObservableList<Book> data = FXCollections.observableArrayList();
final HBox hb = new HBox();
final TextField Title = new TextField();
final TextField Author = new TextField();
final TextField Publisher = new TextField();
final TextField Copywrite = new TextField();
final TextField ISBN = new TextField();
final Boolean CheckedOut = false;
final Label Whom;
final Button addButton = new Button("Add");
Boolean FirstRead = true;
public static class Book {
private final SimpleStringProperty title;
private final SimpleStringProperty author;
private final SimpleStringProperty publisher;
private final SimpleStringProperty copywrite;
private final SimpleStringProperty isbn;
private final BooleanProperty checkedout;
private final SimpleStringProperty who;
Book(String Titl, String Auth, String Publ,
String Cpywrit, String IsBn, Boolean ChkdOut, String WHO) {
this.title = new SimpleStringProperty(Titl);
this.author = new SimpleStringProperty(Auth);
this.publisher = new SimpleStringProperty(Publ);
this.copywrite = new SimpleStringProperty(Cpywrit);
this.isbn = new SimpleStringProperty(IsBn);
this.checkedout = new SimpleBooleanProperty(ChkdOut);
this.who = new SimpleStringProperty(WHO);
}
public boolean isCheckedOut() {
return checkedout.get();
}
public void setCheckedOut(boolean international) {
this.checkedout.set(international);
}
public BooleanProperty isCheckedOutProperty() {
return checkedout;
}
public String getTitle() {
return title.get();
}
public void setTitle(String Title) {
title.set(Title);
}
public String getAuthor() {
return author.get();
}
public void setAutor(String Author) {
author.set(Author);
}
public String getPublisher() {
return publisher.get();
}
public void setPublisher(String Publisher) {
publisher.set(Publisher);
}
public String getCopywrite() {
return copywrite.get();
}
public void setCopywrite(String Copywrite) {
copywrite.set(Copywrite);
}
public String getIsbn() {
return isbn.get();
}
public void setIsbn(String ISBN) {
isbn.set(ISBN);
}
public Boolean getIo() {
return checkedout.get();
}
public void setIo(Boolean CheckedOut) {
checkedout.set(CheckedOut);
}
public String getWho() {
return who.get();
}
public void setWho(String Who) {
who.set(Who);
}
public ObservableValue<String> whoProperty() {
return who;
}
}
public Books(final File User) throws IOException {
this.Whom = new Label("inLibrary");
this.data = FXCollections.<Book>observableArrayList(
(Book bk) -> new Observable[]{bk.isCheckedOutProperty()
});
final PhoneList p = new PhoneList(User);
final Label label = new Label("Book List");
label.setFont(new Font("Arial", 20));
table.setPrefSize(600, 400);
table.setEditable(true);
TableColumn nameCol = bookName();
TableColumn authorCol = bookAuthor();
TableColumn publisherCol = bookPublisher();
TableColumn copywriteCol = bookCopywrite();
TableColumn isbnCol = bookISBN();
final TableColumn<Book, Boolean> ioCol = new TableColumn<>("In/Out");
ioCol.setMinWidth(50);
ioCol.setEditable(true);
ioCol.setCellValueFactory(new PropertyValueFactory<>("isCheckedOut"));
final Callback<TableColumn<Book, Boolean>, TableCell<Book, Boolean>> iocellFactory = CheckBoxTableCell.forTableColumn(ioCol);
ioCol.setCellFactory((TableColumn<Book, Boolean> column) -> {
TableCell<Book, Boolean> iocell = iocellFactory.call(column);
iocell.setAlignment(Pos.CENTER);
return iocell;
});
ioCol.setCellFactory(iocellFactor
final TableColumn<String, Book> whoCol = new TableColumn<>("Who to");
whoCol.setMinWidth(100);
whoCol.setEditable(true);
whoCol.setCellValueFactory(new PropertyValueFactory<>("who"));
whoCol.setCellFactory(ComboBoxTableCell.forTableColumn(new StringConverter<Book>() {
#Override
public String toString(Book string) {
return string.getWho();
}
#Override
public Book fromString(String string) {
return null;
}
}, data));
AddBook(nameCol, authorCol, publisherCol, copywriteCol, isbnCol, ioCol, whoCol, User);
data.addListener((javafx.collections.ListChangeListener.Change<? extends Book> change) -> {
while (change.next()) {
if (change.wasUpdated() && FirstRead != true) {
try {
System.out.println("List changed");
writeFile(User);
} catch (IOException ex) {
Logger.getLogger(Books.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, hb);
getChildren().addAll(vbox);
try {
readFile(User);
} catch (Exception ex) {
Logger.getLogger(Books.class.getName()).log(Level.SEVERE, null, ex);
}
}
private TableColumn bookISBN() {
TableColumn isbnCol = new TableColumn("ISBN #");
isbnCol.setMinWidth(100);
isbnCol.setCellValueFactory(
new PropertyValueFactory<>("isbn"));
isbnCol.setCellFactory(TextFieldTableCell.forTableColumn());
return isbnCol;
}
private TableColumn bookCopywrite() {
TableColumn copywriteCol = new TableColumn("Copywrite");
copywriteCol.setMinWidth(100);
copywriteCol.setCellValueFactory(
new PropertyValueFactory<>("copywrite"));
copywriteCol.setCellFactory(TextFieldTableCell.forTableColumn());
return copywriteCol;
}
private TableColumn bookPublisher() {
TableColumn publisherCol = new TableColumn("Publisher");
publisherCol.setMinWidth(100);
publisherCol.setCellValueFactory(
new PropertyValueFactory<>("publisher"));
publisherCol.setCellFactory(TextFieldTableCell.forTableColumn());
return publisherCol;
}
private TableColumn bookAuthor() {
TableColumn authorCol = new TableColumn("Author");
authorCol.setMinWidth(100);
authorCol.setCellValueFactory(
new PropertyValueFactory<>("author"));
authorCol.setCellFactory(TextFieldTableCell.forTableColumn());
return authorCol;
}
private TableColumn bookName() {
TableColumn nameCol = new TableColumn("Title");
nameCol.setMaxWidth(100);
nameCol.setCellValueFactory(
new PropertyValueFactory<>("title"));
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
return nameCol;
}
private void AddBook(TableColumn nameCol, TableColumn authorCol, TableColumn publisherCol,
TableColumn copywriteCol, TableColumn isbnCol, TableColumn ioCol, TableColumn whoCol, final File User) {
table.setItems(data);
table.getColumns().addAll(nameCol, authorCol, publisherCol, copywriteCol, isbnCol, ioCol, whoCol);
addButton.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
addBook();
try {
writeFile(User);
} catch (IOException ex) {
Logger.getLogger(Books.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void addBook() {
data.add(new Book(
Title.getText(),
Author.getText(),
Publisher.getText(),
Copywrite.getText(),
ISBN.getText(),
CheckedOut,
Whom.getText()
));
Title.clear();
Author.clear();
Publisher.clear();
Copywrite.clear();
ISBN.clear();
}
});
hb.getChildren().addAll(Title, Author, Publisher,
Copywrite, ISBN, addButton);
hb.setSpacing(10);
Title.setPromptText("Tile of Book");
Title.setMaxWidth(nameCol.getPrefWidth());
Author.setMaxWidth(authorCol.getPrefWidth());
Author.setPromptText("Author");
Publisher.setMaxWidth(publisherCol.getPrefWidth());
Publisher.setPromptText("Publisher");
Copywrite.setMaxWidth(copywriteCol.getPrefWidth());
Copywrite.setPromptText("Year Copywrite");
ISBN.setMaxWidth(isbnCol.getPrefWidth());
ISBN.setPromptText("ISBN #");
}
private void writeFile(File User) throws IOException {
File file = new File(User + "/Books.txt");
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outFile = new PrintWriter(bw);
if (table.getItems() != null) {
data.stream().map((data1) -> {
if (data1.getTitle().equals("")) {
data1.setTitle("No_Title");
}
return data1;
}).map((data1) -> {
if (data1.getAuthor().equals("")) {
data1.setAutor("No_Author");
}
return data1;
}).map((data1) -> {
if (data1.getPublisher().equals("")) {
data1.setPublisher("No_Publisher");
}
return data1;
}).map((data1) -> {
if (data1.getCopywrite().equals("")) {
data1.setCopywrite("No_Copywrite");
}
return data1;
}).map((data1) -> {
if (data1.getIsbn().equals("")) {
data1.setIsbn("No_ISBN");
}
return data1;
}).map((data1) -> {
if (data1.getWho().equals("")) {
data1.setWho("InLibrary");
}
return data1;
}).map((data1) -> {
outFile.println(data1.getTitle());
return data1;
}).map((data1) -> {
outFile.println(data1.getAuthor());
return data1;
}).map((data1) -> {
outFile.println(data1.getPublisher());
return data1;
}).map((data1) -> {
outFile.println(data1.getCopywrite());
return data1;
}).map((data1) -> {
outFile.println(data1.getIsbn());
return data1;
}).map((data1) -> {
outFile.println(data1.getIo());
return data1;
}).forEach((data1) -> {
outFile.println(data1.getWho());
});
outFile.close();
}
}
private void readFile(File User) throws Exception {
try {
String name, author, publisher, copywrite, isbn, whom;
Boolean InOut;
try (Scanner inFile = new Scanner(new File(User + "/Books.txt"))) {
while (inFile.hasNextLine()) {
name = inFile.next();
author = inFile.next();
publisher = inFile.next();
copywrite = inFile.next();
isbn = inFile.next();
InOut = inFile.nextBoolean();
whom = inFile.next();
data.add(new Book(name, author, publisher, copywrite,
isbn, InOut, whom));
}
}
table.setItems(data);
} //insert catch statements
catch (FileNotFoundException exception) {
System.out.println("File not found");
} catch (ArrayIndexOutOfBoundsException AIOOBexception) {
System.out.println("Array Index is out of bounds");
} catch (IllegalArgumentException IAexception) {
System.out.println("Divide by zero error");
} catch (NoSuchElementException NAexception) {
}
FirstRead = false;
}
}
This gives the following error:
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: mediatracker.Books$Book cannot be cast to java.lang.String
at mediatracker.Books$1.toString(Books.java:198)
Line 198 starts:
whoCol.setCellFactory(ComboBoxTableCell.forTableColumn(new StringConverter<Book>() {
Can anyone type in the "theory" behind the ComboBoxTableCell, and list the parts necessary to accomoplish this. All I want to do is to change the value of the cell extracted from a PhoneList in another file.

I'm just going to assume that line 198 is
return (String) object ;
in the anonymous StringConverter's toString() method. When you post a question with a stack trace, always indicate which is the line in your code to which the exception is pointing.
First, it's always better to use generic types instead of raw types. So instead of
TableColumn whoCol = ...
you should have
TableColumn<S,T> whoCol = ...
where you replace S with the type of the data in the table and T with the type of the data in the column. Since you haven't given a complete example, I have no way of guessing what S is; from the error message it looks like the type of the data in the column might be Book.
Read the Javadocs for the method you are calling. They clearly state what the converter is:
converter - A StringConverter to convert the given item (of type T) to
a String for displaying to the user.
So, assuming that your TableColumn is displaying Books, and assuming data is of type ObservableList<Book>, you should have something like
ObservableList<Book> data = ... ;
TableColumn<S, Book> whoCol = new TableColumn<>("Who to");
// ...
whoCol.setCellFactory(ComboBoxTableCell.forTableColumn(new StringConverter<Book>() {
#Override
public String toString(Book book) {
// assuming your Book class defines a getTitle() method, and that's
// how you want to display it in your ComboBox:
return book.getTitle(); // or get a String from book some other way
}
#Override
public Book fromString(String string) {
// I think this is not actually used, as the combo box is not editable
// So you could probably safely just return null here.
// But in general:
Book book = ... ; // create a book from the string
return book ;
}
}, data));
Again, you replace S by whatever you are using for the type of the TableView; and again I had to make guesses at the type of your TableColumn as you didn't provide a complete example. But this should be enough for you to get the idea.

`final TableColumn<Book, String> whoCol = new TableColumn<>("Who to");
whoCol.setMinWidth(100);
whoCol.setEditable(true);
whoCol.setCellValueFactory(new PropertyValueFactory<>("who"));
whoCol.setCellFactory(ComboBoxTableCell.<Book, String>forTableColumn(p.data.get(myIndex()).toString()));
whoCol.setOnEditCommit((TableColumn.CellEditEvent<Book, String> t) -> {
((Book) t.getTableView().getItems().get(
t.getTablePosition().getRow()))
.setWho(t.getNewValue());
try {
writeFile(User);
} catch (IOException ex) {
Logger.getLogger(Books.class.getName()).log(Level.SEVERE, null, ex);
}
});`
This works - #James_D thank you for your aid - you sent me in the right direction

Your problems don't seem to have anything to do with a ComboBoxTableCell.
Your toString() method is wrong; you're trying to cast an Object to a String. That's (probably) why you're seeing a java.lang.ClassCastException. Can you verify which line is line 198?
Also, I notice all your fromString() method does is return its argument. What exactly are you trying to achieve here in this code snippet? Can you give us a little more background information?

Related

how can we use combos in jface tableviewer columns

I am reading excel data and taking headers(only first row) as my columns and added to list and this list is added as input to my tableviewer to display data in my table.I am creating tablecolumns and added the label provider. I am able to see the data in the table. Now i want to display the all textboxes as combos in each column . How can i can add combos for each column? my code is like
my tableviewer class
public class TableViewerExample {
public TableViewerExample(Shell shell) {
TableViewer viewer = new TableViewer(shell, SWT.BORDER | SWT.FULL_SELECTION);
TableViewerColumn upDownColumn = new TableViewerColumn(viewer, SWT.NONE);
upDownColumn.getColumn().setText("Display Order");
upDownColumn.getColumn().setWidth(200);
upDownColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getDisplayOrder();
}
});
TableViewerColumn checkboxColumn = new TableViewerColumn(viewer, SWT.NONE);
checkboxColumn.getColumn().setText("Checkbox Selection");
checkboxColumn.getColumn().setWidth(200);
checkboxColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getCheckboxSelection();
}
});
TableViewerColumn uniqueFieldsColumn = new TableViewerColumn(viewer, SWT.NONE);
uniqueFieldsColumn.getColumn().setText("Unique Fields");
uniqueFieldsColumn.getColumn().setWidth(200);
uniqueFieldsColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getUniqueFields();
}
});
TableViewerColumn inputFieldNameColumn = new TableViewerColumn(viewer, SWT.NONE);
inputFieldNameColumn.getColumn().setText("Input Field Name");
inputFieldNameColumn.getColumn().setWidth(200);
inputFieldNameColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getInputFieldName();
}
});
TableViewerColumn dataTypeColumn = new TableViewerColumn(viewer, SWT.NONE);
dataTypeColumn.getColumn().setText("Data Type");
dataTypeColumn.getColumn().setWidth(200);
dataTypeColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getDataType();
}
});
TableViewerColumn inputFieldFormatColumn = new TableViewerColumn(viewer, SWT.NONE);
inputFieldFormatColumn.getColumn().setText("Input Field Format");
inputFieldFormatColumn.getColumn().setWidth(200);
inputFieldFormatColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getInputFieldFormat();
}
});
TableViewerColumn displayNameColumn = new TableViewerColumn(viewer, SWT.NONE);
displayNameColumn.getColumn().setText("Display Name");
displayNameColumn.getColumn().setWidth(200);
displayNameColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getDisplayName();
}
});
TableViewerColumn displayFormatColumn = new TableViewerColumn(viewer, SWT.NONE);
displayFormatColumn.getColumn().setText("Display Format");
displayFormatColumn.getColumn().setWidth(200);
displayFormatColumn.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return ((DataSourceModel) element).getDisplayFormat();
}
});
viewer.setContentProvider(ArrayContentProvider.getInstance());
System.out.println(RetrieveExcelData.getDataSourceFieldsList());
viewer.setInput(RetrieveExcelData.getDataSourceFieldsList());
viewer.getTable().setLinesVisible(true);
viewer.getTable().setHeaderVisible(true);
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
new TableViewerExample(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
setinput class
public class RetrieveExcelData {
public static List getDataSourceFieldsList() {
String filename = "D:\\ServiceOrders_point_Org_morethan500.xlsx";
List<List<XSSFCell>> sheetData = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filename)) {
XSSFWorkbook workbook = new XSSFWorkbook(fis);
XSSFSheet myExcelSheet = workbook.getSheetAt(0);
XSSFRow row = (XSSFRow )myExcelSheet.getRow(0);
Iterator cells=row.cellIterator();
List<XSSFCell> data = new ArrayList<>();
while (cells.hasNext()) {
XSSFCell cell = (XSSFCell) cells.next();
data.add(cell);
}
sheetData.add(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return showExcelData(sheetData);
}
private static List showExcelData(List<List<XSSFCell>> sheetData) {
List<DataSourceModel> resultList = new ArrayList();
// Iterates the data and print it out to the console.
for (List<XSSFCell> data : sheetData) {
for (XSSFCell cell : data) {
DataSourceModel dataSourceModel=new DataSourceModel(cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue(), cell.getStringCellValue());
resultList.add(dataSourceModel);
}
}
return resultList;
}
my model class
public class DataSourceModel {
private String displayOrder;
private String checkboxSelection;
private String uniqueFields;
private String inputFieldName;
private String dataType;
private String inputFieldFormat;
private String displayName;
private String displayFormat;
public DataSourceModel(String displayOrder,String checkboxSelection,String uniqueFields,String inputFieldName,String dataType, String inputFieldFormat, String displayName,String displayFormat) {
this.displayOrder=displayOrder;
this.checkboxSelection=checkboxSelection;
this.uniqueFields=uniqueFields;
this.inputFieldName=inputFieldName;
this.dataType=dataType;
this.inputFieldFormat=inputFieldFormat;
this.displayName=displayName;
this.displayFormat=displayFormat;
}
public String getDisplayOrder() {
return displayOrder;
}
public void setDisplayOrder(String displayOrder) {
this.displayOrder = displayOrder;
}
public String getCheckboxSelection() {
return checkboxSelection;
}
public void setCheckboxSelection(String checkboxSelection) {
this.checkboxSelection = checkboxSelection;
}
public String getUniqueFields() {
return uniqueFields;
}
public void setUniqueFields(String uniqueFields) {
this.uniqueFields = uniqueFields;
}
public String getInputFieldName() {
return inputFieldName;
}
public void setInputFieldName(String inputFieldName) {
this.inputFieldName = inputFieldName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getInputFieldFormat() {
return inputFieldFormat;
}
public void setInputFieldFormat(String inputFieldFormat) {
this.inputFieldFormat = inputFieldFormat;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDisplayFormat() {
return displayFormat;
}
public void setDisplayFormat(String displayFormat) {
this.displayFormat = displayFormat;
}
and the table looks like
Now i want to make combos instead of text in the columns . Colud you please help how can i change to combos instead of text boxes using my code for all

Arrayadapter only returning the last element

I'm new to android development and right now I'm trying to parse an J SON array into object and then save each object into a array list then display the array list with a array adapter. But, right now I can only get the array adapter to display the last element.
Here is the main class
public class Venue extends Activity {
Venue_Listing venue = new Venue_Listing();
ArrayList<Venue_Listing> venueList;
ListView listview;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.list);
new GetVenus().execute(URL);
venueList = new ArrayList<Venue_Listing>();
}
private class GetVenus extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
String data;
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(Venue.this);
dialog.setMessage("Loading, please wait");
dialog.show();
dialog.setCancelable(false);
}
protected Boolean doInBackground(String... url) {
try {
HttpGet httppost = new HttpGet(url[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
data = EntityUtils.toString(entity);
}
return true;
}
catch (ParseException e1) {
e1.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
Venue_Listing_Adapter adapter = new
Venue_Listing_Adapter(getApplicationContext(),R.layout.venue_list_layout, venueList);
try {
JSONArray jarray = new JSONArray(data);
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
if (venue != null) {
venue.SET_ID(object.getString("venue_ID"));
venue.SET_NAME(object.getString("name"));
listview.setAdapter(adapter);
}
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
}
This class holds all the J SON parse data
public class Venue_Listing {
private String ID;
private String NAME;
public Venue_Listing() {
}
public Venue_Listing(String ID, String NAME) {
super();
this.ID = ID;
this.NAME = NAME;
}
// setter & getter....
And here is what I have for my array adapter
public class Venue_Listing_Adapter extends ArrayAdapter<Venue_Listing> {
private ArrayList<Venue_Listing> objects;
public Venue_Listing_Adapter(Context context, int resource, ArrayList<Venue_Listing> objects) {
super(context, resource, objects);
this.objects = objects;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.venue_list_layout, null);
}
Venue_Listing i = objects.get(position);
if (i != null) {
TextView id = (TextView) v.findViewById(R.id.id);
TextView name = (TextView) v.findViewById(R.id.name);
if (id != null ){
id.setText(i.GET_ID());
}
if (name != null) {
name.setText(i.GET_NAME());
}
}
return v;
}
}
Any help would be appreciated
Thank you
Please print and check the values of 'venueList'.
You have not added values in 'venueList' object.
You need to create 'venue' object every time and add object 'venue' in 'venueList'. Hence you are not getting all items in list view.
The Code may go this way: -
Venue_Listing venue;
try {
JSONArray jarray = new JSONArray(data);
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
venue = new Venue_Listing();
if (object != null) {
venue.SET_ID(object.getString("venue_ID"));
venue.SET_NAME(object.getString("name"));
venueList.add(venue);
}
}
Venue_Listing_Adapter adapter = new Venue_Listing_Adapter(getApplicationContext(),R.layout.venue_list_layout, venueList);
listview.setAdapter(adapter);
}
catch (JSONException e) {
e.printStackTrace();
}

Jenkins plugin development - persistence

I'm still learning plugin dev. This is my first one.
I would like to persist the configuration of my plugin, but it won't work.
Could you please tell me, what am I doing wrong?
I have tried debuging the process, starting from the addition of the plugin to the job 'til the saving of the job config.
I have found, that inside the load() method of the descriptor, no xml file is found!
The path it is looking for is something like: c:\users\Peter\workspace\r-script.\work\whatEverDir\xy.xml
I don't think that the .\ part is causing the config file not to be found, but since it is a Jenkins class generating this path, I would not bet on it. Although the system might have tried to create it here at the first place.
Thanks in advance!
Scriptrunner.jelly
<f:block>
<f:entry title="RScript" field="command">
<f:textarea style="width:99%" />
</f:entry>
</f:block>
<f:entry field="installedPackages" title="Installed packages">
<f:select style="width:40%" />
</f:entry>
<f:entry field="mirrors" title="Choose a mirror">
<f:select style="width:40%" />
</f:entry>
<f:entry>
<f:repeatableProperty field="availablePackages" minimum="1"/>
</f:entry>
AvailablePackage.jelly
<f:entry field="availablePackages">
<f:select style="width:40%" />
<f:repeatableDeleteButton />
</f:entry>
ScriptRunner.java
public class ScriptRunner extends Builder {
private static final String fileExtension = ".R";
private ArrayList<AvailablePackage> availablePackages;
private String command;
private String chosenMirror;
private List<String> mirrorList = new ArrayList<String>();
#DataBoundConstructor
public ScriptRunner(String command, ArrayList<String> installedPackages, ArrayList<String> mirrors, ArrayList<AvailablePackage> availablePackages) {
this.chosenMirror = mirrors.get(0);
this.availablePackages = availablePackages;
this.command = command;
}
public final String getCommand() {
return command;
}
#Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException {
return perform(build, launcher, (TaskListener) listener);
}
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
TaskListener listener) throws InterruptedException {
FilePath workSpace = build.getWorkspace();
FilePath rScript = null;
if (workSpace == null) {
try {
throw new NoSuchFileException("Workspace could not be set!");
} catch (NoSuchFileException e) {
e.printStackTrace();
}
}
try {
try {
String fullScript;
if (command.contains("options(repos=structure(")) {
fullScript = PackagesManager.singleton().createFullScript(availablePackages, "", command);
} else {
fullScript = PackagesManager.singleton().createFullScript(availablePackages, chosenMirror, command);
}
rScript = workSpace.createTextTempFile("RScriptTemp",
getFileExtension(), fullScript, false);
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToProduceScript()));
return false;
}
boolean successfullyRan = false;
try {
EnvVars envVars = build.getEnvironment(listener);
for (Map.Entry<String, String> e : build.getBuildVariables()
.entrySet()) {
envVars.put(e.getKey(), e.getValue());
}
if (launcher.launch().cmds(buildCommandLine(rScript))
.envs(envVars).stdout(listener).pwd(workSpace).join() == 1) {
successfullyRan = true;
}
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_CommandFailed()));
}
return successfullyRan;
} finally {
try {
if (rScript != null) {
rScript.delete();
}
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToDelete(rScript)));
} catch (Exception e) {
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToDelete(rScript)));
}
}
}
public String[] buildCommandLine(FilePath script) {
return new String[] { "Rscript", script.getRemote() };
}
protected String getFileExtension() {
return fileExtension;
}
public List<String> getMirrorList() {
return mirrorList;
}
public void setMirrorList(List<String> mirrorList) {
this.mirrorList = mirrorList;
}
public String getChosenMirror() {
return chosenMirror;
}
public void setChosenMirror(String chosenMirror) {
this.chosenMirror = chosenMirror;
}
public ArrayList<AvailablePackage> getAvailablePackages() {
return availablePackages;
}
#Override
public ScriptBuildStepDescriptorImplementation getDescriptor() {
return (ScriptBuildStepDescriptorImplementation)super.getDescriptor();
}
#Extension
public static class ScriptBuildStepDescriptorImplementation extends
BuildStepDescriptor<Builder> {
private boolean showInstalled;
private String command;
private String chosenMirror;
private ArrayList<AvailablePackage> availablePackages;
public ScriptBuildStepDescriptorImplementation() {
load();
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
#Override
public String getDisplayName() {
return "Advanced R script runner";
}
#Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
public ListBoxModel doFillInstalledPackagesItems() {
ListBoxModel mirrors = new ListBoxModel();
Set<String> mirrorsList = PackagesManager.singleton()
.getInstalledPackages();
for (String entry : mirrorsList) {
mirrors.add(entry);
}
return mirrors;
}
public ListBoxModel doFillAvailablePackagesItems() {
ListBoxModel packages = new ListBoxModel();
List<String> packageList = PackagesManager.singleton().getAvailablePackages();
Set<String> alreadyInstalled = PackagesManager.singleton().getInstalledPackages();
for (String entry : packageList) {
if (!alreadyInstalled.contains(entry)) {
packages.add(entry);
}
}
return packages;
}
public ListBoxModel doFillMirrorsItems() {
ListBoxModel mirrors = new ListBoxModel();
String[] mirrorsList = MirrorManager.singleton().getMirrors();
int selected = 34;
for (int i = 0; i < mirrorsList.length; i++) {
String[] splitCurrent = mirrorsList[i].split(" - ");
if (chosenMirror != null && chosenMirror.equals(splitCurrent[1])) {
selected = i;
}
mirrors.add(splitCurrent[1], splitCurrent[0]);
}
mirrors.get(selected).selected = true;
return mirrors;
}
public boolean getShowInstalled() {
return showInstalled;
}
public void setShowInstalled(boolean showInstalled) {
this.showInstalled = showInstalled;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getChosenMirror() {
return chosenMirror;
}
public void setChosenMirror(String chosenMirror) {
this.chosenMirror = chosenMirror;
}
}
}
AvailablePackage.java
public class AvailablePackage extends AbstractDescribableImpl<AvailablePackage> {
private String name;
#DataBoundConstructor
public AvailablePackage(String availablePackages) {
this.name = availablePackages;
}
public String getName() {
return name;
}
#Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
#Extension
public static class DescriptorImpl extends Descriptor<AvailablePackage> {
private String name;
public DescriptorImpl() {
load();
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
public ListBoxModel doFillAvailablePackagesItems() {
return PackagesManager.singleton().getAvailablePackagesAsListBoxModel(name);
}
#Override
public String getDisplayName() {
return "";
}
public String getName() {
return name;
}
}
}
Sorry for the code formatting! First timer at stackoverflow code posting.
I think you may need to comment this line out
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
//return super.configure(req,formData);
return true;
}
as it will then save again but with no fields.
A good place to locate Jenkins plugin examples is in https://github.com/jenkinsci

how to get data from database with parameter

I'm trying to show a list with the list items from my database having 2 parameters, but the list didn't show.
Here's my query database from php:
$query = mysql_query("SELECT d.model_name from detail_product d join brand b on d.id_brandtype = b.id_brand join biketype t on d.id_biketype = t.id_type where d.id_brandtype = 1 and d.id_biketype=1");
I've set the parameter there.
and here's my DAO:
public class info_xc_dao {
public final static int VIEW_POL_XC = 0;
private static final String URL_VIEW_POL_XC = ServerConfiguration.SERVER_URL
+ "polygon_xc.php";
private int Action;
pol_xc_Result pol_xc_Result;
public info_xc_dao(pol_xc_Result pol_xc_Result) {
// TODO Auto-generated constructor stub
this.pol_xc_Result = pol_xc_Result;
}
public void view_pol_xc() {
Action = VIEW_POL_XC;
new ConnectionHandler(connectionResult, null, URL_VIEW_POL_XC,
ConnectionHandler.GET);
}
public ConnectionResult connectionResult = new ConnectionResult() {
#Override
public void gotResult(String result, String message) {
// TODO Auto-generated method stub
if (result != null) {
switch (Action) {
case VIEW_POL_XC:
try {
JSONObject jsonObject = null;
jsonObject = new JSONObject(result);
int response = jsonObject.getInt("result");
if (response != 0) {
JSONArray jsonArray = new JSONArray(
jsonObject.getString("data"));
ArrayList<Entity_Detail_Product> arrayList = new ArrayList<Entity_Detail_Product>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject pol_xc = new JSONObject(jsonArray
.get(i).toString());
Entity_Detail_Product ent_detail_product = new Entity_Detail_Product();
ent_detail_product.setModel_name(pol_xc
.getString("model_name"));
arrayList.add(ent_detail_product);
}
pol_xc_Result.gotResult(arrayList, null, Action);
} else {
String error_message = jsonObject
.getString("message");
pol_xc_Result.gotResult(null, error_message,
Action);
}
} catch (JSONException e) {
// TODO: handle exception
pol_xc_Result.gotResult(null,
"Failed parsing data from database. Please try again.. "
+ e.getMessage(), Action);
Log.e("CON ERROR", e.getMessage());
}
}
} else {
pol_xc_Result.gotResult(null, message, Action);
Log.e("CON ERROR", message);
}
}
};
public static abstract class pol_xc_Result {
public abstract void gotResult(Object obj, String message, int action);
}
and here's my activity to call DAO.
public class Information_XC_Activity extends ListActivity {
WebView mWebView;
TextView tv;
private Adapter_DetailPolXC adapterDetailPolXC;
private ListView mainListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info_xc);
final ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
actionBar.setTitle(getString(R.string.app_name));
int index = getIntent().getIntExtra("text", 0);
mWebView = (WebView) findViewById(R.id.webview_xc);
String temp = "<html><body>" + "<p align=\"justify\">"
+ getString(R.string.xc_info + index) + "</p> "
+ "</body></html>";
mWebView.loadData(temp, "text/html", "utf-8");
ArrayList<Entity_Detail_Product> arraylist = new ArrayList<Entity_Detail_Product>();
adapterDetailPolXC = new Adapter_DetailPolXC(this, R.layout.info_row,
arraylist);
setListAdapter(adapterDetailPolXC);
new info_xc_dao(response).view_pol_xc();
}
pol_xc_Result response = new pol_xc_Result() {
#Override
public void gotResult(Object obj, String message, int action) {
// TODO Auto-generated method stub
// actionBar.setProgressBarVisibility(View.INVISIBLE);
#SuppressWarnings("unchecked")
ArrayList<Entity_Detail_Product> arrayList = (ArrayList<Entity_Detail_Product>) obj;
AlertDialog.Builder builder = new AlertDialog.Builder(
Information_XC_Activity.this);
if (arrayList == null) {
builder.setIcon(R.drawable.alert_warning);
builder.setTitle("Error");
builder.setMessage("Data Not Found !");
builder.setNegativeButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
for (Entity_Detail_Product entity_Detail_Product : arrayList) {
adapterDetailPolXC.add(entity_Detail_Product);
}
adapterDetailPolXC.notifyDataSetChanged();
}
}
};
private class Adapter_DetailPolXC extends
ArrayAdapter<Entity_Detail_Product> {
private ArrayList<Entity_Detail_Product> items;
public Adapter_DetailPolXC(Context context, int textViewResourceId,
ArrayList<Entity_Detail_Product> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
if (v == null) {
LayoutInflater layoutInflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = (View) layoutInflater.inflate(R.layout.info_xc, null);
}
Entity_Detail_Product adapter_Detail_Product = items.get(position);
if (adapter_Detail_Product != null) {
TextView textView = (TextView) v.findViewById(R.id.tv_test);
if (textView != null)
textView.setText(adapter_Detail_Product.getModel_name());
}
return v;
}
}
and here's my logcat :
09-22 12:41:30.239: W/IInputConnectionWrapper(12808): showStatusIcon on inactive InputConnection
09-22 12:41:33.129: E/HttpResponse(12808): {"result":1,"data":[{"0":"1","id_brand":"1","1":"Polygon","brand_name":"Polygon"},{"0":"2","id_brand":"2","1":"United Bike","brand_name":"United Bike"},{"0":"3","id_brand":"3","1":"WimCycle","brand_name":"WimCycle"}]}
09-22 12:41:35.009: E/HttpResponse(12808): {"result":1,"data":[{"0":"1","id_type":"1","1":"Cross Country (XC)","type_name":"Cross Country (XC)"},{"0":"2","id_type":"2","1":"Bicycle Motocross (BMX)","type_name":"Bicycle Motocross (BMX)"},{"0":"3","id_type":"3","1":"Free Ride (FR)","type_name":"Free Ride (FR)"},{"0":"4","id_type":"4","1":"DownHill (DH)","type_name":"DownHill (DH)"},{"0":"5","id_type":"5","1":"DirtJump (DJ)","type_name":"DirtJump (DJ)"},{"0":"6","id_type":"6","1":"Road Bike (RB)","type_name":"Road Bike (RB)"}]}
09-22 12:41:37.219: D/PhoneWindow(12808): couldn't save which view has focus because the focused view com.android.internal.policy.impl.PhoneWindow$DecorView#405440f0 has no id.
09-22 12:41:37.519: I/webclipboard(12808): clipservice: android.sec.clipboard.ClipboardExManager#405d4d40
09-22 12:41:37.839: V/webview(12808): OnSizeChanged: Enter
09-22 12:41:37.859: E/HttpResponse(12808): {"result":1,"data":[{"0":"1","id_type":"1","1":"Cross Country (XC)","type_name":"Cross Country (XC)"},{"0":"2","id_type":"2","1":"Bicycle Motocross (BMX)","type_name":"Bicycle Motocross (BMX)"},{"0":"3","id_type":"3","1":"Free Ride (FR)","type_name":"Free Ride (FR)"},{"0":"4","id_type":"4","1":"DownHill (DH)","type_name":"DownHill (DH)"},{"0":"5","id_type":"5","1":"DirtJump (DJ)","type_name":"DirtJump (DJ)"},{"0":"6","id_type":"6","1":"Road Bike (RB)","type_name":"Road Bike (RB)"}]}
09-22 12:41:38.169: E/CON ERROR(12808): No value for model_name
09-22 12:41:38.859: V/webview(12808): ZoomScale 3 mPreserveZoom: false
09-22 12:41:38.889: D/CONTEXT(12808): m_mainFrame->editor()->hasComposition not
09-22 12:41:38.959: D/CONTEXT(12808): m_mainFrame->editor()->hasComposition not

CheckboxCell, MultiSelectionModel unwantonly reset DataGrid's data

Using GWT 2.4...
I am building upon a complex Composite dual view/edit mode implementation that is backed GWT's DataGrid and MultiSelectionModel. My goal is for a user to be able to click a checkbox in each row that they'd like to post updates for.
Here's a screenshot from a semi-functional interface:
Note the selected (highlighted) rows.
Now the problem is that when I type something in any of the cells (e.g., the first row's $ cell under the $/Mw 1 composite cell header), then click that row's checkbox (or any other row's checkbox for that matter) to select or de-select, the value gets reset to the original value when the screen's data was first requested. Not desired behavior by any stretch!
Let's take a look at my custom implementation for the grid. (Excuse the length).
public abstract class ToggleableGrid<T extends Identifiable<?>> extends Composite {
private static final int CHKBOX_COLUMN_WIDTH = App.INSTANCE.checkboxColumnWidth();
private static final DisplayMode DEFAULT_MODE = DisplayMode.VIEW;
private ProvidesKey<T> keyProvider;
private DataGrid<T> grid;
private MultiSelectionModel<T> selectionModel;
private ListDataProvider<T> dataProvider;
private int tabIndex = 0;
public ToggleableGrid() {
final DataGridConfiguration config = new DefaultDataGridConfiguration();
initGrid(config);
}
public ToggleableGrid(DataGridConfiguration config) {
initGrid(config);
}
private void initGrid(DataGridConfiguration config) {
keyProvider = new ProvidesKey<T>() {
#Override
public Object getKey(T item) {
return item == null ? null : item.getId();
}
};
grid = new DataGrid<T>(config.getPageSize(), config.getResources(), keyProvider);
// Set the message to display when the table is empty.
grid.setEmptyTableWidget(new Label(UiMessages.INSTANCE.no_results()));
initWidget(grid);
setVisible(true);
}
public void setInput(List<T> content) {
setInput(content, DEFAULT_MODE);
}
public void setInput(List<T> content, DisplayMode mode) {
resetTableColumns();
if (isInEditMode(mode)) {
// Add a selection model so we can select cells
selectionModel = new MultiSelectionModel<T>(keyProvider);
grid.setSelectionModel(selectionModel, DefaultSelectionEventManager.<T> createCheckboxManager(0));
addRowSelector();
}
dataProvider = new ListDataProvider<T>(content);
final ListHandler<T> sortHandler = new ListHandler<T>(dataProvider.getList());
grid.addColumnSortHandler(sortHandler);
initializeStructure(constructMetadata(), sortHandler, mode);
dataProvider.addDataDisplay(grid);
}
// see https://stackoverflow.com/questions/3772480/remove-all-columns-from-a-celltable
// concrete classes are forced to maintain a handle on all columns added
private void resetTableColumns() {
for (final Column<T, ?> column: allColumns()) {
grid.removeColumn(column);
}
allColumns().clear();
}
protected boolean isInEditMode(DisplayMode currentDisplayMode) {
boolean result = false;
if (currentDisplayMode.equals(DisplayMode.EDIT)) {
result = true;
}
return result;
}
protected abstract Set<Column<T, ?>> allColumns();
protected abstract TableMetadata constructMetadata();
protected abstract void initializeStructure(TableMetadata metadata, ListHandler<T> sortHandler, DisplayMode mode);
protected void setColumnHorizontalAlignment(Column<T, ?> column, HorizontalAlignmentConstant alignment) {
column.setHorizontalAlignment(alignment);
}
// TODO figure out how to add a checkbox to column header that provides select/de-select all capability
// see https://stackoverflow.com/questions/6174689/gwt-celltable-programmatically-select-checkboxcell
protected void addRowSelector() {
final Column<T, Boolean> rowSelectColumn = new Column<T, Boolean>(new CheckboxCell(true, false)) {
#Override
public Boolean getValue(T value) {
Boolean result;
// check for null value and return null;
if(value == null || value.getId() == null) {
result = null;
} else { // get value from the selection model
result = selectionModel.isSelected(value);
}
return result;
}
};
addColumn(rowSelectColumn, UiMessages.INSTANCE.select());
setColumnWidth(rowSelectColumn, CHKBOX_COLUMN_WIDTH, Unit.PX);
setColumnHorizontalAlignment(rowSelectColumn, HasHorizontalAlignment.ALIGN_CENTER);
}
protected void setColumnWidth(Column<T, ?> column, int width, Unit unit) {
grid.setColumnWidth(column, width, unit);
}
protected void addColumn(Column<T, ?> column, String columnHeaderName) {
addColumn(column, columnHeaderName, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addColumn(Column<T, ?> column, String columnHeaderName, HorizontalAlignmentConstant alignment) {
final SafeHtmlBuilder sb = new SafeHtmlBuilder();
final String divStart = "<div align=\""+ alignment.getTextAlignString() + "\" class=\"" +UiResources.INSTANCE.style().word_wrap() + "\">";
sb.appendHtmlConstant(divStart).appendEscaped(columnHeaderName).appendHtmlConstant("</div>");
final SafeHtml header = sb.toSafeHtml();
grid.addColumn(column, header);
allColumns().add(column);
}
protected CompositeCell<T> generateCompositeCell(final List<HasCell<T, ?>> hasCells) {
final CompositeCell<T> compositeCell = new CompositeCell<T>(hasCells) {
#Override
public void render(Context context, T value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<table><tbody><tr>");
super.render(context, value, sb);
sb.appendHtmlConstant("</tr></tbody></table>");
}
#Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
#Override
protected <X> void render(Context context, T value,
SafeHtmlBuilder sb, HasCell<T, X> hasCell) {
final Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</td>");
}
};
return compositeCell;
}
// FIXME not working quite the way we'd expect, index incremented within column for each row, not each row by column
protected int nextTabIndex() {
tabIndex++;
return tabIndex;
}
protected AbstractCellTable<T> getGrid() {
return grid;
}
/**
* Gets the selected (row(s) of) data from grid (used in edit mode)
* #return the selected data (as per selection model)
*/
public List<T> getSelectedData() {
final List<T> data = new ArrayList<T>();
data.addAll(selectionModel.getSelectedSet());
return data;
}
/**
* Gets all (row(s) of) data in grid (used in edit mode)
* #return all data as list
*/
public List<T> getAllData() {
return dataProvider.getList();
}
/**
* Clears the currently selected (row(s) of) data (used in edit mode)
*/
public void clearSelectedData() {
selectionModel.clear();
grid.redraw();
}
}
So, the interesting methods to stare at above (I think) are setInput, generateCompositeCell and addRowSelector.
We initialize the grid with List data and set a display mode in setInput. It's here as well that the selection model is initialized. It uses GWT's DefaultSelectionEventManager createCheckboxManager().
I've been trying to grok the event model, but it eludes me. I've visited the following sources online, but have come up short on avenues to solving this problem.
-- https://groups.google.com/forum/?fromgroups#!topic/google-web-toolkit/k5sfURxDaVg
AbstractInputCell's getConsumedEventsImpl adds focus, blur and keydown, so this (I believe) is not a track I need to explore
-- GWT CellTable programmatically select CheckBoxCell
The various ways you can instantiate a CheckBoxCell got me curious, and I've tried many constructor argument permutations, but the one I settled on (true, false) is (I believe) the right one
Agreeing here and now (before being reprimanded) that there's perhaps some unnecessary complexity in my implementation, but I am looking for guidance nonetheless. Thanks!
Update
If it helps here's an impl of the aforementioned ToggleableGrid. If anything it gives you more detail on what goes into each CompositeCell. For details on AbstractValidatableColumn and ValidatableInputCell, see: In search of a GWT validation example... where art thou?.
public class EnergyOfferGrid extends ToggleableGrid<EnergyOfferDTO> {
public EnergyOfferGrid() {
super();
}
public EnergyOfferGrid(DataGridConfiguration config) {
super(config);
}
private static final int MAX_NUMBER_OF_MW_PRICE_POINTS = App.INSTANCE.maxNoOfMwPricePoints();
private Set<Column<EnergyOfferDTO, ?>> columns = new HashSet<Column<EnergyOfferDTO, ?>>();
#Override
protected Set<Column<EnergyOfferDTO, ?>> allColumns() {
return columns;
}
#Override
protected TableMetadata constructMetadata() {
final TableMetadata metadata = new TableMetadata();
// TODO Consider a predefined set of ReferenceData to be held in a common package
// Use Slope
metadata.addColumnMetadata(UiMessages.INSTANCE.use_slope(), new String[] {UiMessages.INSTANCE.yes(), UiMessages.INSTANCE.no()}, new String[] {"true", "false"});
return metadata;
}
#Override
protected void initializeStructure(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
addHourColumn(sortHandler);
addUseSlopeColumn(metadata, sortHandler, currentDisplayMode);
for (int i = 0; i < MAX_NUMBER_OF_MW_PRICE_POINTS; i++) { // zero-based indexing
addPriceMwColumn(i, currentDisplayMode);
}
}
protected void addHourColumn(ListHandler<EnergyOfferDTO> sortHandler) {
final Column<EnergyOfferDTO, String> hourColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer.getId() != null) {
final String isoDateTime = energyOffer.getId().getOperatingHour();
if (isoDateTime != null && !isoDateTime.isEmpty()) {
final Date dateTime = CSTimeUtil.isoToDate(isoDateTime);
if (dateTime != null) {
result = CSTimeUtil.dateToHour(dateTime);
}
}
}
return result;
}
};
hourColumn.setSortable(true);
sortHandler.setComparator(hourColumn, new Comparator<EnergyOfferDTO>() {
#Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
final String date1 = eo1.getId() != null ? eo1.getId().getOperatingHour() : "";
final String date2 = eo2.getId() != null ? eo2.getId().getOperatingHour() : "";
return date1.compareTo(date2);
}
});
// We know that the data is sorted by hour by default.
getGrid(). getColumnSortList().push(hourColumn);
addColumn(hourColumn, UiMessages.INSTANCE.hour());
setColumnWidth(hourColumn, 45, Unit.PX);
setColumnHorizontalAlignment(hourColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addUseSlopeColumn(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
final ReferenceData refData = metadata.allColumnMetadata().get(UiMessages.INSTANCE.use_slope());
Column<EnergyOfferDTO, String> useSlopeColumn;
Cell<String> cell;
if (isInEditMode(currentDisplayMode)) {
cell = new ReferenceDataBackedSelectionCell(refData);
} else {
cell = new TextCell();
}
useSlopeColumn = new Column<EnergyOfferDTO, String>(cell) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return refData.getDisplayValueForSubmitValue(Boolean.toString(energyOffer.isSlopeUsed()));
}
};
useSlopeColumn.setSortable(true);
sortHandler.setComparator(useSlopeColumn, new Comparator<EnergyOfferDTO>() {
#Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
final String slopeUsed1 = String.valueOf(eo1.isSlopeUsed());
final String slopeUsed2 = String.valueOf(eo1.isSlopeUsed());
return slopeUsed1.compareTo(slopeUsed2);
}
});
addColumn(useSlopeColumn, UiMessages.INSTANCE.use_slope());
setColumnWidth(useSlopeColumn, 75, Unit.PX);
setColumnHorizontalAlignment(useSlopeColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addPriceMwColumn(final int colIndex, DisplayMode currentDisplayMode) {
// Construct a composite cell for energy offers that includes a pair of text inputs
final List<HasCell<EnergyOfferDTO, ?>> columns = new ArrayList<
HasCell<EnergyOfferDTO, ?>>();
// this DTO is passed along so that price and mw values for new entries are kept together
final OfferPriceMwPair newOfferPriceMwPair = new OfferPriceMwPair();
// Price
final Column<EnergyOfferDTO, String> priceColumn = generatePriceColumn(colIndex, newOfferPriceMwPair, currentDisplayMode);
columns.add(priceColumn);
// MW
final Column<EnergyOfferDTO, String> mwColumn = generateMwColumn(colIndex, newOfferPriceMwPair, currentDisplayMode);
columns.add(mwColumn);
// Composite
final CompositeCell<EnergyOfferDTO> priceMwColumnInnards = generateCompositeCell(columns);
final IdentityColumn<EnergyOfferDTO> priceMwColumn = new IdentityColumn<EnergyOfferDTO>(priceMwColumnInnards);
final StringBuilder colHeader = new StringBuilder();
colHeader.append(UiMessages.INSTANCE.price_mw_header()).append(" ").append(String.valueOf(colIndex + 1));
addColumn(priceMwColumn, colHeader.toString());
setColumnWidth(priceMwColumn, 7, Unit.EM);
setColumnHorizontalAlignment(priceMwColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected Column<EnergyOfferDTO, String> generatePriceColumn(final int colIndex, final OfferPriceMwPair newOfferPriceMwPair, DisplayMode currentDisplayMode) {
Column<EnergyOfferDTO, String> priceColumn;
if (isInEditMode(currentDisplayMode)) {
priceColumn = new BigDecimalValidatableColumn<EnergyOfferDTO, OfferPriceMwPair>(nextTabIndex(), getGrid()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return obtainPriceValue(colIndex, energyOffer, false);
}
#Override
public void doUpdate(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal price = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair == null) { // we have a new price value
newOfferPriceMwPair.setPrice(price);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPair.setPrice(price);
}
}
}
#Override
protected String getPropertyName() {
return "price";
}
#Override
protected Class<OfferPriceMwPair> getPropertyOwner() {
return OfferPriceMwPair.class;
}
};
} else {
priceColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
final String result = obtainPriceValue(colIndex, energyOffer, true);
return result;
}
};
}
return priceColumn;
}
private String obtainPriceValue(final int colIndex, EnergyOfferDTO energyOffer, boolean withCurrency) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final int numberOfPairs = offerPriceCurve.size();
if (colIndex < numberOfPairs) {
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair != null) {
final BigDecimal price = offerPriceMwPair.getPrice();
if (price != null) {
final double value = price.doubleValue();
if (withCurrency) {
result = NumberFormat.getCurrencyFormat().format(value);
} else {
result = NumberFormat.getDecimalFormat().format(value);
}
}
}
}
}
return result;
}
protected Column<EnergyOfferDTO, String> generateMwColumn(final int colIndex, final OfferPriceMwPair newOfferPriceMwPair, DisplayMode currentDisplayMode) {
Column<EnergyOfferDTO, String> mwColumn;
if (isInEditMode(currentDisplayMode)) {
mwColumn = new BigDecimalValidatableColumn<EnergyOfferDTO, PriceMwPair>(nextTabIndex(), getGrid()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return obtainMwValue(colIndex, energyOffer);
}
#Override
public void doUpdate(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal mw = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair == null) { // we have a new price value
newOfferPriceMwPair.setMw(mw);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPair.setMw(mw);
}
}
}
#Override
protected String getPropertyName() {
return "mw";
}
#Override
protected Class<PriceMwPair> getPropertyOwner() {
return PriceMwPair.class;
}
};
} else {
mwColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
final String result = obtainMwValue(colIndex, energyOffer);
return result;
}
};
}
return mwColumn;
}
private String obtainMwValue(final int colIndex, EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final int numberOfPairs = offerPriceCurve.size();
if (colIndex < numberOfPairs) {
final PriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair != null) {
final BigDecimal mw = offerPriceMwPair.getMw();
if (mw != null) {
result = NumberFormat.getDecimalFormat().format(mw);
}
}
}
}
return result;
}
}
All that custom work w.r.t. WrapperCell and CompositeValidatableColumn was unnecessary.
It turns out that there's a way you should not construct CompositeCells. See http://code.google.com/p/google-web-toolkit/issues/detail?id=5714. My CompositeCells were not receiving events. So, I changed the way I construct them in ToggleableGrid.
protected CompositeCell<T> generateCompositeCell(final List<HasCell<T, String>> hasCells) {
final CompositeCell<T> compositeCell = new CompositeCell<T>(hasCells) {
// to not run afoul of http://code.google.com/p/google-web-toolkit/issues/detail?id=5714
#Override
public void render(Context context, T value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<div style=\"display: inline\">");
super.render(context, value, sb);
sb.appendHtmlConstant("</div>");
}
#Override
protected Element getContainerElement(Element parent) {
// Return the first element in the DIV.
return parent.getFirstChildElement();
}
};
return compositeCell;
}
After that change and incorporating my other validation-oriented classes: ValidatableFieldUpdater, AbstractValidatableColumn (and derivatives), ValidatableInputField and ConversionResult, life couldn't be more grand!