View Javadoc

1   package com.explosion.datastream.exql.gui.dbbrowser;
2   
3   /*
4    * =============================================================================
5    * 
6    * Copyright 2004 Stephen Cowx
7    * 
8    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9    * use this file except in compliance with the License. You may obtain a copy of
10   * the License at
11   * 
12   * http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.awt.BorderLayout;
24  import java.awt.FontMetrics;
25  import java.beans.PropertyChangeEvent;
26  import java.beans.PropertyChangeListener;
27  import java.util.Enumeration;
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.Vector;
31  
32  import javax.swing.JLabel;
33  import javax.swing.JPanel;
34  import javax.swing.JScrollPane;
35  import javax.swing.JTable;
36  import javax.swing.table.DefaultTableModel;
37  import javax.swing.table.JTableHeader;
38  import javax.swing.table.TableColumn;
39  
40  import org.apache.log4j.LogManager;
41  import org.apache.log4j.Logger;
42  
43  import com.explosion.datastream.exql.EXQLConstants;
44  import com.explosion.datastream.exql.EXQLModuleManager;
45  import com.explosion.datastream.exql.gui.EXQLBaseTool;
46  import com.explosion.datastream.exql.gui.table.DsProTable;
47  import com.explosion.datastream.exql.gui.table.Sort_HeaderRenderer;
48  import com.explosion.datastream.exql.gui.table.Sort_MouseListener;
49  import com.explosion.expf.Application;
50  import com.explosion.expfmodules.rdbmsconn.dbom.DBEntity;
51  import com.explosion.expfmodules.rdbmsconn.dbom.DBEntityBuffer;
52  import com.explosion.expfmodules.rdbmsconn.dbom.DataSet;
53  import com.explosion.utilities.GeneralUtils;
54  import com.explosion.utilities.RowHeaderUtil;
55  import com.explosion.utilities.exception.ExceptionManagerFactory;
56  
57  /***
58   * @author Stephen Cowx
59   */
60  
61  public class TabularDataView extends JPanel {
62  
63  	private static Logger log = LogManager.getLogger(TabularDataView.class);
64  	private JScrollPane scrollPane = new JScrollPane();
65  	private DsProTable dataTable;
66  
67  	private Sort_MouseListener mouseListener = null;
68  	private Sort_HeaderRenderer headerRenderer = null;
69      private JLabel label;
70  	
71  	/* A map containing the last columnWidths if there was no DBEntityData */
72  	private Map lastColumnWidths = new HashMap();
73  
74  	/***
75  	 * Constructor
76  	 */
77  	public TabularDataView(EXQLBaseTool tool, boolean editable) {
78  		try {
79  			dataTable = new DsProTable(tool, editable);
80  			init();
81  		} catch (Exception e) {
82  			ExceptionManagerFactory.getExceptionManager().manageException(e,
83  					"Exception caught while constructing data view.");
84  		}
85  	}
86  
87  	/***
88  	 * Initialises the panel
89  	 */
90  	private void init() throws Exception {
91  		this.setLayout(new BorderLayout());
92  		this.add(scrollPane, BorderLayout.CENTER);
93  		scrollPane.getViewport().add(dataTable, null);
94  		
95  	}
96  
97  	/***
98  	 * Applies the properties for this tool;
99  	 */
100 	public void applyPreferences() {
101 
102 		dataTable.applyPreferences();
103 	}
104     
105     /***
106      * Adds a label with the specified message
107      */
108     private void addLabel(String message)
109     {
110         label = new JLabel(message);
111         label.setName(message);
112         this.add(label, BorderLayout.NORTH);
113     }
114     /***
115      * Removes a label with the specified message if it exists
116      */
117     private void removeLabel()
118     {
119         if (label != null)
120         {
121           this.remove(label);
122           this.label = null;
123         }
124     }
125 
126 	/***
127 	 * This method updates the displayed values
128 	 */
129 	public void update(EXQLBaseTool tool) {
130 		try {
131 			DataSet set = tool.getCurrentEntityMetaData().getDataSet();
132 			DBEntity dbed = tool.getCurrentEntityMetaData().getDbEntity();
133             removeLabel();
134             
135 			if (set != null) {
136 				log.debug("Dbed: " + dbed);
137                 Application.ensureLocalCookie(EXQLConstants.MENU_EXPORT, 1, tool);
138                 
139                 
140                 RowHeaderUtil util = new RowHeaderUtil();
141 				util.setRowHeader(dataTable, false);
142 				
143                 /* Mark it as not editable if there is no metadata or no primary key */
144                 if (dbed == null || dbed.getPrimaryKeyColumns().size() < 1)
145                 {
146                     dataTable.setEditable(false);
147                     if (dbed != null)
148                     {
149                         addLabel("No primary key defined, edits not allowed on this table");
150                     }
151                 }
152                 else
153                 {
154                     dataTable.setEditable(true);
155                     
156                 }
157                 dataTable.setModel(set.getTableModel());
158 
159 				if (dbed != null) {
160 					/*
161 					 * Add listeners for the column widths and set the widths if
162 					 * they have been persisted from last time
163 					 */
164 					boolean widthsSet = false;
165 					Enumeration eneration = dataTable.getColumnModel()
166 							.getColumns();
167 					while (eneration.hasMoreElements()) {
168 						TableColumn column = (TableColumn) eneration
169 								.nextElement();
170 
171 						ColumnWidthListener listener = new ColumnWidthListener(
172 								dbed.getDBEntityBuffer(), (String) column
173 										.getHeaderValue());
174 						column.addPropertyChangeListener(listener);
175 
176 					}
177                }
178                
179 				
180 				/* Add lsiteners and renderes for sorting */
181 				JTableHeader header = dataTable.getTableHeader();
182 				if (header != null) {
183 					if (dbed != null) {
184 						if (mouseListener == null) {
185 							mouseListener = new Sort_MouseListener(tool.getViewer());
186 							header.addMouseListener(mouseListener);
187                             header.setToolTipText("Double click on this header to sort by this column.  Shift Double click to remove the sort.  Cntrl Double Click to reverse the sort");
188 							headerRenderer = new Sort_HeaderRenderer(dataTable);
189 							header.setDefaultRenderer(headerRenderer);
190 						}
191 
192 						mouseListener.setEntity(dbed);
193 						headerRenderer.setEntity(dbed);
194 					} else {
195 						header.removeMouseListener(mouseListener);
196 						//header.setDefaultRenderer(null);
197 						mouseListener = null;
198 						headerRenderer = null;
199 					}
200 				}
201 
202 				int maxWidth = ((Integer) EXQLModuleManager.instance().getPreference(EXQLConstants.RDBMS_OPTION_MAX_AUTO_COLUMNWIDTH).getValue()).intValue();
203 				
204 				/* Size the columns to fit */
205                 sizeColumnsToFitWidths(dbed != null ? dbed.getDBEntityBuffer() : null, dataTable, set
206 						.getLongestEntries(), set.getColumnNames(), maxWidth, true);
207 			} else {
208                 Application.ensureLocalCookie(EXQLConstants.MENU_EXPORT, 0, tool);
209 				show_NoInfo_Message();
210 			}
211 		} catch (Exception ex) {
212 			ExceptionManagerFactory.getExceptionManager()
213 					.manageException(ex,
214 							"Experienced exception while populating view of table data.");
215 			show_NoInfo_Message();
216 		}
217 	}
218 
219 	/***
220 	 * Returns the dataTable.
221 	 * 
222 	 * @return JTable
223 	 */
224 	public DsProTable getDataTable() {
225 		return dataTable;
226 	}
227 
228 	public void showMessage(String message) {
229 		FontMetrics fontMetrics = dataTable.getFontMetrics(dataTable.getFont());
230 		int width = fontMetrics.stringWidth(message);
231 		String[] longestEntry = {message};
232 
233 		this.dataTable.setModel(GeneralUtils.getEmptyModel(message));
234 		GeneralUtils.sizeColumnsToFitWidths(dataTable, longestEntry, null, 500,
235 				false);
236 	}
237 
238 	public void show_NoInfo_Message() {
239 		showMessage("No information to show.");
240 	}
241 
242 	public void clear() {
243 		dataTable.setModel(new DefaultTableModel(new Vector(), new Vector()));
244 	}
245 
246 	/***
247 	 * This method sizes a tables columns sensibly. It requires quite a lot of
248 	 * info.
249 	 */
250 	private void sizeColumnsToFitWidths(DBEntityBuffer buffer, JTable table,
251 			String[] longestColumnEntries, Vector columnNames, int maxWidth,
252 			boolean includeColumnNames) {
253 		if (table == null || longestColumnEntries == null)
254 			return;
255 
256 		if (includeColumnNames && columnNames == null)
257 			throw new IllegalArgumentException(
258 					"Invalid use of method, includeColumnNames is true but no names have been provided.");
259 
260 		FontMetrics fontMetrics = table.getFontMetrics(table.getFont());
261 		Enumeration columns = table.getColumnModel().getColumns();
262 		int i = 0;
263 		
264 		while (columns.hasMoreElements()) {
265 			int width = -1;
266 			TableColumn column = (TableColumn) columns.nextElement();
267 			if (buffer != null)
268 			    width = buffer.getColumnWidth((String) column.getHeaderValue());
269 			
270 			if (width >= 0) {
271 				/*
272 				 * This column width has been set before so we reset it to it's
273 				 * last value and move on to the next column
274 				 */
275 				column.setWidth(width);
276 				column.setPreferredWidth(width);
277 				continue;
278 			}
279 
280 			if (includeColumnNames)
281 			{
282 				if (column.getHeaderValue().equals("CAPTUREDATE"))
283 					{
284 					  int f=0;
285 					}
286 				
287 				if (longestColumnEntries[i].length() < ((String) columnNames.elementAt(i)).length())
288 				{
289 			    	width = fontMetrics.stringWidth((String) columnNames.elementAt(i)) + 10;
290 				}
291 				else
292 				{
293 					width = fontMetrics.stringWidth(longestColumnEntries[i]) + 10;
294 				}
295 			}
296 			else
297 			{
298 				width = fontMetrics.stringWidth(longestColumnEntries[i]) + 10;
299 			}
300 
301 			if (width > maxWidth) {
302 				if (buffer != null)
303 				   buffer.setColumnWidth((String) column.getHeaderValue(),
304 						maxWidth);
305 				column.setWidth(maxWidth);
306 				column.setPreferredWidth(maxWidth);
307 			} else {
308 				column.setWidth(width);
309 				column.setPreferredWidth(width);
310 				if (buffer != null)
311 					buffer.setColumnWidth((String) column.getHeaderValue(), width);
312 			}
313 			i++;
314 		}
315 	}
316 
317 	/***
318 	 * @return Returns the scrollPane.
319 	 */
320 	public JScrollPane getScrollPane() {
321 		return scrollPane;
322 	}
323 }
324 /***
325  * This class monitors the width of the column as the user changes it then sets
326  * the correct width in the DBEntity Buffer so that the user will get the same
327  * size columns when they come back next time.
328  * 
329  * @author Stephen Created on Apr 29, 2004
330  */
331 
332 class ColumnWidthListener implements PropertyChangeListener {
333 
334 	private DBEntityBuffer buffer;
335 	private String columnName;
336 	private Map lastColumnWidths;
337 	private static Logger log = LogManager.getLogger(ColumnWidthListener.class);
338 
339 	/***
340 	 * Constructor
341 	 * 
342 	 * @param buffer
343 	 * @param columnName
344 	 */
345 	public ColumnWidthListener(DBEntityBuffer buffer, String columnName) {
346 		this.buffer = buffer;
347 		this.columnName = columnName;
348 		//this.lastColumnWidths = lastColumnWidths;
349 	}
350 
351 	/***
352 	 * changes the entitybuffer column width if appropriate
353 	 * 
354 	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
355 	 * @param event
356 	 */
357 	public void propertyChange(PropertyChangeEvent event) {
358 		if (event.getPropertyName().equals("width")) {
359 			buffer.setColumnWidth(columnName, ((Number) event.getNewValue())
360 					.intValue());
361 		}
362 	}
363 }
364