package gui; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.FileDialog; import java.awt.Toolkit; import javax.swing.JFrame; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.JButton; import java.awt.Component; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JList; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import database.CustomProperty; import database.DatabaseItem; import database.DatabaseModel; import database.DatabaseProperty; import database.IntegerDatabaseProperty; import database.ItemListDatabaseProperty; import database.StringListDatabaseProperty; import database.TextDatabaseProperty; import database.BooleanDatabaseProperty; import database.StringPairListDatabaseProperty; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import javax.swing.JTextField; import javax.swing.JComboBox; import javax.swing.JSplitPane; import javax.swing.ListSelectionModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionEvent; public class WindowMain { private static JFrame frame; private static DatabaseTableModel tableModel; private static JList itemList, propertyList; private static DefaultListModel itemListModel; private static JTabbedPane viewSelectPanel; private static DatabaseModel _model; private static JTextField txtItemName; private static JTextField txtPropertyName; private static JComboBox propertyTypeSelect; private static JButton btnDeleteItem; private static JButton btnDeleteProperty; private static Component propertyEditComponent; private static DatabaseItem selectedItem; private static DatabaseProperty selectedProperty; private static String[] _propertyTypes = new String[]{"Text", "Integer", "Boolean", "Item List", "String List", "String Pairs", "Custom Type"}; private static JTable databaseTable; // Our currently open file for purposes of save and save as private File _openFile; private String _emptyXml; private WindowMain _selfReference; /** * Launch the application. */ public static void main(String[] args) { try { System.setProperty("apple.laf.useScreenMenuBar", "true"); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Database Editor"); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { } EventQueue.invokeLater(new Runnable() { @SuppressWarnings("static-access") public void run() { try { WindowMain window = new WindowMain(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public WindowMain() { _selfReference = this; initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { _model = new DatabaseModel(); _emptyXml = _model.xmlDigest(); frame = new JFrame(); frame.setBounds(100, 100, 800, 600); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent winEvt) { if(onExit()) System.exit(0); } }); // Set up the program to catch OSX quit events try { OSXAdapter.setQuitHandler(this, this.getClass().getMethod("onExit", new Class[] {})); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } // The Menu Bar JMenuBar menuBar = new JMenuBar(); frame.setJMenuBar(menuBar); JMenu mnFile = new JMenu("File"); menuBar.add(mnFile); JMenuItem mntmNew = new JMenuItem("New"); mntmNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); mntmNew.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { clear(); _openFile = null; } }); mnFile.add(mntmNew); JMenuItem mntmOpen = new JMenuItem("Open"); mntmOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); mntmOpen.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Run the file dialogue later since it's blocking SwingUtilities.invokeLater(new Runnable() { public void run() { FileDialog chooser = new FileDialog(frame, "Open", FileDialog.LOAD); chooser.setVisible(true); if (chooser.getFile() != null) { clear(); File file = new File(chooser.getDirectory(), chooser.getFile()); DatabaseModel maybeModel = DatabaseModel.createModelFromXML(file); if (maybeModel != null) { setNewModel(maybeModel); _openFile = file; } else { JOptionPane.showMessageDialog(frame, "File failed to open!", "Open Error", JOptionPane.ERROR_MESSAGE); } } } }); } }); mnFile.add(mntmOpen); JMenuItem mntmSave = new JMenuItem("Save"); mntmSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); mntmSave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Invoke the save later since it's a blocking method SwingUtilities.invokeLater(new Runnable() { public void run() { save(); } }); } }); mnFile.add(mntmSave); JMenuItem mntmSaveAs = new JMenuItem("Save As"); mntmSaveAs.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Invoke the save later since it's a blocking method SwingUtilities.invokeLater(new Runnable() { public void run() { String xml = _model.xmlDigest(); saveAs(xml); } }); } }); JMenuItem mntmExit = new JMenuItem("Exit"); mntmExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); mntmExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (onExit()) System.exit(0); } }); mnFile.add(mntmExit); JMenu mnHelp = new JMenu("Help"); menuBar.add(mnHelp); JSplitPane splitPane = new JSplitPane(); splitPane.setResizeWeight(0.5); splitPane.setDividerLocation(0.5); splitPane.setAlignmentY(Component.CENTER_ALIGNMENT); splitPane.setAlignmentX(Component.CENTER_ALIGNMENT); frame.getContentPane().add(splitPane); JPanel newItemPanel = new JPanel(); splitPane.setLeftComponent(newItemPanel); newItemPanel.setLayout(new BoxLayout(newItemPanel, BoxLayout.X_AXIS)); JButton btnNewItem = new JButton("Add item with name:"); newItemPanel.add(btnNewItem); btnNewItem.setAlignmentX(Component.CENTER_ALIGNMENT); splitPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, btnNewItem.getPreferredSize().height)); txtItemName = new JTextField(); txtItemName.setMaximumSize(new Dimension(Integer.MAX_VALUE, btnNewItem.getPreferredSize().height)); newItemPanel.add(txtItemName); txtItemName.setText("itemname"); txtItemName.setColumns(10); btnNewItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { String itemName = txtItemName.getText(); DatabaseItem newItem = new DatabaseItem(itemName); if(!_model.addItemToDatabase(newItem)) JOptionPane.showMessageDialog((Component)arg0.getSource(), "Item name: " + itemName + " already exists in database!"); // Set our selected item index to the new item else itemList.setSelectedValue(newItem, true); } }); btnDeleteItem = new JButton("Delete Selected Item"); btnDeleteItem.setVisible(false); newItemPanel.add(btnDeleteItem); btnDeleteItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (selectedItem == null) return; int response = JOptionPane.showConfirmDialog(frame, "Really remove " + selectedItem.getName() + "?", "Delete?", JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { _model.removeItemFromDatabase(selectedItem); } } }); } }); JPanel newPropertyPanel = new JPanel(); splitPane.setRightComponent(newPropertyPanel); newPropertyPanel.setLayout(new BoxLayout(newPropertyPanel, BoxLayout.X_AXIS)); JButton btnNewProperty = new JButton("Add property of type:"); btnNewProperty.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { // Create a new Database property based on the selected type and name String selectedType = propertyTypeSelect.getSelectedItem().toString(); String attemptedName = txtPropertyName.getText(); DatabaseProperty attemptedProperty; if(selectedType.equals("Text")) attemptedProperty = new TextDatabaseProperty(attemptedName); else if(selectedType.equals("Boolean")) attemptedProperty = new BooleanDatabaseProperty(attemptedName); else if(selectedType.equals("Integer")) attemptedProperty = new IntegerDatabaseProperty(attemptedName); else if(selectedType.equals("Item List")) attemptedProperty = new ItemListDatabaseProperty(attemptedName); else if(selectedType.equals("String List")) attemptedProperty = new StringListDatabaseProperty(attemptedName); else if(selectedType.equals("String Pairs")) attemptedProperty = new StringPairListDatabaseProperty(attemptedName); else if(selectedType.equals("Custom Type")) { if(_model.isPropertyNameInDatabase(attemptedName)) { JOptionPane.showMessageDialog((Component)arg0.getSource(), "Property name: " + attemptedName + " already exists in database!"); return; } frame.setEnabled(false); JFrame propertyDefine = new CustomPropertyDefinitionFrame(_selfReference, attemptedName); propertyDefine.setVisible(true); return; } else return; if(!_model.addPropertyToDatabase(attemptedProperty)) JOptionPane.showMessageDialog((Component)arg0.getSource(), "Property name: " + attemptedName + " already exists in database!"); } }); newPropertyPanel.add(btnNewProperty); propertyTypeSelect = new JComboBox(); propertyTypeSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, btnNewProperty.getPreferredSize().height)); newPropertyPanel.add(propertyTypeSelect); propertyTypeSelect.setModel(new DefaultComboBoxModel(_propertyTypes)); JLabel lblWithName = new JLabel("with name:"); newPropertyPanel.add(lblWithName); txtPropertyName = new JTextField(); txtPropertyName.setMaximumSize(new Dimension(Integer.MAX_VALUE, btnNewProperty.getPreferredSize().height)); newPropertyPanel.add(txtPropertyName); txtPropertyName.setText("propertyname"); txtPropertyName.setColumns(10); btnDeleteProperty = new JButton("Remove Selected Property"); btnDeleteProperty.setVisible(false); newPropertyPanel.add(btnDeleteProperty); btnDeleteProperty.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (selectedProperty == null) return; int response = JOptionPane.showConfirmDialog(frame, "Really remove property " + selectedProperty.getName() + "?", "Delete?", JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { _model.removePropertyFromDatabase(selectedProperty); } } }); } }); viewSelectPanel = new JTabbedPane(JTabbedPane.TOP); frame.getContentPane().add(viewSelectPanel); JPanel listViewPanel = new JPanel(); viewSelectPanel.addTab("List View", null, listViewPanel, null); listViewPanel.setLayout(new BoxLayout(listViewPanel, BoxLayout.X_AXIS)); JPanel itemSelectPanel = new JPanel(); listViewPanel.add(itemSelectPanel); itemSelectPanel.setLayout(new BoxLayout(itemSelectPanel, BoxLayout.Y_AXIS)); JLabel itemSelectLabel = new JLabel("Database Items"); itemSelectLabel.setAlignmentX(Component.CENTER_ALIGNMENT); itemSelectPanel.add(itemSelectLabel); JScrollPane itemSelectScroll = new JScrollPane(); itemSelectPanel.add(itemSelectScroll); itemList = new JList(); itemList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent arg0) { selectedItem = (DatabaseItem)itemList.getSelectedValue(); if(selectedItem == null) { btnDeleteItem.setVisible(false); return; } btnDeleteItem.setVisible(true); // Change the list of displayed properties to the property names the item has propertyList.setListData(selectedItem.getPropertyNames()); } }); itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); itemListModel = new DefaultListModel(); itemList.setModel(itemListModel); itemSelectScroll.setViewportView(itemList); JPanel propertySelectPanel = new JPanel(); listViewPanel.add(propertySelectPanel); propertySelectPanel.setLayout(new BoxLayout(propertySelectPanel, BoxLayout.Y_AXIS)); JLabel propertySelectLabel = new JLabel("Properties"); propertySelectLabel.setAlignmentX(Component.CENTER_ALIGNMENT); propertySelectPanel.add(propertySelectLabel); JScrollPane propertySelectScroll = new JScrollPane(); propertySelectPanel.add(propertySelectScroll); propertyList = new JList(); propertyList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent arg0) { if(propertyEditComponent != null) { frame.getContentPane().remove(propertyEditComponent); } if(propertyList.getSelectedValue() != null && itemList.getSelectedValue() != null) { DatabaseItem selectedItem = (DatabaseItem)itemList.getSelectedValue(); String propertyName = propertyList.getSelectedValue().toString(); btnDeleteProperty.setVisible(true); selectedProperty = (DatabaseProperty)selectedItem.getPropertyValue(propertyName); if(selectedProperty == null) { selectedProperty = _model.createInstance(propertyName); selectedItem.addProperty(propertyName, selectedProperty); } selectedProperty.update(_model); propertyEditComponent = selectedProperty.getEditingUI(); frame.getContentPane().add(propertyEditComponent); } else { propertyEditComponent = null; btnDeleteProperty.setVisible(false); } frame.getContentPane().validate(); frame.getContentPane().repaint(); } }); propertySelectScroll.setViewportView(propertyList); JPanel tableViewPanel = new JPanel(); viewSelectPanel.addTab("Table View", null, tableViewPanel, null); tableViewPanel.setLayout(new BoxLayout(tableViewPanel, BoxLayout.Y_AXIS)); JScrollPane scrollPane = new JScrollPane(); tableViewPanel.add(scrollPane); databaseTable = new JTable(); databaseTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); databaseTable.setRowSelectionAllowed(false); scrollPane.setViewportView(databaseTable); tableModel = new DatabaseTableModel(_model); databaseTable.setModel(tableModel); //databaseTable.add ListSelectionListener tableListener = new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent arg0) { if(propertyEditComponent != null) { frame.getContentPane().remove(propertyEditComponent); } if(databaseTable.getSelectedColumn() != -1 && databaseTable.getSelectedRow() != -1) { selectedItem = tableModel.getSelectedItem(databaseTable.getSelectedRow()); selectedProperty = tableModel.selectProperty(databaseTable.getSelectedRow(), databaseTable.getSelectedColumn()); btnDeleteProperty.setVisible(selectedProperty != null); btnDeleteItem.setVisible(true); if(selectedProperty == null || selectedProperty.isTableElementEditable()) propertyEditComponent = null; else { propertyEditComponent = selectedProperty.getEditingUI(); frame.getContentPane().add(propertyEditComponent); } } else { btnDeleteItem.setVisible(false); btnDeleteProperty.setVisible(false); selectedItem = null; selectedProperty = null; propertyEditComponent = null; } frame.getContentPane().validate(); frame.getContentPane().repaint(); } }; databaseTable.getSelectionModel().addListSelectionListener(tableListener); databaseTable.getColumnModel().getSelectionModel().addListSelectionListener(tableListener); viewSelectPanel.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent arg0) { //System.out.println(viewSelectPanel.getSelectedIndex()); if(viewSelectPanel.getSelectedIndex() == 1) { propertyList.clearSelection(); } else if(viewSelectPanel.getSelectedIndex() == 0) { databaseTable.clearSelection(); } } }); } public static void addItemToListView(DatabaseItem item) { itemListModel.addElement(item); } public static void removeItemFromListView(DatabaseItem item) { itemListModel.removeElement(item); } public static void addItemToTableView(DatabaseItem item) { tableModel.addItem(item); } public static void removeItemFromTableView(DatabaseItem item) { tableModel.removeItem(item); } public static void removePropertyFromTableView(DatabaseProperty property) { tableModel.removeProperty(property); } public static void addPropertyToTableView(DatabaseProperty property) { tableModel.addProperty(property); } public static void updateGUI() { itemList.invalidate(); propertyList.invalidate(); DatabaseItem selectedItem = (DatabaseItem)itemList.getSelectedValue(); // Update the list of properties for the selected database item if(selectedItem != null) { propertyList.setListData(selectedItem.getPropertyNames()); } } public void returnFromCustomPropertyDef(CustomProperty property) { frame.setEnabled(true); if(property != null) _model.addPropertyToDatabase(property); } public void clear() { _model = new DatabaseModel(); itemListModel.clear(); itemList.setSelectedValue(null, true); propertyList.setModel(new DefaultListModel()); propertyList.setSelectedValue(null, true); tableModel = new DatabaseTableModel(_model); databaseTable.setModel(tableModel); } public void setNewModel(DatabaseModel model) { _model = model; tableModel = new DatabaseTableModel(_model); databaseTable.setModel(tableModel); } private boolean save() { String xml = _model.xmlDigest(); if (_openFile != null) { try { BufferedWriter writer = new BufferedWriter(new FileWriter(_openFile)); writer.write(xml); writer.close(); return true; } catch (IOException ioe) { ioe.printStackTrace(); return false; } } else return saveAs(xml); } private boolean saveAs(String xml) { FileDialog chooser = new FileDialog(frame, "Save", FileDialog.SAVE); chooser.setVisible(true); if (chooser.getFile() != null) { try { File saveFile = new File(chooser.getDirectory(), chooser.getFile()); BufferedWriter writer = new BufferedWriter(new FileWriter(saveFile)); writer.write(xml); writer.close(); _openFile = saveFile; return true; } catch (IOException ioe) { ioe.printStackTrace(); return false; } } else { return false; } } public boolean onExit() { if (!unsavedChanges()) return true; else { int response = JOptionPane.showConfirmDialog(frame, "Save Unsaved Changes?", "Save?", JOptionPane.YES_NO_CANCEL_OPTION); if ((response == JOptionPane.YES_OPTION && save()) || response == JOptionPane.NO_OPTION) return true; } return false; } private Boolean unsavedChanges() { String currentXml = _model.xmlDigest(); String oldXml; if (_openFile == null) oldXml = _emptyXml; else { try { FileInputStream stream = new FileInputStream(_openFile); FileChannel fc = stream.getChannel(); MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); /* Instead of using default, pass in a decoder. */ oldXml = Charset.defaultCharset().decode(bb).toString(); } catch (Exception e) { e.printStackTrace(); return true; } } return !currentXml.equals(oldXml); } }