package textbender.a.r.page; // Copyright 2006-2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import java.awt.*; import java.io.*; import java.util.concurrent.atomic.*; import javax.swing.*; import textbender.a.r.page.navdo.*; import textbender.g.hold.*; import textbender.g.lang.*; import textbender.g.util.logging.*; import textbender.o.*; import textbender.o.awt.*; import textbender.o.rhinohide.*; import textbender.o.rhinohide._.*; import textbender.o.swing.*; import static textbender.o.awt.FontX.EN; import static textbender.o.awt.FontX.EM; /** The page daemon's primary user applet, which functions as a toolbar. * It is injected into the page either by a user script (normal case), * or by the {@linkplain BootApplet default boot applet}. * Its first job is to instantiate the page daemon, * allowing it to install its various hooks into the page. * Thereafter, it functions as a toolbar. */ public @ThreadRestricted("AWT event dispatch") final class ToolbarApplet extends JApplet { static{ boolean startedHere = Run.i().start(); assert startedHere; } /** Constructs a ToolbarApplet. */ public ToolbarApplet() { toolbar = new JToolBar(); // populated in start() toolbar.setFloatable( false ); toolbar.setRollover( true ); // no effect in JDK 1.6 (and no help setting button borders to null, it eliminates press feedback) getContentPane().add( toolbar, BorderLayout.CENTER ); // - - - // setFocusable( false ); } // - A p p l e t ---------------------------------------------------------------------- public @ThreadSafe void destroy() { LoggerX.i(getClass()).fine( "destroying toolbar applet" ); final Catcher catcher = new CatcherL(); if( !preSpool.unwind( catcher )) assert false; EventQueueX.invokeNowOrWait( new Runnable() { public void run() // in AWT event dispatch thread { if( !spoolEDT.unwind( catcher )) assert false; } }); if( !spool.unwind( catcher )) assert false; } private final AtomicBoolean isStartedA = new AtomicBoolean(); public @ThreadSafe void start() { if( isStartedA.getAndSet( true )) return; // start once only LoggerX.i(getClass()).fine( "initializing toolbar applet" ); try { final RhiWindow window = RhiWindow.createWindow( ToolbarApplet.this ); spool.add( new Hold() { public @ThreadSafe void release() { window.release(); }}); // Redirect if this page is not the ultimate destination. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - final File file = BootApplet.resolveFile( window ); VersionedFile versionedFile = null; // till proven otherwise if( file != null ) versionedFile = VersionedFile.fromFile( file ); if( versionedFile != null && versionedFile.initRedirect( window )) return; // Ensure shared communication links are up. [doing this earlier now] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PageDaemons.i().connections().refresh(); if( PageDaemons.i().connections().hostServiceRegistry() == null ) { LoggerX.i(getClass()).info( "no running desk daemon, page daemon will be inactive" ); return; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - final PageVisit pageVisit = new PageVisit ( window, file, versionedFile, ToolbarApplet.this ); EventQueueX.invokeNowOrWait( new Runnable() { public void run() // in AWT event dispatch thread { toolbar.add( Box.createHorizontalStrut( EN )); toolbar.add( new JLabel( ImageIconX.tryCreate( // fake button for the PopupMenu (q.v., it pops no matter where you press) getClass().getClassLoader().getResource( "textbender/o/silk/bullet_arrow_down.png" ), 16 ) )); toolbar.add( Box.createHorizontalStrut( EM )); // toolbar.add( Box.createHorizontalGlue() ); toolbar.add( pageVisit.edt().reloadAction() ); // no need to unregister, registry does not outlive this listener toolbar.add( pageVisit.edt().saveAction() ); // " // toolbar.add( Box.createHorizontalGlue() ); } }); } catch( StunnedRhinoException xSR ) { LoggerX.i(getClass()).config( Browser.pageExitSupressionMessage( xSR )); } catch( Exception x ) { user.logAndShow( x ); } // all, checked or not } //// P r i v a t e /////////////////////////////////////////////////////////////////////// /** Spool unwound before this applet is destroyed. */ final Spool preSpool = new SpoolT(); /** Spool unwound as this applet is destroyed. */ final Spool spool = new SpoolT(); /** Spool unwound as this applet is destroyed. */ final SpoolEDT spoolEDT = new SpoolEDT(); final JToolBar toolbar; final User user = new User( /*windowParent*/ToolbarApplet.this ); }