I defined a custom FieldEditorPreferencePage. In createFieldEditors method I construct a simple interface with a custom FieldEditor that holds button that loads a file. When a user loads the file the interface region (where the button stands) need to change and show other specific gui. How to invalidate the FieldEditorPreferencePage? I used the layout() method of the parent composite but nothing happens. What am I doing wrong here?
public class MyPage extends FieldEditorPreferencePage {
...
private Composite fieldEditorParent;
private boolean fileLoaded = false;
#Override
protected void createFieldEditors() {
fieldEditorParent = this.getFieldEditorParent();
MyFieldEditor compositeFieldEditor = new MyFieldEditor(fieldEditorParent) {
if(fileLoaded) {
//draw file content
} else {
Button chooseButton = new Button(buttonsComposite, SWT.NONE);
chooseButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
//choose file
fileLoaded = true;
//invalidate page <-- THIS DOES NOT WORK!
fieldEditorParent.layout(true, true);
}
}
}
}
}
Related
I know this has a few answers, but none of them are working for me. Also the questions are a bit different because I'm using my own model implementation.
This code shows what should happen on button click.
Here the content is set to the tree viewer:
root = new TreeRootModel(solverEntries, null, configParser.getConfFile());
root.addInstances(instances);
viewer.setInput(new TreeRootModel[] { root });
column.pack(); // important to see TreeViewer at start
viewer.expandAll();
The TreeRootModel class is just a storage class under which an array is stored, with getter and setter. Not worth showing here.
ToolBar toolBar = new ToolBar(newMainComposite, SWT.FLAT | SWT.WRAP | SWT.RIGHT);
ToolItem addItem = new ToolItem(toolBar, SWT.PUSH);
addItem.setText("Add");
addItem.setImage(addIcon);
addItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
InstanceModel newInstance = new InstanceModel("new Instance", null);
instances.add(newInstance);
// none of these three calls has an effect
viewer.refresh();
tree.update();
column.pack();
}
});
So the content of the TreeViewer is root, and root contains the List "instances". These objects will be displayed in the TreeViewer. Upon clicking the add button, an object is added to the List instances. I want to see that immediately in the TreeViewer.
The ContentProvider's inputChanged method is empty.
public class GoalInstanceContentProvider implements ITreeContentProvider, IResourceChangeListener {
TreeRootModel root;
ArrayList<InstanceModel> instances = new ArrayList<>();
private TreeViewer viewer;
private TreeRootModel[] input;
#Override
public void dispose() {
}
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
#SuppressWarnings("unchecked")
#Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof TreeRootModel) {
root = (TreeRootModel) inputElement;
return root.getInstances().toArray();
} else if (inputElement instanceof ArrayList) {
instances = (ArrayList<InstanceModel>) inputElement;
return instances.toArray();
}
return ArrayContentProvider.getInstance().getElements(inputElement);
}
...
}
Stop putting root inside of an array when setting the input. Use it directly.
I created a wizard with one page and has two widgets: a list and a button
but when calling the wizard using dialog.open() the wizard opens but the widgets of the page are not displayed. I don't know what is wrong!
Here is the code of the page
public class SelectCriterionPage extends WizardPage {
private Composite container;
ArrayList<String> listItems=new ArrayList<String>();
List variables,selected;
protected SelectCriterionPage() {
super("CriterionSelection","SelectCriterionPage",null);
setTitle("Selection of criterion variables");
}
#Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
variables=new List(container, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
//fill the list with variables
for(String item:listItems)
variables.add(item);
variables.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
Button btn=new Button(container, SWT.PUSH);
btn.setText("<");
GridData gr=new GridData(GridData.FILL,SWT.CENTER);
btn.setLayoutData(gr);
setControl(container);
}
}
i called my wizard
WizardDialog dialog = new WizardDialog(null, new SelectSlicingCriterionWizard());
dialog.open();
here is my wizard:
public class SelectSlicingCriterionWizard extends Wizard{
IWorkbenchPage workbench;
IStructuredSelection selection;
ArrayList<String> listItems;
public SelectSlicingCriterionWizard() {
super();
setNeedsProgressMonitor(true);
}
#Override
public boolean performFinish() {
System.out.println("Finish clicked");
return true;
}
#Override
public boolean performCancel(){
return true;
}
#Override
public void addPages() {
SelectCriterionPage criterionpage=new SelectCriterionPage();
addPage(criterionpage);
}
#Override
public String getWindowTitle() {
return "Select Criterion Variables";
}
public void init(IWorkbench workbench, IStructuredSelection selection)
{
this.workbench=workbench.getActiveWorkbenchWindow().getActivePage();
this.selection=selection;
}
}
You have not set a Layout for your wizard page Composite. Since you seem to be trying to use Grids this should be:
container = new Composite(parent, SWT.NONE);
container.setLayout(new GridLayout());
Your GridData for the button is using the wrong constructor (the two parameter constructor sets the height and width). Use something like:
GridData gr = new GridData(SWT.BEGINNING, SWT.TOP, false, false);
btn.setLayoutData(gr);
You need to set a Layout for your Composite.
For examples on using GridLayout please see - https://www.eclipse.org/swt/snippets/#gridlayout
For an example on using GridLayout in WizardPage, please see - http://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/examples/org.eclipse.jface.snippets/Eclipse%20JFace%20Snippets/org/eclipse/jface/snippets/wizard/Snippet047WizardWithLongRunningOperation.java
I have 2 classes, one class is a JFrame (MainUIHolder.java) and the other class is a JDialog (EditValuationsDialog.java). MainUIHolder can call EditValuationsDialog on button click event.
Once EditValuationsDialog is open, user can enter data in its fields and press its "Add" button. OK, here is the issue now. Once the user press the "Add" button, the EditValuationsDialog should inform that to the MainUIHolder.
Below is the code.
MainUIHolder
Action edit = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
JTable table = (JTable)e.getSource();
int rowNum = Integer.valueOf(e.getActionCommand());
Object valueAt = table.getModel().getValueAt(rowNum, 0);
EditValuationsDialog edit = new EditValuationsDialog(null,true);
edit.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
edit.setTitle("Edit Valuations");
edit.setClientName(portfolioViewClientName.getText());
edit.setPortfolioType(portfolioViewInvestmentTypeCombo.getSelectedItem().toString());
edit.setPortfolioId(id);
edit.setOngoingValuationsId(Integer.parseInt(String.valueOf(valueAt)));
edit.setLocationRelativeTo(table);
edit.setVisible(true);
//CATCH THE CALL FROM EditValuationsDialog HERE!!!!//
}
};
EditValuationsDialog
//Action Listeners
private class AddBtnAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(someCondition)
{
return String / int to MainUIHolder (See where I want to catch it in MainUIHolder)
}
else
{
do nothing
}
}
}
In my code I have indicated from where the call to MainUIHolder should be generated and in what place I must catch that call in MainUIHolder. How can I do this call back work?
You could...
Add a static method to EditValuationsDialog that shows the dialog, evaluates the results and returns the value you are expecting...
public void actionPerformed(ActionEvent e)
{
int result = EditValuationsDialog.showDialog();
}
public class EditValuationsDialog ... {
//...
private int result = -1;
//...
public int getResult() {
return result;
}
//...
public static int showDialog(Component source, int rowNum, Object valueAt) {
EditValuationsDialog edit = null;
Window parent = SwingUtilities.windowFor(source);
if (parent instanceof Frame) {
edit = new EditValuationsDialog((Frame)parent,true);
} else if (parent instanceof Dialog) {
edit = new EditValuationsDialog((Dialog)parent,true);
} else {
edit = new EditValuationsDialog(null,true);
}
edit.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
edit.setTitle("Edit Valuations");
edit.setClientName(portfolioViewClientName.getText());
edit.setPortfolioType(portfolioViewInvestmentTypeCombo.getSelectedItem().toString());
edit.setPortfolioId(id);
edit.setOngoingValuationsId(Integer.parseInt(String.valueOf(valueAt)));
edit.setLocationRelativeTo(source);
edit.setVisible(true);
return edit.getResult();
}
//...
private class AddBtnAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(someCondition)
{
result = 0;
}
else
{
result = 1;
}
EditValuationsDialog.this.dispose();
}
}
}
Or you could...
Simply evaluate the results of getResult() from the above example directly...
Side note: Because I don't like extending from top level containers like JDialog, I tend to create some of my panels/components with static showDialog methods, thing something along the lines of a login panel for example. It means I could re-use the panel else where, but provides me with the convenience of been able to popup a dialog when I need to. I've also used JOptionPane from time to time to show these panels, but it depends on the complexity of the available actions...
Make the dialog modal (setModal(true)). Then the code after dialog.setVisible(true) is executed after the dialog is closed.
BTW it's better to pass the MainUIHolder JFrame instance as parent of the dialog.
You could add an interface to the EditValuationsDialog something like this:
Interface EditValuationsDialogInterface {
public void onAddClicked(addedVlue);
}
and then add it as such:
edit.setOnAddButtonCallback(new EditValuationsDialogInterface () {
#Override
onAddClicked(addedVlue){
//DO SOMETHING
}
});
in your EditValuationsDialog's add button onclick call add this:
onAddButtonClickedCallback.onAddClicked(retunrValue);
This allows you to have a direct link back to the original calling class.
I have a menubar in my vaadin application and want to add an item to open a pdf-file is a new tab of the browser. I found some solutions to open files with a button, but I have to use an MenuItem...
MenuBar.Command commandHandler = new MenuBar.Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
if (selectedItem.equals(menu_help)) {
openHelp();
}
}
};
...
menu_help = menuBar
.addItem("", WebImageList.getImage(ImageList.gc_helpIcon),
commandHandler);
...
private void openHelp() {
// open pdf-file in new window
}
Thanks for help!
SOLUTION:
private void openHelp() {
final String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
Resource pdf = new FileResource(new File(basepath + "/WEB-INF/datafiles/help.pdf"));
setResource("help", pdf);
ResourceReference rr = ResourceReference.create(pdf, this, "help");
Page.getCurrent().open(rr.getURL(), "blank_");
}
Attention: This code works, but the the structure of code is not perfect ;-) Better is to store "basepath" and "pdf" as attribute...
There is a similar problem described here: How to specify a button to open an URL?
One possible solution:
public class MyMenuBar extends MenuBar {
ResourceReference rr;
public MyMenuBar() {
Resource pdf = new FileResource(new File("C:/temp/temp.pdf"));
setResource("help", pdf);
rr = ResourceReference.create(pdf, this, "help");
}
private void openHelp() {
Page.getCurrent().open(rr.getURL(), "blank_");
}
...
}
The setResource method of AbstractClientConnector is protected, so this is you need to extend some Vaadin component to make it work. This is why Im creating the class MyMenuBar here. If you are using an external resource you don't need to attach it to any component with setResource and then this is not nessecary.
I used the following code to do something similar:
private Component buildUserMenu() {
final MenuBar settings = new MenuBar();
settings.addStyleName("user-menu");
final User user = getCurrentUser();
settingsItem = settings.addItem("", new ThemeResource(
"img/logo.png"), null);
updateUserName(null);
settingsItem.addItem(Lang.getMessage("menu.edit"), new Command() {
#Override
public void menuSelected(final MenuItem selectedItem) {
ProfilePreferencesWindow.open(user, false);
}
});
settingsItem.addSeparator();
settingsItem.addItem(Lang.getMessage("menu.help"), new Command() {
#Override
public void menuSelected(final MenuItem selectedItem) {
Window help = new Window();
help.setWidth("90%");
help.setHeight("90%");
BrowserFrame e = new BrowserFrame("PDF File", new ThemeResource("pdf/ayuda.pdf"));
e.setWidth("100%");
e.setHeight("100%");
help.setContent(e);
help.center();
help.setModal(true);
UI.getCurrent().addWindow(help);
}
});
settingsItem.addSeparator();
settingsItem.addItem(Lang.getMessage("menu.logout"), new Command() {
#Override
public void menuSelected(final MenuItem selectedItem) {
BarsEventBus.post(new UserLoggedOutEvent());
}
});
return settings;
}
I want to create a popup (implemented as a DialogBox or other similar component) which i should be able to reuse in multiple pages or forms. I want the DialogBox to be able to return a value to the "opener".
I am thinking i.e. on a DialogBox that shows a table (obtained via RPC). That DialogBox can be used in several different pages. When the user selects a row, an object is "passed back to the page" (for example, calling a method on it), so it can write it to a form field, or do whatever with it. The called doesn't know anything about the logic inside de DialogBox, only knows how to deal with the returning type.
A good example of what i'm intending to do could be a DatePicker that returns a java.util.Date.
Have you done something similiar?
I appreciate your help.
Thanks!
David
It's really easy. You should first create an interface that will be implemented by all the pages opening you DialogBox :
public interface DialogBoxOpener {
void dialogBoxValidated (Date selectedDate);
void dialogBoxCancelled ();
}
Then, create your DialogBox, and take a DialogBoxOpener as parameter to your showDialogBox method :
public class MyDialogBox extends DialogBox {
private DialogBoxOpener opener = null;
private final Button cancelButton = new Button("Cancel");
private final Button validButton = new Button("Ok");
private final DateBox myDateBox = new DateBox();
public MyDialogBox () {
cancelButton.addClickHandler(new ClickHandler () {
#Override
public void onClick(final ClickEvent event) {
hide();
if (opener!=null)
opener.dialogBoxCancelled();
}
});
validButton.addClickHandler(new ClickHandler () {
#Override
public void onClick(final ClickEvent event) {
hide();
if (opener!=null)
opener.dialogBoxValidated(myDateBox.getValue());
}
});
// TODO : create your DialogBox
}
public void showDialogBox (final DialogBoxOpener opener) {
this.opener = opener;
// Show the DialogBox
center ();
}
}
And now, you can show your DialogBox from your page :
public class MyPage implements DialogBoxOpener {
private MyDialogBox myDialogBox = getMyDialogBox();
private void openDialogBox () {
myDialogBox.showDialogBox(this);
}
public void dialogBoxValidated (Date selectedDate) {
// TODO : Do something with the date
}
public void dialogBoxCancelled () {
// TODO : Do something
}
}