001: package org.jsqltool.gui.panel;
002:
003: import javax.swing.*;
004: import java.awt.*;
005: import javax.swing.event.*;
006: import javax.swing.table.*;
007: import javax.swing.border.*;
008: import java.awt.event.*;
009: import java.util.Vector;
010: import org.jsqltool.conn.DbConnectionUtil;
011: import org.jsqltool.model.CustomTableModel;
012: import org.jsqltool.gui.graphics.DateCellEditor;
013: import org.jsqltool.gui.graphics.DateCellRenderer;
014: import org.jsqltool.utils.Options;
015: import org.jsqltool.utils.ImageLoader;
016:
017: /**
018: * <p>Title: JSqlTool Project</p>
019: * <p>Description: Panel which contains a query result (a block of records).
020: * </p>
021: * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
022: *
023: * <p> This file is part of JSqlTool project.
024: * This library is free software; you can redistribute it and/or
025: * modify it under the terms of the (LGPL) Lesser General Public
026: * License as published by the Free Software Foundation;
027: *
028: * GNU LESSER GENERAL PUBLIC LICENSE
029: * Version 2.1, February 1999
030: *
031: * This library is distributed in the hope that it will be useful,
032: * but WITHOUT ANY WARRANTY; without even the implied warranty of
033: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
034: * Library General Public License for more details.
035: *
036: * You should have received a copy of the GNU Library General Public
037: * License along with this library; if not, write to the Free
038: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
039: *
040: * The author may be contacted at:
041: * maurocarniel@tin.it</p>
042: *
043: * @author Mauro Carniel
044: * @version 1.0
045: */
046: public final class DataPanel extends JPanel {
047:
048: BorderLayout borderLayout1 = new BorderLayout();
049: JScrollPane scrollPane = new JScrollPane();
050: private Table table = new Table();
051: private String query = null;
052: private Vector parameters = new Vector();
053: private String originalQuery = null;
054:
055: /** number of records per block */
056: private int BLOCK_SIZE = 100;
057:
058: /** current first row in block */
059: private int inc = 0;
060: private DbConnectionUtil dbConnUtil = null;
061: private TableModelListener tableModelListener = null;
062: private AdjustmentEvent adjEvent = null;
063: private static final String NO_SORT_SYMBOL = "";
064: private static final String ASC_SYMBOL = "ASC";
065: private static final String DESC_SYMBOL = "DESC";
066:
067: /** table model column index, related to the current sorted column; -1 = no sorted column */
068: private int sortColIndex = -1;
069:
070: /** sort versus: ascending or descending; "" no sort versus */
071: private String sortColValue = "";
072:
073: public DataPanel(DbConnectionUtil dbConnUtil,
074: TableModelListener tableModelListener) {
075: this .dbConnUtil = dbConnUtil;
076: this .tableModelListener = tableModelListener;
077: try {
078: jbInit();
079: init();
080: } catch (Exception e) {
081: e.printStackTrace();
082: }
083: }
084:
085: public DataPanel() {
086: this (null, null);
087: }
088:
089: private void init() {
090: // listener used to set column sorting...
091: MouseAdapter listMouseListener = new MouseAdapter() {
092: public void mouseClicked(MouseEvent e) {
093: try {
094: if (query != null) {
095: if ((e.getClickCount() == 1)
096: && table.getModel().getRowCount() > 1) {
097: int gridColIndex = table.getColumnModel()
098: .getColumnIndexAtX(e.getX());
099: int modelColIndex = table.getColumnModel()
100: .getColumn(gridColIndex)
101: .getModelIndex();
102: String colModelName = table.getModel()
103: .getColumnName(modelColIndex);
104: String colGridName = table.getColumnModel()
105: .getColumn(gridColIndex)
106: .getIdentifier().toString();
107: sortColIndex = modelColIndex;
108: if (sortColValue.equals(NO_SORT_SYMBOL)) {
109: sortColValue = ASC_SYMBOL;
110: } else if (sortColValue.equals(ASC_SYMBOL)) {
111: sortColValue = DESC_SYMBOL;
112: } else if (sortColValue.equals(DESC_SYMBOL)) {
113: sortColValue = NO_SORT_SYMBOL;
114: }
115: table.getColumnModel().getColumn(
116: gridColIndex).setHeaderValue(
117: colGridName);
118: table.getColumnModel().getColumn(
119: gridColIndex).setHeaderRenderer(
120: table.getTableHeader()
121: .getDefaultRenderer());
122: if (sortColValue.equals(NO_SORT_SYMBOL)) {
123: if (originalQuery != null) {
124: query = originalQuery;
125: sortColValue = "";
126: }
127: setQuery();
128: } else {
129: if (originalQuery == null)
130: originalQuery = query;
131: int indexOrderBy = originalQuery
132: .toUpperCase().lastIndexOf(
133: "ORDER BY");
134: int indexGroupBy = originalQuery
135: .toUpperCase().lastIndexOf(
136: "GROUP BY");
137: if (indexOrderBy != -1
138: && indexGroupBy == -1) {
139: query = originalQuery + ","
140: + colModelName + " "
141: + sortColValue;
142: } else if (indexOrderBy != -1
143: && indexOrderBy < indexGroupBy) {
144: query = originalQuery.substring(0,
145: indexGroupBy)
146: + ","
147: + colModelName
148: + " "
149: + sortColValue
150: + " "
151: + originalQuery
152: .substring(indexGroupBy);
153: } else if (indexOrderBy != -1
154: && indexOrderBy > indexGroupBy) {
155: query = originalQuery + ","
156: + colModelName + " "
157: + sortColValue;
158: } else
159: query = originalQuery
160: + " ORDER BY "
161: + colModelName + " "
162: + sortColValue;
163: setQuery();
164:
165: }
166: }
167: }
168: } catch (Exception ex) {
169: }
170: }
171: };
172: JTableHeader th = table.getTableHeader();
173: th.addMouseListener(listMouseListener);
174:
175: // key listener used to scroll table...
176: table.addKeyListener(new KeyAdapter() {
177: public void keyReleased(KeyEvent e) {
178: if (e.getKeyCode() == e.VK_DOWN) {
179: if (table.getSelectedRow() == table.getRowCount() - 1
180: && table.getRowCount() == BLOCK_SIZE) {
181: // fetch next block...
182: inc += BLOCK_SIZE;
183: readBlock();
184: if (table.getRowCount() > 0)
185: table.setRowSelectionInterval(0, 0);
186: table.scrollRectToVisible(table.getCellRect(
187: table.getSelectedRow(), 0, true));
188: }
189: } else if (e.getKeyCode() == e.VK_UP) {
190: if (table.getSelectedRow() == 0 && inc > 0) {
191: // fetch previous block...
192: inc -= BLOCK_SIZE;
193: if (inc < 0)
194: inc = 0;
195: readBlock();
196: table.setRowSelectionInterval(table
197: .getRowCount() - 1,
198: table.getRowCount() - 1);
199: table.scrollRectToVisible(table.getCellRect(
200: table.getSelectedRow(), 0, true));
201: }
202: } else if (e.getKeyCode() == e.VK_PAGE_DOWN) {
203: if (table.getSelectedRow() == table.getRowCount() - 1
204: && table.getRowCount() == BLOCK_SIZE) {
205: // fetch next block...
206: inc += BLOCK_SIZE;
207: readBlock();
208: if (table.getRowCount() > 0)
209: table.setRowSelectionInterval(0, 0);
210: table.scrollRectToVisible(table.getCellRect(
211: table.getSelectedRow(), 0, true));
212: }
213: } else if (e.getKeyCode() == e.VK_PAGE_UP) {
214: if (table.getSelectedRow() == 0 && inc > 0) {
215: // fetch previous block...
216: inc -= BLOCK_SIZE;
217: if (inc < 0)
218: inc = 0;
219: readBlock();
220: table.setRowSelectionInterval(table
221: .getRowCount() - 1,
222: table.getRowCount() - 1);
223: table.scrollRectToVisible(table.getCellRect(
224: table.getSelectedRow(), 0, true));
225: }
226: }
227: }
228: });
229:
230: }
231:
232: private void jbInit() throws Exception {
233: this .setLayout(borderLayout1);
234: table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
235: this .add(scrollPane, BorderLayout.CENTER);
236: scrollPane.getViewport().add(table, null);
237: // scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
238: // public void adjustmentValueChanged(AdjustmentEvent e) {
239: // adjEvent = e;
240: // }
241: // });
242: // scrollPane.getVerticalScrollBar().addMouseListener(new MouseAdapter() {
243: // public void mouseReleased(MouseEvent e){
244: // if (javax.swing.SwingUtilities.isLeftMouseButton(e)){
245: // scrollMov((JScrollBar)adjEvent.getAdjustable());
246: // }
247: // }
248: // }); // mouse lister applied to the scrollbar...
249: // (scrollPane.getVerticalScrollBar().getComponents())[0].addMouseListener(new MouseAdapter() {
250: // public void mouseReleased(MouseEvent e){
251: // if (javax.swing.SwingUtilities.isLeftMouseButton(e)){
252: // scrollMov((JScrollBar)adjEvent.getAdjustable());
253: // }
254: // }
255: // }); // mouse lister applied to the scrollbar up button...
256: // (scrollPane.getVerticalScrollBar().getComponents())[1].addMouseListener(new MouseAdapter() {
257: // public void mouseReleased(MouseEvent e){
258: // if (javax.swing.SwingUtilities.isLeftMouseButton(e)){
259: // scrollMov((JScrollBar)adjEvent.getAdjustable());
260: // }
261: // }
262: // }); // mouse lister applied to the scrollbar down button...
263: }
264:
265: public void setQuery() {
266: this .inc = 0;
267: readBlock();
268: }
269:
270: public void setLastQuery() {
271: this .inc = dbConnUtil.getLastQueryIndex(query, parameters,
272: BLOCK_SIZE);
273: readBlock();
274: }
275:
276: private void readBlock() {
277: if (query == null)
278: return;
279: updateSortIcons();
280: table.getModel().removeTableModelListener(tableModelListener);
281: table.setModel(dbConnUtil.getQuery(query, parameters, inc,
282: BLOCK_SIZE));
283: try {
284: for (int i = 0; i < table.getColumnCount(); i++) {
285: if (((CustomTableModel) table.getModel())
286: .getColumnClass(
287: table.convertColumnIndexToModel(i))
288: .equals(java.util.Date.class)
289: || ((CustomTableModel) table.getModel())
290: .getColumnClass(
291: table
292: .convertColumnIndexToModel(i))
293: .equals(java.sql.Date.class)
294: || ((CustomTableModel) table.getModel())
295: .getColumnClass(
296: table
297: .convertColumnIndexToModel(i))
298: .equals(java.sql.Timestamp.class)) {
299: table.getColumnModel().getColumn(i).setCellEditor(
300: new DateCellEditor());
301: table.getColumnModel().getColumn(i)
302: .setCellRenderer(new DateCellRenderer());
303: table.getColumnModel().getColumn(i)
304: .setPreferredWidth(
305: 6 * Options.getInstance()
306: .getDateFormat().length());
307: } else
308: table
309: .getColumnModel()
310: .getColumn(i)
311: .setPreferredWidth(
312: ((CustomTableModel) table
313: .getModel()).getColSizes()[table
314: .convertColumnIndexToModel(i)]);
315: }
316: if (table.getRowCount() > 0)
317: table.setRowSelectionInterval(0, 0);
318: } catch (Exception ex) {
319: ex.printStackTrace();
320: }
321: table.getModel().addTableModelListener(tableModelListener);
322: }
323:
324: public void setQuery(String query, Vector parameters) {
325: this .query = query;
326: this .parameters = parameters;
327: this .sortColIndex = -1;
328: this .originalQuery = null;
329: setQuery();
330: }
331:
332: public void resetPanel() {
333: this .inc = 0;
334: table.getModel().removeTableModelListener(tableModelListener);
335: table.setModel(new DefaultTableModel());
336: table.getModel().addTableModelListener(tableModelListener);
337: }
338:
339: /**
340: * Method used to read the next/previous block of records.
341: * It's called by mouseReleased method, when the user clicks on the scrollbar.
342: */
343: private void scrollMov(JScrollBar scrollBar) {
344: int scrollableZoneSize = scrollBar.getMaximum()
345: - scrollBar.getVisibleAmount();
346: if ((scrollBar.getValue() > scrollableZoneSize / 4 * 3) && (true)) {
347: // scrolling table over 75% of rows (near the end)
348: table.getModel().removeTableModelListener(
349: tableModelListener);
350: inc += BLOCK_SIZE;
351: table.setModel(dbConnUtil.getQuery(query, new Vector(),
352: inc, BLOCK_SIZE));
353: table.getModel().addTableModelListener(tableModelListener);
354: scrollBar.setValue(250);
355: } else if ((scrollBar.getValue() < scrollableZoneSize / 4)
356: && (inc > 0)) {
357: // scrolling table on 25% of rows (near the beginning)
358: table.getModel().removeTableModelListener(
359: tableModelListener);
360: inc -= BLOCK_SIZE;
361: if (inc < 0)
362: inc = 0;
363: table.setModel(dbConnUtil.getQuery(query, new Vector(),
364: inc, BLOCK_SIZE));
365: table.getModel().addTableModelListener(tableModelListener);
366: scrollBar.setValue(250);
367: }
368: }
369:
370: public TableModel getTableModel() {
371: return table.getModel();
372: }
373:
374: public Table getTable() {
375: return table;
376: }
377:
378: /**
379: * Method used to draw sorting versus onto the table columns.
380: */
381: private void updateSortIcons() {
382: try {
383: Object o = new Object();
384: String[] colOrder = new String[2];
385: TableCellRenderer hr = null;
386: Icon3 ic = null;
387: // reset all columns...
388: for (int i = 0; i < getTable().getColumnCount(); i++) {
389: if ((o = getTable().getColumnModel().getColumn(i)) == null)
390: continue;
391: if ((hr = ((TableColumn) o).getHeaderRenderer()) == null)
392: continue;
393: if (hr instanceof JLabel)
394: if (((JLabel) hr).getIcon() != null)
395: ((Icon3) ((JLabel) hr).getIcon())
396: .setOrder(NO_SORT_SYMBOL);
397: }
398: // re-set icons...
399: if (sortColIndex != -1) {
400: String order = NO_SORT_SYMBOL;
401: if (sortColValue.equals(ASC_SYMBOL))
402: order = ASC_SYMBOL;
403: else if (sortColValue.equals(DESC_SYMBOL))
404: order = DESC_SYMBOL;
405:
406: TableColumn col = null;
407: try {
408: col = getTable()
409: .getColumn(
410: getTableModel().getColumnName(
411: sortColIndex));
412: } catch (IllegalArgumentException ex) {
413: }
414: if ((o = col) == null)
415: return;
416:
417: if ((hr = ((TableColumn) o).getHeaderRenderer()) == null)
418: return;
419:
420: // if (hr instanceof JLabel) {
421: if (hr instanceof DefaultTableCellRenderer
422: || hr instanceof JLabel) {
423:
424: Component comp = col.getHeaderRenderer()
425: .getTableCellRendererComponent(null,
426: col.getHeaderValue(), false, false,
427: 0, 0);
428:
429: ic = new Icon3(order);
430: ((DefaultTableCellRenderer) hr).setIcon(ic);
431: ((DefaultTableCellRenderer) hr)
432: .setHorizontalTextPosition(JLabel.LEFT);
433: }
434: getTable().getTableHeader().revalidate();
435: getTable().getTableHeader().repaint();
436: }
437: } catch (Exception ex) {
438: ex.printStackTrace();
439: }
440: }
441:
442: /**
443: * <p>Description: Inner class used to draw the sorting icon.</p>
444: */
445: class Icon3 implements Icon {
446: String m_order;
447:
448: public Icon3(String order) {
449: m_order = order;
450: }
451:
452: public int getIconWidth() {
453: return 0;
454: }
455:
456: public int getIconHeight() {
457: return getIconWidth();
458: }
459:
460: public void setOrder(String order) {
461: m_order = order;
462: }
463:
464: public void paintIcon(Component c, Graphics g, int x, int y) {
465: if (sortColIndex != -1
466: && ((DefaultTableCellRenderer) c).getText().equals(
467: table.getColumnName(sortColIndex)))
468: drawSort(c, g, x, y, m_order);
469: }
470: }
471:
472: /**
473: * Draw image of sort triangle.
474: * @param c the 1st parameter of the "Icon.paintIcon(...)". It should
475: * be an instance of the header renderer (STDLabel).
476: * @param g the 2nd parameter of the "Icon.paintIcon(...)".
477: * @param x the 3rd parameter of the "Icon.paintIcon(...)".
478: * @param y the 4th parameter of the "Icon.paintIcon(...)".
479: * @param iSize priority:
480: * <UL>
481: * 0 - primary sort (normal triangle)<br>
482: * </UL>
483: * @param asc True: ascending sort, false: descending sort.
484: */
485: private void drawSort(Component c, Graphics g, int x, int y,
486: String order) {
487: if (order.equals(NO_SORT_SYMBOL))
488: return;
489: int iSize = 7;
490: Border b = ((JComponent) c).getBorder();
491: int y1 = iSize + 3
492: + ((b == null) ? 1 : b.getBorderInsets(c).left);
493: x = c.getSize().width - y1;
494: y = c.getSize().height - ++y1;
495: //------------
496: y1 = order.equals(DESC_SYMBOL) ? y : y + iSize;
497: y = order.equals(DESC_SYMBOL) ? y + iSize : y;
498: //------------
499: Color clr1 = getBackground().brighter();
500: Color clr2 = getBackground().darker().darker();
501: g.setColor(clr2);
502: //------------
503: // left line
504: g.drawLine(x, y, x + iSize / 2, y1);
505: //------------
506: // horizontal line
507: g.setColor(order.equals(DESC_SYMBOL) ? clr1 : clr2);
508: x++;
509: g.drawLine(x, y, x + iSize, y);
510: //------------
511: // right line
512: g.setColor(clr1);
513: g.drawLine(x + iSize / 2, y1, x + iSize, y);
514: }
515:
516: }
|