OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 19 | Rev 41 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.ui.table;
15
 
16
import java.awt.Color;
17
import java.awt.Component;
18
import java.awt.Graphics;
19
import java.beans.PropertyChangeEvent;
20
import java.beans.PropertyChangeListener;
21
import java.util.Collections;
22
import java.util.HashMap;
23
import java.util.Map;
24
 
25
import javax.swing.JComponent;
26
import javax.swing.JTable;
27
import javax.swing.table.DefaultTableCellRenderer;
28
import javax.swing.table.TableCellRenderer;
29
import javax.swing.table.TableColumn;
30
 
31
/**
32
 * A renderer that color odd lines (à la iTunes).
33
 *
34
 * @author Sylvain
35
 */
19 ilm 36
public class AlternateTableCellRenderer extends TableCellRendererDecorator {
17 ilm 37
 
25 ilm 38
    public static final Color COLOR_LIGHT_GRAY = new Color(243, 247, 251);
17 ilm 39
    public static final Color DEFAULT_BG_COLOR = Color.WHITE;
40
    /** Default map from white to gray */
41
    public static final Map<Color, Color> DEFAULT_MAP = Collections.singletonMap(DEFAULT_BG_COLOR, COLOR_LIGHT_GRAY);
42
 
43
    private static final String ODD_BG_COLOR_MAP_PROP = AlternateTableCellRenderer.class.getSimpleName() + " odd background colour map";
44
 
45
    public static void setBGColorMap(final JComponent comp, final Color evenColor, final Color oddColor) {
46
        setBGColorMap(comp, Collections.singletonMap(evenColor, oddColor));
47
    }
48
 
49
    /**
50
     * Indicate which alternate background colour to use for odd rows. The {@link #DEFAULT_MAP} is
51
     * always set first.
52
     *
53
     * @param comp the renderer component.
54
     * @param m a map from even colours to odd colours.
55
     */
56
    public static void setBGColorMap(final JComponent comp, final Map<Color, Color> m) {
57
        final Map<Color, Color> res = new HashMap<Color, Color>(DEFAULT_MAP);
58
        res.putAll(m);
59
        comp.putClientProperty(ODD_BG_COLOR_MAP_PROP, res);
60
    }
61
 
62
    @SuppressWarnings("unchecked")
63
    private static Map<Color, Color> getBGColorMap(final JComponent comp) {
64
        return (Map<Color, Color>) comp.getClientProperty(ODD_BG_COLOR_MAP_PROP);
65
    }
66
 
67
    private static Color getAlternateColor(Color c) {
68
        return new Color((int) (c.getRed() * .9), (int) (c.getGreen() * .9), (int) (c.getBlue() * .9));
69
    }
70
 
71
    private static final ProxyComp altComp = new ProxyComp();
72
 
73
    private static final class ProxyComp extends JComponent {
74
 
75
        private Component comp;
76
        private JComponent jComp;
77
        private Map<Color, Color> oddBGColorMap;
78
 
79
        public ProxyComp setComp(Component comp) {
80
            if (this.comp != comp) {
81
                this.comp = comp;
82
                this.jComp = comp instanceof JComponent ? (JComponent) comp : null;
83
            }
84
            final Map<Color, Color> jCompMap = this.jComp == null ? null : getBGColorMap(this.jComp);
85
            this.oddBGColorMap = jCompMap == null ? DEFAULT_MAP : jCompMap;
86
            return this;
87
        }
88
 
89
        private Color getAlternateColor(final Color c) {
90
            final Color res = this.oddBGColorMap.get(c);
91
            return res != null ? res : AlternateTableCellRenderer.getAlternateColor(c);
92
        }
93
 
94
        @Override
95
        public void paint(Graphics g) {
96
            final Color origBG = this.comp.getBackground();
97
            final Color altBG = this.getAlternateColor(origBG);
98
 
99
            boolean wasDoubleBuffered = false;
100
            if (this.jComp != null && this.jComp.isDoubleBuffered()) {
101
                wasDoubleBuffered = true;
102
                this.jComp.setDoubleBuffered(false);
103
            }
104
 
105
            // can't rely on *validate() since this.comp isn't displayed
106
            if (this.getWidth() != this.comp.getWidth() || this.getHeight() != this.comp.getHeight()) {
107
                this.comp.setSize(this.getWidth(), this.getHeight());
108
                this.comp.doLayout();
109
            }
110
 
111
            this.comp.setBackground(altBG);
112
            this.comp.paint(g);
113
            this.comp.setBackground(origBG);
114
 
115
            if (wasDoubleBuffered) {
116
                this.jComp.setDoubleBuffered(true);
117
            }
118
        }
119
    };
120
 
19 ilm 121
    static public final TableCellRendererDecoratorUtils<AlternateTableCellRenderer> UTILS = createUtils(AlternateTableCellRenderer.class);
17 ilm 122
 
123
    private static final PropertyChangeListener RENDERER_L = new PropertyChangeListener() {
124
        @Override
125
        public void propertyChange(PropertyChangeEvent evt) {
126
            if ("cellRenderer".equals(evt.getPropertyName())) {
19 ilm 127
                UTILS.setRenderer((TableColumn) evt.getSource());
17 ilm 128
            }
129
        }
130
    };
131
 
132
    static public final void setRendererAndListen(final TableColumn col) {
133
        // handle calling more than once
134
        col.removePropertyChangeListener(RENDERER_L);
135
        setRenderer(col);
136
        col.addPropertyChangeListener(RENDERER_L);
137
    }
138
 
139
    static public final void setRenderer(final TableColumn col) {
19 ilm 140
        UTILS.setRenderer(col);
17 ilm 141
    }
142
 
143
    static public AlternateTableCellRenderer createDefault() {
144
        return new AlternateTableCellRenderer(new DefaultTableCellRenderer());
145
    }
146
 
147
    public AlternateTableCellRenderer() {
148
        this(null);
149
    }
150
 
151
    public AlternateTableCellRenderer(TableCellRenderer renderer) {
19 ilm 152
        super(renderer);
17 ilm 153
    }
154
 
155
    @Override
156
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
19 ilm 157
        TableCellRenderer tableRenderer = this.getRenderer(table, column);
17 ilm 158
        if (tableRenderer instanceof IAlternateTableCellRenderer) {
159
            return ((IAlternateTableCellRenderer) tableRenderer).getAlternateTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
160
        } else {
161
            final Component comp = tableRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
162
            if (isSelected || row % 2 == 0) {
163
                return comp;
164
            } else {
165
                return altComp.setComp(comp);
166
            }
167
        }
168
    }
169
}