java gwt celltree - java

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

Related

Java TableViewer - change cell image on selection

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

Using additional Saveables in Eclipse AbstractTextEditor

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.

GWT Editors - select an item from a list using a valuelistbox

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?

ArrayList displayed incorrectly

I'm testing to display Array List into JavaFX accordion:
public class Navigation {
// Object for storing conenctions
public static List<dataObj> list = new ArrayList<>();
private ObservableList<dataObj> data;
public class dataObj {
private String conenctionname;
public dataObj(String conenctionname) {
this.conenctionname = conenctionname;
}
public String getConenctionname() {
return conenctionname;
}
public void setConenctionname(String conenctionname) {
this.conenctionname = conenctionname;
}
}
public void initNavigation(Stage primaryStage, Group root, Scene scene) {
VBox stackedTitledPanes = createStackedTitledPanes();
ScrollPane scroll = makeScrollable(stackedTitledPanes);
scroll.getStyleClass().add("stacked-titled-panes-scroll-pane");
scroll.setPrefSize(395, 580);
scroll.setLayoutX(5);
scroll.setLayoutY(32);
root.getChildren().add(scroll);
}
private ScrollPane makeScrollable(final VBox node) {
final ScrollPane scroll = new ScrollPane();
scroll.setContent(node);
scroll.viewportBoundsProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds) {
node.setPrefWidth(bounds.getWidth());
}
});
return scroll;
}
/////////////////////////////////////////////////////////////////////////////////////
// Generate accordition with Connections, Tables and Description
private VBox createStackedTitledPanes() {
VBox stackedTitledPanes = new VBox();
stackedTitledPanes.getChildren().setAll(
createConnectionsList("Connections"));
((TitledPane) stackedTitledPanes.getChildren().get(0)).setExpanded(true);
stackedTitledPanes.getStyleClass().add("stacked-titled-panes");
return stackedTitledPanes;
}
//////////////////////////////////////////////////////////////////////////////
// Generate list with Connections
public TitledPane createConnectionsList(String title) {
initObject();
data = FXCollections.observableArrayList(list);
ListView<dataObj> lv = new ListView<>(data);
lv.setCellFactory(new Callback<ListView<dataObj>, ListCell<dataObj>>() {
#Override
public ListCell<dataObj> call(ListView<dataObj> p) {
return new ConnectionsCellFactory();
}
});
AnchorPane content = new AnchorPane();
content.getChildren().add(lv);
// add to TitelPane
TitledPane pane = new TitledPane(title, content);
return pane;
}
static class ConnectionsCellFactory extends ListCell<dataObj> {
#Override
public void updateItem(dataObj item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
for (int i = 0; i < list.size(); i++) {
setText(list.get(i).getConenctionname());
}
}
}
}
// Insert Some test data
public void initObject() {
dataObj test1 = new dataObj("test data 1");
dataObj test2 = new dataObj("test data 2");
list.add(test1);
list.add(test2);
}
}
But for some reason I cannot get proper list of Objects from the Array list and display them. I get this result:
The proper result should be test data 1 and test data 2. How I can fix this?
The problem is in the ConnectionsCellFactory, the method updateItem is called for every item in List. So in you code, for every cell you are setting the text for every item in the list
you should try:
static class ConnectionsCellFactory extends ListCell<dataObj> {
#Override
public void updateItem(dataObj item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.getConenctionname());
}
}
}

Get the parent of an IStructuredSelection (eclipse-rcp)?

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

Categories