/* * Copyright (C) 2007 TGMG <thegamemakerguru@gmail.com> * Copyright (C) 2007, 2011 IsmAvatar <IsmAvatar@gmail.com> * Copyright (C) 2007, 2008 Clam <clamisgood@gmail.com> * Copyright (C) 2007 Quadduc <quadduc@gmail.com> * * This file is part of LateralGM. * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.subframes; /* * Stolen from Font Family listener. Not sure what m_monitor was... * String m_fontName = m_cbFonts.getSelectedItem().toString(); * MutableAttributeSet attr = new SimpleAttributeSet(); * StyleConstants.setFontFamily(attr,m_fontName); * // setAttributeSet(attr); * // m_monitor.grabFocus(); * * TODO: Add font color functionality */ import static javax.swing.GroupLayout.DEFAULT_SIZE; import static javax.swing.GroupLayout.PREFERRED_SIZE; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.beans.ExceptionListener; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComboBox; import javax.swing.JEditorPane; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.SpinnerNumberModel; import javax.swing.GroupLayout.Alignment; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import javax.swing.text.rtf.RTFEditorKit; import org.lateralgm.components.CustomFileChooser; import org.lateralgm.components.NumberField; import org.lateralgm.components.impl.CustomFileFilter; import org.lateralgm.components.impl.DocumentUndoManager; import org.lateralgm.components.impl.ResNode; import org.lateralgm.components.impl.TextAreaFocusTraversalPolicy; import org.lateralgm.components.mdi.RevertableMDIFrame; import org.lateralgm.main.LGM; import org.lateralgm.messages.Messages; import org.lateralgm.resources.GameInformation; import org.lateralgm.resources.Resource; import org.lateralgm.resources.GameInformation.PGameInformation; import org.lateralgm.ui.swing.propertylink.PropertyLinkFactory; public class GameInformationFrame extends RevertableMDIFrame implements ActionListener, ExceptionListener { private static final long serialVersionUID = 1L; protected GameInformation res, resOriginal; protected final PropertyLinkFactory<PGameInformation> plf; protected JTabbedPane tabs; protected JEditorPane editor; private RTFEditorKit rtf = new RTFEditorKit(); protected JMenuBar menubar; protected JToolBar toolbar; protected JComboBox cbFonts; protected JSpinner sSizes; protected JToggleButton tbBold; protected JToggleButton tbItalic; protected JToggleButton tbUnderline; protected DocumentUndoManager undoManager = new DocumentUndoManager(); private CustomFileChooser fc; // These prevent the Formatting Bar things from firing when the caret moves // because that would cause the selection to conform the text to the caret format protected boolean fFamilyChange = false; protected boolean fSizeChange = false; protected boolean documentChanged = false; private JMenuBar makeMenuBar() { JMenuBar menuBar = new JMenuBar(); //File JMenu menu = new JMenu(Messages.getString("GameInformationFrame.MENU_FILE")); //$NON-NLS-1$ menuBar.add(menu); menu.addActionListener(this); JMenuItem item = addItem("GameInformationFrame.LOAD"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); item = addItem("GameInformationFrame.FILESAVE"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); menu.addSeparator(); item = addItem("GameInformationFrame.CLOSESAVE"); //$NON-NLS-1$ menu.add(item); //Edit menu = new JMenu(Messages.getString("GameInformationFrame.MENU_EDIT")); //$NON-NLS-1$ menuBar.add(menu); item = new JMenuItem(undoManager.getUndoAction()); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); item = new JMenuItem(undoManager.getRedoAction()); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); menu.addSeparator(); item = addItem("GameInformationFrame.CUT"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); item = addItem("GameInformationFrame.COPY"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); item = addItem("GameInformationFrame.PASTE"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); menu.addSeparator(); item = addItem("GameInformationFrame.SELECTALL"); //$NON-NLS-1$ item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,KeyEvent.CTRL_DOWN_MASK)); menu.add(item); return menuBar; } protected JButton save; private JToolBar makeToolBar() { JToolBar tool = new JToolBar(); tool.setFloatable(false); // Setup the buttons save = new JButton(LGM.getIconForKey("GameInformationFrame.CLOSESAVE")); //$NON-NLS-1$ save.setRequestFocusEnabled(false); save.setActionCommand("GameInformationFrame.CLOSESAVE"); //$NON-NLS-1$ save.addActionListener(this); tool.add(save); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String[] fontNames = ge.getAvailableFontFamilyNames(); tool.addSeparator(); cbFonts = new JComboBox(fontNames); cbFonts.setRequestFocusEnabled(false); cbFonts.setMaximumSize(cbFonts.getPreferredSize()); cbFonts.setEditable(true); ActionListener lst = new ActionListener() { public void actionPerformed(ActionEvent e) { if (fFamilyChange) { fFamilyChange = false; return; } editor.grabFocus(); setSelectionAttribute(StyleConstants.Family,cbFonts.getSelectedItem().toString()); } }; cbFonts.addActionListener(lst); tool.add(cbFonts); tool.addSeparator(); sSizes = new JSpinner(new SpinnerNumberModel(12,1,100,1)); sSizes.setRequestFocusEnabled(false); sSizes.setMaximumSize(sSizes.getPreferredSize()); sSizes.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { if (fSizeChange) { fSizeChange = false; return; } setSelectionAttribute(StyleConstants.Size,sSizes.getValue()); editor.grabFocus(); } }); tool.add(sSizes); tool.addSeparator(); tbBold = new JToggleButton(LGM.getIconForKey("GameInformationFrame.BOLD")); //$NON-NLS-1$ tbBold.setRequestFocusEnabled(false); lst = new ActionListener() { public void actionPerformed(ActionEvent arg0) { setSelectionAttribute(StyleConstants.Bold,tbBold.isSelected()); } }; tbBold.addActionListener(lst); tool.add(tbBold); tbItalic = new JToggleButton(LGM.getIconForKey("GameInformationFrame.ITALIC")); //$NON-NLS-1$ tbItalic.setRequestFocusEnabled(false); lst = new ActionListener() { public void actionPerformed(ActionEvent arg0) { setSelectionAttribute(StyleConstants.Italic,tbItalic.isSelected()); } }; tbItalic.addActionListener(lst); tool.add(tbItalic); tbUnderline = new JToggleButton(LGM.getIconForKey("GameInformationFrame.UNDERLINED")); //$NON-NLS-1$ tbUnderline.setRequestFocusEnabled(false); lst = new ActionListener() { public void actionPerformed(ActionEvent arg0) { setSelectionAttribute(StyleConstants.Underline,tbUnderline.isSelected()); } }; tbUnderline.addActionListener(lst); tool.add(tbUnderline); tool.addSeparator(); JButton but = new JButton(LGM.getIconForKey("GameInformationFrame.COLOR")); //$NON-NLS-1$ but.setRequestFocusEnabled(false); but.setActionCommand("GameInformationFrame.COLOR"); //$NON-NLS-1$ but.addActionListener(this); tool.add(but); return tool; } public JTextField sTitle; public NumberField sX; public NumberField sY; public NumberField sWidth; public NumberField sHeight; public JCheckBox sShowBorder; public JCheckBox sAllowResize; public JCheckBox sAlwaysOnTop; public JCheckBox sPauseGame; public JCheckBox sEmbed; private JPanel makeSettings() { JPanel p = new JPanel(); GroupLayout gl = new GroupLayout(p); p.setLayout(gl); gl.setAutoCreateGaps(true); gl.setAutoCreateContainerGaps(true); JLabel lTitle = new JLabel(Messages.getString("GameInformationFrame.WINDOW_TITLE")); //$NON-NLS-1$ sTitle = new JTextField(); plf.make(sTitle.getDocument(),PGameInformation.FORM_CAPTION); JPanel position = new JPanel(); position.setBorder(BorderFactory.createTitledBorder( /**/Messages.getString("GameInformationFrame.POSITION"))); //$NON-NLS-1$ GroupLayout pl = new GroupLayout(position); position.setLayout(pl); pl.setAutoCreateGaps(true); pl.setAutoCreateContainerGaps(true); JLabel lX = new JLabel(Messages.getString("GameInformationFrame.X")); //$NON-NLS-1$ JLabel lY = new JLabel(Messages.getString("GameInformationFrame.Y")); //$NON-NLS-1$ JLabel lWidth = new JLabel(Messages.getString("GameInformationFrame.WIDTH")); //$NON-NLS-1$ JLabel lHeight = new JLabel(Messages.getString("GameInformationFrame.HEIGHT")); //$NON-NLS-1$ sX = new NumberField(0); sY = new NumberField(0); sWidth = new NumberField(0); sHeight = new NumberField(0); plf.make(sX,PGameInformation.LEFT); plf.make(sY,PGameInformation.TOP); plf.make(sWidth,PGameInformation.WIDTH); plf.make(sHeight,PGameInformation.HEIGHT); sShowBorder = new JCheckBox(Messages.getString("GameInformationFrame.SHOW_BORDER")); //$NON-NLS-1$ sAllowResize = new JCheckBox(Messages.getString("GameInformationFrame.RESIZABLE")); //$NON-NLS-1$ sAlwaysOnTop = new JCheckBox(Messages.getString("GameInformationFrame.ALWAYS_ON_TOP")); //$NON-NLS-1$ sPauseGame = new JCheckBox(Messages.getString("GameInformationFrame.PAUSE")); //$NON-NLS-1$ sEmbed = new JCheckBox(Messages.getString("GameInformationFrame.EMBED")); //$NON-NLS-1$ plf.make(sShowBorder,PGameInformation.SHOW_BORDER); plf.make(sAllowResize,PGameInformation.ALLOW_RESIZE); plf.make(sAlwaysOnTop,PGameInformation.STAY_ON_TOP); plf.make(sPauseGame,PGameInformation.PAUSE_GAME); plf.make(sEmbed,PGameInformation.MIMIC_GAME_WINDOW); pl.setHorizontalGroup(pl.createSequentialGroup() /**/.addGroup(pl.createParallelGroup(Alignment.TRAILING) /* */.addComponent(lX) /* */.addComponent(lWidth)) /**/.addGroup(pl.createParallelGroup() /* */.addComponent(sX) /* */.addComponent(sWidth)) /**/.addGroup(pl.createParallelGroup(Alignment.TRAILING) /* */.addComponent(lY) /* */.addComponent(lHeight)) /**/.addGroup(pl.createParallelGroup() /* */.addComponent(sY) /* */.addComponent(sHeight))); pl.setVerticalGroup(pl.createSequentialGroup() /* */.addGroup(pl.createParallelGroup() /* */.addComponent(lX) /* */.addComponent(sX,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE) /* */.addComponent(lY) /* */.addComponent(sY,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE)) /* */.addGroup(pl.createParallelGroup() /* */.addComponent(lWidth) /* */.addComponent(sWidth,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE) /* */.addComponent(lHeight) /* */.addComponent(sHeight,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE))); gl.setHorizontalGroup(gl.createParallelGroup() /**/.addGroup(gl.createSequentialGroup() /* */.addComponent(lTitle) /* */.addComponent(sTitle)) /**/.addComponent(position) /**/.addComponent(sShowBorder) /**/.addComponent(sAllowResize) /**/.addComponent(sAlwaysOnTop) /**/.addComponent(sPauseGame) /**/.addComponent(sEmbed)); gl.setVerticalGroup(gl.createSequentialGroup() /**/.addGroup(gl.createParallelGroup() /* */.addComponent(lTitle) /* */.addComponent(sTitle,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE)) /**/.addComponent(position) /**/.addComponent(sShowBorder) /**/.addComponent(sAllowResize) /**/.addComponent(sAlwaysOnTop) /**/.addComponent(sPauseGame) /**/.addComponent(sEmbed)); return p; } public GameInformationFrame(GameInformation res) { super(Messages.getString("GameInformationFrame.TITLE"),true); //$NON-NLS-1$ plf = new PropertyLinkFactory<PGameInformation>(res.properties,this); this.res = res; resOriginal = res.clone(); setFrameIcon(LGM.getIconForKey("GameInformationFrame.INFO")); //$NON-NLS-1$ setDefaultCloseOperation(HIDE_ON_CLOSE); setSize(600,400); menubar = makeMenuBar(); setJMenuBar(menubar); toolbar = makeToolBar(); add(toolbar,BorderLayout.NORTH); tabs = new JTabbedPane(); add(tabs,BorderLayout.CENTER); tabs.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { boolean enabled = tabs.getSelectedIndex() == 0; if (enabled) editor.requestFocusInWindow(); JMenuBar mb = getJMenuBar(); for (int i = 0; i < mb.getComponentCount(); i++) { JMenu m = (JMenu) mb.getComponent(i); if (!m.getText().equals(Messages.getString("GameInformationFrame.MENU_FILE"))) //$NON-NLS-1$ m.setEnabled(enabled); } for (int i = 0; i < toolbar.getComponentCount(); i++) { Component c = toolbar.getComponent(i); if (c != save) c.setEnabled(enabled); } } }); editor = new JEditorPane(); editor.setEditorKit(rtf); setFocusTraversalPolicy(new TextAreaFocusTraversalPolicy(editor)); addDocumentListeners(); editor.addCaretListener(undoManager); editor.addCaretListener(new CaretListener() { public void caretUpdate(CaretEvent ce) { fFamilyChange = true; fSizeChange = true; StyledDocument d = (StyledDocument) editor.getDocument(); int dot = ce.getDot(); if (ce.getMark() <= dot) dot--; AttributeSet as = d.getCharacterElement(dot).getAttributes(); String f = StyleConstants.getFontFamily(as); int s = StyleConstants.getFontSize(as); boolean b = StyleConstants.isBold(as); boolean i = StyleConstants.isItalic(as); boolean u = StyleConstants.isUnderline(as); cbFonts.setSelectedItem(f); sSizes.setValue(s); tbBold.setSelected(b); tbItalic.setSelected(i); tbUnderline.setSelected(u); } }); tabs.addTab(Messages.getString("GameInformationFrame.TAB_INFO"), //$NON-NLS-1$ /**/null,new JScrollPane(editor),Messages.getString("GameInformationFrame.HINT_INFO")); //$NON-NLS-1$ tabs.addTab(Messages.getString("GameInformationFrame.TAB_SETTINGS"), //$NON-NLS-1$ /**/null,makeSettings(),Messages.getString("GameInformationFrame.HINT_SETTINGS")); //$NON-NLS-1$ revertResource(); fc = new CustomFileChooser("/org/lateralgm","LAST_GAMEINFO_DIR"); //$NON-NLS-1$ //$NON-NLS-2$ fc.setFileFilter(new CustomFileFilter( Messages.getString("GameInformationFrame.TYPE_RTF"),".rtf")); //$NON-NLS-1$ //$NON-NLS-2$ } private void addDocumentListeners() { editor.getDocument().addDocumentListener(new DocumentListener() { public void removeUpdate(DocumentEvent e) { documentChanged = true; } public void changedUpdate(DocumentEvent e) { documentChanged = true; } public void insertUpdate(DocumentEvent e) { documentChanged = true; } }); editor.getDocument().addUndoableEditListener(undoManager); } public void setEditorBackground(Color c) { editor.setBackground(c); Color sc = new Color(c.getRed() > 127 ? 0 : 255,c.getGreen() > 127 ? 0 : 255, c.getBlue() > 127 ? 0 : 255); editor.setSelectedTextColor(c); editor.setSelectionColor(sc); Color cc = new Color((c.getRed() + sc.getRed()) / 2,(c.getGreen() + sc.getGreen()) / 2, (c.getBlue() + sc.getBlue()) / 2); editor.setCaretColor(cc); } public void setSelectionAttribute(Object key, Object value) { StyledDocument sd = (StyledDocument) editor.getDocument(); int a = editor.getSelectionStart(); int b = editor.getSelectionEnd(); if (a == b) { rtf.getInputAttributes().addAttribute(key,value); return; } SimpleAttributeSet sas = new SimpleAttributeSet(); sas.addAttribute(key,value); sd.setCharacterAttributes(a,b - a,sas,false); } public JMenuItem addItem(String key) { JMenuItem item = new JMenuItem(Messages.getString(key)); item.setIcon(LGM.getIconForKey(key)); item.setActionCommand(key); item.addActionListener(this); add(item); return item; } public void loadFromFile() { fc.setDialogTitle(Messages.getString("GameInformationFrame.LOAD_TITLE")); //$NON-NLS-1$ while (true) { if (fc.showOpenDialog(LGM.frame) != JFileChooser.APPROVE_OPTION) return; if (fc.getSelectedFile().exists()) break; JOptionPane.showMessageDialog(null,fc.getSelectedFile().getName() + Messages.getString("SoundFrame.FILE_MISSING"), //$NON-NLS-1$ Messages.getString("GameInformationFrame.LOAD_TITLE"), //$NON-NLS-1$ JOptionPane.WARNING_MESSAGE); } try { FileInputStream i = new FileInputStream(fc.getSelectedFile()); editor.setText(""); //$NON-NLS-1$ rtf.read(i,editor.getDocument(),0); i.close(); } catch (Exception e) { e.printStackTrace(); } } public void saveToFile() { fc.setDialogTitle(Messages.getString("GameInformationFrame.SAVE_TITLE")); //$NON-NLS-1$ if (fc.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return; String name = fc.getSelectedFile().getPath(); if (CustomFileFilter.getExtension(name) == null) name += ".rtf"; //$NON-NLS-1$ try { FileOutputStream i = new FileOutputStream(new File(name)); rtf.write(i,editor.getDocument(),0,0); i.close(); } catch (Exception e) { e.printStackTrace(); } } public Object getUserObject() { for (int m = 0; m < LGM.root.getChildCount(); m++) { ResNode n = (ResNode) LGM.root.getChildAt(m); if (n.kind == Resource.Kind.GAMEINFO) return n.getUserObject(); } return Messages.getString("LGM.GAMEINFO"); //$NON-NLS-1$ } public void actionPerformed(ActionEvent arg0) { String com = arg0.getActionCommand(); if (com.equals("GameInformationFrame.LOAD")) //$NON-NLS-1$ { tabs.setSelectedIndex(0); loadFromFile(); } if (com.equals("GameInformationFrame.CLOSESAVE")) //$NON-NLS-1$ { updateResource(); close(); return; } if (com.equals("GameInformationFrame.FILESAVE")) //$NON-NLS-1$ { tabs.setSelectedIndex(0); saveToFile(); return; } if (com.equals("GameInformationFrame.COLOR")) //$NON-NLS-1$ { String colorStr = Messages.getString("GameInformationFrame.COLOR"); //$NON-NLS-1$ Color c = JColorChooser.showDialog(this,colorStr,editor.getBackground()); if (c != null) setEditorBackground(c); return; } if (com.equals("GameInformationFrame.CUT")) //$NON-NLS-1$ { editor.cut(); return; } if (com.equals("GameInformationFrame.COPY")) //$NON-NLS-1$ { editor.copy(); return; } if (com.equals("GameInformationFrame.PASTE")) //$NON-NLS-1$ { editor.paste(); return; } if (com.equals("GameInformationFrame.SELECTALL")) //$NON-NLS-1$ { editor.selectAll(); return; } } public void commitChanges() { res.put(PGameInformation.BACKGROUND_COLOR,editor.getBackground()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { rtf.write(baos,editor.getDocument(),0,0); res.put(PGameInformation.TEXT,baos.toString("UTF-8")); //$NON-NLS-1$ } catch (IOException e) { } catch (BadLocationException e) { } } public void setComponents(GameInformation info) { setEditorBackground((Color) res.get(PGameInformation.BACKGROUND_COLOR)); editor.setText(null); try { rtf.read( new ByteArrayInputStream(((String) res.get(PGameInformation.TEXT)).getBytes("UTF-8")), //$NON-NLS-1$ editor.getDocument(),0); } catch (IOException e) { } catch (BadLocationException e) { } } @Override public String getConfirmationName() { return (String) getUserObject(); } @Override public boolean resourceChanged() { commitChanges(); return !res.properties.equals(resOriginal.properties); } @Override public void revertResource() { res.properties.putAll(resOriginal.properties); setComponents(res); } @Override public void updateResource() { commitChanges(); resOriginal = res.clone(); } public void exceptionThrown(Exception e) { e.printStackTrace(); } }