Added CheckRenderDataProvider
interface.
+
true
if the check-box should be displayed, false
otherwise.
+ */
+ boolean isCheckable(Object o);
+
+ /**
+ * Provide the enabled state of the check-box.
+ *
+ * @param o the tree object
+ * @return true
if the check-box should be enabled, false
otherwise.
+ */
+ boolean isCheckEnabled(Object o);
+
+ /**
+ * Provide the selected state of the check-box.
+ *
+ * @param o the tree object
+ * @return true
if the check-box should be selected,
+ * false
if it should be unselected and
+ * null
if the state is unknown.
+ */
+ Boolean isSelected(Object o);
+
+ /**
+ * Called by the renderer when the check-box gets selected/unselected
+ *
+ * @param o the tree object
+ * @param selected true
if the check-box was selected,
+ * false
if the check-box was unselected.
+ */
+ void setSelected(Object o, Boolean selected);
+
+}
diff --git a/o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineCellRenderer.java b/o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineCellRenderer.java
--- a/o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineCellRenderer.java
+++ b/o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineCellRenderer.java
@@ -42,9 +42,12 @@
import java.awt.Color;
import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.Icon;
+import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
@@ -66,10 +69,16 @@
private boolean leaf = true;
private boolean showHandle = true;
private int nestingDepth = 0;
+ private final JCheckBox theCheckBox;
+ private JCheckBox checkBox;
private static final Border expansionBorder = new ExpansionHandleBorder();
/** Creates a new instance of DefaultOutlineTreeCellRenderer */
public DefaultOutlineCellRenderer() {
+ theCheckBox = new JCheckBox();
+ theCheckBox.setSize(theCheckBox.getPreferredSize());
+ theCheckBox.setBorderPainted(false);
+ theCheckBox.setOpaque(false);
}
/** Overridden to combine the expansion border (whose insets determine how
@@ -140,6 +149,10 @@
private void setShowHandle (boolean val) {
showHandle = val;
}
+
+ private void setCheckBox(JCheckBox checkBox) {
+ this.checkBox = checkBox;
+ }
private boolean isLeaf () {
return leaf;
@@ -159,6 +172,14 @@
* node. */
private int getNestingDepth() {
return nestingDepth;
+ }
+
+ private JCheckBox getCheckBox() {
+ return checkBox;
+ }
+
+ int getTheCheckBoxWidth() {
+ return theCheckBox.getSize().width;
}
/** Get a component that can render cells in an Outline. If
@@ -218,6 +239,22 @@
tbl.getSelectionForeground() : tbl.getForeground());
}
icon = rendata.getIcon(value);
+
+ JCheckBox cb = null;
+ if (rendata instanceof CheckRenderDataProvider) {
+ CheckRenderDataProvider crendata = (CheckRenderDataProvider) rendata;
+ if (crendata.isCheckable(value)) {
+ cb = theCheckBox;
+ Boolean chSelected = crendata.isSelected(value);
+ cb.setSelected(!Boolean.FALSE.equals(chSelected));
+ // Third state is "selected armed" to be consistent with org.openide.explorer.propertysheet.ButtonModel3Way
+ cb.getModel().setArmed(chSelected == null);
+ cb.getModel().setPressed(chSelected == null);
+ cb.setEnabled(crendata.isCheckEnabled(value));
+ cb.setBackground(getBackground());
+ }
+ }
+ setCheckBox(cb);
}
if (icon == null) {
if (!isleaf) {
@@ -239,7 +276,7 @@
}
return this;
}
-
+
private static class ExpansionHandleBorder implements Border {
private static final boolean isGtk = "GTK".equals (UIManager.getLookAndFeel ().getID ()); //NOI18N
@@ -271,6 +308,9 @@
insets.right = 1;
insets.bottom = 1;
}
+ if (ren.getCheckBox() != null) {
+ insets.left += ren.getCheckBox().getSize().width;
+ }
return insets;
}
@@ -296,7 +336,13 @@
} else {
icon.paintIcon(c, g, iconX, iconY);
}
-
+ }
+ JCheckBox chBox = ren.getCheckBox();
+ if (chBox != null) {
+ int chBoxX = getExpansionHandleWidth() + ren.getNestingDepth() * getNestingWidth();
+ Dimension chDim = chBox.getSize();
+ java.awt.Graphics gch = g.create(chBoxX, 0, chDim.width, chDim.height);
+ chBox.paint(gch);
}
}
}
diff --git a/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java b/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java
--- a/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java
+++ b/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java
@@ -549,6 +549,38 @@
return false;
}
}
+ // It may be a request to check/uncheck a check-box
+ RenderDataProvider render = getRenderDataProvider();
+ TableCellRenderer tcr = getDefaultRenderer(Object.class);
+ if (render instanceof CheckRenderDataProvider && tcr instanceof DefaultOutlineCellRenderer) {
+ CheckRenderDataProvider crender = (CheckRenderDataProvider) render;
+ DefaultOutlineCellRenderer ocr = (DefaultOutlineCellRenderer) tcr;
+ Object value = getValueAt(row, column);
+ if (crender.isCheckable(value)) {
+ int handleWidth = DefaultOutlineCellRenderer.getExpansionHandleWidth();
+ int chWidth = ocr.getTheCheckBoxWidth();
+ Insets ins = getInsets();
+ int nd = path.getPathCount() - (isRootVisible() ? 1 : 2);
+ if (nd < 0) {
+ nd = 0;
+ }
+ int chStart = ins.left + (nd * DefaultOutlineCellRenderer.getNestingWidth()) + handleWidth;
+ int chEnd = chStart + chWidth;
+ //TODO: Translate x/y to position of column if non-0
+
+ boolean enabled = crender.isCheckEnabled(value);
+ if ((me.getX() > ins.left && me.getX() >= chStart && me.getX() <= chEnd) &&
+ me.getClickCount() == 1 && enabled) {
+
+ Boolean selected = crender.isSelected(value);
+ if (selected == null || Boolean.TRUE.equals(selected)) {
+ crender.setSelected(value, Boolean.FALSE);
+ } else {
+ crender.setSelected(value, Boolean.TRUE);
+ }
+ }
+ }
+ }
}
boolean res = super.editCellAt(row, column, e);
diff --git a/o.n.swing.outline/src/org/netbeans/swing/outline/RenderDataProvider.java b/o.n.swing.outline/src/org/netbeans/swing/outline/RenderDataProvider.java
--- a/o.n.swing.outline/src/org/netbeans/swing/outline/RenderDataProvider.java
+++ b/o.n.swing.outline/src/org/netbeans/swing/outline/RenderDataProvider.java
@@ -46,10 +46,7 @@
/** A class which can provide rendering data for the tree portion an Outline,
* such as converting values to text, providing tooltip text and icons.
* Makes it possible to provide most of the interesting data that affects
- * display without needing to provide a custom cell renderer. An Outline
- * will use its RenderDataProvider to fetch data for all
- * its columns, so it is possible to affect the display of both property
- * columns and the tree column via this interface.
+ * display without needing to provide a custom cell renderer.
*
* @author Tim Boudreau
*/
diff --git a/openide.explorer/apichanges.xml b/openide.explorer/apichanges.xml
--- a/openide.explorer/apichanges.xml
+++ b/openide.explorer/apichanges.xml
@@ -47,9 +47,21 @@
setSelectedNodes()
.
- does partial selection
+ does partial selection
of valid nodes instead of throwing IllegalArgumentException.
true
if the check-box should be displayed, false
otherwise.
+ */
+ boolean isCheckable();
+
+ /**
+ * Provide the enabled state of the check-box.
+ *
+ * @return true
if the check-box should be enabled, false
otherwise.
+ */
+ boolean isCheckEnabled();
+
+ /**
+ * Provide the selected state of the check-box.
+ *
+ * @return true
if the check-box should be selected,
+ * false
if it should be unselected and
+ * null
if the state is unknown.
+ */
+ Boolean isSelected();
+
+ /**
+ * Called by the view when the check-box gets selected/unselected
+ *
+ * @param selected true
if the check-box was selected,
+ * false
if the check-box was unselected.
+ */
+ void setSelected(Boolean selected);
+
+}
diff --git a/openide.explorer/src/org/openide/explorer/view/NodeRenderDataProvider.java b/openide.explorer/src/org/openide/explorer/view/NodeRenderDataProvider.java
--- a/openide.explorer/src/org/openide/explorer/view/NodeRenderDataProvider.java
+++ b/openide.explorer/src/org/openide/explorer/view/NodeRenderDataProvider.java
@@ -47,6 +47,7 @@
import javax.swing.tree.AbstractLayoutCache;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
+import org.netbeans.swing.outline.CheckRenderDataProvider;
import org.netbeans.swing.outline.Outline;
import org.netbeans.swing.outline.RenderDataProvider;
import org.openide.nodes.Node;
@@ -55,12 +56,12 @@
*
* @author David Strupl
*/
-class NodeRenderDataProvider implements RenderDataProvider {
+class NodeRenderDataProvider implements CheckRenderDataProvider {
- private JTable table;
+ private Outline table;
/** Creates a new instance of NodeRenderDataProvider */
- public NodeRenderDataProvider(JTable table) {
+ public NodeRenderDataProvider(Outline table) {
this.table = table;
}
@@ -95,7 +96,7 @@
}
Collections.reverse(al);
TreePath tp = new TreePath(al.toArray());
- AbstractLayoutCache layout = ((Outline)table).getLayoutCache();
+ AbstractLayoutCache layout = table.getLayoutCache();
expanded = layout.isExpanded(tp);
}
java.awt.Image image = null;
@@ -118,5 +119,39 @@
public boolean isHtmlDisplayName(Object o) {
return false;
}
-
+
+ private CheckNodeCookie getCheckCookie(Object o) {
+ Node n = Visualizer.findNode(o);
+ if (n == null) {
+ throw new IllegalStateException("TreeNode must be VisualizerNode but was: " + o + " of class " + o.getClass().getName());
+ }
+ return n.getCookie(CheckNodeCookie.class);
+ }
+
+ public boolean isCheckable(Object o) {
+ CheckNodeCookie c = getCheckCookie(o);
+ return c != null && c.isCheckable();
+ }
+
+ public boolean isCheckEnabled(Object o) {
+ CheckNodeCookie c = getCheckCookie(o);
+ return c != null && c.isCheckEnabled();
+ }
+
+ public Boolean isSelected(Object o) {
+ CheckNodeCookie c = getCheckCookie(o);
+ if (c != null) {
+ return c.isSelected();
+ } else {
+ return null;
+ }
+ }
+
+ public void setSelected(Object o, Boolean selected) {
+ CheckNodeCookie c = getCheckCookie(o);
+ if (c != null) {
+ c.setSelected(selected);
+ }
+ }
+
}