001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ecoinformatics.seek.ecogrid;
031
032import java.awt.BorderLayout;
033import java.awt.Color;
034import java.awt.Component;
035import java.awt.Dimension;
036import java.awt.Font;
037import java.awt.event.ItemEvent;
038import java.awt.event.ItemListener;
039import java.util.Vector;
040
041import javax.swing.JCheckBox;
042import javax.swing.JLabel;
043import javax.swing.JPanel;
044import javax.swing.JTable;
045import javax.swing.border.LineBorder;
046import javax.swing.table.TableCellRenderer;
047
048import org.apache.commons.logging.Log;
049import org.apache.commons.logging.LogFactory;
050
051/**
052 * This class will render a table cell as panel - label + a check box
053 * 
054 * @author Jing Tao
055 * 
056 */
057
058public class CheckBoxTableCellRenderer implements TableCellRenderer {
059
060        private static final int FONTSIZE = 12;
061        private static final String FONTNAME = "TableCellText";
062        private static final char SEPERATOR = '.';
063
064        public static final int DEFAUTTOPROW = -1;
065
066        private JTable jTable = null;
067        private JTable topTable = null;
068        private Vector selectedServiceList = null;
069        private int topRowNum = DEFAUTTOPROW;
070        private static Log log;
071        private static boolean isDebugging;
072
073        static {
074                log = LogFactory
075                                .getLog("org.ecoinformatics.seek.ecogrid.CheckBoxTableCellRenderer");
076                isDebugging = log.isDebugEnabled();
077        }
078
079        /**
080         * Default Constructor
081         */
082        public CheckBoxTableCellRenderer(JTable topTable,
083                        Vector selectedServiceList, int topRowNum) {
084                this.topTable = topTable;
085                this.selectedServiceList = selectedServiceList;
086                this.topRowNum = topRowNum;
087
088        }// CheckBoxTableCellRenderer
089
090        public Component getTableCellRendererComponent(JTable table, Object value,
091                        boolean isSelected, boolean hasFocus, int row, int column) {
092                jTable = table;
093
094                JPanel cellPanel = new JPanel();
095                cellPanel.setBorder(new LineBorder(Color.lightGray, 1));
096                cellPanel.setBackground(Color.WHITE);
097                cellPanel.setPreferredSize(new Dimension(
098                                ServicesDisplayPanel.CELLPREFERREDWIDTH,
099                                ServicesDisplayPanel.HEIGHT));
100
101                SelectableDocumentType selectedDocumentType = null;
102                boolean isChecked = false;
103                boolean isEnable = true;
104                String text = null;
105                if (value != null && value instanceof SelectableObjectInterface) {
106                        SelectableObjectInterface selectedObj = (SelectableObjectInterface) value;
107                        text = selectedObj.getSelectableObjectLabel();
108                        isChecked = selectedObj.getIsSelected();
109                        isEnable = selectedObj.getEnabled();
110                }
111
112                /*
113                 * label = (JLabel)renderer.getTableCellRendererComponent(table, text,
114                 * isSelected, hasFocus, row, column);
115                 */
116                JLabel label = new JLabel(text);
117                label.setFont(new Font(FONTNAME, Font.PLAIN, FONTSIZE));
118                label.setPreferredSize(new Dimension(
119                                ServicesDisplayPanel.LABELPREFERWIDTH,
120                                ServicesDisplayPanel.HEIGHT));
121                // set a check box name
122                String checkBoxName = "" + topRowNum + SEPERATOR + row;
123                JCheckBox checkBox = new JCheckBox();
124                checkBox.setName(checkBoxName);
125                checkBox.setBackground(Color.WHITE);
126                checkBox.setSelected(isChecked);
127                CheckBoxListener listener = new CheckBoxListener();
128                checkBox.addItemListener(listener);
129                // checkBox.setEnabled(false);
130
131                /*
132                 * if (topRowNum != DEFAUTTOPROW ) { // for sub table we need to set up
133                 * check box enable status checkBox.setEnabled(isEnable); }//if
134                 */
135
136                // add the label and checkbox to jpanel which has a border layout
137                // manager
138                BorderLayout layoutManager = new BorderLayout();
139                cellPanel.setLayout(layoutManager);
140                cellPanel.add(label, BorderLayout.CENTER);
141                cellPanel.add(checkBox, BorderLayout.WEST);
142                return cellPanel;
143        }// getTableCellRender
144
145        /*
146         * This method will parse a checkbox name string "topRowNumber.rowNumber"
147         * for top table, topNumber should be -1 and rowNumber is the service
148         * vector's element number. For the subtable(documentType), the topRowNumber
149         * is service'vector element number and row number is array number in
150         * document type array
151         */
152        private RowNumberObject parseCheckBoxName(String checkBoxName) {
153                RowNumberObject rowNumberObj = null;
154                try {
155                        if (checkBoxName != null) {
156                                checkBoxName = checkBoxName.trim();
157                                int seperatorPosition = checkBoxName.indexOf(SEPERATOR);
158                                String topRowStr = checkBoxName.substring(0, seperatorPosition);
159                                String rowStr = checkBoxName.substring(seperatorPosition + 1,
160                                                checkBoxName.length());
161                                if (isDebugging) {
162                                        log.debug("The top row number is " + topRowStr);
163                                        log.debug("The row number is " + rowStr);
164                                }
165                                int topRow = (new Integer(topRowStr)).intValue();
166                                int row = (new Integer(rowStr)).intValue();
167                                rowNumberObj = new RowNumberObject(topRow, row);
168                        }
169                } catch (Exception e) {
170                        log.debug("Couldn't parse check box name ", e);
171                }
172                return rowNumberObj;
173        }
174
175        /*
176         * When use checked serviceName checkbox, every document type which belong
177         * to thsi serviceName should checked and checkbox will be disalbed
178         */
179        private void checkAllDocumentTypes(int rowNumber) {
180                boolean checked = true;
181                handleAllDocumentTypes(rowNumber, checked);
182        }// checkedAllDocumentTypes
183
184        /*
185         * When user unchecked serviceName checkbox, every document type which
186         * belong to this serviceName should be unchecked and checkbox will be
187         * enable
188         */
189        private void uncheckAllDocumentTypes(int rowNumber) {
190                boolean checked = false;
191                handleAllDocumentTypes(rowNumber, checked);
192        }// uncheckedAllDocumentTypes
193
194        /*
195         * This method will handle check and unchecked, enable and disable document
196         * types checkbox
197         */
198        private void handleAllDocumentTypes(int rowNumber, boolean checked) {
199                SelectableEcoGridService service = (SelectableEcoGridService) selectedServiceList
200                                .elementAt(rowNumber);
201                // set boolean value for every document list
202                SelectableDocumentType[] typeList = service
203                                .getSelectableDocumentTypeList();
204                if (typeList != null) {
205                        int length = typeList.length;
206                        // change the tableModel value for documenttype list
207                        for (int i = 0; i < length; i++) {
208                                SelectableDocumentType type = typeList[i];
209                                if (type != null) {
210                                        type.setIsSelected(checked);
211                                        // type.setEnabled(checked);
212                                }// if
213                        }// for
214                        // repaint table
215                        if (jTable != null) {
216                                jTable.repaint();
217                        }
218                }// if
219
220        }// handleAllDocumentTypes
221
222        /* Class to listen for ItemEvents */
223        private class CheckBoxListener implements ItemListener {
224                public void itemStateChanged(ItemEvent event) {
225                        Object object = event.getItemSelectable();
226                        JCheckBox checkBox = (JCheckBox) object;
227                        String checkBoxName = checkBox.getName();
228                        RowNumberObject rowNumberObj = parseCheckBoxName(checkBoxName);
229                        int topRowNumber = -1;
230                        int rowNumber = 0;
231                        if (rowNumberObj != null) {
232                                topRowNumber = rowNumberObj.getTopRowNumber();
233                                rowNumber = rowNumberObj.getRowNumber();
234                        }
235
236                        SelectableEcoGridService service = null;
237                        if (topRowNumber == DEFAUTTOPROW) {
238                                // this is for top table cell(serive Name)
239                                service = (SelectableEcoGridService) selectedServiceList
240                                                .elementAt(rowNumber);
241                                if (service != null) {
242                                        SelectableServiceName serviceName = service
243                                                        .getSelectableServiceName();
244                                        if (serviceName != null) {
245                                                if (serviceName.getIsSelected()) {
246                                                        serviceName.setIsSelected(false);
247                                                        uncheckAllDocumentTypes(rowNumber);
248                                                } else {
249                                                        serviceName.setIsSelected(true);
250                                                        checkAllDocumentTypes(rowNumber);
251                                                }
252                                                service.setSelectableServiceName(serviceName);
253                                        }// if
254                                }// if
255                        }// if
256                        else {
257                                // this is for sub table cell(document type array
258                                service = (SelectableEcoGridService) selectedServiceList
259                                                .elementAt(topRowNumber);
260                                SelectableDocumentType[] docTypeList = service
261                                                .getSelectableDocumentTypeList();
262                                SelectableDocumentType docType = null;
263                                if (docTypeList != null) {
264                                        docType = docTypeList[rowNumber];
265                                        if (docType != null) {
266                                                if (docType.getIsSelected()) {
267                                                        docType.setIsSelected(false);
268                                                } else {
269                                                        docType.setIsSelected(true);
270                                                }
271                                        }
272                                        // if all document type are unselected then we will
273                                        // unselected
274                                        // service name and make document type selectiong box
275                                        // disable
276                                        if (isAllDocTypeUnSelected(docTypeList)) {
277
278                                                SelectableServiceName serviceName = service
279                                                                .getSelectableServiceName();
280                                                serviceName.setIsSelected(false);
281                                                service.setSelectableServiceName(serviceName);
282                                                SelectableDocumentType[] typeLists = service
283                                                                .getSelectableDocumentTypeList();
284                                                int length = typeLists.length;
285                                                for (int i = 0; i < length; i++) {
286                                                        SelectableDocumentType type = typeLists[i];
287                                                        // type.setEnabled(false);
288                                                }
289
290                                                if (topTable != null) {
291                                                        topTable.repaint();
292                                                }
293                                        } else if (!(service.getSelectableServiceName()
294                                                        .getIsSelected())) {
295                                                // if we selected a doctype, but service name is not
296                                                // selected
297                                                // we should set up service selected
298                                                service.getSelectableServiceName().setIsSelected(true);
299                                                if (topTable != null) {
300                                                        topTable.repaint();
301                                                }
302                                        }
303                                }// if
304                        }// else
305                }// itemStateChanged
306
307        }// CheckBoxListner
308
309        /*
310         * This method will to make sure if all document type in a service are
311         * unselected
312         */
313        private boolean isAllDocTypeUnSelected(SelectableDocumentType[] docTypeList) {
314                boolean allUnSelected = true;
315                if (docTypeList == null) {
316                        return allUnSelected;
317                }
318
319                int size = docTypeList.length;
320                for (int i = 0; i < size; i++) {
321                        SelectableDocumentType type = docTypeList[i];
322                        if (type.getIsSelected()) {
323                                allUnSelected = false;
324                                break;
325                        }
326                }
327                return allUnSelected;
328        }
329
330        /*
331         * This class represents a object which inclue both topRowNumber and
332         * rowNumber If topRowNumber is -1, this means it is top table cell and row
333         * number is service vector's element number. If the topRowNumber is not -1,
334         * then the topRowNumber will be service vector's element number, the
335         * rowNumber now will be the array number in documentType in one service
336         */
337        private class RowNumberObject {
338                private int topRowNumber = -1;
339                private int rowNumber = 0;
340
341                /**
342                 * Contructor of RowNumberObject
343                 * 
344                 * @param topRowNumber
345                 *            int
346                 * @param rowNumber
347                 *            int
348                 */
349                public RowNumberObject(int topRowNumber, int rowNumber) {
350                        this.topRowNumber = topRowNumber;
351                        this.rowNumber = rowNumber;
352                }// RowNumberObject
353
354                /**
355                 * Method to get top row number
356                 * 
357                 * @return int
358                 */
359                public int getTopRowNumber() {
360                        return topRowNum;
361                }// getTopRowNumber
362
363                /**
364                 * Method to get row number
365                 * 
366                 * @return int
367                 */
368                public int getRowNumber() {
369                        return rowNumber;
370                }// getRowNumber
371        }// RowNumberObject
372
373}// CheckBoxForSubTableListner