/* * [SnapTime.java] * * Summary: A stopwotch variant. * * Copyright: (c) 2016-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2016-06-16 initial version */ package com.mindprod.snaptime; import com.mindprod.common18.Build; import com.mindprod.common18.CMPAboutJBox; import com.mindprod.common18.FontFactory; import com.mindprod.common18.HybridJ; import com.mindprod.common18.JEButton; import com.mindprod.common18.Laf; import com.mindprod.common18.VersionCheck; import javax.swing.JApplet; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.SimpleDateFormat; import java.util.GregorianCalendar; import java.util.TimeZone; import java.util.Timer; import java.util.TimerTask; /** * A stopwotch variant. *

* * @author Roedy Green, Canadian Mind Products * @version 1.0 2016-06-16 initial version * @noinspection FieldCanBeLocal * @since 2016-06-16 */ public final class SnapTime extends JApplet implements ActionListener, ChangeListener { /** * height of Applet box in pixels. Does not include surrounding frame. */ private static final int APPLET_HEIGHT = 220; /** * Width of Applet box in pixels. Oddly displays as 286 */ private static final int APPLET_WIDTH = 350; private static final int FIRST_COPYRIGHT_YEAR = 2016; /** * copyright not displayed * * @noinspection UnusedDeclaration */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2016-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String RELEASE_DATE = "2016-06-16"; private static final String TITLE_STRING = "SnapTime"; private static final String VERSION_STRING = "1.0"; private static final Color BACKGROUND_FOR_APPLET = new Color( 0xfaf0e6 )/* linen */; private static final Color FOREGROUND_FOR_APPLET = new Color( 0x1e90ff )/* dodger blue */; /** * for titles */ private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c ); /** * for for titles and About buttons */ private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 ); /** * for for title second line */ private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 ); /** * DARK_GREEN Colour. */ private static final Color FOREGROUND_FOR_TEXT = new Color( 0x008000 ); /** * Wedgewood blue. */ private static final Color FOREGROUND_FOR_SNAPLIST = new Color( 0x5157ff ); /** * Local date formatter. */ private static final SimpleDateFormat FLOCAL = new SimpleDateFormat( "h:mm:ss:SSS aa" ); // aa=AM/PM /** * where lsist of time snaps are displayed */ private JTextArea snaps; /** * button to request another password */ private JEButton snapButton; /** * Displayed title */ private JLabel title; /** * title, second line */ private JLabel title2; /** * control to contain the PC's time */ private JTextField pcTimeText; /** * allocate all components */ private void buildComponents() { title = new JLabel( TITLE_STRING + " " + VERSION_STRING ); title.setForeground( FOREGROUND_FOR_TITLE ); title.setFont( FONT_FOR_TITLE ); title2 = new JLabel( "released:" + RELEASE_DATE + " build:" + Build.BUILD_NUMBER ); title2.setFont( FONT_FOR_TITLE2 ); title2.setForeground( FOREGROUND_FOR_TITLE ); pcTimeText = new JTextField(); pcTimeText.setForeground( FOREGROUND_FOR_TEXT ); pcTimeText.setEditable( false ); pcTimeText.setHorizontalAlignment( JTextField.CENTER ); snaps = new JTextArea( 20, 15 ); snaps.setForeground( FOREGROUND_FOR_SNAPLIST ); snaps.setEditable( false ); snapButton = new JEButton( "SNAP" ); snapButton.setToolTipText( "Take a snapshot of the time." ); } /** * build a menu with Look & Feel and About across the top */ private void buildMenu() { // turn on anti-alias System.setProperty( "swing.aatext", "true" ); final JMenuBar menubar = new JMenuBar(); setJMenuBar( menubar ); final JMenu lafMenu = Laf.buildLookAndFeelMenu(); if ( lafMenu != null ) { menubar.add( lafMenu ); } final JMenu menuHelp = new JMenu( "Help" ); menubar.add( menuHelp ); final JMenuItem aboutItem = new JMenuItem( "About" ); menuHelp.add( aboutItem ); aboutItem.addActionListener( e -> { // open aboutbox frame new CMPAboutJBox( TITLE_STRING, VERSION_STRING, "Stop watch variant.", "", "freeware", RELEASE_DATE, FIRST_COPYRIGHT_YEAR, "Roedy Green", "SNAPTIME", "1.8" ); } ); } /** * display PC local time. Used by both refresh and background updater */ private void displayPCTime() { // intern to reduce garbage collection frequency // Avoid flicker, since can easily tell if no change. GregorianCalendar pcTime = new GregorianCalendar(); // get current time of day FLOCAL.setTimeZone( TimeZone.getDefault() ); final String t = FLOCAL.format( pcTime.getTime() ).intern(); // setText is thread safe, but not getText pcTimeText.setText( t ); } // end displayPCTime /** * What happens after SNAP button hit. */ private void hit() { displayPCTime(); // extra non-scheduled // add current time to the list, final String now = pcTimeText.getText(); snaps.append( now + "\n" ); } /** * Install listeners */ private void installHooks() { snapButton.addActionListener( this ); } /** * Layout components in a GridBag * * @param contentPane JApplet contentPane. */ private void layoutComponents( Container contentPane ) { // layout // --- 0-------------1-------------- // 0---- title ------- title2--- // 1 ----time -- --snaps---- // 2 -----SNAP--- ------------ // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title, new GridBagConstraints( 0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 10, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title2, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 5, 5, 10 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( pcTimeText, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 100, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( new JScrollPane( snaps, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ), new GridBagConstraints( 1, 1, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 100, 100 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( snapButton, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 5, 5, 10, 5 ), 20, 10 ) ); } /** * set up an event to happen later */ private void startClockDisplay() { // repeat new Timer().schedule( new ScheduleRunner(), 0, 200 /** every 200 ms */ ); } /** * Allow JApplet to be run as an Application * * @param args not used. */ public static void main( String[] args ) { HybridJ.fireup( new SnapTime(), TITLE_STRING + " " + VERSION_STRING, APPLET_WIDTH, APPLET_HEIGHT ); } /** * Invoked when an action occurs. * * @param e event, not used */ public void actionPerformed( ActionEvent e ) { hit(); } /** * Called by the browser or Applet viewer to inform * this Applet that it is being reclaimed and that it should destroy * any resources that it has allocated. */ @Override public void destroy() { title2 = null; title = null; } /** * Called by the browser or Applet viewer to inform * this Applet that it has been loaded into the system. */ @Override public void init() { Container contentPane = this.getContentPane(); if ( !VersionCheck.isJavaVersionOK( 1, 8, 0, contentPane ) ) { // effectively abort return; } buildMenu(); // also initial L&F contentPane.setLayout( new GridBagLayout() ); contentPane.setBackground( BACKGROUND_FOR_APPLET ); contentPane.setForeground( FOREGROUND_FOR_APPLET ); buildComponents(); layoutComponents( contentPane ); installHooks(); startClockDisplay(); this.validate(); this.setVisible( true ); } /** * Applet has scrolled onscreen. */ public void start() { } /** * Invoked when the target of the listener has changed its state. * * @param e a ChangeEvent object, not used */ public void stateChanged( ChangeEvent e ) { hit(); } /** * Applet scrolled offscreen */ public void stop() { } /** * run method will be invoked when time is up. */ private class ScheduleRunner extends TimerTask { /** * executed when time is up. */ public void run() { displayPCTime(); } } // end inner class ScheduleRunner }