001/* 002 * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>. 003 * 004 * This file is part of 005 * CleanSheets - a spreadsheet application for the Java platform. 006 * 007 * CleanSheets is free software; you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation; either version 2 of the License, or 010 * (at your option) any later version. 011 * 012 * CleanSheets is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with CleanSheets; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 */ 021package csheets.ui; 022 023import java.awt.BorderLayout; 024import java.awt.Container; 025import java.awt.Dimension; 026import java.awt.EventQueue; 027import java.awt.FlowLayout; 028import java.awt.Font; 029import java.awt.Toolkit; 030 031import javax.swing.JComponent; 032import javax.swing.JFrame; 033import javax.swing.JPanel; 034import javax.swing.JSplitPane; 035import javax.swing.JTabbedPane; 036import javax.swing.JToolBar; 037 038import csheets.CleanSheets; 039import csheets.core.Workbook; 040import csheets.ui.ctrl.AboutAction; 041import csheets.ui.ctrl.ActionManager; 042import csheets.ui.ctrl.AddSpreadsheetAction; 043import csheets.ui.ctrl.ClearAction; 044import csheets.ui.ctrl.CloseAction; 045import csheets.ui.ctrl.CloseAllAction; 046import csheets.ui.ctrl.CopyAction; 047import csheets.ui.ctrl.CutAction; 048import csheets.ui.ctrl.ExitAction; 049import csheets.ui.ctrl.HelpAction; 050import csheets.ui.ctrl.InsertColumnAction; 051import csheets.ui.ctrl.InsertRowAction; 052import csheets.ui.ctrl.LicenseAction; 053import csheets.ui.ctrl.NewAction; 054import csheets.ui.ctrl.OpenAction; 055import csheets.ui.ctrl.PasteAction; 056import csheets.ui.ctrl.PreferencesAction; 057import csheets.ui.ctrl.PrintAction; 058import csheets.ui.ctrl.RedoAction; 059import csheets.ui.ctrl.RemoveColumnAction; 060import csheets.ui.ctrl.RemoveRowAction; 061import csheets.ui.ctrl.RemoveSpreadsheetAction; 062import csheets.ui.ctrl.RenameSpreadsheetAction; 063import csheets.ui.ctrl.SaveAction; 064import csheets.ui.ctrl.SaveAsAction; 065import csheets.ui.ctrl.SearchAction; 066import csheets.ui.ctrl.SelectAllAction; 067import csheets.ui.ctrl.SelectionEvent; 068import csheets.ui.ctrl.SelectionListener; 069import csheets.ui.ctrl.SortAction; 070import csheets.ui.ctrl.UIController; 071import csheets.ui.ctrl.UndoAction; 072import csheets.ui.ext.UIExtension; 073import csheets.ui.sheet.AddressBox; 074import csheets.ui.sheet.CellEditor; 075import csheets.ui.sheet.WorkbookPane; 076 077/** 078 * The main frame of the GUI. 079 * @author Einar Pehrson 080 */ 081@SuppressWarnings("serial") 082public class Frame extends JFrame implements SelectionListener { 083 084 /** The base of the window title */ 085 public static final String TITLE = "CleanSheets"; 086 087 /** The CleanSheets application */ 088 private CleanSheets app; 089 090 /** 091 * Creates a new frame. 092 * @param app the CleanSheets application 093 */ 094 public Frame(CleanSheets app) { 095 // Stores members and creates controllers 096 this.app = app; 097 UIController uiController = new UIController(app); 098 099 // Creates action manager 100 FileChooser chooser = null; 101 try { 102 chooser = new FileChooser(this, app.getUserProperties()); 103 } catch (java.security.AccessControlException ace) {} 104 ActionManager actionManager = new ActionManager(app, uiController, chooser); 105 106 // Registers file actions 107 actionManager.registerAction("new", new NewAction(app)); 108 actionManager.registerAction("open", new OpenAction(app, uiController, chooser)); 109 actionManager.registerAction("close", new CloseAction(app, uiController, chooser)); 110 actionManager.registerAction("closeall", new CloseAllAction(app, uiController, chooser)); 111 actionManager.registerAction("save", new SaveAction(app, uiController, chooser)); 112 actionManager.registerAction("saveas", new SaveAsAction(app, uiController, chooser)); 113 actionManager.registerAction("exit", new ExitAction(app, uiController, chooser)); 114 actionManager.registerAction("print", new PrintAction()); 115 116 // Registers edit actions 117 actionManager.registerAction("undo", new UndoAction()); 118 actionManager.registerAction("redo", new RedoAction()); 119 actionManager.registerAction("cut", new CutAction()); 120 actionManager.registerAction("copy", new CopyAction()); 121 actionManager.registerAction("paste", new PasteAction()); 122 actionManager.registerAction("clear", new ClearAction()); 123 actionManager.registerAction("selectall", new SelectAllAction()); 124 actionManager.registerAction("sort", new SortAction()); 125 actionManager.registerAction("search", new SearchAction()); 126 actionManager.registerAction("prefs", new PreferencesAction()); 127 128 // Registers spreadsheet actions 129 actionManager.registerAction("addsheet", new AddSpreadsheetAction(uiController)); 130 actionManager.registerAction("removesheet", new RemoveSpreadsheetAction(uiController)); 131 actionManager.registerAction("renamesheet", new RenameSpreadsheetAction(uiController)); 132 actionManager.registerAction("insertcolumn", new InsertColumnAction()); 133 actionManager.registerAction("removecolumn", new RemoveColumnAction()); 134 actionManager.registerAction("insertrow", new InsertRowAction()); 135 actionManager.registerAction("removerow", new RemoveRowAction()); 136 137 // Registers help actions 138 actionManager.registerAction("help", new HelpAction()); 139 actionManager.registerAction("license", new LicenseAction()); 140 actionManager.registerAction("about", new AboutAction()); 141 142 // Creates spreadsheet components 143 WorkbookPane workbookPane = new WorkbookPane(uiController, actionManager); 144 CellEditor cellEditor = new CellEditor(uiController); 145 AddressBox addressBox = new AddressBox(uiController); 146 147 // Creates tool bars 148 JPanel toolBarPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); 149 toolBarPanel.add(new StandardToolBar(actionManager)); 150 for (UIExtension extension : uiController.getExtensions()) { 151 JToolBar extToolBar = extension.getToolBar(); 152 if (extToolBar != null) 153 toolBarPanel.add(extToolBar); 154 } 155 156 // Creates and lays out top panel 157 JPanel cellPanel = new JPanel(new BorderLayout()); 158 cellPanel.add(addressBox, BorderLayout.WEST); 159 cellPanel.add(cellEditor, BorderLayout.CENTER); 160 JPanel topPanel = new JPanel(new BorderLayout()); 161 topPanel.add(toolBarPanel, BorderLayout.NORTH); 162 topPanel.add(cellPanel, BorderLayout.SOUTH); 163 164 // Creates and lays out side bar components 165 JTabbedPane sideBar = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT); 166 sideBar.setPreferredSize(new Dimension(170, 480)); 167 Font font = sideBar.getFont(); 168 sideBar.setFont(new Font(font.getFamily(), Font.PLAIN, font.getSize() - 1)); 169 for (UIExtension extension : uiController.getExtensions()) { 170 JComponent extBar = extension.getSideBar(); 171 if (extBar != null) 172 sideBar.insertTab(extension.getExtension().getName(), extension.getIcon(), 173 extBar, null, sideBar.getTabCount()); 174 } 175 176 // Lays out split pane 177 workbookPane.setMinimumSize(new Dimension(300, 100)); 178 sideBar.setMinimumSize(new Dimension(140, 100)); 179 JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 180 workbookPane, sideBar); 181 splitPane.setOneTouchExpandable(true); 182 splitPane.setResizeWeight(1.0); 183 184 // Configures layout and adds panels 185 Container pane = getContentPane(); 186 pane.setPreferredSize(new Dimension(640, 480)); 187 pane.setLayout(new BorderLayout()); 188 pane.add(topPanel, BorderLayout.NORTH); 189 pane.add(splitPane, BorderLayout.CENTER); 190 setJMenuBar(new MenuBar(app, actionManager, uiController)); 191 192 // Registers listeners 193 uiController.addSelectionListener(this); 194 addWindowListener(new WindowClosingHandler(this, 195 actionManager.getAction("exit"))); 196 197 // Configures appearance 198 setTitle(TITLE); 199 setIconImage(Toolkit.getDefaultToolkit().getImage( 200 CleanSheets.class.getResource("res/img/sheet.gif"))); 201 pack(); 202 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 203 setLocationRelativeTo(null); 204 } 205 206 /** 207 * Updates the title of the window when a new active workbook is selected. 208 * @param event the selection event that was fired 209 */ 210 public void selectionChanged(SelectionEvent event) { 211 Workbook workbook = event.getWorkbook(); 212 if (workbook != null) { 213 setVisible(true); 214 if (app.isWorkbookStored(workbook)) 215 setTitle(TITLE + " - " + app.getFile(workbook).getName()); 216 else 217 setTitle(TITLE + " - Untitled"); 218 } else 219 setTitle(TITLE); 220 } 221 222 /** 223 * A utility for creating a Frame on the AWT event dispatching thread. 224 * @author Einar Pehrson 225 */ 226 public static class Creator implements Runnable { 227 228 /** The component that was created */ 229 private Frame frame; 230 231 /** The CleanSheets application */ 232 private CleanSheets app; 233 234 /** 235 * Creates a new frame creator. 236 * @param app the CleanSheets application 237 */ 238 public Creator(CleanSheets app) { 239 this.app = app; 240 } 241 242 /** 243 * Creates a component on the AWT event dispatching thread. 244 * @return the component that was created 245 */ 246 public Frame createAndWait() { 247 try { 248 EventQueue.invokeAndWait(this); 249 } catch (InterruptedException e) { 250 return null; 251 } catch (java.lang.reflect.InvocationTargetException e) { 252 e.printStackTrace(); 253 return null; 254 } 255 return frame; 256 } 257 258 /** 259 * Asks the event queue to create a component at a later time. 260 * (Included for conformity.) 261 */ 262 public void createLater() { 263 EventQueue.invokeLater(this); 264 } 265 266 public void run() { 267 frame = new Frame(app); 268 } 269 } 270}