001/*
002 * Copyright (c) 2005 Einar Pehrson
003 *
004 * This file is part of
005 * CleanSheets Extension for Style
006 *
007 * CleanSheets Extension for Style is free software; you can
008 * redistribute it and/or modify it under the terms of the GNU General Public
009 * License as published by the Free Software Foundation; either version 2 of
010 * the License, or (at your option) any later version.
011 *
012 * CleanSheets Extension for Style is distributed in the hope that
013 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
014 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
015 * See the 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 Extension for Style; if not, write to the
019 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020 * Boston, MA  02111-1307  USA
021 */
022package csheets.ext.style;
023
024import java.awt.Color;
025import java.awt.Font;
026import java.text.DateFormat;
027import java.text.Format;
028import java.text.NumberFormat;
029
030import javax.swing.BorderFactory;
031import javax.swing.SwingConstants;
032import javax.swing.UIManager;
033import javax.swing.border.Border;
034
035import csheets.core.Cell;
036import csheets.core.Value;
037import csheets.ext.CellExtension;
038
039/**
040 * An extension of a cell in a spreadsheet, with support for style, i.e. font,
041 * format, alignment, color and border.
042 * @author Einar Pehrson
043 */
044public class StylableCell extends CellExtension {
045
046        /** The unique version identifier used for serialization */
047        private static final long serialVersionUID = -4860391005521272291L;
048
049        /** The default number format */
050        public static final NumberFormat NUMBER_FORMAT  = NumberFormat.getInstance();
051
052        /** The default date format */
053        public static final DateFormat DATE_FORMAT
054                = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
055
056        /** The default font */
057        public static final Font FONT = UIManager.getFont("Table.font");
058
059        /** The default vertical alignment */
060        public static final int VERTICAL_ALIGNMENT = SwingConstants.CENTER;
061
062        /** The default foreground color */
063        public static final Color FOREGROUND = UIManager.getColor("Table.foreground");
064
065        /** The default background color */
066        public static final Color BACKGROUND = UIManager.getColor("Table.background");
067
068        /** The default empty border */
069        public static final Border BORDER
070                = BorderFactory.createEmptyBorder(1, 1, 1, 1);
071
072        /** The format applied to the cell's value before rendering */
073        private Format format;
074
075        /** The font used when rendering the cell's content */
076        private Font font;
077
078        /** The horizontal alignment of the cell's content */
079        private int hAlignment;
080
081        /** The vertical alignment of the cell's content */
082        private int vAlignment;
083
084        /** The color used when rendering the cell's content */
085        private Color fgColor;
086
087        /** The background color of the cell */
088        private Color bgColor;
089
090        /** The border of the cell */
091        private Border border;
092
093        /**
094         * Creates a stylable cell extension for the given cell.
095         * @param cell the cell to extend
096         */
097        StylableCell(Cell cell) {
098                super(cell, StyleExtension.NAME);
099                resetStyle();
100        }
101
102        /**
103         * Returns whether a format can be applied to the cell's value.
104         * @return whether a format can be applied to the cell's value
105         */
106        public boolean isFormattable() {
107                Value.Type valueType = getValue().getType();
108                return valueType == Value.Type.NUMERIC || valueType == Value.Type.DATE;
109        }
110
111        /**
112         * Returns the format applied to the cell's value before rendering.
113         * @return the format applied to the cell's value before rendering
114         */
115        public Format getFormat() {
116                switch (getValue().getType()) {
117                        case NUMERIC:
118                                return format instanceof NumberFormat ? format : NUMBER_FORMAT;
119                        case DATE:
120                                return format instanceof DateFormat ? format : DATE_FORMAT;
121                        default:
122                                return null;
123                }
124        }
125
126        /**
127         * Returns the font used when rendering the cell's content.
128         * @return the font used when rendering the cell's content
129         */
130        public Font getFont() {
131                return font;
132        }
133
134        /**
135         * Returns the horizontal alignment of the cell's content.
136         * @return the horizontal alignment of the cell's content
137         */
138        public int getHorizontalAlignment() {
139                if (hAlignment == -1)
140                        // Returns default alignment
141                        switch (getValue().getType()) {
142                                case NUMERIC:
143                                case DATE:              return SwingConstants.RIGHT;
144                                case BOOLEAN:
145                                case ERROR:     return SwingConstants.CENTER;
146                                default:                return SwingConstants.LEFT;
147                        }
148                else
149                        return hAlignment;
150        }
151
152        /**
153         * Returns the vertical alignment of the cell's content.
154         * @return the vertical alignment of the cell's content
155         */
156        public int getVerticalAlignment() {
157                return vAlignment;
158        }
159
160        /**
161         * Returns the color used when rendering the cell's content.
162         * @return the color used when rendering the cell's content
163         */
164        public Color getForegroundColor() {
165                return fgColor;
166        }
167
168        /**
169         * Returns the background color of the cell.
170         * @return the background color of the cell
171         */
172        public Color getBackgroundColor() {
173                return bgColor;
174        }
175
176        /**
177         * Returns the border of the cell.
178         * @return the border of the cell
179         */
180        public Border getBorder() {
181                return border;
182        }
183
184        /**
185         * Sets the format applied to the cell's value before rendering.
186         * @param format the format applied to the cell's value before rendering
187         */
188        public void setFormat(Format format) {
189                this.format = format;
190        }
191
192        /**
193         * Sets the font used when rendering the cell's content.
194         * @param font the font used when rendering the cell's content
195         */
196        public void setFont(Font font) {
197                this.font = font;
198        }
199
200        /**
201         * Sets the horizontal alignment of the cell's content.
202         * @param hAlignment the horizontal alignment of the cell's content
203         */
204        public void setHorizontalAlignment(int hAlignment) {
205                if (hAlignment == SwingConstants.LEFT
206                 ||     hAlignment == SwingConstants.CENTER
207                 ||     hAlignment == SwingConstants.RIGHT)
208                        this.hAlignment = hAlignment;
209                 else throw new IllegalArgumentException("Illegal alignment");
210        }
211
212        /**
213         * Sets the vertical alignment of the cell's content.
214         * @param vAlignment the vertical alignment of the cell's content
215         */
216        public void setVerticalAlignment(int vAlignment) {
217                if (vAlignment == SwingConstants.TOP
218                 ||     vAlignment == SwingConstants.CENTER
219                 ||     vAlignment == SwingConstants.BOTTOM)
220                        this.vAlignment = vAlignment;
221                 else throw new IllegalArgumentException("Illegal alignment");
222        }
223
224        /**
225         * Sets the color used when rendering the cell's content.
226         * @param fgColor the color used when rendering the cell's content
227         */
228        public void setForegroundColor(Color fgColor) {
229                this.fgColor = fgColor;
230        }
231
232        /**
233         * Sets the background color of the cell.
234         * @param bgColor the background color of the cell
235         */
236        public void setBackgroundColor(Color bgColor) {
237                this.bgColor = bgColor;
238        }
239
240        /**
241         * Sets the border of the cell.
242         * @param border the border of the cell
243         */
244        public void setBorder(Border border) {
245                this.border = border;
246        }
247
248        /**
249         * Restes the style of the cell.
250         */
251        public void resetStyle() {
252                this.format             = null;
253                this.font               = FONT;
254                this.hAlignment = -1;
255                this.vAlignment = VERTICAL_ALIGNMENT;
256                this.fgColor    = FOREGROUND;
257                this.bgColor    = BACKGROUND;
258                this.border             = BORDER;
259        }
260
261        /**
262         * Removes the style from the cell.
263         * @param cell the cell that was modified
264         */
265        public void cellCleared(Cell cell) {
266                if (this.getDelegate().equals(cell)) {
267                        resetStyle();
268                }
269        }
270
271        /**
272         * Copies the style from the source cell to this one.
273         * @param cell the cell that was modified
274         * @param source the cell from which data was copied
275         */
276        public void cellCopied(Cell cell, Cell source) {
277                if (this.getDelegate().equals(cell)) {
278                        StylableCell stylableSource = (StylableCell)source.getExtension(
279                                StyleExtension.NAME);
280                        this.format             = stylableSource.format;
281                        this.font               = stylableSource.font;
282                        this.hAlignment = stylableSource.hAlignment;
283                        this.vAlignment = stylableSource.vAlignment;
284                        this.fgColor    = stylableSource.fgColor;
285                        this.bgColor    = stylableSource.bgColor;
286                        this.border             = stylableSource.border;
287                }
288        }
289}