001: package tide.exttools.PMD;
002:
003: import java.awt.Color;
004: import java.awt.EventQueue;
005: import java.awt.Component;
006: import javax.swing.tree.*;
007: import javax.swing.*;
008: import javax.swing.event.*;
009: import java.awt.BorderLayout;
010: import java.awt.event.*;
011:
012: public final class RulesTree extends JPanel {
013: DefaultTreeModel treeModel = new DefaultTreeModel(
014: new DefaultMutableTreeNode("?"));
015: JTree tree = new JTree(treeModel);
016: JTextArea detailsArea = new JTextArea(
017: "double click to expand, single click on the boxes to select/deselect, right click for options");
018:
019: public RulesTree() {
020: super (new BorderLayout());
021:
022: final JSplitPane jsp = new JSplitPane(
023: JSplitPane.VERTICAL_SPLIT, new JScrollPane(tree),
024: new JScrollPane(detailsArea));
025: jsp.setOneTouchExpandable(true);
026: EventQueue.invokeLater(new Runnable() {
027: public void run() {
028: jsp.setDividerLocation(0.93);
029: }
030: });
031:
032: add(jsp, BorderLayout.CENTER);
033:
034: tree.setCellRenderer(new CheckBoxRenderer());
035: tree.setRootVisible(false);
036: tree.putClientProperty("JTree.lineStyle", "Horizontal");
037:
038: //ToolTipManager.sharedInstance().registerComponent(tree);
039:
040: MouseListener ml = new MouseAdapter() {
041:
042: @Override
043: public void mouseReleased(MouseEvent e) {
044: if (e.isPopupTrigger()) {
045: displayPopup(e);
046: return;
047: }
048: }
049:
050: public void mousePressed(MouseEvent e) {
051: if (e.isPopupTrigger()) {
052: displayPopup(e);
053: return;
054: }
055:
056: int selRow = tree.getRowForLocation(e.getX(), e.getY());
057: TreePath selPath = tree.getPathForLocation(e.getX(), e
058: .getY());
059: if (selRow != -1 && selPath != null) {
060:
061: // single clicks "on the checkbox" toggles the state !
062: int itemIndent = selPath.getPath().length - 2; // category = 0, type = 1
063: int ri = (Integer) UIManager
064: .get("Tree.rightChildIndent")
065: + (Integer) UIManager
066: .get("Tree.leftChildIndent");
067: int min = itemIndent * ri;
068: int max = min + 20;
069:
070: boolean toggle = e.getX() < max && e.getX() >= min
071: && e.getClickCount() == 1;
072: if (toggle) {
073: if (selPath.getLastPathComponent() instanceof Rule) {
074: Rule r = (Rule) selPath
075: .getLastPathComponent();
076: r.selected = !r.selected;
077: } else {
078: RuleSet r = (RuleSet) selPath
079: .getLastPathComponent();
080: if (r.isRuleSetFullSelected()) {
081: r.setAllRulesetSelected(false);
082: } else {
083: r.setAllRulesetSelected(true);
084: }
085: }
086: tree.repaint();
087: }
088: }
089:
090: }
091: }; // ml
092: tree.addMouseListener(ml);
093:
094: tree.addTreeSelectionListener(new TreeSelectionListener() {
095: public void valueChanged(TreeSelectionEvent tse) {
096: TreePath sel = tree.getSelectionPath();
097: if (sel == null) {
098: detailsArea.setText("");
099: return;
100: }
101:
102: if (sel.getLastPathComponent() instanceof Rule) {
103: Rule r = (Rule) sel.getLastPathComponent();
104: detailsArea.setText(r.description);
105: detailsArea.append("\npriority=" + r.priority);
106: //detailsArea.append("\nname="+r.name);
107: } else {
108: RuleSet r = (RuleSet) sel.getLastPathComponent();
109: detailsArea.setText("" + r); // toString
110: }
111: detailsArea.setCaretPosition(0);
112: }
113: });
114: }
115:
116: public void displayPopup(MouseEvent me) {
117: JPopupMenu menu = new JPopupMenu();
118: JMenuItem selectAll = new JMenuItem("Select all");
119: menu.add(selectAll);
120: selectAll.addActionListener(new ActionListener() {
121: public void actionPerformed(ActionEvent ae) {
122: setAllSelected(true);
123: }
124: });
125:
126: JMenuItem deselectAll = new JMenuItem("Deselect all");
127: menu.add(deselectAll);
128: deselectAll.addActionListener(new ActionListener() {
129: public void actionPerformed(ActionEvent ae) {
130: setAllSelected(false);
131: }
132: });
133:
134: menu.show(tree, me.getX(), me.getY());
135: }
136:
137: /** sets the parsed xml rules as a tree
138: */
139: public void setAvailableRules(RuleSet rs) {
140: treeModel.setRoot(rs);
141: }
142:
143: /** sets stored selections
144: */
145: public void setSelectedRules(String sel) {
146: //System.out.println("setSelectedRules "+sel);
147: setAllSelected(false);
148: for (String ri : sel.split(",")) {
149: ri = ri.trim();
150:
151: int ip = ri.indexOf(".xml/");
152: if (ip > 0) {
153: // try
154: String rn = ri.substring(0, ip + 4);
155: String rnsn = ri.substring(ip + 5);
156: RuleSet rs = getSet(rn);
157: if (rs != null) {
158: //System.out.println("Found...");
159: Rule r = rs.getRule(rnsn);
160: if (r != null) {
161: r.selected = true;
162: } else {
163: System.out.println("rule not found: " + rnsn
164: + " in " + rn);
165: }
166: } else {
167: System.out.println("Ruleset not found: " + rn
168: + " for " + ri);
169: }
170:
171: } else {
172: RuleSet rs = getSet(ri);
173: if (rs != null) {
174: rs.setAllRulesetSelected(true);
175: } else {
176: System.out.println("Ruleset not found: " + ri);
177: }
178: }
179: }
180: tree.repaint();
181: }
182:
183: /** selects or deselects !
184: */
185: public void setAllSelected(boolean is) {
186: if (!(treeModel.getRoot() instanceof RuleSet))
187: return;
188:
189: RuleSet root = (RuleSet) treeModel.getRoot();
190: for (int i = 0; i < root.getChildCount(); i++) {
191: RuleSet ri = (RuleSet) root.getChildAt(i);
192: ri.setAllRulesetSelected(is);
193: }
194: tree.repaint();
195: }
196:
197: private RuleSet getSet(String name) {
198: if (!name.toLowerCase().endsWith(".xml")) {
199: name = "rulesets/" + name + ".xml";
200: }
201:
202: if (!(treeModel.getRoot() instanceof RuleSet))
203: return null;
204:
205: RuleSet root = (RuleSet) treeModel.getRoot();
206: for (int i = 0; i < root.getChildCount(); i++) {
207: RuleSet ri = (RuleSet) root.getChildAt(i);
208: if (ri.fullName.equalsIgnoreCase(name))
209: return ri;
210: }
211: return null;
212: }
213:
214: /** gets the selected rules
215: */
216: public String getSelectedRules() {
217: if (!(treeModel.getRoot() instanceof RuleSet))
218: return null;
219:
220: StringBuilder sb = new StringBuilder();
221: RuleSet root = (RuleSet) treeModel.getRoot();
222: for (int i = 0; i < root.getChildCount(); i++) {
223: RuleSet ri = (RuleSet) root.getChildAt(i);
224:
225: boolean[] ss = ri.getSelectionState();
226: if (ss[0] && !ss[1]) {
227: // all are selected
228: sb.append(ri.fullName + ",");
229: } else {
230: // not all are selected
231: for (int j = 0; j < ri.getChildCount(); j++) {
232: Rule rij = (Rule) ri.getChildAt(j);
233: if (rij.selected) {
234: if (rij.reference != null
235: && rij.reference.length() > 0) {
236: sb.append(rij.reference + ",");
237: } else {
238: sb.append(ri.fullName + "/" + rij.name
239: + ",");
240: }
241: }
242: }
243: }
244: }
245: if (sb.length() < 2)
246: return "";
247:
248: sb.setLength(sb.length() - 1); // remove last ","
249: return sb.toString();
250: }
251:
252: // Todo: tristate
253: public class CheckBoxRenderer extends JCheckBox implements
254: TreeCellRenderer {
255: public CheckBoxRenderer() {
256: super ();
257: setFont(UIManager.getFont("Tree.font"));
258: }
259:
260: public Component getTreeCellRendererComponent(JTree tree,
261: Object value, boolean selected, boolean expanded,
262: boolean leaf, int row, boolean hasFocus) {
263: setForeground(UIManager.getColor("Tree.foreground"));
264: if (selected) {
265: setBackground(UIManager
266: .getColor("Tree.selectionBackground"));
267: } else {
268: setBackground(UIManager.getColor("Tree.background"));
269: }
270:
271: if (value instanceof RuleSet) {
272: RuleSet node = (RuleSet) value;
273: boolean[] st = node.getSelectionState();
274:
275: if (st[0] && !st[1]) {
276: this .setSelected(true);
277: } else if (!st[0] && st[1]) {
278: this .setSelected(false);
279: } else {
280: // mixed mode
281: this .setForeground(Color.lightGray);
282: this .setSelected(true);
283: }
284: this .setText(node.name + ": " + node.descr);
285: } else if (value instanceof Rule) {
286: Rule node = (Rule) value;
287: this .setSelected(node.selected);
288: if (node.reference != null) {
289: this .setText("REF: " + node.reference);
290: } else {
291: this .setText(node.name + " (" + node.priority
292: + ")");
293: }
294: }
295: return this;
296: }
297: }
298:
299: }
|