View Javadoc

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 }