1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package fr.ifremer.quadrige3.ui.swing.component.date;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 import fr.ifremer.quadrige3.ui.swing.component.date.constraints.DateSelectionConstraint;
55
56 import javax.swing.*;
57 import javax.swing.event.ChangeEvent;
58 import javax.swing.event.ChangeListener;
59 import javax.swing.event.TableModelEvent;
60 import javax.swing.event.TableModelListener;
61 import javax.swing.table.DefaultTableCellRenderer;
62 import javax.swing.table.JTableHeader;
63 import javax.swing.table.TableColumn;
64 import javax.swing.table.TableModel;
65 import java.awt.*;
66 import java.awt.event.*;
67 import java.text.DateFormat;
68 import java.util.*;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class JDatePanel extends JComponent {
87
88 private static final long serialVersionUID = -2299249311312882915L;
89
90
91 public static final String COMMIT_DATE = "commit";
92
93 private final Set<ActionListener> actionListeners;
94 private final Set<DateSelectionConstraint> dateConstraints;
95
96 private boolean showYearButtons;
97 private boolean doubleClickAction;
98 private final int firstDayOfWeek;
99
100 private final InternalCalendarModel internalModel;
101 private final InternalController internalController;
102 private final InternalView internalView;
103
104
105
106
107 public JDatePanel() {
108 this(createModel());
109 }
110
111
112
113
114
115
116 public JDatePanel(DateModel model) {
117 actionListeners = new HashSet<>();
118 dateConstraints = new HashSet<>();
119
120 showYearButtons = false;
121 doubleClickAction = false;
122 firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();
123
124 internalModel = new InternalCalendarModel(model);
125 internalController = new InternalController();
126 internalView = new InternalView();
127
128 setLayout(new GridLayout(1, 1));
129 add(internalView);
130 }
131
132
133
134
135
136
137 public static DateModel createModel() {
138 return new DateModel();
139 }
140
141
142
143
144
145
146 public void addActionListener(ActionListener actionListener) {
147 actionListeners.add(actionListener);
148 }
149
150
151
152
153
154
155 public void removeActionListener(ActionListener actionListener) {
156 actionListeners.remove(actionListener);
157 }
158
159
160
161
162 private void fireActionPerformed() {
163 for (ActionListener actionListener : actionListeners) {
164 actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, COMMIT_DATE));
165 }
166 }
167
168
169
170
171
172
173 public void setShowYearButtons(boolean showYearButtons) {
174 this.showYearButtons = showYearButtons;
175 internalView.updateShowYearButtons();
176 }
177
178
179
180
181
182
183 public boolean isShowYearButtons() {
184 return this.showYearButtons;
185 }
186
187
188
189
190
191
192 public void setDoubleClickAction(boolean doubleClickAction) {
193 this.doubleClickAction = doubleClickAction;
194 }
195
196
197
198
199
200
201 public boolean isDoubleClickAction() {
202 return doubleClickAction;
203 }
204
205
206
207
208
209
210 public DateModel getModel() {
211 return internalModel.getModel();
212 }
213
214
215
216
217
218
219 public void addDateSelectionConstraint(DateSelectionConstraint constraint) {
220 dateConstraints.add(constraint);
221 }
222
223
224
225
226
227
228 public void removeDateSelectionConstraint(DateSelectionConstraint constraint) {
229 dateConstraints.remove(constraint);
230 }
231
232
233
234
235 public void removeAllDateSelectionConstraints() {
236 dateConstraints.clear();
237 }
238
239
240
241
242
243
244 public Set<DateSelectionConstraint> getDateSelectionConstraints() {
245 return Collections.unmodifiableSet(dateConstraints);
246 }
247
248
249
250
251
252
253
254 protected boolean checkConstraints(DateModel model) {
255 for (DateSelectionConstraint constraint : dateConstraints) {
256 if (!constraint.isValidSelection(model)) {
257 return false;
258 }
259 }
260 return true;
261 }
262
263 private static ComponentTextDefaults getTexts() {
264 return ComponentTextDefaults.getInstance();
265 }
266
267 private static ComponentIconDefaults getIcons() {
268 return ComponentIconDefaults.getInstance();
269 }
270
271 private AbstractComponentColor colors;
272
273
274
275
276
277
278 public AbstractComponentColor getColors() {
279 if (colors == null) {
280 try {
281 colors = ComponentColorDefaults.getInstance().clone();
282 } catch (CloneNotSupportedException e) {
283 colors = ComponentColorDefaults.getInstance();
284 }
285 }
286 return colors;
287 }
288
289 private static ComponentFormatDefaults getFormats() {
290 return ComponentFormatDefaults.getInstance();
291 }
292
293
294 @Override
295 public void setVisible(boolean aFlag) {
296 super.setVisible(aFlag);
297
298 if (aFlag) {
299 internalView.updateTodayLabel();
300 }
301 }
302
303
304 @Override
305 public void setEnabled(boolean enabled) {
306 internalView.setEnabled(enabled);
307
308 super.setEnabled(enabled);
309 }
310
311
312
313
314
315
316 public Date getDate() {
317 return getModel().getDate();
318 }
319
320
321
322
323
324
325 public void setDate(Date date) {
326 getModel().setDate(date);
327 }
328
329
330
331
332
333
334 private class InternalView extends JPanel {
335
336 private static final long serialVersionUID = -6844493839307157682L;
337
338 private static final int DEFAULT_WIDTH = 280;
339 private static final int DEFAULT_HEIGHT = 200;
340
341 private JPanel centerPanel;
342 private JPanel northCenterPanel;
343 private JPanel northPanel;
344 private JPanel southPanel;
345 private JPanel previousButtonPanel;
346 private JPanel nextButtonPanel;
347 private JTable dayTable;
348 private JTableHeader dayTableHeader;
349 private InternalTableCellRenderer dayTableCellRenderer;
350 private JLabel monthLabel;
351 private JLabel todayLabel;
352 private JLabel noneLabel;
353 private JPopupMenu monthPopupMenu;
354 private JMenuItem[] monthPopupMenuItems;
355 private JButton nextMonthButton;
356 private JButton previousMonthButton;
357 private JButton previousYearButton;
358 private JButton nextYearButton;
359 private JSpinner yearSpinner;
360
361
362
363
364 private void updateShowYearButtons() {
365 if (showYearButtons) {
366 getNextButtonPanel().add(getNextYearButton());
367 getPreviousButtonPanel().removeAll();
368 getPreviousButtonPanel().add(getPreviousYearButton());
369 getPreviousButtonPanel().add(getPreviousMonthButton());
370 } else {
371 getNextButtonPanel().remove(getNextYearButton());
372 getPreviousButtonPanel().remove(getPreviousYearButton());
373 }
374 }
375
376
377
378
379 private void updateMonthLabel() {
380 monthLabel.setText(getTexts().getText(ComponentTextDefaults.Key.getMonthKey(internalModel.getModel().getMonth())));
381 }
382
383 public InternalView() {
384 initialise();
385 }
386
387
388
389
390 private void initialise() {
391 this.setLayout(new java.awt.BorderLayout());
392 this.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
393 this.setPreferredSize(getSize());
394 this.setOpaque(false);
395 this.add(getNorthPanel(), java.awt.BorderLayout.NORTH);
396 this.add(getSouthPanel(), java.awt.BorderLayout.SOUTH);
397 this.add(getCenterPanel(), java.awt.BorderLayout.CENTER);
398 }
399
400
401
402
403
404
405 private JPanel getNorthPanel() {
406 if (northPanel == null) {
407 northPanel = new javax.swing.JPanel();
408 northPanel.setLayout(new java.awt.BorderLayout());
409 northPanel.setName("");
410 northPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(3, 3, 3, 3));
411 northPanel.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_MONTH_SELECTOR));
412 northPanel.add(getPreviousButtonPanel(), java.awt.BorderLayout.WEST);
413 northPanel.add(getNextButtonPanel(), java.awt.BorderLayout.EAST);
414 northPanel.add(getNorthCenterPanel(), java.awt.BorderLayout.CENTER);
415 }
416 return northPanel;
417 }
418
419
420
421
422
423
424 private JPanel getNorthCenterPanel() {
425 if (northCenterPanel == null) {
426 northCenterPanel = new javax.swing.JPanel();
427 northCenterPanel.setLayout(new java.awt.BorderLayout());
428 northCenterPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 5, 0, 5));
429 northCenterPanel.setOpaque(false);
430 northCenterPanel.add(getMonthLabel(), java.awt.BorderLayout.CENTER);
431 northCenterPanel.add(getYearSpinner(), java.awt.BorderLayout.EAST);
432 }
433 return northCenterPanel;
434 }
435
436
437
438
439
440
441 private JLabel getMonthLabel() {
442 if (monthLabel == null) {
443 monthLabel = new javax.swing.JLabel();
444 monthLabel.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_MONTH_SELECTOR));
445 monthLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
446 monthLabel.addMouseListener(internalController);
447 updateMonthLabel();
448 }
449 return monthLabel;
450 }
451
452
453
454
455
456
457 private JSpinner getYearSpinner() {
458 if (yearSpinner == null) {
459 yearSpinner = new javax.swing.JSpinner();
460 yearSpinner.setModel(internalModel);
461 }
462 return yearSpinner;
463 }
464
465
466
467
468
469
470 private JPanel getSouthPanel() {
471 if (southPanel == null) {
472 southPanel = new javax.swing.JPanel();
473 southPanel.setLayout(new java.awt.BorderLayout());
474 southPanel.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_TODAY_SELECTOR));
475 southPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(3, 3, 3, 3));
476 southPanel.add(getTodayLabel(), java.awt.BorderLayout.WEST);
477 southPanel.add(getNoneLabel(), java.awt.BorderLayout.EAST);
478 }
479 return southPanel;
480 }
481
482
483
484
485
486
487 private JLabel getNoneLabel() {
488 if (noneLabel == null) {
489 noneLabel = new javax.swing.JLabel();
490 noneLabel.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_TODAY_SELECTOR_ENABLED));
491 noneLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
492 noneLabel.addMouseListener(internalController);
493
494
495 noneLabel.setIcon(getIcons().getClearIcon());
496 }
497 return noneLabel;
498 }
499
500 private void updateTodayLabel() {
501 Calendar now = Calendar.getInstance();
502 DateFormat df = getFormats().getFormat(ComponentFormatDefaults.Key.TODAY_SELECTOR);
503 todayLabel.setText(getTexts().getText(
504 ComponentTextDefaults.Key.TODAY)
505 + ": "
506 + df.format(now.getTime()));
507 }
508
509
510
511
512
513
514 private JLabel getTodayLabel() {
515 if (todayLabel == null) {
516 todayLabel = new javax.swing.JLabel();
517 todayLabel.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_TODAY_SELECTOR_ENABLED));
518 todayLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
519 todayLabel.addMouseListener(internalController);
520 updateTodayLabel();
521 }
522 return todayLabel;
523 }
524
525
526
527
528
529
530 private JPanel getCenterPanel() {
531 if (centerPanel == null) {
532 centerPanel = new javax.swing.JPanel();
533 centerPanel.setLayout(new java.awt.BorderLayout());
534 centerPanel.setOpaque(false);
535 centerPanel.add(getDayTableHeader(), java.awt.BorderLayout.NORTH);
536 centerPanel.add(getDayTable(), java.awt.BorderLayout.CENTER);
537 }
538 return centerPanel;
539 }
540
541
542
543
544
545
546 private JTable getDayTable() {
547 if (dayTable == null) {
548 dayTable = new javax.swing.JTable();
549 dayTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
550 dayTable.setModel(internalModel);
551 dayTable.setShowGrid(true);
552 dayTable.setGridColor(getColors().getColor(AbstractComponentColor.Key.BG_GRID));
553 dayTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
554 dayTable.setCellSelectionEnabled(true);
555 dayTable.setRowSelectionAllowed(true);
556 dayTable.setFocusable(false);
557 dayTable.addMouseListener(internalController);
558 for (int i = 0; i < 7; i++) {
559 TableColumn column = dayTable.getColumnModel().getColumn(i);
560 column.setCellRenderer(getDayTableCellRenderer());
561 }
562 dayTable.addComponentListener(new ComponentListener() {
563
564 public void componentResized(ComponentEvent e) {
565
566 final double w = e.getComponent().getSize().getWidth();
567 final double h = e.getComponent().getSize().getHeight();
568
569
570 final float sw = (float) (w / 18);
571 final float sh = (float) (h / 9);
572 float fs = Math.min(sw, sh);
573 dayTable.setFont(dayTable.getFont().deriveFont(fs));
574
575
576 final int r = (int) Math.floor(h / 6);
577 dayTable.setRowHeight(r);
578 }
579
580 public void componentMoved(ComponentEvent e) {
581
582 }
583
584 public void componentShown(ComponentEvent e) {
585
586 }
587
588 public void componentHidden(ComponentEvent e) {
589
590 }
591
592 });
593 }
594 return dayTable;
595 }
596
597 private InternalTableCellRenderer getDayTableCellRenderer() {
598 if (dayTableCellRenderer == null) {
599 dayTableCellRenderer = new InternalTableCellRenderer();
600 }
601 return dayTableCellRenderer;
602 }
603
604 private JTableHeader getDayTableHeader() {
605 if (dayTableHeader == null) {
606 dayTableHeader = getDayTable().getTableHeader();
607 dayTableHeader.setResizingAllowed(false);
608 dayTableHeader.setReorderingAllowed(false);
609 dayTableHeader.setDefaultRenderer(getDayTableCellRenderer());
610 }
611 return dayTableHeader;
612 }
613
614
615
616
617
618
619 private JPanel getPreviousButtonPanel() {
620 if (previousButtonPanel == null) {
621 previousButtonPanel = new javax.swing.JPanel();
622 java.awt.GridLayout layout = new java.awt.GridLayout(1, 2);
623 layout.setHgap(3);
624 previousButtonPanel.setLayout(layout);
625 previousButtonPanel.setName("");
626 previousButtonPanel.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_MONTH_SELECTOR));
627 if (isShowYearButtons()) {
628 previousButtonPanel.add(getPreviousYearButton());
629 }
630 previousButtonPanel.add(getPreviousMonthButton());
631 }
632 return previousButtonPanel;
633 }
634
635
636
637
638
639
640 private JPanel getNextButtonPanel() {
641 if (nextButtonPanel == null) {
642 nextButtonPanel = new javax.swing.JPanel();
643 java.awt.GridLayout layout = new java.awt.GridLayout(1, 2);
644 layout.setHgap(3);
645 nextButtonPanel.setLayout(layout);
646 nextButtonPanel.setName("");
647 nextButtonPanel.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_MONTH_SELECTOR));
648 nextButtonPanel.add(getNextMonthButton());
649 if (isShowYearButtons()) {
650 nextButtonPanel.add(getNextYearButton());
651 }
652 }
653 return nextButtonPanel;
654 }
655
656
657
658
659
660
661 private JButton getNextMonthButton() {
662 if (nextMonthButton == null) {
663 nextMonthButton = new JButton();
664 nextMonthButton.setIcon(getIcons().getNextMonthIconEnabled());
665 nextMonthButton.setDisabledIcon(getIcons().getNextMonthIconDisabled());
666 nextMonthButton.setText("");
667 nextMonthButton.setPreferredSize(new java.awt.Dimension(20, 15));
668 nextMonthButton.setFocusable(false);
669 nextMonthButton.addActionListener(internalController);
670 nextMonthButton.setToolTipText(getTexts().getText(ComponentTextDefaults.Key.MONTH));
671 }
672 return nextMonthButton;
673 }
674
675
676
677
678
679
680 private JButton getNextYearButton() {
681 if (nextYearButton == null) {
682 nextYearButton = new JButton();
683 nextYearButton.setIcon(getIcons().getNextYearIconEnabled());
684 nextYearButton.setDisabledIcon(getIcons().getNextYearIconDisabled());
685 nextYearButton.setText("");
686 nextYearButton.setPreferredSize(new java.awt.Dimension(20, 15));
687 nextYearButton.setFocusable(false);
688 nextYearButton.addActionListener(internalController);
689 nextYearButton.setToolTipText(getTexts().getText(ComponentTextDefaults.Key.YEAR));
690 }
691 return nextYearButton;
692 }
693
694
695
696
697
698
699 private JButton getPreviousMonthButton() {
700 if (previousMonthButton == null) {
701 previousMonthButton = new JButton();
702 previousMonthButton.setIcon(getIcons().getPreviousMonthIconEnabled());
703 previousMonthButton.setDisabledIcon(getIcons().getPreviousMonthIconDisabled());
704 previousMonthButton.setText("");
705 previousMonthButton.setPreferredSize(new java.awt.Dimension(20, 15));
706 previousMonthButton.setFocusable(false);
707 previousMonthButton.addActionListener(internalController);
708 previousMonthButton.setToolTipText(getTexts().getText(ComponentTextDefaults.Key.MONTH));
709 }
710 return previousMonthButton;
711 }
712
713
714
715
716
717
718 private JButton getPreviousYearButton() {
719 if (previousYearButton == null) {
720 previousYearButton = new JButton();
721 previousYearButton.setIcon(getIcons().getPreviousYearIconEnabled());
722 previousYearButton.setDisabledIcon(getIcons().getPreviousYearIconDisabled());
723 previousYearButton.setText("");
724 previousYearButton.setPreferredSize(new java.awt.Dimension(20, 15));
725 previousYearButton.setFocusable(false);
726 previousYearButton.addActionListener(internalController);
727 previousYearButton.setToolTipText(getTexts().getText(ComponentTextDefaults.Key.YEAR));
728 }
729 return previousYearButton;
730 }
731
732
733
734
735
736
737 private JPopupMenu getMonthPopupMenu() {
738 if (monthPopupMenu == null) {
739 monthPopupMenu = new javax.swing.JPopupMenu();
740 JMenuItem[] menuItems = getMonthPopupMenuItems();
741 for (JMenuItem menuItem : menuItems) {
742 monthPopupMenu.add(menuItem);
743 }
744 }
745 return monthPopupMenu;
746 }
747
748 private JMenuItem[] getMonthPopupMenuItems() {
749 if (monthPopupMenuItems == null) {
750 monthPopupMenuItems = new JMenuItem[12];
751 for (int i = 0; i < 12; i++) {
752 JMenuItem mi = new JMenuItem(getTexts().getText(ComponentTextDefaults.Key.getMonthKey(i)));
753 mi.addActionListener(internalController);
754 monthPopupMenuItems[i] = mi;
755 }
756 }
757 return monthPopupMenuItems;
758 }
759
760 @Override
761 public void setEnabled(boolean enabled) {
762 dayTable.setEnabled(enabled);
763 dayTableCellRenderer.setEnabled(enabled);
764 nextMonthButton.setEnabled(enabled);
765 if (nextYearButton != null) {
766 nextYearButton.setEnabled(enabled);
767 }
768 previousMonthButton.setEnabled(enabled);
769 if (previousYearButton != null) {
770 previousYearButton.setEnabled(enabled);
771 }
772 yearSpinner.setEnabled(enabled);
773 if (enabled) {
774 todayLabel.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_TODAY_SELECTOR_ENABLED));
775 } else {
776 todayLabel.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_TODAY_SELECTOR_DISABLED));
777 }
778
779 super.setEnabled(enabled);
780 }
781 }
782
783
784
785
786
787
788
789 private class InternalTableCellRenderer extends DefaultTableCellRenderer {
790
791 private static final long serialVersionUID = -2341614459632756921L;
792
793 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
794
795 if (value == null) {
796 return super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);
797 }
798
799 JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
800 label.setHorizontalAlignment(JLabel.CENTER);
801
802 if (row == -1) {
803 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_HEADER));
804 label.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_GRID_HEADER));
805 label.setHorizontalAlignment(JLabel.CENTER);
806 return label;
807 }
808
809 Calendar todayCal = Calendar.getInstance();
810 Calendar selectedCal = Calendar.getInstance();
811 selectedCal.set(internalModel.getModel().getYear(), internalModel.getModel().getMonth(), internalModel.getModel().getDay());
812
813 int cellDayValue = (Integer) value;
814 int lastDayOfMonth = selectedCal.getActualMaximum(Calendar.DAY_OF_MONTH);
815
816
817 if (cellDayValue < 1 || cellDayValue > lastDayOfMonth) {
818 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_OTHER_MONTH));
819
820 Calendar calForDay = Calendar.getInstance();
821 calForDay.set(internalModel.getModel().getYear(), internalModel.getModel().getMonth(), cellDayValue);
822 DateModel modelForDay = new DateModel(calForDay);
823 label.setBackground(checkConstraints(modelForDay) ?
824 getColors().getColor(AbstractComponentColor.Key.BG_GRID) :
825 getColors().getColor(AbstractComponentColor.Key.BG_GRID_NOT_SELECTABLE)
826 );
827
828
829 if (cellDayValue > lastDayOfMonth) {
830 label.setText(Integer.toString(cellDayValue - lastDayOfMonth));
831 }
832
833 else {
834 Calendar lastMonth = new GregorianCalendar();
835 lastMonth.set(selectedCal.get(Calendar.YEAR), selectedCal.get(Calendar.MONTH) - 1, 1);
836 int lastDayLastMonth = lastMonth.getActualMaximum(Calendar.DAY_OF_MONTH);
837 label.setText(Integer.toString(lastDayLastMonth + cellDayValue));
838 }
839 }
840
841 else {
842 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_THIS_MONTH));
843
844 Calendar calForDay = Calendar.getInstance();
845 calForDay.set(internalModel.getModel().getYear(), internalModel.getModel().getMonth(), cellDayValue);
846 DateModel modelForDay = new DateModel(calForDay);
847 label.setBackground(checkConstraints(modelForDay) ?
848 getColors().getColor(AbstractComponentColor.Key.BG_GRID) :
849 getColors().getColor(AbstractComponentColor.Key.BG_GRID_NOT_SELECTABLE)
850 );
851
852
853 if (todayCal.get(Calendar.DATE) == cellDayValue
854 && todayCal.get(Calendar.MONTH) == internalModel.getModel().getMonth()
855 && todayCal.get(Calendar.YEAR) == internalModel.getModel().getYear()) {
856 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_TODAY));
857
858 if (internalModel.getModel().isSelected() && selectedCal.get(Calendar.DATE) == cellDayValue) {
859 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_TODAY_SELECTED));
860 label.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_GRID_TODAY_SELECTED));
861 }
862 }
863
864 else {
865
866 if (internalModel.getModel().isSelected() && selectedCal.get(Calendar.DATE) == cellDayValue) {
867 label.setForeground(getColors().getColor(AbstractComponentColor.Key.FG_GRID_SELECTED));
868 label.setBackground(getColors().getColor(AbstractComponentColor.Key.BG_GRID_SELECTED));
869 }
870 }
871 }
872
873 return label;
874 }
875
876 }
877
878
879
880
881
882
883
884
885 private class InternalController implements ActionListener, MouseListener {
886
887
888
889
890
891 public void actionPerformed(ActionEvent e) {
892 if (!JDatePanel.this.isEnabled()) {
893 return;
894 }
895
896 if (e.getSource() == internalView.getNextMonthButton()) {
897 internalModel.getModel().addMonth(1);
898 } else if (e.getSource() == internalView.getPreviousMonthButton()) {
899 internalModel.getModel().addMonth(-1);
900 } else if (e.getSource() == internalView.getNextYearButton()) {
901 internalModel.getModel().addYear(1);
902 } else if (e.getSource() == internalView.getPreviousYearButton()) {
903 internalModel.getModel().addYear(-1);
904 } else {
905 for (int month = 0; month < internalView.getMonthPopupMenuItems().length; month++) {
906 if (e.getSource() == internalView.getMonthPopupMenuItems()[month]) {
907 internalModel.getModel().setMonth(month);
908 }
909 }
910 }
911 }
912
913
914
915
916
917
918
919 public void mouseClicked(MouseEvent e) {
920 if (!JDatePanel.this.isEnabled()) {
921 return;
922 }
923
924 if (e.getSource() == internalView.getMonthLabel()) {
925 internalView.getMonthPopupMenu().setLightWeightPopupEnabled(false);
926 internalView.getMonthPopupMenu().show((Component) e.getSource(), e.getX(), e.getY());
927 } else if (e.getSource() == internalView.getTodayLabel()) {
928 Calendar today = Calendar.getInstance();
929 internalModel.getModel().setDate(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DATE));
930 } else if (e.getSource() == internalView.getDayTable()) {
931 int row = internalView.getDayTable().getSelectedRow();
932 int col = internalView.getDayTable().getSelectedColumn();
933 if (row >= 0 && row <= 5) {
934 Integer date = (Integer) internalModel.getValueAt(row, col);
935
936
937 int oldDay = internalModel.getModel().getDay();
938 internalModel.getModel().setDay(date);
939 if (!checkConstraints(internalModel.getModel())) {
940
941 internalModel.getModel().setDay(oldDay);
942 return;
943 }
944
945 internalModel.getModel().setSelected(true);
946
947 if (doubleClickAction && e.getClickCount() == 2) {
948 fireActionPerformed();
949 }
950 if (!doubleClickAction) {
951 fireActionPerformed();
952 }
953 }
954 } else if (e.getSource() == internalView.getNoneLabel()) {
955 internalModel.getModel().setSelected(false);
956
957 if (doubleClickAction && e.getClickCount() == 2) {
958 fireActionPerformed();
959 }
960 if (!doubleClickAction) {
961 fireActionPerformed();
962 }
963 }
964
965 e.consume();
966 }
967
968 public void mousePressed(MouseEvent e) {
969 }
970
971 public void mouseEntered(MouseEvent e) {
972 }
973
974 public void mouseExited(MouseEvent e) {
975 }
976
977 public void mouseReleased(MouseEvent e) {
978 }
979
980 }
981
982
983
984
985
986
987
988
989 protected class InternalCalendarModel implements TableModel, SpinnerModel, ChangeListener {
990
991 private final DateModel model;
992 private final Set<ChangeListener> spinnerChangeListeners;
993 private final Set<TableModelListener> tableModelListeners;
994
995 public InternalCalendarModel(DateModel model) {
996 this.spinnerChangeListeners = new HashSet<>();
997 this.tableModelListeners = new HashSet<>();
998 this.model = model;
999 model.addChangeListener(this);
1000 }
1001
1002 public DateModel getModel() {
1003 return model;
1004 }
1005
1006
1007
1008
1009 public void addChangeListener(ChangeListener e) {
1010 spinnerChangeListeners.add(e);
1011 }
1012
1013
1014
1015
1016 public void removeChangeListener(ChangeListener e) {
1017 spinnerChangeListeners.remove(e);
1018 }
1019
1020
1021
1022
1023 public Object getNextValue() {
1024 return Integer.toString(model.getYear() + 1);
1025 }
1026
1027
1028
1029
1030 public Object getPreviousValue() {
1031 return Integer.toString(model.getYear() - 1);
1032 }
1033
1034
1035
1036
1037 public void setValue(Object text) {
1038 String year = (String) text;
1039 model.setYear(Integer.parseInt(year));
1040 }
1041
1042
1043
1044
1045 public Object getValue() {
1046 return Integer.toString(model.getYear());
1047 }
1048
1049
1050
1051
1052 public void addTableModelListener(TableModelListener e) {
1053 tableModelListeners.add(e);
1054 }
1055
1056
1057
1058
1059 public void removeTableModelListener(TableModelListener e) {
1060 tableModelListeners.remove(e);
1061 }
1062
1063
1064
1065
1066 public int getColumnCount() {
1067 return 7;
1068 }
1069
1070
1071
1072
1073 public int getRowCount() {
1074 return 6;
1075 }
1076
1077
1078
1079
1080 public String getColumnName(int columnIndex) {
1081 ComponentTextDefaults.Key key = ComponentTextDefaults.Key.getDowKey(((firstDayOfWeek) + columnIndex) % 7);
1082 return getTexts().getText(key);
1083 }
1084
1085 private int[] lookup = null;
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 private int[] lookup() {
1104 if (lookup == null) {
1105 lookup = new int[8];
1106 lookup[(firstDayOfWeek - 1) % 7] = 0;
1107 lookup[(firstDayOfWeek) % 7] = 1;
1108 lookup[(firstDayOfWeek + 1) % 7] = 2;
1109 lookup[(firstDayOfWeek + 2) % 7] = 3;
1110 lookup[(firstDayOfWeek + 3) % 7] = 4;
1111 lookup[(firstDayOfWeek + 4) % 7] = 5;
1112 lookup[(firstDayOfWeek + 5) % 7] = 6;
1113 }
1114 return lookup;
1115 }
1116
1117
1118
1119
1120
1121
1122
1123
1124 public Object getValueAt(int rowIndex, int columnIndex) {
1125 int series = columnIndex + rowIndex * 7 + 1;
1126
1127 Calendar firstOfMonth = Calendar.getInstance();
1128 firstOfMonth.set(model.getYear(), model.getMonth(), 1);
1129 int dowForFirst = firstOfMonth.get(Calendar.DAY_OF_WEEK);
1130 int daysBefore = lookup()[dowForFirst - 1];
1131
1132 return series - daysBefore;
1133 }
1134
1135
1136
1137
1138 @SuppressWarnings({"unchecked", "rawtypes"})
1139 public Class getColumnClass(int e) {
1140 return Integer.class;
1141 }
1142
1143
1144
1145
1146 public boolean isCellEditable(int e, int arg1) {
1147 return false;
1148 }
1149
1150
1151
1152
1153 public void setValueAt(Object e, int arg1, int arg2) {
1154 }
1155
1156
1157
1158
1159
1160
1161
1162 private void fireValueChanged() {
1163
1164 for (ChangeListener cl : spinnerChangeListeners) {
1165 cl.stateChanged(new ChangeEvent(this));
1166 }
1167
1168
1169 internalView.updateMonthLabel();
1170
1171
1172 for (TableModelListener tl : tableModelListeners) {
1173 tl.tableChanged(new TableModelEvent(this));
1174 }
1175 }
1176
1177
1178
1179
1180 public void stateChanged(ChangeEvent e) {
1181 fireValueChanged();
1182 }
1183
1184 }
1185
1186 }