How to set icons in Tree Grid GXT(GWT) columns? - java

I am working on GWT app where I should change default icons in Tree Grid to icons from my own. In other cases, I can easily set icons but that is not the case when I have tree grid. When I have just default grid my code for set icon is like this:
Protected List<ColumnConfig> getColumns() {
List<ColumnConfig> columnConfigs = new ArrayList<ColumnConfig>();
ColumnConfig columnConfig = new ColumnConfig("status", MSGS.gridUserColumnHeaderStatus(), 50);
GridCellRenderer<GwtUser> setStatusIcon = new GridCellRenderer<GwtUser>() {
public String render(GwtUser gwtUser, String property, ColumnData config, int rowIndex, int colIndex, ListStore<GwtUser> deviceList, Grid<GwtUser> grid) {
KapuaIcon icon;
if (gwtUser.getStatusEnum() != null) {
switch (gwtUser.getStatusEnum()) {
case DISABLED:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.RED);
break;
case ENABLED:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREEN);
break;
default:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREY);
break;
}
} else {
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREY);
}
return icon.getInlineHTML();
}
};
columnConfig.setRenderer(setStatusIcon);
columnConfig.setAlignment(HorizontalAlignment.CENTER);
columnConfig.setSortable(false);
columnConfigs.add(columnConfig);
But when I apply that on my Tree Grid then just first item have an icon, and I can't expand the grid. This is my current code for that Tree Grid
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig column = new ColumnConfig("topicName", MSGS.topicInfoTableTopicHeader(), 150);
column.setRenderer(new TreeGridCellRenderer<GwtTopic>());
configs.add(column);
column = new ColumnConfig("timestamp", MSGS.topicInfoTableLastPostedHeader(), 150);
configs.add(column);
store = new TreeStore<GwtTopic>();
AsyncCallback<List<GwtTopic>> topicsCallback = new AsyncCallback<List<GwtTopic>>() {
#Override
public void onSuccess(List<GwtTopic> topics) {
store.add(topics, true);
topicInfoGrid.unmask();
}
#Override
public void onFailure(Throwable t) {
FailureHandler.handle(t);
topicInfoGrid.unmask();
}
};
dataService.findTopicsTree(currentSession.getSelectedAccount().getId(), topicsCallback);
topicInfoGrid = new TreeGrid<GwtTopic>(store, new ColumnModel(configs));
topicInfoGrid.setBorders(false);
topicInfoGrid.setStateful(false);
topicInfoGrid.setLoadMask(true);
topicInfoGrid.mask("Loading");
topicInfoGrid.setStripeRows(true);
topicInfoGrid.getView().setAutoFill(true);
topicInfoGrid.getView().setEmptyText(MSGS.topicInfoGridEmptyText());
topicInfoGrid.disableTextSelection(false);
How to change this code to be able to set my own icons?

You can use the setIconProvider method to change the icon of a leaf:
topicInfoGrid.setIconProvider(new IconProvider<GwtTopic>() {
#Override
public ImageResource getIcon(GwtTopic gwtTopic) {
GwtTopicType type = gwtTopic.getType();
if (type == GwtTopicType.Folder) {
if (topicInfoGrid.isExpanded(gwtTopic)) return new TopicInfoResources.Instance.iconFolderOpen();
else return TopicInfoResources.Instance.iconFolder();
}
return TopicInfoResources.Instance.user();
}
});
And this is your interface that extends ClientBundle:
public interface TopicInfoResources extends ClientBundle
{
public static final TopicInfoResources Instance = GWT.create(TopicInfoResources.class);
#Source("folder.png") ImageResource iconFolder();
#Source("folder-open.png") ImageResource iconFolderOpen();
#Source("user.png") ImageResource user();
}
Hope this helps!

Related

Spring boot app with Vaadin UI constantly refreshing screen

I have a boot app that I am adding some crud screens to. I decided to use Vaadin and it seems to work great until I deploy it to a multi-nodal production environment.
Once in the prod environment the screens constantly refresh for no apparent reason. For example there is a grid in one screen that when a row is clicked a dialog pops up that shows item details. but as soon as the dialog pops up the page refreshes numerous times.
This forum thread here https://vaadin.com/forum/thread/17586129/routerlayout-causing-page-refresh is an example of the same layout I am using and describes a very similar issue.
I have a base abstract class that extends VerticalLayout and all of the concrete classes extend this base abstract class. Each concrete class defines its own route and use a common layout class.
I have reached out on gitter, vaadin forum and opened a bug in github but no one from Vaadin want to respond to anything as far as I can tell.
Here are the versions of everything I am using:
Vaadin Flow version: 14
Java version: 12.0.1+12
OS version: Mac 10.14.5
Browser version: Fire Fox 70.0.1, Chrome 78.0.3904.97
Code snippets from my implementation:
Main View
#Slf4j
#RoutePrefix("v1/crud")
#Theme(value = Material.class, variant = Material.DARK)
public class MainView extends Div implements RouterLayout {
private H1 h1 = new H1("Vaadin Crud UI");
private HorizontalLayout header = new HorizontalLayout(h1);
private Div content = new Div();
private ApplicationContext context;
#Inject
public MainView(ApplicationContext context) {
this.context = context;
setSizeFull();
h1.setWidthFull();
content.setWidthFull();
header.setWidthFull();
header.setAlignItems(FlexComponent.Alignment.CENTER);
VerticalLayout navigationBar = new VerticalLayout();
navigationBar.setWidth("25%");
navigationBar.add(createNavigationButton("Home", VaadinIcon.HOME, ReportTab.class));
navigationBar.add(createNavigationButton("Batch Search", VaadinIcon.SEARCH, BatchSearchTab.class));
... a bunch more buttons
HorizontalLayout layout = new HorizontalLayout(navigationBar, content);
layout.setWidthFull();
VerticalLayout page = new VerticalLayout(header, layout);
page.setWidthFull();
add(page);
}
#Override
public void showRouterLayoutContent(HasElement hasElement) {
if (hasElement != null) {
Element newElement = hasElement.getElement();
if (newElement != null) {
content.removeAll();
content.getElement().appendChild(newElement);
}
}
}
private Button createNavigationButton(String caption, VaadinIcon icon, Class<? extends BaseEditor> editor) {
Button button = new Button(caption, icon.create());
button.addClickListener(event -> UI.getCurrent().navigate(editor));
button.addThemeVariants(ButtonVariant.MATERIAL_CONTAINED);
button.getStyle().set("background-color", "#00819D");
button.setWidthFull();
return button;
}
}
Base Component:
#Slf4j
#Data
#SpringComponent
#UIScope
public abstract class BaseEditor<P, B> extends VerticalLayout {
private final RememberMeService rememberMe;
private final P businessProcess;
protected Binder<B> binder;
protected Dialog editDialog = new Dialog();
protected Button save = new Button("Save", VaadinIcon.CHECK.create());
protected Button close = new Button("Close", VaadinIcon.EXIT.create());
protected Button delete = new Button("Delete", VaadinIcon.TRASH.create());
protected B bean;
private ChangeHandler changeHandler;
private boolean proceed = true;
public BaseEditor(P businessProcess, RememberMeService rememberMe) {
this.rememberMe = rememberMe;
this.businessProcess = businessProcess;
save.addClickListener(e -> save());
delete.addClickListener(e -> delete());
}
public abstract void delete();
public abstract void save();
protected abstract Component getContent();
protected void edit(B e) {
bean = e;
editDialog.open();
getBinder().setBean(e);
}
protected void initEditorPanel(Component... components) {
HorizontalLayout actions = new HorizontalLayout(save, close, delete);
VerticalLayout data = new VerticalLayout(components);
data.add(actions);
editDialog.removeAll();
editDialog.add(data);
getBinder().bindInstanceFields(this);
close.addClickListener(e -> editDialog.close());
}
public interface ChangeHandler {
void onChange();
}
void setChangeHandler(ChangeHandler h) {
changeHandler = h;
}
void errorDialog(String message) {
final Button close = new Button("Close", VaadinIcon.CLOSE.create());
H3 h3 = new H3(message);
final Dialog errorDialog = new Dialog(h3, close);
errorDialog.open();
close.addClickListener(e -> errorDialog.close());
}
BaseEditor filter(Predicate<B> predicate) {
Objects.requireNonNull(predicate);
proceed = predicate.test(bean);
return this;
}
void buttonConsumer(Consumer<B> consumer) {
if (!proceed) {
proceed = true;
return;
}
try {
consumer.accept(bean);
} catch (Exception e) {
errorDialog(e.getMessage());
} finally {
editDialog.close();
getChangeHandler().onChange();
}
}
void either(Consumer<B> whenTrue, Consumer<B> whenFalse) {
try {
if (proceed) {
whenTrue.accept(bean);
} else {
whenFalse.accept(bean);
}
} catch (Exception e) {
errorDialog(e.getMessage());
} finally {
proceed = true;
editDialog.close();
getChangeHandler().onChange();
}
}
}
Concrete Component:
#Slf4j
#Route(value = "search/batch", layout = MainView.class)
public class BatchSearchTab extends BaseEditor<BatchService, Batch> {
private TextField searchField1;
private TextField searchField2;
public BatchSearchTab(BatchService businessProcess, RememberMeService rememberMe) {
super(businessProcess, rememberMe);
binder = new Binder<>(Batch.class);
save.setIcon(VaadinIcon.REPLY.create());
save.setText("Replay");
delete.setIcon(VaadinIcon.CLOSE.create());
delete.setText("Cancel");
getContent();
}
#Override
public void delete() {
buttonConsumer(b -> getBusinessProcess().cancelBatch(b.getBatchId(), b.getUserAgent()));
}
#Override
public void save() {
filter(b -> b.isReplayable()).buttonConsumer(b -> getBusinessProcess().buildAndSendFile((getBean())));
}
#Override
public void edit(Batch batch) {
HorizontalLayout actions = new HorizontalLayout();
H2 h2 = new H2();
if (batch.isReplayable()) {
h2.setText("Would you like to replay the following.");
actions.add(save, delete, close);
} else {
h2.setText("This record is not eligible for replay.");
actions.add(close);
}
Label batchId = new Label("Correlation Id: " + batch.getBatchId());
Label txnCount = new Label("Transaction Count: " + batch.getTotalTxns());
Label txnAmount = new Label("Total: " + batch.getTotalBatchAmount());
VerticalLayout data = new VerticalLayout(h2, batchId, txnCount, txnAmount, actions);
data.add(actions);
editDialog.removeAll();
editDialog.add(data);
close.addClickListener(e -> editDialog.close());
editDialog.open();
getBinder().setBean(batch);
}
#Override
protected Component getContent() {
final H2 h2 = new H2("Locate Batches");
searchField1 = new TextField("Batch Code");
searchField2 = new TextField("User Agent");
searchField2.addKeyPressListener(Key.ENTER, e -> keyPressListener());
Button searchBtn = new Button("Search", VaadinIcon.SEARCH.create());
HorizontalLayout search = new HorizontalLayout(searchField1, searchField2);
searchBtn.addClickListener(e -> {
search(searchField1.getValue(), searchField2.getValue());
});
add(h2, search, searchBtn);
return this;
}
private void search(String code, String userAgent) {
log.info("Searching {} and {}", code, userAgent);
List<Batch> batches =
getBusinessProcess().getBatchesForUserAgent(code, userAgent, 60);
log.info("Found {} batches", batches.size());
if (batches.size() > 0) {
buildGrid(batches, "BatchId", "totalTxns", "totalBatchAmount", "status");
} else {
errorDialog("No Records found for criteria");
}
}
private void keyPressListener() {
String code = StringUtils.isNotBlank(searchField1.getValue()) ? searchField1.getValue() : null;
if (StringUtils.isNotBlank(searchField2.getValue())) {
search(code, searchField2.getValue());
}
}
private void buildGrid(Collection<Batch> records, String... columns) {
Component result;
if (records.size() == 0) {
result = new Label("NO REPORT DATA AVAILABLE.");
} else {
final Grid<Batch> grid = new Grid<>(Batch.class);
grid.setHeightByRows(records.size() < 10);
grid.setColumns(columns);
grid.setItems(records);
grid.setWidthFull();
grid.asSingleSelect().addValueChangeListener(l -> Optional.ofNullable(l.getValue()).ifPresent(this::edit));
result = grid;
}
if (getComponentCount() < 3) {
add(result);
} else {
replace(getComponentAt(2), result);
}
}
private void loadData(String code, String userAgent) {
if (StringUtils.isNotBlank(code)) {
search(null, userAgent);
} else {
search(code, userAgent);
}
}
}
Disclaimer: some further fact finding happended via IRC
The answer to the question is related to OP running multiple instances of the application behind an round robin load ballancer. The clients hit random servers and therefor had no session running there.
The solution to this is having a shared session store and ideally have the load ballancer dispatch on existing session, so "hot" backend servers get hit.

Drag Cursor not showing on OSX

We have a large Java app that is used on both Windows and OSX.
We do custom Drag and Drop between 2 of our JTables.
On Windows, this works perfectly. The custom cursor is displayed as you drag over the target JTable.
On the Mac, the custom cursor is never displayed. Instead a gray rectangle (border only) is displayed when you start dragging. This rectangle is the width of the table column, and the height of the table. Our logging is showing that the dragOver() and dropActionChanged() methods are getting called, and we are setting the custom cursor. It just never gets displayed.
If I disable our custom cursor code, the same box is displayed - but it has the Circle/slash icon in the middle as well.
I want to get rid of the weird box, and display the custom cursor.
Excerpts from the code:
private class FileTransferHandler extends TransferHandler {
private static final long serialVersionUID = 1L;
private final Logger log = LogManager.getLogger();
private final CursorDragSourceListener dragSourceListener = new CursorDragSourceListener();
// Left out the Drop handling code that was here
#Override
public int getSourceActions( final JComponent c) {
log.debug("FileTransferHandler.getSourceAction: ");
return COPY | MOVE;
}
#Override
protected Transferable createTransferable( final JComponent c) {
log.debug("FileTransferHandler.createTransferable:");
List<iFilePage> pages = new ArrayList<iFilePage>();
// Left out the code that builds the pages list
DragSource.getDefaultDragSource().addDragSourceListener(dragSourceListener);
dragSourceListener.setCursorChoice(pages.size() == 1);
return new FilePageTransferable(pages);
}
#Override
protected void exportDone( final JComponent c,
final Transferable t,
final int action) {
log.debug("FileTransferHandler.exportDone: {}", action, t);
tblFixed.getSelectionModel().clearSelection();
DragSource.getDefaultDragSource().removeDragSourceListener(dragSourceListener);
return;
}
}
private static class CursorDragSourceListener implements DragSourceListener {
private Cursor singlePage = null;
private Cursor multiPage = null;
private Cursor badSinglePage = null;
private Cursor useCursor = null;
private boolean useSingle = false;
public CursorDragSourceListener() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
URL url;
String name;
Image img;
url = FileUtils.getResourceURL("/images/page.png");
name = "DragPage";
img = toolkit.createImage(url);
singlePage = toolkit.createCustomCursor(img, new Point(16, 16), name);
url = FileUtils.getResourceURL("/images/badpage_stack.png");
name = "DragBadPage";
img = toolkit.createImage(url);
badSinglePage = toolkit.createCustomCursor(img, new Point(16, 16), name);
url = FileUtils.getResourceURL("/images/page_stack.png");
name = "DragPageStack";
img = toolkit.createImage(url);
multiPage = toolkit.createCustomCursor(img, new Point(16, 16), name);
return;
}
public void setCursorChoice( final boolean single) {
log.debug("CursorDragSourceListener.setCursorChoice: {}", single);
useSingle = single;
if (useSingle) {
useCursor = singlePage;
} else {
useCursor = multiPage;
}
return;
}
#Override
public void dropActionChanged( final DragSourceDragEvent dsde) {
log.debug("CursorDragSourceListener.dropActionChanged: {}", dsde.getDropAction(), useSingle);
if (dsde.getDropAction() == 2) {
if (!useSingle) {
useCursor = badSinglePage;
} else {
useCursor = singlePage;
}
} else {
if (useSingle) {
useCursor = singlePage;
} else {
useCursor = multiPage;
}
}
dsde.getDragSourceContext().setCursor(useCursor);
return;
}
#Override
public void dragOver( final DragSourceDragEvent dsde) {
try {
Object x = dsde.getDragSourceContext().getTransferable()
.getTransferData(DataFlavor.javaFileListFlavor);
log.trace("CursorDragSourceListener.dragOver: {}", (x != null) ? x.getClass().getSimpleName() : "null");
if (x instanceof ArrayList) {
dsde.getDragSourceContext().setCursor(useCursor);
}
} catch (Exception e) {
log.error("CursorDragSourceListener.dragOver:", e);
}
}
#Override
public void dragExit( final DragSourceEvent dse) {
}
#Override
public void dragEnter( final DragSourceDragEvent dsde) {
}
#Override
public void dragDropEnd( final DragSourceDropEvent dsde) {
}
}
After a bunch more checking and analysis, it turns out that our Custom Selection Model was causing this problem on OSX.
We have a selection model that allows you to select multiple individual cells, not just whole rows.
So the getMinSelectionindex() and getMaxSelectionIndex() methods returned dummy data, since we never used them.
That works fine on MS Win, but apparently the OSX drag and drop for JTable uses those calls.
After modifying our code to return reasonable values, the selection box is no longer as tall as the table.
The custom cursors appear most of the time, but still randomly disappear for no apparent reason.

Tree View JavaFX Memory out of Space

I have created javaFX tree with custom Objects (SystemNode).
Tree Items has graphics: check-box and image icon which I have set through updateItems() method.
Whenever I expand or collapse Item in tree ,twice or thrice I get JAVA HEAP MEMORY OUT OF SPACE and whole UI hangs UP.
PS: updateItems() method is invoked every time I expand or collapse tree node
I have tried adding event handlers but they didn't work.
Can anyone give some solutions.
Here is how I set cellFactory :
treeView_technicalAreas.setCellFactory(Util.getTreeCellFactory());
Here is code for cell factory:
public static Callback<TreeView<SystemNode>, TreeCell<SystemNode>> getTreeCellFactory() {
Callback<TreeView<SystemNode>, TreeCell<SystemNode>> callback = new Callback<TreeView<SystemNode>, TreeCell<SystemNode>>() {
#Override
public TreeCell<SystemNode> call(TreeView<SystemNode> p) {
TreeCell<SystemNode> cell = new TreeCell<SystemNode>() {
#Override
protected void updateItem(SystemNode t, boolean isEmpty) {
super.updateItem(t, isEmpty); //To change body of generated methods, choose Tools | Templates.
if (!isEmpty) {
System.out.println("util call back : " + t.getSystem().getName());
setText(t.getSystem().getName());
HBox hBox = new HBox();
CheckBox checkBox = new CheckBox();
checkBox.setSelected(t.getSelected());
checkBox.selectedProperty().bindBidirectional(t.getSelectedProperty());
hBox.setSpacing(SPACING_BETWEEN_ICON_AND_CHECKBOX);
ImageView imageView_icon = null;
if (t.getSystem().getType() == TYPE.BAREA) {
imageView_icon = new ImageView(Constant.Image_AREAS);
} else if (t.getSystem().getType() == TYPE.AREA) {
imageView_icon = new ImageView(Constant.Image_AREAS);
} else if (t.getSystem().getType() == TYPE.DOCUMENT) {
imageView_icon = new ImageView(Constant.Image_DOCUMENTS);
} else if (t.getSystem().getType() == TYPE.NOUN_NAME) {
imageView_icon = new ImageView(Constant.Image_NOUN_NAME);
} else if (t.getSystem().getType() == TYPE.CHANGE) {
imageView_icon = new ImageView(Constant.Image_DCC);
} else if (t.getSystem().getType() == TYPE.TASK) {
imageView_icon = new ImageView(Constant.Image_TASK);
}
hBox.getChildren().addAll(checkBox, imageView_icon);
setGraphic(hBox);
}
}
};
return cell;
}
};
return callback;
}

How to add data to the GXT Grid properly?

I have a webapp in which I need to get some data from the file and fill to the table. Here is the code of the page with this table:
public class Rules extends ContentPanel{
private final ServerManagementAsync serverManagementSvc = GWT.create(ServerManagement.class);
private ArrayList<PropertyItem> propslist;
private ArrayList<PropertyItem> itemArrayList;
private EditorGrid<PropertyItem> grid;
public Rules(final String customerId){
setLayout(new FlowLayout(10));
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig column = new ColumnConfig();
column.setId("name");
column.setHeader("Name");
column.setWidth(220);
TextField<String> text = new TextField<String>();
text.setAllowBlank(false);
column.setEditor(new CellEditor(text));
configs.add(column);
column = new ColumnConfig();
column.setId("type");
column.setHeader("Type");
column.setWidth(220);
TextField<String> typeText = new TextField<String>();
typeText.setAllowBlank(false);
column.setEditor(new CellEditor(typeText));
configs.add(column);
column = new ColumnConfig();
column.setId("value");
column.setHeader("Value");
column.setWidth(220);
configs.add(column);
final ListStore<PropertyItem> store = new ListStore<PropertyItem>();
propslist = getPropslist(customerId);
for (PropertyItem propertyItem: propslist){
store.insert(propertyItem, 0);
}
ColumnModel cm = new ColumnModel(configs);
setHeading("Settings");
setFrame(true);
setWidth(600);
setLayout(new FitLayout());
grid = new EditorGrid<PropertyItem>(store, cm);
grid.setAutoExpandColumn("name");
grid.setBorders(true);
add(grid);
ToolBar toolBar = new ToolBar();
setTopComponent(toolBar);
setButtonAlign(Style.HorizontalAlignment.RIGHT);
addButton(new Button("Refresh", new SelectionListener<ButtonEvent>() {
#Override
public void componentSelected(ButtonEvent ce) {
store.insert(getPropslist(customerId), 5);
}
}));
addButton(new Button("Add", new SelectionListener<ButtonEvent>() {
#Override
public void componentSelected(ButtonEvent ce) {
store.commitChanges();
}
}));
}
public ArrayList<PropertyItem> getPropslist(String customerId){
itemArrayList = new ArrayList<PropertyItem>();
AsyncCallback<ArrayList<PropertyItem>> callback = new AsyncCallback<ArrayList<PropertyItem>>() {
#Override
public void onFailure(Throwable throwable) {
}
#Override
public void onSuccess(ArrayList<PropertyItem> propertyItems) {
itemArrayList = propertyItems;
Window.alert("read successful");
}
}
};
serverManagementSvc.getProperties(customerId, callback);
return itemArrayList;
}
}
When I run my app I See only columns names and no data in the cells(and no cells of course). As the example I used this one: Ext GWT 2.2.6 Explorer(Grid)
I don't understand what could cause such proplem. What can be the reason of this?
Because your propsList is being populated Asynchronously the grid is being rendered before the server call returns.
To fix this first make the store a private property like the grid
Next, move the code that populates your store:
for (PropertyItem propertyItem: propslist){
store.insert(propertyItem, 0);
}
into the onSuccess Method of your callback.
Lastly, you may also need to call :
grid.reconfigure(grid.getStore(), grid.getColumnModel());
Just to get the Grid to render again.

Eclipse RCP: Generating views from form values

I want to build a user interface similar to the sketch below:
When the user fills out the form on the right and clicks the 'Plot!' button, a new closeable tab opens on the left with a chart.
I am new to RCP and have been following this tutorial. I am able to bring up tabs with charts triggered from a menu item. How do I go about:
creating the tab (view?) with the form
open a new chart tab when the user clicks the button
Edit
Here is my current code. It satisfies the basic requirements outlined in this question, but I am not sure if that is the best approach. I would be delighted if someone here can guide me in the right direction.
A view with the form; the button's listener invokes a command.
public class FormView extends ViewPart {
public static final String ID =
FormView.class.getPackage().getName() + ".Form";
private FormToolkit toolkit;
private Form form;
public Text text;
#Override
public void createPartControl(Composite parent) {
toolkit = new FormToolkit(parent.getDisplay());
form = toolkit.createForm(parent);
form.setText("Pie Chucker");
GridLayout layout = new GridLayout();
form.getBody().setLayout(layout);
layout.numColumns = 2;
GridData gd = new GridData();
gd.horizontalSpan = 2;
Label label = new Label(form.getBody(), SWT.NULL);
label.setText("Chart Title:");
text = new Text(form.getBody(), SWT.BORDER);
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button button = new Button(form.getBody(), SWT.PUSH);
button.setText("Plot");
gd = new GridData();
gd.horizontalSpan = 2;
button.setLayoutData(gd);
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseDown(MouseEvent e) {
IHandlerService handlerService = (IHandlerService) getSite()
.getService(IHandlerService.class);
try {
handlerService.executeCommand(ShowChartHandler.ID, null);
} catch (Exception ex) {
throw new RuntimeException(ShowChartHandler.ID +
" not found");
}
}
});
}
#Override
public void setFocus() {
}
}
The command invoked by the button from the form. This opens a new view with a chart.
public class ShowChartHandler extends AbstractHandler implements IHandler {
public static final String ID =
ShowChartHandler.class.getPackage().getName() + ".ShowChart";
private int count = 0;
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
try {
window.getActivePage().showView(ChartView.ID,
String.valueOf(++count), IWorkbenchPage.VIEW_ACTIVATE);
} catch (PartInitException e) {
e.printStackTrace();
}
return null;
}
}
The view with the chart. It looks up the form view and reads a value from a text field in the form (?!):
public class ChartView extends ViewPart {
public static final String ID =
ChartView.class.getPackage().getName() + ".Chart";
private static final Random random = new Random();
public ChartView() {
// TODO Auto-generated constructor stub
}
#Override
public void createPartControl(Composite parent) {
FormView form =
(FormView) Workbench.getInstance()
.getActiveWorkbenchWindow()
.getActivePage()
.findView(FormView.ID);
String title = form == null? null : form.text.getText();
if (title == null || title.trim().length() == 0) {
title = "Pie Chart";
}
setPartName(title);
JFreeChart chart = createChart(createDataset(), title);
new ChartComposite(parent, SWT.NONE, chart, true);
}
#Override
public void setFocus() {
// TODO Auto-generated method stub
}
/**
* Creates the Dataset for the Pie chart
*/
private PieDataset createDataset() {
Double[] nums = getRandomNumbers();
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("One", nums[0]);
dataset.setValue("Two", nums[1]);
dataset.setValue("Three", nums[2]);
dataset.setValue("Four", nums[3]);
dataset.setValue("Five", nums[4]);
dataset.setValue("Six", nums[5]);
return dataset;
}
private Double[] getRandomNumbers() {
Double[] nums = new Double[6];
int sum = 0;
for (int i = 0; i < 5; i++) {
int r = random.nextInt(20);
nums[i] = new Double(r);
sum += r;
}
nums[5] = new Double(100 - sum);
return nums;
}
/**
* Creates the Chart based on a dataset
*/
private JFreeChart createChart(PieDataset dataset, String title) {
JFreeChart chart = ChartFactory.createPieChart(title, // chart title
dataset, // data
true, // include legend
true, false);
PiePlot plot = (PiePlot) chart.getPlot();
plot.setSectionOutlinesVisible(false);
plot.setLabelFont(new Font("SansSerif", Font.PLAIN, 12));
plot.setNoDataMessage("No data available");
plot.setCircular(false);
plot.setLabelGap(0.02);
return chart;
}
}
The perspective that ties it all together:
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
layout.setEditorAreaVisible(false);
layout.addStandaloneView(FormView.ID, false,
IPageLayout.RIGHT, 0.3f,
IPageLayout.ID_EDITOR_AREA);
IFolderLayout charts = layout.createFolder("Charts",
IPageLayout.LEFT, 0.7f, FormView.ID);
charts.addPlaceholder(ChartView.ID + ":*");
}
}
I would recommend a different aproach. Eclipse has viewparts (views) and editors. It is easy to open multiple editors. Views are not so much for open multiple ones.
So my suggestion is, that you implement the part you call "FormView" as a StandAloneView and implement the "ChartView" as an editor.
I would also recommend to use a different listener for the button, so also the code will be executed when using the keyboard to click the button.
My proposal:
public class FormView extends ViewPart {
...
button.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
// this below can also be called by a command but you need to take care about the data, which the user put into the fields in different way.
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page = window.getActivePage();
ChartEditorInput input = new ChartEditorInput(text.getText(),...<other data you need to pass>);
try {
page.openEditor(input, ChartEditor.ID);
} catch (PartInitException e) {
e.printStackTrace();
}
}
});
ChartView needs to be changed to ChartEditor. See here http://www.vogella.de/articles/RichClientPlatform/article.html#editor_editorinput how that is done.
ChartEditorInput hereby is a class you need to implement aside the editor class, which holds the data.
In your perspective you call:
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setFixed(false);
layout.setEditorAreaVisible(true);
layout.addStandaloneView("your.domain.and.FormView", true,IPageLayout.RIGHT, 0.15f, editorArea);
Hope this helps!

Categories