001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.ui.view;
042:
043: import java.awt.Color;
044: import java.awt.Component;
045: import java.awt.GridBagConstraints;
046: import java.awt.GridBagLayout;
047: import java.awt.Point;
048: import java.awt.Rectangle;
049: import java.awt.event.ItemEvent;
050: import java.awt.event.ItemListener;
051: import java.awt.event.MouseEvent;
052: import java.util.ArrayList;
053: import java.util.Enumeration;
054: import java.util.EventObject;
055: import java.util.List;
056:
057: import javax.swing.BorderFactory;
058: import javax.swing.ImageIcon;
059: import javax.swing.JCheckBox;
060: import javax.swing.JComponent;
061: import javax.swing.JLabel;
062: import javax.swing.JOptionPane;
063: import javax.swing.JTree;
064: import javax.swing.event.CellEditorListener;
065: import javax.swing.tree.DefaultTreeCellRenderer;
066: import javax.swing.tree.TreeCellEditor;
067: import javax.swing.tree.TreeCellRenderer;
068: import javax.swing.tree.TreePath;
069:
070: import net.java.hulp.i18n.Logger;
071: import org.netbeans.modules.etl.logger.Localizer;
072: import org.netbeans.modules.etl.logger.LogUtil;
073: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
074: import org.netbeans.modules.sql.framework.model.SQLDBTable;
075:
076: /**
077: * @author Jonathan Giron
078: * @version $Revision$
079: */
080: public class TableColumnTreeCellEditor extends JComponent implements
081: TreeCellEditor {
082: private static transient final Logger mLogger = LogUtil
083: .getLogger(TableColumnTreeCellEditor.class.getName());
084: private static transient final Localizer mLoc = Localizer.get();
085:
086: /**
087: * Class CheckBoxItemListener listens for checkbox changes.
088: */
089: private class CheckBoxItemListener implements ItemListener {
090:
091: private void selectTableAndColumn(boolean isSelected) {
092: Enumeration e = node.children();
093: while (e.hasMoreElements()) {
094: TableColumnNode child = (TableColumnNode) e
095: .nextElement();
096: if (child.isEnabled()) {
097: child.setSelected(isSelected);
098: }
099: }
100: node.setSelected(isSelected);
101: }
102:
103: /**
104: * Invoked when an item has been selected or deselected by the user. The code
105: * written for this method performs the operations that need to occur when an item
106: * is selected (or deselected).
107: *
108: * @param e ItemEvent to handle
109: */
110: public void itemStateChanged(ItemEvent e) {
111: boolean isSelected = (e.getStateChange() == ItemEvent.SELECTED);
112:
113: if (node.getUserObject() instanceof SQLDBTable) {
114: if (!isSelected) {
115: String nbBundle1 = mLoc
116: .t("PRSR001: All links to and from the table will be lost. Are you sure you want to deselect all table columns?");
117: String message = Localizer.parse(nbBundle1);
118: String nbBundle2 = mLoc
119: .t("PRSR001: Confirm deselect all");
120: String header = Localizer.parse(nbBundle2);
121: int response = JOptionPane.showConfirmDialog(
122: parent, message, header,
123: JOptionPane.YES_OPTION);
124: if (response == JOptionPane.YES_OPTION) {
125: selectTableAndColumn(isSelected);
126: }
127: } else {
128: selectTableAndColumn(isSelected);
129: }
130: } else if (node.getUserObject() instanceof SQLDBColumn) {
131: node.setSelected(isSelected);
132: TableColumnNode tableNode = (TableColumnNode) node
133: .getParent();
134: if (tableNode != null) {
135: tableNode.setSelectedBasedOnChildren();
136: }
137: }
138:
139: if (tree != null) {
140: tree.repaint();
141: }
142: }
143:
144: }
145:
146: /** Parent dialog **/
147: private JComponent parent = null;
148:
149: /** Color to use for the background when the node isn't selected. */
150: protected Color backgroundNonSelectionColor;
151:
152: /** Color to use for the background when a node is selected. */
153: protected Color backgroundSelectionColor;
154:
155: /** Color to use for the focus indicator when the node has focus. */
156: protected Color borderSelectionColor;
157:
158: /** True if has focus. */
159: protected boolean hasFocus;
160:
161: /**
162: * Used in editing. Indicates x position to place <code>editingComponent</code>.
163: */
164: protected transient int offset;
165:
166: /** Is the value currently selected. */
167: protected boolean selected;
168:
169: /** Color to use for the foreground for non-selected nodes. */
170: protected Color textNonSelectionColor;
171:
172: // Colors
173: /** Color to use for the foreground for selected nodes. */
174: protected Color textSelectionColor;
175:
176: /** Checkbox indicating selection state */
177: //private JCheckBox checkBox;
178: private transient int lastRow;
179:
180: private List listeners = new ArrayList();
181:
182: private TableColumnNode node;
183:
184: private JTree tree;
185:
186: /**
187: * Constructor TableColumnTreeCellEditor constructs this object.
188: */
189: public TableColumnTreeCellEditor(JComponent prnt) {
190: this .parent = prnt;
191: }
192:
193: /**
194: * @see javax.swing.CellEditor#addCellEditorListener(CellEditorListener)
195: */
196: public void addCellEditorListener(CellEditorListener l) {
197: if (!listeners.contains(l)) {
198: listeners.add(l);
199: }
200: }
201:
202: /**
203: * @see javax.swing.CellEditor#cancelCellEditing()
204: */
205: public void cancelCellEditing() {
206: }
207:
208: /**
209: * Returns the background color to be used for non selected nodes.
210: *
211: * @return Color for the nonselection color
212: */
213: public Color getBackgroundNonSelectionColor() {
214: return backgroundNonSelectionColor;
215: }
216:
217: /**
218: * Returns the color to use for the background if node is selected.
219: *
220: * @return Color is the new background selection color.
221: */
222: public Color getBackgroundSelectionColor() {
223: return backgroundSelectionColor;
224: }
225:
226: /**
227: * Returns the color the border is drawn.
228: *
229: * @return Color of the border selection
230: */
231: public Color getBorderSelectionColor() {
232: return borderSelectionColor;
233: }
234:
235: /**
236: * @see javax.swing.CellEditor#getCellEditorValue()
237: */
238: public Object getCellEditorValue() {
239: return (node != null) ? node.getUserObject() : null;
240: }
241:
242: /**
243: * Returns the color the text is drawn with when the node isn't selected.
244: *
245: * @return Color of the text non selection.
246: */
247: public Color getTextNonSelectionColor() {
248: return textNonSelectionColor;
249: }
250:
251: /**
252: * Returns the color the text is drawn with when the node is selected.
253: *
254: * @return Color of text selection
255: */
256: public Color getTextSelectionColor() {
257: return textSelectionColor;
258: }
259:
260: /**
261: * @see javax.swing.tree.TreeCellEditor#getTreeCellEditorComponent(JTree, Object,
262: * boolean, boolean, boolean, int)
263: */
264: public Component getTreeCellEditorComponent(JTree aTree,
265: Object value, boolean isSelected, boolean expanded,
266: boolean leaf, int row) {
267: setTree(aTree);
268:
269: DefaultTreeCellRenderer dtc = new DefaultTreeCellRenderer();
270: dtc.setComponentOrientation(tree.getComponentOrientation());
271:
272: JLabel label = (JLabel) dtc.getTreeCellRendererComponent(aTree,
273: value, selected, expanded, leaf, row, hasFocus);
274:
275: node = null;
276: if (value instanceof TableColumnNode) {
277: node = (TableColumnNode) value;
278: }
279: if (node == null) {
280: return label;
281: }
282:
283: this .removeAll();
284: this .setLayout(new GridBagLayout());
285: this .setBackground(label.getBackground());
286: JCheckBox checkBox = new JCheckBox();
287: checkBox.setBorder(BorderFactory.createEmptyBorder(2, 1, 2, 2));
288: checkBox.addItemListener(new CheckBoxItemListener());
289: checkBox.setBackground(label.getBackground());
290:
291: GridBagConstraints gc = new GridBagConstraints();
292: gc.weightx = 0.0;
293: gc.weighty = 0.0;
294: gc.anchor = GridBagConstraints.LINE_START;
295: gc.fill = GridBagConstraints.NONE;
296: gc.gridwidth = 1;
297: this .add(checkBox, gc);
298:
299: gc = new GridBagConstraints();
300: gc.weightx = 1.0;
301: gc.weighty = 0.0;
302: gc.anchor = GridBagConstraints.LINE_START;
303: gc.fill = GridBagConstraints.HORIZONTAL;
304: gc.gridwidth = 1;
305: this .add(label, gc);
306:
307: label.setText(node.getName());
308: label.setIcon(new ImageIcon(node.getIcon(0)));
309: checkBox.setSelected(node.isSelected());
310:
311: if (!node.isEnabled()) {
312: checkBox.setEnabled(false);
313: checkBox.setFocusable(false);
314: label.setEnabled(false);
315: label.setFocusable(false);
316: } else {
317: checkBox.setEnabled(true);
318: checkBox.setFocusable(true);
319: }
320: return this ;
321: }
322:
323: /**
324: * @see javax.swing.CellEditor#isCellEditable(EventObject)
325: */
326: public boolean isCellEditable(EventObject anEvent) {
327: if (anEvent != null && anEvent instanceof MouseEvent
328: && (((MouseEvent) anEvent).getClickCount() == 1)
329: && isMouseClickOnCheckBox(((MouseEvent) anEvent))) {
330: return true;
331: }
332: return false;
333: }
334:
335: /**
336: * method isMouseClickOnCheckBox returns true if the mouse event is clicked on a
337: * checkbox.
338: *
339: * @param event is the mouse event to be used.
340: * @return boolean true if the mouse is checked.
341: */
342: public boolean isMouseClickOnCheckBox(MouseEvent event) {
343: if (event != null) {
344: if (event.getSource() instanceof JTree) {
345: setTree((JTree) event.getSource());
346: TreeCellRenderer renderer = tree.getCellRenderer();
347: if (renderer instanceof TableColumnTreeCellRenderer) {
348: if (lastRow != -1 && tree != null) {
349: TreePath path = tree.getUI()
350: .getClosestPathForLocation(tree,
351: event.getX(), event.getY());
352: Rectangle bounds = tree.getUI().getPathBounds(
353: tree, path);
354: Point p = event.getPoint();
355:
356: if (bounds.contains(p)) {
357: p.x = p.x - bounds.x;
358: p.y = p.y - bounds.y;
359: }
360:
361: return ((TableColumnTreeCellRenderer) renderer)
362: .isMouseClickOnCheckBox(p);
363: }
364: }
365: }
366: }
367: return true;
368: }
369:
370: /**
371: * method isMouseClickOnCheckBox is used to determine if the user has clicked the
372: * mouse on the checkbox.
373: *
374: * @param p is the point to check
375: * @return boolean true if the user has clicked on the checkbox.
376: */
377: //public boolean isMouseClickOnCheckBox(Point p) {
378: // return checkBox.contains(p);
379: //}
380: /**
381: * @see javax.swing.CellEditor#removeCellEditorListener(CellEditorListener)
382: */
383: public void removeCellEditorListener(CellEditorListener l) {
384: listeners.remove(l);
385: }
386:
387: /**
388: * Sets the background color to be used for non selected nodes.
389: *
390: * @param newColor is the new color for background nonselection
391: */
392: public void setBackgroundNonSelectionColor(Color newColor) {
393: backgroundNonSelectionColor = newColor;
394: }
395:
396: /**
397: * Sets the color to use for the background if node is selected.
398: *
399: * @param newColor is the new background selection color to use.
400: */
401: public void setBackgroundSelectionColor(Color newColor) {
402: backgroundSelectionColor = newColor;
403: }
404:
405: /**
406: * Sets the color to use for the border.
407: *
408: * @param newColor is the new color for border selection
409: */
410: public void setBorderSelectionColor(Color newColor) {
411: borderSelectionColor = newColor;
412: }
413:
414: /**
415: * Sets the color the text is drawn with when the node isn't selected.
416: *
417: * @param newColor is the new color for text nonselection
418: */
419: public void setTextNonSelectionColor(Color newColor) {
420: textNonSelectionColor = newColor;
421: }
422:
423: /**
424: * Sets the color the text is drawn with when the node is selected.
425: *
426: * @param newColor is the new color for text selection
427: */
428: public void setTextSelectionColor(Color newColor) {
429: textSelectionColor = newColor;
430: }
431:
432: /**
433: * @see javax.swing.CellEditor#shouldSelectCell(EventObject)
434: */
435: public boolean shouldSelectCell(EventObject anEvent) {
436: return true;
437: }
438:
439: /**
440: * @see javax.swing.CellEditor#stopCellEditing()
441: */
442: public boolean stopCellEditing() {
443: return true;
444: }
445:
446: /**
447: * Returns true if the passed in location is a valid mouse location to start editing
448: * from. This is implemented to return false if <code>x</code> is <= the width of
449: * the icon and icon gap displayed by the renderer. In other words this returns true
450: * if the user clicks over the text part displayed by the renderer, and false
451: * otherwise.
452: *
453: * @param x the x-coordinate of the point
454: * @param y the y-coordinate of the point
455: * @return true if the passed in location is a valid mouse location
456: * @todo implement this correctly
457: */
458: protected boolean inHitRegion(int x, int y) {
459: if (lastRow != -1 && tree != null) {
460: //Rectangle bounds = tree.getRowBounds(lastRow);
461: // if (bounds != null && x <= (bounds.x + offset)
462: // && offset < (bounds.width -5))
463: // { return false; }
464: }
465: return true;
466: }
467:
468: private void setTree(JTree tree) {
469: this.tree = tree;
470: }
471: }
|