/* * Created on Dec 27, 2003 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package com.ecyrd.jspwiki.plugin; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import javax.servlet.http.HttpServletRequest; import com.ecyrd.jspwiki.WikiEngine; /** * A simple calendar item container and HTML printer, used by CalendarPlugin. * Implement CalendarFormatter and plug in your own to produce a different * appearance. * *

This particular formatter produces a div with a string that looks like the following: *

 * << <  JAN 2004  > >>
 * mo tu we th fr sa su
 *          01 02 03 04
 * 05 06 07 08 09 10 11
 * 12 13 14 15 16 17 18
 * 19 20 21 22 23 24 25
 * 26 27 28 29 30 31   
 * 
* *

No table is used in the generation; you will want to check the CSS styles used * by the output and define monospaced fonts in the jspwiki.css file. * *

Each day is a link to a WikiPage named calendarname_YYYYMMDD. * * @author ebu */ public class CalendarPrinter { private int m_dayMarker; private int m_dayPseudoMarker; private int m_monthMarker; private int m_yearMarker; private String CSS_TODAY = "today"; private String CSS_SELECTED = "selected"; private String CSS_EXISTINGENTRY = "exists"; /** Stores the cached HTML string, to prevent needless rendering. */ private String m_cached = null; /** The name of this calendar. Should correspond to a WikiPage, too. */ private String m_calendarName; /** The CSS style prefix to use for DIVs in this calendar. Default is 'calendar'. */ private String m_style = "calendar"; private WikiEngine m_engine; /** The WikiPage that this calendar is displayed on. */ private String m_owningPage; private boolean m_changed = false; /** * Linking mode; if LINK_TO_DAY, each day entry takes us to a day-specific WikiPage. * If LINK_TO_NAME, sets the date to the clicked day and takes us to the page * m_calendarName, which presumably contains a summary view to this calendar. */ private int m_linkMode = LINK_TO_DAY; private String m_handledQuery; // Utilities for HTML printing. private final String m_empty = " "; private final String m_space = "\n"; // private final String m_empty = "  "; // private final String m_space = " "; // A nice up arrow / home mutant hybrid. Necessitates UTF-8, bad me. private final String m_today = "(Back to Today)"; private final String m_edit = "E"; public static final int LINK_TO_DAY = 0; public static final int LINK_TO_CURRENT = 1; /** * Creates a new calendar display object that uses the given name. * The name is free-form, but we expect it to also be an existant * WikiPage, and link to it accordingly. */ public CalendarPrinter( WikiEngine wiki, String name ) { m_calendarName = name; m_engine = wiki; Calendar cal = Calendar.getInstance(); m_dayMarker = cal.get( Calendar.DAY_OF_MONTH ); m_dayPseudoMarker = m_dayMarker; m_monthMarker = cal.get( Calendar.MONTH ); m_yearMarker = cal.get( Calendar.YEAR ); clear(); } /** * Sets the linking mode of individual calendar days. */ public void setLinkingMode( int mode ) { m_linkMode = mode; m_changed = true; } public void clear() { m_changed = true; } /** * Sets the unique name of the calendar. This is also presumed to be the name * of a WikiPage associated with this calendar. */ public void setName( String name ) { m_calendarName = name; m_changed = true; } /** * Returns the unique(?) name of the calendar. */ public String getName() { return( m_calendarName ); } /* * Sets the year to display. * This is optimized to cause re-rendering only if the date has actually changed. */ public void setYear( String y ) { try { setYear( Integer.parseInt( y ) ); } catch( NumberFormatException e ) { } } /* * Sets the year to display. * This is optimized to cause re-rendering only if the date has actually changed. */ public void setYear( int year ) { if( m_yearMarker != year ) { m_yearMarker = year; m_changed = true; } } public int getYear() { return( m_yearMarker ); } public int getMonth() { return( m_monthMarker ); } public int getDay() { return( m_dayMarker ); } /* * Sets the css style to use for the calendar div. * If the style is x, the following CSS classes are used in the calendar view: * x, xtitle */ public void setCSSStyle( String cssStyle ) { m_style = cssStyle; m_changed = true; } /* * Sets the month to display. * This is optimized to cause re-rendering only if the date has actually changed. */ public void setMonth( String m ) { try { int month = Integer.parseInt( m ); month = month % 12; setMonth( month ); } catch( NumberFormatException e ) { } } /* * Sets the month to display. * This is optimized to cause re-rendering only if the date has actually changed. */ public void setMonth( int month ) { if( m_monthMarker != month ) { m_monthMarker = month; setDay( m_dayMarker ); // update in case of now.maxdate < previously.maxdate m_changed = true; } } /* * Sets the day to (maybe) display. * This is optimized to cause re-rendering only if the date has actually changed. * Should be called after setMonth(). */ public void setDay( String d ) { try { int day = Integer.parseInt( d ); setDay( day ); } catch( NumberFormatException e ) { } } /* * Sets the month to display. * Always causes a render update, because we're too lazy to check for an actual change. */ public void setDay( int d ) { if( m_dayMarker != d ) { m_dayMarker = d; m_changed = true; } Calendar cal = Calendar.getInstance(); cal.set( Calendar.DAY_OF_MONTH, 1 ); cal.set( Calendar.MONTH, m_monthMarker ); int max = cal.getActualMaximum( Calendar.DAY_OF_MONTH ); int p = (m_dayMarker > max ? max : m_dayMarker); if( p != m_dayPseudoMarker ) { m_dayPseudoMarker = p; m_changed = true; } } /** * Sets page the calendar is displayed on. This information is used in generating * the next/previous month/year links, so that clicking on them brings us back to * the same page, but with new calendar date info. * This is optimized to cause re-rendering only if the date has actually changed. */ public void setDisplayPage( String wikiPage ) { if( wikiPage.equals( m_owningPage ) == false ) { m_owningPage = wikiPage; m_changed = true; } } public String getDisplayPage() { return( m_owningPage ); } protected void setHandledRequest( HttpServletRequest req ) { m_handledQuery = req.getQueryString(); } public boolean requestHandled( HttpServletRequest req ) { if( req == null || m_handledQuery == null ) return( false ); String newQuery = req.getQueryString(); if( m_handledQuery == newQuery ) return( true ); if( m_handledQuery.equals( newQuery ) ) return( true ); return( false ); } SimpleDateFormat m_datefmt = new SimpleDateFormat( "yyyyMMdd" ); /** * Return the filename this object would use for the given date in its html output. */ public String getEntryName( Calendar date ) { return( m_calendarName + "_" + m_datefmt.format( date.getTime() ) ); } /** * Produces HTML output for a monthly view, tailored for the given page. */ public String printMonthView() { if( m_changed ) { Calendar marker = Calendar.getInstance(); marker.setFirstDayOfWeek( Calendar.MONDAY ); int realMonth = marker.get( Calendar.MONTH ); int realYear = marker.get( Calendar.YEAR ); int realDay = marker.get( Calendar.DAY_OF_MONTH ); // Currently displayed month/year/day. Get before clone(), in case we did stupidities... int currMonth = m_monthMarker; int currYear = m_yearMarker; int currDay = m_dayPseudoMarker; marker.set( Calendar.MONTH, currMonth ); marker.set( Calendar.DAY_OF_MONTH, currDay ); marker.set( Calendar.YEAR, currYear ); int maxDays = marker.getActualMaximum( Calendar.DAY_OF_MONTH ); int yearDays = marker.getActualMaximum( Calendar.DAY_OF_YEAR ); Date currDate = marker.getTime(); // Scrollers for iterating through the days of the month. Calendar cal = (Calendar)marker.clone(); Calendar scroller = (Calendar)marker.clone(); cal.set( Calendar.DAY_OF_MONTH, 1 ); // 1 is start date int maxDate = cal.getActualMaximum( Calendar.DAY_OF_MONTH ); int firstDayOfWeek = cal.get( Calendar.DAY_OF_WEEK ); // 1 is Monday. if( firstDayOfWeek < 2 ) firstDayOfWeek += 7; // Formatting for month/year in title, and days in table SimpleDateFormat monthfmt = new SimpleDateFormat( "MMM" ); SimpleDateFormat yearfmt = new SimpleDateFormat( "yyyy" ); SimpleDateFormat dayfmt = new SimpleDateFormat( "dd" ); // Shortcuts for already too long HTML string nasties. String cy = CalendarPlugin.EXT_YEAR; String cm = CalendarPlugin.EXT_MONTH; String cd = CalendarPlugin.EXT_DAY; // Target page time scroller links take to (the page this calendar is shown on). String currentURL = m_engine.getViewURL( m_owningPage ); StringBuffer buf = new StringBuffer(); // Start calendar div. Date-change-info is encoded in HTTP params, so the CalendarPlugin can figure them out. // buf.append( "

\n" ); buf.append( "\n" ); buf.append( "\n" ); buf.append( "\n" ); //buf.append( "" ); // Start date table. Add empty days. We don't show the previous month's days. buf.append( "\n" ); col++; } else { buf.append( m_space ); col++; } cal.add( Calendar.DAY_OF_MONTH, 1 ); } // Move to the end of the last row. while (col < 6) { buf.append( " " + m_space ); col++; } if( cal.get( Calendar.DAY_OF_WEEK ) != Calendar.MONDAY ) { buf.append( " \n" ); } // A bit of finery: always pad to the full 6 rows (the 6th will also get a today link). // while( row++ < 5 ) // { // buf.append( "\n" ); // col = 0; // } buf.append( "\n" ); buf.append( "
\n" ); // '<<', with link to current page, previous year in this calendar buf.append( "<< " ); // '<', with link to current page, previous month in this calendar scroller.add( Calendar.MONTH, -1 ); buf.append( "<  " ); // month, with link to WikiPage m_calendarName, last day of this month, maxDays days buf.append( "" + monthfmt.format( cal.getTime() ) + " " ); // year, with link to WikiPage m_calendarName, last day of year, about 365 days buf.append( "" + yearfmt.format( cal.getTime() ) + "" ); // '>', next month, this page scroller.add( Calendar.MONTH, 2 ); buf.append( "  >" ); // '>>', next year, this page buf.append( " >>" ); buf.append( "
\n" ); //FIX: hard-coding: buf.append( "
motuwethfrsasu
 
" ); for( int i = Calendar.MONDAY; i < firstDayOfWeek; i++ ) // 1 for first day, again. Argh. buf.append( m_empty + m_space ); // Add dates, with style (if set), link (if set), and remember // a newline and break when the week ends (on sundays). int row = 0; // Tracks the week row we're doing. int col = 0; // Tracks the day column we're doing. while( cal.get( Calendar.MONTH ) == currMonth ) { int d = cal.get(Calendar.DAY_OF_MONTH); String targetPageName = getEntryName( cal ); String dayEntryPageName = targetPageName; // By default, link to a daily entry (LINK_TO_DAY). LINK_TO_NAME provides a navigation mode, instead. if( m_linkMode == LINK_TO_CURRENT ) targetPageName = m_owningPage; String pageUrl = m_engine.getViewURL( targetPageName ); String cssClass = ""; if( m_engine.pageExists( dayEntryPageName ) ) cssClass = "class=\"" + CSS_EXISTINGENTRY + "\" "; // Current date higlight overrides page exists higlight. (Oops.) if( currYear == realYear && currMonth == realMonth && d == realDay ) cssClass = "class=\"" + CSS_TODAY + "\" "; // Currently selected day higlight overrides current date highlight. (Oops again.) if( d == currDay ) cssClass = "class=\"" + CSS_SELECTED + "\" "; if ( cal.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) { buf.append( "
" ); col = 0; } buf.append( "" + dayfmt.format( cal.getTime() ) + "" ); // Advance row counter on sunday. Need to keep track of row and col, though. if( cal.get( Calendar.DAY_OF_WEEK ) == Calendar.SUNDAY ) { row++; buf.append( "
 
" + m_today + "
\n" ); // buf.append( "
\n" ); m_cached = buf.toString(); m_changed = false; } return( m_cached ); } }