How to edit a tree node in SWT - java

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 .

Related

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

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.

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;
}

formatting TreeItem Text colour?

I am working on Eclipse plugin. Here i created a separate view and now i want to format the color of tree node.
These are code present in createpartcontrol method.
ScrolledComposite sc = new ScrolledComposite(parent, SWT.V_SCROLL );
Composite composite1 = new Composite(sc, SWT.NONE);
Composite composite_1 = creatingcomposite(composite1);
Tree tree = new Tree(composite_1, SWT.FULL_SELECTION );
TreeItem item = new TreeItem(tree, SWT.NONE);
here i want to set some colour like blue.
item.setText("This is sparta");
Now here i want some different colour like yellow on subsubitem text.
TreeItem subsubItem = new TreeItem(subItem, SWT.NONE);
subsubItem.setText(new String[] { "Function Name: "+ errorPreTest11.description.get(j).function });
For doing this i tried to set SWT.COLOR_BLUE but it's not working.
Use
item.setForeground(tree.getDisplay().getSystemColor(SWT.COLOR_BLUE));
You can also create your own colors but if you do this you must dispose of them when you are done.
I suggest you using the TreeViewer. In this case you would have a functionality to set a LabelProvier on your viewer. Label provider has a subclass called StyledCellLabelProvider, which you can successfully extend to provide styling of your labels like this: (Please also see a TextStyle class for more formating options).
public class MyStyledLabelProvider extends StyledCellLabelProvider {
private Styler defaultStyler;
public MyStyledLabelProvider () {
defaultStyler = new Styler() {
#Override
public void applyStyles(TextStyle textStyle) {
textStyle.strikeout = true;
}
};
}
#Override
public void update(ViewerCell cell) {
Object element = cell.getElement();
StyledString styledString = getStyledString(element);
cell.setText(styledString.toString());
cell.setStyleRanges(styledString.getStyleRanges());
super.update(cell);
}
#SuppressWarnings("unchecked")
private StyledString getStyledString(Object element) {
return new StyledString("Cell string", defaultStyler);
}
}

Enter Key Listener for Date is not working in linux flavours

Here is my full coding.I have Two class firstone MyDateTime and Second one is Employee.
i have included currently working coding of mine.For the EmployeePart class,AbstractEditorPart is our own parent class Which is extended
public class MyDateTime extends DateTime{
public DateTime(Composite parent, int style)
{
super(parent, style);
}
public Date getValue()
{
Date date = new Date(getYear(), getMonth(), getDay());
return date;
}
}
public Class EmployeePart extends AbstractEditorPart(
private MyDateTime currentDate;
public void createBody(Composite parent){
currentDate=Util.createDateChooserCombo(parent, toolkit, "Date:", 2);
}
public void save(Employee input){
return null;
}
}
}
Turns out to be a little more complicated than I first thought.
One solution is to define a TabList for the Composite that contains your Widgets.
This way you can first define in which order you want them to be traversed.
Then add a Listener to each of the Widgets you want to traverse. This Listener will determine the next item in the TabList and force the focus on this item when either Tab or Enter is pressed.
Here is some example code:
public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Composite content = new Composite(shell, SWT.NONE);
content.setLayout(new FillLayout());
Text first = new Text(content, SWT.BORDER);
Text second = new Text(content, SWT.BORDER);
content.setTabList(new Control[] {first, second});
Listener enterListener = new Listener()
{
#Override
public void handleEvent(Event event)
{
/* Is it a traverse via Tab or Enter? */
if(event.keyCode == SWT.CR || event.keyCode == SWT.TRAVERSE_RETURN || event.keyCode == SWT.TRAVERSE_TAB_NEXT)
{
/* Get source of event */
Widget source = event.widget;
/* Get traverse order of content composite */
Control[] tabList = content.getTabList();
/* Try to find current position in the tab list */
for(int i = 0; i < tabList.length; i++)
{
if(source.equals(tabList[i]))
{
/* Get the next item in the tab list */
Control nextControl = tabList[(i + 1) % tabList.length];
/* And force the focus on this item */
nextControl.setFocus();
nextControl.forceFocus();
return;
}
}
}
}
};
first.addListener(SWT.KeyUp, enterListener);
second.addListener(SWT.KeyUp, enterListener);
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}

Java SWT - listen if new children are added to the Composite?

I have a Composite.
In SWT the children are added, by children, no by parents:
Composite parent = new Composite(shell, SWT.none);
Composite child = new Composite(parent, SWT.none);
That means, that inside of the parent I do not know, in which way and when the children are added to their parents.
QUESTION:
Inside of the parent I need to know, when new children are added to the parent.
Is there any way to register an onChildAddListener or any add() method to override?
The only way to add custom MyComposite and create custom ChildEvent as well as ChildEventListener interface. MyComposite is capable of registering listeners of ChildEvent and fire this event when a child Composite is created.
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.TypedEvent;
import org.eclipse.swt.internal.SWTEventListener;
import org.eclipse.swt.widgets.*;
/*
* This example demonstrates the minimum amount of code required
* to open an SWT Shell and process the events.
*/
public class HelloWorld1 {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new HelloWorld1 ().open (display);
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
public Shell open (Display display) {
Shell shell = new Shell (display);
MyComposite parent = new MyComposite(shell, SWT.NONE);
parent.addChildEventListener(new ChildEventListener() {
#Override
public void add(ChildEvent e) {
System.out.println("Child added.");
}
});
MyComposite child = new MyComposite(parent, SWT.NONE);
// shell.open ();
return shell;
}
}
class MyComposite extends Composite {
ChildEventListener[] childEventListeners = new ChildEventListener[0];
public MyComposite(Composite parent, int style) {
super(parent, style);
if (parent instanceof MyComposite){
((MyComposite)parent).fireChildEvent(new ChildEvent(this));
}
}
public void addChildEventListener (ChildEventListener listener) {
checkWidget();
if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
ChildEventListener[] newChildEventListeners = new ChildEventListener[childEventListeners.length + 1];
System.arraycopy(childEventListeners, 0, newChildEventListeners, 0, childEventListeners.length);
childEventListeners = newChildEventListeners;
childEventListeners[childEventListeners.length - 1] = listener;
}
public void removeChildEventListener (ChildEventListener listener) {
if (childEventListeners.length == 0) return;
int index = -1;
for (int i = 0; i < childEventListeners.length; i++) {
if (listener == childEventListeners[i]){
index = i;
break;
}
}
if (index == -1) return;
if (childEventListeners.length == 1) {
childEventListeners = new ChildEventListener[0];
return;
}
ChildEventListener[] newChildEventListeners = new ChildEventListener[childEventListeners.length - 1];
System.arraycopy (childEventListeners, 0, newChildEventListeners, 0, index);
System.arraycopy (childEventListeners, index + 1, newChildEventListeners, index, childEventListeners.length - index - 1);
childEventListeners = newChildEventListeners;
}
public void fireChildEvent(ChildEvent event){
for (int i = 0; i < childEventListeners.length; i++) {
childEventListeners[i].add (event);
}
}
}
interface ChildEventListener extends SWTEventListener {
public void add(ChildEvent e);
}
class ChildEvent extends TypedEvent {
public ChildEvent(Widget widget) {
super(widget);
// TODO Auto-generated constructor stub
}
}
The purpose for which I wanted to know about child addition - is for layoing out the children
(adding LayoutData e.g. GridData) when the child is added to a child, which is layed out with a particular Layout (e.g. GridLayout).
Since it is not possible to layout children on addition - check their layout on every widget resize:
/*
* To make the forms fill the group - laying out the children is necessary.
* Unfortunately it is not possible to listen for children addition, in order to layout the children addition automatically.
* This means that the user will have to remember to layout the children, which is a nogo.
*
* Solution:
* istead of adding right layout on child addition - check if there are new children every time the widget is resized.
* if a widget without layoutData is found (new child not layed out) - add a layout
*/
this.addControlListener(new ControlAdapter() {
#Override
public void controlResized(ControlEvent e) {
layoutChildren();
}
});
}
private void layoutChildren(){
for(Control child:getChildren()){
if(child.getLayoutData() == null){
child.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}
}
}
public void addToGroup(Composite child){
child.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}

Categories

Resources