1/*
2 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @key headful
27 * @bug 6711682
28 * @summary  JCheckBox in JTable: checkbox doesn't alaways respond to the first mouse click
29 * @author Alexander Potochkin
30 * @run main bug6711682
31 */
32
33import javax.swing.*;
34import javax.swing.event.CellEditorListener;
35import javax.swing.table.TableCellEditor;
36import javax.swing.table.TableCellRenderer;
37import java.awt.*;
38import java.awt.event.InputEvent;
39import java.awt.event.KeyEvent;
40import java.util.EventObject;
41
42public class bug6711682 {
43    private static JCheckBox editorCb;
44    private static JCheckBox rendererCb;
45    private static JTable table;
46
47    public static void main(String[] args) throws Exception {
48        Robot robot = new Robot();
49        robot.setAutoDelay(50);
50        SwingUtilities.invokeAndWait(new Runnable() {
51            public void run() {
52                createAndShowGUI();
53            }
54        });
55        robot.waitForIdle();
56        Point l = table.getLocationOnScreen();
57        int h = table.getRowHeight();
58        for (int i = 0; i < 3; i++) {
59            robot.mouseMove(l.x + 5, l.y + 5 + i * h);
60            robot.mousePress(InputEvent.BUTTON1_MASK);
61            robot.mouseRelease(InputEvent.BUTTON1_MASK);
62        }
63        // Without pressing F2 the last table's cell
64        // reported <code>false</code> value
65        // note that I can't press it inside the for loop
66        // because it doesn't reproduce the bug
67        robot.keyPress(KeyEvent.VK_F2);
68        robot.keyRelease(KeyEvent.VK_F2);
69
70        for (int i = 0; i < 3; i++) {
71            if (!Boolean.TRUE.equals(table.getValueAt(i, 0))) {
72                throw new RuntimeException("Row #" + i + " checkbox is not selected");
73            }
74        }
75        for (int i = 2; i >= 0; i--) {
76            robot.mouseMove(l.x + 5, l.y + 5 + i * h);
77            robot.mousePress(InputEvent.BUTTON1_MASK);
78            robot.mouseRelease(InputEvent.BUTTON1_MASK);
79        }
80        robot.keyPress(KeyEvent.VK_F2);
81        robot.keyRelease(KeyEvent.VK_F2);
82        for (int i = 0; i < 3; i++) {
83            if (Boolean.TRUE.equals(table.getValueAt(i, 0))) {
84                throw new RuntimeException("Row #" + i + " checkbox is selected");
85            }
86        }
87    }
88
89    private static void createAndShowGUI() {
90        editorCb = new JCheckBox();
91        rendererCb = new JCheckBox();
92        JFrame f = new JFrame("Table with CheckBox");
93        Container p = f.getContentPane();
94        p.setLayout(new BorderLayout());
95        table = new JTable(new Object[][]{{false}, {false}, {false}}, new Object[]{"CheckBox"});
96        TableCellEditor editor = new TableCellEditor() {
97            int editedRow;
98
99            public Component getTableCellEditorComponent(JTable table,
100                                                         Object value, boolean isSelected, int row, int column) {
101                this.editedRow = row;
102                editorCb.setSelected(Boolean.TRUE.equals(value));
103                editorCb.setBackground(UIManager.getColor("Table.selectionBackground"));
104                return editorCb;
105            }
106
107            public void addCellEditorListener(CellEditorListener l) {
108            }
109
110            public void cancelCellEditing() {
111            }
112
113            public Object getCellEditorValue() {
114                return editorCb.isSelected();
115            }
116
117            public boolean isCellEditable(EventObject anEvent) {
118                return true;
119            }
120
121            public void removeCellEditorListener(CellEditorListener l) {
122            }
123
124            public boolean shouldSelectCell(EventObject anEvent) {
125                return true;
126            }
127
128            public boolean stopCellEditing() {
129                table.getModel().setValueAt(editorCb.isSelected(), editedRow, 0);
130                return true;
131            }
132        };
133        table.getColumnModel().getColumn(0).setCellEditor(editor);
134
135        TableCellRenderer renderer = new TableCellRenderer() {
136            public Component getTableCellRendererComponent(JTable table,
137                                                           Object value, boolean isSelected, boolean hasFocus,
138                                                           int row, int column) {
139                rendererCb.setSelected(Boolean.TRUE.equals(value));
140                return rendererCb;
141            }
142        };
143        table.getColumnModel().getColumn(0).setCellRenderer(renderer);
144
145        p.add(table, BorderLayout.CENTER);
146
147        f.pack();
148        f.setVisible(true);
149    }
150}
151