display open nodes in a GWT Tree - gwt

I create a GWT Tree, and I would like it to be initially displayed with open nodes. Let's take the standard Tree example from GWT javadocs:
public class TreeExample implements EntryPoint {
public void onModuleLoad() {
// Create a tree with a few items in it.
TreeItem root = new TreeItem("root");
root.addItem("item0");
root.addItem("item1");
root.addItem("item2");
// Add a CheckBox to the tree
TreeItem item = new TreeItem(new CheckBox("item3"));
root.addItem(item);
Tree t = new Tree();
t.addItem(root);
// Add it to the root panel.
RootPanel.get().add(t);
}
}
I want it initially displayed as:
root
item0
item1
item2
item3
Now, I thought that it was as simple as setting the state of the TreeItem that I want to be opened by calling setState(true): javadoc for setState says "Sets whether this item's children are displayed". However, if I add for example
root.setState(true);
to the above example, I don't get the expected effect. Apparently nothing changes when I do root.setState(true); or root.setState(false);: the tree is always displayed with its nodes closed.
How do I get the desired behaviour?

The call to setState() depends on the sequence of the method calls to TreeItem and Tree (as stated here).
As a rule of thumb call setState(true) after adding all the items to the TreeItem and after adding the root item to the Tree.

Related

Using e3x property view with e4 Selection service from EMF Model

I built a small e4 RCP application containing both an "e4 xmi" tree view populated by emf generated model code (using ComposedAdapterFactory) and an "e3 properties view".
Tried following "dirksmetric tutorial" to display property view in application.e4xmi (shared elements) with an empty property view.
To get a tree's selected element displayed in my property sheet (IItemPropertySource), I did the following things :
On my e4 treeviewer side, I use the e4 selection service in #createComposite:
// Register the viewer as a selection provider (to be consumed by the property view...)
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
// set the selection to the service
selectionService.setSelection(
selection.size() == 1? selection.getFirstElement(): selection.toArray());
}
});
On the e3 "classical" property sheet side, I defined a couple of things :
I called IDE.registerAdapters in my ApplicationWorkbenchAdvisor#initialize.
I declared my property source adapter as follow in my plugin.xml :
extension point="org.eclipse.core.runtime.adapters">
factory adaptableType="org.eclipse.emf.ecore.EObject"
class="myappmodeler.properties.ModelPropertiesAdapter">
adapter type="org.eclipse.ui.views.properties.IPropertySource">
My ModelPropertiesAdapter#getAdapter returns a property source :
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType== IPropertySource.class && adaptableObject instanceof EObject){
emfGlobalFactory = new ComposedAdapterFactory();
emfGlobalFactory.addAdapterFactory(new RepositorystructureItemProviderAdapterFactory());
emfGlobalFactory.addAdapterFactory(new ApplicationItemProviderAdapterFactory());
emfGlobalFactory.addAdapterFactory(new ServiceItemProviderAdapterFactory());
return new AdapterFactoryContentProvider(emfGlobalFactory).getPropertySource(adaptableObject);
}
return null;
}
My problem is this adapter is not even executed.
Currently using Eclipse neon (it was recently updated to synchronise E3 and E4 selection service)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=403930
There are different ways to fix this problem, but for my case, these are the steps
I took to these steps to solve mine
Take control of the base model - create an interface which extends EObject
Create custom property provider, source and descriptor - extends org.eclipse.emf.edit.ui.provider.*
at runtime we need IItemPropertySource
Create a content provider class (extends AdapterFactoryContentProvider) and override createPropertySource with custom property source
Note; I also developed a table layout which means implementing custom ItemProvider (implement ITableItemLabelProvider) for individual elements in the model
Worked perfectly with ESelectionService
Hope these notes helps somebody

Custom Perspective Switcher Toolbar: How can I dynamically update it?

I'm trying to implement a custom perspective switcher toolbar to replace eclipse's built-in one. I couldn't get the toolbar to display, and it was shown to me that due to a bug with the dynamic element in a menu contribution, I have to use a control element instead, as described in the workaround to the dynamic bug.
I have a toolbar displaying following that approach, but I cannot figure out how to update it dynamically. The workaround instruction is to call ContributionItem#fill(CoolBar, int) from my WorkbenchControlContributionItem's update method instead of doing the fill in the createControl method.
I don't know who is supposed to call update, but it never gets invoked no matter what I do. I have a perspective listener which knows when to update the toolbar, so from that listener's callback I call fill(CoolBar, int). But I wasn't sure how to get the CoolBar to pass to that method, so I created one on the current shell.
The end result of all this is that the toolbar displays the correct number of items initially, but when I need to add an item, it has no effect. I call fill(CoolBar, int) and it adds the new item to the toolbar, but everything I've tried to make the CoolBar and ToolBarupdate does not work. When I re-launch the app, the toolbar has the added item.
I'm sure I'm doing this wrong, but I can't figure out the right way. Here's an elided representation of my code (omitting methods, layout code, etc not related to the update problem).
public class PerspectiveSwitcherToolbar extends WorkbenchWindowControlContribution implements IPerspectiveListener {
...
#Override
protected Control createControl(Composite parent) {
this.parent = parent;
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.getWorkbenchWindow().addPerspectiveListener(this);
toolBarManager = (ToolBarManager)parent.getParent().getData();
fTopControl = new Composite(parent, SWT.BORDER);
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
return fTopControl;
}
#Override
public void fill(CoolBar coolbar, int index) {
IPerspectiveDescriptor[] openPerspectives = page.getOpenPerspectives();
String activePerspective = getPerspectiveId();
ToolBar toolbar = new ToolBar(fTopControl, SWT.NONE);
for(IPerspectiveDescriptor descriptor : openPerspectives) {
ToolItem item = new ToolItem(toolbar, SWT.RADIO);
//overkill here, trying to find some way to upate the toolbar
toolbar.update();
parent.update();
parent.layout(true);
parent.getParent().update();
parent.getParent().layout(true);
coolbar.layout(true);
}
//PerspectiveListener callback
#Override
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
if (page.getWorkbenchWindow() instanceof WorkbenchWindow){
//this non-API call doesn't help either
((WorkbenchWindow) page.getWorkbenchWindow()).updateActionBars();
}
}
...
}

GWT Tree Widget getElement() method not working as expected

I have a GWT UI Panel Created with Elements , and I need to add a GWT tree to the UI
I did
TreeItem department = new TreeItem("Packages");
TreeItem salesDepartment = new TreeItem("Package1");
TreeItem marketingDepartment = new TreeItem("Package2");
TreeItem manufacturingDepartment = new TreeItem("Package3");
TreeItem employee1 = new TreeItem("Flight");
TreeItem employee2 = new TreeItem("Cruilse");
TreeItem employee3 = new TreeItem("Flight");
salesDepartment.addItem(employee1);
salesDepartment.addItem(employee2);
salesDepartment.addItem(employee3);
TreeItem employee4 = new TreeItem("Cruise");
TreeItem employee5 = new TreeItem("Hotel");
marketingDepartment.addItem(employee4);
marketingDepartment.addItem(employee5);
TreeItem employee6 = new TreeItem("Cruise");
TreeItem employee7 = new TreeItem("Hotel");
manufacturingDepartment.addItem(employee6);
manufacturingDepartment.addItem(employee7);
department.addItem(salesDepartment);
department.addItem(marketingDepartment);
department.addItem(manufacturingDepartment);
Tree tree = new Tree();
tree.addItem(department);
// consider that treeDiv is already added
private Element treeDiv = DOM.createDiv();
DOM.appendChild( treeDiv , tree.getElement() );
when I added the tree widget as a Element it shows only text inputs no expand buttons or anything,its not working as a tree just texts.
please tell me is there any fix for this.
// consider that treeDiv is already added
private Element treeDiv = DOM.createDiv();
DOM.appendChild( treeDiv , tree.getElement() );
when I added the tree widget as a Element it shows only text inputs no expand buttons or anything,its not working as a tree just texts. please tell me is there any fix for this.
I'm not sure what that comment means, given that the tree was just created so could not have already been added, but even if that was a concern, I'm not sure why we must use the tree's element directly. If there are more pieces to this question you are skipping, please add them. For example: what is the treeDiv ever added to?
As a direct answer to the question, Don't Do This. Instead, use the widget's own add method, add widgets to other widgets, rather than directly manipulating the dom elements.
For example, if you are adding the tree to the <body> directly, this would look like this:
RootPanel.get().add(tree);
Or, if you already have a parent widget (called here panel), just add it directly to that parent:
panel.add(tree);
The reason for this is that the Widget wiring has its own event wiring that needs to be set up - to avoid memory leaks in the crappier browsers, it is important to make sure that event wiring is removed when the widgets are taken off the page. See http://www.gwtproject.org/articles/dom_events_memory_leaks_and_you.html for more details, but the short version is that after actually adding a widget's dom element to the greater dom, the widget's onAttach must be called, and any children widgets must also have their onAttach called as well. This is automatically done when adding a widget to another widget - you should stick to that API.

Dynamic treegrid context menus

Is there a way using the treegrid in gwt-ext to have different context menus for different rows?
For example I would like my leaf rows to have different menu options then my non-leaf rows, or at least be able to disable menu options when they aren't revelent to the row that was right clicked.
I created a solution for this problem:
When you create the leafs, you should set the property "type" to "leaf", and the others to "non-leaf".
BaseTreeModel base = new BaseTreeModel();
base.set("type", "leaf");
So, in the selectionChanged event of your tree, you put the verification, and create the menu only for your leafs.
*treePanel.getSelectionModel().addListener(Events.SelectionChange, new SelectionChangedListener<ModelData>() {
#Override
public void selectionChanged(SelectionChangedEvent<ModelData> data) {
BaseTreeModel selected = (BaseTreeModel) data.getSelectedItem();
if ("leaf".equals(selected .get("type").toString())) {
// create the Menu and set it to contextMenu of your tree
} else {
treePanel.setContextMenu(null);
}*
André.

How to handle property sheet from customized editor in eclipse plugin development?

I have to bind my editor widget objects in property sheet.So that i can the property of my widget from property view.
Please help me on this, if possible provide me some code snippets.
You have a good example in the Getting started with Properties
Using the Properties view is simple enough.
Since it shows properties for the selected object, the first step to using it is to make sure that the workbench selection service knows about the object selected in your view. There’s an entire Eclipse Corner article written on the subject of the selection service
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
getSite().setSelectionProvider(viewer);
viewer.setInput(getViewSite());
}
Once you have your view contributing to the workbench selection, you need to make sure that the objects that your view is selecting contribute properties
(extract)
public class Person implements IPropertySource {
private String name;
private Object street;
private Object city;
public Person(String name) {
this.name = name;
this.street = "";
this.city = "";
}
public Object getEditableValue() {
return this;
}
public IPropertyDescriptor[] getPropertyDescriptors() {
return new IPropertyDescriptor[] {
new TextPropertyDescriptor("name", "Name"),
new TextPropertyDescriptor("street", "Street"),
new TextPropertyDescriptor("city", "City")
};
}
I indicated earlier that this solution is “not necessarily [the] most correct”. This is because, for this to work, my domain object needs to know about the very view-centric (and Eclipse-centric) notion of being a property source; in short, there is a tight-coupling between the model and view and this not a good thing™.
Using adapter is a better approach, as described in this article:
Person should implement IAdaptable.
See also this recent article on how to create a custom property view
how to hack the Properties View to listen only to a specific view.
The isImportant() method is the one which decides whether to create an IPage for the specific IWorkbenchPart or not.
The idea is to override that method and return false for all the workbenchPart that we are not interested in. Lets create the view first:
<view
class="com.eclipse_tips.views.CustomPropertiesView"
icon="icons/sample.gif"
id="com.eclipse-tips.views.customePropertiesView"
name="My Properties View">
</view>
The CustomPropertiesView should extend PropertySheet and override the isImportant():
public class CustomPropertiesView extends PropertySheet {
#Override
protected boolean isImportant(IWorkbenchPart part) {
if (part.getSite().getId().equals(IPageLayout.ID_PROJECT_EXPLORER))
return true;
return false;
}
}
In this case, I'm making the view only to respond to Project Explorer and ignore other views
According to this thread, the same principle should be valid for an Editor instead of a View.
The property sheet listens to the workbench page selection provider.
The selection provider depends on what viewer/editor is active.
Each editor/viewer provides their own selection provider to use when that editor/viewer is active.
This way the property sheet doesn't care who is active, it just listens to the selection provider.
That way depending upon the view, a different set of properties are displayed.
For example, the Navigator view provides IResource selections, so the property sheet then displays IResource properties when the Navigator is active.
The Workbench Selection mechanism is illustrated in this article
The ISelectionListener is a simple interface with just one method.
A typical implementation looks like this:
private ISelectionListener mylistener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
if (sourcepart != MyView.this && // 1
selection instanceof IStructuredSelection) { // 2
doSomething(((IStructuredSelection) selection).toList()); // 3
}
}
};
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part (1).
Check whether we can handle this kind of selection (2).
Get the selected content from the selection and process it (3).