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