/* * Copyright (C) 2012 IsmAvatar <IsmAvatar@gmail.com> * * This file is part of LibMaker. * * LibMaker 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. * * LibMaker 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 (COPYING) 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/>. */ package org.lateralgm.libmaker; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.LinkedList; import java.util.List; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JToolBar; import javax.swing.UIManager; import org.lateralgm.libmaker.backend.Action; import org.lateralgm.libmaker.backend.Action.PAction; import org.lateralgm.libmaker.backend.Argument; import org.lateralgm.libmaker.backend.Argument.PArgument; import org.lateralgm.libmaker.backend.Library; import org.lateralgm.libmaker.backend.Library.PLibrary; import org.lateralgm.libmaker.backend.PropertyMap; import org.lateralgm.libmaker.backend.PropertyMap.PropertyListener; import org.lateralgm.libmaker.backend.PropertyMap.PropertyUpdateEvent; import org.lateralgm.libmaker.components.AboutBox; import org.lateralgm.libmaker.components.GmMenu; import org.lateralgm.libmaker.components.ObservableList.ListUpdateEvent; import org.lateralgm.libmaker.components.ObservableList.ListUpdateListener; import org.lateralgm.libmaker.file.FileChooser; import org.lateralgm.libmaker.mockui.MockUI; public class LibMaker extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; protected FileChooser fc; protected MockUI ui; protected Library currentLib; protected ChangeListener cl; protected boolean modified; public LibMaker() { super(); //Title gets set when library is set setIconImage(Messages.getIconForKey("LibMaker.FRAME_ICON").getImage()); //$NON-NLS-1$ ui = new MockUI(); fc = new FileChooser(this); setJMenuBar(createMenu()); add(createTool(),BorderLayout.NORTH); add(ui,BorderLayout.CENTER); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (!saveConfirm()) return; System.exit(0); return; } }); pack(); setLocationRelativeTo(null); setMinimumSize(getSize()); setLibrary(new Library()); //Now that we have our needed size, setup with our initial library } protected JMenuBar createMenu() { JMenuBar mb = new JMenuBar(); GmMenu menu; mb.add(menu = new GmMenu(Messages.getString("Menu.FILE"),this)); //$NON-NLS-1$ menu.addItem("Menu.NEW",KeyEvent.VK_N,InputEvent.CTRL_DOWN_MASK); //$NON-NLS-1$ menu.addItem("Menu.OPEN",KeyEvent.VK_O,InputEvent.CTRL_DOWN_MASK); //$NON-NLS-1$ menu.addSeparator(); menu.addItem("Menu.SAVE",KeyEvent.VK_S,InputEvent.CTRL_DOWN_MASK); //$NON-NLS-1$ menu.addItem("Menu.SAVEAS"); //$NON-NLS-1$ menu.addSeparator(); menu.addItem("Menu.MERGE",KeyEvent.VK_M,InputEvent.CTRL_DOWN_MASK); //$NON-NLS-1$ menu.addSeparator(); menu.addItem("Menu.EXIT",KeyEvent.VK_F4,InputEvent.ALT_DOWN_MASK); //$NON-NLS-1$ mb.add(menu = new GmMenu(Messages.getString("Menu.HELP"),this)); //$NON-NLS-1$ menu.addItem("Menu.MANUAL",KeyEvent.VK_F1,0); //$NON-NLS-1$ menu.addSeparator(); menu.addItem("Menu.ABOUT"); //$NON-NLS-1$ return mb; } protected void addMenuItem(JMenu mb, String key) { JMenuItem mi = new JMenuItem(key); mb.add(mi); mi.setActionCommand(key); mi.addActionListener(this); } protected JToolBar createTool() { JToolBar tb = new JToolBar(); tb.setFloatable(false); addToolItem(tb,"Tool.NEW"); //$NON-NLS-1$ addToolItem(tb,"Tool.OPEN"); //$NON-NLS-1$ addToolItem(tb,"Tool.SAVE"); //$NON-NLS-1$ addToolItem(tb,"Tool.SAVEAS"); //$NON-NLS-1$ tb.addSeparator(); addToolItem(tb,"Tool.MANUAL"); //$NON-NLS-1$ tb.add(Box.createHorizontalGlue()); //right align after this addToolItem(tb,"Tool.PREVIEW"); //$NON-NLS-1$ return tb; } protected void addToolItem(JToolBar tb, String key) { ImageIcon icon = Messages.getIconForKey(key); String tip = Messages.getString(key); JButton b = new JButton(icon); if (icon == null) b.setText(key); b.setToolTipText(tip); b.setActionCommand(key); b.addActionListener(this); tb.add(b); } public void save(boolean as) { boolean b; if (as || currentLib.sourceFile == null) b = fc.saveNewFile(currentLib); else b = fc.save(currentLib,currentLib.sourceFile,currentLib.format); if (b) setModified(false); } public void setLibrary(Library lib) { if (cl != null) cl.dispose(); currentLib = lib; modified = false; ui.setLibrary(lib); setTitleFile(lib.sourceFile); cl = new ChangeListener(lib); } class ChangeListener implements ListUpdateListener { Library lib; List<MyPropList<?>> lists = new LinkedList<MyPropList<?>>(); public ChangeListener(Library lib) { this.lib = lib; lib.actions.addListUpdateListener(this); lists.add(new MyPropList<PLibrary>(lib.properties)); for (Action a : lib.actions) { lists.add(new MyPropList<PAction>(a.properties)); for (Argument arg : a.arguments) lists.add(new MyPropList<PArgument>(arg.properties)); } } public void dispose() { lib.actions.removeListUpdateListener(this); for (MyPropList<?> mpl : lists) mpl.dispose(); } public void fire() { setModified(true); } class MyPropList<K extends Enum<K>> implements PropertyListener<K> { protected PropertyMap<K> map; public MyPropList(PropertyMap<K> map) { this.map = map; map.addPropertyListener(this); } public void dispose() { map.removePropertyListener(this); } @Override public void propertyUpdate(PropertyUpdateEvent<K> evt) { fire(); } } @Override public void listUpdate(ListUpdateEvent evt) { fire(); } } public void setModified(boolean mod) { if (mod == modified) return; modified = mod; setModifiedTitleIndicator(mod); } public boolean saveConfirm() { if (modified) { int r = JOptionPane.showConfirmDialog(this,Messages.getString("LibMaker.SAVE_CHANGES")); //$NON-NLS-1$ if (r == JOptionPane.CANCEL_OPTION) return false; if (r == JOptionPane.YES_OPTION) save(false); } return true; } /** * Set whether to display an indicator in the title * that indicates whether the file has been modified or not. * Currently the indicator is implemented as an appended asterisk (*). * <p> * Setting the indicator to the same value twice has no effect. * <p> * Note that any method that sets the title (like setTitleFile) * will clear the indicator. This is usually convenient since * you usually only set the title when a file is created or loaded, * in which case the file will already be unmodified. * @param mod */ public void setModifiedTitleIndicator(boolean mod) { final String ind = "*"; String title = getTitle(); if (!mod ^ title.endsWith(ind)) return; setTitle(mod ? title + ind : title.substring(0,title.length() - 1)); } public void setTitleFile(File f) { String name = f == null ? Messages.getString("LibMaker.NEWLIB") : f.getName(); //$NON-NLS-1$ setTitle(Messages.format("LibMaker.TITLE",name)); //$NON-NLS-1$ } @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.endsWith(".NEW")) //$NON-NLS-1$ { if (!saveConfirm()) return; setLibrary(new Library()); return; } if (cmd.endsWith(".OPEN")) //$NON-NLS-1$ { if (!saveConfirm()) return; Library lib = fc.openNewFile(); if (lib != null) setLibrary(lib); return; } if (cmd.endsWith(".SAVE")) //$NON-NLS-1$ { save(false); return; } if (cmd.endsWith(".SAVEAS")) //$NON-NLS-1$ { save(true); return; } if (cmd.endsWith(".MERGE")) //$NON-NLS-1$ { Library lib = fc.openNewFile(); if (lib != null) currentLib.actions.addAll(lib.actions); return; } if (cmd.endsWith(".EXIT")) //$NON-NLS-1$ { if (!saveConfirm()) return; System.exit(0); return; } if (cmd.endsWith(".ABOUT")) //$NON-NLS-1$ { new AboutBox(this).setVisible(true); return; } if (cmd.endsWith(".HELP")) //$NON-NLS-1$ { //TODO: Help return; } if (cmd.endsWith(".PREVIEW")) //$NON-NLS-1$ { ui.previewSelectedAction(this); return; } } public static void main(String[] args) { //Annoyingly, Metal bolds almost all components by default. This unbolds them. UIManager.put("swing.boldMetal",Boolean.FALSE); //$NON-NLS-1$ new LibMaker().setVisible(true); } }