001/**
002 *  '$Author: barseghian $'
003 *  '$Date: 2010-06-24 00:25:10 +0000 (Thu, 24 Jun 2010) $'
004 *  '$Revision: 24970 $'
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.Rectangle;
030import java.util.EventObject;
031import java.util.Iterator;
032
033import javax.swing.JTable;
034import javax.swing.event.CellEditorListener;
035import javax.swing.event.ChangeEvent;
036import javax.swing.table.JTableHeader;
037import javax.swing.table.TableCellEditor;
038import javax.swing.table.TableColumn;
039
040import org.kepler.workflowrunmanager.WRMDefaults;
041
042/**
043 * ColumnGroup, GroupableTableColumnModel, GroupableTableHeader,
044 * GroupableTableHeaderUI and GroupableTableCellRenderer taken from a post by
045 * Steve Webb (16/09/04). He extended code originally posted by Nobuo Tamemasa. Many thanks
046 * to both authors. I've made some changes, including making the headers 
047 * editable.
048 * 
049 */
050
051/**
052 * This is the object which manages the header of the JTable and also provides
053 * functionality for groupable headers.
054 */
055public class GroupableTableHeader extends JTableHeader implements
056                CellEditorListener {
057
058        public static final int HEADER_ROW = -10;
059        transient protected int editingColumn;
060        transient protected TableCellEditor cellEditor;
061        transient protected Component editorComp;
062
063        private WRMDefaults wrmdefaults = WRMDefaults.getInstance();
064
065        /**
066         * Constructs a GroupableTableHeader which is initialized with cm as the
067         * column model. If cm is null this method will initialize the table header
068         * with a default TableColumnModel.
069         * 
070         * @param model
071         *            the column model for the table
072         */
073        public GroupableTableHeader(GroupableTableColumnModel model) {
074                super(model);
075                setUI(new GroupableTableHeaderUI());
076                cellEditor = null;
077                // setDefaultEditor(Date.class, new JDateChooserCellEditor());
078                // setReorderingAllowed(false);
079                // recreateTableColumn(model);
080        }
081
082        /**
083         * Sets the margins correctly for all groups within the header.
084         */
085        public void setColumnMargin() {
086                int columnMargin = getColumnModel().getColumnMargin();
087                Iterator<ColumnGroup> iter = ((GroupableTableColumnModel) columnModel)
088                                .columnGroupIterator();
089                while (iter.hasNext()) {
090                        ColumnGroup cGroup = iter.next();
091                        cGroup.setColumnMargin(columnMargin);
092                }
093        }
094
095        // 
096        /*
097         * protected void recreateTableColumn(GroupableTableColumnModel columnModel)
098         * { int n = columnModel.getColumnCount(); EditableHeaderTableColumn[]
099         * newCols = new EditableHeaderTableColumn[n]; TableColumn[] oldCols = new
100         * TableColumn[n]; for (int i=0;i<n;i++) { oldCols[i] =
101         * columnModel.getColumn(i); newCols[i] = new EditableHeaderTableColumn();
102         * newCols[i].copyValues(oldCols[i]); } for (int i=0;i<n;i++) {
103         * columnModel.removeColumn(oldCols[i]); } for (int i=0;i<n;i++) {
104         * columnModel.addColumn(newCols[i]); } }
105         */
106
107        public void editingCanceled(ChangeEvent e) {
108                removeEditor();
109        }
110
111        public void editingStopped(ChangeEvent e) {
112
113                TableCellEditor editor = getCellEditor();
114                if (editor != null) {
115                        Object value = editor.getCellEditorValue();
116                        int index = getEditingColumn();
117                        int realColumnIndex = getTable().convertColumnIndexToModel(index);
118                        // TODO change instead the appropriate part of header
119                        GroupableTableColumnModel columnModel = (GroupableTableColumnModel) getColumnModel();
120                        // need to use realColumnIndex here
121                        columnModel.getColumnGroup(realColumnIndex).setHeaderValue(value);
122                        removeEditor();
123                }
124                
125        }
126
127        public void removeEditor() {
128
129                TableCellEditor editor = getCellEditor();
130                if (editor != null) {
131                        editor.removeCellEditorListener(this);
132
133                        // requestFocus(); //discouraged because platform dependent behavior
134                        // boolean requestFocusInWindow = requestFocusInWindow(); //never
135                        // works
136
137                        remove(editorComp);
138
139                        int index = getEditingColumn();
140                        Rectangle cellRect = getHeaderRect(index);
141
142                        setCellEditor(null);
143                        setEditingColumn(index);
144                        // setEditingColumn(-1);
145                        editorComp = null;
146
147                        repaint(cellRect);
148                        // paintComponent(editorComp);
149                }
150        }
151
152        /*
153         * public boolean editCellAt(int index) { return editCellAt(index); }
154         */
155
156        public boolean editCellAt(int index, EventObject e) {
157
158                if (cellEditor != null && !cellEditor.stopCellEditing()) {
159                        return false;
160                }
161                if (!isCellEditable(index)) {
162                        return false;
163                }
164
165                // int realColumnIndex = getTable().convertColumnIndexToModel(index);
166                // int columnIndex = columnModel.getColumn(index).getModelIndex();
167                TableCellEditor editor = getCellEditor(index);
168
169                if (editor != null && editor.isCellEditable(e)) {
170                        // TODO check this is right:
171                        editorComp = prepareEditor(editor, index);
172                        editorComp.setBounds(getHeaderRect(index));
173                        add(editorComp);
174                        editorComp.validate();
175                        setCellEditor(editor);
176                        // GroupableTableColumnModel columnModel =
177                        // (GroupableTableColumnModel) getColumnModel();
178                        // columnIndex = columnModel.getColumn(index).getModelIndex();
179                        // setEditingColumn(columnIndex);
180                        setEditingColumn(index); // should use index
181                        editor.addCellEditorListener(this);
182                        return true;
183                }
184                return false;
185        }
186
187        public boolean isCellEditable(int index) {
188
189                if (getReorderingAllowed()) {
190                        ///System.out.println("GroupableTableHeader isCellEditable("+index+"). getReorderingAllowed():"+getReorderingAllowed());
191                        // return false;
192                }
193                // int columnIndex = columnModel.getColumn(index).getModelIndex();
194                // EditableHeaderTableColumn col =
195                // (EditableHeaderTableColumn)columnModel.getColumn(columnIndex);
196
197                // System.out.println("GroupableTableHeader isCellEditable("+index+") returning "
198                // + col.isHeaderEditable());
199
200                // FIXME hardcode
201                return true;
202
203                // return col.isHeaderEditable();
204        }
205
206        public TableCellEditor getCellEditor() {
207                return cellEditor;
208        }
209
210        public TableCellEditor getCellEditor(int index) {
211
212                GroupableTableColumnModel columnModel = (GroupableTableColumnModel) getColumnModel();
213                TableColumn aColumn = columnModel.getColumn(index);
214                Iterator<ColumnGroup> iter = columnModel.getColumnGroups(aColumn);
215                if (iter != null) {
216                        // FIXME get rid of loop, only return appropriate thing
217                        while (iter.hasNext()) {
218                                ColumnGroup cGroup = iter.next();
219                                TableCellEditor tce = cGroup.getHeaderEditor();
220                                // System.out.println("GroupableTableHeader getCellEditor("+index+")"+"
221                                // cGroup.getHeaderValue().toString():"+
222                                return tce;
223                        }
224                }
225
226                // return col.getHeaderEditor();
227                return null;
228        }
229
230        public int getEditingColumn() {
231                return editingColumn;
232        }
233
234        public void setEditingColumn(int aColumn) {
235                editingColumn = aColumn;
236        }
237
238        public void setCellEditor(TableCellEditor newEditor) {
239                TableCellEditor oldEditor = cellEditor;
240                cellEditor = newEditor;
241
242                // firePropertyChange
243
244                if (oldEditor != null) {
245                        ((TableCellEditor) oldEditor)
246                                        .removeCellEditorListener((CellEditorListener) this);
247                }
248                if (newEditor != null) {
249                        ((TableCellEditor) newEditor)
250                                        .addCellEditorListener((CellEditorListener) this);
251                }
252
253        }
254
255        public Component getEditorComponent() {
256                return editorComp;
257        }
258
259        public Component prepareEditor(TableCellEditor editor, int index) {
260
261                // GroupableTableColumnModel columnModel =
262                // (GroupableTableColumnModel)getColumnModel();
263                // Object value = columnModel.getColumn(index).getHeaderValue();
264                // System.out.println("value.toString():" + value.toString());
265
266                Object value = null;
267                GroupableTableColumnModel columnModel = (GroupableTableColumnModel) getColumnModel();
268                TableColumn aColumn = columnModel.getColumn(index);
269                Iterator<ColumnGroup> iter = columnModel.getColumnGroups(aColumn);
270                if (iter != null) {
271                        // FIXME get rid of loop, only return appropriate thing
272                        while (iter.hasNext()) {
273                                ColumnGroup cGroup = iter.next();
274                                value = cGroup.getHeaderValue();
275                                if (wrmdefaults.containsName(value.toString())) {
276                                        value = "";
277                                }
278                        }
279                }
280
281                boolean isSelected = true;
282                int row = HEADER_ROW;
283                JTable table = getTable();
284
285                Component comp = editor.getTableCellEditorComponent(table, value,
286                                isSelected, row, index);
287                // Component comp = editor.getTableCellEditorComponent(table, value,
288                // isSelected, row, wrmdefaultsRealColumnIndex);
289                // if (comp instanceof JComponent) {
290                // ((JComponent) comp).setNextFocusableComponent(this); //deprecated as
291                // of 1.4
292                // }
293                return comp;
294        }
295
296}