1 /*
2 * File: AbstractTimeBarRowModel.java
3 * Copyright (c) 2004-2007 Peter Kliem (Peter.Kliem@jaret.de)
4 * A commercial license is available, see http://www.jaret.de.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 package de.jaret.util.ui.timebars.model;
21
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Vector;
27
28 import de.jaret.util.date.Interval;
29 import de.jaret.util.date.JaretDate;
30
31 /**
32 * An abstract base implementation of the TimeBarRow interface. The part to implement is the storage and retrieval of
33 * the intervals in the row. Care has to be taken to update the min/max date fields with the intervals. Implementations
34 * for some additional methods are given, but are not guaranteed to be optimal (in fact they are not!).
35 *
36 * @author Peter Kliem
37 * @version $Id: AbstractTimeBarRowModel.java 800 2008-12-27 22:27:33Z kliem $
38 */
39 public abstract class AbstractTimeBarRowModel implements TimeBarRow, PropertyChangeListener {
40 /** the row header of the row. */
41 protected TimeBarRowHeader _header;
42
43 /**
44 * the minimum date of all intervals. This should always be up to date by updating.
45 */
46 protected JaretDate _minDate;
47
48 /**
49 * the maximum date of all intervals. This should always be up to date by updating.
50 */
51 protected JaretDate _maxDate;
52
53 /** the registered listeners. */
54 protected List<TimeBarRowListener> _listenerList;
55
56 /**
57 * Default constructor. Note that a header should be set.
58 *
59 */
60 public AbstractTimeBarRowModel() {
61 }
62
63 /**
64 * onstructor supplying a header.
65 *
66 * @param header row header to be used
67 */
68 public AbstractTimeBarRowModel(TimeBarRowHeader header) {
69 setRowHeader(header);
70 }
71
72 /**
73 * {@inheritDoc} Remains abstract and has to implemented.
74 */
75 public abstract List<Interval> getIntervals();
76
77 /**
78 * {@inheritDoc} Very simple (imperformant) implementation.
79 */
80 public List<Interval> getIntervals(JaretDate beginDate, JaretDate endDate) {
81 // List is sorted
82 List<Interval> result = new ArrayList<Interval>();
83 if (getIntervals() != null) {
84 for (Interval interval : getIntervals()) {
85 if ((interval.getBegin().compareTo(beginDate) >= 0 && interval.getBegin().compareTo(endDate) <= 0)
86 || (interval.getEnd().compareTo(beginDate) >= 0 && interval.getEnd().compareTo(endDate) <= 0)
87 || (interval.getBegin().compareTo(beginDate) <= 0 && interval.getEnd().compareTo(endDate) >= 0)) {
88 result.add(interval);
89 }
90 // this may be an optimization if it is guaranteed that the
91 // intervals are sorted.
92 // else if (interval.getBegin().compareTo(endDate) >= 0) {
93 // break;
94 // }
95 }
96 }
97 return result;
98 }
99
100 /**
101 * {@inheritDoc}
102 */
103 public List<Interval> getIntervals(JaretDate date) {
104 // Liste ist sortiert
105 List<Interval> result = new ArrayList<Interval>();
106 for (Interval interval : getIntervals()) {
107 if (interval.contains(date)) {
108 result.add(interval);
109 }
110 // see above
111 // else if (interval.getBegin().compareTo(date) >= 0) {
112 // break;
113 // }
114 }
115 return result;
116 }
117
118 /**
119 * {@inheritDoc}
120 */
121 public TimeBarRowHeader getRowHeader() {
122 return _header;
123 }
124
125 /**
126 * Set the row header.
127 *
128 * @param header header to set
129 */
130 public void setRowHeader(TimeBarRowHeader header) {
131 if (_header != null) {
132 _header.removePropertyChangeListener(this);
133 }
134 _header = header;
135 if (_header != null) {
136 _header.addPropertyChangeListener(this);
137 }
138 fireHeaderChanged();
139 }
140
141 /**
142 * {@inheritDoc}
143 */
144 public synchronized void addTimeBarRowListener(TimeBarRowListener tbrl) {
145 if (_listenerList == null) {
146 _listenerList = new Vector<TimeBarRowListener>();
147 }
148 _listenerList.add(tbrl);
149 }
150
151 /**
152 * {@inheritDoc}
153 */
154 public void remTimeBarRowListener(TimeBarRowListener tbrl) {
155 if (_listenerList != null) {
156 _listenerList.remove(tbrl);
157 }
158 }
159
160 /**
161 * Inform listeners that all row data may have changed.
162 *
163 */
164 protected void fireRowDataChanged() {
165 if (_listenerList != null) {
166 for (TimeBarRowListener tbrl : _listenerList) {
167 tbrl.rowDataChanged(this);
168 }
169 }
170 }
171
172 /**
173 * Inform listeners that a new interval has been added.
174 *
175 * @param element added interval
176 */
177 protected void fireElementAdded(Interval element) {
178 if (_listenerList != null) {
179 for (TimeBarRowListener tbrl : _listenerList) {
180 tbrl.elementAdded(this, element);
181 }
182 }
183 }
184
185 /**
186 * Inform listeners that an interval has been removed.
187 *
188 * @param element removed interval
189 */
190 protected void fireElementRemoved(Interval element) {
191 if (_listenerList != null) {
192 for (TimeBarRowListener tbrl : _listenerList) {
193 tbrl.elementRemoved(this, element);
194 }
195 }
196 }
197
198 /**
199 * Inform listeners that an element has changed.
200 *
201 * @param element changed interval
202 */
203 protected void fireElementChanged(Interval element) {
204 if (_listenerList != null) {
205 for (TimeBarRowListener tbrl : _listenerList) {
206 tbrl.elementChanged(this, element);
207 }
208 }
209 }
210
211 /**
212 * Inform listeners about a chnage of the header.
213 *
214 */
215 protected void fireHeaderChanged() {
216 if (_listenerList != null) {
217 for (TimeBarRowListener tbrl : _listenerList) {
218 tbrl.headerChanged(this, getRowHeader());
219 }
220 }
221 }
222
223 /**
224 * @return Returns the maxDate.
225 */
226 public JaretDate getMaxDate() {
227 return _maxDate;
228 }
229
230 /**
231 * @return Returns the minDate.
232 */
233 public JaretDate getMinDate() {
234 return _minDate;
235 }
236
237 /**
238 * Handle property changes of the intervals in the row and of the header.
239 *
240 * @param evt propChange event from the model elements
241 */
242 public void propertyChange(PropertyChangeEvent evt) {
243 if (evt.getSource() instanceof Interval) {
244 updateMinMax();
245 fireElementChanged((Interval) evt.getSource());
246 } else if (evt.getSource() == _header) {
247 fireHeaderChanged();
248 } else {
249 throw new RuntimeException("Unknown sender " + evt.getSource());
250 }
251 }
252
253 /**
254 * Updates the minimum and the maximum dates that may be queried by users of the row.
255 *
256 */
257 protected void updateMinMax() {
258 // need to check all intervals since the limits may have been reduced
259 // ...
260 _minDate = null;
261 _maxDate = null;
262 for (Interval i : getIntervals()) {
263 if (_minDate == null || _minDate.compareTo(i.getBegin()) > 0) {
264 _minDate = i.getBegin().copy();
265 }
266 if (_maxDate == null || _maxDate.compareTo(i.getEnd()) < 0) {
267 _maxDate = i.getEnd().copy();
268 }
269 }
270 if (_minDate == null) {
271 _minDate = new JaretDate();
272 }
273 if (_maxDate == null) {
274 _maxDate = new JaretDate();
275 }
276 }
277 }