001 /*
002 * This program is free software; you can redistribute it and/or modify
003 * it under the terms of the GNU General Public License as published by
004 * the Free Software Foundation; version 2 of the License.
005 *
006 * This program is distributed in the hope that it will be useful,
007 * but WITHOUT ANY WARRANTY; without even the implied warranty of
008 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
009 * GNU General Public License for more details.
010 *
011 * You should have received a copy of the GNU General Public License along
012 * with this program; if not, write to the Free Software Foundation, Inc.,
013 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
014 */
015 package org.tastybug.bugwerk.bugtrail.widget.ticket;
016
017 import java.awt.Dimension;
018 import java.util.Arrays;
019 import java.util.Date;
020 import java.util.Iterator;
021
022 import javax.swing.JScrollPane;
023 import javax.swing.JTabbedPane;
024 import javax.swing.SwingConstants;
025 import javax.swing.ToolTipManager;
026
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029 import org.tastybug.bugwerk.blueprint.event.IncidentChangeListener;
030 import org.tastybug.bugwerk.blueprint.event.TicketChangeListener;
031 import org.tastybug.bugwerk.blueprint.model.Incident;
032 import org.tastybug.bugwerk.blueprint.model.Ticket;
033 import org.tastybug.bugwerk.bugtrail.widget.incident.IncidentTable;
034
035
036 /**
037 * This <code>JTabbedPane</code> displays a ticket.
038 * <br>
039 * One tab is created for the base data of the Ticket, one tab for each contained <code>Incident</code>,
040 * containing an <code>IncidentTable</code>.
041 * <br><br>
042 *
043 * <hr>
044 * Copyright 2006 Philipp Bartsch.<br>
045 * <a href="http://www.tastybug.com">www.tastybug.com</a><br>
046 * <hr>
047 * Created on Feb 8, 2006<br>
048 * @author Philipp Bartsch, philipp.bartsch{at}tastybug{dot}com</a>
049 */
050 public class TicketDisplayTabPane extends JTabbedPane implements TicketChangeListener, IncidentChangeListener {
051
052 /**Comment for <code>serialVersionUID</code>*/
053 private static final long serialVersionUID = -6451931754422314904L;
054
055 /**The commons logger.*/
056 private static final Log logger = LogFactory.getLog(TicketDisplayTabPane.class);
057
058
059 private Ticket ticket;
060 private Incident[] incidents;
061 private final Dimension scrollerDimension;
062
063 /**
064 * Creates the tab pane with TOP tab layout.
065 *
066 * @param _scrollerDimension the dimension of the scroller that holds the tabs content
067 */
068 public TicketDisplayTabPane (Dimension _scrollerDimension) {
069 super(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
070 scrollerDimension = _scrollerDimension;
071 ToolTipManager.sharedInstance().registerComponent(this);
072 // erstmal eine null-Sicht
073 setTicket(null);
074 }
075
076 /**
077 * Sets a new <code>Ticket</code> that is to be displayed. The display unregisters
078 * from the old ticket.
079 *
080 * @param _ticket the new ticket - can be <code>null</code> to empty the display
081 */
082 public void setTicket (Ticket _ticket) {
083
084 // beim alten ticket und seinen incidents abmelden
085 if (ticket != null) {
086 ticket.removeTicketChangeListener(this);
087 for (Iterator incidentsIt = Arrays.asList(incidents).iterator(); incidentsIt.hasNext();)
088 ((Incident)incidentsIt.next()).removeIncidentChangeListener(this);
089 }
090
091 // neues ticket merken
092 ticket = _ticket;
093
094 // alle alten tabs entfernen
095 removeAll();
096
097 // common-tab bauen
098 JScrollPane scroller = new JScrollPane(new TicketTable(ticket));
099 scroller.setPreferredSize(scrollerDimension);
100 addTab("Common", null, scroller, "bla");
101
102 // gibts ein neues ticket oder wird die komponente "zurueckgesetzt"?
103 if (ticket == null) {
104 incidents = null;
105 } else {
106 incidents = ticket.getIncidents();
107 ticket.addTicketChangeListener(this);
108
109 // incident-tabs bauen
110 Incident incident;
111 for (Iterator incidentsIt = Arrays.asList(incidents).iterator(); incidentsIt.hasNext();) {
112 incident = (Incident)incidentsIt.next();
113 // gleich mal beim incident als listener anemelden
114 incident.addIncidentChangeListener(this);
115 addIncidentTab(incident);
116 }
117 }
118 }
119
120 /**
121 * Adds a tab for <code>incident</code>.
122 *
123 * @param incident the incident
124 */
125 private void addIncidentTab (Incident incident) {
126
127 IncidentTable incidentTable = new IncidentTable(incident);
128 incidentTable.setName(incident.getOccurrenceDate() + ""); // noch markieren, damit wirs wieder finden
129 JScrollPane scroller = new JScrollPane(incidentTable);
130 scroller.setPreferredSize(scrollerDimension);
131
132 addTab(new Date(incident.getOccurrenceDate().longValue()).toString(), null, scroller, "Lists the incident from " + new Date(incident.getOccurrenceDate().longValue()).toString() + ".");
133 }
134
135 /**
136 * Removes the tab of <code>incident</code>
137 *
138 * @param incident the incident
139 */
140 private void removeIncidentTab (Incident incident) {
141 // durch alle tabs iterieren und dasjenige loeschen, hinter dem sich der incident verbirgt
142 int incidentIndex = getIndexOfIncident(incident);
143 if (incidentIndex != -1)
144 removeTabAt(incidentIndex);
145 else
146 logger.error("Incident '" + incident.getIncidentSignature() + "' has been removed, but i couldn`t find its tab within me!");
147 }
148
149 /**
150 * Returns the tab index at which <code>incident</code> is displayed.
151 *
152 * @param incident the incident
153 * @return the index or -1, if <code>incident</code> was not found
154 */
155 private int getIndexOfIncident (Incident incident) {
156 if (getTabCount() <= 1)
157 return -1;
158
159 for (int i = 1; i < getTabCount(); i++) {
160 // hier gucken, ob der name der komponente mit dem incident-datum uebereinstimmt
161 if (getComponentAt(i).getName().equals(incident.getOccurrenceDate() + "")) {
162 return i;
163 }
164 }
165 return -1;
166 }
167
168 /**
169 * Results in the removal of the corresponding incident tab.
170 *
171 * @see org.tastybug.bugwerk.blueprint.event.TicketChangeListener#performIncidentRemovedEvent(org.tastybug.bugwerk.blueprint.event.TicketChangeListener.IncidentEvent)
172 */
173 public void performIncidentRemovedEvent(IncidentEvent event) {
174 // keine ueberpruefung, obs ueberhaupt incidents gibt (incidents.length > 0), da es
175 // keinen event gibt, wenns keine incidents gibt
176 removeIncidentTab(event.getIncident());
177 }
178
179 /**
180 * Results in the appendage of a display tab for the new incident
181 *
182 * @see org.tastybug.bugwerk.blueprint.event.TicketChangeListener#performIncidentAddedEvent(org.tastybug.bugwerk.blueprint.event.TicketChangeListener.IncidentEvent)
183 */
184 public void performIncidentAddedEvent(IncidentEvent event) {
185 addIncidentTab(event.getIncident());
186 }
187
188 /**
189 * Results in an update of the base data tab.
190 *
191 * @see org.tastybug.bugwerk.blueprint.event.TicketChangeListener#performTicketChangedEvent(org.tastybug.bugwerk.blueprint.event.TicketChangeListener.TicketChangeEvent)
192 */
193 public void performTicketChangedEvent(TicketChangeEvent event) {
194 setTicket(event.getTicket());
195 }
196
197 /**
198 * Results in an update of the corresponding incident tab.
199 *
200 * @see org.tastybug.bugwerk.blueprint.event.IncidentChangeListener#performIncidentChangedEvent(org.tastybug.bugwerk.blueprint.event.IncidentChangeListener.IncidentChangeEvent)
201 */
202 public void performIncidentChangedEvent(IncidentChangeEvent event) {
203 // alten display loeschen
204 removeIncidentTab(event.getIncident());
205 // neuen display hinzufuegen
206 addIncidentTab(event.getIncident());
207 }
208
209 /**
210 * Results in an update of the corresponding incident tab.
211 *
212 * @see org.tastybug.bugwerk.blueprint.event.IncidentChangeListener#performAttachementAddedEvent(org.tastybug.bugwerk.blueprint.event.IncidentChangeListener.AttachmentEvent)
213 */
214 public void performAttachementAddedEvent(AttachmentEvent event) {
215 // alten display loeschen
216 removeIncidentTab(event.getIncident());
217 // neuen display hinzufuegen
218 addIncidentTab(event.getIncident());
219 }
220
221 /**
222 * Results in an update of the corresponding incident tab.
223 *
224 * @see org.tastybug.bugwerk.blueprint.event.IncidentChangeListener#performAttachmentRemovedEvent(org.tastybug.bugwerk.blueprint.event.IncidentChangeListener.AttachmentEvent)
225 */
226 public void performAttachmentRemovedEvent(AttachmentEvent event) {
227 // alten display loeschen
228 removeIncidentTab(event.getIncident());
229 // neuen display hinzufuegen
230 addIncidentTab(event.getIncident());
231 }
232
233 }