I have a TreeViewer in a view and need to get the parent (if it exists) of an item selected. Nothing seems to work and google yields no answers..
mBacktestTree.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
IWorkbenchPage page = getSite().getPage();
TreeViewer tree = (TreeViewer) event.getSource();
Object selectObject = ((IStructuredSelection) tree.getSelection()).getFirstElement();
// now how can I get the parent of selectObject?
You can get the parent from an ITreeSelection. E.g.
public class DirectoryView extends ViewPart
{
public void createPartControl(Composite parent)
{
TreeViewer treeViewer = new TreeViewer(parent);
treeViewer.setContentProvider(new DirectoryProvider());
treeViewer.setInput(new File(System.getProperty("user.home")));
treeViewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
ITreeSelection selection = ((ITreeSelection)event.getSelection());
System.out.println(selection.getPaths()[0].getParentPath().getLastSegment());
}
});
}
class DirectoryProvider implements ITreeContentProvider
{
public Object[] getChildren(Object parentElement)
{
File[] folders = ((File) parentElement).listFiles();
return folders == null ? new File[0] : folders;
}
public Object getParent(Object element)
{
return ((File) element).getParent();
}
public boolean hasChildren(Object element)
{
return getChildren(element).length >0;
}
public Object[] getElements(Object inputElement)
{
return getChildren(inputElement);
}
public void dispose()
{
// ignore
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
{
// ignore
}
}
public void setFocus()
{
// ignore
}
}
You can also obtain the parent from your tree content provider:
mBacktestTree.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
IWorkbenchPage page = getSite().getPage();
TreeViewer tree = (TreeViewer) event.getSource();
Object selectObject = ((IStructuredSelection)tree.getSelection()).getFirstElement();
ITreeContentProvider tcp =tree.getContentProvider();
Object parent = tcp.getParent(selectObject);
Related
I have followed Vogella's tutorial on Table Viewer and using the StyledCellLabelProvider presented there. It creates a CHECKED or UNCHECKED icon on the third column
col = createTableViewerColumn(titles[3], bounds[3], 3);
col.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return null;
}
#Override
public Image getImage(Object element) {
if (((Person) element).isMarried()) {
return CHECKED;
} else {
return UNCHECKED;
}
}
});
col.setEditingSupport(new MarriedEditingSupport(viewer));
The column images get painted accordingly when the table is created but how can I change the icon when the user clicks a cell ? (I want to simulate a check box)
You can use an EditingSupport class based on CheckboxCellEditor for this:
class MarriedEditingSupport extends EditingSupport
{
private final CheckboxCellEditor _editor;
MarriedEditingSupport(TableViewer viewer)
{
super(viewer);
_editor = new CheckboxCellEditor(viewer.getTable());
}
#Override
protected CellEditor getCellEditor(Object element)
{
return _editor;
}
#Override
protected boolean canEdit(Object element)
{
return true;
}
#Override
protected Object getValue(Object element)
{
return Boolean.valueOf(((Person)element).isMarried());
}
#Override
protected void setValue(Object element, Object value)
{
((Person)element).setMarried(((Boolean)value).booleanValue());
getViewer().update(element, null);
}
}
I would like to modify the right click context menu for some some SWT Text boxes.
I would like to still have some of the default options like Copy, Cut, Paste, but would also like to have a custom action 'Generate Random' to fill the text box with a UUID.
How can I add such a menu to the control?
here's what I came up with to add some of the standard functions (cut, copy, paste, select all) as well as a custom action (generate UUID)
public static void addContextMenuWithUUID(final Text control)
{
Menu menu = new Menu(control);
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText("Cut");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.cut();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Copy");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.copy();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Paste");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.paste();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Select All");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.selectAll();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Generate UUID");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.setText(UUID.randomUUID().toString());
}
});
control.setMenu(menu);
}
When I had to do something similar a while ago, this is what I did,
I adopted the TextActionHandler class provided by eclipse and modified the code to suit my needs.
public final class TextActionHandler {
enum TextAction {
CUT (WorkbenchMessages.Workbench_cut, IWorkbenchCommandConstants.EDIT_CUT),
COPY (WorkbenchMessages.Workbench_copy, IWorkbenchCommandConstants.EDIT_COPY),
PASTE (WorkbenchMessages.Workbench_paste, IWorkbenchCommandConstants.EDIT_PASTE),
DELETE (WorkbenchMessages.Workbench_delete, null),
SELECT_ALL(WorkbenchMessages.Workbench_selectAll, WorkbenchCommandConstants.EDIT_SELECT_ALL);
private String text;
private String commandId;
private TextAction(String text, String commandId ) {
this.text = text;
this.commandId = commandId;
}
public String getCommandId() {
return commandId;
}
public String getText() {
return text;
}
}
public TextActionHandler(Text text) {
addText(text);
}
public TextActionHandler() {
super();
}
public void addText(Text textControl) {
if (textControl == null) {
return;
}
textControl.addDisposeListener(new DisposeListener() {
#Override
public void widgetDisposed(DisposeEvent e) {
removeText(activeTextControl);
}
});
textControl.addListener(SWT.Activate, textControlListener);
textControl.addListener(SWT.Deactivate, textControlListener);
textControl.addKeyListener(keyAdapter);
textControl.addMouseListener(mouseAdapter);
activeTextControl = textControl;
updateActionsEnableState();
}
public void hookContextMenu() {
final MenuManager menuMgr = new MenuManager("#PMPopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
addContextMenuOptions(menuMgr);
}
});
Menu menu = menuMgr.createContextMenu(activeTextControl);
activeTextControl.setMenu(menu);
}
private void addContextMenuOptions(MenuManager manager) {
manager.removeAll();
manager.add(textCutAction);
manager.add(textCopyAction);
manager.add(textPasteAction);
manager.add(textDeleteAction);
manager.add(new Separator());
manager.add(textSelectAllAction);
// add your own action handlers here
}
...
// example.
private final class CutActionHandler extends Action {
private CutActionHandler() {
setProperties(this, TextAction.CUT);
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.cut();
updateActionsEnableState();
}
}
#Override
public boolean isEnabled() {
return activeTextControl != null && !activeTextControl.isDisposed()
&& activeTextControl.getEditable()
&& activeTextControl.getSelectionCount() > 0;
}
public void updateEnabledState() {
setEnabled(isEnabled());
}
}
private void setProperties(Action action, TextAction actionEnum){
action.setText(actionEnum.getText());
action.setActionDefinitionId(actionEnum.getCommandId());
action.setImageDescriptor(getImageDescriptor(actionEnum));
action.setDisabledImageDescriptor(getDisabledImageDescriptor(actionEnum));
}
}
Likewise, you can have your own ActionHandlers added. e.g, RandomGeneratorHandler.
To hook this to your textboxes, do
Text text = new Text(parent, SWT.NONE);
...
TextActionHandler handler = new TextActionHandler();
handler.addText(text);
handler.hookContextMenu();
Note - I have not provided the complete class here, for other actions like copy, paste, delete and select all etc, you will have to do something similar as Cut. I have used the same code defined in the TextActionHandler class.
I have a textual editor that extends AbstractTextEditor and I also have an Outline that needs to be saved when its content is modified by the user. I am currently using a Saveable which is added to the editor.
If the editor was marked as 'dirty' and it is saved, the Saveableis saved as well. However, if the Saveable's state changes to 'dirty', the * next to the file name does not appear. The save button in the top menu bar does show, but when I click it, nothing happens.
This is my implementation:
public class MyTextEditor extends AbstractTextEditor {
...
public void setOutlineSaveable(Saveable saveable) {
this.outlineSaveable = saveable;
ISaveablesLifecycleListener lifecycleListener = (ISaveablesLifecycleListener)getSite().getService(ISaveablesLifecycleListener.class);
lifecycleListener.handleLifecycleEvent( new SaveablesLifecycleEvent(this, SaveablesLifecycleEvent.POST_OPEN, new Saveable[] {saveable}, false));
}
#Override
public Saveable[] getSaveables() {
if(outlineSaveable != null) {
// copy Saveables from super.getSaveables() to a new array
Saveable[] superSaveables = super.getSaveables();
Saveable[] res = new Saveable[superSaveables.length + 1];
int i = 0;
for(; i < superSaveables.length; i++) {
res[i] = superSaveables[i];
}
res[i] = outlineSaveable;
return res;
}
else
return super.getSaveables();
}
public void saveableDirty() {
firePropertyChange(PROP_DIRTY);
}
}
My ContentOutlinePage:
public class GraphicalOutlinePage extends ContentOutlinePage {
...
private GraphicalOutlineSaveable saveable;
public Saveable getSaveable() {
return saveable;
}
class GraphicalOutlineSaveable extends Saveable {
private boolean dirty = false;
private IEditorPart editor;
public GraphicalOutlineSaveable(IEditorPart editor) {
this.editor = editor;
}
#Override
public void doSave(IProgressMonitor monitor) throws CoreException {
viewer.doSave(monitor);
dirty = false;
}
#Override
public boolean equals(Object obj) {
System.err.println("GraphicalOutline.GraphicalOutlineSaveable.equals");
return obj instanceof GraphicalOutlineSaveable && ((Saveable)obj).getName() == getName();
}
#Override
public ImageDescriptor getImageDescriptor() {
return editor.getEditorInput().getImageDescriptor();
}
#Override
public String getName() {
return "Graphical Outline: " + editor.getEditorInput().getName();
}
#Override
public String getToolTipText() {
return "";
}
#Override
public boolean isDirty() {
System.err.println("GraphicalOutlinePage.GraphicalOutlineSaveable.isDirty: " + dirty);
return dirty;
}
public void setDirty() {
System.err.println("GraphicalOutlinePage.GraphicalOutlineSaveable.setDirty");
dirty = true;
// notify text editor about property change
if(editor instanceof AbstractTextEditor) {
((MyTextEditor)editor).saveableDirty();
}
}
#Override
public int hashCode() {
return viewer.hashCode();
}
}
}
vieweris a GraphicalViewerdisplayed in the ContentOutlinePage.
Somewhere in another class, I then call:
textEditor.setSaveable(grOutlinePage.getSaveable());
You may need to override the main editor isDirty() method and test each of the Saveable objects dirty flags.
It seems that the handling of multiple Saveables is not done as cleanly is it might have been.
I have a ValueAwareEditor that contains a couple of sub editors:
Essentially, an OfferDto is composed of a TariffDto and a Commission. The Commission can be one of 4 sub-types, but there is only ever one. Usually this list of possible commissions inside the TariffDto will only contain one element, but it can sometimes contain two.
public class OfferDto
{
private TariffDto tariff;
// selected from the list in the tariff
private Commission commission;
}
public class TariffDto extends EntityDto
{
// omitted for brevity...
protected List<Commission> commissions = new ArrayList<Commission>();
}
When commissions contains more than one item, I want to display a dropdown with the two optiions, and add allow the user to choose between them, each time resetting the commission in the OfferDto and the CommissionEditor.
The problem is that, when call commission.setValue() for the second time, the editor does not change. What should I be doing here?
public class OfferEditor extends Composite implements ValueAwareEditor<OfferDto>
{
#UiField
TariffRenderer tariff;
#Ignore
#UiField
HTMLPanel panel;
#UiField
CommissionEditor commission;
#Override
public void setValue(final OfferDto value)
{
panel.clear();
List<Commission> commissions = value.getTariff().getCommissions();
if(commissions.size() == 1)
{
value.setCommission(commissions.get(0));
}
else
{
// multiple commissions
ValueListBox<Commission> dropdown = new ValueListBox<Commission>(new Renderer<Commission>()
{
#Override
public String render(Commission object)
{
return object == null ? "" : object.getName();
}
#Override
public void render(Commission object, Appendable appendable) throws IOException
{
appendable.append(render(object));
}
});
dropdown.setValue(value.getCommission());
dropdown.setAcceptableValues(commissions);
dropdown.addValueChangeHandler(new ValueChangeHandler<Commission>()
{
#Override
public void onValueChange(ValueChangeEvent<Commission> event)
{
Commission selected = event.getValue();
// this works, but the CommissionEditor that was first rendered remains
value.setCommission(selected);
}
});
panel.add(dropdown);
}
}
}
Currently, I am rendering the list of commissions in a ValueListBox, then when the value changes I am pushing that value to the OfferDto. The Commission seems to get set right, but the subEditor does not change.
Any help greatly appreciated.
EDIT:
CommissionEditor shows the relevant sub-editor depending on the type.
public class CommissionEditor extends Composite implements Editor<Commission>
{
private static CommissionEditorUiBinder uiBinder = GWT.create(CommissionEditorUiBinder.class);
interface CommissionEditorUiBinder extends UiBinder<Widget, CommissionEditor>
{
}
#UiField
Panel subEditorPanel;
public CommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
#Ignore
final UnitRateCommissionEditor unitRateCommissionEditor = new UnitRateCommissionEditor();
#Path("")
final AbstractSubTypeEditor<Commission, UnitRateCommission, UnitRateCommissionEditor> unitRateCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, UnitRateCommission, UnitRateCommissionEditor>(
unitRateCommissionEditor)
{
#Override
public void setValue(final Commission value)
{
if(value instanceof UnitRateCommission)
{
setValue(value, value instanceof UnitRateCommission);
System.out.println("UnitRateCommission setValue");
subEditorPanel.clear();
subEditorPanel.add(unitRateCommissionEditor);
}
}
};
#Ignore
final StandingChargeCommissionEditor standingChargeCommissionEditor = new StandingChargeCommissionEditor();
#Path("")
final AbstractSubTypeEditor<Commission, StandingChargeCommission, StandingChargeCommissionEditor> standingChargeCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, StandingChargeCommission, StandingChargeCommissionEditor>(
standingChargeCommissionEditor)
{
#Override
public void setValue(final Commission value)
{
if(value instanceof StandingChargeCommission)
{
setValue(value, value instanceof StandingChargeCommission);
System.out.println("StandingChargeCommission setValue");
subEditorPanel.clear();
subEditorPanel.add(standingChargeCommissionEditor);
}
}
};
#Ignore
final PerMwhCommissionEditor perMwhCommissionEditor = new PerMwhCommissionEditor();
#Path("")
final AbstractSubTypeEditor<Commission, PerMwhCommission, PerMwhCommissionEditor> perMwhCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, PerMwhCommission, PerMwhCommissionEditor>(
perMwhCommissionEditor)
{
#Override
public void setValue(final Commission value)
{
if(value instanceof PerMwhCommission)
{
setValue(value, value instanceof PerMwhCommission);
System.out.println("PerMwhCommission setValue");
subEditorPanel.clear();
subEditorPanel.add(perMwhCommissionEditor);
}
}
};
}
Possible Solution:
I changed OfferEditor as so:
public class OfferEditor extends Composite implements Editor<OfferDto>
{
#UiField
TariffRenderer tariff;
#Path("tariff.commissions")
#UiField
CommissionsEditor commission;
}
New editor CommissionsEditor is a CompositeEditor. It needs to take List tariff.commissions and set the chosen Commission into offer.commission:
public class CommissionsEditor extends Composite implements CompositeEditor<List<Commission>, Commission, CommissionEditor>
{
private static CommissionsEditorUiBinder uiBinder = GWT.create(CommissionsEditorUiBinder.class);
interface CommissionsEditorUiBinder extends UiBinder<Widget, CommissionsEditor>
{
}
private EditorChain<Commission, CommissionEditor> chain;
#UiField
FlowPanel dropdownPanel, subEditorPanel;
#Ignore
CommissionEditor subEditor;
public CommissionsEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public void setValue(List<Commission> valueList)
{
// clear both panels
dropdownPanel.clear();
subEditorPanel.clear();
if(valueList.size() == 1)
{
// set the commission to the first in the list
Commission selected = valueList.get(0);
subEditor = new CommissionEditor();
subEditorPanel.add(subEditor);
chain.attach(selected, subEditor);
}
else if(valueList.size() > 1)
{
ValueListBox<Commission> dropdown = new ValueListBox<Commission>(new Renderer<Commission>()
{
#Override
public String render(Commission object)
{
return object == null ? "" : object.getName();
}
#Override
public void render(Commission object, Appendable appendable) throws IOException
{
appendable.append(render(object));
}
});
dropdownPanel.add(dropdown);
dropdown.setValue(valueList.get(0));
dropdown.setAcceptableValues(valueList);
dropdown.addValueChangeHandler(new ValueChangeHandler<Commission>()
{
#Override
public void onValueChange(ValueChangeEvent<Commission> event)
{
Commission selected = event.getValue();
subEditorPanel.clear();
CommissionEditor subEditor = new CommissionEditor();
subEditorPanel.add(subEditor);
chain.attach(selected, subEditor);
}
});
}
}
#Override
public void flush()
{
}
#Override
public void onPropertyChange(String... paths)
{
// TODO Auto-generated method stub
}
#Override
public void setDelegate(EditorDelegate<List<Commission>> delegate)
{
// TODO Auto-generated method stub
}
#Override
public CommissionEditor createEditorForTraversal()
{
return new CommissionEditor();
}
#Override
public String getPathElement(CommissionEditor subEditor)
{
return null;
}
#Override
public void setEditorChain(EditorChain<Commission, CommissionEditor> chain)
{
this.chain = chain;
}
}
When the CommissionsEditor renders the dropdown and onValueChange() is called, the new editor gets created, but the value for the commission never seems to get set.
For some reason the selected subEditor's value is not pushed into offer.setCommission(). I thought chain.attach() would perform this for me?
I implemented a CellTree structure in java gwt which opens it's childs when clicking on the little arrow in the cell contains. Is it possible to open the subtree also when just clicking on the cell itself and not explicitly on the arrow?
public class SomeCellTree extends Composite {
private SelectionModel selectionModel;
private CellTree cellTree;
private class SomeTreeViewModel implements TreeViewModel {
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
...
}
#Override
public boolean isLeaf(Object value) {
...
}
}
public SomeCellTree(...) {
this.selectionModel = new SingleSelectionModel();
this.selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
...
}
});
cellTree = new CellTree(new SomeTreeViewModel(),null,RESOURCES);
initWidget(cellTree);
}
}
You have to use recursion to find the node for the selected DTO and then you have to call setChildOpen to open the subtree. Something like this:
this.selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
T selectedObj = selectionModel.getSelectedObject();
TreeNode rootNode = cellTree.getRootTreeNode();
openTree(rootNode,T);
}
});
private void openTree(rootNode node,T object) {
for (int i = 0; i < node.getChildCount(); i++) {
if (!node.isChildLeaf(i)) {
find(node.setChildOpen(i, true));
if (node.getValue().equals(T))
return;
}
}
}