1   package debugger.gui.resources;
2   
3   import debugger.gui.GuiFactory;
4   import debugger.resources.ResourcesFactory;
5   import debugger.resources.lr.LRRoot;
6   import debugger.resources.pr.PRRoot;
7   import debugger.resources.pr.RuleModel;
8   import debugger.resources.pr.RuleTrace;
9   import debugger.resources.pr.TraceContainer;
10  
11  import javax.swing.*;
12  import javax.swing.tree.TreeCellRenderer;
13  import java.awt.*;
14  import java.util.HashMap;
15  import java.util.Iterator;
16  
17  /**
18   * Copyright (c) Ontos AG (http://www.ontosearch.com).
19   * This class is part of JAPE Debugger component for
20   * GATE (Copyright (c) "The University of Sheffield" see http://gate.ac.uk/)
21   * @author Andrey Shafirin, Oleg Mishchenko
22   */
23  public class ResourceTreeCellRenderer extends JPanel implements TreeCellRenderer {
24      private static Color RULE_SELECTION_COLOR = new Color(153, 204, 255);
25      private static Color RULE_FINISHED_COLOR = new Color(153, 255, 204);
26      private static Color RULE_TRIED_COLOR = Color.pink;
27      private static Color RULE_OVERRIDED_COLOR = Color.yellow;
28  
29      private JCheckBox checkBox;
30      private JLabel label;
31  
32      private long startIndex = 0;
33      private long endIndex = 0;
34  
35      private boolean updateNeeded = false;
36      private HashMap ruleColors = new HashMap();
37  
38      public ResourceTreeCellRenderer() {
39          this.setLayout(new GridBagLayout());
40  
41          label = new JLabel();
42          label.setFont(new Font("Arial", Font.PLAIN, 11));
43          label.setForeground(Color.black);
44  
45          checkBox = new JCheckBox();
46          checkBox.setBackground(Color.white);
47  
48          initGui(false);
49      }
50  
51      public Component getTreeCellRendererComponent(JTree tree, final Object value,
52                                                    boolean sel,
53                                                    boolean expanded,
54                                                    boolean leaf, int row,
55                                                    boolean hasFocus) {
56          boolean isCheckBoxShown = false;
57          if (sel) {
58              this.setBackground(RULE_SELECTION_COLOR);
59              checkBox.setBackground(RULE_SELECTION_COLOR);
60              label.setBackground(RULE_SELECTION_COLOR);
61          } else {
62              this.setBackground(Color.white);
63              checkBox.setBackground(Color.white);
64              label.setBackground(Color.white);
65          }
66          this.setToolTipText("");
67          if ((value instanceof ResourceTree.PRTreeNode && ((ResourceTree.PRTreeNode) value).getPRResource() instanceof PRRoot)
68                  || (value instanceof ResourceTree.LRTreeNode && ((ResourceTree.LRTreeNode) value).getLRResource() instanceof LRRoot)) {
69              this.initGui(false);
70              isCheckBoxShown = false;
71          }
72          if (value instanceof ResourceTree.PRTreeNode && ((ResourceTree.PRTreeNode) value).getPRResource() instanceof RuleModel) {
73              RuleModel ruleModel = (RuleModel) ((ResourceTree.PRTreeNode) value).getPRResource();
74              this.initGui(true);
75              isCheckBoxShown = true;
76              if (ruleModel.isStopOnMatch()) {
77                  checkBox.setSelected(true);
78              } else {
79                  checkBox.setSelected(false);
80              }
81              /*
82               * After user has selected new part of text, we select the colors for each rule and put
83               * them into ruleColors HashMap, so the iteration doesn't take place on every repaint() of
84               * the tree, thus the performance is improved.
85               */
86              if (updateNeeded == true) {
87                  ruleColors = new HashMap();
88                  TraceContainer traceContainer = ResourcesFactory.getPhaseController().getRuleTrace().getTraceByOffset(new Long(startIndex), new Long(endIndex));
89                  for (Iterator it = traceContainer.iterator(); it.hasNext();) {
90                      RuleTrace ruleTrace = (RuleTrace) it.next();
91                      RuleModel currentRuleModel = ruleTrace.getRuleModel();
92                      TraceContainer currentTraceContainer = traceContainer.getTraceByRuleModel(currentRuleModel);
93                      /*
94                       * If rule has only one corresponding ruleTrace, the color is set using this ruleTrace;
95                       * otherwise, traceContainer with several ruleTraces is put into ruleColors HashMap,
96                       * and the exact color is set after call of
97                       * GuiFactory.getDebugPanel().getTraceHistoryPanel().getCurrentRuleTrace() so that we know
98                       * the exact ruleTrace to use for selection of color.
99                       */
100                     if (currentTraceContainer.size() == 1) {
101                         RuleTrace rTrace = (RuleTrace) currentTraceContainer.iterator().next();
102                         if (rTrace.isFinished() && rTrace.getOverrided() == null) {
103                             ruleColors.put(currentRuleModel, RULE_FINISHED_COLOR);
104                         }
105                         if (rTrace.isFinished() && rTrace.getOverrided() != null) {
106                             ruleColors.put(currentRuleModel, RULE_OVERRIDED_COLOR);
107                         }
108                         if (!rTrace.isFinished()) {
109                             ruleColors.put(currentRuleModel, RULE_TRIED_COLOR);
110                         }
111                     } else {
112                         ruleColors.put(currentRuleModel, currentTraceContainer);
113                     }
114                 }
115                 updateNeeded = false;
116             }
117             /* If update is not needed, use ruleColors HashMap to set the correct color for the rule. */
118             else {
119                 Object color = ruleColors.get(ruleModel);
120                 if (color instanceof Color) {
121                     label.setBackground((Color) color);
122                     this.setBackground((Color) color);
123                     if (color.equals(RULE_OVERRIDED_COLOR)) {
124                         TraceContainer traceContainer = ResourcesFactory.getPhaseController().getRuleTrace().getTraceByOffset(new Long(startIndex), new Long(endIndex));
125                         traceContainer = traceContainer.getTraceByRuleModel(ruleModel);
126                         if (traceContainer.size() == 1) {
127                             RuleTrace ruleTrace = (RuleTrace) traceContainer.iterator().next();
128                             this.setToolTipText("Overrided by: " + ruleTrace.getOverrided().getName());
129                         }
130                     }
131                 } else if (color instanceof TraceContainer) //awful hack! - one gui class should not call method of another gui class
132                 {
133                     RuleModel rModel = GuiFactory.getDebugPanel().getTraceHistoryPanel().getCurrentRuleModel();
134                     if (rModel != null && rModel.equals(ruleModel)) {
135                         RuleTrace ruleTrace = GuiFactory.getDebugPanel().getTraceHistoryPanel().getCurrentRuleTrace();
136                         if (ruleTrace != null) {
137                             if (ruleTrace.isFinished() && ruleTrace.getOverrided() == null) {
138                                 label.setBackground(RULE_FINISHED_COLOR);
139                                 this.setBackground(RULE_FINISHED_COLOR);
140                             }
141                             if (ruleTrace.isFinished() && ruleTrace.getOverrided() != null) {
142                                 label.setBackground(RULE_OVERRIDED_COLOR);
143                                 this.setBackground(RULE_OVERRIDED_COLOR);
144                                 this.setToolTipText("Overrided by: " + ruleTrace.getOverrided().getName());
145                             }
146                             if (!ruleTrace.isFinished()) {
147                                 label.setBackground(RULE_TRIED_COLOR);
148                                 this.setBackground(RULE_TRIED_COLOR);
149                             }
150                         } else {
151                             RuleTrace rTrace = (RuleTrace) ((TraceContainer) color).iterator().next();
152                             if (rTrace.isFinished() && rTrace.getOverrided() == null) {
153                                 label.setBackground(RULE_FINISHED_COLOR);
154                                 this.setBackground(RULE_FINISHED_COLOR);
155                             }
156                             if (rTrace.isFinished() && rTrace.getOverrided() != null) {
157                                 label.setBackground(RULE_OVERRIDED_COLOR);
158                                 this.setBackground(RULE_OVERRIDED_COLOR);
159                                 this.setToolTipText("Overrided by: " + rTrace.getOverrided().getName());
160                             }
161                             if (!rTrace.isFinished()) {
162                                 label.setBackground(RULE_TRIED_COLOR);
163                                 this.setBackground(RULE_TRIED_COLOR);
164                             }
165                         }
166                     } else {
167                         RuleTrace rTrace = (RuleTrace) ((TraceContainer) color).iterator().next();
168                         if (rTrace.isFinished() && rTrace.getOverrided() == null) {
169                             label.setBackground(RULE_FINISHED_COLOR);
170                             this.setBackground(RULE_FINISHED_COLOR);
171                         }
172                         if (rTrace.isFinished() && rTrace.getOverrided() != null) {
173                             label.setBackground(RULE_OVERRIDED_COLOR);
174                             this.setBackground(RULE_OVERRIDED_COLOR);
175                             this.setToolTipText("Overrided by: " + rTrace.getOverrided().getName());
176                         }
177                         if (!rTrace.isFinished()) {
178                             label.setBackground(RULE_TRIED_COLOR);
179                             this.setBackground(RULE_TRIED_COLOR);
180                         }
181                     }
182                 }
183             }
184         } else {
185             this.initGui(false);
186             isCheckBoxShown = false;
187         }
188 
189         label.setText(value.toString());
190 
191         int additionalPixels = 0;
192         if (isCheckBoxShown)
193             additionalPixels = 19;//checkBox.getSize().width;
194         setPreferredSize(new Dimension(label.getFontMetrics(label.getFont()).stringWidth(label.getText()) + additionalPixels + 4,
195                 label.getFontMetrics(label.getFont()).getHeight()));
196 
197         revalidate();
198         repaint();
199         return this;
200     }
201 
202     private void initGui(boolean withCheckBox) {
203         this.removeAll();
204         this.setLayout(new GridBagLayout());
205         GridBagConstraints c = new GridBagConstraints();
206         c.gridx = 0;
207         c.gridy = 0;
208         c.weightx = 0;
209         c.weighty = 0;
210         c.anchor = GridBagConstraints.WEST;
211         c.insets = new Insets(1, 2, 1, 1);
212         if (withCheckBox) {
213             this.add(checkBox, c);
214             c.gridx = 1;
215             this.add(label, c);
216             c.gridx = 2;
217             c.weightx = 1;
218             JPanel panel = new JPanel();
219             panel.setOpaque(false);
220             this.add(panel, c);
221         } else {
222             this.add(label, c);
223             c.gridx = 1;
224             c.weightx = 1;
225             JPanel panel = new JPanel();
226             panel.setOpaque(false);
227             this.add(panel, c);
228         }
229     }
230 
231     public void setIndexes(int startIndex, int endIndex) {
232         this.startIndex = startIndex;
233         this.endIndex = endIndex;
234         updateNeeded = true;
235     }
236 }
237