JFace TreeViewer doesn't update when element is added to model - java

I know this has a few answers, but none of them are working for me. Also the questions are a bit different because I'm using my own model implementation.
This code shows what should happen on button click.
Here the content is set to the tree viewer:
root = new TreeRootModel(solverEntries, null, configParser.getConfFile());
root.addInstances(instances);
viewer.setInput(new TreeRootModel[] { root });
column.pack(); // important to see TreeViewer at start
viewer.expandAll();
The TreeRootModel class is just a storage class under which an array is stored, with getter and setter. Not worth showing here.
ToolBar toolBar = new ToolBar(newMainComposite, SWT.FLAT | SWT.WRAP | SWT.RIGHT);
ToolItem addItem = new ToolItem(toolBar, SWT.PUSH);
addItem.setText("Add");
addItem.setImage(addIcon);
addItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
InstanceModel newInstance = new InstanceModel("new Instance", null);
instances.add(newInstance);
// none of these three calls has an effect
viewer.refresh();
tree.update();
column.pack();
}
});
So the content of the TreeViewer is root, and root contains the List "instances". These objects will be displayed in the TreeViewer. Upon clicking the add button, an object is added to the List instances. I want to see that immediately in the TreeViewer.
The ContentProvider's inputChanged method is empty.
public class GoalInstanceContentProvider implements ITreeContentProvider, IResourceChangeListener {
TreeRootModel root;
ArrayList<InstanceModel> instances = new ArrayList<>();
private TreeViewer viewer;
private TreeRootModel[] input;
#Override
public void dispose() {
}
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
#SuppressWarnings("unchecked")
#Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof TreeRootModel) {
root = (TreeRootModel) inputElement;
return root.getInstances().toArray();
} else if (inputElement instanceof ArrayList) {
instances = (ArrayList<InstanceModel>) inputElement;
return instances.toArray();
}
return ArrayContentProvider.getInstance().getElements(inputElement);
}
...
}

Stop putting root inside of an array when setting the input. Use it directly.

Related

How to tell a FieldEditorPreferencePage to invalidate/redraw programatically?

I defined a custom FieldEditorPreferencePage. In createFieldEditors method I construct a simple interface with a custom FieldEditor that holds button that loads a file. When a user loads the file the interface region (where the button stands) need to change and show other specific gui. How to invalidate the FieldEditorPreferencePage? I used the layout() method of the parent composite but nothing happens. What am I doing wrong here?
public class MyPage extends FieldEditorPreferencePage {
...
private Composite fieldEditorParent;
private boolean fileLoaded = false;
#Override
protected void createFieldEditors() {
fieldEditorParent = this.getFieldEditorParent();
MyFieldEditor compositeFieldEditor = new MyFieldEditor(fieldEditorParent) {
if(fileLoaded) {
//draw file content
} else {
Button chooseButton = new Button(buttonsComposite, SWT.NONE);
chooseButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
//choose file
fileLoaded = true;
//invalidate page <-- THIS DOES NOT WORK!
fieldEditorParent.layout(true, true);
}
}
}
}
}

JavaFX CheckBoxTree in popup of drop-down Button

In order for the end-user to constrain a search to some columns of the main TableView, I needed a treeview with checkboxes.
I decided to embed this TreeView in a popup, showing on click on a custom button.
I have created the following class, inspired from the question:
Java FX8 TreeView in a table cell
public class CustomTreeMenuButton extends MenuButton {
private PopupControl popup = new PopupControl();
private TreeView<? extends Object> tree;
private CustomTreeMenuButton me = this;
public void setTree(TreeView<? extends Object> tree) {
this.tree = tree;
}
public CustomTreeMenuButton() {
super();
this.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (!popup.isShowing()) {
Bounds b = me.localToScreen(me.getBoundsInLocal());
double x = b.getMinX();
double y = b.getMaxY();
popup.setAutoHide(true);
// popup.setAutoFix(true);
popup.setAnchorX(x);
popup.setAnchorY(y);
popup.setSkin(new Skin<Skinnable>() {
#Override
public void dispose() {
}
#Override
public Node getNode() {
return tree;
}
#Override
public Skinnable getSkinnable() {
return null;
}
});
popup.show(me.getScene().getWindow());
}
}
});
}
}
The tree I am working with contains CheckBoxTreeItem objects, and while the popup is working, there is some weird blur on all checkboxes, whenever the focus is not on a checkbox. (See GIF below)
First, I was thinking it was maybe an antialiasing problem, but popup.getScene().getAntiAliasing().toString() returns DISABLED
Then, I saw that non integer anchor points could cause problems. However popup.setAutoFix(true) did nothing, nor did the following:
popup.setAnchorX(new Double(x).intValue());
popup.setAnchorY(new Double(y).intValue());
It might be worth noting that I am working with FXML.
How can I get sharp checkboxes regardless of their focus ?
I would suggest a built-in control, CustomMenuItem, rather than reinventing the wheel:
A MenuItem that allows for arbitrary nodes to be embedded within it,
by assigning a Node to the content property.
An example
// Create the tree
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("All stuff");
rootItem.setExpanded(true);
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setEditable(true);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
for (int i = 0; i < 8; i++) {
final CheckBoxTreeItem<String> checkBoxTreeItem =
new CheckBoxTreeItem<String>("Stuff" + (i+1));
rootItem.getChildren().add(checkBoxTreeItem);
}
tree.setRoot(rootItem);
tree.setShowRoot(true);
// Create a custom menu item
CustomMenuItem customMenuItem = new CustomMenuItem(tree);
customMenuItem.setHideOnClick(false);
// Create the menu button
MenuButton mb = new MenuButton("Stuffs");
mb.getItems().add(customMenuItem);
And the output
Note: It is important to set the hideOnClickProperty to true, to avoid closing when the user clicks in the tree, which can be even done in the contructor, so you can shorten the initialization to:
CustomMenuItem customMenuItem = new CustomMenuItem(tree, false);
If you want to remove the hover glow, you can add the following CSS class:
.menu-item {
-fx-padding: 0;
}

How to edit a tree node in SWT

I am creating a RCP application which will display a tree structure. I used the following code for this purpose. But, I need to make the nodes editable. How to do that?
Please find the below code which I have written.
public class TreeView extends ViewPart {
public static final String ID = "TreeProject.project";
public TreeView() {
}
public static ProjectTree mc = new ProjectTree("root");
public static TreeViewer treeViewer;
#Override
public void createPartControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
treeViewer = new TreeViewer(composite);
Tree tree = treeViewer.getTree();
tree.setLocation(0, 0);
tree.setSize(181, 469);
StyledText styledText = new StyledText(composite, SWT.BORDER);
styledText.setText("Welcome\"!");
styledText.setBounds(179, 0, 415, 469);
treeViewer.setContentProvider(new ProjectContentProvider());
treeViewer.setInput(getRootNode());
treeViewer.expandAll();
System.out.println(tree.getSelection());
}
private ProjectTree getRootNode() {
ProjectTree node0 = new ProjectTree("Node0");
ProjectTree node1 = new ProjectTree("Node1");
mc.addChild(node0, "");
node0.addChild(node1, "");
return mc;
}
#Override
public void setFocus() {
}
}
You need to use a selection listener on the treeViewer which would give you the node selected. You then have to remove the node object and its children,if any, from the model . Here I see that your model is the object mc. Then call treeViewer.refresh(). Similarly for add .

Jface TreeViewer add right click menu, depending on clicked node

There is a good thread on how to correctly hook up a right-click menu to a Jface TreeViewer depending on the selected item.
I would like to show the right click menu depending on: if the right-click was on a node or into "empty space". The problem is that TreeViewer does not automatically clear the selection if you click into empty space. Is there any clean way how to achieve this?
My current approach would be to simply hook up a MouseListener to the tree with the following mouseDown method:
#Override
public void mouseDown(MouseEvent e) {
TreeItem item = treeViewer.getTree().getItem(new Point(e.x, e.y));
if (item == null) {
treeViewer.getTree().deselectAll();
}
}
This seems to work quite well. What do you think of this?
Ok, I found a dirty workaround. So if you really want to do it, here is a possible solution:
final Tree tree = viewer.getTree();
final Menu menu = new Menu(tree);
tree.setMenu(menu);
menu.addMenuListener(new MenuAdapter()
{
#Override
public void menuShown(MenuEvent e)
{
Point point = tree.toControl(Display.getDefault().getCursorLocation());
boolean found = false;
for (TreeItem item : tree.getItems())
{
for (int i = 0; i < tree.getColumnCount(); i++)
if (item.getBounds(i).contains(point))
found = true;
}
System.out.println(found);
}
});
How to add popup menu to your SWT/JFace TreeViewer
Hi, in your applications main class (that extends ApplicationWindow) in protected Control createContents(Composite parent) method you should add code like this:
//Author: Darius Kucinskas (c) 2008-2009
//Email: d[dot]kucinskas[eta]gmail[dot]com
//Blog: http://blog-of-darius.blogspot.com/
//License: GPL
// Create the popup menu
MenuManager menuMgr = new MenuManager();
Menu menu = menuMgr.createContextMenu(mTreeViewer.getControl());
menuMgr.addMenuListener(new IMenuListener() {
#Override
public void menuAboutToShow(IMenuManager manager) {
if(mTreeViewer.getSelection().isEmpty()) {
return;
}
if(mTreeViewer.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection)mTreeViewer.getSelection();
DatabaseModelObject object = (DatabaseModelObject)selection.getFirstElement();
if (object.getType() == DATABASE_OBJECT_TYPE.TABLE){
manager.add(new ShowTableDataAction(SWTApp.this));
}
}
}
});
menuMgr.setRemoveAllWhenShown(true);
mTreeViewer.getControl().setMenu(menu);
DatabaseModelObject - is class from my problem domain (specific to my program). mTreeViewer - is object of TreeViewer class (JFace). Thanks, have a nice day!

Pass fields with enter key?

I'm looking for a way to pass fields with enter key in VerticalLayout or others. In vaadin book there an example with Shortcut and Handler listeners but I don't know how to implement that.
I'm trying this.
public class MyWindow extends Window implements Handler{
private Action action_enter; //pass fields with enter
private Action action_esc;
private TextField name, lastName;
public MyWindow(){
super("this window is opened");
VerticalLayout vLayout = new VerticalLayout();
setContent(vLayout);
center();
setModal(true);
setClosable(false);
setDraggable(false);
setResizable(false);
//actions
action_enter = new ShortcutAction("Enter key", ShortcutAction.KeyCode.ENTER, null);
action_esc = new ShortcutAction("Esc key", ShortcutAction.KeyCode.ESCAPE, null);
addActionHandler(this);
//fields
name = new TextField("Name");
lastName = new TextField("Last name");
name.focus();
vLayout.addComponent(name);
vLayout.addComponent(lastName);
}
#Override
public Action[] getActions(Object target, Object sender) {
return new Action[] { action_enter, action_esc };
}
#Override
public void handleAction(Action action, Object sender, Object target) {
/** close window with esc key */
if(action == action_esc){
close();
}
/** pass fields with enter key */
if(action == action_enter){
//here pass fields with enter key
}
}
}
any idea ?
try this way with ShortcutListener:
ShortcutListener skEnterListener = new ShortcutListener("Enter", ShortcutAction.KeyCode.ENTER, null){
#Override
public void handleAction(Object sender, Object target) {
if (target instanceof VerticalLayout) { // VerticalLayout or other
// sending fileds here
}
}
};
addShortcutListener(skEnterListener);
change focus of TextField using Enter instead Tab:
final TextField tf1 = new TextField("tf1");
tf1.setId("tf1");
final TextField tf2 = new TextField("tf2");
tf2.setId("tf2");
ShortcutListener skEnterListener = new ShortcutListener("Enter", ShortcutAction.KeyCode.ENTER, null){
#Override
public void handleAction(Object sender, Object target) {
if (target instanceof TextField) {
TextField field = (TextField) target;
if ("tf1".equals(field.getId())) {
tf2.focus();
}
if ("tf2".equals(field.getId())) {
tf1.focus();
}
}
}
};
addShortcutListener(skEnterListener);
There is no interface which does provide an accessor that would allow you finding out the currently focused component. Focus information can be acquired for some (but not all) field components through the com.vaadin.event.FieldEvents.FocusListener and com.vaadin.event.FieldEvents.BlurListener interfaces.
You could add for all possible fields a FocusListener and remember every time it's invoked, the current field in a variable. (Problem: not all fields provide a FocusListener.) Then when ENTER is pressed focus the next component according to the current focused field (remember the variable) that has to be focused (with the help of a simple List, LinkedList, Map, switch-case and so forth). To make it even better add a BlurListener as well to know when not to focus the next field.
Hope that helps.

Categories

Resources