Skip to content

Commit

Permalink
Add API to add and obtain typed listeners to/from Widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell committed Mar 15, 2024
1 parent 7479681 commit c52bb34
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.swt.widgets;

import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.internal.*;
Expand Down Expand Up @@ -439,11 +441,11 @@ boolean resignFirstResponder (long id, long sel) {
}

/**
* Adds the listener to the collection of listeners who will
* Adds the listener to the collection of {@link Listener listeners} who will
* be notified when an event of the given type occurs. When the
* event does occur in the widget, the listener is notified by
* sending it the <code>handleEvent()</code> message. The event
* type is one of the event constants defined in class <code>SWT</code>.
* type is one of the event constants defined in class {@link SWTError}.
*
* @param eventType the type of event to listen for
* @param listener the listener which should be notified when the event occurs
Expand All @@ -456,8 +458,6 @@ boolean resignFirstResponder (long id, long sel) {
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @see Listener
* @see SWT
* @see #getListeners(int)
* @see #removeListener(int, Listener)
* @see #notifyListeners
Expand All @@ -468,6 +468,43 @@ public void addListener (int eventType, Listener listener) {
_addListener (eventType, listener);
}

/**
* Adds the {@link EventListener typed listener} to the collection of listeners
* who will be notified when an event of the given types occurs.
* When the event does occur in the widget, the listener is notified
* by calling the type's handling methods.
* The event type is one of the event constants defined in class {@link SWT}
* and must correspond to the listeners type.
* If for example a {@link SelectionListener} is passed the {@code eventTypes}
* can be {@link SWT#Selection} or {@link SWT#DefaultSelection}.
*
* @param listener the listener which should be notified when the event occurs
* @param eventTypes the types of event to listen for
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @see #getTypedListeners(int)
* @see #removeTypedListener(int, EventListener)
* @see #notifyListeners
* @since 3.126
*/
protected void addTypedListener (EventListener listener, int... eventTypes) {
checkWidget();
if (listener == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
TypedListener typedListener = new TypedListener(listener);
for (int eventType : eventTypes) {
_addListener(eventType, typedListener);
}
}

void _addListener (int eventType, Listener listener) {
if (eventTable == null) eventTable = new EventTable ();
eventTable.hook (eventType, listener);
Expand Down Expand Up @@ -948,9 +985,9 @@ boolean getDrawing () {
}

/**
* Returns an array of listeners who will be notified when an event
* Returns an array of {@link Listener listeners} who will be notified when an event
* of the given type occurs. The event type is one of the event constants
* defined in class <code>SWT</code>.
* defined in class {@link SWT}.
*
* @param eventType the type of event to listen for
* @return an array of listeners that will be notified when the event occurs
Expand All @@ -960,8 +997,6 @@ boolean getDrawing () {
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @see Listener
* @see SWT
* @see #addListener(int, Listener)
* @see #removeListener(int, Listener)
* @see #notifyListeners
Expand All @@ -974,6 +1009,31 @@ public Listener[] getListeners (int eventType) {
return eventTable.getListeners(eventType);
}

/**
* Returns an array of typed listeners who will be notified when an event of the given type occurs.
* The event type is one of the event constants defined in class {@link SWT} and the returned listeners correspond to that type.
* If for example the {@code eventType} is {@link SWT#Selection} the returned listeners are of type {@link SelectionListener}.
*
* @param eventType the type of event to listen for
* @return an array of typed listeners that will be notified when the event occurs
*
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @see #addTypedListener(EventListener, int...)
* @see #removeTypedListener(int, EventListener)
* @see #notifyListeners
*
* @since 3.126
*/
public EventListener[] getTypedListeners (int eventType) {
return Arrays.stream(getListeners(eventType)) //
.filter(TypedListener.class::isInstance).map(l -> ((TypedListener) l).eventListener)
.toArray(EventListener[]::new);
}

String getName () {
String string = getClass ().getName ();
int index = string.lastIndexOf ('.');
Expand Down Expand Up @@ -1463,11 +1523,42 @@ public void removeListener (int eventType, Listener listener) {
* @noreference This method is not intended to be referenced by clients.
* @nooverride This method is not intended to be re-implemented or extended by clients.
*/
protected void removeListener (int eventType, SWTEventListener handler) {
protected void removeListener (int eventType, SWTEventListener listener) {
removeTypedListener(eventType, listener);
}

/**
* Removes the listener from the collection of listeners who will
* be notified when an event of the given type occurs.
* <p>
* <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
* public API. It is marked public only so that it can be shared
* within the packages provided by SWT. It should never be
* referenced from application code.
* </p>
*
* @param eventType the type of event to listen for
* @param listener the listener which should no longer be notified
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @see Listener
* @see #addListener
*
* @noreference This method is not intended to be referenced by clients.
* @nooverride This method is not intended to be re-implemented or extended by clients.
*/
protected void removeTypedListener (int eventType, EventListener listener) {
checkWidget();
if (handler == null) error (SWT.ERROR_NULL_ARGUMENT);
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
if (eventTable == null) return;
eventTable.unhook (eventType, handler);
eventTable.unhook (eventType, listener);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -14,6 +14,8 @@
package org.eclipse.swt.widgets;


import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;

Expand Down Expand Up @@ -145,12 +147,12 @@ public void unhook (int eventType, Listener listener) {
}
}

public void unhook (int eventType, SWTEventListener listener) {
public void unhook (int eventType, EventListener listener) {
if (types == null) return;
for (int i=0; i<types.length; i++) {
if (types [i] == eventType) {
if (listeners [i] instanceof TypedListener typedListener) {
if (typedListener.getEventListener () == listener) {
if (typedListener.eventListener == listener) {
remove (i);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
package org.eclipse.swt.widgets;


import org.eclipse.swt.internal.SWTEventListener;
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.internal.*;

/**
* Instances of this class are <em>internal SWT implementation</em>
Expand All @@ -40,7 +42,7 @@ public class TypedListener implements Listener {
/**
* The receiver's event listener
*/
protected SWTEventListener eventListener;
protected EventListener eventListener;

/**
* Constructs a new instance of this class for the given event listener.
Expand All @@ -59,6 +61,10 @@ public TypedListener (SWTEventListener listener) {
eventListener = listener;
}

TypedListener (EventListener listener) {
eventListener = listener;
}

/**
* Returns the receiver's event listener.
* <p>
Expand All @@ -73,7 +79,11 @@ public TypedListener (SWTEventListener listener) {
* @noreference This method is not intended to be referenced by clients.
*/
public SWTEventListener getEventListener () {
return eventListener;
// At the moment all typed listeners implement SWTEventListener but that interface is intended to be removed in the future and then they will only implement EventListener.
// This method should not be called for typed listeners listeners that only implement EventListener.
// This is only relevant for custom typed listeners that implement EventListener directly before SWTEventListener is eventually removed.
// But then the new Widget.getTypedListener() method can be used.
return (SWTEventListener) eventListener;
}

/**
Expand Down

0 comments on commit c52bb34

Please sign in to comment.