/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.tuwien.ifs.somtoolbox.apps.viewer.controls; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Vector; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.RowFilter; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import at.tuwien.ifs.commons.gui.controls.swing.table.ClassColorTableModel; import at.tuwien.ifs.somtoolbox.SOMToolboxException; import at.tuwien.ifs.somtoolbox.apps.viewer.CommonSOMViewerStateData; import at.tuwien.ifs.somtoolbox.apps.viewer.SOMPane; import at.tuwien.ifs.somtoolbox.apps.viewer.fileutils.ExportUtils; import at.tuwien.ifs.somtoolbox.util.FileUtils; import at.tuwien.ifs.somtoolbox.util.GridBagConstraintsIFS; /** * Displays the class legend, i.e. the names of the different classes and the colours attached to them. Class colours * can be changed; the assignment can also be save and loaded to/from a file. * * @author Michael Dittenbach * @author Rudolf Mayer * @author Thomas Lidy * @version $Id: ClassLegendPane.java 3939 2010-11-17 16:06:14Z frank $ */ public class ClassLegendPane extends AbstractViewerControl { private static final long serialVersionUID = 1L; // private static final String[] columnNames = new String[] { "Class Name", "Color" }; // private ColourLegendTable table = null; private JTable table = null; private ClassColorTableModel classColorTM = null; private JLabel noClassesLoaded = null; private SOMPane mapPane = null; private JFileChooser fc; private JTextField txtFilter = null; public ClassLegendPane(SOMPane mapPane, String title, CommonSOMViewerStateData state) { super(title, state, new GridBagLayout()); this.mapPane = mapPane; if (mapPane.getClassLegendNames() != null) { // this.colors = state.inputDataObjects.getClassInfo().getClassColors(); initClassTable(); setVisible(true); } else { initNoClassInfo(); setVisible(false); } } public void initNoClassInfo() { if (table != null) { remove(table); } if (noClassesLoaded != null) { remove(noClassesLoaded); } else { noClassesLoaded = new JLabel("No class information file was loaded!"); } add(noClassesLoaded); repaint(); } public void initClassTable() { GridBagConstraintsIFS b = new GridBagConstraintsIFS(GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH).setWeights( 1, 1); if (table != null) { remove(table); } if (noClassesLoaded != null) { remove(noClassesLoaded); } classColorTM = new ClassColorTableModel(mapPane.getClassLegendNames(), mapPane.getClassLegendColors()); table = ClassColorTableModel.createColorLegendTable(classColorTM); table.setFillsViewportHeight(true); table.setPreferredScrollableViewportSize(new Dimension(state.controlElementsWidth, 120)); JPanel filterPanel = new JPanel(); filterPanel.setLayout(new GridBagLayout()); JLabel lblFilter = new JLabel("Filter:"); JButton btnClearFilter = new JButton("x"); btnClearFilter.setMargin(new Insets(0, 0, 0, 0)); txtFilter = new JTextField(); final TableRowSorter<ClassColorTableModel> sorter = new TableRowSorter<ClassColorTableModel>(classColorTM); table.setRowSorter(sorter); txtFilter.getDocument().addDocumentListener(new DocumentListener() { private void actionPerformed(DocumentEvent e) { RowFilter<ClassColorTableModel, Integer> rf = null; try { final Matcher matcher = Pattern.compile(txtFilter.getText(), Pattern.CASE_INSENSITIVE).matcher(""); rf = new RowFilter<ClassColorTableModel, Integer>() { @Override public boolean include( javax.swing.RowFilter.Entry<? extends ClassColorTableModel, ? extends Integer> entry) { matcher.reset(entry.getModel().getClassName(entry.getIdentifier())); return matcher.find(); } }; } catch (java.util.regex.PatternSyntaxException ex) { return; } sorter.setRowFilter(rf); } @Override public void removeUpdate(DocumentEvent e) { actionPerformed(e); } @Override public void insertUpdate(DocumentEvent e) { actionPerformed(e); } @Override public void changedUpdate(DocumentEvent e) { } }); lblFilter.setLabelFor(txtFilter); btnClearFilter.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { txtFilter.setText(""); } }); final GridBagConstraintsIFS c = new GridBagConstraintsIFS(GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH); filterPanel.add(lblFilter, c); filterPanel.add(txtFilter, c.nextCol().setWeightX(1.0)); filterPanel.add(btnClearFilter, c.nextCol().resetWeights()); if (classColorTM.getRowCount() > 9) { add(filterPanel, b.nextRow().setGridWidth(3)); } // Jakob: to propagate color-changes table.getModel().addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { if (e.getColumn() == 1) { TableModel tm = table.getModel(); for (int i = 0; i < tm.getRowCount(); i++) { if (i == TableModelEvent.HEADER_ROW) { continue; } Color c = (Color) tm.getValueAt(i, 1); state.inputDataObjects.getClassInfo().setClassColor(i, c); // state.mapPNode.setClassColor(i, c); state.mapPNode.setClassColors(((ClassColorTableModel) tm).getColors()); } } else if (e.getColumn() == 2 || e.getColumn() == -1) { mapPane.updateClassSelection(classColorTM.getSelectedClassIndices()); } } }); JScrollPane sp = new JScrollPane(table); add(sp, b.nextRow().setGridWidth(3)); final JCheckBox chkShowOnlySelectedPieSegments = new JCheckBox("Show only selected classes"); chkShowOnlySelectedPieSegments.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mapPane.setShowOnlySelectedClasses(chkShowOnlySelectedPieSegments.isSelected()); } }); add(chkShowOnlySelectedPieSegments, b.nextRow().setAnchor(GridBagConstraints.EAST)); // init load/save buttons JButton btLoadColors = new JButton("Load Colours"); btLoadColors.setMargin(new Insets(2, 2, 1, 2)); btLoadColors.setFont(smallFont); btLoadColors.addActionListener(new ActionListener() { // listener for loading @Override public void actionPerformed(ActionEvent e) { initFileChooser(); fc.showOpenDialog(ClassLegendPane.this); File file = fc.getSelectedFile(); if (file == null) { return; } if (state.inputDataObjects.getClassInfo().loadClassColours(file)) { // then update visualization updateClassColours(); mapPane.repaint(); } } }); add(btLoadColors, b.nextRow().setGridWidth(1).resetWeights()); JButton btSaveColors = new JButton("Save Colours"); btSaveColors.setFont(smallFont); btSaveColors.setMargin(new Insets(2, 2, 1, 2)); btSaveColors.addActionListener(new ActionListener() { // listener for saving @Override public void actionPerformed(ActionEvent e) { if (classColorTM.getColors() != null) { initFileChooser(); fc.showSaveDialog(ClassLegendPane.this); File file = fc.getSelectedFile(); if (file == null) { return; } Logger.getLogger("at.tuwien.ifs.somtoolbox").info("Saving colors to file: " + file.toString()); try { FileWriter fw = new FileWriter(file); final Color[] colors = classColorTM.getColors(); for (Color color : colors) { fw.write(color.getRed() + " " + color.getGreen() + " " + color.getBlue() + "\n"); } fw.close(); } catch (IOException ex) { Logger.getLogger("at.tuwien.ifs.somtoolbox").warning( "Could not write colors to file! " + ex.getMessage()); ex.printStackTrace(); } } } }); add(btSaveColors, b.nextCol()); JButton btExportlegend = new JButton("Export Legend"); btExportlegend.setFont(smallFont); btExportlegend.setMargin(new Insets(2, 2, 1, 2)); btExportlegend.addActionListener(new ActionListener() { // listener for exporting the class legend to an image file @Override public void actionPerformed(ActionEvent e) { File file = ExportUtils.getFilePath(ClassLegendPane.this, state.getFileChooser(), "Export class legend to"); if (file != null) { try { FileUtils.saveImageToFile(file.getAbsolutePath(), ClassColorTableModel.asBufferedImage(classColorTM, true)); } catch (SOMToolboxException e1) { Logger.getLogger("at.tuwien.ifs.somtoolbox").severe( "Could not write class legend to file '" + file.getAbsolutePath() + "': " + e1.getMessage()); } } } }); add(btExportlegend, b.nextCol()); } private void initFileChooser() { if (fc == null) { fc = new JFileChooser(state.fileChooser.getCurrentDirectory()); } } public void updateClassColours() { for (int i = 0; i < table.getRowCount(); i++) { table.setValueAt(state.inputDataObjects.getClassInfo().getClassColors()[i], i, 1); } } private class ClassSelectionHandler implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { ListSelectionModel lsm = (ListSelectionModel) e.getSource(); // System.out.println("value changed"); Vector<Integer> selIndices = new Vector<Integer>(); if (e.getValueIsAdjusting() == false) { if (lsm.isSelectionEmpty()) { // no selection mapPane.updateClassSelection(null); } else { // Find out which indexes are selected. int minIndex = lsm.getMinSelectionIndex(); int maxIndex = lsm.getMaxSelectionIndex(); for (int i = minIndex; i <= maxIndex; i++) { if (lsm.isSelectedIndex(i)) { selIndices.addElement(new Integer(i)); } } int[] selectedIndices = new int[selIndices.size()]; for (int i = 0; i < selectedIndices.length; i++) { selectedIndices[i] = selIndices.elementAt(i).intValue(); } mapPane.updateClassSelection(selectedIndices); } } } } @Override public void setEnabled(boolean enabled) { table.setEnabled(enabled); } public Color[] getColors() { return classColorTM.getColors(); } /* (non-Javadoc) * @see at.tuwien.ifs.somtoolbox.apps.viewer.controls.AbstractViewerControl#isFullFunctional() */ @Override public boolean isFullFunctional() { return mapPane.getClassLegendNames() != null; } }