I need to show different tool tip for each table cell - javafx-8

Please see this
This is what I want to see... I mean the tool tip
At run time I get this error message for each row that is being loaded.
The tool tip text lies in the an object and is retrieved by thisRow.getCourseTootip(i);
Number of columns in the table varies and I create them and add them to the table view thru code.
for (int courseNo = 0; courseNo < numberOfCourses; courseNo++) {
String colName = getASemesterCourse(thisSemester, courseNo).getCourseID();
TableColumn<AResultRow, String> thisColumn = new TableColumn<>(colName);
thisColumn.setPrefWidth(80);
thisColumn.setStyle("-fx-alignment: CENTER; font-weight:bold;");
String str = TableRows.get(1).getGrade(courseNo);
final int i = courseNo;
thisColumn.setCellValueFactory(cellData -> cellData.getValue().courseGradeProperty(i));
thisColumn.setCellFactory(new Callback<TableColumn<AResultRow, String>, TableCell<AResultRow, String>>() {
public TableCell<AResultRow, String> call(TableColumn<AResultRow, String> column) {
return new TableCell<AResultRow, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setText(item);
AResultRow thisRow = new AResultRow();
thisRow = getTableView().getItems().get(getTableRow().getIndex());
final Tooltip tip= new Tooltip();
tip.setText(thisRow.getCourseTootip(i));
setTooltip(tip);
tip.setStyle("-fx-background-color: pink; -fx-text-fill: black; -fx-font: normal normal 12pt \"Times New Roman\"");
}
}
};
}
});
boolean retVal = thisTable.getColumns().addAll(thisColumn);
}
Error is
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at victoriairene.TheMainFXMLController$1$1.updateItem(TheMainFXMLController.java:434)
at victoriairene.TheMainFXMLController$1$1.updateItem(TheMainFXMLController.java:427)
Line 434 is
thisRow = getTableView().getItems().get(getTableRow().getIndex());
Text for the tool tip for this cell comes from thisRow.getCourseTootip(i).
Can someone tell me, what is wrong with my code? Which object is null ? If it is null, then how do I get to see the correct Tooltip text, in spite of getting error messages for each row ?
I have been struggling with this for one full day.
Please help and thanks in advance.
As requested by Kleopatra I am enclosing the entire Create Table function.
public void createTableForThisSemester(int thisSemester, int numberOfCourses, javafx.collections.ObservableList<AResultRow> TableRows) {
TableView<AResultRow> thisTable = new TableView<>();
thisTable.setContextMenu(contextMenu);
TableColumn<AResultRow, String> tcolRollNo = new TableColumn<>("Roll Number");
tcolRollNo.setEditable(false);
tcolRollNo.setPrefWidth(120);
TableColumn<AResultRow, String> tcolName = new TableColumn<>("Student Name");
tcolName.setEditable(false);
tcolName.setPrefWidth(350);
tcolRollNo.setCellValueFactory(cellData -> cellData.getValue().StudentIDProperty());
tcolName.setCellValueFactory(cellData -> cellData.getValue().StudentNameProperty());
boolean xyz = thisTable.getColumns().addAll(tcolRollNo, tcolName);
// TableColumn[] courseColumn = new TableColumn[numberOfCourses];
for (int courseNo = 0; courseNo < numberOfCourses; courseNo++) {
String colName = getASemesterCourse(thisSemester, courseNo).getCourseID();
TableColumn<AResultRow, String> thisColumn = new TableColumn<>(colName);
thisColumn.setPrefWidth(80);
thisColumn.setStyle("-fx-alignment: CENTER; font-weight:bold;");
String str = TableRows.get(1).getGrade(courseNo);
final int i = courseNo;
thisColumn.setCellValueFactory(cellData -> cellData.getValue().courseGradeProperty(i));
thisColumn.setCellFactory(new Callback<TableColumn<AResultRow, String>, TableCell<AResultRow, String>>() {
public TableCell<AResultRow, String> call(TableColumn<AResultRow, String> column) {
return new TableCell<AResultRow, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setText(item);
AResultRow thisRow = new AResultRow();
thisRow = getTableView().getItems().get(getTableRow().getIndex());
final Tooltip tip= new Tooltip();
tip.setText(thisRow.getCourseTootip(i));
setTooltip(tip);
tip.setStyle("-fx-background-color: pink; -fx-text-fill: black; -fx-font: normal normal 12pt \"Times New Roman\"");
}
}
};
}
});
boolean retVal = thisTable.getColumns().addAll(thisColumn);
}
// System.out.println("# of Rows in Table [" + thisSemester + "] = " + TableRows.size());
TableColumn<AResultRow, String> tcolGPA = new TableColumn<>("GPA");
tcolGPA.setEditable(false);
tcolGPA.setPrefWidth(80);
tcolGPA.setStyle("-fx-alignment: CENTER; font-weight:bold;");
tcolGPA.setCellValueFactory(cellData -> cellData.getValue().returnStringGPA());
boolean retVal = thisTable.getColumns().addAll(tcolGPA);
thisTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
thisTable.setItems(TableRows);
thisTable.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
//Check whether item is selected and set value of selected item to Label
if (thisTable.getSelectionModel().getSelectedItem() == null) {
gRollNumber = null;
gStudentName = null;
} else {
gRollNumber = newValue.getStudentID();
gStudentName = newValue.getStudentName();
}
});
ScrollPane thisScrollPane = new ScrollPane();
thisScrollPane.setFitToWidth(true);
thisScrollPane.setFitToHeight(true);
thisScrollPane.setMinHeight((theDetails.getHeight() - 25));
thisScrollPane.setMaxHeight((theDetails.getHeight() - 25));
thisScrollPane.setMinWidth((theDetails.getWidth() - 25));
thisScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
Tab thisTab = tabs.getTabs().get(thisSemester);
thisTab.setContent(thisScrollPane);
thisScrollPane.setContent(thisTable);
}
I am repeating the hierarchy again - please excuse.
Table view is associated with an observablelist named ATableRows which a class ATableRow.
ATableRow contains several members and one of them is an array of class ACourseResult.
I need to know the ROW number and the array index (which is actually the Table Column number for that Cell) before I can retrieve the text for the tooltip.
Thing is the code works... except for the runtime error of null pointer. I still do not understand what the CellFactory and CellValueFactories do. Sorry about that. Oracle's documents do not say what they do......
While I am at this.... I want to tell you that my TABLE is READ ONLY. Do I Have to use the Observable List ? Can't I do this by setting values directly to each cell (just a curiosity).
Thanks in advance and sorry if my questions seem dumber.
Thanks to JAMES my problem is solved.... I am enclosing the modified code for others.
for (int courseNo = 0; courseNo < numberOfCourses; courseNo++) {
String colName = getASemesterCourse(thisSemester, courseNo).getCourseID();
TableColumn<AResultRow, String> thisColumn = new TableColumn<>(colName);
thisColumn.setPrefWidth(80);
thisColumn.setStyle("-fx-alignment: CENTER; font-weight:bold;");
String str = TableRows.get(1).getGrade(courseNo);
final int i = courseNo;
thisColumn.setCellValueFactory(cellData -> cellData.getValue().courseGradeProperty(i));
thisColumn.setCellFactory(new Callback<TableColumn<AResultRow, String>, TableCell<AResultRow, String>>() {
public TableCell<AResultRow, String> call(TableColumn<AResultRow, String> column) {
return new TableCell<AResultRow, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setText(item);
AResultRow thisRow = new AResultRow();
final int k = this.getIndex(); **// These are the changes suggested by James**
thisRow = getTableView().getItems().get(k); ***// These are the changes suggested by James***
// thisRow = getTableView().getItems().get(getTableRow().getIndex()); <- this is the old code commented out.
final Tooltip tip= new Tooltip();
tip.setText(thisRow.getCourseTootip(i));
setTooltip(tip);
tip.setStyle("-fx-background-color: pink; -fx-text-fill: black; -fx-font: normal normal 12pt \"Times New Roman\"");
}
}
};
}
});
boolean retVal = thisTable.getColumns().addAll(thisColumn);
}

The quick, and wrong, answer to the question is to point out that TableCell has a getTableRow() method, that will give you the row data without having to look it up through the underlying data via the row index.
Technically, you should give the TableCell all of the information it needs to work independently when its updateItem() method is called. This would mean restructing the data model such that the table cell is given a structure with both the displayed contents of the cell, and the text to go in the tooltip. It would appear that the AResultRow data structure has two associated lists, one with whatever shows in the cell, and the other with whatever goes into the tooltip. My suggestion would be to refactor that so that it's a single list holding objects which contain both data elements. Once you do that, the rest of the table structure becomes trivial. Here's a working example:
public class SampleTable extends Application {
private BorderPane testPane;
class TestPane extends BorderPane {
public TestPane(List<DataModel> dataItems) {
TableView<DataModel> tableView = new TableView<DataModel>();
setCenter(tableView);
TableColumn<DataModel, ClassInfo> column1 = new TableColumn<DataModel, ClassInfo>("column 1");
TableColumn<DataModel, ClassInfo> column2 = new TableColumn<DataModel, ClassInfo>("column 2");
column1.setCellValueFactory(new PropertyValueFactory<DataModel, ClassInfo>("column1Data"));
column2.setCellValueFactory(new PropertyValueFactory<DataModel, ClassInfo>("column2Data"));
column1.setCellFactory(column -> new CustomTableCell());
column2.setCellFactory(column -> new CustomTableCell());
tableView.getColumns().addAll(column1, column2);
tableView.setItems(FXCollections.observableList(dataItems));
}
}
public static void main(String[] args) {
launch(args);
}
public class CustomTableCell extends TableCell<DataModel, ClassInfo> {
#Override
protected void updateItem(ClassInfo item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
if (item != null) {
setText(item.getName());
setTooltip(new Tooltip(item.getDescription()));
}
}
}
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Task Progress Tester");
List<DataModel> dataItems = new ArrayList<DataModel>();
DataModel row1Data = new DataModel();
row1Data.setColumn1Data(new ClassInfo("row1Col1Name", "This is the description for Row1, Column 1"));
row1Data.setColumn2Data(new ClassInfo("row1Col2Name", "This is the description for Row1, Column 2"));
dataItems.add(row1Data);
DataModel row2Data = new DataModel();
row2Data.setColumn1Data(new ClassInfo("row2Col1Name", "This is the description for Row2, Column 1"));
row2Data.setColumn2Data(new ClassInfo("row2Col2Name", "This is the description for Row2, Column 2"));
dataItems.add(row2Data);
testPane = new TestPane(dataItems);
primaryStage.setScene(new Scene(testPane, 300, 250));
primaryStage.show();
}
public class DataModel {
private ObjectProperty<ClassInfo> column1Data = new SimpleObjectProperty<ClassInfo>();
private ObjectProperty<ClassInfo> column2Data = new SimpleObjectProperty<ClassInfo>();
public void setColumn2Data(ClassInfo newValue) {
column2Data.set(newValue);
}
public void setColumn1Data(ClassInfo newValue) {
column1Data.set(newValue);
}
public ObjectProperty<ClassInfo> column1DataProperty() {
return column1Data;
}
}
public class ClassInfo {
private String name;
private String description;
public ClassInfo(String name, String description) {
this.setName(name);
this.setDescription(description);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
}

Related

assertion failed: Unknown column layout data

When I create combo box in particular only one 3rd column using table viewer in Eclipse SWT.
I think I've done everything ok until now, however when I compile the code then i get error:
Code:
public void createPartControl(Composite parent) {
Composite tableComposite = new Composite(parent, SWT.NONE);
tableColumnLayout = new TableColumnLayout();
tableComposite.setLayout(tableColumnLayout);
tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
true));
tableViewer = new TableViewer(tableComposite, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
// TODO viewer.setLabelProvider(new ViewLabelProvider());
table = tableViewer.getTable();
// Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
String[] titles = { "Threat Name", "Category Name", "Status",
"Priority", "Description", "Justification" };
int[] bounds = { 100, 100, 100, 100 };
TableViewerColumn col = createTableViewerColumn(titles[2], bounds[2], 2);
col.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
Dummy p = (Dummy) element;
return p.getValue();
}
});
col.setEditingSupport(new FirstValueEditingSupport(tableViewer));
}
private SelectionAdapter getSelectionAdapter(final TableColumn column,
final int index) {
SelectionAdapter selectionAdapter = new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
tableViewer.refresh();
}
};
return selectionAdapter;
}
private static class Dummy {
public String value;
public Dummy(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public static class FirstValueEditingSupport extends EditingSupport {
private final TableViewer viewer;
private final CellEditor editor;
private final String[] possibleValues = { "Mitigated",
"Not Applicable", "Not Started", "Needs Investigation" };
public FirstValueEditingSupport(TableViewer viewer) {
super(viewer);
this.viewer = viewer;
this.editor = new ComboBoxCellEditor(viewer.getTable(),
possibleValues);
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
Dummy dummy = (Dummy) element;
int index = 0;
for (int i = 0; i < possibleValues.length; i++) {
if (Objects.equals(possibleValues[i], dummy.getValue())) {
index = i;
break;
}
}
return index;
}
#Override
protected void setValue(Object element, Object value) {
Dummy dummy = (Dummy) element;
int index = (Integer) value;
dummy.setValue(possibleValues[index]);
viewer.update(element, null);
}
}
private void fillRows(String shortdesc, String categ, String descp) {
System.out.println("fillRows call from above method.");
TableColumn status_Name_Col = tableViewer.getTable().getColumn(2);
System.out.println("**************** status_Name_Col ************ "
+ status_Name_Col);
tableViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(
SelectionChangedEvent selectionChangedEvent) {
StructuredSelection selection = (StructuredSelection) selectionChangedEvent
.getSelection();
System.out.println(((Dummy) selection.getFirstElement())
.getValue());
}
});
List<Dummy> elements = new ArrayList<>();
for (int i = 0; i < Connection.Number_Of_Connection; i++) {
elements.add(new Dummy("First option"));
}
tableViewer.setInput(elements);
tableColumnLayout.setColumnData(status_Name_Col, new ColumnWeightData(
1, true));
tableViewerColumn.setEditingSupport(new FirstValueEditingSupport(
tableViewer));
}
Questions:
how to display combo box in particular only one column?
You must not do the TableViewer setInput call until you have set up everything on the table. All the content providers, label providers, column layouts, editing support, .... must be set before setInput is called.
You must also call setColumnData for every column you create.

Cannot understand ComboBoxTableCell in a TableView

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?

Building a custom row on demand with GWT CellTableBuilder

In GWT 2.5 RC CellTableBuilder API was introduced but there are no comprehensive documentation available yet. Is there any tutorial\example of implementing on-demand custom row building with CellTableBuilder? The only example I've found so far was this one http://showcase2.jlabanca-testing.appspot.com/#!CwCustomDataGrid but it is quite confusing for me.
So, my goal is to create extra row containing widget that provides details about clicked row in a table.
I've found suitable solution for this problem. Here is the code sample:
public class CustomCellTableBuilder extends AbstractCellTableBuilder<Object>{
//here go fields, ctor etc.
//ids of elements which details we are going to show
private Set elements;
#Override
protected void buildRowImpl(Object rowValue, int absRowIndex){
//building main rows logic
if(elements.contains(absRowIndex)){
buildExtraRow(absRowIndex, rowValue);
elements.add(absRowIndex);
}
}
private void buildExtraRow(int index, Object rowValue){
TableRowBuilder row = startRow();
TableCellBuilder td = row.startTD().colSpan(getColumns().size());
DivBuilder div = td.startDiv();
Widget widget = new Widget();
//update widget state and appearance here depending on rowValue
div.html(SafeHtmlUtils.fromTrustedString(widget.getElement().getInnerHTML()));
div.end();
td.endTD();
row.endTR();
}}
It should be mentioned, that when you handle some event which leads to appearance of extra row, you should invoke redrawRaw(rowIndex) on CellTable which is attached to TableBuilder. And before this call it is necessary to add target row ID to elements Set.
Hope this was helpful.
I have created this class for expanding rows in GWT. It takes a column that you want to expand and replaces it with a place holder that can have 2 states.
I use it like this:
PlaceHolderColumn<Notification, SafeHtml> placeholder = new PlaceHolderColumn<Notification, SafeHtml>(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(Notification object) {
return SafeHtmlUtils.fromSafeConstant(getSelected() ? "<i class=\"glyphicon glyphicon-chevron-down\"></i>"
: "<i class=\"glyphicon glyphicon-chevron-right\"></i>");
}
};
notificationsTable.setTableBuilder(new ExpandableCellTableBuilder<Notification, SafeHtml>(notificationsTable, columnBody, placeholder));
I have access to glyphicon so I use those instead of the default placeholder column which is +/-
< Image here... but for lack of reputation :( >
columnBody in the above code sample is just a standard column that will span the width of the table. The place holder will be displayed in its place in whatever position columnBody was configured to sit at.
Hope that helps someone :)
public class ExpandableCellTableBuilder<T, U> extends AbstractCellTableBuilder<T> {
private Column<T, U> expandColumn = null;
private PlaceHolderColumn<T, ?> placeholderColumn = null;
private final String evenRowStyle;
private final String oddRowStyle;
private final String selectedRowStyle;
private final String cellStyle;
private final String evenCellStyle;
private final String oddCellStyle;
private final String firstColumnStyle;
private final String lastColumnStyle;
private final String selectedCellStyle;
public static class ExpandMultiSelectionModel<T> extends AbstractSelectionModel<T> {
Map<Object, T> selected = new HashMap<Object, T>();
/**
* #param keyProvider
*/
public ExpandMultiSelectionModel(ProvidesKey<T> keyProvider) {
super(keyProvider);
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.view.client.SelectionModel#isSelected(java.lang.Object)
*/
#Override
public boolean isSelected(T object) {
return isKeySelected(getKey(object));
}
protected boolean isKeySelected(Object key) {
return selected.get(key) != null;
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.view.client.SelectionModel#setSelected(java.lang.Object, boolean)
*/
#Override
public void setSelected(T object, boolean selected) {
Object key = getKey(object);
if (isKeySelected(key)) {
this.selected.remove(key);
} else {
this.selected.put(key, object);
}
scheduleSelectionChangeEvent();
}
}
public static abstract class PlaceHolderColumn<T, C> extends Column<T, C> {
private boolean isSelected;
/**
* #param cell
*/
public PlaceHolderColumn(Cell<C> cell) {
super(cell);
}
protected boolean getSelected() {
return isSelected;
}
}
private int expandColumnIndex;
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn) {
this(cellTable, expandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), null);
}
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, SelectionModel<T> selectionModel) {
this(cellTable, exandColumn, selectionModel, null);
}
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, PlaceHolderColumn<T, ?> placeHolder) {
this(cellTable, exandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), placeHolder);
}
/**
* #param cellTable
* #param columnBody
*/
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn, SelectionModel<T> selectionModel,
PlaceHolderColumn<T, ?> placeHolder) {
super(cellTable);
this.expandColumn = expandColumn;
this.cellTable.setSelectionModel(selectionModel);
if (placeHolder == null) {
this.placeholderColumn = new PlaceHolderColumn<T, String>(new TextCell()) {
#Override
public String getValue(T object) {
return getSelected() ? "-" : "+";
}
};
} else {
this.placeholderColumn = placeHolder;
}
// Cache styles for faster access.
Style style = cellTable.getResources().style();
evenRowStyle = style.evenRow();
oddRowStyle = style.oddRow();
selectedRowStyle = " " + style.selectedRow();
cellStyle = style.cell();
evenCellStyle = " " + style.evenRowCell();
oddCellStyle = " " + style.oddRowCell();
firstColumnStyle = " " + style.firstColumn();
lastColumnStyle = " " + style.lastColumn();
selectedCellStyle = " " + style.selectedRowCell();
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.user.cellview.client.AbstractCellTableBuilder#buildRowImpl(java.lang.Object, int)
*/
#Override
protected void buildRowImpl(T rowValue, int absRowIndex) {
// Calculate the row styles.
SelectionModel<? super T> selectionModel = cellTable.getSelectionModel();
final boolean isSelected = (selectionModel == null || rowValue == null) ? false : selectionModel.isSelected(rowValue);
boolean isEven = absRowIndex % 2 == 0;
StringBuilder trClasses = new StringBuilder(isEven ? evenRowStyle : oddRowStyle);
if (isSelected) {
trClasses.append(selectedRowStyle);
}
// Add custom row styles.
RowStyles<T> rowStyles = cellTable.getRowStyles();
if (rowStyles != null) {
String extraRowStyles = rowStyles.getStyleNames(rowValue, absRowIndex);
if (extraRowStyles != null) {
trClasses.append(" ").append(extraRowStyles);
}
}
// Build the row.
TableRowBuilder tr = startRow();
tr.className(trClasses.toString());
// Build the columns.
int columnCount = cellTable.getColumnCount();
for (int curColumn = 0; curColumn < columnCount; curColumn++) {
Column<T, ?> column = cellTable.getColumn(curColumn);
if (column == expandColumn) {
expandColumnIndex = curColumn;
column = placeholderColumn;
placeholderColumn.isSelected = isSelected;
}
// Create the cell styles.
StringBuilder tdClasses = new StringBuilder(cellStyle);
tdClasses.append(isEven ? evenCellStyle : oddCellStyle);
if (curColumn == 0) {
tdClasses.append(firstColumnStyle);
}
if (isSelected) {
tdClasses.append(selectedCellStyle);
}
// The first and last column could be the same column.
if (curColumn == columnCount - 1) {
tdClasses.append(lastColumnStyle);
}
// Add class names specific to the cell.
Context context = new Context(absRowIndex, curColumn, cellTable.getValueKey(rowValue));
String cellStyles = column.getCellStyleNames(context, rowValue);
if (cellStyles != null) {
tdClasses.append(" " + cellStyles);
}
// Build the cell.
HorizontalAlignmentConstant hAlign = column.getHorizontalAlignment();
VerticalAlignmentConstant vAlign = column.getVerticalAlignment();
TableCellBuilder td = tr.startTD();
td.className(tdClasses.toString());
if (hAlign != null) {
td.align(hAlign.getTextAlignString());
}
if (vAlign != null) {
td.vAlign(vAlign.getVerticalAlignString());
}
// Add the inner div.
DivBuilder div = td.startDiv();
div.style().outlineStyle(OutlineStyle.NONE).endStyle();
// Render the cell into the div.
renderCell(div, context, column, rowValue);
// End the cell.
div.endDiv();
td.endTD();
}
// End the row.
tr.endTR();
if (isSelected) {
buildExpandedRow(rowValue, absRowIndex, columnCount, trClasses, isEven, isSelected);
}
}
/**
* #param trClasses
*
*/
private void buildExpandedRow(T rowValue, int absRowIndex, int columnCount, StringBuilder trClasses, boolean isEven, boolean isSelected) {
TableRowBuilder tr = startRow();
tr.className(trClasses.toString());
Column<T, ?> column = expandColumn;
// Create the cell styles.
StringBuilder tdClasses = new StringBuilder(cellStyle);
tdClasses.append(isEven ? evenCellStyle : oddCellStyle);
tdClasses.append(firstColumnStyle);
if (isSelected) {
tdClasses.append(selectedCellStyle);
}
tdClasses.append(lastColumnStyle);
// Add class names specific to the cell.
Context context = new Context(absRowIndex, expandColumnIndex, cellTable.getValueKey(rowValue));
String cellStyles = column.getCellStyleNames(context, rowValue);
if (cellStyles != null) {
tdClasses.append(" " + cellStyles);
}
// Build the cell.
HorizontalAlignmentConstant hAlign = column.getHorizontalAlignment();
VerticalAlignmentConstant vAlign = column.getVerticalAlignment();
TableCellBuilder td = tr.startTD();
td.colSpan(columnCount);
td.className(tdClasses.toString());
if (hAlign != null) {
td.align(hAlign.getTextAlignString());
}
if (vAlign != null) {
td.vAlign(vAlign.getVerticalAlignString());
}
// Add the inner div.
DivBuilder div = td.startDiv();
div.style().outlineStyle(OutlineStyle.NONE).endStyle();
// Render the cell into the div.
renderCell(div, context, column, rowValue);
// End the cell.
div.endDiv();
td.endTD();
// End the row.
tr.endTR();
}

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!

Drag and drop for tableviewer in SWT

I need to Drag tableViewer cell value to another tableViewer cell in swt.
I need to remove that value where i dragged and add those value where i dropped in tableViewer i'm able to drag and drop but not able to drop where i want too and not able to remove and add value when i drag and drop in tableviewer. Here is the i have:Thank in advance for help.
public void DragandDrop(){
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DragSource source = new DragSource(table_2, DND.DROP_MOVE | DND.DROP_COPY);
source.setTransfer(types);
source.addDragListener(new DragSourceAdapter() {
public void dragSetData(DragSourceEvent event) {
DragSource ds = (DragSource) event.widget;
Table table = (Table) ds.getControl();
TableItem[] selection = table.getSelection();
StringBuffer buff = new StringBuffer();
for (int i = 0, n = selection.length; i < n; i++) {
buff.append(selection[i].getText());
}
event.data = buff.toString();
}
});
DropTarget target = new DropTarget(table_3, DND.DROP_MOVE | DND.DROP_COPY );
target.setTransfer(types);
target.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
if (event.detail != DND.DROP_DEFAULT) {
event.detail = (event.operations & DND.DROP_COPY) != 0 ? DND.DROP_COPY : DND.DROP_NONE;
}
for (int i = 0, n = event.dataTypes.length; i < n; i++) {
if (TextTransfer.getInstance().isSupportedType(event.dataTypes[i])) {
event.currentDataType = event.dataTypes[i];
}
}
}
public void dragOver(DropTargetEvent event) {
event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL;
}
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
DropTarget target = (DropTarget) event.widget;
Table table = (Table) target.getControl();
String data = (String) event.data;
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] { data });
// table.redraw();
}
}
});
}
to remove the selected value you can use follows
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
DropTarget target = (DropTarget) event.widget;
Table table = (Table) target.getControl();
String data = (String) event.data;
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] { data });
//remove the tableitem you drag
table.remove(table.getSelectionIndex());
}
I was looking for Drag and Drop on TableViewer and found the solutions. Hope everyone understand easily. My case, I created two new Listener class inheritance from DragSourceListener & DropTargetListener. Because I want to use TableViewer functions. You need three things to do.
First save index of source item from void dragStart(DragSourceEvent event),
Seconds set data into event.data and
Then Last found target index from void drop(DropTargetEvent event).
public class TestClass extends TableViewer {
private int sourceIndex;
priavte class DragListener implements DragSourceListener {
private TableViewer viewer;
public ItemDragListener(TableViewer viewer) {
this.viewer = viewer;
}
public void dragStart(DragSourceEvent event) {
sourceIndex = viewer.getTable().getSelectionIndex();
}
public void dragSetData(DragSourceEvent event) {
// save data
ISelection select = viewer.getSelection();
if (select instanceof IStructuredSelection) {
Object item = (Object) ((IStructuredSelection)select).getFirstElement();
// save item to event.data
event.data = .........
}
:
}
private class ItemDropListener implements DropTargetListener {
TableViewer viewer;
public ItemDropListener(TableViewer viewer) {
this.viewer = viewer;
}
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
TableItem item = (TableItem)event.item;
int targetIndex= -1;
if (item != null) {
Table table = item.getParent();
targetIndex= table.indexOf(item);
}
String data = (String) event.data;
// add an item
if (targetIndex >= 0)
viewer.insert((Object)data, targetIndex);
else
viewer.add((Object)data);
// remove an item
viewer.getTable().remove(sourceIndex); // Careful, it can be changed after add an item
}
}
public void init() {
Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() };
this.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, new ItemDragListener(this));
this.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, new ItemDropListener(this));
}
}