OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 150 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 150 Rev 168
1
package org.jopencalendar.ui;
1
package org.jopencalendar.ui;
2
 
2
 
3
import java.awt.BasicStroke;
3
import java.awt.BasicStroke;
4
import java.awt.Color;
4
import java.awt.Color;
5
import java.awt.Container;
5
import java.awt.Container;
6
import java.awt.Dimension;
6
import java.awt.Dimension;
7
import java.awt.Font;
7
import java.awt.Font;
8
import java.awt.Graphics;
8
import java.awt.Graphics;
9
import java.awt.Graphics2D;
9
import java.awt.Graphics2D;
10
import java.awt.Rectangle;
10
import java.awt.Rectangle;
11
import java.awt.RenderingHints;
11
import java.awt.RenderingHints;
12
import java.awt.event.InputEvent;
12
import java.awt.event.InputEvent;
13
import java.awt.event.MouseAdapter;
13
import java.awt.event.MouseAdapter;
14
import java.awt.event.MouseEvent;
14
import java.awt.event.MouseEvent;
15
import java.awt.event.MouseWheelEvent;
15
import java.awt.event.MouseWheelEvent;
16
import java.awt.event.MouseWheelListener;
16
import java.awt.event.MouseWheelListener;
17
import java.util.ArrayList;
17
import java.util.ArrayList;
18
import java.util.HashSet;
18
import java.util.HashSet;
19
import java.util.List;
19
import java.util.List;
20
import java.util.Set;
20
import java.util.Set;
21
 
21
 
22
import javax.swing.JPanel;
22
import javax.swing.JPanel;
23
import javax.swing.JPopupMenu;
23
import javax.swing.JPopupMenu;
24
import javax.swing.Scrollable;
24
import javax.swing.Scrollable;
25
import javax.swing.SwingUtilities;
25
import javax.swing.SwingUtilities;
26
 
26
 
27
import org.jopencalendar.model.JCalendarItem;
27
import org.jopencalendar.model.JCalendarItem;
28
import org.jopencalendar.model.JCalendarItemPart;
28
import org.jopencalendar.model.JCalendarItemPart;
29
 
29
 
30
public abstract class MultipleDayView extends JPanel implements Scrollable {
30
public abstract class MultipleDayView extends JPanel implements Scrollable {
31
    public static final String CALENDARD_ITEMS_PROPERTY = "calendard_items_changed";
31
    public static final String CALENDARD_ITEMS_PROPERTY = "calendard_items_changed";
32
    public final static Color WHITE_TRANSPARENCY_COLOR = new Color(255, 255, 255, 180);
32
    public static final Color WHITE_TRANSPARENCY_COLOR = new Color(255, 255, 255, 180);
33
    public static final Color LIGHT_BLUE = new Color(202, 212, 220);
33
    public static final Color LIGHT_BLUE = new Color(202, 212, 220);
34
    public final static Color LIGHT = new Color(222, 222, 222);
34
    public static final Color LIGHT = new Color(222, 222, 222);
35
    public static final int TITLE_HEIGHT = 20;
35
    public static final int TITLE_HEIGHT = 20;
36
    public static final int HOURS_LABEL_WIDTH = 50;
36
    public static final int HOURS_LABEL_WIDTH = 50;
37
 
37
 
38
    protected static final int YEAR_HEIGHT = 20;
38
    protected static final int YEAR_HEIGHT = 20;
39
    private int deltaY = 10;
39
    private int deltaY = 10;
40
    private int rowHeight = 44;
40
    private int rowHeight = 44;
41
 
41
 
42
    private List<List<AllDayItem>> allDayItems = new ArrayList<List<AllDayItem>>();
42
    private List<List<AllDayItem>> allDayItems = new ArrayList<List<AllDayItem>>();
43
    private List<List<ItemPartView>> itemParts = new ArrayList<List<ItemPartView>>();
43
    private List<List<ItemPartView>> itemParts = new ArrayList<List<ItemPartView>>();
44
 
44
 
45
    private int allDayItemsRowCount;
45
    private int allDayItemsRowCount;
46
    public int allDayItemsRowHeight = 20;
46
    public int allDayItemsRowHeight = 20;
47
 
47
 
48
    private Set<ItemPartView> selectedItems = new HashSet<ItemPartView>();
48
    private Set<ItemPartView> selectedItems = new HashSet<ItemPartView>();
49
    // Right click menu
49
    // Right click menu
50
    private JPopupMenuProvider popupProvider;
50
    private JPopupMenuProvider popupProvider;
51
 
51
 
52
    protected List<ItemPartHoverListener> hListeners = new ArrayList<ItemPartHoverListener>();
52
    protected List<ItemPartHoverListener> hListeners = new ArrayList<ItemPartHoverListener>();
53
    private int startHour = 0;
53
    private int startHour = 0;
54
    private int endHour = 24;
54
    private int endHour = 24;
55
 
55
 
56
    public MultipleDayView() {
56
    public MultipleDayView() {
57
 
57
 
58
        this.addMouseListener(new MouseAdapter() {
58
        this.addMouseListener(new MouseAdapter() {
59
            @Override
59
            @Override
60
            public void mousePressed(MouseEvent e) {
60
            public void mousePressed(MouseEvent e) {
61
                ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
61
                ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
62
                if (newSelection != null) {
62
                if (newSelection != null) {
63
                    boolean isCurrentlySelected = newSelection.isSelected();
63
                    boolean isCurrentlySelected = newSelection.isSelected();
64
                    // Click on a non selected item
64
                    // Click on a non selected item
65
                    boolean ctrlPressed = ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK);
65
                    boolean ctrlPressed = ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK);
66
                    if (!ctrlPressed) {
66
                    if (!ctrlPressed) {
67
                        deselectAll();
67
                        deselectAll();
68
                    }
68
                    }
69
                    if (e.getButton() == MouseEvent.BUTTON1) {
69
                    if (e.getButton() == MouseEvent.BUTTON1) {
70
                        if (isCurrentlySelected) {
70
                        if (isCurrentlySelected) {
71
                            // Click on a selected item
71
                            // Click on a selected item
72
                            newSelection.setSelected(false);
72
                            newSelection.setSelected(false);
73
                            selectedItems.remove(newSelection);
73
                            selectedItems.remove(newSelection);
74
                        } else {
74
                        } else {
75
                            newSelection.setSelected(true);
75
                            newSelection.setSelected(true);
76
                            selectedItems.add(newSelection);
76
                            selectedItems.add(newSelection);
77
                        }
77
                        }
78
                    } else {
78
                    } else {
79
                        newSelection.setSelected(true);
79
                        newSelection.setSelected(true);
80
                        selectedItems.add(newSelection);
80
                        selectedItems.add(newSelection);
81
                    }
81
                    }
82
                    repaint();
82
                    repaint();
83
                }
83
                }
84
                // Deselect all if nothing is selected
84
                // Deselect all if nothing is selected
85
                if (newSelection == null && !selectedItems.isEmpty()) {
85
                if (newSelection == null && !selectedItems.isEmpty()) {
86
                    deselectAll();
86
                    deselectAll();
87
                    repaint();
87
                    repaint();
88
                }
88
                }
89
                // For mac
89
                // For mac
90
                showPopup(e);
90
                showPopup(e);
91
            }
91
            }
92
 
92
 
93
            @Override
93
            @Override
94
            public void mouseReleased(MouseEvent e) {
94
            public void mouseReleased(MouseEvent e) {
95
                showPopup(e);
95
                showPopup(e);
96
            }
96
            }
97
 
97
 
98
            private void showPopup(MouseEvent e) {
98
            private void showPopup(MouseEvent e) {
99
                if (e.isPopupTrigger()) {
99
                if (e.isPopupTrigger()) {
100
                    ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
100
                    ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
101
                    if (newSelection != null && !newSelection.isSelected()) {
101
                    if (newSelection != null && !newSelection.isSelected()) {
102
                        newSelection.setSelected(true);
102
                        newSelection.setSelected(true);
103
                        selectedItems.add(newSelection);
103
                        selectedItems.add(newSelection);
104
                        repaint();
104
                        repaint();
105
                    }
105
                    }
106
 
106
 
107
                    if (popupProvider != null) {
107
                    if (popupProvider != null) {
108
                        // Selected parts
108
                        // Selected parts
109
                        final List<JCalendarItemPart> sParts = new ArrayList<JCalendarItemPart>();
109
                        final List<JCalendarItemPart> sParts = new ArrayList<JCalendarItemPart>();
110
                        for (ItemPartView p : selectedItems) {
110
                        for (ItemPartView p : selectedItems) {
111
                            sParts.add(p.getPart());
111
                            sParts.add(p.getPart());
112
                        }
112
                        }
113
                        // Current column parts
113
                        // Current column parts
114
                        final List<JCalendarItemPart> currentColumnParts = new ArrayList<JCalendarItemPart>();
114
                        final List<JCalendarItemPart> currentColumnParts = new ArrayList<JCalendarItemPart>();
115
                        int columnIndex = getColumnIndex(e.getX());
115
                        int columnIndex = getColumnIndex(e.getX());
116
                        List<ItemPartView> l = MultipleDayView.this.itemParts.get(columnIndex);
116
                        List<ItemPartView> l = MultipleDayView.this.itemParts.get(columnIndex);
117
                        for (ItemPartView p : l) {
117
                        for (ItemPartView p : l) {
118
                            currentColumnParts.add(p.getPart());
118
                            currentColumnParts.add(p.getPart());
119
                        }
119
                        }
120
 
120
 
121
                        JPopupMenu popup = popupProvider.getPopup(sParts, currentColumnParts);
121
                        JPopupMenu popup = popupProvider.getPopup(sParts, currentColumnParts);
122
                        if (popup != null) {
122
                        if (popup != null) {
123
                            popup.show(MultipleDayView.this, e.getX(), e.getY());
123
                            popup.show(MultipleDayView.this, e.getX(), e.getY());
124
                        }
124
                        }
125
                    }
125
                    }
126
                }
126
                }
127
            }
127
            }
128
        });
128
        });
129
        this.addMouseMotionListener(new MouseAdapter() {
129
        this.addMouseMotionListener(new MouseAdapter() {
130
            ItemPartView previous;
130
            ItemPartView previous;
131
 
131
 
132
            @Override
132
            @Override
133
            public void mouseMoved(MouseEvent e) {
133
            public void mouseMoved(MouseEvent e) {
134
                if (hListeners.isEmpty()) {
134
                if (hListeners.isEmpty()) {
135
                    return;
135
                    return;
136
                }
136
                }
137
                ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
137
                ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
138
 
138
 
139
                if (newSelection != previous) {
139
                if (newSelection != previous) {
140
 
140
 
141
                    for (ItemPartHoverListener l : hListeners) {
141
                    for (ItemPartHoverListener l : hListeners) {
142
                        if (newSelection == null) {
142
                        if (newSelection == null) {
143
                            l.mouseOn(null);
143
                            l.mouseOn(null);
144
                        } else {
144
                        } else {
145
                            l.mouseOn(newSelection.getPart());
145
                            l.mouseOn(newSelection.getPart());
146
                        }
146
                        }
147
                    }
147
                    }
148
                    previous = newSelection;
148
                    previous = newSelection;
149
                }
149
                }
150
 
150
 
151
            }
151
            }
152
 
152
 
153
        });
153
        });
154
 
154
 
155
    }
155
    }
156
 
156
 
157
    protected int getColumnIndex(int currentX) {
157
    protected int getColumnIndex(int currentX) {
158
        int x = HOURS_LABEL_WIDTH;
158
        int x = HOURS_LABEL_WIDTH;
159
        int columnCount = getColumnCount();
159
        int columnCount = getColumnCount();
160
        for (int i = 0; i < columnCount - 1; i++) {
160
        for (int i = 0; i < columnCount - 1; i++) {
161
            x += getColumnWidth(i);
161
            x += getColumnWidth(i);
162
            if (currentX < x) {
162
            if (currentX < x) {
163
                return i;
163
                return i;
164
            }
164
            }
165
        }
165
        }
166
        return 0;
166
        return 0;
167
    }
167
    }
168
 
168
 
169
    public void setHourRange(int start, int end) {
169
    public void setHourRange(int start, int end) {
170
        if (start < 0 || start > 24) {
170
        if (start < 0 || start > 24) {
171
            throw new IllegalArgumentException("Bad start hour : " + start);
171
            throw new IllegalArgumentException("Bad start hour : " + start);
172
        }
172
        }
173
        if (end < 0 || end > 24) {
173
        if (end < 0 || end > 24) {
174
            throw new IllegalArgumentException("Bad end hour : " + end);
174
            throw new IllegalArgumentException("Bad end hour : " + end);
175
        }
175
        }
176
        if (end - start < 1) {
176
        if (end - start < 1) {
177
            throw new IllegalArgumentException("Bad end hour must be > (start + 1)");
177
            throw new IllegalArgumentException("Bad end hour must be > (start + 1)");
178
        }
178
        }
179
        this.startHour = start;
179
        this.startHour = start;
180
        this.endHour = end;
180
        this.endHour = end;
181
        repaint();
181
        repaint();
182
    }
182
    }
183
 
183
 
184
    protected void setItems(List<List<JCalendarItem>> list) {
184
    protected void setItems(List<List<JCalendarItem>> list) {
185
        assert SwingUtilities.isEventDispatchThread();
185
        assert SwingUtilities.isEventDispatchThread();
186
        this.itemParts.clear();
186
        this.itemParts.clear();
187
        this.allDayItems.clear();
187
        this.allDayItems.clear();
188
        for (List<JCalendarItem> l : list) {
188
        for (List<JCalendarItem> l : list) {
189
            final List<AllDayItem> aDayItems = new ArrayList<AllDayItem>();
189
            final List<AllDayItem> aDayItems = new ArrayList<AllDayItem>();
190
            final List<ItemPartView> aItems = new ArrayList<ItemPartView>();
190
            final List<ItemPartView> aItems = new ArrayList<ItemPartView>();
191
            for (JCalendarItem jCalendarItem : l) {
191
            for (JCalendarItem jCalendarItem : l) {
192
                if (jCalendarItem.getDtStart().before(jCalendarItem.getDtEnd())) {
192
                if (jCalendarItem.getDtStart().before(jCalendarItem.getDtEnd())) {
193
                    if (jCalendarItem.isDayOnly()) {
193
                    if (jCalendarItem.isDayOnly()) {
194
                        aDayItems.add(new AllDayItem(jCalendarItem));
194
                        aDayItems.add(new AllDayItem(jCalendarItem));
195
                    } else {
195
                    } else {
196
                        aItems.addAll(ItemPartView.split(jCalendarItem));
196
                        aItems.addAll(ItemPartView.split(jCalendarItem));
197
                    }
197
                    }
198
                } else {
198
                } else {
199
                    System.err.println(
199
                    System.err.println(
200
                            "MultipleDayView.setItems() " + jCalendarItem.getSummary() + " start :" + jCalendarItem.getDtStart().getTime() + " after " + jCalendarItem.getDtEnd().getTime() + " !");
200
                            "MultipleDayView.setItems() " + jCalendarItem.getSummary() + " start :" + jCalendarItem.getDtStart().getTime() + " after " + jCalendarItem.getDtEnd().getTime() + " !");
201
                }
201
                }
202
            }
202
            }
203
            this.allDayItems.add(aDayItems);
203
            this.allDayItems.add(aDayItems);
204
            this.itemParts.add(aItems);
204
            this.itemParts.add(aItems);
205
        }
205
        }
206
 
206
 
207
        layoutAllDayItems();
207
        layoutAllDayItems();
208
        layoutItemParts();
208
        layoutItemParts();
209
        // Tweak to force header to be relayouted and repainted
209
        // Tweak to force header to be relayouted and repainted
210
        final Container parent = getParent().getParent();
210
        final Container parent = getParent().getParent();
211
        final int w = parent.getSize().width;
211
        final int w = parent.getSize().width;
212
        final int h = parent.getSize().height;
212
        final int h = parent.getSize().height;
213
        parent.setSize(w + 1, h);
213
        parent.setSize(w + 1, h);
214
        parent.validate();
214
        parent.validate();
215
        parent.setSize(w, h);
215
        parent.setSize(w, h);
216
        parent.validate();
216
        parent.validate();
217
        firePropertyChange(CALENDARD_ITEMS_PROPERTY, null, list);
217
        firePropertyChange(CALENDARD_ITEMS_PROPERTY, null, list);
218
    }
218
    }
219
 
219
 
220
    private void layoutItemParts() {
220
    private void layoutItemParts() {
221
        ItemPartViewLayouter layouter = new ItemPartViewLayouter();
221
        ItemPartViewLayouter layouter = new ItemPartViewLayouter();
222
        for (List<ItemPartView> items : itemParts) {
222
        for (List<ItemPartView> items : itemParts) {
223
            layouter.layout(items);
223
            layouter.layout(items);
224
        }
224
        }
225
 
225
 
226
    }
226
    }
227
 
227
 
228
    private void layoutAllDayItems() {
228
    private void layoutAllDayItems() {
229
        // final Calendar c = getFirstDayCalendar();
229
        // final Calendar c = getFirstDayCalendar();
230
        // Collections.sort(this.allDayItems, new Comparator<AllDayItem>() {
230
        // Collections.sort(this.allDayItems, new Comparator<AllDayItem>() {
231
        //
231
        //
232
        // @Override
232
        // @Override
233
        // public int compare(AllDayItem o1, AllDayItem o2) {
233
        // public int compare(AllDayItem o1, AllDayItem o2) {
234
        // return o1.getLengthFrom(c) - o2.getLengthFrom(c);
234
        // return o1.getLengthFrom(c) - o2.getLengthFrom(c);
235
        // }
235
        // }
236
        // });
236
        // });
237
        // final int size = this.allDayItems.size();
237
        // final int size = this.allDayItems.size();
238
        // for (int i = 0; i < size; i++) {
238
        // for (int i = 0; i < size; i++) {
239
        // AllDayItem jCalendarItem = this.allDayItems.get(i);
239
        // AllDayItem jCalendarItem = this.allDayItems.get(i);
240
        // // set X and W
240
        // // set X and W
241
        // Calendar start = jCalendarItem.getItem().getDtStart();
241
        // Calendar start = jCalendarItem.getItem().getDtStart();
242
        // Calendar end = jCalendarItem.getItem().getDtEnd();
242
        // Calendar end = jCalendarItem.getItem().getDtEnd();
243
        // if (start.before(getFirstDayCalendar())) {
243
        // if (start.before(getFirstDayCalendar())) {
244
        // start = getFirstDayCalendar();
244
        // start = getFirstDayCalendar();
245
        // } else {
245
        // } else {
246
        // jCalendarItem.setLeftBorder(true);
246
        // jCalendarItem.setLeftBorder(true);
247
        // }
247
        // }
248
        //
248
        //
249
        // if (end.after(getAfterLastDayCalendar())) {
249
        // if (end.after(getAfterLastDayCalendar())) {
250
        // end = getAfterLastDayCalendar();
250
        // end = getAfterLastDayCalendar();
251
        // end.add(Calendar.MILLISECOND, -1);
251
        // end.add(Calendar.MILLISECOND, -1);
252
        // } else {
252
        // } else {
253
        // jCalendarItem.setRightBorder(true);
253
        // jCalendarItem.setRightBorder(true);
254
        // }
254
        // }
255
        // int x = (int) (start.getTimeInMillis() - getFirstDayCalendar().getTimeInMillis());
255
        // int x = (int) (start.getTimeInMillis() - getFirstDayCalendar().getTimeInMillis());
256
        // x = x / MILLIS_PER_DAY;
256
        // x = x / MILLIS_PER_DAY;
257
        // jCalendarItem.setX(x);
257
        // jCalendarItem.setX(x);
258
        // int l = ((int) (end.getTimeInMillis() - start.getTimeInMillis())) / MILLIS_PER_DAY + 1;
258
        // int l = ((int) (end.getTimeInMillis() - start.getTimeInMillis())) / MILLIS_PER_DAY + 1;
259
        // jCalendarItem.setW(l);
259
        // jCalendarItem.setW(l);
260
        //
260
        //
261
        // // Y and H
261
        // // Y and H
262
        // jCalendarItem.setY(0);
262
        // jCalendarItem.setY(0);
263
        // jCalendarItem.setH(1);
263
        // jCalendarItem.setH(1);
264
        // for (int j = 0; j < i; j++) {
264
        // for (int j = 0; j < i; j++) {
265
        // AllDayItem layoutedItem = this.allDayItems.get(j);
265
        // AllDayItem layoutedItem = this.allDayItems.get(j);
266
        // if (layoutedItem.conflictWith(jCalendarItem)) {
266
        // if (layoutedItem.conflictWith(jCalendarItem)) {
267
        // jCalendarItem.setY(layoutedItem.getY() + 1);
267
        // jCalendarItem.setY(layoutedItem.getY() + 1);
268
        // }
268
        // }
269
        // }
269
        // }
270
        // }
270
        // }
271
        // allDayItemsRowCount = 0;
271
        // allDayItemsRowCount = 0;
272
        // for (int i = 0; i < size; i++) {
272
        // for (int i = 0; i < size; i++) {
273
        // AllDayItem jCalendarItem = this.allDayItems.get(i);
273
        // AllDayItem jCalendarItem = this.allDayItems.get(i);
274
        // if (jCalendarItem.getY() + jCalendarItem.getH() > allDayItemsRowCount) {
274
        // if (jCalendarItem.getY() + jCalendarItem.getH() > allDayItemsRowCount) {
275
        // allDayItemsRowCount = jCalendarItem.getY() + jCalendarItem.getH();
275
        // allDayItemsRowCount = jCalendarItem.getY() + jCalendarItem.getH();
276
        // }
276
        // }
277
        // }
277
        // }
278
    }
278
    }
279
 
279
 
280
    @Override
280
    @Override
281
    public Dimension getPreferredSize() {
281
    public Dimension getPreferredSize() {
282
        return new Dimension(800, TITLE_HEIGHT + (this.endHour - this.startHour) * rowHeight);
282
        return new Dimension(800, TITLE_HEIGHT + (this.endHour - this.startHour) * rowHeight);
283
    }
283
    }
284
 
284
 
285
    @Override
285
    @Override
286
    protected void paintComponent(Graphics g) {
286
    protected void paintComponent(Graphics g) {
287
        Graphics2D g2 = (Graphics2D) g;
287
        Graphics2D g2 = (Graphics2D) g;
288
        float[] dash4 = { 8f, 4f };
288
        float[] dash4 = { 8f, 4f };
289
 
289
 
290
        BasicStroke bs4 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash4, 1f);
290
        BasicStroke bs4 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash4, 1f);
291
 
291
 
292
        final BasicStroke s = new BasicStroke(1f);
292
        final BasicStroke s = new BasicStroke(1f);
293
        g.setColor(Color.WHITE);
293
        g.setColor(Color.WHITE);
294
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
294
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
295
        int columnCount = getColumnCount();
295
        int columnCount = getColumnCount();
296
        if (columnCount < 1)
296
        if (columnCount < 1)
297
            return;
297
            return;
298
 
298
 
299
        g2.setStroke(s);
299
        g2.setStroke(s);
300
        // H lines : Hours
300
        // H lines : Hours
301
        int y = deltaY;
301
        int y = deltaY;
302
        int hourPaintedCount = this.endHour - this.startHour;
302
        int hourPaintedCount = this.endHour - this.startHour;
303
        for (int i = 0; i < hourPaintedCount; i++) {
303
        for (int i = 0; i < hourPaintedCount; i++) {
304
            g.setColor(Color.LIGHT_GRAY);
304
            g.setColor(Color.LIGHT_GRAY);
305
            g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
305
            g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
306
            y += rowHeight;
306
            y += rowHeight;
307
        }
307
        }
308
        // H lines : 1/2 Hours
308
        // H lines : 1/2 Hours
309
        y = deltaY + rowHeight / 2;
309
        y = deltaY + rowHeight / 2;
310
        if (rowHeight > 44) {
310
        if (rowHeight > 44) {
311
            g2.setStroke(s);
311
            g2.setStroke(s);
312
        } else {
312
        } else {
313
            g2.setStroke(bs4);
313
            g2.setStroke(bs4);
314
        }
314
        }
315
        g.setColor(LIGHT);
315
        g.setColor(LIGHT);
316
        for (int i = 0; i < hourPaintedCount; i++) {
316
        for (int i = 0; i < hourPaintedCount; i++) {
317
            g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
317
            g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
318
            y += rowHeight;
318
            y += rowHeight;
319
        }
319
        }
320
 
320
 
321
        if (rowHeight > 44) {
321
        if (rowHeight > 44) {
322
            g2.setStroke(bs4);
322
            g2.setStroke(bs4);
323
            y = deltaY + rowHeight / 4;
323
            y = deltaY + rowHeight / 4;
324
            for (int i = 0; i < hourPaintedCount * 2; i++) {
324
            for (int i = 0; i < hourPaintedCount * 2; i++) {
325
                g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
325
                g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
326
                y += rowHeight / 2;
326
                y += rowHeight / 2;
327
            }
327
            }
328
        }
328
        }
329
 
329
 
330
        // Horizontal lines : 5 minutes
330
        // Horizontal lines : 5 minutes
331
        g.setColor(Color.LIGHT_GRAY);
331
        g.setColor(Color.LIGHT_GRAY);
332
        if (rowHeight > 120) {
332
        if (rowHeight > 120) {
333
            g2.setStroke(s);
333
            g2.setStroke(s);
334
            final float h5 = rowHeight / 12f;
334
            final float h5 = rowHeight / 12f;
335
 
335
 
336
            // int w = this.getWidth();
336
            // int w = this.getWidth();
337
            int x = HOURS_LABEL_WIDTH;
337
            int x = HOURS_LABEL_WIDTH;
338
            for (int j = 0; j < columnCount - 1; j++) {
338
            for (int j = 0; j < columnCount - 1; j++) {
339
                x += getColumnWidth(j);
339
                x += getColumnWidth(j);
340
                y = deltaY + (int) h5;
340
                y = deltaY + (int) h5;
341
                int x2 = x + 10;
341
                int x2 = x + 10;
342
                for (int i = 0; i < 24; i++) {
342
                for (int i = 0; i < 24; i++) {
343
                    float y1 = y;
343
                    float y1 = y;
344
                    g.drawLine(x, (int) y1, x2, (int) y1);
344
                    g.drawLine(x, (int) y1, x2, (int) y1);
345
                    y1 += h5;
345
                    y1 += h5;
346
                    g.drawLine(x, (int) y1, x2, (int) y1);
346
                    g.drawLine(x, (int) y1, x2, (int) y1);
347
                    y1 += 2 * h5;
347
                    y1 += 2 * h5;
348
                    g.drawLine(x, (int) y1, x2, (int) y1);
348
                    g.drawLine(x, (int) y1, x2, (int) y1);
349
                    y1 += h5;
349
                    y1 += h5;
350
                    g.drawLine(x, (int) y1, x2, (int) y1);
350
                    g.drawLine(x, (int) y1, x2, (int) y1);
351
                    y += rowHeight / 2;
351
                    y += rowHeight / 2;
352
                }
352
                }
353
            }
353
            }
354
        }
354
        }
355
 
355
 
356
        // Hours : text on left
356
        // Hours : text on left
357
        g2.setStroke(s);
357
        g2.setStroke(s);
358
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
358
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
359
        g.setFont(getFont().deriveFont(14f));
359
        g.setFont(getFont().deriveFont(14f));
360
        y = deltaY + 6;
360
        y = deltaY + 6;
361
        g.setColor(Color.GRAY);
361
        g.setColor(Color.GRAY);
362
        for (int i = this.startHour; i < this.endHour; i++) {
362
        for (int i = this.startHour; i < this.endHour; i++) {
363
            g.drawString(getHourLabel(i), 5, y);
363
            g.drawString(getHourLabel(i), 5, y);
364
            y += rowHeight;
364
            y += rowHeight;
365
        }
365
        }
366
        // Vertical lines
366
        // Vertical lines
367
        int x = HOURS_LABEL_WIDTH;
367
        int x = HOURS_LABEL_WIDTH;
368
 
368
 
369
        for (int i = 0; i < columnCount - 1; i++) {
369
        for (int i = 0; i < columnCount - 1; i++) {
370
            x += getColumnWidth(i);
370
            x += getColumnWidth(i);
371
            g.drawLine(x, 0, x, this.getHeight());
371
            g.drawLine(x, 0, x, this.getHeight());
372
        }
372
        }
373
        int dY = deltaY - this.startHour * rowHeight;
373
        int dY = deltaY - this.startHour * rowHeight;
374
        for (int i = 0; i < this.itemParts.size(); i++) {
374
        for (int i = 0; i < this.itemParts.size(); i++) {
375
            List<ItemPartView> items = this.itemParts.get(i);
375
            List<ItemPartView> items = this.itemParts.get(i);
376
            final int columnWidth = getColumnWidth(i);
376
            final int columnWidth = getColumnWidth(i);
377
            // Draw standard items
377
            // Draw standard items
378
            for (ItemPartView jCalendarItem : items) {
378
            for (ItemPartView jCalendarItem : items) {
379
                final int itemX = getColumnX(i);
379
                final int itemX = getColumnX(i);
380
                jCalendarItem.draw(g2, itemX, dY, rowHeight, columnWidth);
380
                jCalendarItem.draw(g2, itemX, dY, rowHeight, columnWidth);
381
            }
381
            }
382
        }
382
        }
383
 
383
 
384
    }
384
    }
385
 
385
 
386
    String getHourLabel(int i) {
386
    String getHourLabel(int i) {
387
        if (i < 10) {
387
        if (i < 10) {
388
            return "0" + i + ":00";
388
            return "0" + i + ":00";
389
        }
389
        }
390
        return String.valueOf(i) + ":00";
390
        return String.valueOf(i) + ":00";
391
    }
391
    }
392
 
392
 
393
    public int getColumnWidth(int column) {
393
    public int getColumnWidth(int column) {
394
        final int c = (this.getWidth() - HOURS_LABEL_WIDTH) / getColumnCount();
394
        return (this.getWidth() - HOURS_LABEL_WIDTH) / getColumnCount();
395
 
-
 
396
        return c;
-
 
397
    }
395
    }
398
 
396
 
399
    public int getColumnX(int column) {
397
    public int getColumnX(int column) {
400
        int x = HOURS_LABEL_WIDTH;
398
        int x = HOURS_LABEL_WIDTH;
401
        for (int i = 0; i < column; i++) {
399
        for (int i = 0; i < column; i++) {
402
            x += getColumnWidth(i);
400
            x += getColumnWidth(i);
403
 
401
 
404
        }
402
        }
405
        return x;
403
        return x;
406
    }
404
    }
407
 
405
 
408
    public void paintHeader(Graphics g) {
406
    public void paintHeader(Graphics g) {
409
 
407
 
410
        g.setColor(Color.WHITE);
408
        g.setColor(Color.WHITE);
411
        g.fillRect(0, 0, this.getWidth() + 100, getHeaderHeight());
409
        g.fillRect(0, 0, this.getWidth() + 100, getHeaderHeight());
412
        g.setColor(Color.GRAY);
410
        g.setColor(Color.GRAY);
413
        // Vertical lines
411
        // Vertical lines
414
        int columnCount = getColumnCount();
412
        int columnCount = getColumnCount();
415
        int x = HOURS_LABEL_WIDTH;
413
        int x = HOURS_LABEL_WIDTH;
416
 
414
 
417
        for (int i = 0; i < columnCount - 1; i++) {
415
        for (int i = 0; i < columnCount - 1; i++) {
418
            x += getColumnWidth(i);
416
            x += getColumnWidth(i);
419
            g.drawLine(x, YEAR_HEIGHT, x, this.getHeaderHeight());
417
            g.drawLine(x, YEAR_HEIGHT, x, this.getHeaderHeight());
420
        }
418
        }
421
        g.setColor(Color.DARK_GRAY);
419
        g.setColor(Color.DARK_GRAY);
422
        // Text : month & year
420
        // Text : month & year
423
        Graphics2D g2 = (Graphics2D) g;
421
        Graphics2D g2 = (Graphics2D) g;
424
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
422
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
425
        g.setFont(getFont().deriveFont(13f));
423
        g.setFont(getFont().deriveFont(13f));
426
 
424
 
427
        String strTitle = getTitle();
425
        String strTitle = getTitle();
428
        Rectangle r = g.getFontMetrics().getStringBounds(strTitle, g).getBounds();
426
        Rectangle r = g.getFontMetrics().getStringBounds(strTitle, g).getBounds();
429
        int w = 0;
427
        int w = 0;
430
        for (int i = 0; i < getColumnCount(); i++) {
428
        for (int i = 0; i < getColumnCount(); i++) {
431
            w += getColumnWidth(i);
429
            w += getColumnWidth(i);
432
        }
430
        }
433
        g.drawString(strTitle, (int) (HOURS_LABEL_WIDTH + (w - r.getWidth()) / 2), 15);
431
        g.drawString(strTitle, (int) (HOURS_LABEL_WIDTH + (w - r.getWidth()) / 2), 15);
434
 
432
 
435
        // Text : day
433
        // Text : day
436
        final Font font1 = getFont().deriveFont(12f);
434
        final Font font1 = getFont().deriveFont(12f);
437
        g.setFont(font1);
435
        g.setFont(font1);
438
        x = HOURS_LABEL_WIDTH;
436
        x = HOURS_LABEL_WIDTH;
439
        Rectangle clipRect = g.getClipBounds();
437
        Rectangle clipRect = g.getClipBounds();
440
        for (int i = 0; i < columnCount; i++) {
438
        for (int i = 0; i < columnCount; i++) {
441
            String str = getColumnTitle(i);
439
            String str = getColumnTitle(i);
442
            r = g.getFontMetrics().getStringBounds(str, g).getBounds();
440
            r = g.getFontMetrics().getStringBounds(str, g).getBounds();
443
            int columnWidth = getColumnWidth(i);
441
            int columnWidth = getColumnWidth(i);
444
            g.setClip(x, YEAR_HEIGHT, columnWidth - 1, YEAR_HEIGHT + 20);
442
            g.setClip(x, YEAR_HEIGHT, columnWidth - 1, YEAR_HEIGHT + 20);
445
            // Centering
443
            // Centering
446
            int x2 = (int) (x + (columnWidth - r.getWidth()) / 2);
444
            int x2 = (int) (x + (columnWidth - r.getWidth()) / 2);
447
            // If no room, left align
445
            // If no room, left align
448
            if (x2 < x + 2) {
446
            if (x2 < x + 2) {
449
                x2 = x + 2;
447
                x2 = x + 2;
450
            }
448
            }
451
            g.drawString(str, x2, YEAR_HEIGHT + 15);
449
            g.drawString(str, x2, YEAR_HEIGHT + 15);
452
            x += columnWidth;
450
            x += columnWidth;
453
 
451
 
454
        }
452
        }
455
        g.setClip(clipRect);
453
        g.setClip(clipRect);
456
        paintHeaderAlldays(g);
454
        paintHeaderAlldays(g);
457
    }
455
    }
458
 
456
 
459
    public String getTitle() {
457
    public String getTitle() {
460
        return "Title";
458
        return "Title";
461
    }
459
    }
462
 
460
 
463
    public void paintHeaderAlldays(Graphics g) {
461
    public void paintHeaderAlldays(Graphics g) {
464
        // Draw alldays
462
        // Draw alldays
465
        // for (AllDayItem jCalendarItem : this.allDayItems) {
463
        // for (AllDayItem jCalendarItem : this.allDayItems) {
466
        // int w = 0;
464
        // int w = 0;
467
        // for (int i = jCalendarItem.getX(); i < jCalendarItem.getX() + jCalendarItem.getW(); i++)
465
        // for (int i = jCalendarItem.getX(); i < jCalendarItem.getX() + jCalendarItem.getW(); i++)
468
        // {
466
        // {
469
        // w += getColumnWidth(i);
467
        // w += getColumnWidth(i);
470
        // }
468
        // }
471
        // int x2 = getColumnX(jCalendarItem.getX());
469
        // int x2 = getColumnX(jCalendarItem.getX());
472
        // jCalendarItem.draw(g2, x2, YEAR_HEIGHT + TITLE_HEIGHT, allDayItemsRowHeight, w);
470
        // jCalendarItem.draw(g2, x2, YEAR_HEIGHT + TITLE_HEIGHT, allDayItemsRowHeight, w);
473
        // }
471
        // }
474
    }
472
    }
475
 
473
 
476
    public int getHeaderHeight() {
474
    public int getHeaderHeight() {
477
        return YEAR_HEIGHT + TITLE_HEIGHT + this.allDayItemsRowCount * this.allDayItemsRowHeight + 4;
475
        return YEAR_HEIGHT + TITLE_HEIGHT + this.allDayItemsRowCount * this.allDayItemsRowHeight + 4;
478
    }
476
    }
479
 
477
 
480
    @Override
478
    @Override
481
    public Dimension getPreferredScrollableViewportSize() {
479
    public Dimension getPreferredScrollableViewportSize() {
482
        return new Dimension(1024, 768);
480
        return new Dimension(1024, 768);
483
    }
481
    }
484
 
482
 
485
    @Override
483
    @Override
486
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
484
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
487
        return orientation * this.rowHeight * 2;
485
        return orientation * this.rowHeight * 2;
488
    }
486
    }
489
 
487
 
490
    @Override
488
    @Override
491
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
489
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
492
        return this.rowHeight;
490
        return this.rowHeight;
493
    }
491
    }
494
 
492
 
495
    @Override
493
    @Override
496
    public boolean getScrollableTracksViewportWidth() {
494
    public boolean getScrollableTracksViewportWidth() {
497
        return true;
495
        return true;
498
    }
496
    }
499
 
497
 
500
    @Override
498
    @Override
501
    public boolean getScrollableTracksViewportHeight() {
499
    public boolean getScrollableTracksViewportHeight() {
502
        return false;
500
        return false;
503
    }
501
    }
504
 
502
 
505
    public void mouseWheelMoved(MouseWheelEvent e, MouseWheelListener[] l) {
503
    public void mouseWheelMoved(MouseWheelEvent e, MouseWheelListener[] l) {
506
 
504
 
507
        if (e.getModifiers() == InputEvent.CTRL_MASK) {
505
        if (e.getModifiers() == InputEvent.CTRL_MASK) {
508
 
506
 
509
            if (e.getWheelRotation() < 0) {
507
            if (e.getWheelRotation() < 0) {
510
                zoom(22);
508
                zoom(22);
511
            } else {
509
            } else {
512
                zoom(-22);
510
                zoom(-22);
513
            }
511
            }
514
 
512
 
515
            e.consume();
513
            e.consume();
516
        } else {
514
        } else {
517
            for (int i = 0; i < l.length; i++) {
515
            for (int i = 0; i < l.length; i++) {
518
                MouseWheelListener mouseWheelListener = l[i];
516
                MouseWheelListener mouseWheelListener = l[i];
519
                mouseWheelListener.mouseWheelMoved(e);
517
                mouseWheelListener.mouseWheelMoved(e);
520
            }
518
            }
521
        }
519
        }
522
 
520
 
523
    }
521
    }
524
 
522
 
525
    public final void setZoom(int zIndex) {
523
    public final void setZoom(int zIndex) {
526
        if (zIndex >= 0) {
524
        if (zIndex >= 0) {
527
            int rh = (1 + zIndex) * 22;
525
            int rh = (1 + zIndex) * 22;
528
            setRowHeight(rh);
526
            setRowHeight(rh);
529
        }
527
        }
530
    }
528
    }
531
 
529
 
532
    public final int getZoom() {
530
    public final int getZoom() {
533
        return (this.rowHeight / 22) - 1;
531
        return (this.rowHeight / 22) - 1;
534
    }
532
    }
535
 
533
 
536
    private void zoom(int v) {
534
    private void zoom(int v) {
537
        setRowHeight(this.rowHeight + v);
535
        setRowHeight(this.rowHeight + v);
538
    }
536
    }
539
 
537
 
540
    public final void setRowHeight(final int v) {
538
    public final void setRowHeight(final int v) {
541
        if (this.rowHeight != v && v < 200 && v > 20) {
539
        if (this.rowHeight != v && v > 20 && v < 250) {
542
            this.rowHeight = v;
540
            this.rowHeight = v;
543
            // update size
541
            // update size
544
            final int w = this.getSize().width;
542
            final int w = this.getSize().width;
545
            final int h = getPreferredSize().height;
543
            final int h = getPreferredSize().height;
546
            setSize(new Dimension(w, h));
544
            setSize(new Dimension(w, h));
547
            validate();
545
            validate();
548
            repaint();
546
            repaint();
549
            this.firePropertyChange("rowHeight", null, v);
547
            this.firePropertyChange("rowHeight", null, v);
550
            this.firePropertyChange("zoom", null, getZoom());
548
            this.firePropertyChange("zoom", null, getZoom());
551
        }
549
        }
552
    }
550
    }
553
 
551
 
554
    // how many pixels for one hour
552
    // how many pixels for one hour
555
    public final int getRowHeight() {
553
    public final int getRowHeight() {
556
        return this.rowHeight;
554
        return this.rowHeight;
557
    }
555
    }
558
 
556
 
559
    public void setPopupMenuProvider(JPopupMenuProvider popupProvider) {
557
    public void setPopupMenuProvider(JPopupMenuProvider popupProvider) {
560
        this.popupProvider = popupProvider;
558
        this.popupProvider = popupProvider;
561
    }
559
    }
562
 
560
 
563
    public Set<ItemPartView> getSelectedItems() {
561
    public Set<ItemPartView> getSelectedItems() {
564
        return selectedItems;
562
        return selectedItems;
565
    }
563
    }
566
 
564
 
567
    public ItemPartView getItemPartAt(int x, int y) {
565
    public ItemPartView getItemPartAt(int x, int y) {
568
        ItemPartView newSelection = null;
566
        ItemPartView newSelection = null;
569
        for (List<ItemPartView> l : itemParts) {
567
        for (List<ItemPartView> l : itemParts) {
570
            for (ItemPartView p : l) {
568
            for (ItemPartView p : l) {
571
                if (p.contains(x, y)) {
569
                if (p.contains(x, y)) {
572
                    newSelection = p;
570
                    newSelection = p;
573
                    break;
571
                    break;
574
                }
572
                }
575
            }
573
            }
576
        }
574
        }
577
        return newSelection;
575
        return newSelection;
578
    }
576
    }
579
 
577
 
580
    public void addItemPartHoverListener(ItemPartHoverListener l) {
578
    public void addItemPartHoverListener(ItemPartHoverListener l) {
581
        this.hListeners.add(l);
579
        this.hListeners.add(l);
582
    }
580
    }
583
 
581
 
584
    public void removeItemPartHoverListener(ItemPartHoverListener l) {
582
    public void removeItemPartHoverListener(ItemPartHoverListener l) {
585
        this.hListeners.remove(l);
583
        this.hListeners.remove(l);
586
    }
584
    }
587
 
585
 
588
    abstract public String getColumnTitle(int index);
586
    public abstract String getColumnTitle(int index);
589
 
587
 
590
    abstract public int getColumnCount();
588
    public abstract int getColumnCount();
591
 
589
 
592
    abstract public void reload();
590
    public abstract void reload();
593
 
591
 
594
    public void deselectAll() {
592
    public void deselectAll() {
595
        for (ItemPartView p : selectedItems) {
593
        for (ItemPartView p : selectedItems) {
596
            p.setSelected(false);
594
            p.setSelected(false);
597
        }
595
        }
598
        selectedItems.clear();
596
        selectedItems.clear();
599
 
597
 
600
    }
598
    }
601
}
599
}