How to update/refresh a view in an eclipse plug-in? - java

I have an eclipse plug-in with a single view (like the eclipse helloworld-view-plugin-project). In the view-file I get an event when I want to update the view.
In this view I have a GridData in a Group with multiple labels. I have several services which register to the programe and whose status should be shown in this GridData.
Edit: In order to better show my problem I updated this post and added the whole code:
CreatePartControl():
public void createPartControl(Composite _parent) {
parent = _parent;
createContents();
addBindings();
makeActions();
contributeToActionBars();
}
CreateContents():
protected void createContents() {
// fixed
checkIcon = //...
errorIcon = //...
smallFont = SWTResourceManager.getFont("Segoe UI", 7, SWT.NORMAL);
// content
gl_shell = new GridLayout(1, false);
//margins, etc. for gl_shell
parent.setLayout(gl_shell);
final Label lblGreeting = new Label(parent, SWT.NONE);
lblGreeting.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1));
lblGreeting.setText("Hi " + Preferences.getPreName());
// -- GROUP YOUR STATS (show all services)
createStatusGroupBox();
}
createStatusGroupBox():
private Group grpYourStatus = null; // outside the method for access in listener (below)
private void createStatusGroupBox() {
grpYourStatus = new Group(parent, SWT.NONE);
grpYourStatus.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
grpYourStatus.setText("Your upload status");
grpYourStatus.setLayout(new GridLayout(3, false));
// add message if no service is registered
if ( r.getServiceList().size() == 0 ) {
Label status = new Label(grpYourStatus, SWT.NONE);
status.setText("No service registered.");
new Label(grpYourStatus, SWT.NONE); //empty
new Label(grpYourStatus, SWT.NONE); //empty
}
// add labels (status, message, name) for each registered service
for ( IRecorderObject service : r.getServiceList() ) {
Label name = new Label(grpYourStatus, SWT.NONE);
Label status = new Label(grpYourStatus, SWT.NONE);
Label message = new Label(grpYourStatus, SWT.NONE);
message.setFont(smallFont);
message.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
service.getServiceViewItem().setLabelsAndIcons(name, status, message, checkIcon, errorIcon); //this also sets the values of the labels (label.setText(...) via data binding)
}
Unfortunately, I don't know what the right way is to update/reset it. I tried the following:
listener (which should update the view / the services-list):
r.addPropertyChangeListener(BindingNames.SERVICE_ADDED, new PropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent evt) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// This "redraws" the view, but just places the whole content (generated in createStatusGroupBox()) above the other parts.
//Display.getCurrent().update();
//createStatusGroupBox();
//parent.layout(true);
//parent.redraw();
// disposes grpYourStatus-Group but doesn't show anything then
grpYourStatus.dispose();
createStatusGroupBox();
grpYourStatus.layout();
grpYourStatus.redraw();
}
});
}
});
I also tried the following statements (individually); all without success:
parent.redraw();
parent.update();
parent.layout();
parent.layout(true);
parent.refresh();
In this post I read the following:
createPartControls is that time of the life cycle of a view, where its
contained widgets are created (when the view becomes visible
initially). This code is only executed once during the view life
cycle, therefore you cannot add anything here directly to refresh your
view.
Eclipse parts typically update their content as a reaction to a
changed selection inside of the workbench (e.g. the user might click
on another stack frame in the debug view).
Unfortunately, I don't know what to else I could try and I didn't find anything helpful with searches... thank's for your help and suggestions!

I finally found the answer (together with AndreiC's help!):
my listener now looks like this:
r.addPropertyChangeListener(BindingNames.SERVICE_ADDED, new PropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent evt) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// remove grpYourStatus from parent
grpYourStatus.dispose();
// add grpYourStatus (with updated values) to parent
createStatusGroupBox();
// refresh view
parent.pack();
parent.layout(true);
}
});
}
});
The rest is the same like the code above.

I do not know the API by heart, but have you tried parent.update()?

Related

How to make the children of a composite visible immediately after disposed them and loaded them again in SWT?

I'm working with Eclipse RCP. There I have a view with the standard method createPartControl(Composite parent) which I have implemented as follows:
public void createPartControl(Composite parent) {
this.parent = parent;
createContent();
}
In createContent(), the composite parent gets a few elements (e. g. a table with the state of something) which I would like to update. Therefore, I have an update button. When you click on it, all children of parent should be disposed and the method createPartControl(parent) should be executed again.
This is my current code for that:
buttonUpdate = new Button(parent, SWT.NONE);
buttonUpdate.setText("Update");
GridData gridData = new GridData(80, 30);
buttonUpdate.setLayoutData(gridData);
buttonUpdate.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
switch (e.type) {
case SWT.Selection:
for (Control control : parent.getChildren()) {
control.dispose();
}
createPartControl(parent);
break;
}
}
});
When I started my application and clicked on the update button, the window becomes empty but no new content appears. Only, when I open another view in my app and then switch back, I see the updated content. How to make the new content visible immediately?
You need to layout the parent composite again.
Call
parent.layout(true, true);
after the createPartControl call.
I got it! I have found this page and
parent.layout(true, true);
helps me.

Eclipse Plugin: Opening dialogs alongside quickfix

I'm working on a plugin and am trying to add some additional information around the quickfix menu that is triggered by clicking on my custom markers.
I'm adding a method call in MarkerResolutionGenerator.getResolutions() to draw the new dialog window, but I'm having trouble getting it to agree with the quickfix dialog. I can get it to draw at the same time, but I can't control the position and it also draws an extra blank dialog in the background.
Any thoughts? Relevant code below. The first two methods are from my MarkerResolutionGenerator, and my custom class is below that. (I just copied it from an example, I'm more worried about getting it to behave before I work on the content.)
#Override
public IMarkerResolution[] getResolutions(IMarker marker)
{
IMarker problem = marker;
makeStuff();
...
}
private void makeStuff()
{
Display display = Activator.getDefault().getWorkbench().getDisplay();
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor()
.getSite().getWorkbenchWindow().getShell();
Shell myShell = new Shell(shell, SWT.NO_TRIM);
MyDialog md = new MyDialog(myShell);
md.open();
}
public class MyDialog extends Dialog
{
public MyDialog(Shell parentShell)
{
super(parentShell);
setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE);
setBlockOnOpen(false);
}
#Override
protected Control createDialogArea(Composite parent)
{
Composite container = (Composite) super.createDialogArea(parent);
Button button = new Button(container, SWT.PUSH);
button.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
button.setText("Press me");
button.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Pressed");
}
});
return container;
}
...
}
Do you really need to create another Shell? Why not just use the one you already have as parent for your dialog? It might be the reason for the "extra blank dialog in the background".
You should be able to set the initial position overriding getInitialLocation in your custom dialog:
#Override
protected Point getInitialLocation(Point initialSize) {
return new Point(10, 10); // x and y coordinates of the initial position
}

Using wizard and ScrolledForm(jface and forms api)

I'm new to eclipse plugin - SWT development. I'm trying to create wizard page having number of text fields and combo boxes. For better look n feel I'm trying to use FormToolkit for creating components and add them in ScrolledForm. But with this nothing is rendered on wizard page at runtime and there is no error also.
Questions:
Is it possible to have scrolled container inside wizard page?
Can we mix JFace and forms api?
(removed unwanted code)
Here is wizard page code:
public class ContactWizardPage extends WizardPage {
private static int counter;
private Form form;
public ContactWizardPage() {
super("New Contact Wizard" + ++counter, "New Contact Wizard" + counter, null);
setMessage("Please enter contact info." + counter);
}
public void createControl(final Composite parent) {
createControlWithoutToolkit(parent);
// commenting out toolkit code
// createControlWithToolkit(parent);
}
public void createControlWithoutToolkit(final Composite parent) {
Composite composite = new Composite(parent, SWT.DEFAULT);
composite.setLayout(new GridLayout(2, true));
Label lblFirstName = new Label(composite, SWT.FLAT);
lblFirstName.setText("First Name");
Label lblLastName = new Label(composite, SWT.FLAT);
lblLastName.setText("Last Name");
Text txtFirstName = new Text(composite, SWT.FLAT);
Text txtLastName = new Text(composite, SWT.FLAT);
Label lblEmail = new Label(composite, SWT.FLAT);
lblEmail.setText("Email");
GridDataFactory.swtDefaults().span(2, 1).align(
SWT.FILL,
SWT.BEGINNING).applyTo(lblEmail);
Text txtEmail = new Text(composite, SWT.FLAT);
GridDataFactory.swtDefaults().span(2, 1).align(
SWT.FILL,
SWT.BEGINNING).applyTo(txtEmail);
setControl(composite);
}
public void createControlWithToolkit(final Composite parent) {
FormToolkit toolkit = new FormToolkit(Display.getCurrent());
ScrolledForm form = toolkit.createScrolledForm(parent);
Composite composite = form.getBody();
composite.setLayout(new GridLayout(2, true));
Label lblFirstName = toolkit.createLabel(composite, "First Name");
Label lblLastName = toolkit.createLabel(composite, "Last Name");
Text txtFirstName = toolkit.createText(composite, "");
Text txtLastName = toolkit.createText(composite, "");
Label lblEmail = toolkit.createLabel(composite, "Email");
GridDataFactory.swtDefaults().span(2, 1).align(
SWT.FILL,
SWT.BEGINNING).applyTo(lblEmail);
Text txtEmail = toolkit.createText(composite, "");
GridDataFactory.swtDefaults().span(2, 1).align(
SWT.FILL,
SWT.BEGINNING).applyTo(txtEmail);
setControl(composite);
}
}
Here is Wizard code:
public class SampleNewWizard extends Wizard implements INewWizard {
public SampleNewWizard() {
super();
setNeedsProgressMonitor(true);
}
#Override
public IWizardPage getNextPage(IWizardPage page) {
return super.getNextPage(page);
}
public void addPages() {
addPage(new ContactWizardPage());
addPage(new ContactWizardPage());
addPage(new ContactWizardPage());
addPage(new ContactWizardPage());
}
public boolean performFinish() {
return true;
}
public void init(IWorkbench workbench, IStructuredSelection selection) {
}
}
With this code first page of wizard shows fine but second page is never rendered properly. :(
here are screenshots:
first page:
second page:
The line
parent.getShell().setSize(240, 320);
is upsetting something (and is not something you should do in a wizard page as the Wizard class deals with sizing). Testing here it works fine without it (and I get your problem with it).
Make sure that you do not dispose the FormToolKit as long as the wizard is open. Paint events need the toolkit after createControl() has finished.
My solution is to create and dispose the FormToolKit in the wizard:
#Override
public void createPageControls(Composite pageContainer) {
toolkit = new FormToolkit(pageContainer.getDisplay());
super.createPageControls(pageContainer);
}
#Override
public void dispose() {
super.dispose();
if (toolkit != null) {
try { toolkit.dispose(); } catch (Exception e) {}
}
}
public FormToolkit getToolkit() {
return toolkit;
}
In the wizard pages you can than use ((FormWizard) getWizard).getToolkit() to get a reference to the wizard's form toolkit.
#Override
public void createControl(Composite parent) {
FormToolkit toolkit = ((FormWizard) getWizard()).getToolkit();
...
Hope this helps ...

Eclipse RCP - How to create and open View programmatically?

I want to open a View which includes table when operation is executed.
I can open view by viewId by that code:
display.asyncExec(new Runnable(){
public void run() {
ApplicationGIS.getView(true, viewId);
}});
This view's id defined on plugin.xml but I have to pass some parameters to the table on this view. I can create my custom view programatically but this time i can't open it becuase I don't have its id. Here is my view class:
public class MyCustomView extends ViewPart {
private Text text;
private Table table;
private TableViewer tableViewer;
#Override
public void createPartControl(Composite parent) {
// TODO Auto-generated method stub
parent.setLayout(new GridLayout(4, false));
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
composite.setLayout(new GridLayout(2, false));
text = new Text(composite, SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
Composite composite_1 = new Composite(composite, SWT.NONE);
composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
GridLayout gl_composite_1 = new GridLayout(1, false);
gl_composite_1.horizontalSpacing = 0;
gl_composite_1.marginHeight = 0;
gl_composite_1.marginWidth = 0;
gl_composite_1.verticalSpacing = 0;
composite_1.setLayout(gl_composite_1);
tableViewer = new TableViewer(composite_1, SWT.BORDER | SWT.FULL_SELECTION);
table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
}
#Override
public void setFocus() {
// TODO Auto-generated method stub
}
}
So how can I access this programmatically created view and open it?
In Eclipse 3.x you can open a View like this:
MyView view = (MyView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(viewer_ID);
Or if you are implementing a command handler, you can call:
HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().showView(viewId);
To set some content you can simply add a method like void setInput(MyContent input) to your ViewPart and pass the needed arguments to this method, after opening it.
I had the exact same problem. I wanted to create additional views from the one registered in the plugin. These URL's will get you what you want:
http://wiki.eclipse.org/FAQ_How_do_I_open_multiple_instances_of_the_same_view
http://www.java-tips.org/other-api-tips/eclipse/how-to-create-multiple-instances-of-one-viewpart.html
PlatformUI.getWorkbench().getActiveWorkbenchWindow().
getActivePage().showView(String viewID,String secondaryID,int Mode);
From #Chriss answer;
I added a method setInput(parameter) to my view and then I can pass my values to my custom view like this
MyCustomView view = new MyCustomView();
view.setInput(parameter);
display.asyncExec(new Runnable(){
public void run() {
ApplicationGIS.getView(true, viewId);
}});
and this works.

How to set a JFace TreeViewer with no selection allowed?

When creating a JFace TreeViewer, one can use the SWT constants to set single or multiple selections allowed for the user to the tree items (SWT.SINGLE or SWT.MULTI).
Can anyone help me please as I want a tree that its items can not be selected at all? I want it as for preview purpose and user should not be able to select an item there.
Many thanks in advance,
I don't really understand why do you want to suppress the selection, but this is how it may work:
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(final SelectionChangedEvent event) {
if (!event.getSelection().isEmpty()) {
v.setSelection(StructuredSelection.EMPTY);
}
}
});
In addition to this I would make sure that the viewer:
is not registered as the selection provider in the part's site
accepts no other ISelectionChangedListeners
Another easy solution is to put the viewer into a separate composite and set the enabled state of it to false:
Composite c = new Composite(parent, SWT.NONE);
TreeViewer viewer = new TreeViewer(c, SWT.Border);
c.setEnabled(false);
Your viewer will now NOT appear grey (setting viewer.setEnabled will make it appear grey) but the user is unable to select anything in the viewer. Updating and refreshing the viewer works just fine. But keep in mind that no SelectionEvents will be thrown when clicking into the viewer now.
Could you try this?
Basically adding filter on selection events. In case of Viewer implementation,
org.eclipse.jface.util.OpenStrategy class is responsible for firing selection events what Viewer's understand. If filter is added on SWT selection event, Viewer will never know about underlying selection.
public class SWTSimpleTree {
Display display = new Display();
Shell shell = new Shell(display);
Tree tree;
private Listener filter = new Listener() {
#Override
public void handleEvent(Event event) {
event.type=SWT.None;
event.doit=false;
event.item = null;
tree.deselectAll();
}
};
public SWTSimpleTree() {
shell.setLayout(new GridLayout());
tree = new Tree(shell, SWT.BORDER);
tree.setLayoutData(new GridData(GridData.FILL_BOTH));
TreeItem item = new TreeItem(tree, SWT.NULL);
item.setText("ITEM");
TreeItem item2 = new TreeItem(item, SWT.NULL);
item2.setText("ITEM2");
TreeItem item3 = new TreeItem(item2, SWT.NULL);
item3.setText("ITEM3");
System.out.println("item: " + item.getParent() + ", " + item.getParentItem());
System.out.println("item2: " + item2.getParent() + ", " + item2.getParentItem());
System.out.println(tree.getItemCount());
System.out.println(tree.getItems().length);
tree.getDisplay().addFilter(SWT.Selection, filter);
tree.getDisplay().addFilter(SWT.DefaultSelection, filter);
shell.setSize(300, 200);
shell.open();
//textUser.forceFocus();
// Set up the event loop.
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
// If no more entries in event queue
display.sleep();
}
}
display.dispose();
}
private void init() {
}
public static void main(String[] args) {
new SWTSimpleTree();
}
}

Categories