6

How do I remove all listener from a SWT StyledText if I'm missing the instances? I tried to use the StyledText.getListeners(int) method to get all the instances, being able to remove them afterwards. But it's exhausting to find all the required int values. Is this the most straightforward way? Thank you!

Here is my temporary solution:

public void removeAllListener(StyledText st) {
    int[] eventTypes = { 3007, 3011, SWT.Resize, SWT.Move, SWT.Dispose,
            SWT.DragDetect, 3000, SWT.FocusIn, SWT.FocusOut, SWT.Gesture,
            SWT.Help, SWT.KeyUp, SWT.KeyDown, 3001, 3002, SWT.MenuDetect,
            SWT.Modify, SWT.MouseDown, SWT.MouseUp, SWT.MouseDoubleClick,
            SWT.MouseMove, SWT.MouseEnter, SWT.MouseExit, SWT.MouseHover,
            SWT.MouseWheel, SWT.Paint, 3008, SWT.Selection, SWT.Touch,
            SWT.Traverse, 3005, SWT.Verify, 3009, 3010 };

    for (int eventType : eventTypes) {
        Listener[] listeners = st.getListeners(eventType);
        for (Listener listener : listeners) {
            st.removeListener(eventType, listener);
        }
    }
}

I had to copy some of the values since they are part of StyledText class declared with the default modifier. So I cannot access them.

I hope, I didn't miss any int values ;)

Florent
  • 12,310
  • 10
  • 49
  • 58
kon
  • 3,732
  • 3
  • 26
  • 34

1 Answers1

4

In general, there is no mechanism to do this. However, I managed to get it working by subclassing StyledText. The new class is called StyledTextWithListeners. You can just rename it if you want ;) . However, you will have to use

styledText.addListenerByUser(int eventType, Listener listener);

to add you Listeners rather than

styledText.addListener(int eventTyle, Listener listener);

This is necessary to discriminate between Listeners added by you and those added by SWT upon creation.

To remove all listeners added by the user (you) just call

styledText.removeAllListeners();

Here is the code:

import java.util.HashMap;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class MiniExample {

    public static void main(String[] args) {
        Display display = Display.getDefault();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(1, false));

        StyledTextWithListeners text = new StyledTextWithListeners(shell, SWT.BORDER);

        text.setText("TEXT");

        text.addListenerByUser(SWT.Verify, new Listener() {

            @Override
            public void handleEvent(Event arg0) {

            }
        });

        text.removeAllListeners();

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
    }

    public static class StyledTextWithListeners extends StyledText
    {
        HashMap<Integer, Listener> listeners;
        public StyledTextWithListeners(Composite parent, int style) {
            super(parent, style);
        }

        public void addListenerByUser(int eventType, Listener listener)
        {
            addListener(eventType, listener);
            System.out.println("Adding: " + listener.getClass().toString());

            if(listeners == null)
                listeners = new HashMap<Integer, Listener>();

            listeners.put(eventType, listener);
        }

        public void removeAllListeners()
        {
            for(Integer type : listeners.keySet())
            {
                System.out.println("Removing: " + listeners.get(type).getClass().toString());
                removeListener(type.intValue(), listeners.get(type));
            }
            listeners = new HashMap<Integer, Listener>();
        }
    }
}

It basically saves all the Listeners you add in a HashMap and removes them when you call removeAllListeners.

Keep in mind that I didn't take care of the case where you add a second Listener with the same eventType to the StyledText as done before. In this case, the old Listener will be replaced in the HashMap, but not removed from the StyledText. If this case can occur in your scenario, just add some code yourself.

Baz
  • 36,440
  • 11
  • 68
  • 94
  • When I try to do the same thing with `Text`, I get an SWTException saying that subclassing is not allowed (Eclipse 3.6) but I don't when using a `StyledText`. Why? How do I overcome this? Also, will they perhaps one day throw the same exception when trying to subclass StyledText, making this impossible? – MrMas Jun 05 '13 at 19:53
  • 1
    I got around the SubClassing exception by adding this method: protected void checkSubclass(){ } – Dinis Cruz Dec 10 '13 at 13:34
  • @DinisCruz Yes, it is possible to subclass these widgets, however it is [not recommended](http://stackoverflow.com/questions/4264983/why-is-subclassing-not-allowed-for-many-of-the-swt-controls). I wouldn't suggest this answer anymore, but rather to wrap the `StyledText` in another class and handle adding/removing `Listener`s there. – Baz Dec 10 '13 at 14:15
  • @MrMas That is because of the reason explained [here](http://stackoverflow.com/questions/4264983/why-is-subclassing-not-allowed-for-many-of-the-swt-controls). I wouldn't suggest this answer anymore, but rather to wrap the `StyledText` in another class and handle adding/removing `Listener`s there. – Baz Dec 10 '13 at 14:15
  • I extend SWT Widgets all the time to add new methods! No problem with that. – marcolopes May 31 '23 at 22:00