SWT MessageBox with custom button titles - java

I want to add the custom button titles in my non-RCP SWT app.
MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
messageBox.setText("Warning");
messageBox.setMessage("Save the changes before exiting?");
int buttonID = messageBox.open();
switch(buttonID) {
case SWT.YES:
// saves changes ...
case SWT.NO:
// exits here ...
break;
case SWT.CANCEL:
// does nothing ...
}
System.out.println(buttonID);
}
It works fine but i button titles are "Abort", "Retry", "ignore"
I want custom button titles, like "overwrite", "rename", "cancel".
How it can be done?
Please help.
*** EDIT ********
I also tried
MessageDialog dialog = new MessageDialog(null, "Dangerous Activity", null,
"Are you sure you want to delete?", MessageDialog.CONFIRM,
new String[]{"Preview>", "Delete", "Cancel"}, 0)
{
protected void buttonPressed(int buttonId) {
setReturnCode(buttonId);
// close(); Call close for Delete or Cancel?
}};
But MessageDialog requires app to be RCP, therefore not importing the package required. Help.

Here is a very simple example on how to do your own Dialog in SWT (there are more comfortable ways to do this with JFace though):
public class CustomDialog extends Dialog
{
private String message = "";
private Shell shell;
public CustomDialog(Shell parent)
{
// Pass the default styles here
this(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
shell = parent;
}
public CustomDialog(Shell parent, int style)
{
// Let users override the default styles
super(parent, style);
shell = parent;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
public void open()
{
shell.setText(getText());
createContents(shell);
shell.pack();
shell.open();
Display display = getParent().getDisplay();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
/**
* Creates the dialog's contents
*
* #param shell
* the dialog window
*/
private void createContents(final Shell shell)
{
shell.setLayout(new GridLayout(3, true));
// Show the message
Label label = new Label(shell, SWT.NONE);
label.setText(message);
GridData data = new GridData();
data.horizontalSpan = 3;
label.setLayoutData(data);
// Display the input box
Label image = new Label(shell, SWT.NONE);
image.setImage(shell.getDisplay().getSystemImage(SWT.ICON_ERROR));
data = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
data.horizontalSpan = 3;
image.setLayoutData(data);
Button preview = new Button(shell, SWT.PUSH);
preview.setText("Preview");
data = new GridData(SWT.FILL, SWT.END, true, true);
preview.setLayoutData(data);
preview.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
System.out.println("Preview");
}
});
Button delete = new Button(shell, SWT.PUSH);
delete.setText("Delete");
data = new GridData(SWT.FILL, SWT.END, true, true);
delete.setLayoutData(data);
delete.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
System.out.println("Delete");
}
});
Button cancel = new Button(shell, SWT.PUSH);
cancel.setText("Cancel");
data = new GridData(SWT.FILL, SWT.END, true, true);
cancel.setLayoutData(data);
cancel.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
shell.close();
}
});
shell.setDefaultButton(preview);
}
public static void main(String[] args)
{
CustomDialog dialog = new CustomDialog(new Shell());
dialog.setText("Title");
dialog.setMessage("Message");
dialog.open();
}
}
It looks like this:

MessageBox cannot be extended this way. Your best option - when not doing an RCP application - probably is to roll your own dialog :-)
But given the simple nature of these dialogs, that should be easy enough.

I'm a little late to this, but if anyone else is looking for a cutomizable MessageBox, here it is. Create a class, then copy/paste the code into it. I want to thank Baz for giving me the starting point :-)
import java.util.ArrayList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
/**
* Custom MessageBox which allows custom button captions, such as using language specific text<br>
* <br>
* <code><b>
* int cancelResult = 0;<br>
* int deleteResult = 1;<br>
* <br>
* CustomMessageBox messageBox = new CustomMessageBox( ivShell, CustomMessageBox.ImageCode.QUESTION, "Confirm Delete", "Are you sure you want to delete:\n\n" + key );<br>
* <br>
* messageBox.addButton( "Cancel", cancelResult, true );<br>
* messageBox.addButton( "Delete " + key, deleteResult );<br>
* <br>
* if (messageBox.getResult() == deleteResult)<br>
* remove( key );<br>
* </b></code>
*/
public class CustomMessageBox extends Dialog
{
/**
* Standard SWT icons used in a message box
*/
public enum ImageCode
{
INFORMATION(SWT.ICON_INFORMATION),
QUESTION(SWT.ICON_QUESTION),
WARNING(SWT.ICON_WARNING),
ERROR(SWT.ICON_ERROR);
private int ivImageCode;
private ImageCode( int imageCode )
{
ivImageCode = imageCode;
}
private int getImageCode()
{
return ivImageCode;
}
}
private static final int FORM_SPACING = 5;
private static final String OK_CAPTION = "Ok"; //$NON-NLS-1$
private static final int SCREEN_MINIMUM = 20;
private Shell ivParentShell;
private Shell ivShell;
private Composite ivCompositeImage;
private Composite ivCompositeMessage;
private Composite ivCompositeDummy;
private Composite ivCompositeButtons;
private Label ivLabelImage;
private Label ivLabelMessage;
private Color ivMessageForegroundColor;
private Color ivMessageBackgroundColor;
private Font ivMessageFont;
private ImageCode ivImageCode;
private String ivTitle;
private String ivMessage;
private ArrayList<ButtonParameter> ivButtons;
private int ivResult;
/**
* Create a custom message box. You must {#link #addButton(String, int, boolean)} before calling {#link #getResult()}
* #param parentShell - the parent shell. The message box will be centered within this shell
* #param imageCode - the image to be shown in the upper/left corner
* #param title - the title for the message box
* #param message - the message shown to the user. You can have newlines in the message
*/
public CustomMessageBox( Shell parentShell, ImageCode imageCode, String title, String message )
{
super( parentShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL );
ivParentShell = parentShell;
ivImageCode = imageCode;
ivTitle = title;
ivMessage = message;
ivButtons = new ArrayList<>();
ivMessageForegroundColor = null;
ivMessageBackgroundColor = null;
ivMessageFont = null;
}
/**
* Buttons are created right to left, so add the right-most button first. This will not be the default button
* #param caption - the caption for the button
* #param result - the returned result when the button is chosen. Should be unique!
*/
public void addButton( String caption, int result )
{
addButton( caption, result, false );
}
/**
* Buttons are created right to left, so add the right-most button first.<br><br>
* If more than one button is set to be the default or no buttons are set to be the default, then the last one added will actually become the default.
* #param caption - the caption for the button
* #param result - the returned result when the button is chosen. Should be unique!
* #param isDefault - this will be the default button.
*/
public void addButton( String caption, int result, boolean isDefault )
{
ivButtons.add( new ButtonParameter( caption, result, isDefault ) );
}
/**
* Set the message foreground color
* #param foregroundColor
*/
public void setMessageForegroundColor( Color foregroundColor )
{
ivMessageForegroundColor = foregroundColor;
}
/**
* Set the message background color
* #param backgroundColor
*/
public void setMessageBackgroundColor( Color backgroundColor )
{
ivMessageBackgroundColor = backgroundColor;
}
/**
* Set the message font
* #param messageFont
*/
public void setMessageFont( Font messageFont )
{
ivMessageFont = messageFont;
}
/**
* Open the window and get the result. If no buttons were added, a stock "Ok" button will be created
*/
public int getResult()
{
Display display = Display.getDefault();
// bad programmer, bad
if (ivButtons.size() == 0)
addButton( OK_CAPTION, 0, true );
ivShell = new Shell( SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL );
createContents( display );
ivShell.pack();
ivShell.setLocation( centerOnParent( ivParentShell, ivShell ) );
ivShell.open();
while (!ivShell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
return ivResult;
}
/**
* Centers the message box within the parent shell
*/
private Point centerOnParent( Shell parentShell, Shell childShell )
{
Rectangle parent = parentShell.getBounds();
Rectangle child = childShell.getBounds();
int x = (int) (parent.x + (parent.width - child.width) * 0.5f);
int y = (int) (parent.y + (parent.height - child.height) * 0.5f);
// just to keep the left edge on the screen
if (x < SCREEN_MINIMUM)
x = SCREEN_MINIMUM;
// just to keep the top edge on the screen
if (y < SCREEN_MINIMUM)
y = SCREEN_MINIMUM;
return new Point( x, y );
}
/**
* Creates the contents and places them in the shell
*/
private void createContents( Display display )
{
FormData formData;
GridData gridData;
Button button;
Button lastButton;
ivShell.setLayout( new GridLayout( 2, false ) );
ivShell.setText( ivTitle );
{
ivCompositeImage = new Composite( ivShell, SWT.NONE );
ivCompositeImage.setLayout( new FormLayout() );
gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.verticalAlignment = SWT.TOP;
gridData.horizontalAlignment = SWT.LEFT;
ivCompositeImage.setLayoutData( gridData );
}
{
ivCompositeMessage = new Composite( ivShell, SWT.NONE );
ivCompositeMessage.setLayout( new FormLayout() );
gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
ivCompositeMessage.setLayoutData( gridData );
}
{
ivCompositeDummy = new Composite( ivShell, SWT.NONE );
ivCompositeDummy.setLayout( new FormLayout() );
}
{
ivCompositeButtons = new Composite( ivShell, SWT.NONE );
ivCompositeButtons.setLayout( new FormLayout() );
gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.horizontalAlignment = SWT.END;
ivCompositeButtons.setLayoutData( gridData );
}
{
ivLabelImage = new Label( ivCompositeImage, SWT.NONE );
formData = new FormData();
formData.top = new FormAttachment( 0, 0 );
formData.left = new FormAttachment( 0, 0 );
ivLabelImage.setLayoutData( formData );
ivLabelImage.setImage( display.getSystemImage( ivImageCode.getImageCode() ) );
}
{
ivLabelMessage = new Label( ivCompositeMessage, SWT.WRAP );
formData = new FormData();
formData.top = new FormAttachment( 0, 0 );
formData.left = new FormAttachment( 0, 0 );
formData.right = new FormAttachment( 100, 0 );
formData.bottom = new FormAttachment( 100, 0 );
ivLabelMessage.setLayoutData( formData );
// we add a new line to place white-space between the message and the buttons
// the trailing space is required!
ivLabelMessage.setText( ivMessage + System.getProperty( "line.separator" ) + " " ); //$NON-NLS-1$ //$NON-NLS-2$
if (ivMessageForegroundColor != null)
ivLabelMessage.setForeground( ivMessageForegroundColor );
if (ivMessageBackgroundColor != null)
ivLabelMessage.setBackground( ivMessageBackgroundColor );
if (ivMessageFont != null)
ivLabelMessage.setFont( ivMessageFont );
}
lastButton = null;
for (ButtonParameter parm : ivButtons)
{
button = new Button( ivCompositeButtons, SWT.PUSH );
formData = new FormData();
if (lastButton == null)
formData.right = new FormAttachment( 100, -FORM_SPACING );
else
formData.right = new FormAttachment( lastButton, -FORM_SPACING, SWT.LEFT );
formData.bottom = new FormAttachment( 100, -FORM_SPACING );
button.setLayoutData( formData );
button.setText( parm.getCaption() );
button.addMouseListener( new ButtonMouseListener( parm.getResult() ) );
lastButton = button;
if (parm.isDefault())
ivShell.setDefaultButton( button );
}
if (ivShell.getDefaultButton() == null)
ivShell.setDefaultButton( lastButton );
}
/**
* Internal class which holds the button parameters. This is created by the {#link CustomMessageBox#addButton(String, int, boolean)} method
*/
private class ButtonParameter
{
private String ivCaption;
private int ivResult;
private boolean ivIsDefault;
/**
* Create a button parameter
* #param caption - the caption for the button
* #param result - the returned result when the button is chosen
* #param isDefault - this will be the default button.
*/
private ButtonParameter( String caption, int result, boolean isDefault )
{
super();
ivCaption = caption;
ivResult = result;
ivIsDefault = isDefault;
}
private String getCaption()
{
return ivCaption;
}
private int getResult()
{
return ivResult;
}
private boolean isDefault()
{
return ivIsDefault;
}
}
/**
* Mouse listener for the buttons.
*/
private class ButtonMouseListener extends MouseAdapter
{
private int ivButtonResult;
/**
* Creates the listener
* #param result - The result returned when the button is pressed
*/
private ButtonMouseListener( int result )
{
super();
ivButtonResult = result;
}
#Override
public void mouseUp( MouseEvent e )
{
ivResult = ivButtonResult;
ivShell.close();
}
}
}

Related

How do I add a toolbar with controls to the DefaultInformationControl?

What I managed to do so far is adding a ToolBarManager for the ToolBar I created, which contains the ToolItem I want to add but nothing is shown when the hover popup based on this DefaultInformationControl is open.
I gave all the ToolItems text and style.
My code is :
public class JavaTextHover implements IJavaEditorTextHover, ITextHoverExtension{
.
.
.
#Override
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
ToolBar toolBar = new ToolBar(parent, SWT.NONE);
ToolItem itemPush = new ToolItem(toolBar, SWT.PUSH);
itemPush.setText("PUSH item");
ToolItem itemCheck = new ToolItem(toolBar, SWT.CHECK);
itemCheck.setText("CHECK item");
ToolItem itemRadio1 = new ToolItem(toolBar, SWT.RADIO);
itemRadio1.setText("RADIO item 1");
ToolItem itemRadio2 = new ToolItem(toolBar, SWT.RADIO);
itemRadio2.setText("RADIO item 2");
ToolItem itemSeparator = new ToolItem(toolBar, SWT.SEPARATOR);
Text text = new Text(toolBar, SWT.BORDER | SWT.SINGLE);
text.pack();
itemSeparator.setWidth(text.getBounds().width);
itemSeparator.setControl(text);
final ToolItem itemDropDown = new ToolItem(toolBar, SWT.DROP_DOWN);
itemDropDown.setText("DROP_DOWN item");
itemDropDown.setToolTipText("Click here to see a drop down menu ...");
final Menu menu = new Menu(parent, SWT.POP_UP);
new MenuItem(menu, SWT.PUSH).setText("Menu item 1");
new MenuItem(menu, SWT.PUSH).setText("Menu item 2");
new MenuItem(menu, SWT.SEPARATOR);
new MenuItem(menu, SWT.PUSH).setText("Menu item 3");
itemDropDown.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
if(event.detail == SWT.ARROW) {
Rectangle bounds = itemDropDown.getBounds();
Point point = toolBar.toDisplay(bounds.x, bounds.y + bounds.height);
menu.setLocation(point);
menu.setVisible(true);
}
}
});
Listener selectionListener = new Listener() {
public void handleEvent(Event event) {
ToolItem item = (ToolItem)event.widget;
System.out.println(item.getText() + " is selected");
if( (item.getStyle() & SWT.RADIO) != 0 || (item.getStyle() & SWT.CHECK) != 0 )
System.out.println("Selection status: " + item.getSelection());
}
};
itemPush.addListener(SWT.Selection, selectionListener);
itemCheck.addListener(SWT.Selection, selectionListener);
itemRadio1.addListener(SWT.Selection, selectionListener);
itemRadio2.addListener(SWT.Selection, selectionListener);
itemDropDown.addListener(SWT.Selection, selectionListener);
toolBar.pack();
toolBar.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,false));
ToolBarManager tbm=new ToolBarManager(toolBar);
System.out.println(tbm.getControl().getChildren().length);
DefaultInformationControl dic=new DefaultInformationControl(parent, tbm);
dic.setBackgroundColor(new Color(null, 98,201,145));
return dic;
}
};
}
.
.
.
}
The only example of using the tool bar that I can see in the Eclipse core code does things this way:
private static final class PresenterControlCreator extends AbstractReusableInformationControlCreator {
#Override
public IInformationControl doCreateInformationControl(Shell parent) {
ToolBarManager tbm= new ToolBarManager(SWT.FLAT);
NLSHoverControl iControl= new NLSHoverControl(parent, tbm);
OpenPropertiesFileAction openPropertiesFileAction= new OpenPropertiesFileAction(iControl);
tbm.add(openPropertiesFileAction);
tbm.update(true);
return iControl;
}
}
NLSHoverControl extends DefaultInformationControl.
So it is adding to the tool bar after creating the DefaultInformationControl and using actions rather than tool items.
static class NLSHoverControl extends DefaultInformationControl implements IInformationControlExtension2 {
/**
* The NLS control input.
*/
private NLSHoverControlInput fInput;
/**
* Creates a resizable NLS hover control with the given shell as parent.
*
* #param parent the parent shell
* #param tbm the toolbar manager or <code>null</code> if toolbar is not desired
*/
public NLSHoverControl(Shell parent, ToolBarManager tbm) {
super(parent, tbm);
}
/**
* Creates an NLS hover control with the given shell as parent.
*
* #param parent the parent shell
* #param tooltipAffordanceString the text to be used in the status field or
* <code>null</code> to hide the status field
*/
public NLSHoverControl(Shell parent, String tooltipAffordanceString) {
super(parent, tooltipAffordanceString);
}
/**
* {#inheritDoc} This control can handle {#link NLSStringHover.NLSHoverControlInput}.
*/
public void setInput(Object input) {
Assert.isLegal(input instanceof NLSHoverControlInput);
NLSHoverControlInput info= (NLSHoverControlInput)input;
setInformation(info.fInformation);
fInput= info;
}
/**
* Returns the control input.
*
* #return the control input
*/
public NLSHoverControlInput getInput() {
return fInput;
}
}

how can i read class properties (members) in lexicographic order on java?

im trying to build input dialog using swt.
i want to read my class properties and make the dialog window on specified order or even lexicographic order. i'll keep my class properties in linkedhahmap\treemap.
example:
public class MazeProperties {
/** Maze Name. */
private String MazeName;
/** Number of rows in maze. */
private int x;
/** The Floors. */
private int y;
/** Number of columns in maze. */
private int z;
public MazeProperties(String mazeName, int rows, int floors, int columns) {
MazeName = mazeName;
Rows = rows;
Floors = floors;
Columns = columns;
}
public class ClassInputDialog extends Dialog{
/** The shell. */
Shell shell;
/** the generic class. */
private Class<?> template;
/** Property Descriptors give me the ability to see what properties the class contains - and has generic functionalities for setters and getters for fields!. */
PropertyDescriptor[] descs;
/** I wanna have a robust connection between a property to a text box - that way upon pressing OK I could know what class property was written in it.
*
*/
HashMap<PropertyDescriptor,Text> txtMap=new LinkedHashMap<PropertyDescriptor,Text>();
//TreeMap<String,Text> txtMapOrderName=new TreeMap<String,Text>();
//Map<PropertyDescriptor, Text> txtMap = Collections.synchronizedMap(new LinkedHashMap<PropertyDescriptor, Text>());
/** The bonus demanded that this dialog will support all given classes
* but what happens when a class has an enum? a whole new story with combo-boxes and once again I wanna have a connection between the class field enum to the String that was selected in the form.
*
*/
HashMap<PropertyDescriptor,String> enumMap=new **HashMap<PropertyDescriptor,String>();**
/** This is the reference of the instance I will return.
*
*/
private Object input;
/** Ct'r for people that don't know a thing about SWT.
* #param parent - Shell
* #param template - The Class to create form to
*/
public ClassInputDialog(Shell parent,Class<?> template) {
this(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL,template);
}
/**
* Ct'r with SWT style.
*
* #param parent - Shell
* #param style - SWT style
* #param template - The Class to create form to
*/
public ClassInputDialog(Shell parent, int style,Class<?> template) {
super(parent, style);
this.template=template;
descs=PropertyUtils.getPropertyDescriptors(template);
setText("Set Properties");
}
/**
* Gets the input.
*
* #return the input
*/
public Object getInput() {
return input;
}
/**
* Sets the input.
*
* #param input the new input
*/
public void setInput(Object input) {
this.input = input;
}
/** Here the window layout is set and the main loop event happens. When window closes User's input is returned.
* #return The user's input
*/
public Object open() {
this.shell = new Shell(getParent(), getStyle());
shell.setText(getText());
createContents(shell);
shell.pack();
shell.open();
Display display = getParent().getDisplay();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
//display.dispose();
return input;
}
/** Creates Window content and layout - sets Labels, Text boxes and combo boxes nicely.
* #param shell - window's parent
*/
private void createContents(final Shell shell) {
shell.setLayout(new GridLayout(2, true));
for(**PropertyDescriptor propDesc: descs**)
if(!propDesc.getName().equals("class"))
{
if(!propDesc.getPropertyType().isEnum())
{
Label label = new Label(shell, SWT.NONE);
label.setText(propDesc.getName());
GridData data = new GridData();
data.horizontalSpan = 2;
label.setLayoutData(data);
final Text text = new Text(shell, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
text.setLayoutData(data);
txtMap.put(propDesc, text);
// txtMapOrderName.put(propDesc.getDisplayName(), text);
System.out.println(propDesc.getDisplayName());
}
else
{
Label label = new Label(shell, SWT.NONE);
label.setText(propDesc.getName());
GridData data = new GridData();
data.horizontalSpan = 2;
label.setLayoutData(data);
final Combo combo = new Combo(shell, SWT.DROP_DOWN);
String[] toCombo=new String[propDesc.getPropertyType().getEnumConstants().length];
for(int i=0;i<propDesc.getPropertyType().getEnumConstants().length;i++)
toCombo[i]=propDesc.getPropertyType().getEnumConstants()[i].toString();
combo.setItems(toCombo);
data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
combo.setLayoutData(data);
combo.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent arg0) {
enumMap.put(propDesc, combo.getText());
}
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
}
});
}
}
the output is not as the class properties order, it's something like
y
mazeName
x
z
If you want to map keys to values in a deterministic, predictable order, you should store them in a TreeMap, taking care that the key class implements Comparator. If it doesn't, you must implement your own Comparator and pass it as a parameter to the TreeMap constructor.
In your case, if you want PropertyDescriptor as key, you must implement your own Comparator to compare PropertyDescriptor objects.

how to shake a login dialog in javaFX/8

How do I make my javaFX/8 dialog box shake more elegantly whenever a user input a wrong login name/password pair?.
Since the dialog in java8u40 does NOT have one, I set out to make one it myself. However, it doesn't look good enough.
What's wrong with it? Can someone help? Is there a better way in doing it?
public void loginDialog() {
// Create the custom dialog.
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle("Mars Simulation Project");
dialog.setHeaderText("Log in");
dialog.setContentText("Enter your username and password : ");
dialog.initModality(Modality.NONE);
// Set the button types.
ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
// Create the username and password labels and fields.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
TextField tfPlayer = new TextField();
tfPlayer.setPromptText("e.g. m03j");
PasswordField tfPassword = new PasswordField();
tfPassword.setPromptText("xxxx");
Button defaultPWB = new Button("Use Default");
Button guestB = new Button("As Guest");
defaultPWB.setOnAction(event -> {
tfPassword.setText("msp0");
} );
guestB.setOnAction(event -> {
tfPlayer.setText("Guest_");
tfPassword.setText("msp0");
} );
grid.add(new Label("Player Name :"), 0, 0);
grid.add(tfPlayer, 1, 0);
grid.add(guestB, 2, 0);
grid.add(new Label("Password :"), 0, 1);
grid.add(tfPassword, 1, 1);
grid.add(defaultPWB, 2, 1);
// Enable/Disable login button depending on whether a username was entered.
Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
loginButton.setDisable(true);
// Do some validation (using the Java 8 lambda syntax).
tfPlayer.textProperty().addListener((observable, oldValue, newValue) -> {
loginButton.setDisable(newValue.trim().isEmpty());
} );
dialog.getDialogPane().setContent(grid);
// Request focus on the player name field by default.
Platform.runLater(() -> tfPlayer.requestFocus());
// Convert the result to a player name /host address pair when the login
// button is clicked.
dialog.setResultConverter(dialogButton -> {
if (dialogButton == loginButtonType) {
return new Pair<>(tfPlayer.getText(), tfPassword.getText());
}
return null;
} );
Optional<Pair<String, String>> result = dialog.showAndWait();
result.ifPresent(input -> {
playerName = tfPlayer.getText();
logger.info("Player " + input.getKey() + " connecting to server at " + serverAddressStr);
try {
dialog.show();
makeContact(serverAddressStr);
// obtain a client id
boolean isSuccessful = sendRegister();
if (isSuccessful) {
dialog.close();
// establish chat...
} else {
// shake the dialog or send an alert to inform the user the
// player name is NOT valid
DialogEarthquakeCenter dec = new DialogEarthquakeCenter(dialog);
dec.startTimer();
try {
System.out.println("start sleeping ");
Thread.sleep(2000);
System.out.println("done sleeping ");
}
catch (InterruptedException e) {}
loginDialog();
}
} catch (Exception e) {
e.printStackTrace();
}
} );
So far, my problem is that as soon as I hit the button "login", the dialog will close by default.
Therefore I have to use dialog.show() to make it show up again.
[edit] This, however, still cannot prevent the momentary gap from happening (seeing the dialog disappear and reappear).
After that, I create an instance of DialogEarthquakeCenter in order to shake the dialog.
Note that my DialogEarthquakeCenter below is a direct modification of this original :
https://github.com/gigiigig/Java-Chat/blob/master/tag/FacebookChatCore_Original/src/facebookchat/ui/common/DialogEarthquakeCenter.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.scene.control.Dialog;
import javafx.util.Duration;
import javafx.util.Pair;
public class DialogEarthquakeCenter {
public static final int SHAKE_DISTANCE = 10;
public static final double SHAKE_CYCLE = 50;
public static final int SHAKE_DURATION = 500;
public static final int SHAKE_UPDATE = 5;
private Dialog<Pair<String, String>> dialog;
private int x, y;
private long startTime;
private Timer shakeTimer;
private final double TWO_PI = Math.PI * 2.0;
private Timeline timeline;
public DialogEarthquakeCenter(Dialog<Pair<String, String>> parent) {
dialog = parent;
}
/**
* Creates and starts the timer
*
* #return Scene
*/
public void startTimer() {
x = (int) dialog.getX();
y = (int) dialog.getY();
startTime = System.currentTimeMillis();
// Set up earth time text update
timeline = new Timeline(new KeyFrame(Duration.millis(SHAKE_DURATION), ae -> startNudging()));
//timeline.setCycleCount(javafx.animation.Animation.INDEFINITE);
timeline.play();
}
public void startNudging() {
x = (int) dialog.getX();
y = (int) dialog.getY();
startTime = System.currentTimeMillis();
shakeTimer = new Timer(SHAKE_UPDATE, new ActionListener() {
public void actionPerformed(ActionEvent e) {
shake();
}
});
shakeTimer.start();
}
public void shake() {
// calculate elapsed time
long elapsed = System.currentTimeMillis() - startTime;
//System.out.println("elapsed is " + elapsed);
// use sin to calculate an x-offset
double waveOffset = (elapsed % SHAKE_CYCLE) / SHAKE_CYCLE;
double angle = waveOffset * TWO_PI;
// offset the x-location by an amount
// proportional to the sine, up to shake_distance
int shakenX = (int) ((Math.sin(angle) * SHAKE_DISTANCE) + x);
Platform.runLater(() -> {
//dialog.hide();
dialog.setX(shakenX);
//System.out.println("set shakenX to " + shakenX);
dialog.setY(y);
dialog.show();
});
//try {Thread.sleep(20);}
//catch (InterruptedException ex) {}
// should we stop timer
if (elapsed >= SHAKE_DURATION) {
stopShake();
}
}
public void stopShake() {
shakeTimer.stop();
Platform.runLater(() -> {
timeline.stop();
dialog.close();
});
}
}
I did notice that controlsfx dialog has a shake() method.
Does anyone know if it works well ?
see https://code.google.com/p/mqtt-spy/source/browse/mqtt-spy/src/main/java/org/controlsfx/dialog/CustomDialogs.java?r=6ec0240e4e64d1b8cc2b59bc77cd5902a68e0c81
Thanks much for any comments!
There's a way you can add a transition once the user has click on the login button using the Dialog API, before the window is closed.
Using dialog.show() instead of dialog.showAndWait()`, the trick is just trapping the click action on the button, consume the event, and then perform the required logic.
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.show();
loginButton.addEventFilter(EventType.ROOT,
e->{
if(e.getEventType().equals(ActionEvent.ACTION)){
e.consume();
// (hardcoded) Login Validation
boolean isSuccessful = false;
if (isSuccessful) {
dialog.close();
}
else {
// perform animation and close the dialog (or any other action)
ShakeTransition anim = new ShakeTransition(dialog.getDialogPane(), t->dialog.close());
anim.playFromStart();
}
}
});
For the shake animation, I've modified ShakeTransition from Jasper Potts, in order to move the dialog window, as #jewelsea already pointed out:
/**
* Animate a shake effect on the given node
*
* Based on CachedTimelineTransition, a Transition that uses a Timeline internally
* and turns SPEED caching on for the animated node during the animation.
*
* https://github.com/fxexperience/code/blob/master/FXExperienceControls/src/com/fxexperience/javafx/animation/CachedTimelineTransition.java
*
* and ShakeTransition
*
* https://github.com/fxexperience/code/blob/master/FXExperienceControls/src/com/fxexperience/javafx/animation/ShakeTransition.java
*
* #author Jasper Potts
*/
class ShakeTransition extends Transition {
private final Interpolator WEB_EASE = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
private final Timeline timeline;
private final Node node;
private boolean oldCache = false;
private CacheHint oldCacheHint = CacheHint.DEFAULT;
private final boolean useCache=true;
private final double xIni;
private final DoubleProperty x = new SimpleDoubleProperty();
/**
* Create new ShakeTransition
*
* #param node The node to affect
*/
public ShakeTransition(final Node node, EventHandler<ActionEvent> event) {
this.node=node;
statusProperty().addListener((ov, t, newStatus) -> {
switch(newStatus) {
case RUNNING:
starting();
break;
default:
stopping();
break;
}
});
this.timeline= new Timeline(
new KeyFrame(Duration.millis(0), new KeyValue(x, 0, WEB_EASE)),
new KeyFrame(Duration.millis(100), new KeyValue(x, -10, WEB_EASE)),
new KeyFrame(Duration.millis(200), new KeyValue(x, 10, WEB_EASE)),
new KeyFrame(Duration.millis(300), new KeyValue(x, -10, WEB_EASE)),
new KeyFrame(Duration.millis(400), new KeyValue(x, 10, WEB_EASE)),
new KeyFrame(Duration.millis(500), new KeyValue(x, -10, WEB_EASE)),
new KeyFrame(Duration.millis(600), new KeyValue(x, 10, WEB_EASE)),
new KeyFrame(Duration.millis(700), new KeyValue(x, -10, WEB_EASE)),
new KeyFrame(Duration.millis(800), new KeyValue(x, 10, WEB_EASE)),
new KeyFrame(Duration.millis(900), new KeyValue(x, -10, WEB_EASE)),
new KeyFrame(Duration.millis(1000), new KeyValue(x, 0, WEB_EASE))
);
xIni=node.getScene().getWindow().getX();
x.addListener((ob,n,n1)->(node.getScene().getWindow()).setX(xIni+n1.doubleValue()));
setCycleDuration(Duration.seconds(1));
setDelay(Duration.seconds(0.2));
setOnFinished(event);
}
/**
* Called when the animation is starting
*/
protected final void starting() {
if (useCache) {
oldCache = node.isCache();
oldCacheHint = node.getCacheHint();
node.setCache(true);
node.setCacheHint(CacheHint.SPEED);
}
}
/**
* Called when the animation is stopping
*/
protected final void stopping() {
if (useCache) {
node.setCache(oldCache);
node.setCacheHint(oldCacheHint);
}
}
#Override
protected void interpolate(double d) {
timeline.playFrom(Duration.seconds(d));
timeline.stop();
}
}
And this will be a JavaFX application using your login dialog:
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Show Login Dialog");
btn.setOnAction(mevent -> {
// Create the custom dialog.
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle("Mars Simulation Project");
dialog.setHeaderText("Log in");
dialog.setContentText("Enter your username and password : ");
dialog.initModality(Modality.NONE);
// Set the button types.
ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
// Create the username and password labels and fields.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
TextField tfPlayer = new TextField();
tfPlayer.setPromptText("e.g. m03j");
PasswordField tfPassword = new PasswordField();
tfPassword.setPromptText("xxxx");
Button defaultPWB = new Button("Use Default");
Button guestB = new Button("As Guest");
defaultPWB.setOnAction(event -> {
tfPassword.setText("msp0");
} );
guestB.setOnAction(event -> {
tfPlayer.setText("Guest_");
tfPassword.setText("msp0");
} );
grid.add(new Label("Player Name :"), 0, 0);
grid.add(tfPlayer, 1, 0);
grid.add(guestB, 2, 0);
grid.add(new Label("Password :"), 0, 1);
grid.add(tfPassword, 1, 1);
grid.add(defaultPWB, 2, 1);
// Enable/Disable login button depending on whether a username was entered.
Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
loginButton.setDisable(true);
// Do some validation (using the Java 8 lambda syntax).
tfPlayer.textProperty().addListener((observable, oldValue, newValue) -> {
loginButton.setDisable(newValue.trim().isEmpty());
} );
dialog.getDialogPane().setContent(grid);
// Request focus on the player name field by default.
Platform.runLater(() -> tfPlayer.requestFocus());
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.show();
loginButton.addEventFilter(EventType.ROOT,
e->{
if(e.getEventType().equals(ActionEvent.ACTION)){
e.consume();
// (hardcoded) Login Validation
boolean isSuccessful = false;
if (isSuccessful) {
dialog.close();
}
else {
ShakeTransition anim = new ShakeTransition(dialog.getDialogPane(), t->dialog.close());
anim.playFromStart();
}
}
});
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Shaky Login Dialog");
primaryStage.setScene(scene);
primaryStage.show();
}

JMenuBar with drop-down list for hidden JMenu

Want to create a JMenuBar. If window-JFrame.width to small to show all JMenu of JMenuBar, a Button appears in JMenuBar and all hidden JMenu can chosen in a drop-down list. How can I realize it, please?
I'd look at JToolBar, illustrated here. You can use any required layout and most L&Fs allow the bar to become a floating window.
Use CardLayout to have a panel that contains both the normal menu, and a menu implemented with the button. Then add a ComponentListener (ComponentAdapter) to it and select the desired menu implementation in the listener's componentResized() method.
In code it would look roughly like this:
JMenuBar createCustomMenu() {
final CardLayout layout = new CardLayout();
final JMenuBar menu = new JMenuBar();
menu.setLayout(layout);
// Here you should create the normal, wide menu
JComponent normalMenu = createNormalMenu();
// Here you create the compressed, one button version
JComponent compressedMenu = createCompressedMenu();
menu.add(normalMenu, "normal");
menu.add(compressedMenu, "compressed");
menu.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
if (menu.getPreferredSize().getWidth() > menu.getWidth()) {
layout.show(menu, "compressed");
} else {
layout.show(menu, "normal");
}
}
});
return menu;
}
(edit: changed to return JMenuBar, since it seems to work just fine)
Here is some old code I was playing with 5 years ago. Its been so long I don't even remember how well the code works. It was designed for a JToolBar but it may give you some ideas on how to do this with a JMenuBar:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
*
* #author subanark
*/
public class PopupMenuLayout implements java.awt.LayoutManager
{
private JPopupMenu popupMenu = new JPopupMenu();
private JButton popupButton = new JButton(new PopupAction());
/** Creates a new instance of PopupMenuLayout */
public PopupMenuLayout()
{
}
/** If the layout manager uses a per-component string,
* adds the component <code>comp</code> to the layout,
* associating it
* with the string specified by <code>name</code>.
*
* #param name the string to be associated with the component
* #param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp)
{
}
/**
* Lays out the specified container.
* #param parent the container to be laid out
*/
public void layoutContainer(Container parent)
{
// Position all buttons in the container
Insets insets = parent.getInsets();
int x = insets.left;
int y = insets.top;
System.out.println("bottom: " + insets.bottom);
int spaceUsed = insets.right + insets.left;
for (int i = 0; i < parent.getComponentCount(); i++ )
{
Component aComponent = parent.getComponent(i);
aComponent.setSize(aComponent.getPreferredSize());
aComponent.setLocation(x,y);
int componentWidth = aComponent.getPreferredSize().width;
x += componentWidth;
spaceUsed += componentWidth;
}
// All the buttons won't fit, add extender button
// Note: the size of the extender button changes once it is added
// to the container. Add it here so correct width is used.
int parentWidth = parent.getSize().width;
if (spaceUsed > parentWidth)
{
popupMenu.removeAll();
parent.add(popupButton);
popupButton.setSize( popupButton.getPreferredSize() );
int popupX = parentWidth - insets.right - popupButton.getSize().width;
popupButton.setLocation(popupX, y );
spaceUsed += popupButton.getSize().width;
}
// Remove buttons that don't fit and add to the popup menu
// System.out.println(spaceUsed + " ::: " + parentWidth);
int lastVisibleButtonIndex = 1;
while (spaceUsed > parentWidth)
{
lastVisibleButtonIndex++;
int last = parent.getComponentCount() - lastVisibleButtonIndex;
Component component = parent.getComponent( last );
component.setVisible( false );
spaceUsed -= component.getSize().width;
addComponentToPopup(component);
// popupButton.setLocation( button.getLocation() );
// System.out.println(spaceUsed + " : " + parentWidth);
}
}
private void addComponentToPopup(Component component)
{
System.out.println(component.getClass());
if (component instanceof JButton)
{
JButton button = (JButton)component;
JMenuItem menuItem = new JMenuItem(button.getText());
menuItem.setIcon( button.getIcon() );
ActionListener[] listeners = button.getActionListeners();
for (int i = 0; i < listeners.length; i++)
menuItem.addActionListener( listeners[i] );
popupMenu.insert(menuItem, 0);
}
if (component instanceof JToolBar.Separator)
{
popupMenu.insert( new JSeparator(), 0);
}
}
/**
* Calculates the minimum size dimensions for the specified
* container, given the components it contains.
* #param parent the component to be laid out
* #see #preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent)
{
return popupButton.getMinimumSize();
}
/** Calculates the preferred size dimensions for the specified
* container, given the components it contains.
* #param parent the container to be laid out
*
* #see #minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent)
{
// Move all components to the container and remove the extender button
parent.remove(popupButton);
/*
while ( popupMenu.getComponentCount() > 0 )
{
Component aComponent = popupMenu.getComponent(0);
popupMenu.remove(aComponent);
parent.add(aComponent);
}
*/
// Calculate the width of all components in the container
Dimension d = new Dimension();
d.width += parent.getInsets().right + parent.getInsets().left;
for (int i = 0; i < parent.getComponents().length; i++)
{
Component component = parent.getComponent(i);
component.setVisible( true );
d.width += component.getPreferredSize().width;
d.height = Math.max(d.height, component.getPreferredSize().height);
}
// d.height += parent.getInsets().top + parent.getInsets().bottom + 5;
d.height += parent.getInsets().top + parent.getInsets().bottom;
return d;
}
/** Removes the specified component from the layout.
* #param comp the component to be removed
*/
public void removeLayoutComponent(Component comp)
{
}
protected class PopupAction extends AbstractAction
{
public PopupAction()
{
super(">>");
}
public void actionPerformed(ActionEvent e)
{
JComponent component = (JComponent)e.getSource();
popupMenu.show(component,0,component.getHeight());
}
}
public static void main(String[] argv)
{
ActionListener simpleAction = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand());
}
};
JToolBar toolBar = new JToolBar();
toolBar.setLayout(new PopupMenuLayout());
toolBar.add( createButton("one", simpleAction) );
toolBar.add( createButton("two", simpleAction) );
toolBar.add( createButton("three", simpleAction) );
toolBar.add( createButton("four", simpleAction) );
toolBar.add( createButton("five", simpleAction) );
toolBar.add( createButton("six", simpleAction) );
toolBar.addSeparator();
toolBar.add( createButton("seven", simpleAction) );
toolBar.add( createButton("eight", simpleAction) );
toolBar.addSeparator();
toolBar.add( createButton("nine", simpleAction) );
toolBar.add( createButton("ten", simpleAction) );
JFrame f = new JFrame();
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(toolBar,BorderLayout.NORTH);
f.setBounds(300,200,400,300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
private static JButton createButton(String text, ActionListener listener)
{
JButton button = new JButton(text);
button.addActionListener( listener );
return button;
}
}
In this case the toolbar button was converted to a JMenu when no space was available. In you case you already have a JMenu, so you should be able to juse move the JMenu from the JMenuBar to the popup menu. However you will need to change the code to always move the menus from the popup menu back to the menu bar before determining the preferred size of the menu bar.

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