001: package com.xoetrope.swing.date;
002:
003: import java.util.Calendar;
004: import java.util.Date;
005:
006: import java.awt.Color;
007: import java.awt.Dimension;
008: import java.awt.Graphics;
009: import java.awt.event.MouseEvent;
010: import java.awt.event.MouseListener;
011: import java.awt.event.MouseMotionListener;
012: import javax.swing.JComponent;
013: import com.xoetrope.event.XDateListener;
014: import java.awt.Component;
015: import java.awt.FontMetrics;
016: import java.awt.GradientPaint;
017: import java.awt.Graphics2D;
018: import java.awt.RenderingHints;
019: import java.text.DateFormatSymbols;
020: import net.xoetrope.xui.XProjectManager;
021: import net.xoetrope.xui.helper.XuiUtilities;
022: import net.xoetrope.xui.style.XStyle;
023: import net.xoetrope.xui.style.XStyleManager;
024:
025: /**
026: * A date chooser class. This class is used by the XDateChooser class to display
027: * a month of the calendar. A date can then be selected visually.
028: *
029: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
030: * the GNU Public License (GPL), please see license.txt for more details. If
031: * you make commercial use of this software you must purchase a commercial
032: * license from Xoetrope.</p>
033: * <p> $Revision: 1.11 $</p>
034: */
035: public class XDateChooserPanel extends JComponent implements
036: MouseListener, MouseMotionListener {
037: protected XStyleManager styleManager;
038: private Calendar calendar;
039:
040: protected int selectedDay;
041: protected int highlightedDay;
042:
043: private boolean mouseEventInvoked = false;
044: private boolean showDayNames = true;
045: private int cellHeight = 10;
046: private int cellWidth = 10;
047: private int startDay = 1;
048: private int oldX = 0;
049: private int oldY = 0;
050: private int top;
051:
052: private Color foregroundColor, backgroundColor, highlightedColor,
053: highlightedBkColor, selectedColor, selectedBkColor,
054: weekendColor, weekendBkColor;
055: private String styleWeekend, styleSelected, styleHighlighted,
056: styleHeader, basicStyle;
057: private XDateListener listener;
058:
059: public XDateChooserPanel() {
060: calendar = Calendar.getInstance();
061: selectedDay = calendar.get(Calendar.DATE);
062:
063: addMouseListener(this );
064: addMouseMotionListener(this );
065:
066: styleWeekend = "base";
067: styleSelected = "base";
068: styleHighlighted = "base";
069:
070: styleManager = XProjectManager.getCurrentProject()
071: .getStyleManager();
072:
073: XStyle weekendStyle = styleManager.getStyle(styleWeekend);
074: XStyle selectedStyle = weekendStyle;
075: XStyle highlightedStyle = weekendStyle;
076: selectedColor = highlightedColor = weekendColor = selectedStyle
077: .getStyleAsColor(XStyle.COLOR_FORE);
078: selectedBkColor = highlightedBkColor = weekendBkColor = selectedStyle
079: .getStyleAsColor(XStyle.COLOR_BACK);
080:
081: backgroundColor = getBackground();
082: if (backgroundColor == null) {
083: backgroundColor = new Color(255, 255, 225);
084: weekendBkColor = new Color(255, 243, 198);
085: }
086: foregroundColor = getForeground();
087: if (foregroundColor == null)
088: foregroundColor = Color.darkGray;
089: }
090:
091: /**
092: * Gets the current date.
093: * @return
094: */
095: public Date getDate() {
096: return calendar.getTime();
097: }
098:
099: /**
100: * Sets the current date
101: * @param newDate the new date
102: */
103: public void setDate(Date newDate) {
104: calendar.setTime(newDate);
105: selectedDay = calendar.get(Calendar.DATE);
106: repaint();
107: }
108:
109: /**
110: * Move to the previous month
111: */
112: public void prev() {
113: if (calendar.get(Calendar.MONTH) == 0)
114: calendar.roll(Calendar.YEAR, false);
115: calendar.roll(Calendar.MONTH, false);
116: selectedDay = calendar.get(Calendar.DAY_OF_MONTH);
117: highlightedDay = 0;
118: repaint();
119: }
120:
121: /**
122: * Move to the next month
123: */
124: public void next() {
125: if (calendar.get(Calendar.MONTH) == 11)
126: calendar.roll(Calendar.YEAR, true);
127: calendar.roll(Calendar.MONTH, true);
128: if (calendar.get(Calendar.MONTH) == 12)
129: selectedDay = 1;
130: highlightedDay = 0;
131: repaint();
132: }
133:
134: /**
135: * Move to the previous year
136: */
137: public void prevYear() {
138: calendar.roll(Calendar.YEAR, false);
139: selectedDay = calendar.get(Calendar.DAY_OF_MONTH);
140: highlightedDay = 0;
141: repaint();
142: }
143:
144: /**
145: * Move to the next year
146: */
147: public void nextYear() {
148: calendar.roll(Calendar.YEAR, true);
149: selectedDay = calendar.get(Calendar.DAY_OF_MONTH);
150: highlightedDay = 0;
151: repaint();
152: }
153:
154: /**
155: * Renders the current month
156: * @param g
157: */
158: public void paint(Graphics g) {
159: Graphics2D g2d = (Graphics2D) g;
160:
161: Color weekendShadow = new Color(240, 240, 240);
162: Dimension d = getSize();
163: int width = Math.max(d.width, 2);
164: int height = Math.max(d.height, 2);
165:
166: int month = calendar.get(Calendar.MONTH);
167: int year = calendar.get(Calendar.YEAR);
168: int day = calendar.get(Calendar.DATE);
169: calendar.set(year, month, 1);
170: int cellPos = startDay = calendar.get(calendar.DAY_OF_WEEK) - 1;
171: int numDays = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
172: int numWeeks = 1 + (int) (((double) numDays + (double) startDay) / 7.0 + 0.9);
173:
174: cellHeight = Math.max(1, height / numWeeks);
175: cellWidth = Math.max(1, width / 7);
176:
177: FontMetrics fm = g.getFontMetrics();
178: int fontOffset = (cellHeight + fm.getAscent()) / 2;
179: int pad = (cellWidth - fm.stringWidth("28")) / 2;
180: top = 0;
181:
182: if (showDayNames) {
183: top = cellHeight;
184: Color headerColor = XuiUtilities.unsaturateColor(
185: backgroundColor, 50);
186: GradientPaint gradient = new GradientPaint(0.0F, 0.0F,
187: headerColor.brighter(), (float) top / 2,
188: (float) width / 2, headerColor.darker(), true);
189: g2d.setPaint(gradient);
190: g.fillRect(0, 0, width, top);
191:
192: g.setColor(XuiUtilities
193: .unsaturateColor(foregroundColor, 50));
194: String[] dayNames = new DateFormatSymbols()
195: .getShortWeekdays();
196: for (int i = 1; i < 8; i++)
197: g2d.drawString(dayNames[i], pad / 2 + (i - 1) * width
198: / 7, fontOffset);
199:
200: Color lineColor = headerColor.darker().darker();
201: g2d.setColor(new Color(lineColor.getRed(), lineColor
202: .getGreen(), lineColor.getBlue(), 128));
203: g2d.drawLine(0, top - 1, width, top - 1);
204: }
205: g.setColor(backgroundColor);
206: g.fillRect(0, top, width, height);
207:
208: for (int i = 1; i <= numDays; i++) {
209: // Calculate the position of the day in the months grid as the first day of
210: // the month may not be the first day of the week.
211: int cellX = cellPos % 7;
212: int cellY = cellPos / 7;
213:
214: int arc = 4;
215: if ((cellX == 0) || (cellX == 6))
216: arc = 0;
217:
218: // Choose the highlight colour
219: Object oldHint = g2d
220: .getRenderingHint(RenderingHints.KEY_ANTIALIASING);
221: g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
222: RenderingHints.VALUE_ANTIALIAS_ON);
223: if ((i == highlightedDay) || (i == selectedDay)) {
224: Color fillColor = ((i == selectedDay) ? ((i == highlightedDay) ? selectedBkColor
225: .brighter()
226: : selectedBkColor)
227: : highlightedBkColor);
228: GradientPaint gradient = new GradientPaint(0.0F, 0.0F,
229: fillColor.brighter(), (float) top / 2,
230: (float) width / 2, fillColor, true);
231: g2d.setPaint(gradient);
232: g.fillRoundRect(cellX * cellWidth, top + cellY
233: * cellHeight, cellWidth, cellHeight, arc, arc);
234: if (i == selectedDay) {
235: g.setColor(fillColor.darker());
236: g.drawRoundRect(cellX * cellWidth, top + cellY
237: * cellHeight, cellWidth - 1,
238: cellHeight - 1, arc, arc);
239: g.setColor(selectedColor);
240: } else
241: g.setColor(highlightedColor);
242: } else {
243: // Shade weekend days
244: if ((cellX == 0) || (cellX == 6)) {
245: g.setColor(weekendBkColor);
246: g.fillRect(cellX * cellWidth, top + cellY
247: * cellHeight, cellWidth, cellHeight);
248: g.setColor(weekendColor);
249: } else
250: g.setColor(foregroundColor);
251: }
252: g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
253: oldHint);
254:
255: g2d.drawString(new Integer(i).toString(), pad + cellX
256: * cellWidth, top + cellY * cellHeight + fontOffset);
257:
258: calendar.roll(Calendar.DATE, 1);
259: cellPos++;
260: if (calendar.get(Calendar.DATE) == 1)
261: break;
262: }
263: g.setColor(backgroundColor);
264: //g.drawRect( 0, top, width-1, height-1-top );
265:
266: calendar.set(year, month, day);
267: }
268:
269: /**
270: * Selects the highlighted date
271: */
272: private void setSelection() {
273: selectedDay = highlightedDay;
274: if ((selectedDay <= 0)
275: || (selectedDay > calendar
276: .getActualMaximum(calendar.DAY_OF_MONTH)))
277: return;
278:
279: int month = calendar.get(Calendar.MONTH);
280: int year = calendar.get(Calendar.YEAR);
281: int day = calendar.get(Calendar.DATE);
282: calendar.set(year, month, selectedDay);
283:
284: repaint();
285:
286: if (listener != null)
287: listener.setDate(calendar.getTime());
288: }
289:
290: /**
291: * Highlights the date under the cursor.
292: * @param e
293: */
294: private void showSelection(MouseEvent e) {
295: int x = e.getX();
296: int y = e.getY() - top;
297: highlightedDay = (x / cellWidth + (y / cellHeight) * 7)
298: - startDay + 1;
299: repaint(0, oldX, top + oldY, cellWidth, cellHeight);
300: oldX = x - x % cellWidth;
301: oldY = y - y % cellHeight;
302: repaint(0, oldX, top + oldY, cellWidth, cellHeight);
303: }
304:
305: /**
306: * Clear the highlight data
307: */
308: private void clearSelection() {
309: highlightedDay = -1;
310: repaint(0, oldX, top + oldY, (int) cellWidth, (int) cellHeight);
311: }
312:
313: public void mouseClicked(MouseEvent e) {
314: if (!mouseEventInvoked)
315: setSelection();
316:
317: if (e.getClickCount() > 1) {
318: Component parent = getParent();
319: while ((parent != null)
320: && !(parent instanceof XDateChooserDialog))
321: parent = parent.getParent();
322:
323: if (parent != null)
324: ((XDateChooserDialog) parent).closeDlg();
325: }
326: mouseEventInvoked = true;
327: }
328:
329: public void mouseEntered(MouseEvent e) {
330: showSelection(e);
331: }
332:
333: public void mouseExited(MouseEvent e) {
334: clearSelection();
335: }
336:
337: public void mousePressed(MouseEvent e) {
338: mouseEventInvoked = false;
339: }
340:
341: public void mouseReleased(MouseEvent e) {
342: if (!mouseEventInvoked)
343: setSelection();
344: mouseEventInvoked = true;
345: }
346:
347: public void mouseMoved(MouseEvent e) {
348: showSelection(e);
349: }
350:
351: public void mouseDragged(MouseEvent e) {
352: showSelection(e);
353: }
354:
355: void setDateListener(XDateListener dl) {
356: listener = dl;
357: }
358:
359: /**
360: * Get the style asociated with the selected elements
361: * @return the style name
362: */
363: public String getStyleSelected() {
364: return styleSelected;
365: }
366:
367: /**
368: * Get the style asociated with the selected elements
369: * @param newStyle the style name
370: */
371: public void setStyleSelected(String newStyle) {
372: styleSelected = newStyle;
373: XStyle selectedStyle = styleManager.getStyle(styleSelected);
374: if (selectedStyle != null) {
375: selectedColor = selectedStyle
376: .getStyleAsColor(XStyle.COLOR_FORE);
377: selectedBkColor = selectedStyle
378: .getStyleAsColor(XStyle.COLOR_BACK);
379: }
380: }
381:
382: /**
383: * Get the style asociated with the weekend element
384: * @return the style name
385: */
386: public String getStyleWeekend() {
387: return styleWeekend;
388: }
389:
390: /**
391: * set the style asociated with weekend element
392: * @param newStyle the style name
393: */
394: public void setStyleWeekend(String newStyle) {
395: styleWeekend = newStyle;
396: XStyle weekendStyle = styleManager.getStyle(styleWeekend);
397: if (weekendStyle != null) {
398: weekendColor = weekendStyle
399: .getStyleAsColor(XStyle.COLOR_FORE);
400: weekendBkColor = weekendStyle
401: .getStyleAsColor(XStyle.COLOR_BACK);
402: }
403: repaint();
404: }
405:
406: /**
407: * Get the style asociated with the highlighted element
408: * @return the style name
409: */
410: public String getStyleHighlighted() {
411: return styleHighlighted;
412: }
413:
414: /**
415: * set the style asociated with highlighted element
416: * @param newStyle the style name
417: */
418: public void setStyleHighlighted(String newStyle) {
419: styleHighlighted = newStyle;
420: XStyle highlightedStyle = styleManager
421: .getStyle(styleHighlighted);
422: if (highlightedStyle != null) {
423: highlightedColor = highlightedStyle
424: .getStyleAsColor(XStyle.COLOR_FORE);
425: highlightedBkColor = highlightedStyle
426: .getStyleAsColor(XStyle.COLOR_BACK);
427: }
428: }
429:
430: /**
431: * Get the style asociated with the normal elements
432: * @return the style name
433: */
434: public String getStyle() {
435: return basicStyle;
436: }
437:
438: /**
439: * set the style asociated with the normal elements
440: * @param newStyle the style name
441: */
442: public void setStyle(String newStyle) {
443: basicStyle = newStyle;
444: XStyle style = styleManager.getStyle(basicStyle);
445: if (style != null) {
446: foregroundColor = style.getStyleAsColor(XStyle.COLOR_FORE);
447: backgroundColor = style.getStyleAsColor(XStyle.COLOR_BACK);
448: }
449: }
450:
451: /**
452: * Set the styles for the date panel
453: * @param styles the styles in the following order: style, selectedStyle, weekendStyle, highlightStyle, headerStyle, threeDStyle
454: */
455: public void setStyles(String[] styles) {
456: setStyle(styles[0]);
457: setStyleSelected(styles[1]);
458: setStyleWeekend(styles[2]);
459: setStyleHighlighted(styles[3]);
460: }
461:
462: /**
463: * Show or hide the day names
464: * @param state true to show the day names
465: */
466: public void setShowDayNames(boolean state) {
467: showDayNames = state;
468: }
469: }
|