View Javadoc
1   /*** PlateView.java - part of the MirkE (say murky) application for colormetric analysis emphesizing 
2   kinetics.
3   
4   Created by: Scott Menor on 21 July, 2004.
5   Last modified by: Scott Menor on 12 December, 2004
6   
7   Copyright (c) 2004 Arizona State University - Cancer Research Institute. All rights reserved.
8   
9   MirkE is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13  
14  MirkE is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18  
19  You should have received a copy of the GNU General Public License
20  along with MirkE; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  US
22  */
23  
24  package edu.asu.cri.MirkE.gui;
25  
26  import java.awt.Dimension;
27  import java.awt.GridBagConstraints;
28  
29  import javax.swing.JLabel;
30  import javax.swing.JPanel;
31  import javax.swing.border.EtchedBorder;
32  import javax.swing.event.EventListenerList;
33  
34  import edu.asu.cri.MirkE.MirkE;
35  import edu.asu.cri.MirkE.dataStructures.DataSet;
36  import edu.asu.cri.MirkE.exceptions.MirkEApplicationException;
37  
38  
39  /*** A viewer for multiwell plates used to represent colormetric data and to allow users to select which well(s) belong to a specific group 
40  
41  @author Scott Menor
42  @version 0.3.0 1 februrary, 2004
43  */
44  public class PlateView extends JPanel {
45  	private DataSet dataSet;
46  	private MirkE mirke;
47  	
48  	protected EventListenerList listenerList = new EventListenerList();
49  	protected PlateViewEvent plateViewEvent = null;
50  	
51  	private String selectableParameter;
52  	
53  	/***
54  		@param selectableParameter
55  		*/
56  	public void setSelectableParameter(String selectableParameter) {
57  		this.selectableParameter = selectableParameter;
58  		// TODO - mass update query to change category names
59  		
60  		firePlateViewUpdated();
61  	}
62  	
63  	/***
64  		@return selectableParameter
65  	 */
66  	public String getSelectableParameter() {
67  		return selectableParameter;
68  	}
69  	
70  	private int numberOfRows = 0;
71  	private int numberOfColumns = 0;
72  	
73  	/*** constructor
74  	 *	
75  	 * @param mirke
76  	 * @param selectableParameter
77  	 * @throws MirkEApplicationException
78  	 */
79  	public PlateView(MirkE mirke, 
80  	        String selectableParameter) throws MirkEApplicationException{
81  	    super();
82  		
83  		this.mirke = mirke;
84  		this.dataSet = mirke.getDataSet();
85  		this.selectableParameter = selectableParameter;
86  		
87  		initialize();
88  	}
89  	
90  	/***
91  	 * @throws MirkEApplicationException 
92  	 */
93  	public void initialize() throws MirkEApplicationException {
94  		dataSet.computePlateDimensions(); // TODO - call this automagically when DataSet is updated?
95  		numberOfRows = dataSet.getNumberOfRows();
96  		numberOfColumns = dataSet.getNumberOfColumns();
97  		createPlateViewGUI();
98  	}
99  	
100 	/***
101 	 * @throws MirkEApplicationException
102 	 */
103 	public void createPlateViewGUI() throws MirkEApplicationException{
104 		java.awt.GridBagConstraints gridBagConstraints;
105 		gridBagConstraints = new java.awt.GridBagConstraints();
106 		gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
107 		gridBagConstraints.ipadx = 8;
108 		gridBagConstraints.ipady = 8;
109 		
110 		setLayout(new java.awt.GridBagLayout()); 
111 		
112 		gridBagConstraints.gridwidth = 1;
113 		gridBagConstraints.gridheight = 1;
114 		gridBagConstraints.anchor = GridBagConstraints.CENTER;
115 		
116 		gridBagConstraints.gridx = 0;
117 		
118 		for (int rowNumber=0;rowNumber<numberOfRows;rowNumber++) {
119 			gridBagConstraints.gridy = rowNumber + 1;
120 			add(new JLabel("" + rowNumberToLabel(rowNumber),
121 						   JLabel.CENTER), 
122 				gridBagConstraints);
123 		}
124 		
125 		gridBagConstraints.gridy = 0;
126 		
127 		for (int columnNumber=0;columnNumber<numberOfColumns;columnNumber++) {
128 			gridBagConstraints.gridx = columnNumber + 1;
129 			
130 			add(new JLabel("" + columnNumberToColumnLabel(columnNumber),
131 						   JLabel.CENTER), 
132 				gridBagConstraints);
133 		}
134 		
135 		Dimension wellSize = new Dimension(25, 
136 										   25); // TODO - automate
137 		String plateWellType = "";
138 		
139 		for (int rowNumber=0;rowNumber<numberOfRows;rowNumber++) {
140 			gridBagConstraints.gridy = rowNumber + 1;
141 			String rowLabel = rowNumberToLabel(rowNumber);
142 			
143 			for (int columnNumber=0;columnNumber<numberOfColumns;columnNumber++) {
144 				gridBagConstraints.gridx = columnNumber + 1;
145 				String columnLabel = columnNumberToColumnLabel(columnNumber);
146 				
147 				java.util.List plateWellDescriptorList = mirke.getDataSet().find("from PlateWellDescriptor as d " +
148 																				 "where d.plateWellType='M' and " + 
149 																				 "d.plateRow='"+rowLabel+"' and " + 
150 																				 "d.plateColumn='"+columnLabel+"'");
151 				
152 				plateWellType = "E";
153 				
154 				if (plateWellDescriptorList.size() > 0) {
155 					plateWellType = "M";
156 				}
157 				
158 				WellButton wellButton = new WellButton(mirke, 
159 													   rowLabel, 
160 													   columnLabel,
161 													   plateWellType,
162 													   selectableParameter);
163 				
164 				wellButton.setPreferredSize(wellSize);
165 				
166 				addPlateViewListener(wellButton);
167 				
168 				add(wellButton, 
169 					gridBagConstraints);
170 			}
171 		}
172 		
173 		setBorder(new EtchedBorder()); // TODO - make a custom plate Border (that actually looks a bit more like a multiwell plate with a notch) and wrap the WellButton s by themselves 
174 	}
175 	
176 	/***
177 		
178 	 @param rowNumber
179 	 
180 	 @return rowLabel
181 	 */
182 	public String rowNumberToLabel(int rowNumber) {
183 		String rowLabel = "";
184 		
185 		rowLabel += (char)('A' + rowNumber);
186 		
187 		return rowLabel;
188 	}
189 	
190 	/***
191 		
192 	 @param columnNumber
193 	 
194 	 @return columnLabel
195 	 */
196 	public String columnNumberToColumnLabel(int columnNumber) {
197 		String columnLabel = "" + (columnNumber + 1);
198 		
199 		return columnLabel;
200 	}
201 	
202 	/***
203 		
204 	 @param mirke
205 	 */
206 	public void setMirke(MirkE mirke) {
207 		this.mirke = mirke;
208 	}
209 	
210 	/***
211 		
212 	 @return mirke
213 	 */
214 	public MirkE getMirke() {
215 		return this.mirke;
216 	}
217 	
218 	/*** Add a listener to be notified of changes in an instance of the <code>PlateView</code>
219 		
220 		@param plateViewEventListener
221 		*/
222 	public void addPlateViewListener(PlateViewEventListener plateViewEventListener) {
223 		listenerList.add(PlateViewEventListener.class, plateViewEventListener);
224 	}
225 	
226 	/*** Remove a listener (no longer notify it of changes to an instance of the <code>PlateView</code>).
227 		
228 		@param plateViewEventListener
229 		*/
230 	public void removePlateViewListener(PlateViewEventListener plateViewEventListener) {
231 		listenerList.remove(PlateViewEventListener.class, plateViewEventListener);
232 	}
233 	
234 	/*** Notify all listeners that the <code>PlateView</code> has changed (TODO - add finer-grain notification so listeners don't need to update everything on a change event)
235 		
236 		*/
237 	protected void firePlateViewUpdated() {
238 		
239 		Object[] listeners = listenerList.getListenerList();
240 		for (int i = listeners.length-2; i>=0; i-=2) { 
241 			if (listeners[i] == PlateViewEventListener.class) {
242 				
243 				// create the event if one doesn't already exist (TODO - should we ensure that a different event is created for each time the model is updated or just use the same one every time; for this case, I think it's fine to use the same one since there is no content to the event object)
244 				if (plateViewEvent == null) {
245 					plateViewEvent = new PlateViewEvent(this);
246 				} 
247 				
248 				((PlateViewEventListener)listeners[i+1]).plateViewChanged(plateViewEvent);
249 			}
250 		}
251 	}	
252 }