PageRenderTime 33ms CodeModel.GetById 14ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 1ms

/edu/uncc/parsets/gui/GroupedDataSetList.java

https://code.google.com/p/parsets/
Java | 312 lines | 199 code | 41 blank | 72 comment | 17 complexity | 8df99107ea3b2ab4a79c8954abc0a1ca MD5 | raw file
  1package edu.uncc.parsets.gui;
  2
  3import java.awt.Color;
  4import java.awt.Component;
  5import java.awt.Font;
  6import java.awt.GradientPaint;
  7import java.awt.Graphics;
  8import java.awt.Graphics2D;
  9import java.awt.GridLayout;
 10import java.awt.event.MouseEvent;
 11import java.awt.event.MouseListener;
 12import java.text.DecimalFormat;
 13import java.util.Arrays;
 14import java.util.List;
 15import java.util.Map;
 16import java.util.Vector;
 17
 18import javax.swing.Box;
 19import javax.swing.BoxLayout;
 20import javax.swing.JLabel;
 21import javax.swing.JList;
 22import javax.swing.JPanel;
 23import javax.swing.ListCellRenderer;
 24import javax.swing.ListSelectionModel;
 25import javax.swing.event.ListSelectionEvent;
 26import javax.swing.event.ListSelectionListener;
 27
 28import edu.uncc.parsets.data.DataSet;
 29
 30/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 31 * Copyright (c) 2009, Robert Kosara, Caroline Ziemkiewicz,
 32 *                     and others (see Authors.txt for full list)
 33 * All rights reserved.
 34 * 
 35 * Redistribution and use in source and binary forms, with or without
 36 * modification, are permitted provided that the following conditions are met:
 37 * 
 38 *    * Redistributions of source code must retain the above copyright
 39 *      notice, this list of conditions and the following disclaimer.
 40 *    * Redistributions in binary form must reproduce the above copyright
 41 *      notice, this list of conditions and the following disclaimer in the
 42 *      documentation and/or other materials provided with the distribution.
 43 *    * Neither the name of UNC Charlotte nor the names of its contributors
 44 *      may be used to endorse or promote products derived from this software
 45 *      without specific prior written permission.
 46 *      
 47 * THIS SOFTWARE IS PROVIDED BY ITS AUTHORS ''AS IS'' AND ANY
 48 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 50 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
 51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 54 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 57\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 58
 59/**
 60 * List that shows group headings, and is specific to DataSet. This is a very
 61 * simple adaptation that breaks a lot of JList's functionality.
 62 * 
 63 * Only use {@link #setSectionData(Map)} to set the data for the list, and
 64 * {@link #getSelectedDataSet()} and the {@link DSListener} class to interact
 65 * with this class.
 66 * 
 67 * Also, this currently only works with {@link ListSelectionModel#SINGLE_SELECTION},
 68 * as the functions that would handle multiple selection are not there yet.
 69 *
 70 */
 71@SuppressWarnings("serial")
 72public class GroupedDataSetList extends JList implements ListSelectionListener, MouseListener {
 73
 74	public static interface DSListener {
 75		/** 
 76		 * Called when the user clicks somewhere in the list. The argument is
 77		 * null if the user clicked on a heading.
 78		 * 
 79		 * @param ds The selected {@link DataSet} or null
 80		 */
 81		public void selectDataSet(DataSet ds);
 82
 83		/**
 84		 * Called when the user double-clicks on a dataset. This is only
 85		 * called for actual {@link DataSet}s, never with null.
 86		 * 
 87		 * @param ds The dataset to be opened
 88		 */
 89		public void openDataSet(DataSet ds);
 90	}
 91	
 92	private static final int CELLWIDTH = 180;
 93	
 94	private Object dataSets[];
 95	
 96	private List<DSListener> dsListeners = new Vector<DSListener>();
 97	
 98	private static class DBTableCellRenderer implements ListCellRenderer {
 99
100		private static final Font TITLELABELFONT = new Font("Sans-Serif", Font.PLAIN, 14);
101		private static final Font TITLEBOLDFONT = new Font("Sans-Serif", Font.BOLD, 14);
102		private static final Font DETAILSLABELFONT = new Font("Sans-Serif", Font.PLAIN, 10);
103		private static final Font DETAILSBOLDFONT = new Font("Sans-Serif", Font.BOLD, 10);
104		private static final Color STRIPECOLOR = new Color(230, 230, 255);
105
106		private static final Font SECTIONLABELFONT = new Font("Sans-Serif", Font.BOLD, 14);
107
108		DecimalFormat format = new DecimalFormat("###,###,###");
109		
110		
111		private JLabel titleLabel;
112		private JLabel detailsLabel;
113		private JLabel sectionLabel;
114		
115		private JPanel dsPanel;
116		private JPanel labelPanel;
117
118		protected static final Color GRADIENT_TOP = Color.WHITE;
119		protected static final Color GRADIENT_BOTTOM = new Color(0xeeeeee); //new Color(0xF9E198);
120		
121		public DBTableCellRenderer() {
122			dsPanel = new JPanel();
123			dsPanel.setLayout(new GridLayout(2, 1));
124			dsPanel.setOpaque(true);
125			Box b = new Box(BoxLayout.X_AXIS);
126			b.add(Box.createHorizontalStrut(2));
127			b.add(titleLabel = new JLabel("DataSet Name"));
128			titleLabel.setFont(TITLELABELFONT);
129			dsPanel.add(b);
130			b = new Box(BoxLayout.X_AXIS);
131			b.add(Box.createHorizontalStrut(2));
132			b.add(detailsLabel = new JLabel("DataSet Details"));
133			detailsLabel.setFont(DETAILSLABELFONT);
134			dsPanel.add(b);
135			
136			labelPanel = new JPanel() {
137				protected void paintComponent(Graphics g) {
138					super.paintComponent(g);
139					GradientPaint gradientPaint = new GradientPaint(0, 0,
140							GRADIENT_TOP, 0, getHeight(), GRADIENT_BOTTOM);
141					Graphics2D g2 = (Graphics2D) g;
142					g2.setPaint(gradientPaint);
143					g2.fillRect(0, 0, getWidth(), getHeight()-1);
144				}
145			};
146			labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
147			labelPanel.setOpaque(true);
148			labelPanel.setBackground(Color.WHITE);
149			labelPanel.add(Box.createVerticalStrut(5));
150			b = new Box(BoxLayout.X_AXIS);
151			b.add(sectionLabel = new JLabel("Heading"));
152			labelPanel.add(b);
153			labelPanel.add(Box.createVerticalStrut(5));
154			sectionLabel.setFont(SECTIONLABELFONT);
155		}
156		
157//		@Override
158		public Component getListCellRendererComponent(JList list, Object value,
159				int index, boolean isSelected, boolean cellHasFocus) {
160			
161			if (value instanceof DataSet) {
162				if (isSelected) {
163					dsPanel.setBackground(list.getSelectionBackground());
164					titleLabel.setForeground(list.getSelectionForeground());
165					titleLabel.setFont(TITLEBOLDFONT);
166					detailsLabel.setForeground(list.getSelectionForeground());
167					detailsLabel.setFont(DETAILSBOLDFONT);
168				} else {
169					boolean stripe = (index & 1) == 1;
170					Color bg = (stripe?STRIPECOLOR:Color.WHITE);
171					dsPanel.setBackground(bg);
172					titleLabel.setForeground(list.getForeground());
173					titleLabel.setFont(TITLELABELFONT);
174					detailsLabel.setForeground(list.getForeground());
175					detailsLabel.setFont(DETAILSLABELFONT);
176				}
177
178				DataSet ds = (DataSet) value;
179				titleLabel.setText(ds.getName());
180				
181				StringBuilder sb = new StringBuilder();
182				sb.append(ds.getNumDimensions()+" dimensions, ");
183				sb.append(format.format(ds.getNumRecords())+" items");
184				detailsLabel.setText(sb.toString());
185				return dsPanel;
186			} else {
187				String section = ((SectionLabel) value).getName();
188				sectionLabel.setText(section);
189				return labelPanel;
190			}
191		}
192	}
193	
194	private static class SectionLabel {
195		private String name;
196		
197		public SectionLabel(String sectionName) {
198			name = sectionName;
199		}
200		
201		public String getName() {
202			return name;
203		}
204	}
205	
206	public GroupedDataSetList() {
207		super();
208		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
209		setCellRenderer(new DBTableCellRenderer());
210		setFixedCellWidth(CELLWIDTH);
211		addListSelectionListener(this);
212		addMouseListener(this);
213	}
214	
215	public GroupedDataSetList(Map<String, List<DataSet>> sections) {
216		this();
217		setSectionData(sections);
218	}
219	
220	public void addDSListener(DSListener listener) {
221		dsListeners.add(listener);
222	}
223	
224	public void removeDSListener(DSListener listener) {
225		dsListeners.remove(listener);
226	}
227	
228	public void setSectionData(Map<String, List<DataSet>> sections) {
229		String[] sectionNames = new String[sections.size()];
230		sections.keySet().toArray(sectionNames);
231		Arrays.sort(sectionNames);
232		int numDataSets = 0;
233		for (List<DataSet> dsList : sections.values())
234			numDataSets += dsList.size();
235		dataSets = new Object[numDataSets+sectionNames.length];
236		int index = 0;
237		for (String section : sectionNames) {
238			dataSets[index++] = new SectionLabel(section);
239			for (DataSet ds : sections.get(section))
240				dataSets[index++] = ds;
241		}
242		setListData(dataSets);
243	}
244
245	/**
246	 * Returns true if the item at the given index is a {@link DataSet},
247	 * false if it is a heading.
248	 * 
249	 * @param index the list index to check
250	 * @return true if item at index is a {@link DataSet}
251	 */
252	private boolean isIndexActive(int index) {
253		if (index >= 0)
254			return dataSets[index] instanceof DataSet;
255		else
256			return false;
257	}
258
259	/**
260	 * calls {@link #getDataSet(int)} for the currently selected item.
261	 * 
262	 * @return The selected {@link DataSet} or null
263	 */
264	public DataSet getSelectedDataSet() {
265		return getDataSet(getSelectedIndex());
266	}
267
268	/**
269	 * Returns the {@link DataSet} at the given index, or null if
270	 * that item is a heading.
271	 * 
272	 * @param index The index of the item to return
273	 * @return The {@link DataSet} at the index or null.
274	 */
275	private DataSet getDataSet(int index) {
276		if (isIndexActive(index))
277			return (DataSet) dataSets[index];
278		else
279			return null;
280	}
281
282	public void valueChanged(ListSelectionEvent e) {
283		DataSet ds = getSelectedDataSet();
284		for (DSListener listener : dsListeners)
285			listener.selectDataSet(ds);
286	}
287
288	public void mouseClicked(MouseEvent e) {
289		if (e.getClickCount() == 2) {
290			int index = locationToIndex(e.getPoint());
291			if (isIndexActive(index)) {
292				ensureIndexIsVisible(index);
293				DataSet ds = getDataSet(index);
294				if (ds != null)
295					for (DSListener listener : dsListeners)
296						listener.openDataSet(ds);
297			}
298		}
299	}
300
301	public void mouseEntered(MouseEvent e) {
302	}
303
304	public void mouseExited(MouseEvent e) {
305	}
306
307	public void mousePressed(MouseEvent e) {
308	}
309
310	public void mouseReleased(MouseEvent e) {
311	}
312}