PageRenderTime 135ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mpv5/ui/panels/calendar/ScheduleCalendarDayChooser.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/
Java | 693 lines | 454 code | 97 blank | 142 comment | 91 complexity | dd5904e4e5dae87e574ed2d7ea3db77e MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, GPL-3.0, GPL-2.0, AGPL-3.0, JSON, BSD-3-Clause
  1. /*
  2. * JDayChooser.java - A bean for choosing a day
  3. * Copyright (C) 2004 Kai Toedter
  4. * kai@toedter.com
  5. * www.toedter.com
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. package mpv5.ui.panels.calendar;
  22. import java.awt.BorderLayout;
  23. import java.awt.Color;
  24. import java.awt.Font;
  25. import java.awt.Graphics;
  26. import java.awt.GridLayout;
  27. import java.awt.Insets;
  28. import java.awt.event.KeyEvent;
  29. import java.awt.event.KeyListener;
  30. import java.awt.event.MouseListener;
  31. import java.text.DateFormatSymbols;
  32. import java.util.ArrayList;
  33. import java.util.Calendar;
  34. import java.util.Date;
  35. import java.util.Locale;
  36. import javax.swing.JButton;
  37. import javax.swing.JPanel;
  38. import javax.swing.UIManager;
  39. import javax.swing.border.LineBorder;
  40. import mpv5.db.objects.Schedule;
  41. import mpv5.logging.Log;
  42. import mpv5.ui.panels.ScheduleDayEventsPanel;
  43. import mpv5.utils.date.DateConverter;
  44. import mpv5.utils.date.vTimeframe;
  45. /**
  46. * JDayChooser is a bean for choosing a day.
  47. *
  48. * @author Kai Toedter
  49. * @version $LastChangedRevision: 104 $
  50. * @version $LastChangedDate: 2006-06-04 15:20:45 +0200 (So, 04 Jun 2006) $
  51. */
  52. public final class ScheduleCalendarDayChooser extends JPanel implements KeyListener {
  53. private static final long serialVersionUID = 5876398337018781820L;
  54. protected ScheduleCalendarButton[] days;
  55. protected JButton[] weeks;
  56. protected ScheduleCalendarButton selectedDay;
  57. protected JPanel weekPanel;
  58. protected JPanel dayPanel;
  59. protected int day;
  60. protected Color oldDayBackgroundColor;
  61. protected Color selectedColor;
  62. protected Color sundayForeground;
  63. protected Color weekdayForeground;
  64. protected Color decorationBackgroundColor;
  65. protected String[] dayNames;
  66. protected Calendar calendar;
  67. protected Calendar today;
  68. protected Locale locale;
  69. protected boolean initialized;
  70. protected boolean weekOfYearVisible;
  71. protected boolean decorationBackgroundVisible = false;
  72. protected boolean decorationBordersVisible;
  73. protected boolean dayBordersVisible;
  74. private boolean alwaysFireDayProperty;
  75. protected Date minSelectableDate;
  76. protected Date maxSelectableDate;
  77. protected Date defaultMinSelectableDate;
  78. protected Date defaultMaxSelectableDate;
  79. protected int maxDayCharacters;
  80. private static ArrayList<Schedule> events;
  81. private static ScheduleCalendarDayChooser icke;
  82. /**
  83. * The dc instance
  84. * @return
  85. */
  86. public static ScheduleCalendarDayChooser instanceOf() {
  87. if (icke == null) {
  88. icke = new ScheduleCalendarDayChooser(true);
  89. }
  90. return icke;
  91. }
  92. /**
  93. * JDayChooser constructor.
  94. *
  95. * @param weekOfYearVisible
  96. * true, if the weeks of a year shall be shown
  97. */
  98. private ScheduleCalendarDayChooser(boolean weekOfYearVisible) {
  99. setName("JDayChooser");
  100. setBackground(Color.blue);
  101. this.weekOfYearVisible = weekOfYearVisible;
  102. locale = Locale.getDefault();
  103. days = new ScheduleCalendarButton[49];
  104. selectedDay = null;
  105. calendar = Calendar.getInstance(locale);
  106. today = (Calendar) calendar.clone();
  107. setLayout(new BorderLayout());
  108. dayPanel = new JPanel();
  109. dayPanel.setLayout(new GridLayout(7, 7));
  110. maxDayCharacters = 2;
  111. sundayForeground = new Color(164, 0, 0);
  112. weekdayForeground = new Color(0, 90, 164);
  113. decorationBackgroundColor = new Color(238, 238, 238);
  114. for (int y = 0; y < 7; y++) {
  115. for (int x = 0; x < 7; x++) {
  116. int index = x + (7 * y);
  117. if (y == 0) {
  118. // Create a button that doesn't react on clicks or focus
  119. // changes.
  120. // Thanks to Thomas Schaefer for the focus hint :)
  121. days[index] = new DecoratorButton();
  122. } else {
  123. days[index] = new ScheduleCalendarButton(new Date()) {
  124. private static final long serialVersionUID = -7433645992591669725L;
  125. @Override
  126. public void paint(Graphics g) {
  127. if ("Windows".equals(UIManager.getLookAndFeel().getID())) {
  128. // this is a hack to get the background painted
  129. // when using Windows Look & Feel
  130. if (selectedDay == this) {
  131. g.setColor(selectedColor);
  132. g.fillRect(0, 0, getWidth(), getHeight());
  133. }
  134. }
  135. super.paint(g);
  136. }
  137. };
  138. days[index].addActionListener(days[index]);
  139. days[index].addKeyListener(this);
  140. }
  141. days[index].setMargin(new Insets(1, 1, 1, 1));
  142. days[index].setFocusPainted(true);
  143. days[index].setContentAreaFilled(true);
  144. days[index].setBorderPainted(true);
  145. dayPanel.add(days[index]);
  146. }
  147. }
  148. weekPanel = new JPanel();
  149. weekPanel.setLayout(new GridLayout(7, 1));
  150. weeks = new JButton[7];
  151. for (int i = 0; i < 7; i++) {
  152. weeks[i] = new DecoratorButton();
  153. weeks[i].setMargin(new Insets(0, 0, 0, 0));
  154. weeks[i].setFocusPainted(false);
  155. weeks[i].setForeground(new Color(100, 100, 100));
  156. if (i != 0) {
  157. weeks[i].setText("0" + (i + 1));
  158. }
  159. weekPanel.add(weeks[i]);
  160. }
  161. Calendar tmpCalendar = Calendar.getInstance();
  162. tmpCalendar.set(1, 0, 1, 1, 1);
  163. defaultMinSelectableDate = tmpCalendar.getTime();
  164. minSelectableDate = defaultMinSelectableDate;
  165. tmpCalendar.set(9999, 0, 1, 1, 1);
  166. defaultMaxSelectableDate = tmpCalendar.getTime();
  167. maxSelectableDate = defaultMaxSelectableDate;
  168. init();
  169. setDay(Calendar.getInstance().get(Calendar.DAY_OF_MONTH));
  170. add(dayPanel, BorderLayout.CENTER);
  171. add(weekPanel, BorderLayout.WEST);
  172. updateUI();
  173. }
  174. /**
  175. * Initilizes the locale specific names for the days of the week.
  176. */
  177. protected void init() {
  178. oldDayBackgroundColor = Color.WHITE;
  179. selectedColor = new Color(160, 160, 160);
  180. Date date = calendar.getTime();
  181. calendar = Calendar.getInstance(locale);
  182. calendar.setTime(date);
  183. drawDayNames();
  184. drawDays(Schedule.getEvents2(new vTimeframe(DateConverter.getStartOfMonth(new Date()), DateConverter.getEndOfMonth(new Date()))));
  185. }
  186. /**
  187. * Draws the day names of the day columnes.
  188. *
  189. */
  190. protected void drawDayNames() {
  191. int firstDayOfWeek = calendar.getFirstDayOfWeek();
  192. DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale);
  193. dayNames = dateFormatSymbols.getShortWeekdays();
  194. int fwd = firstDayOfWeek;
  195. for (int i = 0; i < 7; i++) {
  196. if (maxDayCharacters > 0 && maxDayCharacters < 5) {
  197. if (dayNames[fwd].length() >= maxDayCharacters) {
  198. dayNames[fwd] = dayNames[fwd].substring(0, maxDayCharacters);
  199. }
  200. }
  201. days[i].setText(dayNames[fwd]);
  202. days[i].setFont(days[i].getFont().deriveFont(Font.BOLD));
  203. if (fwd == 1) {
  204. days[i].setForeground(sundayForeground);
  205. } else {
  206. days[i].setForeground(weekdayForeground);
  207. }
  208. if (fwd < 7) {
  209. fwd++;
  210. } else {
  211. fwd -= 6;
  212. }
  213. }
  214. }
  215. /**
  216. * Hides and shows the week buttons.
  217. */
  218. protected void drawWeeks() {
  219. Calendar tmpCalendar = (Calendar) calendar.clone();
  220. for (int i = 1; i < 7; i++) {
  221. tmpCalendar.set(Calendar.DAY_OF_MONTH, (i * 7) - 6);
  222. int week = tmpCalendar.get(Calendar.WEEK_OF_YEAR);
  223. String buttonText = Integer.toString(week);
  224. if (week < 10) {
  225. buttonText = "0" + buttonText;
  226. }
  227. weeks[i].setText(buttonText);
  228. weeks[i].setContentAreaFilled(false);
  229. if ((i == 5) || (i == 6)) {
  230. weeks[i].setVisible(days[i * 7].isVisible());
  231. }
  232. }
  233. setDayBordersVisible(true);
  234. }
  235. /**
  236. * Hides and shows the day buttons.
  237. * @param list
  238. */
  239. protected void drawDays(ArrayList<Schedule> list) {
  240. if (list != null) {
  241. events = list;
  242. }
  243. Calendar tmpCalendar = (Calendar) calendar.clone();
  244. tmpCalendar.set(Calendar.HOUR_OF_DAY, 0);
  245. tmpCalendar.set(Calendar.MINUTE, 0);
  246. tmpCalendar.set(Calendar.SECOND, 0);
  247. tmpCalendar.set(Calendar.MILLISECOND, 0);
  248. Calendar minCal = Calendar.getInstance();
  249. minCal.setTime(minSelectableDate);
  250. minCal.set(Calendar.HOUR_OF_DAY, 0);
  251. minCal.set(Calendar.MINUTE, 0);
  252. minCal.set(Calendar.SECOND, 0);
  253. minCal.set(Calendar.MILLISECOND, 0);
  254. Calendar maxCal = Calendar.getInstance();
  255. maxCal.setTime(maxSelectableDate);
  256. maxCal.set(Calendar.HOUR_OF_DAY, 0);
  257. maxCal.set(Calendar.MINUTE, 0);
  258. maxCal.set(Calendar.SECOND, 0);
  259. maxCal.set(Calendar.MILLISECOND, 0);
  260. int firstDayOfWeek = tmpCalendar.getFirstDayOfWeek();
  261. tmpCalendar.set(Calendar.DAY_OF_MONTH, 1);
  262. int firstDay = tmpCalendar.get(Calendar.DAY_OF_WEEK) - firstDayOfWeek;
  263. if (firstDay < 0) {
  264. firstDay += 7;
  265. }
  266. int i;
  267. for (i = 0; i < firstDay; i++) {
  268. days[i + 7].setVisible(false);
  269. days[i + 7].setText("");
  270. }
  271. tmpCalendar.add(Calendar.MONTH, 1);
  272. Date firstDayInNextMonth = tmpCalendar.getTime();
  273. tmpCalendar.add(Calendar.MONTH, -1);
  274. Date time = tmpCalendar.getTime();
  275. int n = 0;
  276. Color foregroundColor = getForeground();
  277. while (time.before(firstDayInNextMonth)) {
  278. days[i + n + 7].setDate(time);
  279. days[i + n + 7].setText(Integer.toString(n + 1));
  280. days[i + n + 7].setVisible(true);
  281. Log.Debug(this, "Creating Day: " + days[i + n + 7].getText());
  282. if ((tmpCalendar.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) && (tmpCalendar.get(Calendar.YEAR) == today.get(Calendar.YEAR))) {
  283. days[i + n + 7].setForeground(sundayForeground);
  284. } else {
  285. days[i + n + 7].setForeground(foregroundColor);
  286. }
  287. if ((n + 1) == this.day) {
  288. days[i + n + 7].setBackground(selectedColor);
  289. selectedDay = days[i + n + 7];
  290. } else {
  291. days[i + n + 7].setBackground(oldDayBackgroundColor);
  292. }
  293. if (tmpCalendar.before(minCal) || tmpCalendar.after(maxCal)) {
  294. days[i + n + 7].setEnabled(false);
  295. } else {
  296. days[i + n + 7].setEnabled(true);
  297. }
  298. Log.Debug(this, "Checking events");
  299. int j = 0;
  300. if (events != null) {
  301. days[i + n + 7].clearScheduledEvents();
  302. while (!events.isEmpty() && events.size() > j) {
  303. Schedule schedule = events.get(j);
  304. Log.Debug(this, "Checking date: "
  305. + schedule.getDate()
  306. + " against "
  307. + days[i + n + 7].getText());
  308. if (schedule.getDate().contains(time)) {
  309. Log.Debug(this, "Found date: " + schedule.getDate());
  310. days[i + n + 7].addScheduledEvent(schedule);
  311. events.remove(j);
  312. } else {
  313. j++;
  314. }
  315. }
  316. }
  317. n++;
  318. tmpCalendar.add(Calendar.DATE, 1);
  319. time = tmpCalendar.getTime();
  320. }
  321. for (int k = n + i + 7; k < 49; k++) {
  322. days[k].setVisible(false);
  323. days[k].setText("");
  324. }
  325. drawWeeks();
  326. }
  327. /**
  328. * Returns the locale.
  329. *
  330. * @return the locale value
  331. *
  332. * @see #setLocale
  333. */
  334. @Override
  335. public Locale getLocale() {
  336. return locale;
  337. }
  338. /**
  339. * Sets the locale.
  340. *
  341. * @param locale
  342. * the new locale value
  343. *
  344. * @see #getLocale
  345. */
  346. @Override
  347. public void setLocale(Locale locale) {
  348. if (!initialized) {
  349. super.setLocale(locale);
  350. } else {
  351. this.locale = locale;
  352. super.setLocale(locale);
  353. init();
  354. }
  355. }
  356. /**
  357. * Sets the day. This is a bound property.
  358. *
  359. * @param d
  360. * the day
  361. *
  362. * @see #getDay
  363. */
  364. public void setDay(int d) {
  365. if (d < 1) {
  366. d = 1;
  367. }
  368. Calendar tmpCalendar = (Calendar) calendar.clone();
  369. tmpCalendar.set(Calendar.DAY_OF_MONTH, 1);
  370. tmpCalendar.add(Calendar.MONTH, 1);
  371. tmpCalendar.add(Calendar.DATE, -1);
  372. int maxDaysInMonth = tmpCalendar.get(Calendar.DATE);
  373. if (d > maxDaysInMonth) {
  374. d = maxDaysInMonth;
  375. }
  376. int oldDay = day;
  377. day = d;
  378. if (selectedDay != null) {
  379. selectedDay.setBackground(oldDayBackgroundColor);
  380. selectedDay.repaint();
  381. }
  382. for (int i = 7; i < 49; i++) {
  383. if (days[i].getText().equals(Integer.toString(day))) {
  384. selectedDay = days[i];
  385. selectedDay.setBackground(selectedColor);
  386. } else if (days[i].hasEvents()) {
  387. days[i].setBackground(Color.GREEN);
  388. }
  389. }
  390. if (alwaysFireDayProperty) {
  391. firePropertyChange("day", 0, day);
  392. } else {
  393. firePropertyChange("day", oldDay, day);
  394. }
  395. }
  396. /**
  397. * Returns the selected day.
  398. *
  399. * @return the day value
  400. *
  401. * @see #setDay
  402. */
  403. public int getDay() {
  404. return day;
  405. }
  406. /**
  407. * Sets a specific month. This is needed for correct graphical
  408. * representation of the days.
  409. *
  410. * @param month
  411. * the new month
  412. */
  413. public void setMonth(int month) {
  414. int maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
  415. calendar.set(Calendar.MONTH, month);
  416. if (maxDays == day) {
  417. day = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
  418. }
  419. Log.Debug(this,
  420. "Setting Month to: " + calendar.getDisplayName(
  421. month,
  422. Calendar.LONG,
  423. locale));
  424. setDay(day);
  425. drawDays(
  426. Schedule.getEvents2(
  427. new vTimeframe(
  428. DateConverter.getStartOfMonth(calendar.getTime()),
  429. DateConverter.getEndOfMonth(calendar.getTime()))));
  430. }
  431. /**
  432. * Sets a specific year. This is needed for correct graphical representation
  433. * of the days.
  434. *
  435. * @param year
  436. * the new year
  437. */
  438. public void setYear(int year) {
  439. calendar.set(Calendar.YEAR, year);
  440. drawDays(
  441. Schedule.getEvents2(
  442. new vTimeframe(
  443. DateConverter.getStartOfMonth(calendar.getTime()),
  444. DateConverter.getEndOfMonth(calendar.getTime()))));
  445. ScheduleDayEventsPanel.instanceOf().setDayEvents(null);
  446. }
  447. /**
  448. * Sets a specific calendar. This is needed for correct graphical
  449. * representation of the days.
  450. *
  451. * @param calendar
  452. * the new calendar
  453. */
  454. public void setCalendar(Calendar calendar) {
  455. this.calendar = calendar;
  456. drawDays(
  457. Schedule.getEvents2(
  458. new vTimeframe(
  459. DateConverter.getStartOfMonth(calendar.getTime()),
  460. DateConverter.getEndOfMonth(calendar.getTime()))));
  461. }
  462. /**
  463. * Sets the font property.
  464. *
  465. * @param font
  466. * the new font
  467. */
  468. @Override
  469. public void setFont(Font font) {
  470. if (days != null) {
  471. for (int i = 0; i < 49; i++) {
  472. days[i].setFont(font);
  473. }
  474. }
  475. if (weeks != null) {
  476. for (int i = 0; i < 7; i++) {
  477. weeks[i].setFont(font);
  478. }
  479. }
  480. }
  481. /**
  482. * JDayChooser is the KeyListener for all day buttons. (Added by Thomas
  483. * Schaefer and modified by Austin Moore)
  484. *
  485. * @param e
  486. * the KeyEvent
  487. */
  488. public void keyPressed(KeyEvent e) {
  489. int offset = (e.getKeyCode() == KeyEvent.VK_UP) ? (-7)
  490. : ((e.getKeyCode() == KeyEvent.VK_DOWN) ? (+7)
  491. : ((e.getKeyCode() == KeyEvent.VK_LEFT) ? (-1)
  492. : ((e.getKeyCode() == KeyEvent.VK_RIGHT) ? (+1) : 0)));
  493. int newDay = getDay() + offset;
  494. if ((newDay >= 1) && (newDay <= calendar.getMaximum(Calendar.DAY_OF_MONTH))) {
  495. setDay(newDay);
  496. }
  497. }
  498. /**
  499. * Does nothing.
  500. *
  501. * @param e
  502. * the KeyEvent
  503. */
  504. public void keyTyped(KeyEvent e) {
  505. }
  506. /**
  507. * Does nothing.
  508. *
  509. * @param e
  510. * the KeyEvent
  511. */
  512. public void keyReleased(KeyEvent e) {
  513. }
  514. public void setDayBordersVisible(boolean dayBordersVisible) {
  515. this.dayBordersVisible = dayBordersVisible;
  516. if (initialized) {
  517. for (int x = 0; x < 7; x++) {
  518. days[x].setContentAreaFilled(false);
  519. days[x].setBorder(new LineBorder(Color.white, 1, false));
  520. days[x].setBorderPainted(true);
  521. days[x].setBackground(Color.LIGHT_GRAY);
  522. }
  523. for (int x = 7; x < 49; x++) {
  524. days[x].setContentAreaFilled(false);
  525. days[x].setBorderPainted(dayBordersVisible);
  526. days[x].setBorder(new LineBorder(Color.darkGray, 1, false));
  527. }
  528. }
  529. }
  530. public void refreshDayPanels(Date nday, Schedule sched, Boolean add) {
  531. Log.Debug(this, "aktualisieren DaySelektor ... geklickt");
  532. for (int o = 0; o < days.length; o++) {
  533. // Log.Debug(this, "Checking ..." + days[o].getDate() + "\n"
  534. // + "angainst ..." + nday );
  535. if (days[o].getDate().equals(nday)) {
  536. if (add) {
  537. Log.Debug(this, "aktualisieren DaySelektor ... a");
  538. days[o].addScheduledEvent(sched);
  539. } else {
  540. Log.Debug(this, "aktualisieren DaySelektor ... b");
  541. days[o].removeScheduledEvent(sched);
  542. }
  543. }
  544. }
  545. Log.Debug(this, "aktualisieren DaySelektor ... fertig");
  546. }
  547. public ArrayList<Schedule> getScheduledEvents(Date nday) {
  548. for (int o = 0; o < days.length; o++) {
  549. if (days[o].getDate().equals(nday)) {
  550. return days[o].getScheduledEvents();
  551. }
  552. }
  553. return null;
  554. }
  555. /**
  556. * Creates a JFrame with a JDayChooser inside and can be used for testing.
  557. *
  558. * @param s
  559. * The command line arguments
  560. */
  561. class DecoratorButton extends ScheduleCalendarButton {
  562. private static final long serialVersionUID = -5306477668406547496L;
  563. public DecoratorButton() {
  564. super(new Date());
  565. setBackground(decorationBackgroundColor);
  566. setContentAreaFilled(decorationBackgroundVisible);
  567. setBorderPainted(decorationBordersVisible);
  568. }
  569. @Override
  570. public void addMouseListener(MouseListener l) {
  571. }
  572. @Override
  573. public boolean isFocusable() {
  574. return false;
  575. }
  576. @Override
  577. public void paint(Graphics g) {
  578. if ("Windows".equals(UIManager.getLookAndFeel().getID())) {
  579. // this is a hack to get the background painted
  580. // when using Windows Look & Feel
  581. if (decorationBackgroundVisible) {
  582. g.setColor(decorationBackgroundColor);
  583. } else {
  584. g.setColor(days[7].getBackground());
  585. }
  586. g.fillRect(0, 0, getWidth(), getHeight());
  587. if (isBorderPainted()) {
  588. setContentAreaFilled(true);
  589. } else {
  590. setContentAreaFilled(false);
  591. }
  592. }
  593. super.paint(g);
  594. }
  595. };
  596. }