/*** * * Copyright (C) 2008 Alessandro La Rosa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: alessandro.larosa@gmail.com * * Author: Alessandro La Rosa */ import java.util.Calendar; import java.util.Date; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; public class CalendarWidget { static final String[] MONTH_LABELS = new String[]{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; static final String[] WEEKDAY_LABELS = new String[]{ "M", "T", "W", "T", "F", "S", "S" }; /* starting week day: 0 for monday, 6 for sunday */ public int startWeekday = 0; /* elements padding */ public int padding = 1; /* cells border properties */ public int borderWidth = 4; public int borderColor = 0x0000ff; /* weekday labels properties */ public Font weekdayFont = Font.getDefaultFont(); public int weekdayBgColor = 0x0000ff; public int weekdayColor = 0xffffff; /* header (month-year label) properties */ public Font headerFont = Font.getDefaultFont(); public int headerBgColor = 0x0000ff; public int headerColor = 0xffffff; /* cells properties */ public Font font = Font.getDefaultFont(); public int foreColor = 0x000000; public int bgColor = 0x9999ff; public int selectedBgColor = 0xffff00; public int selectedForeColor = 0xff0000; /* internal properties */ int width = 0; int height = 0; int headerHeight = 0; int weekHeight = 0; int cellWidth = 0; int cellHeight = 0; /* internal time properties */ long currentTimestamp = 0; Calendar calendar = null; int weeks = 0; public CalendarWidget(Date date) { calendar = Calendar.getInstance(); //we'll see these 2 methods later setDate(date); initialize(); } public Date getSelectedDate() { return calendar.getTime(); } public void setDate(Date d) { currentTimestamp = d.getTime(); calendar.setTime(d); //weeks number can change, depending on week starting day and month total days this.weeks = (int)Math.ceil(((double)getStartWeekday() + getMonthDays()) / 7); } public void setDate(long timestamp) { setDate(new Date(timestamp)); } void initialize() { //let's initialize calendar size this.cellWidth = font.stringWidth("MM") + 2 * padding; this.cellHeight = font.getHeight() + 2 * padding; this.headerHeight = headerFont.getHeight() + 2 * padding; this.weekHeight = weekdayFont.getHeight() + 2 * padding; this.width = 7 * (cellWidth + borderWidth) + borderWidth; initHeight(); } void initHeight() { this.height = headerHeight + weekHeight + this.weeks * (cellHeight + borderWidth) + borderWidth; } int getMonthDays() { int month = calendar.get(Calendar.MONTH); switch(month) { case 3: case 5: case 8: case 10: return 30; case 1: return calendar.get(Calendar.YEAR) % 4 == 0 && calendar.get(Calendar.YEAR) % 100 != 0 ? 29 : 28; default: return 31; } } int getStartWeekday() { //let's create a new calendar with same month and year, but with day 1 Calendar c = Calendar.getInstance(); c.set(Calendar.MONTH, calendar.get(Calendar.MONTH)); c.set(Calendar.YEAR, calendar.get(Calendar.YEAR)); c.set(Calendar.DAY_OF_MONTH, 1); //we must normalize DAY_OF_WEEK returned value return (c.get(Calendar.DAY_OF_WEEK) + 5) % 7; } public void keyPressed(int key) { switch(key) { case Canvas.UP: go(-7); break; case Canvas.DOWN: go(7); break; case Canvas.RIGHT: go(1); break; case Canvas.LEFT: go(-1); break; } } void go(int delta) { int prevMonth = calendar.get(Calendar.MONTH); setDate(currentTimestamp + 86400000 * delta); //we have to check if month has changed //if yes, we have to recalculate month height //since weeks number could be changed if(calendar.get(Calendar.MONTH) != prevMonth) { initHeight(); } } public void paint(Graphics g) { //painting background g.setColor(bgColor); g.fillRect(0, 0, width, height); //painting header (month-year label) g.setFont(headerFont); g.setColor(headerColor); g.drawString(MONTH_LABELS[calendar.get(Calendar.MONTH)] + " " + calendar.get(Calendar.YEAR), width / 2, padding, Graphics.TOP | Graphics.HCENTER); //painting week days labels g.translate(0, headerHeight); g.setColor(weekdayBgColor); g.fillRect(0, 0, width, weekHeight); g.setColor(weekdayColor); g.setFont(weekdayFont); for(int i = 0; i < 7; i++) { g.drawString(WEEKDAY_LABELS[(i + startWeekday) % 7], borderWidth + i * (cellWidth + borderWidth) + cellWidth / 2, padding, Graphics.TOP | Graphics.HCENTER ); } //painting cells borders g.translate(0, weekHeight); g.setColor(borderColor); for(int i = 0; i <= weeks; i++) { g.fillRect(0, i * (cellHeight + borderWidth), width, borderWidth); } for(int i = 0; i <= 7; i++) { g.fillRect(i * (cellWidth + borderWidth), 0, borderWidth, height - headerHeight - weekHeight); } //painting days int days = getMonthDays(); int dayIndex = (getStartWeekday() - this.startWeekday + 7) % 7; g.setColor(foreColor); int currentDay = calendar.get(Calendar.DAY_OF_MONTH); for(int i = 0; i < days; i++) { int weekday = (dayIndex + i) % 7; int row = (dayIndex + i) / 7; int x = borderWidth + weekday * (cellWidth + borderWidth) + cellWidth / 2; int y = borderWidth + row * (cellHeight + borderWidth) + padding; //if this is the current day, we'll use selected bg and fore colors if(i + 1 == currentDay) { g.setColor(selectedBgColor); g.fillRect( borderWidth + weekday * (cellWidth + borderWidth), borderWidth + row * (cellHeight + borderWidth), cellWidth, cellHeight); g.setColor(selectedForeColor); } g.drawString("" + (i + 1), x, y, Graphics.TOP | Graphics.HCENTER); //if this is the current day, we must restore standard fore color if(i + 1 == currentDay) { g.setColor(foreColor); } } //let's traslate back! g.translate(0, - headerHeight - weekHeight); } }