001/*
002 * $Id: TableCellContext.java 3783 2010-09-15 13:13:23Z kleopatra $
003 *
004 * Copyright 2008 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.renderer;
022
023import java.awt.Color;
024
025import javax.swing.JTable;
026import javax.swing.UIManager;
027
028import org.jdesktop.swingx.plaf.UIManagerExt;
029
030/**
031 * Table specific <code>CellContext</code>.
032 * 
033 * This implementation optionally can handle LAF provide alternateRowColor. The default 
034 * is not doing it. To enable, client code must set a UI-Property with key 
035 * HANDLE_ALTERNATE_ROW_BACKGROUND to Boolean.TRUE.
036 */
037public class TableCellContext extends CellContext {
038
039    public static final String HANDLE_ALTERNATE_ROW_BACKGROUND = "TableCellContext.handleAlternateRowBackground";
040    /**
041     * Sets state of the cell's context. Note that the component might be null
042     * to indicate a cell without a concrete context. All accessors must cope
043     * with.
044     * 
045     * @param component the component the cell resides on, might be null
046     * @param value the content value of the cell
047     * @param row the cell's row index in view coordinates
048     * @param column the cell's column index in view coordinates
049     * @param selected the cell's selected state
050     * @param focused the cell's focused state
051     * @param expanded the cell's expanded state
052     * @param leaf the cell's leaf state
053     */
054    public void installContext(JTable component, Object value, int row, int column,
055            boolean selected, boolean focused, boolean expanded, boolean leaf) {
056        this.component = component;
057        installState(value, row, column, selected, focused, expanded, leaf);
058        this.dropOn = checkDropOnState();
059    }
060    
061    
062    /**
063     * 
064     */
065    private boolean checkDropOnState() {
066        if ((getComponent() == null) || !isValidRow() || !isValidColumn()) {
067            return false;
068        }
069        JTable.DropLocation dropLocation = getComponent().getDropLocation();
070        if (dropLocation != null
071                && !dropLocation.isInsertRow()
072                && !dropLocation.isInsertColumn()
073                && dropLocation.getRow() == row
074                && dropLocation.getColumn() == column) {
075            return true;
076        }
077        return false;
078    }
079
080
081    @Override
082    public JTable getComponent() {
083        return (JTable) super.getComponent();
084    }
085
086    /**
087     * Returns the cell's editable property as returned by table.isCellEditable
088     * or false if the table is null.
089     * 
090     * @return the cell's editable property. 
091     */
092    @Override
093    public boolean isEditable() {
094        if ((getComponent() == null) || !isValidRow() || !isValidColumn()) {
095            return false;
096        }
097        return getComponent().isCellEditable(getRow(), getColumn());
098    }
099
100    /** 
101     * @inherited <p>
102     * Overridden to respect UI alternating row colors.
103     * 
104     */
105    @Override
106    protected Color getBackground() {
107        if (isDropOn()) {
108            return getSelectionBackground();
109        }
110        if (getComponent() == null) return null;
111        Color color = getAlternateRowColor();
112        // JW: this is fixing a core bug - alternate color (aka: different 
113        // from default table background) should be the odd row
114        if ((color != null) && getRow() >= 0 && getRow() % 2 == 1) {
115            return color;
116        }
117        return getComponent().getBackground();
118    }
119    
120    /**
121     * Returns a Color to for odd row background if this context should handle the
122     * alternating row color AND the UIManager has the alternateRowColor property set.
123     * Returns null otherwise.
124     * 
125     * @return the color to use for odd row background, or null if either this context
126     *    does not handle or no alternate row color is set.
127     */
128    protected Color getAlternateRowColor() {
129        if (!Boolean.TRUE.equals(UIManager.get(HANDLE_ALTERNATE_ROW_BACKGROUND))) return null;
130        return UIManagerExt.getColor(getUIPrefix() + "alternateRowColor");
131        
132    }
133
134    /**
135     * {@inheritDoc}
136     */
137    @Override
138    protected Color getSelectionBackground() {
139        Color selection = null;
140        if (isDropOn()) {
141            selection = getDropCellBackground();
142            if (selection != null) return selection;
143        }
144        return getComponent() != null ? getComponent()
145                .getSelectionBackground() : null;
146    }
147
148    /**
149     * {@inheritDoc}
150     */
151    @Override
152    protected Color getSelectionForeground() {
153        Color selection = null;
154        if (isDropOn()) {
155            selection = getDropCellForeground();
156            if (selection != null) return selection;
157        }
158        return getComponent() != null ? getComponent()
159                .getSelectionForeground() : null;
160    }
161
162    /**
163     * {@inheritDoc}
164     */
165    @Override
166    protected String getUIPrefix() {
167        return "Table.";
168    }
169
170    /**
171     * PRE getComponent != null
172     * 
173     * @return whether the column coordinate is valid in this context
174     */
175    protected boolean isValidColumn() {
176        return getColumn() >= 0 && getColumn() < getComponent().getColumnCount() ;
177    }
178
179    /**
180     * PRE getComponent != null
181     * 
182     * @return whether the row coordinate is valid in this context
183     */
184    protected boolean isValidRow() {
185        return getRow() >= 0 && getRow() < getComponent().getRowCount() ;
186    }
187
188
189}