GWT does not contain TreeTable but my project requirement with tree table. so I created it by using Tree and FlexTable.
Here Bean class: Item
class Item
{
ItemType itemType; //Parent,Child Enum type
long parentId;
long amount;
String itemName;
String qty;
String rate;
//Setter / Getter Methods
}
This is custom TreeItem class which has relation between parent Item & Child Item. I have Created one row By using TreeItemNode.
public class TreeItemNode extends TreeItem {
private FlexTable table; //this will use to access child
private FlexTable parentTable; //This will use to access parent of particular child.
//This constructor create parent node
public TreeItemNode(FlexTable parentTable) {
setWidget(parentTable);
this.parentTable=parentTable;
setState(true);
}
//The method used to add Child items in parent
public TreeItem addItem(Widget widget) {
this.table=(FlexTable) widget;
TreeItem ret = new TreeItem(widget);
addItem(ret);
return ret;
}
}
Using Item List, This method is creating the tree which has parent and child node relations.
class CustomTreeTable extends Tree
{
public void createTreeTable() {
//This map store parent id and tree item object for letter fetch the parent node and add child node in it
treeItemMap = new HashMap<Long, BOQTreeItem>();
for (Item item : itemList) {
if (item.getParentItemId() == 0) {
//Create new parent node
TreeItemNode itemTreeItem = new TreeItemNode(addChildItem(item,
new FlexTable(), true),
"gwt-TreeNode");
treeItemMap.put(item.getId(), treeItem);
addItem(itemTreeItem);
} else {
//Add child node
if (treeItemMap.containsKey(item.getParentItemId())
&& treeItemMap.get(item.getParentItemId()) != null) {
FlexTable dataFlextable = treeItemMap.get(
item.getParentItemId()).getTable();
if (dataFlextable == null) {
dataFlextable = new FlexTable();
treeItemMap.get(item.getParentItemId()).setTable(
dataFlextable);
}
FlexTable treeTable = addChildItem(item, dataFlextable,
false);
treeItemMap.get(item.getParentItemId()).addItem(treeTable);
}
}
}
}
}
Using this my table is as below. + is my tree node open/ close like:
ItemName qty rate amount
+ item1 11 1 11 //parent item
---------------------------
- item2 11 2 22
--------------------------------
SubItemName qty rate amount //child item
subItem1 5 2 10
subItem2 8 5 40
------------------------------------
The problem is when I want calculate qty* rate in one raw (child item) than I can do using row index but if I want to do calculate all the child item & show in parent row. then logic become so complex. so I just want to know the logic which I implemented like store the instance in map and managed. is it proper? I am going in right direction or wrong.
Maybe using a DataGrid Widget will be simpler for what you are trying to achieve.
Look at the GWT ShowCase : here
On the DataGrid, you have childs under parent row displaying when you click on ShowFriends link.
Hope it helps. :)
Related
It is possible to issue java.lang.reflect.Field to javafx.scene.control.TextField?
For example:
Field[] nodes;
nodes = clase.getDeclaredFields();
for (Field n : nodes)
if (n.getType().getSimpleName().equals("TextField"))
((TextField)((Object) n)).setText("Text");
If you want to modify the TextFields, you need to retrieve the value from those fields (and cast this value to TextField).
The following example should demonstrate the approach:
private TextField t1 = new TextField();
private TextField t2 = new TextField();
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
Object object = this;
Class clazz = object.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (field.getType().getName().equals("javafx.scene.control.TextField")) {
try {
// get field value here
TextField textField = (TextField) field.get(object);
if (textField != null) {
textField.setText("Hello World");
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(ReflectTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
VBox root = new VBox();
root.getChildren().addAll(btn, t1, t2);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
Reflection is probably a really bad approach to this. Among many problems is that you make the functionality dependent on how the code is written. Specifically, you assume that each text field is stored in a specific instance field in some class. If you change the implementation, e.g. so that you keep the text fields in a data structure instead of maintaining references to them yourself, then your functionality will break. It is bad practice to write code that is so tightly coupled to the actual implementation of the code, for obvious reasons.
One better approach would simply to be to put all the text fields in a list (or other data structure), so you can do whatever you need with them easily. E.g.
public class MyForm {
private GridPane view ;
private String[] messages = {"First name:", "Last name", "Email"} ;
private List<TextField> textFields ;
public MyForm {
view = new GridPane();
textFields = new ArrayList<>();
for (int r = 0; r < messages.length ; r++) {
view.addRow(r, new Label(messages[r]), createTextField(messages[r]));
}
}
private TextField createTextField(String text) {
TextField textField = new TextField();
textField.setPromptText(text);
textFields.add(textField);
return textField ;
}
public void processTextFields() {
textField.forEach(tf -> tf.setText("Hello"));
}
}
Another approach would be to use a CSS lookup. If myForm is some node that is an ancestor of all the text fields:
myForm.lookupAll(".text-field").forEach(node -> {
TextField textField = (TextField)node ;
textField.setText("Hello");
});
but note that CSS lookups will not work until after CSS has been applied (by default, this means after the scene has been rendered for the first time).
Another way, if all the text fields are all contained in a single direct parent (such as the grid pane in the first example), would be to iterate through the child nodes and filter the text fields:
textFieldParentNode.getChildrenUnmodifiable().stream()
.filter(TextField.class::isInstance)
.map(TextField.class::cast)
.forEach(tf -> tf.setText("Hello"));
I have listView with drag drop functionality. I'm using ListView with custom layout- I have SeekBar and TextView in custom ListView layout. When I drag and drop each ListView items after changing SeekBar value, TextView is moving and SeekBar value is not moving.
It may be caused by Adapter. So I've share my adapter codes.
https://gist.github.com/salihyalcin/38e320726e3ab8346c50
Thanks in advance
EDIT --- My ListItem Class
class ListItem {
String textdata;
public ListItem(String textdata) {
this.textdata = textdata;
}
public boolean equals(Object o) {
ListItem ndListItemObject = (ListItem) o;
return this.textdata.equalsIgnoreCase(ndListItemObject.textdata);
}
}
** My ListView looks like image below
** Change the SeekBar value of Layer1
** Drag-Drop Layer1 and Layer2
** Layer1 and Layer2 moved but SeekBar values stay same place, they didn't moved.
I think I have an idea. First, your post is missing code snippet of the definition of NavigationDrawerFragment.ListItem class, could be helpful. I do remember that you call method swapElements in DynamicListView but other readers probably don't need to know it.
My suggestion is to save the progress value into the ListItem class, sample code below. We will depend on swapElements() to swap the 2 ListItem objects properly, along with the progress and text (layers in your case).
EDIT, code suggestion for ListItem class:
class ListItem {
String textdata;
int seekBarValue;
public ListItem(String textdata) {
this.textdata = textdata;
}
public ListItem(String textdata, int seekBarValue) {
this.textdata = textdata;
this.seekBarValue = seekBarValue;
}
...
Notes for ListItem code:
Added seekBarValue as a public data member, and another ListItem constructor for the caller's convenience.
This is what I meant by add another data member to this class.
Code snippet suggestion for the Adapter:
holder.mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
final NavigationDrawerFragment.ListItem item = myItems.get(position);
View view = (View) seekBar.getParent();
if (view != null) {
holder.text.setText(progress + "%");
item.seekBarValue = progress;
Notes:
Added code line ...item = myItems.get(position); to get the correct item in the ArrayList.
Set the progress to item.seekBarValue
You may remove these codes below unless you plan on using it, of course:
holder.mSeekBar.getTag();
holder.text.getTag();
mar.get(1,progress);
I have a selectable Tree with checkbox appearance. I need to select all sibling TreeNode on selection of a specific TreeNode.
I could get all the sibling tree nodes, but I don't know what is the attribute name of TreeNode to make that checkbox selected.
Can anybody help me giving some way to select those nodes.
compareGrid.addSelectionChangedHandler(new SelectionChangedHandler() {
#Override
public void onSelectionChanged(SelectionEvent event) {
TreeNode node = (TreeNode) event.getSelectedRecord();
TreeNode parent = tree.getParent(node);//tree is Tree object
treeGrid.selectRecord(parent);
TreeNode[] nodes = tree.getAllNodes(parent);
for(int i=0; i< nodes.length; i++){
if(!nodes[i].getAttributeAsBoolean("isSelected"))
treeGrid.selectRecord(nodes[i]);
}
}
}
});
You can use any of the following:
treeGrid.selectAllRecords();
treeGrid.selectRecord(record);
treeGrid.selectRecords(records);
The first method will select all the TreeNodes of the tree.
The 2nd one will select only one specified TreeNodes of the tree.
And the 3rd one will select multiple specified TreeNodes of the tree.
There are multiple overloaded methods for the last 2 methods, which allows you to specify Nodes in terms of, TreeNode(s) itself, or index of the TreeNode(s).
Here's a solution quite close (without checkboxes) to what you need.
employeeTreeGrid.addNodeClickHandler(new NodeClickHandler() {
public void onNodeClick(NodeClickEvent event) {
if (event.getNode() != null) {
TreeNode node = event.getNode();
TreeNode parent = employeeTree.getParent(node);
if (employeeTreeGrid.isSelected(node)) {
List<TreeNode> nodesToSelect = new ArrayList<TreeNode>();
// omit parent (root) if on first level
if (!"1".equals(node.getAttribute("ReportsTo"))) {
nodesToSelect.add(parent);
}
TreeNode[] siblings = employeeTree.getChildren(parent);
nodesToSelect.addAll(Arrays.asList(siblings));
RecordList recordList = employeeTreeGrid.getOriginalRecordList();
for (TreeNode treeNode : nodesToSelect) {
Record record = recordList.find("EmployeeId", treeNode.getAttribute("EmployeeId"));
if (record != null) {
employeeTreeGrid.selectRecord(record);
}
}
}
}
}
});
Have to use the RecordList and first find required records in order to use ListGrid.selectRecord() methods.
Using SelectionAppearance.CHECKBOX and SelectionChangedHandler can be tricky as programmatic selections are going to trigger further selection events.
This is based on Checkbox tree sample with below changes.
// employeeTreeGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
// employeeTreeGrid.setShowSelectedStyle(false);
employeeTreeGrid.setShowPartialSelection(false);
// employeeTreeGrid.setCascadeSelection(true);
employeeTreeGrid.setSelectionType(SelectionStyle.SIMPLE);
To get the value of selected checkbox from tree grid in smart gwt I have following solution ListGridRecord[] arrRec = event.getSelection(); sample code is below.
employeeTreeGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
employeeTreeGrid.setSelectionType(SelectionStyle.SIMPLE);
employeeTreeGrid.addSelectionChangedHandler(new SelectionChangedHandler() {
#Override
public void onSelectionChanged(SelectionEvent event)
//selectedCounties Set to add selected checkbox or deslected checkbox names/title
if (selectedCounties == null || selectedCounties.size() == 0)
selectedCounties = new TreeSet<String>();
selectedCounties.clear();
ListGridRecord[] arrRec = event.getSelection();
for (ListGridRecord listGridRecord : arrRec) {
selectedCounties.add(listGridRecord.getAttribute("Name"));
}
// You can do iteration over it if needed
selectedCounties.remove("All Counties");
Iterator<String> it = selectedCounties.iterator();
while (it.hasNext()) {
if (it.next().contains("Zone")) {
it.remove();
}
}
}
});
I have a datagrid that may display many rows per page. Let's say I am displayed 25 rows per page. The viewable area of the grid, however, is only 10 rows. i.e. There is only 400px for the entire grid and each row is 40px. So there is a scroll bar on the grid.
When I remove a single row in the grid, the grid automatically moves to the first row in the grid. If I have scrolled the bottom and deleted the last row, I am once again moved to the 1st row.
I have attempted several ways of combatting this, but I can't find a solution that works the way I want it to.
I've tried scrolling the row directly before or after the deleted row into view using the scrollIntoView() method.
I've tried figuring out how to determine which rows were in the visible range before the deletion, but the getVisibleRange() method is relevant to the page range, not the actual displayed range.
I've searched the web for this and seems like I'm the only one having this problem. What am I missing?
I had the same issue, I found that the bug happend if dataGrid has
keyboardSelectionPolicy="BOUND_TO_SELECTION"
If you use ListDataProvider to manage the DataGrid's data, then the DataGrid will not scroll when removing/adding items.
Here is a minimal example of removing grid rows without any scrolling (all contained within the entry point class):
Class for DataGrid Rows:
private class Item{
public String text;
public int value;
public Item(String text, int value){
this.text = text;
this.value = value;
}
}
Filling the DataGrid:
Here I use a private variable, data, to hold the items for the DataGrid. Note, that we must attach the dataGrid to data via the addDataDisplay method.
ListDataProvider data;
public void onModuleLoad() {
// build grid:
DataGrid dataGrid = new DataGrid();
BuildColumns(dataGrid);
dataGrid.setWidth("300px");
dataGrid.setHeight("300px");
// add items:
data = new ListDataProvider();
for(int i = 1; i < 25; i++){
data.getList().add(new Item("Item " + i, i));
}
data.addDataDisplay(dataGrid);
// display:
RootPanel.get().add(dataGrid);
}
Building the DataGrid:
This private method is used to build the columns for the DataGrid. Inside of the FieldUpdater for delCol, which is used to listen for click events for button columns, we remove the respective item from data, and call data.refresh() to update the DataGrid display.
private void BuildColumns(DataGrid dataGrid){
Column textCol = new Column(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(Item object) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendEscaped(object.text);
return sb.toSafeHtml();
}
};
dataGrid.addColumn(textCol);
dataGrid.setColumnWidth(textCol, 75, Unit.PCT);
Column deleteCol = new Column(new ButtonCell()) {
#Override
public String getValue(Item object) {
return "Delete " + object.value;
}
};
deleteCol.setFieldUpdater(new FieldUpdater() {
#Override
public void update(int index, Item object, String value) {
data.getList().remove(index);
data.refresh();
}
});
dataGrid.addColumn(deleteCol);
}
I put this code in a new GWT project and tested it. The DataGrid does not scroll when removing rows.
AID BID count1 count2
AID1 1 3 4
2 4 5
3 4 2
AID2 4 6 10
5 2 4
6 4 6
AID3 7 4 5
8 9 4
THis is the table I am trying to display that is for every AID in ObjA display a list of ObjB s.
I want to display a Sortable data using Wicket DataTable or Listview .I have used the SortableData Provider and it works for simple Objects like
ObjA{
int a;
String b;
}
But I have an Object which has List of Objects within it as field as shown below.
ObjA{
Long aId;
List<ObjB> listObjB;
}
#magomi
Thank you for your response.This is the code and the corresponding Html files. I am using DataTables.
I am not sure how to render the items in the listObjBs (bID,count,count2) in the table for every aID.
What is the right way to add the columns for the listObjBs in the ObjA
***columns.add(new PropertyColumn<ObjA>(Model.of("B ID"), "ObjBCounts.bID",
"ObjBCounts.BID"));
columns.add(new PropertyColumn<ObjA>(Model.of(" Count"), "objBCounts.count"));
columns.add(new PropertyColumn<ObjA>(Model.of("Count2”),"objBCounts.count2"));***
How do I sort on the column bID in the iterator method?
Public class HomePage extends Webpage
private static List<ObjB> listObjBs = Arrays.asList(
new ObjB(15L,2,5),
new ObjB(12L,7,10),
new ObjB(13L,3,5),
new ObjB(10L,6,5));
private static List<ObjA> contacts = Arrays.asList(
new ObjA(1L,listObjBs),
new ObjA(2L,listObjBs),
new ObjA(3L,listObjBs),
new ObjA(4L,listObjBs));
public HomePage(final PageParameters parameters) {
List<IColumn<ObjA>> columns = new ArrayList<IColumn<ObjA>>();
columns.add(new PropertyColumn<ObjA>(Model.of("A ID"), "aID",
"aID"));
Public class HomePage extends Webpage
private static List<ObjB> listObjBs = Arrays.asList(
new ObjB(15L,2,5),
new ObjB(12L,7,10),
new ObjB(13L,3,5),
new ObjB(10L,6,5));
private static List<ObjA> contacts = Arrays.asList(
new ObjA(1L,listObjBs),
new ObjA(2L,listObjBs),
new ObjA(3L,listObjBs),
new ObjA(4L,listObjBs));
public HomePage(final PageParameters parameters) {
List<IColumn<ObjA>> columns = new ArrayList<IColumn<ObjA>>();
columns.add(new PropertyColumn<ObjA>(Model.of("A ID"), "aID",
"aID"));
columns.add(new PropertyColumn<ObjA>(Model.of("B ID"), "ObjBCounts.bID",
"ObjBCounts.BID"));
columns.add(new PropertyColumn<ObjA>(Model.of(" Count"), "objBCounts.count"));
columns.add(new PropertyColumn<ObjA>(Model.of("Count2”),"objBCounts.count2"));
add(new DefaultDataTable<ObjA>("contacts", columns,
new ContactsProvider(), 10));
}
rivate static class ContactsProvider extends SortableDataProvider<ObjA> {
public ContactsProvider() {
setSort("aID", SortOrder.ASCENDING);
}
public Iterator<? extends ObjA> iterator(int first, int count) {
List<ObjA> data = new ArrayList<ObjA>(contacts);
Collections.sort(data, new Comparator<ObjA>() {
public int compare(ObjA o1, ObjA o2) {
int dir = getSort().isAscending() ? 1 : -1;
if ("bID".equals(getSort().getProperty())) {
return dir * (o1.listObjB.get(0).getBID().compareTo(o2.listObjB.get(0).getBID()));
} else {
return dir * (o1.getAID().compareTo(o2.getAID()));
}
}
});
return data.subList(first, Math.min(first + count, data.size()))
.iterator();
}
public int size() {
return contacts.size();
}
public IModel<ObjA> model(ObjA object) {
return Model.of(object);
}
}
<html>
<body>
<table border ="1" cellspacing = "1" wicket:id="contacts" class="contacts"></table>
</body>
</html>
add(new DefaultDataTable<ObjA>("contacts", columns,
new ContactsProvider(), 10));
}
rivate static class ContactsProvider extends SortableDataProvider<ObjA> {
public ContactsProvider() {
setSort("aID", SortOrder.ASCENDING);
}
public Iterator<? extends ObjA> iterator(int first, int count) {
List<ObjA> data = new ArrayList<ObjA>(contacts);
Collections.sort(data, new Comparator<ObjA>() {
public int compare(ObjA o1, ObjA o2) {
int dir = getSort().isAscending() ? 1 : -1;
if ("bID".equals(getSort().getProperty())) {
return dir * (o1.listObjB.get(0).getBID().compareTo(o2.listObjB.get(0).getBID()));
} else {
return dir * (o1.getAID().compareTo(o2.getAID()));
}
}
});
return data.subList(first, Math.min(first + count, data.size()))
.iterator();
}
public int size() {
return contacts.size();
}
public IModel<ObjA> model(ObjA object) {
return Model.of(object);
}
}
<html>
<body>
<table border ="1" cellspacing = "1" wicket:id="contacts" class="contacts"></table>
</body>
</html>
ObjB{
Long bId;
int count;
int count2;
}
It want to display data from ObjA which contains a list of objBs in a Sortable table
Could some one please help me with the wicket markup and and how to populate the columns.
Thank you.
I'm not quite sure but it looks like you are mixing ObjA and ObjB into one table in a way that is not possible. Is it right, you want to show a table of ObjA (at least this is indicated by your first column)? Or do you want to show a table of ObjB (as indicated by the second and third column)?
As long as a table is backed by one list you cannot mix another list into this table.
From my sight you have the following options:
You can can have a table of ObjA and inside a table cell you can have a panel with a table of ObjB. But there is no sorting over all rows of ObjB of all ObjA.
You can define some kind of DTO that has a object mixed from ObjA and ObjB. Something like this:
class Data() {
int objAId;
int objBId;
int count1;
int count2;
...
}
You can use a standard repeating view and implement the sorting into your own data provider.