Java tutorial
/* * Copyright 2005-2006 UniVis Explorer development team. * * This file is part of UniVis Explorer * (http://phobos22.inf.uni-konstanz.de/univis). * * UniVis Explorer is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * Please see COPYING for the complete licence. */ package unikn.dbis.univis.visualization.pivottable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Vector; import java.util.Set; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.border.EtchedBorder; import javax.swing.table.TableColumn; import table.model.renderer.SimpleRenderer; import unikn.dbis.univis.dnd.VDataReferenceFlavor; import unikn.dbis.univis.meta.*; import unikn.dbis.univis.sql.CubeChooser; import unikn.dbis.univis.visualization.Visualizable; //import unikn.dbis.univis.pivot.view.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * TODO: document me!!! * <p/> * The <code>VPivotTable</code> organizes the areas to drop dimensions for X-/Y-Axis * and calculation of the pivot table data for pivot table visualization. * <p/> * User: herb, raedler * Date: 28.08.2006 * Time: 17:06:14 * * @author Roman Rädle * @author Marion Herb * @version $Id$ * @since UniVis Explorer 0.2 */ public class VPivotTable extends JPanel implements Visualizable, DropTargetListener { // The logger to log info, error and other occuring messages // or exceptions. public static final transient Log LOG = LogFactory.getLog(VPivotTable.class); // SQL neu generieren und ausgefhren und Pivottabelle neu zeichnen? boolean selectionChanged = false; private VCube cube; private VMeasure measure; private VFunction function; private JScrollPane tableScrollPane; JPanel panelFirstRow; JPanel panelSecondRow; JPanel panelThirdRow; JTextArea dropAreaX; JTextArea dropAreaY; JTextArea dropAreaMeasure; VTableSorter tableSorter; JTable pivotTable; JScrollBar bar; String textInXYBox = "Drop Element(s)!"; String textInMeasureBox = "Choose Measure!"; Vector<VDimension> xAxisDimensions = new Vector<VDimension>(); Vector<VDimension> yAxisDimensions = new Vector<VDimension>(); Vector<VDimension> measureNodes = new Vector<VDimension>(); VPivotTableData uniData; public VPivotTable() { setBorder(new EtchedBorder()); setPreferredSize(new Dimension(1000, 700)); setLayout(new BorderLayout()); setBackground(Color.white); /* *** First Row *** */ JLabel jlabelMeasure = new JLabel("Measure:"); jlabelMeasure.setVisible(false); JLabel jlabelX = new JLabel("X-Axis Elements:"); JLabel forVerticalSpace = new JLabel(" "); panelFirstRow = new JPanel(new VTableLayout(3, 2, 3, 3)); dropAreaMeasure = new JTextArea(textInMeasureBox); dropAreaMeasure.setToolTipText(textInMeasureBox); dropAreaMeasure.setForeground(Color.LIGHT_GRAY); dropAreaMeasure.setEditable(false); dropAreaMeasure.setPreferredSize(new Dimension(100, 20)); dropAreaMeasure.setBorder(BorderFactory.createEtchedBorder(Color.WHITE, Color.LIGHT_GRAY)); dropAreaMeasure.setVisible(false); dropAreaX = new JTextArea(textInXYBox); dropAreaX.setToolTipText(textInXYBox); dropAreaX.setForeground(Color.LIGHT_GRAY); dropAreaX.setEditable(false); dropAreaX.setPreferredSize(new Dimension(400, 20)); dropAreaX.setBorder(BorderFactory.createEtchedBorder(Color.WHITE, Color.LIGHT_GRAY)); panelFirstRow.add(jlabelMeasure); panelFirstRow.add(jlabelX); panelFirstRow.add(dropAreaMeasure); panelFirstRow.add(dropAreaX); panelFirstRow.add(forVerticalSpace); add(panelFirstRow, BorderLayout.NORTH); /* *** Second Row *** */ JLabel jlabelY1 = new JLabel("Y-Axis"); JLabel jlabelY2 = new JLabel("Elements:"); panelSecondRow = new JPanel(new VTableLayout(1, 2, 3, 3)); dropAreaY = new JTextArea(textInXYBox); dropAreaY.setToolTipText(textInXYBox); dropAreaY.setForeground(Color.LIGHT_GRAY); dropAreaY.setEditable(false); dropAreaY.setLineWrap(true); dropAreaY.setWrapStyleWord(true); dropAreaY.setPreferredSize(new Dimension(100, 400)); dropAreaY.setBorder(BorderFactory.createEtchedBorder(Color.WHITE, Color.LIGHT_GRAY)); JPanel panelY = new JPanel(new VTableLayout(3, 1, 1, 1)); panelY.add(jlabelY1); panelY.add(jlabelY2); panelY.add(dropAreaY); panelSecondRow.add(panelY); add(panelSecondRow, BorderLayout.WEST); new DropTarget(dropAreaX, DnDConstants.ACTION_COPY_OR_MOVE, this); new DropTarget(dropAreaY, DnDConstants.ACTION_COPY_OR_MOVE, this); } /** * Called when the drag operation has terminated with a drop on * the operable part of the drop site for the <code>DropTarget</code> * registered with this listener. * <p/> * This method is responsible for undertaking * the transfer of the data associated with the * gesture. The <code>DropTargetDropEvent</code> * provides a means to obtain a <code>Transferable</code> * object that represents the data object(s) to * be transfered.<P> * From this method, the <code>DropTargetListener</code> * shall accept or reject the drop via the * acceptDrop(int dropAction) or rejectDrop() methods of the * <code>DropTargetDropEvent</code> parameter. * <p/> * Subsequent to acceptDrop(), but not before, * <code>DropTargetDropEvent</code>'s getTransferable() * method may be invoked, and data transfer may be * performed via the returned <code>Transferable</code>'s * getTransferData() method. * <p/> * At the completion of a drop, an implementation * of this method is required to signal the success/failure * of the drop by passing an appropriate * <code>boolean</code> to the <code>DropTargetDropEvent</code>'s * dropComplete(boolean success) method. * <p/> * Note: The data transfer should be completed before the call to the * <code>DropTargetDropEvent</code>'s dropComplete(boolean success) method. * After that, a call to the getTransferData() method of the * <code>Transferable</code> returned by * <code>DropTargetDropEvent.getTransferable()</code> is guaranteed to * succeed only if the data transfer is local; that is, only if * <code>DropTargetDropEvent.isLocalTransfer()</code> returns * <code>true</code>. Otherwise, the behavior of the call is * implementation-dependent. * <p/> * * @param dtde the <code>DropTargetDropEvent</code> */ public void drop(DropTargetDropEvent dtde) { Object o = null; try { if (dtde.getTransferable().isDataFlavorSupported(VDataReferenceFlavor.COMBINATION_FLAVOR)) { o = dtde.getTransferable().getTransferData(VDataReferenceFlavor.COMBINATION_FLAVOR); } if (o == null) { dtde.rejectDrop(); dtde.dropComplete(false); } } catch (UnsupportedFlavorException ufe) { dtde.rejectDrop(); dtde.dropComplete(false); /*if (LOG.isErrorEnabled()) { LOG.error(ufe.getMessage(), ufe); } */ } catch (IOException ioe) { dtde.rejectDrop(); dtde.dropComplete(false); /*if (LOG.isErrorEnabled()) { LOG.error(ioe.getMessage(), ioe); } */ } if (o instanceof VCombination) { VCombination combination = (VCombination) o; VDimension dimension = combination.getDimension(); if (cube == null) { Set<VCube> supportedCubes = dimension.getSupportedCubes(); if (supportedCubes.size() > 1) { cube = CubeChooser.showCubeChooser(VPivotTable.this, supportedCubes); } else { cube = supportedCubes.iterator().next(); } // Check whether a cube exists or a cube has been selected on the // cube chooser. The chooser maybe interrupted with window close // and then return null. if (cube == null) { return; } } if (measure == null) { measure = combination.getMeasure(); } if (function == null) { function = combination.getFunction(); } addDimension(dimension, dtde); setAncestorsDropped(dimension, true); dtde.dropComplete(true); } } private void setAncestorsDropped(VDimension dimension, boolean visibility) { dimension.getSelections().clear(); dimension.setDropped(visibility); VDataReference dataReference = dimension.getParent(); if (dataReference instanceof VDimension) { setAncestorsDropped((VDimension) dataReference, visibility); } } /** * Called while a drag operation is ongoing, when the mouse pointer enters * the operable part of the drop site for the <code>DropTarget</code> * registered with this listener. * * @param dtde the <code>DropTargetDragEvent</code> */ public void dragEnter(DropTargetDragEvent dtde) { // empty } /** * Called when a drag operation is ongoing, while the mouse pointer is still * over the operable part of the drop site for the <code>DropTarget</code> * registered with this listener. * * @param dtde the <code>DropTargetDragEvent</code> */ public void dragOver(DropTargetDragEvent dtde) { // empty } /** * Called if the user has modified * the current drop gesture. * <p/> * * @param dtde the <code>DropTargetDragEvent</code> */ public void dropActionChanged(DropTargetDragEvent dtde) { // empty } /** * Called while a drag operation is ongoing, when the mouse pointer has * exited the operable part of the drop site for the * <code>DropTarget</code> registered with this listener. * * @param dte the <code>DropTargetEvent</code> */ public void dragExit(DropTargetEvent dte) { // empty } public void addDimension(VDimension dimension, DropTargetDropEvent dtde) { if (dtde.getSource() == dropAreaX.getDropTarget()) { if (xAxisDimensions.size() < 1) { // noch kein X-Achsen-Element spezifiziert if (LOG.isDebugEnabled()) { LOG.debug("GUI: dropped as column value [" + dimension + "] Root: " + dimension.getBlueprint()); } xAxisDimensions.add(dimension); // Shows the dropped dimensions in x drop area box. dropAreaX.setForeground(Color.BLACK); StringBuilder sb = new StringBuilder(); for (VDimension d : xAxisDimensions) { sb.append(d).append("\n"); } dropAreaX.setText(sb.toString()); selectionChanged = true; } else { // es wurde schon X-Achsen-Element festgelegt --> momentan nur 1 ausgewertet if (LOG.isErrorEnabled()) { LOG.error("Currently only one Element for X-Axis allowed."); } selectionChanged = false; } } // end of dropAreaX (DropTarget) else if (dtde.getSource() == dropAreaY.getDropTarget()) { if (!yAxisDimensions.contains(dimension)) { // nur wenn noch nicht enthalten if (LOG.isDebugEnabled()) { LOG.debug("GUI: dropped as row value [" + dimension + "] Root: " + dimension.getBlueprint()); } yAxisDimensions.add(dimension); // Shows the dropped dimensions in y drop area box. dropAreaY.setForeground(Color.BLACK); StringBuilder sb = new StringBuilder(); for (VDimension d : yAxisDimensions) { sb.append(d).append("\n"); } dropAreaY.setText(sb.toString()); selectionChanged = true; } else { selectionChanged = false; } } // end of dropAreaY (DropTarget) if (selectionChanged && (xAxisDimensions.size() > 0 || yAxisDimensions.size() > 0)) { createPivotTable(false); } } /* * boolean flag legt fest welche Ansicht gezeigt wird * Entweder Pivottabelle oder Tabelle ohne Totalling */ private void createPivotTable(boolean dataOnly) { // Removes the scroll pane that contains the pivottable. if (tableScrollPane != null) { remove(tableScrollPane); } // JTable anlegen mit Daten sowie Ueberschriften uniData = new VPivotTableData(cube, measure, function); Vector vectorData = uniData.getPivottableData(xAxisDimensions, yAxisDimensions); Vector vectorHeader = uniData.getPivottableHeader(xAxisDimensions, yAxisDimensions); // Sind denn ueberhaupt Daten zurueckgekommen? boolean dataGiven = ((vectorData != null) && (vectorData.size() > 0)); boolean headerDataGiven = ((vectorHeader != null && vectorHeader.size() > 0)); if (!dataGiven) { System.out.println("keine Daten!"); } if (!headerDataGiven) { System.out.println("keine Ueberschriften!"); } if (dataGiven & headerDataGiven) { VPivotTableModel modelOrigin = new VPivotTableModel(vectorData, vectorHeader); if (dataOnly) { tableSorter = new VTableSorter(modelOrigin); pivotTable = new JTable(tableSorter); tableSorter.setTableHeader(pivotTable.getTableHeader()); } else { VEnvelopeTableModel modelEnv = new VEnvelopeTableModel(modelOrigin); pivotTable = new JTable(modelEnv); modelEnv.setTableHeader(pivotTable.getTableHeader()); } SimpleRenderer renderer = new VNumberRenderer(false); pivotTable.setDefaultRenderer(String.class, renderer); // reine Number-Klasse hat Doubles nicht gefaerbt! // pivotTable.setDefaultRenderer(Number.class, renderer); pivotTable.setDefaultRenderer(Integer.class, renderer); pivotTable.setDefaultRenderer(Long.class, renderer); pivotTable.setDefaultRenderer(Double.class, renderer); // spezieller CellRenderer fr letzte Total-Spalte TableColumn col = pivotTable.getColumnModel().getColumn(vectorHeader.size() - 1); col.setCellRenderer(new VTotalCellRenderer()); /* *** Second Row --> Content Area *** */ pivotTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); //Set up tool tips for column headers. // pivotTable.getTableHeader().setToolTipText( // "Click to specify sorting; Control-Click to specify secondary sorting"); /* *** Second Row --> Content Area *** */ pivotTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tableScrollPane = new JScrollPane(pivotTable); tableScrollPane.setVerticalScrollBar(new JScrollBar()); add(tableScrollPane, BorderLayout.CENTER); validate(); repaint(); } } ActionListener al_createTable = new ActionListener() { public void actionPerformed(ActionEvent e) { boolean dataOnly = false; createPivotTable(dataOnly); } }; /* deletes Textfields and most of all JTable */ ActionListener al_reset = new ActionListener() { public void actionPerformed(ActionEvent e) { } }; ActionListener al_dataViewTable = new ActionListener() { public void actionPerformed(ActionEvent e) { boolean dataOnly = true; createPivotTable(dataOnly); } }; public void clear() { if (!xAxisDimensions.isEmpty()) { for (VDimension dimension : xAxisDimensions) { setAncestorsDropped(dimension, false); } } if (!yAxisDimensions.isEmpty()) { for (VDimension dimension : yAxisDimensions) { setAncestorsDropped(dimension, false); } } xAxisDimensions.clear(); yAxisDimensions.clear(); measureNodes.clear(); dropAreaX.setForeground(Color.LIGHT_GRAY); dropAreaX.setToolTipText(textInXYBox); dropAreaX.setText(textInXYBox); dropAreaY.setForeground(Color.LIGHT_GRAY); dropAreaY.setToolTipText(textInXYBox); dropAreaY.setText(textInXYBox); dropAreaMeasure.setForeground(Color.LIGHT_GRAY); dropAreaMeasure.setToolTipText(textInMeasureBox); dropAreaMeasure.setText(textInMeasureBox); if (tableScrollPane != null) { remove(tableScrollPane); } validate(); repaint(); } public void undo() { throw new UnsupportedOperationException( "The undo functionality isn't supported by " + getClass().getName()); } public void redo() { throw new UnsupportedOperationException( "The redo functionality isn't supported by " + getClass().getName()); } public void zoomIn() { throw new UnsupportedOperationException( "The zoom into visualization isn't supported by " + getClass().getName()); } public void zoomOut() { throw new UnsupportedOperationException( "The zoom out of visualization isn't supported by " + getClass().getName()); } public void rotateRight() { throw new UnsupportedOperationException( "The clockwise rotation of the visualization isn't supported by " + getClass().getName()); } public void rotateLeft() { throw new UnsupportedOperationException( "The anticlockwise rotation of the visualization isn't supported by " + getClass().getName()); } public void setMoveable(boolean movable) { throw new UnsupportedOperationException( "The moveing of the visualization isn't supported by " + getClass().getName()); } public boolean isMoveable() { throw new UnsupportedOperationException( "The visualization isn't moveable at this time. See " + getClass().getName()); } }