1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.apple.eawt;
  27 
  28 import java.awt.Toolkit;
  29 import java.io.File;
  30 import java.util.*;
  31 
  32 import com.apple.eawt.AppEvent.*;
  33 
  34 @SuppressWarnings("deprecation")
  35 class _AppEventLegacyHandler implements AboutHandler, PreferencesHandler, _OpenAppHandler, AppReOpenedListener, OpenFilesHandler, PrintFilesHandler, QuitHandler {
  36     final _AppEventHandler parent;
  37     final Vector<ApplicationListener> legacyAppListeners = new Vector<ApplicationListener>();
  38     boolean blockLegacyAPI;
  39     boolean initializedParentDispatchers;
  40 
  41     _AppEventLegacyHandler(final _AppEventHandler parent) {
  42         this.parent = parent;
  43     }
  44 
  45     void blockLegacyAPI() {
  46         blockLegacyAPI = true;
  47     }
  48 
  49     void checkIfLegacyAPIBlocked() {
  50         if (!blockLegacyAPI) return;
  51         throw new IllegalStateException("Cannot add com.apple.eawt.ApplicationListener after installing an app event handler");
  52     }
  53 
  54     void addLegacyAppListener(final ApplicationListener listener) {
  55         checkIfLegacyAPIBlocked();
  56 
  57         if (!initializedParentDispatchers) {
  58             final _AppMenuBarHandler menuBarHandler = Application.getApplication().menuBarHandler;
  59             final boolean prefsMenuAlreadyExplicitlySet = menuBarHandler.prefsMenuItemExplicitlySet;
  60 
  61             parent.aboutDispatcher.setHandler(this);
  62             parent.preferencesDispatcher.setHandler(this);
  63             if (!prefsMenuAlreadyExplicitlySet) {
  64                 menuBarHandler.setPreferencesMenuItemVisible(false); // default behavior is not to have a preferences item
  65             }
  66             parent.openAppDispatcher.setHandler(this);
  67             parent.reOpenAppDispatcher.addListener(this);
  68             parent.openFilesDispatcher.setHandler(this);
  69             parent.printFilesDispatcher.setHandler(this);
  70             parent.quitDispatcher.setHandler(this);
  71 
  72             initializedParentDispatchers = true;
  73         }
  74 
  75         synchronized (legacyAppListeners) {
  76             legacyAppListeners.addElement(listener);
  77         }
  78     }
  79 
  80     public void removeLegacyAppListener(final ApplicationListener listener) {
  81         checkIfLegacyAPIBlocked();
  82 
  83         synchronized (legacyAppListeners) {
  84             legacyAppListeners.removeElement(listener);
  85         }
  86     }
  87 
  88     @Override
  89     public void handleAbout(final AboutEvent e) {
  90         final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
  91         sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
  92             public void dispatchEvent(final ApplicationListener listener) {
  93                 listener.handleAbout(ae);
  94             }
  95         });
  96 
  97         if (ae.isHandled()) return;
  98         parent.openCocoaAboutWindow();
  99     }
 100 
 101     @Override
 102     public void handlePreferences(final PreferencesEvent e) {
 103         final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
 104         sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 105             public void dispatchEvent(final ApplicationListener listener) {
 106                 listener.handlePreferences(ae);
 107             }
 108         });
 109     }
 110 
 111     @Override
 112     public void handleOpenApp() {
 113         final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
 114         sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 115             public void dispatchEvent(final ApplicationListener listener) {
 116                 listener.handleOpenApplication(ae);
 117             }
 118         });
 119     }
 120 
 121     @Override
 122     public void appReOpened(final AppReOpenedEvent e) {
 123         final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
 124         sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 125             public void dispatchEvent(final ApplicationListener listener) {
 126                 listener.handleReOpenApplication(ae);
 127             }
 128         });
 129     }
 130 
 131     @Override
 132     public void openFiles(final OpenFilesEvent e) {
 133         final List<File> files = e.getFiles();
 134         for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
 135             final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
 136             sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 137                 public void dispatchEvent(final ApplicationListener listener) {
 138                     listener.handleOpenFile(ae);
 139                 }
 140             });
 141         }
 142     }
 143 
 144     @Override
 145     public void printFiles(PrintFilesEvent e) {
 146         final List<File> files = e.getFiles();
 147         for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
 148             final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
 149             sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 150                 public void dispatchEvent(final ApplicationListener listener) {
 151                     listener.handlePrintFile(ae);
 152                 }
 153             });
 154         }
 155     }
 156 
 157     @Override
 158     public void handleQuitRequestWith(final QuitEvent e, final QuitResponse response) {
 159         final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
 160         sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
 161             public void dispatchEvent(final ApplicationListener listener) {
 162                 listener.handleQuit(ae);
 163             }
 164         });
 165 
 166         if (ae.isHandled()) {
 167             parent.performQuit();
 168         } else {
 169             parent.cancelQuit();
 170         }
 171     }
 172 
 173     interface EventDispatcher {
 174         void dispatchEvent(final ApplicationListener listener);
 175     }
 176 
 177     // helper that cycles through the loop and aborts if the event is handled, or there are no listeners
 178     void sendEventToEachListenerUntilHandled(final ApplicationEvent event, final EventDispatcher dispatcher) {
 179         synchronized (legacyAppListeners) {
 180             if (legacyAppListeners.size() == 0) return;
 181 
 182             final Enumeration<ApplicationListener> e = legacyAppListeners.elements();
 183             while (e.hasMoreElements() && !event.isHandled()) {
 184                 dispatcher.dispatchEvent(e.nextElement());
 185             }
 186         }
 187     }
 188 }