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     */
022    package csheets.ext.style;
023    
024    import java.awt.Color;
025    import java.awt.Font;
026    import java.text.DateFormat;
027    import java.text.Format;
028    import java.text.NumberFormat;
029    
030    import javax.swing.BorderFactory;
031    import javax.swing.SwingConstants;
032    import javax.swing.UIManager;
033    import javax.swing.border.Border;
034    
035    import csheets.core.Cell;
036    import csheets.core.Value;
037    import 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     */
044    public 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    }