org.bushe.swing.event.ContainerEventServiceFinder Maven / Gradle / Ivy
/**
* Copyright 2005 Bushe Enterprises, Inc., Hopkinton, MA, USA, www.bushe.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bushe.swing.event;
import java.awt.Component;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.RootPaneContainer;
/**
* This class finds a component's container event service, and creates one if necessary and possible.
*
* A Container EventService is, unlike the EventBus, an EventService that is container specific, in other words, it is
* shared only amongst components within a container. For example, a Form component can supply an EventService used
* only by components in the form. The Form's components can publish value change events on their Container's Event
* Service. The Form's Model and Validator may listen to these events to collect data and show errors, respectively.
*
* Most importantly, Container EventService's cuts down event traffic, avoid naming and listener clashes, promotes
* componentization, and splits events usage into logical subsets.
*
* The finder will walk up a component's hierarchy searching for a parent that implements ContainerEventServiceSupplier.
* If it find one, it returns it. If it doesn't find one, the top level JComponent (specifically, the highest parent in
* the hierarchy, typically a JRootPane) has a client property added to it (if not already set) that has the value of a
* new SwingEventService, which is then returned. The EventBus is never returned.
*
* @author Michael Bushe [email protected]
*/
public class ContainerEventServiceFinder {
/** The client property used to put a new SwingEventService on top-level components. */
public static final String CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE = "ContainerEventServiceFinder.createdService";
/**
* Walks the component's parents until it find an ContainerEventServiceSupplier and returns the suppier's
* EventService. If the component in the tree is a JPopupMenu, then the menu's invoker is walked.
*
* @param component any component
*
* @return the ContainerEventService of the nearest parent
*/
public static EventService getEventService(Component component) {
while (component != null) {
if (component instanceof ContainerEventServiceSupplier) {
return ((ContainerEventServiceSupplier) component).getContainerEventService();
}
if (component instanceof JPopupMenu) {
component = ((JPopupMenu) component).getInvoker();
} else {
if (component.getParent() == null) {
//There is no supplier. Instead of returning null, make an event service
//and stick it in the client properties of the top level container.
if (component instanceof RootPaneContainer) {
component = ((RootPaneContainer) component).getRootPane();
}
if (!(component instanceof JComponent)) {
return null;
}
JComponent jComp = ((JComponent) component);
SwingEventService eventService = (SwingEventService) jComp.getClientProperty(CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE);
if (eventService == null) {
eventService = new SwingEventService();
jComp.putClientProperty(CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE, eventService);
}
return eventService;
} else {
component = component.getParent();
}
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy