001/**
002 *  '$Author: welker $'
003 *  '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $'
004 *  '$Revision: 24234 $'
005 *
006 *  For Details:
007 *  http://www.kepler-project.org
008 *
009 *  Copyright (c) 2009-2010 The Regents of the
010 *  University of California. All rights reserved. Permission is hereby granted,
011 *  without written agreement and without license or royalty fees, to use, copy,
012 *  modify, and distribute this software and its documentation for any purpose,
013 *  provided that the above copyright notice and the following two paragraphs
014 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
015 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
016 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
017 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
018 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
019 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
020 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
021 *  SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 *  ENHANCEMENTS, OR MODIFICATIONS.
024 */
025
026package org.kepler.workflowrunmanager.gui;
027
028import java.awt.Component;
029import java.awt.Dimension;
030import java.util.Iterator;
031import java.util.Vector;
032
033import javax.swing.DefaultCellEditor;
034import javax.swing.JLabel;
035import javax.swing.JTable;
036import javax.swing.JTextField;
037import javax.swing.UIManager;
038import javax.swing.table.DefaultTableCellRenderer;
039import javax.swing.table.JTableHeader;
040import javax.swing.table.TableCellEditor;
041import javax.swing.table.TableCellRenderer;
042import javax.swing.table.TableColumn;
043
044/**
045 * ColumnGroup, GroupableTableColumnModel, GroupableTableHeader,
046 * GroupableTableHeaderUI and GroupableTableCellRenderer taken from a post by
047 * Steve Webb (16/09/04). He extended code originally posted by Nobuo Tamemasa.
048 * Many thanks to both authors. I've made some changes, including making the
049 * headers editable.
050 * 
051 */
052
053public class ColumnGroup extends TableColumn {
054        /**
055         * Cell renderer for group header.
056         */
057        protected TableCellRenderer renderer;
058        /**
059         * Holds the TableColumn or ColumnGroup objects contained within this
060         * ColumnGroup instance.
061         */
062        protected Vector<Object> v;
063        /**
064         * The ColumnGroup instance name.
065         */
066        // protected String text;
067
068        /** The ColumnGroup header object of the column. */
069        protected Object cgHeaderObject;
070
071        /**
072         * The margin to use for rendering.
073         */
074        protected int margin = 0;
075
076        protected TableCellEditor headerEditor;
077        protected boolean isHeaderEditable;
078
079        protected boolean isVisible = true;
080
081        /**
082         * Standard ColumnGroup constructor.
083         * 
084         * @param text
085         *            Name of the ColumnGroup which will be displayed when the
086         *            ColumnGroup is rendered.
087         */
088        // public ColumnGroup(String text) {
089        // this(null, text);
090        // this(null, null, text);
091        // }
092
093        /**
094         * Standard ColumnGroup constructor.
095         * 
096         * @param renderer
097         *            a TableCellRenderer for the group.
098         * @param text
099         *            Name of the ColumnGroup which will be displayed when the
100         *            ColumnGroup is rendered.
101         */
102        public ColumnGroup(TableCellRenderer renderer, TableCellEditor tce,
103                        Object cgHeaderObject) {
104
105                // editor stuff:
106                setHeaderEditor(tce);
107                // setHeaderEditor(createDefaultHeaderEditor());
108                isHeaderEditable = true;
109
110                if (renderer == null) {
111                        this.renderer = new DefaultTableCellRenderer() {
112                                public Component getTableCellRendererComponent(JTable table,
113                                                Object value, boolean isSelected, boolean hasFocus,
114                                                int row, int column) {
115                                        JTableHeader header = table.getTableHeader();
116
117                                        if (header != null) {
118                                                setForeground(header.getForeground());
119                                                setBackground(header.getBackground());
120                                                setFont(header.getFont());
121                                        }
122                                        setHorizontalAlignment(JLabel.CENTER);
123                                        setText((value == null) ? "" : value.toString());
124                                        setBorder(UIManager.getBorder("TableHeader.cellBorder"));
125                                        // System.out.println("inside ColumnGroup.java ColumnGroup(renderer, text). 
126                                        //              renderer was null, now renderer: a DefaultTableCellRender");
127                                        return this;
128                                }
129                        };
130                } else {
131                        this.renderer = renderer;
132                        // System.out.println("inside ColumnGroup.java ColumnGroup(renderer, text). 
133                        //              renderer was NOT null, now renderer:"
134                        // + this.renderer.toString());
135
136                }
137                this.cgHeaderObject = cgHeaderObject;
138                v = new Vector<Object>();
139        }
140
141        /**
142         * Add a TableColumn or ColumnGroup object to the ColumnGroup instance.
143         * 
144         * @param obj
145         *            TableColumn or ColumnGroup
146         */
147        public void add(Object obj) {
148                if (obj == null) {
149                        return;
150                }
151                v.addElement(obj);
152        }
153
154        /**
155         * Get the ColumnGroup list containing the required table column.
156         * 
157         * @param g
158         *            vector to populate with the ColumnGroup/s
159         * @param c
160         *            TableColumn
161         * @return Vector containing the ColumnGroup/s
162         */
163        public Vector<ColumnGroup> getColumnGroups(TableColumn c, Vector<ColumnGroup> g) {
164                g.addElement(this);
165                if (v.contains(c)) {
166                        return g;
167                }
168                Iterator<Object> iter = v.iterator();
169                while (iter.hasNext()) {
170                        Object obj = iter.next();
171                        if (obj instanceof ColumnGroup) {
172                                Vector<ColumnGroup> groups = (Vector<ColumnGroup>) ((ColumnGroup) obj).getColumnGroups(c,
173                                                (Vector<ColumnGroup>) g.clone());
174                                if (groups != null) {
175                                        return groups;
176                                }
177                        }
178                }
179                return null;
180        }
181
182        /**
183         * Returns the TableCellRenderer for the ColumnGroup.
184         * 
185         * @return the TableCellRenderer
186         */
187        public TableCellRenderer getHeaderRenderer() {
188                return renderer;
189        }
190
191        /**
192         * Set the TableCellRenderer for this ColumnGroup.
193         * 
194         * @param renderer
195         *            the renderer to use
196         */
197        public void setHeaderRenderer(TableCellRenderer renderer) {
198                if (renderer != null) {
199                        this.renderer = renderer;
200                }
201        }
202
203        /**
204         * Get the ColumnGroup header object.
205         * 
206         * @return cgHeaderObject.
207         */
208        public Object getHeaderValue() {
209                return cgHeaderObject;
210        }
211
212        // TODO fix to only set the right one
213        public void setHeaderValue(Object cgHeaderObject) {
214                this.cgHeaderObject = cgHeaderObject;
215        }
216
217        // public void setHeaderValue(Object cgHeaderValue) {
218        // Object old = this.cgHeaderValue;
219        // this.cgHeaderValue = cgHeaderValue;
220        // firePropertyChange("cgHeaderValue", old, cgHeaderValue);
221        // }
222
223        /**
224         * Get the dimension of this ColumnGroup.
225         * 
226         * @param table
227         *            the table the header is being rendered in
228         * @return the dimension of the ColumnGroup
229         */
230        public Dimension getSize(JTable table) {
231
232                // Component comp = renderer.getTableCellRendererComponent(table,
233                // getHeaderValue(), false, false, -1, -1);
234                // int height = comp.getPreferredSize().height;
235                // FIXME TODO hardcode, temporary...trying to remove all calls to
236                // getTableCellRendererComponent with -1 for col.
237                int height = 17;
238                // System.out.println("derik debug. ColumnGroup getSize. height:" +
239                // height);
240                int width = 0;
241                Iterator<Object> iter = v.iterator();
242                while (iter.hasNext()) {
243                        Object obj = iter.next();
244                        if (obj instanceof TableColumn) {
245                                TableColumn aColumn = (TableColumn) obj;
246                                width += aColumn.getWidth();
247                        } else {
248                                width += ((ColumnGroup) obj).getSize(table).width;
249                        }
250                }
251                return new Dimension(width, height);
252        }
253
254        /**
255         * Sets the margin that ColumnGroup instance will use and all held
256         * TableColumns and/or ColumnGroups.
257         * 
258         * @param margin
259         *            the margin
260         */
261        public void setColumnMargin(int margin) {
262                this.margin = margin;
263                Iterator<Object> iter = v.iterator();
264                while (iter.hasNext()) {
265                        Object obj = iter.next();
266                        if (obj instanceof ColumnGroup) {
267                                ((ColumnGroup) obj).setColumnMargin(margin);
268                        }
269                }
270        }
271
272        public boolean isVisible() {
273                return isVisible;
274        }
275
276        public void setVisible(boolean visible) {
277                isVisible = visible;
278        }
279
280        // methods for editable
281        //
282        public void setHeaderEditor(TableCellEditor headerEditor) {
283
284                this.headerEditor = headerEditor;
285        }
286
287        public TableCellEditor getHeaderEditor() {
288                // FIXME probably need to make a special GroupableTableHeaderCellEditor
289                return headerEditor;
290        }
291
292        public void setHeaderEditable(boolean isEditable) {
293                isHeaderEditable = isEditable;
294        }
295
296        public boolean isHeaderEditable() {
297                return isHeaderEditable;
298        }
299
300        /*
301         * public void copyValues(TableColumn base) {
302         * System.out.println("derik debug. ColumnGroup copyValues start modelIndex:"
303         * +modelIndex); modelIndex = base.getModelIndex(); identifier =
304         * base.getIdentifier(); width = base.getWidth(); minWidth =
305         * base.getMinWidth(); setPreferredWidth(base.getPreferredWidth()); maxWidth
306         * = base.getMaxWidth(); headerRenderer = base.getHeaderRenderer();
307         * headerValue = base.getHeaderValue(); cellRenderer =
308         * base.getCellRenderer(); cellEditor = base.getCellEditor(); isResizable =
309         * base.getResizable();
310         * System.out.println("derik debug. ColumnGroup copyValues end modelIndex:"
311         * +modelIndex); }
312         */
313
314        protected TableCellEditor createDefaultHeaderEditor() {
315                DefaultCellEditor dce = new DefaultCellEditor(new JTextField());
316                return dce;
317        }
318
319}