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.core;
022
023import java.io.IOException;
024import java.io.ObjectInputStream;
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Iterator;
028import java.util.List;
029
030/**
031 * A workbook which can contain several spreadsheets.
032 * @author Einar Pehrson
033 */
034public class Workbook implements Iterable<Spreadsheet>, Serializable {
035
036        /** The unique version identifier used for serialization */
037        private static final long serialVersionUID = -6324252462576447242L;
038
039        /** The spreadsheets of which the workbook consists */
040        private List<Spreadsheet> spreadsheets = new ArrayList<Spreadsheet>();
041
042        /** The cell listeners that have been registered on the cell */
043        private transient List<WorkbookListener> listeners
044                = new ArrayList<WorkbookListener>();
045
046        /** The number of spreadsheets that have been created in the workbook */
047        private int createdSpreadsheets;
048
049        /**
050         * Creates a new empty workbook.
051         */
052        public Workbook() {}
053
054        /**
055         * Creates a new workbook, which initially contains the given number
056         * of blank spreadsheets.
057         * @param sheets the number of sheets to create initially
058         */
059        public Workbook(int sheets) {
060                for (int i = 0; i < sheets; i++)
061                        spreadsheets.add(new SpreadsheetImpl(this,
062                                getNextSpreadsheetTitle()));
063        }
064
065        /**
066         * Creates a new workbook, using the given content matrix to create
067         * spreadsheets initially.
068         * @param contents the content matrices to use when creating spreadsheets
069         */
070        public Workbook(String[][]... contents) {
071                for (String[][] content : contents)
072                        spreadsheets.add(new SpreadsheetImpl(this,
073                                getNextSpreadsheetTitle(), content));
074        }
075
076        /**
077         * Adds a blank spreadsheet to the end of the workbook.
078         */
079        public void addSpreadsheet() {
080                Spreadsheet spreadsheet = new SpreadsheetImpl(this,
081                        getNextSpreadsheetTitle());
082                spreadsheets.add(spreadsheet);
083                fireSpreadsheetInserted(spreadsheet, spreadsheets.size() - 1);
084        }
085
086        /**
087         * Adds a new spreadsheet to the workbook, in which cells are initialized
088         * with data from the given content matrix.
089         * @param content the contents of the cells in the spreadsheet
090         */
091        public void addSpreadsheet(String[][] content) {
092                Spreadsheet spreadsheet = new SpreadsheetImpl(this,
093                        getNextSpreadsheetTitle(), content);
094                spreadsheets.add(spreadsheet);
095                fireSpreadsheetInserted(spreadsheet, spreadsheets.size() - 1);
096        }
097
098        /**
099         * Returns the title to be used for the next spreadsheet added.
100         * @return the title to be used for the next spreadsheet added
101         */
102        private String getNextSpreadsheetTitle() {
103                return SpreadsheetImpl.BASE_TITLE + " " + (createdSpreadsheets++ + 1);
104        }
105
106        /**
107         * Adds a new blank spreadsheet to the workbook.
108         */
109        public void removeSpreadsheet(Spreadsheet spreadsheet) {
110                spreadsheets.remove(spreadsheet);
111                // Remove references to the spreadsheet in remaining spreadsheets!
112                fireSpreadsheetRemoved(spreadsheet);
113        }
114
115        /**
116         * Returns the spreadsheet at the given index.
117         * @param index the index of the spreadsheet in the workbook
118         * @return the spreadsheet at the given index
119         * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index >= |spreadsheets|)
120         */
121        public Spreadsheet getSpreadsheet(int index) throws IndexOutOfBoundsException {
122                return spreadsheets.get(index);
123        }
124
125        /**
126         * Returns the number of spreadsheets in the the workbook.
127         * @return the number of spreadsheets in the the workbook
128         */
129        public int getSpreadsheetCount() {
130                return spreadsheets.size();
131        }
132
133        /**
134         * Returns an iterator over the spreadsheets in the workbook.
135         * @return an iterator over the spreadsheets in the workbook
136         */
137        public Iterator<Spreadsheet> iterator() {
138                return spreadsheets.iterator();
139        }
140
141/*
142 * EVENT HANDLING
143 */
144
145        /**
146         * Registers the given listener on the workbook.
147         * @param listener the listener to be added
148         */
149        public void addWorkbookListener(WorkbookListener listener) {
150                listeners.add(listener);
151        }
152
153        /**
154         * Removes the given listener from the workbook.
155         * @param listener the listener to be removed
156         */
157        public void removeWorkbookListener(WorkbookListener listener) {
158                listeners.remove(listener);
159        }
160
161        /**
162         * Returns the listeners that have been registered on the workbook.
163         * @return the listeners that have been registered on the workbook
164         */
165        public WorkbookListener[] getWorkbookListeners() {
166                return listeners.toArray(new WorkbookListener[listeners.size()]);
167        }
168
169        /**
170         * Notifies all registered listeners that a spreadsheet has been inserted.
171         * @param spreadsheet the spreadsheet that was inserted
172         * @param index the index at which the spreadsheet was inserted
173         */
174        private void fireSpreadsheetInserted(Spreadsheet spreadsheet, int index) {
175                for (WorkbookListener listener : listeners)
176                        listener.spreadsheetInserted(spreadsheet, index);
177        }
178
179        /**
180         * Notifies all registered listeners that a spreadsheet has been removed.
181         * @param spreadsheet the spreadsheet that was removed
182         */
183        private void fireSpreadsheetRemoved(Spreadsheet spreadsheet) {
184                for (WorkbookListener listener : listeners)
185                        listener.spreadsheetRemoved(spreadsheet);
186        }
187
188        /**
189         * Notifies all registered listeners that a spreadsheet has been renamed.
190         * @param spreadsheet the spreadsheet that was renamed
191         */
192        @SuppressWarnings("unused")
193        private void fireSpreadsheetRenamed(Spreadsheet spreadsheet) {
194                for (WorkbookListener listener : listeners)
195                        listener.spreadsheetRenamed(spreadsheet);
196        }
197
198/*
199 * GENERAL
200 */
201
202        /**
203         * Customizes deserialization by recreating the listener list.
204         * @param stream the object input stream from which the object is to be read
205         * @throws IOException If any of the usual Input/Output related exceptions occur
206         * @throws ClassNotFoundException If the class of a serialized object cannot be found.
207         */
208        private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
209                stream.defaultReadObject();
210                listeners = new ArrayList<WorkbookListener>();
211        }
212}