001: /*--------------------------------------------------------------------------*
002: | Copyright (C) 2006 Gereon Fassbender, Christopher Kohlhaas |
003: | |
004: | This program is free software; you can redistribute it and/or modify |
005: | it under the terms of the GNU General Public License as published by the |
006: | Free Software Foundation. A copy of the license has been included with |
007: | these distribution in the COPYING file, if not go to www.fsf.org |
008: | |
009: | As a special exception, you are granted the permissions to link this |
010: | program with every library, which license fulfills the Open Source |
011: | Definition as published by the Open Source Initiative (OSI). |
012: *--------------------------------------------------------------------------*/
013:
014: package org.rapla.components.calendarview.swing;
015:
016: import java.text.*;
017: import java.util.*;
018: import java.awt.*;
019: import javax.swing.*;
020:
021: /** A vertical scale displaying the hours of day. Uses am/pm notation
022: * in the appropriate locale.
023: */
024: public class TimeScale extends JComponent {
025: private static final long serialVersionUID = 1L;
026:
027: private int pixelPerHour = 60;
028: private int mintime;
029: private int maxtime;
030: private boolean useAM_PM = false;
031: private Font fontLarge = new Font("SansSerif", Font.PLAIN, 14);
032: private Font fontSmall = new Font("SansSerif", Font.PLAIN, 9);
033: private FontMetrics fm1 = getFontMetrics(fontLarge);
034: private FontMetrics fm2 = getFontMetrics(fontSmall);
035: String[] hours;
036: private int SCALE_WIDTH = 35;
037: private boolean smallSize = false;
038: private int repeat = 1;
039: private String days[];
040:
041: public TimeScale() {
042: useAM_PM = isAmPmFormat(Locale.getDefault());
043: createHours(Locale.getDefault());
044: }
045:
046: public void setLocale(Locale locale) {
047: if (locale == null)
048: return;
049: useAM_PM = isAmPmFormat(locale);
050: createHours(locale);
051: }
052:
053: public static boolean isAmPmFormat(Locale locale) {
054: // Determines if am-pm-format should be used.
055: DateFormat format = DateFormat.getTimeInstance(
056: DateFormat.SHORT, locale);
057: FieldPosition amPmPos = new FieldPosition(
058: DateFormat.AM_PM_FIELD);
059: format.format(new Date(), new StringBuffer(), amPmPos);
060: return (amPmPos.getEndIndex() > 0);
061: }
062:
063: /**
064: mintime und maxtime definieren das zeitintevall in vollen stunden.
065: die skalen-einteilung wird um vgap pixel nach unten verschoben
066: (um ggf. zu justieren).
067: */
068: public void setTimeIntervall(int mintime, int maxtime,
069: int pixelPerHour) {
070: removeAll();
071: this .mintime = mintime;
072: this .maxtime = maxtime;
073: this .pixelPerHour = pixelPerHour;
074: //setBackground(Color.yellow);
075: //super(JSeparator.VERTICAL);
076: setLayout(null);
077: setPreferredSize(new Dimension(SCALE_WIDTH,
078: (maxtime - mintime + 1) * pixelPerHour * repeat));
079: }
080:
081: private void createHours(Locale locale) {
082: hours = new String[24];
083: Calendar cal = Calendar.getInstance(locale);
084: SimpleDateFormat format = new SimpleDateFormat(useAM_PM ? "h"
085: : "H", locale);
086: for (int i = 0; i < 24; i++) {
087: cal.set(Calendar.HOUR_OF_DAY, i);
088: hours[i] = format.format(cal.getTime());
089: }
090: }
091:
092: public void setSmallSize(boolean smallSize) {
093: this .smallSize = smallSize;
094: }
095:
096: public void setRepeat(int repeat, String[] days) {
097: this .repeat = repeat;
098: this .days = days;
099: }
100:
101: public void paint(Graphics g) {
102: super .paint(g);
103: int indent[];
104: int heightHour = (int) fm1.getLineMetrics("12", g).getHeight();
105: int heightEnding = (int) fm2.getLineMetrics("12", g)
106: .getHeight();
107: int current_y;
108:
109: // Compute indentations
110: FontMetrics fm;
111: String[] indent_string = new String[3];
112: if (days != null) {
113: indent_string[0] = "M";
114: indent_string[1] = "M2";
115: indent_string[2] = "M22";
116: } else {
117: indent_string[0] = "";
118: indent_string[1] = "2";
119: indent_string[2] = "22";
120: }
121: if (smallSize) {
122: fm = fm2;
123: } else {
124: fm = fm1;
125: }
126:
127: indent = new int[3];
128: for (int i = 0; i < 3; i++) {
129: indent[i] = (int) fm.stringWidth(indent_string[i]);
130: }
131:
132: Rectangle rect = g.getClipBounds();
133: //System.out.println(mintime + " - " + maxtime);
134: int height = (maxtime - mintime) * pixelPerHour + 1;
135:
136: if (days != null) {
137: g
138: .drawLine(indent[0] + 1, 0, indent[0] + 1, repeat
139: * height);
140: }
141:
142: for (int r = 0; r < repeat; r++) {
143: current_y = height * r;
144: g.drawLine(0, current_y - 1, SCALE_WIDTH, current_y - 1);
145: int pad = 0;
146: if (days != null) {
147: pad = (maxtime - mintime - days[r].length()) / 2;
148: if (pad < 0) {
149: pad = 0;
150: }
151: }
152: for (int i = mintime; i < maxtime; i++) {
153: int y = current_y + (i - mintime) * pixelPerHour;
154: int hour;
155: String ending;
156: String prefix;
157: if (useAM_PM) {
158: hour = (i == 0) ? 12 : ((i - 1) % 12 + 1);
159: ending = (i <= 11) ? "AM" : "PM";
160: } else {
161: hour = i;
162: ending = "00";
163: }
164:
165: if (days != null
166: && i - mintime < days[r].length() + pad
167: && i - mintime >= pad) {
168: prefix = days[r].substring(i - mintime - pad, i
169: - mintime + 1 - pad);
170: } else {
171: prefix = null;
172: }
173:
174: if (y >= rect.y && y <= (rect.y + rect.height)) {
175: g.drawLine(i == mintime ? 0 : indent[0] + 1, y,
176: SCALE_WIDTH, y);
177: }
178: if (y >= rect.y - heightHour
179: && y <= (rect.y + rect.height) + heightHour) {
180: if (smallSize) {
181: g.setFont(fontSmall);
182: } else {
183: g.setFont(fontLarge);
184: }
185: if (prefix != null) {
186: g.drawString(prefix, (indent[0]
187: - fm.stringWidth(prefix) + 1) / 2, y
188: + heightEnding);
189: }
190: g.drawString(hours[i], (hour < 10) ? indent[1] + 2
191: : indent[0] + 2, y
192: + (smallSize ? heightEnding : heightHour));
193: if (!smallSize) {
194: g.setFont(fontSmall);
195: }
196: g.drawString(ending, indent[2] + 2, y
197: + heightEnding);
198: }
199: }
200: }
201: }
202: }
|