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 */
021 package csheets.ui;
022
023 import java.awt.BorderLayout;
024 import java.awt.Container;
025 import java.awt.Dimension;
026 import java.awt.EventQueue;
027 import java.awt.FlowLayout;
028 import java.awt.Font;
029 import java.awt.Toolkit;
030
031 import javax.swing.JComponent;
032 import javax.swing.JFrame;
033 import javax.swing.JPanel;
034 import javax.swing.JSplitPane;
035 import javax.swing.JTabbedPane;
036 import javax.swing.JToolBar;
037
038 import csheets.CleanSheets;
039 import csheets.core.Workbook;
040 import csheets.ui.ctrl.AboutAction;
041 import csheets.ui.ctrl.ActionManager;
042 import csheets.ui.ctrl.AddSpreadsheetAction;
043 import csheets.ui.ctrl.ClearAction;
044 import csheets.ui.ctrl.CloseAction;
045 import csheets.ui.ctrl.CloseAllAction;
046 import csheets.ui.ctrl.CopyAction;
047 import csheets.ui.ctrl.CutAction;
048 import csheets.ui.ctrl.ExitAction;
049 import csheets.ui.ctrl.HelpAction;
050 import csheets.ui.ctrl.InsertColumnAction;
051 import csheets.ui.ctrl.InsertRowAction;
052 import csheets.ui.ctrl.LicenseAction;
053 import csheets.ui.ctrl.NewAction;
054 import csheets.ui.ctrl.OpenAction;
055 import csheets.ui.ctrl.PasteAction;
056 import csheets.ui.ctrl.PreferencesAction;
057 import csheets.ui.ctrl.PrintAction;
058 import csheets.ui.ctrl.RedoAction;
059 import csheets.ui.ctrl.RemoveColumnAction;
060 import csheets.ui.ctrl.RemoveRowAction;
061 import csheets.ui.ctrl.RemoveSpreadsheetAction;
062 import csheets.ui.ctrl.RenameSpreadsheetAction;
063 import csheets.ui.ctrl.SaveAction;
064 import csheets.ui.ctrl.SaveAsAction;
065 import csheets.ui.ctrl.SearchAction;
066 import csheets.ui.ctrl.SelectAllAction;
067 import csheets.ui.ctrl.SelectionEvent;
068 import csheets.ui.ctrl.SelectionListener;
069 import csheets.ui.ctrl.SortAction;
070 import csheets.ui.ctrl.UIController;
071 import csheets.ui.ctrl.UndoAction;
072 import csheets.ui.ext.UIExtension;
073 import csheets.ui.sheet.AddressBox;
074 import csheets.ui.sheet.CellEditor;
075 import csheets.ui.sheet.WorkbookPane;
076
077 /**
078 * The main frame of the GUI.
079 * @author Einar Pehrson
080 */
081 @SuppressWarnings("serial")
082 public 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 }