001    package nl.cwi.sen1.tide.tool.srcviewer;
002    
003    //{{{ imports
004    
005    import java.awt.BorderLayout;
006    import java.awt.Color;
007    import java.awt.Component;
008    import java.awt.Container;
009    import java.awt.Dimension;
010    import java.awt.Font;
011    import java.awt.FontMetrics;
012    import java.awt.Graphics;
013    import java.awt.Point;
014    import java.awt.Rectangle;
015    import java.awt.event.ActionEvent;
016    import java.awt.event.ActionListener;
017    import java.net.URL;
018    
019    import javax.swing.Icon;
020    import javax.swing.ImageIcon;
021    import javax.swing.JComponent;
022    import javax.swing.JPanel;
023    import javax.swing.JPopupMenu;
024    
025    import nl.cwi.sen1.tide.tool.ToolManager;
026    import nl.cwi.sen1.tide.tool.ruleinspector.RuleInspector;
027    import nl.cwi.sen1.tide.tool.ruleinspector.RuleInspectorFactory;
028    import nl.cwi.sen1.tide.tool.support.DebugProcess;
029    import nl.cwi.sen1.tide.tool.support.DebugProcessListener;
030    import nl.cwi.sen1.tide.tool.support.Expr;
031    import nl.cwi.sen1.tide.tool.support.ExprFormat;
032    import nl.cwi.sen1.tide.tool.support.Port;
033    import nl.cwi.sen1.tide.tool.support.ProcessStatusChangeListener;
034    import nl.cwi.sen1.tide.tool.support.Rule;
035    
036    //}}}
037    
038    class ValuePopup
039            extends JPanel
040            implements DebugProcessListener, ProcessStatusChangeListener, ActionListener {
041            //{{{ Constants
042    
043            public final static int ICON_SIZE = 14;
044    
045            private final static String TAG_UPDATE = "vp-update";
046    
047            /*
048             * private final static Color COLOR_BACK_CLEAN= new Color(0xFF,0xCC,0xCC);
049             * private final static Color COLOR_BACK_DIRTY= new Color(0xFF,0x99,0x99);
050             */
051            private final static Color COLOR_BACK_CLEAN = new Color(0xEE, 0xEE, 0x00);
052            private final static Color COLOR_BACK_DIRTY = new Color(0xCC, 0xCC, 0x00);
053            private final static Color COLOR_BORDER = new Color(0x00, 0x00, 0x00);
054    
055            private final static String ITEM_EDIT_RULE = "Edit Rule";
056            private final static String ITEM_VIEW_VARIABLE = "View Variable";
057    
058            //}}}
059    
060            //{{{ Attributes
061    
062            private static int next_id = 0;
063    
064            private int id;
065            private ToolManager manager;
066            private SourceFileViewer viewer;
067    
068            private String tag_update;
069    
070            private DebugProcess process;
071            private Rule updateRule;
072            private Expr expr;
073            private String label;
074            private ExprFormat format;
075    
076            private boolean uptodate;
077    
078            private String content;
079            private Font font;
080            private FontMetrics metrics;
081            private Icon closeIcon;
082    
083            private int drag_trans_x;
084            private int drag_trans_y;
085    
086            private JPopupMenu menu;
087    
088            //}}}
089    
090            //{{{ public ValuePopup(manager, viewer, process, expr, label, initial)
091    
092            public ValuePopup(
093                    ToolManager manager,
094                    SourceFileViewer viewer,
095                    DebugProcess process,
096                    Expr expr,
097                    String label,
098                    Expr initial_value,
099                    ExprFormat fmt) {
100                    this.id = next_id++;
101                    this.manager = manager;
102                    this.viewer = viewer;
103                    this.process = process;
104                    this.expr = expr;
105                    this.label = label;
106                    this.format = fmt;
107    
108                    tag_update = TAG_UPDATE + "-" + id;
109    
110                    uptodate = true;
111    
112                    process.addDebugProcessListener(this);
113                    process.addProcessStatusChangeListener(this);
114    
115                    closeIcon = loadIcon("mini-close.gif");
116    
117                    content = label + "=" + format.format(initial_value);
118    
119                    setLayout(new BorderLayout());
120    
121                    setBackground(new Color(0xFF, 0xFF, 0x00));
122                    this.setOpaque(true);
123                    setDoubleBuffered(true);
124                    font = new Font("Helvetica", Font.BOLD, 12);
125                    metrics = getFontMetrics(font);
126    
127                    setSize(getPreferredSize());
128    
129                    process.requestRuleCreation(
130                            Port.makeStopped(),
131                            Expr.makeTrue(),
132                            expr,
133                            tag_update,
134                            true);
135    
136                    //{{{ Create menu
137    
138                    menu = new JPopupMenu("Variable " + label);
139                    menu.add(ITEM_EDIT_RULE).addActionListener(this);
140                    menu.add(ITEM_VIEW_VARIABLE).addActionListener(this);
141    
142                    //}}}
143            }
144    
145            //}}}
146            //{{{ public Rule getUpdateRule()
147    
148            public Rule getUpdateRule() {
149                    return updateRule;
150            }
151    
152            //}}}
153            //{{{ private loadIcon(String name)
154    
155            private Icon loadIcon(String name) {
156                    URL url = getClass().getResource("/resources/images/" + name);
157                    return new ImageIcon(url);
158            }
159    
160            //}}}
161            //{{{ public Dimension getPreferredSize()
162    
163            public Dimension getPreferredSize() {
164                    return new Dimension(
165                            ICON_SIZE + 4 + metrics.stringWidth(content),
166                            Math.max(
167                                    ICON_SIZE + 4,
168                                    2 + metrics.getMaxAscent() + metrics.getMaxDescent()));
169            }
170    
171            //}}}
172            //{{{ public void paint(Graphics g)
173    
174            public void paint(Graphics g) {
175                    int width = getSize().width;
176                    int height = getSize().height;
177    
178                    g.setFont(font);
179                    g.setColor(uptodate ? COLOR_BACK_CLEAN : COLOR_BACK_DIRTY);
180                    g.fillRect(0, 0, width, height);
181                    g.setColor(COLOR_BORDER);
182                    g.drawRect(0, 0, width - 1, height - 1);
183                    g.setColor(Color.black);
184    
185                    closeIcon.paintIcon(this, g, 0, (height - ICON_SIZE) / 2);
186                    g.drawString(
187                            content,
188                            ICON_SIZE + 3,
189                            (height - metrics.getHeight()) / 2 + metrics.getMaxAscent() + 1);
190            }
191    
192            //}}}
193            //{{{ public void show(JComponent invoker, int x, int y)
194    
195            public void show(JComponent invoker, int x, int y) {
196                    Point p = new Point(x, y);
197                    //SwingUtilities.convertPointFromScreen(p,invoker.getRootPane().getLayeredPane());
198                    this.setBounds(p.x, p.y, getSize().width, getSize().height);
199                    /*
200                     * invoker.getRootPane().getLayeredPane().add(this,
201                     * JLayeredPane.POPUP_LAYER,0);
202                     */
203                    invoker.add(this);
204                    setVisible(true);
205                    invoker.repaint(p.x, p.y, getSize().width, getSize().height);
206            }
207    
208            //}}}
209            //{{{ public void remove()
210    
211            public void remove() {
212                    Container parent = getParent();
213                    Rectangle r = this.getBounds();
214                    if (parent != null) {
215                            parent.remove(this);
216                            parent.repaint(r.x, r.y, r.width, r.height);
217                    }
218            }
219    
220            //}}}
221            //{{{ public void startDragging(int start_x, int start_y)
222    
223            public void startDragging(int start_x, int start_y) {
224                    drag_trans_x = getX() - start_x;
225                    drag_trans_y = getY() - start_y;
226            }
227    
228            //}}}
229            //{{{ public int getDragTransX()
230    
231            public int getDragTransX() {
232                    return drag_trans_x;
233            }
234    
235            //}}}
236            //{{{ public int getDragTransY()
237    
238            public int getDragTransY() {
239                    return drag_trans_y;
240            }
241    
242            //}}}
243    
244            //{{{ public void closePopup()
245    
246            public void closePopup() {
247                    process.removeProcessStatusChangeListener(this);
248                    process.removeDebugProcessListener(this);
249            }
250    
251            //}}}
252            //{{{ public void updateValue()
253    
254            public void updateValue() {
255                    process.requestEvaluation(expr, tag_update);
256            }
257    
258            //}}}
259            //{{{ public void showMenu(Component parent, int x, int y)
260    
261            public void showMenu(Component parent, int x, int y) {
262                    menu.show(parent, x, y);
263            }
264    
265            //}}}
266    
267            //{{{ public void actionPerformed(ActionEvent event)
268    
269            public void actionPerformed(ActionEvent event) {
270                    if (event.getActionCommand().equals(ITEM_EDIT_RULE)) {
271                            String toolName = RuleInspectorFactory.NAME;
272                            RuleInspector inspector =
273                                    (RuleInspector) manager.launchProcessTool(toolName, process);
274                            inspector.editRule(updateRule);
275                    } else if (event.getActionCommand().equals(ITEM_VIEW_VARIABLE)) {}
276            }
277    
278            //}}}
279    
280            //{{{ public void processStatusChanged(DebugProcess process)
281    
282            public void processStatusChanged(DebugProcess process) {
283                    if (process.isRunning()) {
284                            uptodate = false;
285                            repaint();
286                    }
287            }
288    
289            //}}}
290    
291            //{{{ private void updateValue(Expr value)
292    
293            private void updateValue(Expr value) {
294                    content = label + "=" + format.format(value);
295                    uptodate = process.isStopped();
296                    setSize(getPreferredSize());
297                    repaint();
298            }
299    
300            //}}}
301    
302            //{{{ public void ruleCreated(DebugProcess process, Rule rule)
303    
304            public void ruleCreated(DebugProcess process, Rule rule) {
305                    if (rule.getTag().equals(tag_update)) {
306                            updateRule = rule;
307                    }
308            }
309    
310            //}}}
311            //{{{ public void ruleDeleted(DebugProcess process, Rule rule)
312    
313            public void ruleDeleted(DebugProcess process, Rule rule) {
314                    if (rule == updateRule) {
315                            viewer.removeValuePopup(this);
316                    }
317            }
318    
319            //}}}
320            //{{{ public void ruleModified(DebugProcess process, Rule rule)
321    
322            public void ruleModified(DebugProcess process, Rule rule) {
323            }
324    
325            //}}}
326            //{{{ public void ruleTriggered(DebugProcess process, Rule rule, Expr
327            // value)
328    
329            public void ruleTriggered(DebugProcess process, Rule rule, Expr value) {
330                    if (rule == updateRule) {
331                            updateValue(value);
332                    }
333            }
334    
335            //}}}
336            //{{{ public void evaluationResult(process, expr, value, tag)
337    
338            public void evaluationResult(DebugProcess process, Expr expr, Expr value, String tag) {
339                    if (tag.equals(tag_update)) {
340                            updateValue(value);
341                    }
342            }
343    
344            //}}}
345            //{{{ public void selectRule(DebugProcess process, Rule rule)
346    
347            public void selectRule(DebugProcess process, Rule rule) {}
348    
349            //}}}
350    }