001/*
002 * $Id: BorderHighlighter.java 3100 2008-10-14 22:33:10Z rah003 $
003 *
004 * Copyright 2007 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 * 
012 * This library 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 GNU
015 * Lesser General Public License for more details.
016 * 
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 */
021package org.jdesktop.swingx.decorator;
022
023import java.awt.Component;
024
025import javax.swing.BorderFactory;
026import javax.swing.JComponent;
027import javax.swing.border.Border;
028
029/**
030 * A Highlighter that applies a border the the renderer component.
031 * 
032 * The resulting border can be configured to 
033 * - ignore the component's border, set this highlighter's border
034 * - compound of this highlighter's border and component border, with
035 *   this highlighter's border either inner or outer.
036 *   
037 * The default setting is compound outer.
038 *   
039 */
040public class BorderHighlighter extends AbstractHighlighter {
041
042    private Border paddingBorder;
043    private boolean inner;
044    private boolean compound;
045
046    /**
047     * 
048     * Instantiates a BorderHighlighter with no padding. The
049     * Highlighter is applied unconditionally.
050     * 
051     */
052    public BorderHighlighter() {
053        this((HighlightPredicate) null, null);
054    }
055    
056    /**
057     * 
058     * Instantiates a BorderHighlighter with no padding, using the 
059     * given predicate.
060     * 
061     * @param predicate the HighlightPredicate to use
062     * 
063     */
064    public BorderHighlighter(HighlightPredicate predicate) {
065        this(predicate, null);
066    }
067
068    
069    /**
070     * 
071     * Instantiates a BorderHighlighter with the given padding. The
072     * Highlighter is applied unconditionally.
073     * 
074     * @param paddingBorder the border to apply as visual decoration.
075     * 
076     */
077    public BorderHighlighter(Border paddingBorder) {
078        this(null, paddingBorder);
079    }
080
081    /**
082     * 
083     * Instantiates a BorderHighlighter with the given padding, 
084     * HighlightPredicate and default compound property. 
085     * If the predicate is null, the highlighter
086     * will be applied unconditionally.
087     * 
088     * @param predicate the HighlightPredicate to use
089     * @param paddingBorder the border to apply as visual decoration.
090     * 
091     */
092    public BorderHighlighter(HighlightPredicate predicate, Border paddingBorder) {
093        this(predicate, paddingBorder, true);
094    }
095
096    /**
097     * 
098     * Instantiates a BorderHighlighter with the given padding, 
099     * HighlightPredicate, compound property and default inner property. 
100     * If the predicate is null, the highlighter
101     * will be applied unconditionally.
102     * 
103     * @param predicate the HighlightPredicate to use
104     * @param paddingBorder the border to apply as visual decoration.
105     * @param compound the compound property.
106     * 
107     */
108    public BorderHighlighter(HighlightPredicate predicate, 
109            Border paddingBorder, boolean compound) {
110        this(predicate, paddingBorder, compound, false);
111    }
112    
113    /**
114     * 
115     * Instantiates a BorderHighlighter with the given padding, 
116     * HighlightPredicate and compound property. If the predicate is null, the highlighter
117     * will be applied unconditionally.
118     * 
119     * @param predicate the HighlightPredicate to use
120     * @param paddingBorder the border to apply as visual decoration.
121     * @param compound the compound property
122     * @param inner the inner property
123     */
124    public BorderHighlighter(HighlightPredicate predicate, 
125            Border paddingBorder, boolean compound, boolean inner) {
126        super(predicate);
127        this.paddingBorder = paddingBorder;
128        this.compound = compound;
129        this.inner = inner;
130    }
131
132
133
134
135    /**
136     * {@inheritDoc}
137     */
138    @Override
139    protected Component doHighlight(Component renderer, ComponentAdapter adapter) {
140          ((JComponent) renderer).setBorder(compoundBorder(
141                    ((JComponent) renderer).getBorder()));
142         return renderer;
143    }
144
145    /**
146     * {@inheritDoc} <p>
147     * 
148     * Overridden to prevent highlighting if there's no padding available or
149     * the renderer is not of type JComponent.
150     * 
151     * @param component the cell renderer component that is to be decorated
152     * @param adapter the ComponentAdapter for this decorate operation
153     * @return true padding is available and the 
154     *   renderer is a JComponent. False otherwise.
155     */
156    @Override
157    protected boolean canHighlight(Component component, ComponentAdapter adapter) {
158        return (getBorder() !=  null) && (component instanceof JComponent); 
159    }
160
161    /**
162     * Sets the compound property. If true, the highlight border will be compounded
163     * with the renderer's border, if any. Otherwise, the highlight border will
164     * replace the renderer's border.<p>
165     * 
166     * The default value is true;
167     * 
168     * @param compound a boolean indicating whether the highlight border should be 
169     *  compounded with the component's border.
170     */
171    public void setCompound(boolean compound) {
172        if (isCompound() == compound) return;
173        this.compound = compound;
174        fireStateChanged();
175    }
176    
177    /**
178     * 
179     * @return the compound property.
180     * @see #setCompound(boolean)
181     */
182    public boolean isCompound() {
183        return compound;
184    }
185    
186    /**
187     * Sets the inner property. If true/false and compounded is enabled
188     * the highlight border will be the inner/outer border of the compound. 
189     * 
190     * The default value is false;
191     * 
192     * @param inner a boolean indicating whether the highlight border should be 
193     *  compounded as inner or outer border.
194     *  
195     *  @see #isInner()
196     */
197    public void setInner(boolean inner) {
198        if (isInner() == inner) return;
199        this.inner = inner;
200        fireStateChanged();
201    }
202    
203    /**
204     * Returns the inner property.
205     * 
206     * @return the inner property.
207     * @see #setInner(boolean)
208     */
209    public boolean isInner() {
210        return inner;
211    }
212
213    /**
214     * Sets the Border used for highlighting. <p>
215     * 
216     * The default value is null.
217     * 
218     * @param padding the Border to use
219     */
220    public void setBorder(Border padding) {
221        if (areEqual(padding, getBorder())) return;
222        this.paddingBorder = padding;
223        fireStateChanged();
224    }
225    
226
227    /**
228     * Returns the border used for highlighing.<p>
229     * 
230     * @return the border used to highlight.
231     */
232    public Border getBorder() {
233        return paddingBorder;
234    }
235    
236
237    /**
238     * PRE: paddingBorder != null.
239     * @param border
240     * @return
241     */
242    private Border compoundBorder(Border border) {
243        if (compound) {
244            if (border != null) {
245                if (inner) {
246                    return BorderFactory.createCompoundBorder(border,
247                            paddingBorder);
248                }
249                return BorderFactory.createCompoundBorder(paddingBorder,
250                        border);
251            }
252        }
253        return paddingBorder;
254    }
255
256}
257