/* * [Bio.java] * * Summary: biorhythm calculator. * * Copyright: (c) 2000-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 2000-12-03 calculates various extreme days, draws graph * 1.1 2000-12-15 correct missing Misc class from the jar. * 1.2 2000-12-17 HANS branding, copyright notice * 1.3 2000-12-20 vertical bar to mark today. number sundays * make ticks point down rather than up Today's biorhythm in words. * 1.4 2001-01-24 clickable HANS logo sends you to HANS * website. * 1.5 2001-02-04 remove next low high critical add today's date ensure * only one day considered critical special message if lucky. reorganise * internal class structure use Labels instead of TextAreas * 1.6 2001-02-10 avoid use of getWidth, not supported in JDK 1.1 * defensive code in case getSize returns null or 0. avoid use of * GetResourceAsStream to bypass Netscape bug. * 1.7 2001-02-13 align things better nicer HANS logo correct * spelling errors on Bio.html page. * 1.8 2001-06-12 add FOR date that defaults to Today. redo with * the SelectableDate class * 1.9 2001-07-19 use of anonymous inner classes for listeners * docs on how to use SelectableDate avoid total reset of allowable day of month * choices when high bound changes. * 2.0 2005-06-22 add about box, tidy code, use stomper. distribute * code * 2.1 2005-12-16 complete Javadoc * 2.2 2006-03-04 reformat with IntelliJ, include Javadoc * 2.3 2007-04-04 Customise class to configure, version for * Longevity Circuit. If Applet size is expanded or contracted, the Canvas * grows and shrinks to fit, adding or removing days to plot. * 2.4 2007-05-17 add PAD, icon. * 2.5 2008-04-06 add build to title, tidy code, fix spelling errors. * 2.6 2009-03-24 fix layout bug, use anti-aliasing. * 2.7 2011-03-24 convert to Swing, use DateSpinners * 2.8 2014-04-07 make Applet signed. Oracle now insists Applets using getResource be signed. * 2.9 2014-12-29 allow you to set LAF on menu. */ package com.mindprod.bio; import com.mindprod.common18.BigDate; import com.mindprod.common18.Build; import com.mindprod.common18.CMPAboutJBox; import com.mindprod.common18.Common18; import com.mindprod.common18.FontFactory; import com.mindprod.common18.HybridJ; import com.mindprod.common18.Laf; import com.mindprod.common18.ST; import com.mindprod.common18.VersionCheck; import com.mindprod.spinner.DateSpinner; import javax.swing.ImageIcon; import javax.swing.JApplet; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; 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.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.prefs.Preferences; /** * biorhythm calculator. *

* Computes Biorhythms based on three cycles: physical 23 day (drawn in red) emotional 28 day (drawn in blue) * intellectual 33 day (drawn in green) Cycles start at birth. They are sinusoidal. Interesting points are high, low, * and critical (0-crossing). On 1955-10-28 shortly after 9:00 pm, William Henry Gates III was born. * * @author Roedy Green, Canadian Mind Products * @version 2.9 2014-12-29 allow you to set LAF on menu. * @since 2000-12-03 */ public final class Bio extends JApplet { // declarations /** * height of Applet box in pixels. Does not include surrounding frame. */ private static final int APPLET_HEIGHT = 500; /** * Width of Applet box in pixels. */ private static final int APPLET_WIDTH = 640; private static final int FIRST_COPYRIGHT_YEAR = 2000; /** * undisplayed copyright notice. */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2000-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String RELEASE_DATE = "2014-12-29"; private static final String TITLE_STRING = "Biorhythms Calculator"; private static final String VERSION_STRING = "2.9"; private static final Color BACKGROUND_FOR_APPLET = Color.white; private static final Color FOREGROUND_FOR_LABEL = new Color( 0x0000b0 ); /** * for luck message */ private static final Color FOREGROUND_FOR_LUCK = new Color( 0x008000 ); /** * for titles */ private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c ); /** * for labels */ private static final Font FONT_FOR_LABELS; /** * for for titles and About buttons */ private static final Font FONT_FOR_TITLE; /** * for for title second line */ private static final Font FONT_FOR_TITLE2; // /declarations static { FONT_FOR_LABELS = com.mindprod.common18.FontFactory.build( "Dialog", Font.BOLD, 15 ); FONT_FOR_TITLE = com.mindprod.common18.FontFactory.build( "Dialog", Font.BOLD, 16 ); FONT_FOR_TITLE2 = com.mindprod.common18.FontFactory.build( "Dialog", Font.PLAIN, 14 ); } /** * Initial value for birth date. Current value on spinners of birthDate, or persisted */ private BigDate birthDate = new BigDate( 1955, 10, 28 ); /** * current date to provide the biorhythms for. */ private BigDate forDate; /** * Delegate notified when either birth or for date is modified. */ private ChangeListener dateChangeListener; private Container contentPane; /** * TODO Suggested improvement: use a persistence so that the program remembers your * birthdate when you come back the next day. *

* Group of four fields to let user select birthdate. */ private DateSpinner birthDateChoice; /** * Group of four fields to let the user select the date the want the bio for. */ private DateSpinner forDateChoice; /** * drawingPanel on which to draw the sine waves. */ private DrawingPanel drawingPanel; /** * HANS flower logo. */ private ImageIcon logo; /** * Picture of a shamrock. */ private ImageIcon luckLogo; /** * Prompt to enter birthdate. */ private JLabel birthDatePrompt; /** * Evaluation in words of the combined cycle. */ private JLabel combiEvaluation; /** * label for combined evaluation. */ private JLabel combiLabel; /** * Evaluation in words of emotional cycle. */ private JLabel emotEvaluation; /** * Label for emotional evaluation. */ private JLabel emotLabel; /** * components to display results on screen. */ private JLabel forDateDisplay; /** * Prompt to enter for date. */ private JLabel forDatePrompt; /** * Label for ForDateIndicator. */ private JLabel forLabel; /** * Evaluation in words of intellectual cycle. */ private JLabel intelEvaluation; /** * label for Intellectual evaluation. */ private JLabel intelLabel; /** * Image to display in upper left corner. */ private JLabel logoImage; /** * Message to display extraordinary luck. */ private JLabel luckMessage; /** * Evaluation in words of physical cycle. */ private JLabel physEvaluation; /** * label for Physical evaluation. */ private JLabel physLabel; /** * Title and version for the applet. */ private JLabel title; /** * second title line for app */ private JLabel title2; /** * where we persist start date */ private Preferences userPrefs; /** * allocate all Components */ private void buildComponents() { title = new JLabel( TITLE_STRING + " " + VERSION_STRING ); title.setFont( FONT_FOR_TITLE ); title.setForeground( FOREGROUND_FOR_TITLE ); title2 = new JLabel( "released:" + RELEASE_DATE + " build:" + Build.BUILD_NUMBER ); title2.setFont( FONT_FOR_TITLE2 ); title2.setForeground( FOREGROUND_FOR_TITLE ); logoImage = new JLabel(); // add Icon later // get images to use for logo logo = new ImageIcon( Bio.class.getResource( Customise.logo ) ); luckLogo = new ImageIcon( Bio.class.getResource( Customise.luckLogo ) ); logoImage.setIcon( logo ); // sometimes will be replaced with luckLogo. birthDatePrompt = new JLabel( "Enter your birth date below:" ); birthDatePrompt.setFont( FONT_FOR_LABELS ); birthDatePrompt.setForeground( FOREGROUND_FOR_LABEL ); birthDateChoice = new DateSpinner(); birthDateChoice.setMinimum( new BigDate( 1900, 1, 1 ) ); birthDateChoice.setMaximum( BigDate.localToday() ); birthDateChoice.setValue( birthDate ); // initially Bill Gates' birthday forDatePrompt = new JLabel( "For biorhythms for other than today, enter that date below:" ); forDatePrompt.setFont( FONT_FOR_LABELS ); forDatePrompt.setForeground( FOREGROUND_FOR_LABEL ); forDate = BigDate.localToday(); forDateChoice = new DateSpinner(); forDateChoice.setMinimum( new BigDate( 1900, 1, 1 ) ); forDateChoice.setMaximum( new BigDate( 2030, 12, 31 ) ); forDateChoice.setValue( forDate ); // starts out as today // forDateChoice.display( this, 1, 6 ); drawingPanel = new DrawingPanel(); drawingPanel.setFont( FontFactory.build( "Dialog", Font.PLAIN, 10 ) ); forLabel = new JLabel( "For" ); forLabel.setFont( FONT_FOR_LABELS ); forLabel.setForeground( FOREGROUND_FOR_LABEL ); // default fine print forDateDisplay = new JLabel( forDate.toString() ); physLabel = new JLabel( "Physical" ); physLabel.setFont( FONT_FOR_LABELS ); physLabel.setForeground( CalcBiorhythms.FOREGROUND_FOR_PHYSICAL ); physEvaluation = new JLabel( "average" ); emotLabel = new JLabel( "Emotional" ); emotLabel.setFont( FONT_FOR_LABELS ); emotLabel.setForeground( CalcBiorhythms.FOREGROUND_FOR_EMOTIONAL ); emotEvaluation = new JLabel( "average" ); intelLabel = new JLabel( "Intellectual" ); intelLabel.setFont( FONT_FOR_LABELS ); intelLabel.setForeground( CalcBiorhythms.FOREGROUND_FOR_INTELLECTUAL ); intelEvaluation = new JLabel( "average" ); combiLabel = new JLabel( "Combined" ); combiLabel.setFont( FONT_FOR_LABELS ); combiLabel.setForeground( CalcBiorhythms.FOREGROUND_FOR_COMBI ); combiEvaluation = new JLabel( "average" ); luckMessage = new JLabel( "" ); luckMessage.setFont( FONT_FOR_LABELS ); luckMessage.setForeground( FOREGROUND_FOR_LUCK ); } // /method /** * 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( new ActionListener() { public void actionPerformed( ActionEvent e ) { // open aboutbox frame new CMPAboutJBox( TITLE_STRING, VERSION_STRING, "Calculate Biorhythms", "for any date, past or future", "freeware", RELEASE_DATE, FIRST_COPYRIGHT_YEAR, "Roedy Green", "BIO", "1.8" ); } } ); } // /method /** * Calculate a new biorhythm from the current settings. On entry both birthDate and forDate have been set. Also * displays graph and evaluations. */ private void calc() { // plot four months containing today with 5 days slop at the beginning // will be clipped to fit final BigDate from = new BigDate( forDate.getYYYY(), forDate.getMM(), 1 - 5, BigDate.NORMALISE ); final BigDate to = new BigDate( forDate.getYYYY(), forDate.getMM() + 4, 1, BigDate.NORMALISE ); drawingPanel.set( from.getOrdinal(), to.getOrdinal(), birthDate.getOrdinal(), forDate.getOrdinal() ); drawingPanel.repaint(); final int daysSinceBirth = forDate.getOrdinal() - birthDate.getOrdinal(); physEvaluation.setText( CalcBiorhythms.levelInWords( daysSinceBirth, CalcBiorhythms.PHYSICAL_PERIOD ) ); physEvaluation.invalidate(); emotEvaluation.setText( CalcBiorhythms.levelInWords( daysSinceBirth, CalcBiorhythms.EMOTIONAL_PERIOD ) ); emotEvaluation.invalidate(); intelEvaluation.setText( CalcBiorhythms.levelInWords( daysSinceBirth, CalcBiorhythms.INTELLECTUAL_PERIOD ) ); intelEvaluation.invalidate(); combiEvaluation.setText( CalcBiorhythms.levelInWords( daysSinceBirth, CalcBiorhythms.COMBI_PERIOD ) ); luckMessage.setText( CalcBiorhythms.luckLevelInWords( daysSinceBirth ) ); luckMessage.invalidate(); if ( luckMessage.getText().length() == 0 ) { logoImage.setIcon( logo ); } else { logoImage.setIcon( luckLogo ); } validate(); repaint(); } // /method /** * hook up listeners to Components */ private void hookListeners() { // arrange to be notified any time either date changes dateChangeListener = new ChangeListener() { /** * anonymous inner class to listen for any change in either birth or * for date. * @param event details of what end user just clicked. */ public void stateChanged( ChangeEvent event ) { birthDate = birthDateChoice.getValue(); forDate = forDateChoice.getValue(); forDateDisplay.setText( forDate.toString() ); calc(); } // end actionPerformed }; birthDateChoice.addChangeListener( dateChangeListener ); forDateChoice.addChangeListener( dateChangeListener ); logoImage.addMouseListener( new MouseAdapter() { // anonymous MouseAdapter class public void mouseClicked( MouseEvent m ) { try { // send them off to visit the HANS home page. // only work if we are running under control of a browser. java.net.URL url = new java.net.URL( Customise.url ); getAppletContext().showDocument( url ); } catch ( Exception e ) { // don't sweat it if it does not work. } } // end mouseClicked } // end anonymous class );// end addWMouseListener } // /method /** * layout Components in a GridBag */ private void layoutComponents() { /* __0____1___2____3______4____ 0 .... ---title------- 1 logo ---title2------- " 2 " Enter you birth date: 3 " year-month-day 4 .... Enter for date: 5 ....year-month-day 6 drawingPanel-for-sine-wave-graph 7 for phys emot intel comb 8 date high low high average 9 -----luckmsg------------- __0____1___2____3______4_______ */ // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title, new GridBagConstraints( 1, 0, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 10, 5, 0, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( logoImage, new GridBagConstraints( 0, 1, 1, 3, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets( 10, 10, 5, 5 ) /* T L B R */, 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title2, new GridBagConstraints( 1, 1, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( birthDatePrompt, new GridBagConstraints( 1, 2, 4, 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( birthDateChoice, new GridBagConstraints( 1, 3, 4, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( forDatePrompt, new GridBagConstraints( 1, 4, 4, 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( forDateChoice, new GridBagConstraints( 1, 5, 4, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( drawingPanel, new GridBagConstraints( 0, 6, 5, 1, 0.0, 100.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets( 10, 10, 10, 10 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( forLabel, new GridBagConstraints( 0, 7, 1, 1, 10.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 10, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( physLabel, new GridBagConstraints( 1, 7, 1, 1, 10.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( emotLabel, new GridBagConstraints( 2, 7, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( intelLabel, new GridBagConstraints( 3, 7, 1, 1, 10.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( combiLabel, new GridBagConstraints( 4, 7, 1, 1, 10.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 10 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( forDateDisplay, new GridBagConstraints( 0, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 10, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( physEvaluation, new GridBagConstraints( 1, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( emotEvaluation, new GridBagConstraints( 2, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( intelEvaluation, new GridBagConstraints( 3, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( combiEvaluation, new GridBagConstraints( 4, 8, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, 10 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( luckMessage, new GridBagConstraints( 0, 9, 5, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 10, 10, 10 ), 0, 0 ) ); } /** * Allow this Applet to run as as application as well. * * @param args command line arguments are ignored. */ public static void main( String args[] ) { HybridJ.fireup( new Bio(), TITLE_STRING + " " + VERSION_STRING, APPLET_WIDTH, APPLET_HEIGHT ); } // /method /** * 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() { birthDateChoice = null; birthDatePrompt = null; drawingPanel = null; combiEvaluation = null; combiLabel = null; dateChangeListener = null; emotEvaluation = null; emotLabel = null; forDate = null; forDateChoice = null; forDateDisplay = null; forDatePrompt = null; forLabel = null; intelEvaluation = null; intelLabel = null; logo = null; logoImage = null; luckLogo = null; luckMessage = null; physEvaluation = null; physLabel = null; title = null; title2 = null; } // /method /** * Called by the browser or Applet viewer to inform * this Applet that it has been loaded into the system. */ @Override public void init() { if ( !VersionCheck.isJavaVersionOK( 1, 8, 0, this ) ) { return; } Common18.setLaf(); userPrefs = Preferences.userNodeForPackage( Bio.class ); String birthDateStr = userPrefs.get( "birthdate", "" ); if ( !ST.isEmpty( birthDateStr ) ) { birthDate = new BigDate( Long.parseLong( birthDateStr ) ); } contentPane = this.getContentPane(); contentPane.setBackground( BACKGROUND_FOR_APPLET ); contentPane.setLayout( new GridBagLayout() ); buildMenu(); buildComponents(); layoutComponents(); hookListeners(); calc(); this.validate();// calculate the layouts this.setVisible( true );// Lights, Camera, Action. } // /method } // /method // /methods /** * Fields to customise this app to a particular customer. These are the default settings. */ final class Customise { /** * usual logo for upper left. */ static final String logo = "han.jpg"; /** * logo for a very lucky day. */ static final String luckLogo = "shamrock.png"; /** * alt title not used, but could be configured in. * * @noinspection UnusedDeclaration */ static final String title = "Longevity Circuit Biorhythms"; /** * url to go to if click logo. */ static final String url = "http://www.longevitycircuit.com/"; }