Java close listener for ViewPart - java

I'm using eclipse RCP with a view and I want to print something on the console when the application is closed.
This is what I have done, but It's not working;
public void createPartControl(final Composite parent){
parent.getShell().addListener(SWT.CLOSE, new Listener() {
#Override
public void handleEvent(Event event) {
System.out.println("NOW !");
}
});
}
EDIT:
I found a solution, I needed to add a DisposeListener:
parent.addDisposeListener(new DisposeListener() {
#Override
public void widgetDisposed(DisposeEvent e) {
// TODO Auto-generated method stub
}
});

You want to use the SWT.Close event and not SWT.CLOSE. From the SWT Javadoc:
SWT.Close - The close event type (value is 21).
SWT.CLOSE - Style constant for close box trim (value is 1<<6, since we do not distinguish between CLOSE style and MENU style).

Related

Using SWT DateSpinner with RAP does not dispose calendar widget on focus lost

I am working on a project where I need to use the SWT DateSpinner on a RAP application webpage. I brought the entire Datespinner API into my project and have made changes to accommodate it in the application. I am trying to dispose the calendar widget when the user clicks anywhere on the page outside the bounds of the calendar dropdown.
To accomplish this I tried adding a focus listener to the widget and the actual date spinner but the onFocusLost() method is never executed whenever the datespinner or the calendar composite lose focus. I also tried to add a mouse event listener where I try to dispose the widget if the mouse down event occurs outside the calendar composite bounds but that doesn't get executed either. The showCalendar() method is as shown:
private void showCalendar()
{
if (calendarDropDown != null && !calendarDropDown.isDisposed())
{
calendarDropDown.dispose();
}
calendarDropDown = new DropDown(this);
calendarDropDown.setUsingRelativeControlWidth(false);
Composite composite = calendarDropDown.getDropDown();
composite.setLayout(new FillLayout());
composite.setData(calendarToggle);
Calendar c = Calendar.getInstance();
Date date = this.getDate();
// get current date in the control
if (date != null)
{
c.setTime(this.getDate());
}
CalendarComposite calendarWidget = new CalendarComposite(composite, c);
calendarWidget.setNoneEnabled(this.allowNullDate);
calendarWidget.setMinimumDate(dateToCalendar(getMinimum()));
calendarWidget.setMaximumDate(dateToCalendar(getMaximum()));
// background to match the calendar
composite.setBackground(calendarWidget.getBackground());
calendarDropDown.show(true, composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
text.addFocusListener(new FocusListener()
{
#Override
public void focusLost(FocusEvent event)
{
dispose();
}
#Override
public void focusGained(FocusEvent event)
{
// TODO Auto-generated method stub
}
});
calendarWidget.addMainCalendarListener(new CalendarListenerAdapter()
{
#Override
public void dateChanged(Calendar date)
{
doSetDate(date != null ? date.getTime() : null, false, true);
}
#Override
public void popupClosed()
{
calendarDropDown.dispose();
}
});
}
And the show method of the DropDown is
if ((autoHide && !dropDownShell.isVisible())){
dropDownShell.addMouseListener(new MouseListener()
{
#Override
public void mouseUp(MouseEvent e)
{
// TODO Auto-generated method stub
}
#Override
public void mouseDown(MouseEvent e)
{
if (!isInside(e.x, e.y, dropDownShell.getDisplay().getBounds()))
{
dispose();
}
}
#Override
public void mouseDoubleClick(MouseEvent e)
{
// TODO Auto-generated method stub
}
});
Please let me know what I can do to make the CalendarWidget dispose on losing focus.
I think that if the widget you focus is in another shell than the currently focused widget (your Text), you may not get a focusLost event because each shell can have it's own focused widget. What is actually happens is that the shell the Text is in gets deactivated, which you can be notified about using a ShellListener.

SWT/JFace: How to handle Keyevents for each ViewPart or Form?

I'm building an Eclipse application and I'm trying to make a shortcut for launching an action when pressing F5, and make that the default action when that Tab/ViewPart has the focus.
I have read that this is not possible, or very complex. Is there any simple/straight way of doing it?
I tried with:
Display.getCurrent().addFilter(...)
this.addKeyListener(new KeyAdapter() {...})
...
Making this in the constructor is my best:
this.getShell().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.keyCode == SWT.F5) {
//doAnything()
}
}
});
And this doesn't work when loaded, but if I switch from this to another View/Tab starts to work. But it works too when others have focus (which I don't want).
Is there anyway of making this work at the start, and only when the focus is in the View?
You should define work in a handler & then should use key bindings as given in this example. You can find a good example here. Hope it solves your need.
You should look at RetargetableActions. I think that's Eclipse way of doing it:
You need to look at extensions org.eclipse.ui.bindings and org.eclipse.ui.contexts.
Define a command and its handler
Define a binding for the command
define context (cxtId)
associate context with command so that command is available only when context is active
Activate context when you open the view or form.
If you get the listener of the events of the component it will listen on the events. And if the event occur for this component it will be notified.
To add listener of the key event on the ViewPart we should create the control which could be able listen on the event.
public class SampleView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "views.SampleView";
private Composite mycomposite;
public void createPartControl(Composite parent) {
mycomposite = new Composite(parent, SWT.FILL);
//then add listener
mycomposite.addKeyListener(keyListener);
}
private KeyListener keyListener = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
showMessage("key pressed: "+ e.keyCode);
}
};
//the rest of focusing and handle event
private void showMessage(String message) {
MessageDialog.openInformation(
mycomposite.getShell(),
"Sample View",
message);
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
mycomposite.setFocus();
}
}
//the end

How to catch first time displaying of the WizardPage

I'm writing a little wizard for Eclipse with some pages and I need to catch the moment of the first time page displaying.
I checked constructor and createControl but they are called in the creation moment in the Wizard object (addPages).
Is there a way to get what I need? Maybe somebody knows some trick?
You can override setVisible(boolean) method in your WizardPage. So for example use something like:
private boolean initialized = false;
#Override
public void setVisible(boolean visible) {
if (!initialized && visible) {
//do something
initialized = true;
}
control.setVisible(visible);
}
You can use a IPageChangedListener or a IpageChangingListener, registered on the WizardDialog. They will be notified when the current page of the wizard changes.
I prefer to remove the listener after first painting. That way you don't need an additional boolean field and you avoid unnecessary calling paintControl and checking that boolean every time.
container.addPaintListener(new PaintListener()
{
#Override
public void paintControl(PaintEvent e)
{
doUsefulStuff();
container.removePaintListener(this);
}
});
Ok, I created a listener for a paint event and used a flag m_isFirsTime, which controlled from Wizard class:
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
setControl(container);
container.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent arg0) {
if (m_isFirstTime) {
m_isFirstTime = false;
StartXMLParsing();
}
}
});
...
}
It is ok for me.
After controls created the async UI task executed where a long init operation can be performed. UI already created and shown when Runnable starts therefore wizard appears immediately and user can see initialization progress:
public void createControl(Composite parent) {
// create controls
getContainer().getShell().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
try {
getContainer().run(false, false, new IRunnableWithProgress() {
#Override
public void run(IProgressMonitor arg0) throws InvocationTargetException, InterruptedException {
// init and validate controls here
}
});
} catch (InvocationTargetException e) {
// handle e.getCause();
} catch (InterruptedException e) {
// nothing
}
}
});
}

SWT event propagation

I'm trying to detect click events on a Composite control that contains a number of other composites. I tried:
topComposite.addMouseListener(new MouseListener() {
...
#Override
public void mouseUp(MouseEvent arg0) {
logger.info("HERE");
});
});
But the event never fires. I assumed that when a mouse event occurred on a child it would propagate up the chain but that doesn't happen. How do I do this?
In SWT, the general rule is that events do not propagate. The main exception to this, is the propagation of traverse events - which is pretty complicated to describe.
The easy answer to your problem is that you must add the listener to all the children of you Composite - recursively!
E.g. like this
public void createPartControl(Composite parent) {
// Create view...
final MouseListener ma = new MouseAdapter() {
#Override
public void mouseDown(MouseEvent e) {
System.out.println("down in " + e.widget);
}
};
addMouseListener(parent, ma);
}
private void addMouseListener(Control c, MouseListener ma) {
c.addMouseListener(ma);
if (c instanceof Composite) {
for (final Control cc : ((Composite) c).getChildren()) {
addMouseListener(cc, ma);
}
}
}
The clicked-upon widget is found in e.widget as seen above. An important issue is to remember to do this again if you add more Controls later.

Java KeyListener not firing on JSpinner

have tried a few different approaches to this but with no success so far. Just wondered if I'm missing anything. I have a JSpinner which is a component of a DateSelector widget alongside a Calendar. I am trying to fire a validation method if the user changes any text in the JSpinner instead of using the Calendar control or the JSpinner up and down arrows.
Here are the different approaches I have tried:
jSpinner1.addKeyListener(kl);
jSpinner1.getEditor().addKeyListener(kl);
((JSpinner.DefaultEditor) jSpinner1.getEditor().getTextField().addKeyListener(kl);
Anyone out there got any ideas as to what I'm doing wrong? Thanks
UPDATE
Apologies, I should have said that I have already added a ChangeListener to the JSpinnerDateModel which is attached to the JSpinner. Like so:
ChangeListener changeListener = new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
dateChanged();
}
};
jSpinnerDateModel.addChangeListener(changeListener);
KeyListener keyListener = new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
dateChanged();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
};
((JSpinner.DefaultEditor) jSpinner1.getEditor()).getTextField().addKeyListener(
keyListener);
Thanks
Frank
If you want to disable keyboard editing do this:
JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
tf.setEditable(false);
To listen for key events you need to add a listener to the text field. This works for me:
((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().addKeyListener(new KeyListener(){
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("PRESSED!");
}
#Override
public void keyTyped(KeyEvent e) {
}
});
JSpinners handle KeyEvents themselves, but they fire ChangeEvents to the outside world. Adding a ChangeListener should allow you to perform the validation you wish.
See also: Detecting Spinner Value Changes (Java Tutorials)
This is a shortfall of swing, and in my opinion JSpinner should follow JComboBox in supplying the following access to the underlying text field:
JComboBox.getEditor().getEditorComponent()
From going through the source of J1.7 I found you can acheive pretty much the same thing with
JSpinner.getEditor().getComponent(0)
Therefore you can "hack" the listener in the following way:
JSpinner.getEditor().getComponent(0).addKeyListener(...)
Obviously this depends on the 'under the covers' implementation of swing and works as at J1.7 but there is no guarantee this works for other versions future or past.
Enjoy.
EDIT
or if the editor is an instance of DefaultEditor, you can cast it as such and use 'getTextField()'. It would be handy if this were defined in the interface.

Categories