Java tutorial
/******************************************************************************* * Copyright (C) 2011 Peter Brewer. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Peter Brewer ******************************************************************************/ package org.tellervo.desktop.io; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.List; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JToggleButton; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.tree.DefaultMutableTreeNode; import jsyntaxpane.DefaultSyntaxKit; import org.apache.commons.lang.WordUtils; import org.tellervo.desktop.gui.TridasSelectEvent; import org.tellervo.desktop.gui.TridasSelectListener; import org.tellervo.desktop.gui.widgets.TridasTreeViewPanel; import org.tellervo.desktop.tridasv2.TridasCloner; import org.tellervo.desktop.tridasv2.ui.TellervoPropertySheetTable; import org.tellervo.desktop.tridasv2.ui.TridasPropertyEditorFactory; import org.tellervo.desktop.tridasv2.ui.TridasPropertyRendererFactory; import org.tellervo.desktop.tridasv2.ui.support.TridasEntityDeriver; import org.tellervo.desktop.tridasv2.ui.support.TridasEntityProperty; import org.tellervo.desktop.ui.Alert; import org.tellervo.desktop.ui.Builder; import org.tellervo.desktop.ui.I18n; import org.tridas.interfaces.ITridas; import org.tridas.interfaces.ITridasSeries; import org.tridas.io.AbstractDendroFileReader; import org.tridas.io.exceptions.ConversionWarning; import org.tridas.io.exceptions.InvalidDendroFileException; import org.tridas.io.exceptions.InvalidDendroFileException.PointerType; import org.tridas.schema.TridasDerivedSeries; import org.tridas.schema.TridasElement; import org.tridas.schema.TridasMeasurementSeries; import org.tridas.schema.TridasObject; import org.tridas.schema.TridasRadius; import org.tridas.schema.TridasSample; import org.tridas.util.TridasObjectEx; import com.l2fprod.common.propertysheet.Property; import com.l2fprod.common.propertysheet.PropertySheet; import com.l2fprod.common.propertysheet.PropertySheetPanel; import com.lowagie.text.Font; public class ImportDialog extends JDialog implements PropertyChangeListener, TridasSelectListener { private static final long serialVersionUID = -9142222993569420620L; private final JPanel contentPanel = new JPanel(); private JPanel panelTreeTable; private JTextArea originalFilePane; private TridasFileImportPanel tridasreptree; private ConversionWarningTableModel warningsModel = new ConversionWarningTableModel(); private JSplitPane splitPaneVert; private JPanel panelWarnings; private JPanel panelOrigFile; private JTabbedPane tabbedPane; private JSplitPane horizSplitPane; /** Our property sheet panel (contains table and description) */ private PropertySheetPanel propertiesPanel; /** Our properties table */ private TellervoPropertySheetTable propertiesTable; /** Panel containing the edit/save changes/cancel buttons for the current entity */ private JPanel bottombar; /** The lock/unlock button for making changes to the currently selected entity */ private JToggleButton editEntity; /** Text associated with lock/unlock button */ private JLabel editEntityText; /** The save button when unlocked */ private JButton editEntitySave; /** The cancel button when unlocked */ private JButton editEntityCancel; /** A copy of the entity that we're currently editing */ private ITridas temporaryEditingEntity; /** Whether the current entity has been changed */ private Boolean hasChanged = false; /** The current entity */ private ITridas currentEntity; /** Class of the current entity */ private Class<? extends ITridas> currentEntityType; private JTable tblWarnings; DefaultMutableTreeNode nodeSelected; /** * Create the dialog. */ public ImportDialog(File file, AbstractDendroFileReader reader) { initGui(); setFile(file, reader); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setVisible(true); pack(); tridasreptree.addTridasSelectListener(this); } public void setFile(File file, AbstractDendroFileReader reader) { String origfile = getContents(file); originalFilePane.setText(origfile); try { reader.loadFile(file.getAbsolutePath()); } catch (IOException e) { Alert.errorLoading(file.getAbsolutePath(), e); this.dispose(); } catch (InvalidDendroFileException e) { Alert.error("Invalid File", WordUtils.wrap(e.getLocalizedMessage(), 70)); // Try and highlight the line in the input file that is to blame if poss if (e.getPointerType().equals(PointerType.LINE) && e.getPointerNumber() != null && !e.getPointerNumber().equals("0")) { try { Integer linenum = Integer.parseInt(e.getPointerNumber()); originalFilePane.addCaretListener(new LineHighlighter(Color.red, linenum)); this.tabbedPane.setSelectedIndex(2); int pos = 1; for (int i = 0; i < linenum; i++) { pos = originalFilePane.getText().indexOf("\n", pos + 1); } originalFilePane.setCaretPosition(pos); } catch (NumberFormatException ex) { } tabbedPane.setEnabledAt(0, false); this.horizSplitPane.setDividerLocation(0); this.panelTreeTable.setVisible(false); this.panelWarnings.setVisible(false); pack(); } } catch (NullPointerException e) { Alert.error("Invalid File", e.getLocalizedMessage()); } tridasreptree = new TridasFileImportPanel(reader.getProjects()[0]); setWarnings(reader.getWarnings()); panelTreeTable.add(tridasreptree, BorderLayout.CENTER); } private void setWarnings(ConversionWarning[] warnings) { warningsModel = new ConversionWarningTableModel(warnings); tblWarnings.setModel(warningsModel); tblWarnings.setColumnSelectionAllowed(false); tblWarnings.setRowSelectionAllowed(true); tblWarnings.setDefaultRenderer(String.class, new RowShadingRenderer()); //tblWarnings.getColumnModel().getColumn(2).setCellRenderer(new TextAreaRenderer()); //updateRowHeights(tblWarnings); /*tblWarnings.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tblWarnings.getColumnModel().getColumn(0).sizeWidthToFit(); tblWarnings.getColumnModel().getColumn(1).sizeWidthToFit(); tblWarnings.getColumnModel().getColumn(2).setPreferredWidth(1000);*/ tblWarnings.setRowHeight(40); // Show or hide Warnings panel as necessary if (warnings.length == 0) { splitPaneVert.setDividerLocation(0.99); } else { splitPaneVert.setDividerLocation(0.7); } } /** * Set up the properties panel */ private void initPropertiesPanel() { // Create table and panel to hold it propertiesTable = new TellervoPropertySheetTable(); propertiesPanel = new PropertySheetPanel(propertiesTable); propertiesPanel.getTable().setEnabled(false); // Set various properties of the properties panel! propertiesPanel.setRestoreToggleStates(true); propertiesPanel.setToolBarVisible(false); propertiesPanel.setDescriptionVisible(true); propertiesPanel.setMode(PropertySheet.VIEW_AS_CATEGORIES); propertiesPanel.getTable().setRowHeight(24); propertiesPanel.getTable().setRendererFactory(new TridasPropertyRendererFactory()); propertiesPanel.getTable().setEditorFactory(new TridasPropertyEditorFactory()); propertiesPanel.getTable().addPropertyChangeListener(this); // Set up button bar setupButtonBar(); } /** * Set up the button bar */ private void setupButtonBar() { bottombar = new JPanel(); bottombar.setLayout(new BoxLayout(bottombar, BoxLayout.X_AXIS)); editEntity = new JToggleButton(); editEntity.setIcon(Builder.getIcon("lock.png", Builder.ICONS, 22)); editEntity.setSelectedIcon(Builder.getIcon("unlock.png", Builder.ICONS, 22)); editEntity.setBorderPainted(false); editEntity.setContentAreaFilled(false); editEntity.setFocusable(false); editEntity.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!editEntity.isSelected() && hasChanged) { if (!warnLosingChanges()) { editEntity.setSelected(true); return; } else { editEntity.setSelected(false); hasChanged = false; } } //enableEditing(editEntity.isSelected()); } }); bottombar.add(editEntity); editEntityText = new JLabel(I18n.getText("general.initializing").toLowerCase()); editEntityText.setLabelFor(editEntity); bottombar.add(editEntityText); editEntitySave = new JButton(I18n.getText("general.saveChanges")); editEntityCancel = new JButton(I18n.getText("general.cancel")); // don't let an errant enter key fire these buttons! editEntitySave.setDefaultCapable(false); editEntityCancel.setDefaultCapable(false); editEntitySave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //doSave(); } }); editEntityCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { hasChanged = false; editEntity.setSelected(false); //enableEditing(false); } }); bottombar.add(Box.createHorizontalGlue()); bottombar.add(editEntitySave); bottombar.add(Box.createHorizontalStrut(6)); bottombar.add(editEntityCancel); bottombar.add(Box.createHorizontalStrut(6)); } /** * @return true if the user wants to lose changes, false otherwise */ private boolean warnLosingChanges() { if (!hasChanged) return true; if (this.currentEntity == null) return true; int ret = JOptionPane.showConfirmDialog(this, I18n.getText("question.confirmChangeForm"), I18n.getText("question.continue"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (ret == JOptionPane.YES_OPTION) { hasChanged = false; } return (ret == JOptionPane.YES_OPTION); } static public String getContents(File aFile) { //...checks on aFile are elided StringBuilder contents = new StringBuilder(); try { //use buffering, reading one line at a time //FileReader always assumes default encoding is OK! BufferedReader input = new BufferedReader(new FileReader(aFile)); try { String line = null; //not declared within while loop /* * readLine is a bit quirky : * it returns the content of a line MINUS the newline. * it returns null only for the END of the stream. * it returns an empty String if two newlines appear in a row. */ while ((line = input.readLine()) != null) { contents.append(line); contents.append(System.getProperty("line.separator")); } } finally { input.close(); } } catch (IOException ex) { ex.printStackTrace(); } return contents.toString(); } private void initGui() { setTitle("Import to Database"); setBounds(100, 100, 804, 734); getContentPane().setLayout(new BorderLayout()); contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); getContentPane().add(contentPanel, BorderLayout.CENTER); contentPanel.setLayout(new BorderLayout(0, 0)); { horizSplitPane = new JSplitPane(); horizSplitPane.setOneTouchExpandable(true); horizSplitPane.setBorder(null); horizSplitPane.setDividerLocation(0.4); contentPanel.add(horizSplitPane); { splitPaneVert = new JSplitPane(); splitPaneVert.setOneTouchExpandable(true); splitPaneVert.setBorder(null); splitPaneVert.setOrientation(JSplitPane.VERTICAL_SPLIT); horizSplitPane.setLeftComponent(splitPaneVert); { panelTreeTable = new JPanel(); panelTreeTable.setBorder(new TitledBorder(null, "TRiDaS Representation", TitledBorder.LEADING, TitledBorder.TOP, null, null)); splitPaneVert.setLeftComponent(panelTreeTable); panelTreeTable.setLayout(new BorderLayout(0, 0)); { JButton btnSetFromDB = new JButton("Set current entity from database"); panelTreeTable.add(btnSetFromDB, BorderLayout.SOUTH); } } { panelWarnings = new JPanel(); panelWarnings.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Warnings", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0))); splitPaneVert.setRightComponent(panelWarnings); panelWarnings.setLayout(new BorderLayout(0, 0)); { JScrollPane scrollPane = new JScrollPane(); panelWarnings.add(scrollPane, BorderLayout.CENTER); { tblWarnings = new JTable(); scrollPane.setViewportView(tblWarnings); } } } } { tabbedPane = new JTabbedPane(JTabbedPane.TOP); tabbedPane.setBorder(null); horizSplitPane.setRightComponent(tabbedPane); { JPanel panelMetadata = new JPanel(); panelMetadata.setLayout(new BorderLayout()); initPropertiesPanel(); panelMetadata.add(propertiesPanel, BorderLayout.CENTER); tabbedPane.addTab("Metadata", null, panelMetadata, null); } { JPanel panelData = new JPanel(); tabbedPane.addTab("Data", null, panelData, null); tabbedPane.setEnabledAt(1, false); } { panelOrigFile = new JPanel(); tabbedPane.addTab("Original file", null, panelOrigFile, null); panelOrigFile.setLayout(new BorderLayout(0, 0)); { DefaultSyntaxKit.initKit(); } { JScrollPane scrollPane = new JScrollPane(); panelOrigFile.add(scrollPane, BorderLayout.CENTER); originalFilePane = new JTextArea(); scrollPane.setViewportView(originalFilePane); originalFilePane.setEditable(false); originalFilePane.setFont(new java.awt.Font("Courier", 0, 12)); } } } } { JPanel buttonPane = new JPanel(); buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); getContentPane().add(buttonPane, BorderLayout.SOUTH); { JButton button = new JButton("Finish"); buttonPane.add(button); } } } @Override public void propertyChange(PropertyChangeEvent arg0) { // TODO Auto-generated method stub } @SuppressWarnings("unused") private static void updateRowHeights(JTable table) { try { for (int row = 0; row < table.getRowCount(); row++) { int rowHeight = table.getRowHeight(); for (int column = 0; column < table.getColumnCount(); column++) { Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column); rowHeight = Math.max(rowHeight, comp.getPreferredSize().height); } table.setRowHeight(row, rowHeight); } } catch (ClassCastException e) { } } @Override public void entitySelected(TridasSelectEvent event) { nodeSelected = event.getTreeNode(); try { ITridas entity = event.getEntity(); if (entity instanceof TridasObject || entity instanceof TridasObjectEx) { this.setEntity(entity, TridasObject.class); } else if (entity instanceof TridasElement) { this.setEntity(entity, TridasElement.class); } else if (entity instanceof TridasSample) { this.setEntity(entity, TridasSample.class); } else if (entity instanceof TridasRadius) { this.setEntity(entity, TridasRadius.class); } else if (entity instanceof TridasMeasurementSeries) { this.setEntity(entity, TridasMeasurementSeries.class); } else if (entity instanceof TridasDerivedSeries) { this.setEntity(entity, TridasDerivedSeries.class); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Set the current entity that we are browsing * * @param entity * @param type */ public void setEntity(ITridas entity, Class<? extends ITridas> type) { setEntity(entity, type, false); } /** * Set the current entity that we are browsing and whether the user should be * warned or not * * @param entity * @param type * @param silent */ private void setEntity(ITridas entity, Class<? extends ITridas> type, Boolean silent) { if (!silent) { if (!warnLosingChanges()) { } } hasChanged = false; currentEntityType = type; currentEntity = entity; // Swapping entities so disable editing this.enableEditing(false); // derive a property list List<TridasEntityProperty> properties = TridasEntityDeriver.buildDerivationList(type); Property[] propArray = properties.toArray(new Property[properties.size()]); // set properties and load from entity propertiesPanel.setProperties(propArray); propertiesTable.expandAllBranches(true); // Add data to table from entity if (entity != null) { propertiesPanel.readFromObject(entity); propertiesPanel.setEnabled(true); editEntity.setVisible(true); } else { propertiesPanel.setEnabled(false); editEntity.setVisible(false); } } /** * Called to enable editing * Responsible for loading the duplicate copy into the editor * * @param enable */ @SuppressWarnings("unchecked") protected void enableEditing(boolean enable) { propertiesTable.setEditable(enable); // show/hide our buttons editEntitySave.setEnabled(true); editEntityCancel.setEnabled(true); editEntitySave.setVisible(enable); editEntityCancel.setVisible(enable); if (currentEntity == null) { editEntityText.setText(null); } else { editEntityText.setFont(editEntityText.getFont().deriveFont(Font.BOLD)); editEntityText.setText(enable ? I18n.getText("metadata.currentlyEditingThis") + " " + TridasTreeViewPanel.getFriendlyClassName(currentEntityType).toLowerCase() : I18n.getText("metadata.clickLockToEdit") + " " + TridasTreeViewPanel.getFriendlyClassName(currentEntityType).toLowerCase()); } editEntity.setSelected(enable); if (enable) { if (currentEntity == null) return; if (currentEntity instanceof ITridasSeries) temporaryEditingEntity = TridasCloner.cloneSeriesRefValues((ITridasSeries) currentEntity, (Class<? extends ITridasSeries>) currentEntity.getClass()); else temporaryEditingEntity = TridasCloner.clone(currentEntity, currentEntity.getClass()); if (temporaryEditingEntity != null) propertiesPanel.readFromObject(temporaryEditingEntity); } else { temporaryEditingEntity = null; // don't display anything if we have nothingk! if (currentEntity != null) { propertiesPanel.readFromObject(currentEntity); } else { return; } } } }