FileDocCategorySizeDatePackage
FinderIntegration.javaAPI DocExample10397Wed Jul 17 00:28:14 BST 2002com.wiverson.macosbook.plugin

FinderIntegration.java

/** In order for this plugin to function properly,
 * it must be loaded by the SimpleEdit application
 * and the proper system properties set before execution.
 *
 * For example, the following command, entered on a single line,
 * invokes the JVM and tells the system to display the About menu item
 * in the Mac OS X application menu.
 *
 * java -Dcom.apple.mrj.application.apple.menu.about.name=SimpleEdit
 * com.wiverson.macosbook.plugin.FinderIntegrationPlugin
 */
package com.wiverson.macosbook.plugin;

import javax.swing.JDialog;
import javax.swing.JLabel;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import com.apple.mrj.MRJApplicationUtils;

import com.apple.mrj.MRJOpenApplicationHandler;
import com.apple.mrj.MRJPrefsHandler;
import com.apple.mrj.MRJQuitHandler;
import com.apple.mrj.MRJOpenDocumentHandler;
import com.apple.mrj.MRJAboutHandler;

public class FinderIntegration implements 
MRJOpenApplicationHandler, 
MRJQuitHandler, 
MRJPrefsHandler, 
MRJOpenDocumentHandler, 
MRJAboutHandler
{
    
    /** Creates a new instance of FinderIntegration */
    public FinderIntegration()
    {
    }
    
    // Only want to install this once per application
    // to avoid getting multiple event notifications
    private static boolean installed = false;
    public void execute()
    {
        if(!installed)
        {            
            // Enables the menu item
            MRJApplicationUtils.registerPrefsHandler(this);

            // Overrides the default System.exit() behavior.
            MRJApplicationUtils.registerQuitHandler(this);
            
            // Requires com.apple.mrj.application.apple.menu.about.name=Application
            // system property to be set to appear.
            MRJApplicationUtils.registerAboutHandler(this);
            
            // These require the application to be properly bundled for Mac OS X
            // for the events to be dispatched
            MRJApplicationUtils.registerOpenApplicationHandler(this);
            MRJApplicationUtils.registerOpenDocumentHandler(this);
            
            installed = true;
        }
    }
    
    // We only need one instance of the About dialog.
    static JDialog AboutDialog = null;
    public void handleAbout()
    {
        new DoAbout().start();
    }
        
    /** It may seem a bit strange to create a new Thread
     * just to display an about box.
     *
     * Unfortunately, due to the way the System interacts
     * between the native Carbon libraries and the JVM,
     * displaying a dialog will lock the user interface,
     * leaving kill to terminate the app.
     *
     * This simple thread just hangs on to a singleton
     * dialog, creating a new dialog if it's the first
     * time the dialog is displayed, hiding and reshowing
     * the dialog as needed.
     */
    class DoAbout extends Thread
    {
        public void run()
        {
            if(AboutDialog == null)
            {
                AboutDialog = new JDialog();
                AboutDialog.setResizable(false);
                AboutDialog.setTitle("About Simple Edit");
                AboutDialog.setSize(350, 150);
                Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
                int width = new Double((screensize.getWidth() - 350) / 2).intValue();
                int height = new Double((screensize.getHeight() / 2) - 150).intValue();
                AboutDialog.move(width, height);
                JLabel myAppTitle = new JLabel();
                myAppTitle.setHorizontalAlignment(myAppTitle.CENTER);
                myAppTitle.setText("Simple Edit (c) 2002");
                AboutDialog.getContentPane().add(myAppTitle);
                
                // TODO: Add user and system folder information?
            }
            AboutDialog.show();
        }
    }
    
    /** Note that the application requires Mac OS X bundling
     * (as described in a later chapter) to be enabled.
     * The techniques for writing these handlers are similar
     * to the rest of the add-ons.
     *
     *Typically, you will want to use these handlers to call
     *your standard File -> Open... routines, simply bypassing
     *the standard file dialogs.
     */
    public void handleOpenApplication()
    {
        new DoOpenApplication().start();
    }
    
    class DoOpenApplication extends Thread
    {
        public void run()
        {
            System.out.println("Open Application");
        }
    }
    
    public void handleOpenFile(java.io.File file)
    {
        DoOpenFile myHandler = new DoOpenFile();
        myHandler.setFile(file);
        myHandler.start();
    }
    
    class DoOpenFile extends Thread
    {
        private java.io.File theFile = null;
        public void setFile(java.io.File inFile)
        {
            theFile = inFile;
        }
        
        public void run()
        {
            if(theFile == null)
                return;
            
            JDialog openedFileDialog = new JDialog();            
            openedFileDialog.setResizable(false);
            openedFileDialog.setTitle("File Open Request...");
            openedFileDialog.setSize(350, 150);
            Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
            int width = new Double((screensize.getWidth() - 350) / 2).intValue();
            int height = new Double((screensize.getHeight() / 2) - 150).intValue();
            openedFileDialog.move(width, height);
            
            JLabel myFileName = new JLabel();
            myFileName.setHorizontalAlignment(JLabel.CENTER);
            myFileName.setText("File name: " + theFile.getName());
            openedFileDialog.getContentPane().add(myFileName);
            
            JLabel myFilePath = new JLabel();
            myFilePath.setHorizontalAlignment(JLabel.CENTER);
            myFilePath.setText("File path: " + theFile.getPath());
            openedFileDialog.getContentPane().add(myFilePath);
            
            openedFileDialog.show();
        }
    }
    
    public void handlePrefs() throws java.lang.IllegalStateException
    {
        new com.wiverson.macosbook.plugin.FinderIntegration.DoPrefs().start();
    }
    
    // This is the one preference we are tracking, which
    // only relates to Mac OS X specific behavior anyways.
    // Note that we aren't persisting the user's preferences.
    public static boolean pref_askToClose = true;
    
    static JDialog PrefsDialog = null;
    class DoPrefs extends Thread
    {
        public void run()
        {
            if(PrefsDialog == null)
            {
                PrefsDialog = new JDialog();
                PrefsDialog.setResizable(false);
                PrefsDialog.setTitle("Simple Edit Preferences");
                PrefsDialog.setSize(300, 150);
                Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
                int width = new Double((screensize.getWidth()  - 300) / 2).intValue();
                int height = new Double((screensize.getHeight() / 2) - 150).intValue();
                PrefsDialog.move(width, height);
                
                javax.swing.JCheckBox myQuitPrefButton = new javax.swing.JCheckBox("Confirm Before Quit");
                myQuitPrefButton.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
                myQuitPrefButton.setSelected(true);
                myQuitPrefButton.addItemListener(new ItemListener()
                {
                    public void itemStateChanged(ItemEvent evt)
                    {
                        pref_askToClose = (evt.getStateChange() == ItemEvent.SELECTED);
                    }
                });
                PrefsDialog.getContentPane().add(myQuitPrefButton);
            }
            
            PrefsDialog.show();
        }
    }
    
    /* Note that the Quit thread is slightly more complex
     * than the other threads.
     *
     * There is a bug which manifests as of Mac OS X 10.1, JDK 1.3.1
     * Update 1 which causes it to generate multiple events
     * for a single selection of the Quit menu item on the native
     * application menu.
     *
     * Therefore, to avoid a deadlock, a new thread is created,
     * tracked, and communicated with.  It's arguably overkill for
     * what is supposed to be a modal quit confirmation dialog...
     * but it works.
     */
    com.wiverson.macosbook.plugin.FinderIntegration.DoQuit quitThread = null;
    public void handleQuit() throws java.lang.IllegalStateException
    {
        if(pref_askToClose)
        {
            if(quitThread == null)
            {
                quitThread = new DoQuit();
                // Make sure the application doesn't hang around
                // waiting for this thread.
                quitThread.setDaemon(true);
                quitThread.start();
            }
            else
                quitThread.show();
        } else
        {
            // If the user set a preference not to be 
            // prompted, go ahead and bail out.
            System.exit(0);
        }
    }
    
    class DoQuit extends Thread
    {
        private  QuitConfirmJDialog myQuitDialog = null;
        // Operations on ints are inherently atomic,
        // and we aren't doing anything too fancy
        // requires fancier semaphores & locking.
        int showDialog = 0;
        public void show()
        {
            showDialog = 1;
        }
        
        public void run()
        {
            if(myQuitDialog == null)
                myQuitDialog = new QuitConfirmJDialog(new javax.swing.JFrame(), true);
            
            showDialog = 1;
            // Now that the Quit dialog is ready, go ahead and sit
            // around waiting for a semaphore notification to redisplay.
            while(true)
            {
                if(showDialog == 1)
                {
                    myQuitDialog.show();
                    showDialog = 0;
                }
            };
        }
    }
}