/* Calendar.java: Java program to display a calendar for any month * after 1582. The user inputs the year into a TextField and chooses * the month from a Choice object (drop-down combo box), then clicks * 'New Calendar' to show the calendar for that month and year. Call * applet from an HTML file with this tag: * * * * The applet assumes a 421x481 pixel surface on which to draw. */ /* Version History: * * Version Date Changes * ------- ---------- ---------------------------------------------- * 1.00 12/02/1999 Initial release * 1.01 12/03/1999 Switched position of month and year selecters * 1.10 12/04/1999 Added Text Messages for Dates * Messages are read from hile specified as * * 1.11 12/05/1999 Added Version number to display. * * * */ /** * @version 1.10 * @author Blake M Puhak * */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.Font; import java.util.Date; //not used import java.util.Hashtable; //used to store info for dates import java.util.Calendar; //for calendar object now import java.util.*; import java.io.*; //FileReader / BufferedReader import java.util.StringTokenizer; //StringTokenizer for file processing import java.net.URL; // to access data file public class urcscCalendar extends Applet implements ActionListener { static final int YTOP = 90; /* y-size of margin above calendar box */ static final int YHEADER = 30; /* y-size of horz strip with day names */ static final int NCELLX = 7; /* number of cells across */ static final int CELLSIZE = 60; /* size of each square cell */ static final int MARGIN = 8; /* margin from number to cell top, right */ static final int FEBRUARY = 1; /* special month during leap years */ static final String VERSION = "v1.11"; // Data entry controls at top. Label yearLabel = new Label("Year:"); Choice yearChoice = new Choice(); Label monthLabel = new Label("Month:"); Choice monthChoice = new Choice(); Button newCalButton; // Calendar object to get current month and year. Calendar now = Calendar.getInstance(); // Font for controls at top. Font smallArialFont = new Font("Arial", Font.PLAIN, 15); // Font for days of week Font dayOfWeekArialFont = new Font("Arial", Font.PLAIN, 11); // Font for text Font textArialFont = new Font("Arial", Font.PLAIN, 9); //Font for numerals Font numeralArialFont = new Font("Arial", Font.BOLD, 12); // Font for for month/year caption above calendar. Font largeArialFont = new Font("Arial", Font.BOLD, 30); String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; String months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Month and year entered by user. int userMonth; int userYear; int today; /* used to put date specific info in boxes */ Hashtable dateInfo; //for readData String inputfile = ""; //"http://www.mathcs.richmond.edu/~urcsc/urcscCalendarInfo.txt" URL furl; DataInputStream dis; //reads urcscCalendarInfo.txt InputStream is; String delimdata = ""; /** * Get current month and year, initialize controls. */ public void init() { /* gets inputfile */ getParams(); setBackground(Color.white); // Init month and year to current values. userMonth = now.get(now.MONTH); userYear = now.get(now.YEAR); today = now.get(now.DATE); //sets flow layout across top of calendar setLayout(new FlowLayout()); // "Month:" label. monthLabel.setFont(smallArialFont); add(monthLabel); // Combo box to get month from user: add months, set default to now. monthChoice.setFont(smallArialFont); for (int i = 0; i < 12; i++) monthChoice.addItem(months[i]); monthChoice.select(userMonth); add(monthChoice); //monthChoice.addActionListener(this); // "Year:" label. yearLabel.setFont(smallArialFont); add(yearLabel); // Text field to get year from user. yearChoice.setFont(smallArialFont); for (int i = -1; i < 5; i++) { String yrString = ""; int yearStrAsInt = now.get(now.YEAR); yearStrAsInt += i; yrString += yearStrAsInt; yearChoice.addItem(yrString); } String yrString = ""; yrString += now.get(now.YEAR); yearChoice.select(yrString); add(yearChoice); //yearChoice.addActionListener(this); // "New calendar" button. newCalButton = new Button("New Calendar"); newCalButton.setFont(smallArialFont); add(newCalButton); newCalButton.addActionListener(this); // loads special dates into table try { dateInfo = readData(inputfile); } catch (Exception e){ dateInfo = new Hashtable();} } // init /** * Draws the Calendar with numerals, text, and title. * Called automatically whenever surface needs to be redrawn; also when user clicks * 'New Calendar' button, triggering repaint. * @param Graphics g */ public void paint(Graphics g) { FontMetrics fm; /* to get font info */ int fontAscent; /* character height */ int dayPos; /* y-position of day strings */ int xSize, ySize; /* size of calendar body (cell table) */ int numRows; /* number of rows in cell table (4, 5, 6) */ int xNum, yNum; /* number position at top right of cells */ int xTextNum, yTextNum; /* number position for text */ int numDays; /* number of days in month */ String dayStr; /* day of the week as a string */ int marg; /* margin of month string baseline from cell table */ String caption; /* month string at top center */ // Get font info for number string positioning (default small font). g.setFont(dayOfWeekArialFont); fm = g.getFontMetrics(); fontAscent = fm.getAscent(); dayPos = YTOP + (YHEADER + fontAscent) / 2; // Get x-size of calendar body (cell table). xSize = NCELLX * CELLSIZE; // Header rectangle across top for day names. g.drawRect(0, YTOP, xSize, YHEADER); // Put days at top of each column, centered. for (int i = 0; i < NCELLX; i++) g.drawString(days[i], (CELLSIZE-fm.stringWidth(days[i]))/2 + i*CELLSIZE, dayPos); // Get number of calendar rows needed for this month. numRows = NumberRowsNeeded(userYear, userMonth); // Vertical lines of cell table. ySize = numRows * CELLSIZE; for (int i = 0; i <= xSize; i += CELLSIZE) g.drawLine(i, YTOP + YHEADER, i, YTOP + YHEADER + ySize); // Horizontal lines of cell table. for (int i = 0, j = YTOP + YHEADER; i <= numRows; i++, j += CELLSIZE) g.drawLine(0, j, xSize, j); // Init number positions (upper right of cell). xNum = (CalcFirstOfMonth(userYear, userMonth) + 1) * CELLSIZE - MARGIN; yNum = YTOP + YHEADER + MARGIN + fontAscent; // Init text positions (upper right of cell). xTextNum = (CalcFirstOfMonth(userYear, userMonth) + 1) * CELLSIZE - MARGIN; yTextNum = YTOP + YHEADER + MARGIN + 2*fontAscent; // Get number of days in month, adding one if February of leap year. numDays = DaysInMonth[userMonth] + ((IsLeapYear(userYear) && (userMonth == FEBRUARY)) ? 1 : 0); // set text for numerals g.setFont(numeralArialFont); fm = g.getFontMetrics(); // Show numbers at top right of each cell, right justified. for (int day = 1; day <= numDays; day++) { dayStr = String.valueOf(day); /* sets color of current date to red */ if ((day==today) && (userMonth==now.get(now.MONTH)) && (userYear==now.get(now.YEAR)) ) g.setColor(Color.red); else g.setColor(Color.black); g.drawString(dayStr, xNum - fm.stringWidth(dayStr), yNum); String dateString = new String(); dateString += userYear; int adjustedUserMonth = userMonth + 1; //since userMonth is an array index if (adjustedUserMonth < 10) dateString += "0"; dateString += adjustedUserMonth; if (day < 10) dateString += "0"; dateString += dayStr; String text = new String(); if( dateInfo.containsKey(dateString) ) text = (String)dateInfo.get(dateString); g.setColor(Color.black); //set text font g.setFont(textArialFont); fm = g.getFontMetrics(); //write text if((text == null) || (fm.stringWidth(text) < CELLSIZE - 2)) //if text fits in cell (2 pixel buffer) g.drawString(text, xTextNum - fm.stringWidth(text) + 6, yTextNum); else { StringTokenizer tok = new StringTokenizer(text); int numTokens = tok.countTokens(); String textLine = ""; String nextWord = ""; int tempYTextNum = yTextNum; int counter = 0; int lineCount = 1; boolean flag = false; while((tok.hasMoreTokens() && lineCount <= 3) || flag) { flag = false; textLine = nextWord; while ((fm.stringWidth(textLine) < CELLSIZE - 6) && (counter < numTokens)) { nextWord = tok.nextToken(); counter++; textLine += " " + nextWord; } if (counter < numTokens || lineCount == 1) { textLine = textLine.substring( 0, textLine.length() - nextWord.length() ); flag= true; } else textLine = textLine.substring( 0, textLine.length() ); g.drawString(textLine, xTextNum - fm.stringWidth(textLine) + 6, tempYTextNum); tempYTextNum += fm.getHeight() + 1; lineCount++; } if (tok.hasMoreTokens() && (lineCount < 2)) { nextWord = tok.nextToken(); g.drawString(nextWord, xTextNum - fm.stringWidth(nextWord) + 6, tempYTextNum);} } //reset font g.setFont(numeralArialFont); fm = g.getFontMetrics(); xNum += CELLSIZE; xTextNum += CELLSIZE; // If xNum to right of calendar, 'new line'. if (xNum > xSize) { xNum = CELLSIZE - MARGIN; yNum += CELLSIZE; xTextNum = CELLSIZE - MARGIN; yTextNum += CELLSIZE; } // if } // for to deiplay numbers and text // Set large font for month/year caption. g.setFont(largeArialFont); // Get font info for string positioning (large font now current). fm = g.getFontMetrics(); // Set margin for y-positioning of caption. marg = 2 * fm.getDescent(); // Set caption to month string and center at top. caption = months[userMonth] + " " + String.valueOf(userYear); g.drawString(caption, (xSize-fm.stringWidth(caption))/2, YTOP - marg); //reset font g.setFont(numeralArialFont); fm = g.getFontMetrics(); g.drawString(VERSION, 421 - fm.stringWidth(VERSION), 491); } // paint /** * @param ActionEvent e */ public void actionPerformed(ActionEvent e) { int userYearInt; // Get month from combo box (Choice control). userMonth = monthChoice.getSelectedIndex(); // Get year from TextField, update userYear only if year ok. userYear = yearChoice.getSelectedIndex(); userYear += now.get(now.YEAR) - 1; // Call paint() to draw new calendar. repaint(); } // action /** * Calculates the number of rows needed for a given month and year. * @param int year * @param int month * @returns int Number of Rows Needed */ int NumberRowsNeeded(int year, int month) { int firstDay; /* day of week for first day of month */ int numCells; /* number of cells needed by the month */ /* Start at 1582, when modern calendar starts. */ if (year < 1582) return (-1); /* Catch month out of range. */ if ((month < 0) || (month > 11)) return (-1); /* Get first day of month. */ firstDay = CalcFirstOfMonth(year, month); /* Non leap year February with 1st on Sunday: 4 rows. */ if ((month == FEBRUARY) && (firstDay == 0) && !IsLeapYear(year)) return (4); /* Number of cells needed = blanks on 1st row + days in month. */ numCells = firstDay + DaysInMonth[month]; /* One more cell needed for the Feb 29th in leap year. */ if ((month == FEBRUARY) && (IsLeapYear(year))) numCells++; /* 35 cells or less is 5 rows; more is 6. */ return ((numCells <= 35) ? 5 : 6); } // NumberRowsNeeded /** * Calculates day of the week the first day of the month falls on. * @param int year * @param int month * @returns int Day of the Week */ int CalcFirstOfMonth(int year, int month) { int firstDay; /* day of week for Jan 1, then first day of month */ int i; /* to traverse months before given month */ /* Start at 1582, when modern calendar starts. */ if (year < 1582) return (-1); /* Catch month out of range. */ if ((month < 0) || (month > 11)) return (-1); /* Get day of week for Jan 1 of given year. */ firstDay = CalcJanuaryFirst(year); /* Increase firstDay by days in year before given month to get first day * of month. */ for (i = 0; i < month; i++) firstDay += DaysInMonth[i]; /* Increase by one if month after February and leap year. */ if ((month > FEBRUARY) && IsLeapYear(year)) firstDay++; /* Convert to day of the week and return. */ return (firstDay % 7); } // CalcFirstOfMonth /** * Checks if given year is a leap year. This is Y2K compliant. * @param int year * @returns boolean true if leap year */ boolean IsLeapYear(int year) { /* If multiple of 100, leap year iff multiple of 400. */ if ((year % 100) == 0) return((year % 400) == 0); /* Otherwise leap year iff multiple of 4. */ return ((year % 4) == 0); } // IsLeapYear int CalcJanuaryFirst(int year) /* USE: Calculate day of the week on which January 1 falls for given year. IN: year = given year after 1582 (start of the Gregorian calendar). OUT: Day of week for January 1: 0 = Sunday, 1 = Monday, etc. NOTE: Formula starts with a 5, since January 1, 1582 was a Friday; then advances the day of the week by one for every year, adding the number of leap years intervening, because those years Jan 1 advanced by two days. Calculate mod 7 to get the day of the week. */ { /* Start at 1582, when modern calendar starts. */ if (year < 1582) return (-1); /* Start Fri 01-01-1582; advance a day for each year, 2 for leap yrs. */ return ((5 + (year - 1582) + CalcLeapYears(year)) % 7); } // CalcJanuaryFirst /** * Calculate number of leap years since 1582. * @param int year * @returns int number of leap years since given year */ int CalcLeapYears(int year) /* USE: Calculate number of leap years since 1582. IN: year = given year after 1582 (start of the Gregorian calendar). OUT: number of leap years since the given year, -1 if year < 1582 NOTE: Count doesn't include the given year if it is a leap year. In the Gregorian calendar, used since 1582, every fourth year is a leap year, except for years that are a multiple of a hundred, but not a multiple of 400, which are no longer leap years. Years that are a multiple of 400 are still leap years: 1700, 1800, 1990 were not leap years, but 2000 will be. */ { int leapYears; /* number of leap years to return */ int hundreds; /* number of years multiple of a hundred */ int fourHundreds; /* number of years multiple of four hundred */ /* Start at 1582, when modern calendar starts. */ if (year < 1582) return (-1); /* Calculate number of years in interval that are a multiple of 4. */ leapYears = (year - 1581) / 4; /* Calculate number of years in interval that are a multiple of 100; * subtract, since they are not leap years. */ hundreds = (year - 1501) / 100; leapYears -= hundreds; /* Calculate number of years in interval that are a multiple of 400; * add back in, since they are still leap years. */ fourHundreds = (year - 1201) / 400; leapYears += fourHundreds; return (leapYears); } // CalcLeapYears /* end standard calendar functions */ /* functions to display info on a date */ /** * @returns a Hashtable with Date Data. * @param inputfile The Name of the Input File */ public Hashtable readData(String inputfile) throws IOException { Hashtable ht = new Hashtable(); String theData = ""; String inputData = ""; String param = ""; String emptystring = ""; boolean badfile = false; if(inputfile != null) /* input file exists */ { /* sets up: URL furl */ try { int qt = inputfile.indexOf("http://"); if( qt > -1) furl = new URL(inputfile); else furl = new URL(getDocumentBase(), inputfile); } catch(Exception me) { System.out.println("input file URL * not valid " + me); badfile = true; } /* sets DataInputStream and checks for file */ try { is = furl.openStream(); dis = new DataInputStream(new BufferedInputStream(is)); } catch(Exception dise) { System.out.println("inputfile not found * " + dise); badfile = true; } } if(!badfile) //valid input file { int i = 0; int p = 0; for (inputData = dis.readLine(); inputData!=null; inputData = dis.readLine()) { String key = ""; String elt = ""; if(inputData == null || inputData.length() == 0) i--; else if(inputData != null) { /* key/date format mm/dd/yyyy */ key = new String(); int yyyy, mm ,dd; key += inputData.substring(6, 10); //yyyy key += inputData.substring(0, 2); //mm key += inputData.substring(3, 5); //dd //key += yyyy; //key += mm; //key += dd; elt = inputData.substring( 11, inputData.length() ); ht.put(key, elt); } System.out.println(elt + "" + key); } //end for loop } //end if(!badfile) return ht; } //end readData(String inputfile) /** * Gets Parameters from html file * @throws NullPointerException */ public void getParams() throws NullPointerException { String param = null; String paramdata = null; String go = "no"; go = getParameter("inputfile"); if(go != null) inputfile = go; go = null; } //getParams() /** * Used for clickable links to URLs. * @param String url */ void goToUrl(String url) { try { getAppletContext().showDocument(new URL(url)); showStatus("Go to url= " + url); } catch(Exception e) { showStatus("Cannot go to \"" + url + "\"."); repaint(); } } } // class Calendar