I would like to be able to have it so that the Escape key doesn't close a JFace dialog pop up.
In the code I have prepared you can see this behaviour by running the main method, when you press escape.
public class TestDialog extends Dialog
{
private Label status;
private String title;
public TestDialog(Shell parentShell, String title)
{
super(parentShell);
this.title = title;
setShellStyle(getShellStyle() & ~SWT.CLOSE);
}
#Override
protected void configureShell(Shell shell)
{
super.configureShell(shell);
shell.setText(this.title);
}
#Override
protected Control createDialogArea(Composite parent)
{
Composite composite = (Composite) super.createDialogArea(parent);
composite.setLayout(new GridLayout(1, false));
status = new Label(composite, SWT.NONE);
status.setText("Hello World");
composite.pack();
parent.pack();
return composite;
}
#Override
protected Control createButtonBar(Composite parent)
{
return parent;
}
public static void main(String[] args) {
TestDialog d = new TestDialog(new Shell(), "Test");
d.open();
}
}
You can add a key listener to the parent Composite control and get the keyEvent to match with SWT.ESC and write your custom code there what you want to perform when ESC key is pressed. Now it will prevent the JFace dialog from closing.
#Override
protected Control createDialogArea(final Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
composite.setLayout(new GridLayout(1, false));
status = new Label(composite, SWT.NONE);
status.setText("Hello World");
composite.pack();
parent.pack();
composite.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
String string = "";
if (e.keyCode == SWT.ESC) {
string += "ESCAPE - keyCode = " + e.keyCode;
}
if (!string.isEmpty()) {
// do nothing
// here I am printing in console
System.out.println(string);
}
}
});
return composite;
}
Related
I have MyPreferencePage which extends PreferencePage. Inside the PreferencePage there is a method getApplyButton() I am overriding that method to get the apply button.
I need the apply button because there are some validators that I put on the data in the preference dialog and till the all the data is not correct I dont want the apply button to be enabled.
My code
public class DefaultColorsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
#Override
protected Control createContents(Composite parent) {
this.container = new Composite(parent, SWT.NONE);
this.container.setLayout(new GridLayout(1, false));
GridData gd_area = new GridData(SWT.FILL, SWT.FILL, true, true);
this.container.setLayoutData(gd_area);
this.defalutColoringGroup = new Group(container, SWT.NONE);
this.defalutColoringGroup.setLayout(new GridLayout(1, false));
this.defalutColoringGroup.setLayoutData(gd_area);
this.defalutColoringGroup.setText(Constants.DESCRIPTION_TEXT);
this.defaultColoringCheckBox = new Button(defalutColoringGroup, SWT.CHECK);
this.defaultColoringCheckBox.setText(Constants.DEFAULT_COLORING_BUTTON_TEXT);
errorLabel = new Label(defalutColoringGroup, SWT.NONE);
errorLabel.setText("Expression is not valid, enter a valid expression and try again!");
errorLabel.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
errorLabel.setVisible(false);
this.viewer = tableviewerComposite.createTableViewer(defalutColoringGroup);
this.viewer.setContentProvider(new ArrayContentProvider());
try {
contentProvider = new ContentProvider();
this.viewer.setInput(contentProvider.getScenarios());
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
return container;
}
#Override
protected Button getApplyButton() {
super.getApplyButton();
}
}
//Method to create columns of the table
private void createTableColumns(final TableViewer viewer,final Composite defalutColoringGroup) {
TableViewerColumn scenariosColumn = createTableViewerColumn(viewer,Constants.SCENARIOS_COLUMN_NAME,Constants.SCENARIOS_COLUMN_NUMBER);
ScenariosLabelProvider scenariosLabelProvider = new ScenariosLabelProvider();
scenariosColumn.setLabelProvider(scenariosLabelProvider);
scenariosColumn.setEditingSupport(new ScenariosEditingSupport(viewer));
//more columns
}
//Editing Support for column
public class ScenariosEditingSupport extends EditingSupport {
private final TableViewer viewer;
private final CellEditor editor;
private final DefaultColorsPreferencePage preferencePage;
public ScenariosEditingSupport(TableViewer viewer) {
super(viewer);
this.viewer = viewer;
this.editor = new TextCellEditor(viewer.getTable());
this.preferencePage = new DefaultColorsPreferencePage();
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
return ((Content) element).getExpression();
}
#Override
protected void setValue(Object element, Object changedExpression) {
String expression = String.valueOf(changedExpression);
if(Repository.isExpressionValid(expression)){
((Content) element).setExpression(expression);
viewer.update(element, null);
}
else{
preferencePage.setValid(false);
preferencePage.setErrorMessage("Expression is not valid, enter a valid expression and try again!");
((Content) element).setExpression(expression);
viewer.update(element, null);
}
}
}
You don't access the Apply button to enable / disable the preference page. Instead call the
setValid(false);
method of PreferencePage to disable Apply and OK.
Call setValid(true) when the page is OK.
You might also want to call the setErrorMessage or setMessage methods to set a message while the page is invalid.
I would like to modify the right click context menu for some some SWT Text boxes.
I would like to still have some of the default options like Copy, Cut, Paste, but would also like to have a custom action 'Generate Random' to fill the text box with a UUID.
How can I add such a menu to the control?
here's what I came up with to add some of the standard functions (cut, copy, paste, select all) as well as a custom action (generate UUID)
public static void addContextMenuWithUUID(final Text control)
{
Menu menu = new Menu(control);
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText("Cut");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.cut();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Copy");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.copy();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Paste");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.paste();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Select All");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.selectAll();
}
});
item = new MenuItem(menu, SWT.PUSH);
item.setText("Generate UUID");
item.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event event)
{
control.setText(UUID.randomUUID().toString());
}
});
control.setMenu(menu);
}
When I had to do something similar a while ago, this is what I did,
I adopted the TextActionHandler class provided by eclipse and modified the code to suit my needs.
public final class TextActionHandler {
enum TextAction {
CUT (WorkbenchMessages.Workbench_cut, IWorkbenchCommandConstants.EDIT_CUT),
COPY (WorkbenchMessages.Workbench_copy, IWorkbenchCommandConstants.EDIT_COPY),
PASTE (WorkbenchMessages.Workbench_paste, IWorkbenchCommandConstants.EDIT_PASTE),
DELETE (WorkbenchMessages.Workbench_delete, null),
SELECT_ALL(WorkbenchMessages.Workbench_selectAll, WorkbenchCommandConstants.EDIT_SELECT_ALL);
private String text;
private String commandId;
private TextAction(String text, String commandId ) {
this.text = text;
this.commandId = commandId;
}
public String getCommandId() {
return commandId;
}
public String getText() {
return text;
}
}
public TextActionHandler(Text text) {
addText(text);
}
public TextActionHandler() {
super();
}
public void addText(Text textControl) {
if (textControl == null) {
return;
}
textControl.addDisposeListener(new DisposeListener() {
#Override
public void widgetDisposed(DisposeEvent e) {
removeText(activeTextControl);
}
});
textControl.addListener(SWT.Activate, textControlListener);
textControl.addListener(SWT.Deactivate, textControlListener);
textControl.addKeyListener(keyAdapter);
textControl.addMouseListener(mouseAdapter);
activeTextControl = textControl;
updateActionsEnableState();
}
public void hookContextMenu() {
final MenuManager menuMgr = new MenuManager("#PMPopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
addContextMenuOptions(menuMgr);
}
});
Menu menu = menuMgr.createContextMenu(activeTextControl);
activeTextControl.setMenu(menu);
}
private void addContextMenuOptions(MenuManager manager) {
manager.removeAll();
manager.add(textCutAction);
manager.add(textCopyAction);
manager.add(textPasteAction);
manager.add(textDeleteAction);
manager.add(new Separator());
manager.add(textSelectAllAction);
// add your own action handlers here
}
...
// example.
private final class CutActionHandler extends Action {
private CutActionHandler() {
setProperties(this, TextAction.CUT);
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.cut();
updateActionsEnableState();
}
}
#Override
public boolean isEnabled() {
return activeTextControl != null && !activeTextControl.isDisposed()
&& activeTextControl.getEditable()
&& activeTextControl.getSelectionCount() > 0;
}
public void updateEnabledState() {
setEnabled(isEnabled());
}
}
private void setProperties(Action action, TextAction actionEnum){
action.setText(actionEnum.getText());
action.setActionDefinitionId(actionEnum.getCommandId());
action.setImageDescriptor(getImageDescriptor(actionEnum));
action.setDisabledImageDescriptor(getDisabledImageDescriptor(actionEnum));
}
}
Likewise, you can have your own ActionHandlers added. e.g, RandomGeneratorHandler.
To hook this to your textboxes, do
Text text = new Text(parent, SWT.NONE);
...
TextActionHandler handler = new TextActionHandler();
handler.addText(text);
handler.hookContextMenu();
Note - I have not provided the complete class here, for other actions like copy, paste, delete and select all etc, you will have to do something similar as Cut. I have used the same code defined in the TextActionHandler class.
i created a Dialog with two input fields with the following Code.
public class CCIDDialog extends TitleAreaDialog {
private Text ccidText;
private Text descriptionText;
private String CCID;
private String description;
public CCIDDialog(Shell parentShell) {
super(parentShell);
}
public void create() {
super.create();
setTitle(_title);
setMessage("Bitte geben Sie die CCID "+firstchar+"xxxxxxx und eine Beschreibung ein (max. 7-stellig): ", IMessageProvider.INFORMATION); }
#Override
protected Control createDialogArea(Composite parent) {
Composite area = (Composite) super.createDialogArea(parent);
Composite container = new Composite(area, SWT.NONE);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout(2, false);
container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
container.setLayout(layout);
createCCID(container);
createDescription(container);
return area;
}
private void createCCID(Composite container) {
Label lbtFirstName = new Label(container, SWT.NONE);
lbtFirstName.setText("CCID (ohne "+firstchar+"): ");
GridData dataCCID = new GridData();
dataCCID.grabExcessHorizontalSpace = true;
dataCCID.horizontalAlignment = GridData.FILL;
ccidText = new Text(container, SWT.BORDER);
ccidText.setLayoutData(dataCCID);
}
private void createDescription(Composite container) {
Label lbtLastName = new Label(container, SWT.NONE);
lbtLastName.setText("Beschreibung: ");
GridData dataDescription = new GridData();
dataDescription.grabExcessHorizontalSpace = true;
dataDescription.horizontalAlignment = GridData.FILL;
descriptionText = new Text(container, SWT.BORDER);
descriptionText.setLayoutData(dataDescription);
}
#Override
protected boolean isResizable() {
return true;
}
// save content of the Text fields because they get disposed
// as soon as the Dialog closes
private void saveInput() {
CCID = ccidText.getText();
description = descriptionText.getText();
}
#Override
protected void okPressed() {
saveInput();
super.okPressed();
}
public String getCCID() {
return CCID;
}
public String getDescription() {
return description;
}
}
Is there a way to validate the ccidtext?
If the user type more then 7 chars, he must get a notification and should not be able to continue the dialog. I read so lot at the internet but can`t find a solution for this problem.
Thank u so much for your help.
JonasInt
You can use Text.addModifyListener to add a ModifyListener which will be called each time the text is changed. You can also use Text.addVerifyListener to add VerifyListener which can actually prevent text being entered.
For TitleAreaDialog you can call setMessage or setErrorMessage to display a message in the title area.
You can disable the OK button on the dialog using:
getButton(IDialogConstants.OK_ID).setEnabled(false);
Note: getButton(xxx) can return null if you call it too early in the dialog construction. Buttons are created during the createContents method after the createDialogArea method has been called.
So you can access the buttons by overriding createContents like this:
#Override
protected Control createContents(final Composite parent)
{
Control control = super.createContents(parent);
// TODO access buttons here
return control;
}
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 ...
I have subclassed org.eclipse.swt.widgets.Composite to create a new composite control. I want to capture MouseEnter and MouseExit events in this control but the problem I have is that when the mouse is hovered over a component in the control (say, a Label) the MouseExit event is fired, even though the label is part of the whole Composite.
Is there any way to stop this event being fired? I only want to see the event if the mouse leaves the total boundary of the control. Here is some example code to show you what I mean.
public class MyControl extends Composite{
Label label;
public MyControl(Composite parent, String label) {
super(parent, SWT.NONE);
label = new Label(this,0);
label.setText(label);
this.addListener(SWT.MouseEnter, new Listener() {
#Override
public void handleEvent(Event event) {
// handle this event
}
});
this.addListener(SWT.MouseExit, new Listener() {
#Override
public void handleEvent(Event event) {
// handle this event
}
});
}
}
You can simply put an logic in your event handler to see if the control is a child of your new control and ignore it. Something like the following: (I haven't tested the code, but I think this should work for you)
this.addListener(SWT.MouseExit, new Listener() {
#Override
public void handleEvent(Event event) {
for (Control control : ParentClass.this.getChildren()) {
if (control == event.item)
return;
}
// handler logic goes here
}
});
I solved the same problem (MouseExit is sent to a Composite when the mouse enters one of its children) with an event filter. Here's the code.
public class MouseTracker implements Listener {
static MouseTracker instance;
private static class Item {
Composite composite;
boolean inside;
MouseTrackListener listener;
}
private List<Item> listeners = new ArrayList<>();
private MouseTracker() {
}
public static MouseTracker getInstance() {
if (instance == null)
instance = new MouseTracker();
return instance;
}
private void install() {
Display.getCurrent().addFilter(SWT.MouseEnter, this);
Display.getCurrent().addFilter(SWT.MouseExit, this);
Display.getCurrent().addFilter(SWT.Resize, this);
}
private void uninstall() {
Display.getCurrent().removeFilter(SWT.MouseEnter, this);
Display.getCurrent().removeFilter(SWT.MouseExit, this);
Display.getCurrent().removeFilter(SWT.Resize, this);
}
public void addMouseTrackListener(Composite c, MouseTrackListener listener) {
if (listeners.isEmpty())
install();
Item i = new Item();
i.composite = c;
i.inside = false;
i.listener = listener;
listeners.add(i);
}
public void removeMouseTrackListener(Composite c, MouseTrackListener listener) {
listeners.removeIf((i) -> i.composite == c && i.listener == listener);
if (listeners.isEmpty())
uninstall();
}
public void handleEvent(Event e) {
boolean hasDisposed = false;
for (Item i : listeners) {
Composite c = i.composite;
if (c.isDisposed())
hasDisposed = true;
else {
Point p = Display.getCurrent().getCursorLocation();
boolean containsMouse = c.getBounds().contains(c.getParent().toControl(p));
if (i.inside != containsMouse) {
i.inside = containsMouse;
if (containsMouse)
i.listener.mouseEnter(new MouseEvent(e));
else
i.listener.mouseExit(new MouseEvent(e));
}
}
}
if (hasDisposed) {
listeners.removeIf((i) -> i.composite.isDisposed());
if (listeners.isEmpty())
uninstall();
}
}
}