/* * @(#)DesktopEventService.java * * Project: JHotdraw - a GUI framework for technical drawings * http://www.jhotdraw.org * http://jhotdraw.sourceforge.net * Copyright: © by the original author(s) and all contributors * License: Lesser GNU Public License (LGPL) * http://www.opensource.org/licenses/lgpl-license.html */ package CH.ifa.draw.contrib; import CH.ifa.draw.framework.DrawingView; import CH.ifa.draw.standard.NullDrawingView; import CH.ifa.draw.util.CollectionsFactory; import java.util.List; import java.util.ListIterator; import java.awt.event.ContainerAdapter; import java.awt.event.ContainerListener; import java.awt.event.ContainerEvent; import java.awt.*; /** * @author Wolfram Kaiser * @version <$CURRENT_VERSION$> */ public class DesktopEventService { /** * Current usage of this List is not thread safe, nor should it need to be. * If it ever does we can synchronize on the List itself to provide safety. */ private java.util.List listeners; private DrawingView mySelectedView; private Container myContainer; private Desktop myDesktop; public DesktopEventService(Desktop newDesktop, Container newContainer) { listeners = CollectionsFactory.current().createList(); setDesktop(newDesktop); setContainer(newContainer); getContainer().addContainerListener(createComponentListener()); } private void setDesktop(Desktop newDesktop) { myDesktop = newDesktop; } protected Desktop getDesktop() { return myDesktop; } private void setContainer(Container newContainer) { myContainer = newContainer; } protected Container getContainer() { return myContainer; } public void addComponent(Component newComponent) { getContainer().add(newComponent); } public void removeComponent(DrawingView dv) { Component[] comps = getContainer().getComponents(); for (int x = 0; x < comps.length; x++) { if (dv == Helper.getDrawingView(comps[x])) { getContainer().remove(comps[x]); break; } } } public void removeAllComponents() { getContainer().removeAll(); } public void addDesktopListener(DesktopListener dpl) { listeners.add(dpl); } public void removeDesktopListener(DesktopListener dpl) { listeners.remove(dpl); } protected void fireDrawingViewAddedEvent(final DrawingView dv) { ListIterator li= listeners.listIterator(listeners.size()); DesktopEvent dpe = createDesktopEvent(getActiveDrawingView(), dv); while (li.hasPrevious()) { DesktopListener dpl = (DesktopListener)li.previous(); dpl.drawingViewAdded(dpe); } } protected void fireDrawingViewRemovedEvent(final DrawingView dv) { ListIterator li= listeners.listIterator(listeners.size()); DesktopEvent dpe = createDesktopEvent(getActiveDrawingView(), dv); while (li.hasPrevious()) { DesktopListener dpl = (DesktopListener)li.previous(); dpl.drawingViewRemoved(dpe); } } /** * This method is only called if the selected drawingView has actually changed */ protected void fireDrawingViewSelectedEvent(final DrawingView oldView, final DrawingView newView) { ListIterator li= listeners.listIterator(listeners.size()); DesktopEvent dpe = createDesktopEvent(oldView, newView); while (li.hasPrevious()) { DesktopListener dpl = (DesktopListener)li.previous(); dpl.drawingViewSelected(dpe); } } /** * @param oldView previous active drawing view (may be null because not all events require this information) */ protected DesktopEvent createDesktopEvent(DrawingView oldView, DrawingView newView) { return new DesktopEvent(getDesktop(), newView, oldView); } public DrawingView[] getDrawingViews(Component[] comps) { List al = CollectionsFactory.current().createList(); for (int x = 0; x < comps.length; x++) { DrawingView dv = Helper.getDrawingView(comps[x]); if (dv != null) { al.add(dv); } } DrawingView[] dvs = new DrawingView[al.size()]; al.toArray(dvs); return dvs; } public DrawingView getActiveDrawingView() { return mySelectedView; } protected void setActiveDrawingView(DrawingView newActiveDrawingView) { mySelectedView = newActiveDrawingView; } protected ContainerListener createComponentListener() { return new ContainerAdapter() { /** * If the dv is null assert * @todo does adding a component always make it the selected view? * Yes so far because this is only being used on single view Desktops. * If it is to work on multipleView desktops, the we need to think further. */ public void componentAdded(ContainerEvent e) { DrawingView dv = Helper.getDrawingView((java.awt.Container)e.getChild()); DrawingView oldView = getActiveDrawingView(); if (dv != null) { fireDrawingViewAddedEvent(dv); setActiveDrawingView(dv); fireDrawingViewSelectedEvent(oldView, getActiveDrawingView()); } } /** * If dv is null assert * dv will only be null if something thats not a drawingView was * added to the desktop. it would be simpler if we forbade that. */ public void componentRemoved(ContainerEvent e) { DrawingView dv = Helper.getDrawingView((java.awt.Container)e.getChild()); if (dv != null) { DrawingView oldView = getActiveDrawingView(); setActiveDrawingView(NullDrawingView.getManagedDrawingView(oldView.editor())); fireDrawingViewSelectedEvent(oldView, getActiveDrawingView()); fireDrawingViewRemovedEvent(dv); } } }; } }