Sfoglia il codice sorgente

Add debug plugin.

Tidy up sevreal classes
Add checkboxmenu item
Change menu bar so plugins can add items.
Add update ID to notifications plugin

Fixes issue CLIENT-80

Change-Id: I289bbf7bcad6d9c528eb353dc8cf49ad48954a65
Reviewed-on: http://gerrit.dmdirc.com/1559
Reviewed-by: Chris Smith <chris@dmdirc.com>
Automatic-Compile: Chris Smith <chris@dmdirc.com>
tags/0.6.5
Greg Holmes 13 anni fa
parent
commit
9ad6bc4dd4

+ 4
- 0
src/com/dmdirc/addons/notifications/plugin.config Vedi File

@@ -8,6 +8,7 @@ keysections:
8 8
   version
9 9
   requires
10 10
   defaults
11
+  updates
11 12
 
12 13
 metadata:
13 14
   author=Greg <greg@dmdirc.com>
@@ -16,6 +17,9 @@ metadata:
16 17
   name=notifications
17 18
   nicename=Notification Manager
18 19
 
20
+updates:
21
+  id=61
22
+
19 23
 version:
20 24
   friendly=0.1
21 25
 

+ 85
- 0
src/com/dmdirc/addons/swingdebug/CloseListener.java Vedi File

@@ -0,0 +1,85 @@
1
+/*
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+package com.dmdirc.addons.swingdebug;
23
+
24
+import java.awt.Window;
25
+import java.awt.event.ComponentEvent;
26
+import java.awt.event.ComponentListener;
27
+
28
+import javax.swing.ButtonModel;
29
+
30
+/**
31
+ * Updates checkbox state on window close.
32
+ */
33
+public class CloseListener implements ComponentListener {
34
+
35
+    /** Button model to update. */
36
+    private final ButtonModel model;
37
+
38
+    /**
39
+     * Creates a new Close Listener for the specified window and model.
40
+     *
41
+     * @param model Model to keep updated
42
+     * @param window Window to monitor
43
+     */
44
+    public CloseListener(final ButtonModel model, final Window window) {
45
+        super();
46
+
47
+        this.model = model;
48
+        window.addComponentListener(this);
49
+    }
50
+
51
+    /** {@inheritDoc} */
52
+    @Override
53
+    public void componentResized(final ComponentEvent e) {
54
+        //Ignore, don't care
55
+    }
56
+
57
+    /** {@inheritDoc} */
58
+    @Override
59
+    public void componentMoved(final ComponentEvent e) {
60
+        //Ignore, don't care
61
+    }
62
+
63
+    /** {@inheritDoc} */
64
+    @Override
65
+    public void componentShown(final ComponentEvent e) {
66
+        //Ignore, don't care
67
+    }
68
+
69
+    /** {@inheritDoc} */
70
+    @Override
71
+    public void componentHidden(final ComponentEvent e) {
72
+        model.setSelected(false);
73
+    }
74
+
75
+    /**
76
+     * Adds a close listener to the specified window, updating the specified
77
+     * model.
78
+     *
79
+     * @param model Model to update
80
+     * @param window Window to listener to
81
+     */
82
+    public static void add(final ButtonModel model, final Window window) {
83
+        new CloseListener(model, window);
84
+    }
85
+}

+ 152
- 0
src/com/dmdirc/addons/swingdebug/SwingDebugPlugin.java Vedi File

@@ -0,0 +1,152 @@
1
+/*
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.swingdebug;
24
+
25
+import com.dmdirc.addons.ui_swing.DMDircEventQueue;
26
+import com.dmdirc.addons.ui_swing.SwingController;
27
+import com.dmdirc.addons.ui_swing.components.CheckBoxMenuItem;
28
+import com.dmdirc.addons.ui_swing.components.text.TextLabel;
29
+import com.dmdirc.plugins.Plugin;
30
+import com.dmdirc.plugins.PluginManager;
31
+import java.awt.Toolkit;
32
+import java.awt.event.ActionEvent;
33
+
34
+import java.awt.event.ActionListener;
35
+import java.io.IOException;
36
+import java.io.PrintStream;
37
+
38
+import javax.swing.JCheckBoxMenuItem;
39
+import javax.swing.JDialog;
40
+import javax.swing.JMenu;
41
+import javax.swing.JScrollPane;
42
+import net.miginfocom.swing.MigLayout;
43
+
44
+/**
45
+ * Swing debug plugin. Provides long running EDT task violation detection and
46
+ * a console for System.out and System.err.
47
+ */
48
+public class SwingDebugPlugin extends Plugin implements ActionListener {
49
+
50
+    /** Swing controller. */
51
+    private SwingController controller;
52
+    /** Debug menu. */
53
+    private JMenu debugMenu;
54
+    /** Debug EDT menu item. */
55
+    private JCheckBoxMenuItem debugEDT;
56
+    /** Debug EDT menu item. */
57
+    private JCheckBoxMenuItem showSysOut;
58
+    /** Debug EDT menu item. */
59
+    private JCheckBoxMenuItem showSysErr;
60
+    /** Old System.out. */
61
+    private PrintStream sysout;
62
+    /** Old System.err. */
63
+    private PrintStream syserr;
64
+    /** System.out redirect thread. */
65
+    private SystemStreamRedirectThread out;
66
+    /** System.err redirect thread. */
67
+    private SystemStreamRedirectThread err;
68
+    /** System out frame. */
69
+    private JDialog outFrame;
70
+    /** System error frame. */
71
+    private JDialog errorFrame;
72
+
73
+    /** {@inheritDoc} */
74
+    @Override
75
+    public void onLoad() {
76
+        controller = (SwingController) PluginManager.getPluginManager()
77
+                .getPluginInfoByName("ui_swing").getPlugin();
78
+        try {
79
+            sysout = System.out;
80
+            syserr = System.err;
81
+            final TextLabel outTextArea = new TextLabel();
82
+            final TextLabel errorTextArea = new TextLabel();
83
+            outFrame = new JDialog(controller.getMainFrame());
84
+            errorFrame = new JDialog(controller.getMainFrame());
85
+            outFrame.setTitle("DMDirc: System.out Console");
86
+            errorFrame.setTitle("DMDirc: System.err Console");
87
+            outFrame.setLayout(new MigLayout("ins 0, pack, wmin 20sp, hmin 20sp"));
88
+            errorFrame.setLayout(new MigLayout("ins 0, pack, wmin 20sp, hmin 20sp"));
89
+            outFrame.add(new JScrollPane(outTextArea), "grow, push");
90
+            errorFrame.add(new JScrollPane(errorTextArea), "grow, push");
91
+            outFrame.pack();
92
+            errorFrame.pack();
93
+            out = new SystemStreamRedirectThread(
94
+                    SystemStreamRedirectThread.Stream.OUT,
95
+                    outTextArea.getDocument());
96
+            err = new SystemStreamRedirectThread(
97
+                    SystemStreamRedirectThread.Stream.IN,
98
+                    errorTextArea.getDocument());
99
+            out.start();
100
+            err.start();
101
+            debugMenu = new JMenu("Debug");
102
+            debugEDT = new CheckBoxMenuItem("Check EDT task length");
103
+            showSysOut = new CheckBoxMenuItem("Show System.out Console");
104
+            showSysErr = new CheckBoxMenuItem("Show System.err Console");
105
+            debugEDT.addActionListener(this);
106
+            showSysErr.addActionListener(this);
107
+            showSysOut.addActionListener(this);
108
+            controller.getMainFrame().getJMenuBar().add(debugMenu);
109
+            debugMenu.add(debugEDT);
110
+            debugMenu.add(showSysOut);
111
+            debugMenu.add(showSysErr);
112
+            CloseListener.add(showSysOut.getModel(), outFrame);
113
+            CloseListener.add(showSysErr.getModel(), outFrame);
114
+        } catch (IOException ex) {
115
+            onUnload();
116
+        }
117
+    }
118
+
119
+    /** {@inheritDoc} */
120
+    @Override
121
+    public void onUnload() {
122
+        out.cancel();
123
+        err.cancel();
124
+        System.setOut(sysout);
125
+        System.setErr(syserr);
126
+        outFrame = null;
127
+        errorFrame = null;
128
+        controller.getMainFrame().getJMenuBar().remove(debugMenu);
129
+        controller = null;
130
+    }
131
+
132
+    /** {@inheritDoc} */
133
+    @Override
134
+    public void actionPerformed(final ActionEvent e) {
135
+        if (e.getSource() == debugEDT) {
136
+            if (debugEDT.getState()) {
137
+                Toolkit.getDefaultToolkit().getSystemEventQueue().
138
+                        push(new TracingEventQueue(this, controller));
139
+            } else {
140
+                Toolkit.getDefaultToolkit().getSystemEventQueue().
141
+                        push(new DMDircEventQueue(controller));
142
+            }
143
+        }
144
+        if (e.getSource() == showSysOut) {
145
+            outFrame.setVisible(showSysOut.getState());
146
+        }
147
+        if (e.getSource() == showSysErr) {
148
+            errorFrame.setVisible(showSysErr.getState());
149
+        }
150
+    }
151
+
152
+}

+ 133
- 0
src/com/dmdirc/addons/swingdebug/SystemStreamRedirectThread.java Vedi File

@@ -0,0 +1,133 @@
1
+/*
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.swingdebug;
24
+
25
+import java.io.BufferedReader;
26
+import java.io.IOException;
27
+import java.io.InputStreamReader;
28
+import java.io.PipedInputStream;
29
+import java.io.PipedOutputStream;
30
+import java.io.PrintStream;
31
+
32
+import javax.swing.text.BadLocationException;
33
+import javax.swing.text.Document;
34
+
35
+/**
36
+ * Simple utility class to redirect System streams to the specified Document.
37
+ */
38
+public class SystemStreamRedirectThread implements Runnable {
39
+
40
+    /**
41
+     * Enum to identify System streams.
42
+     */
43
+    public enum Stream {
44
+        /** System.out. */
45
+        OUT,
46
+        /** System.in. */
47
+        IN;
48
+    }
49
+
50
+    /** Is this thread running? */
51
+    private boolean running = false;
52
+    /** Reader to for the system stream. */
53
+    private final BufferedReader rar;
54
+    /** Stream identifier. */
55
+    private final Stream stream;
56
+    /** Document to output stream into. */
57
+    private final Document document;
58
+
59
+    /**
60
+     * Constructs a new redirection thread.
61
+     *
62
+     * @param stream System stream to redirect
63
+     * @param document Document to redirect stream into
64
+     *
65
+     * @throws IOException On error redirecting stream
66
+     */
67
+    public SystemStreamRedirectThread(final Stream stream,
68
+            final Document document) throws IOException {
69
+        super();
70
+        this.stream = stream;
71
+        this.document = document;
72
+
73
+        final PipedInputStream in = new PipedInputStream();
74
+        final PipedOutputStream out = new PipedOutputStream(in);
75
+        rar = new BufferedReader(new InputStreamReader(in));
76
+        switch (stream) {
77
+            case OUT:
78
+                System.setOut(new PrintStream(out));
79
+                break;
80
+            case IN:
81
+                System.setErr(new PrintStream(out));
82
+                break;
83
+            default:
84
+                throw new IllegalArgumentException("Unknown stream type: "
85
+                        + stream);
86
+        }
87
+    }
88
+
89
+    /** {@inheritDoc} */
90
+    @Override
91
+    public void run() {
92
+        running = true;
93
+        while (running) {
94
+            try {
95
+                if (rar.ready()) {
96
+                    document.insertString(document.getLength(), rar.readLine(),
97
+                            null);
98
+                    document.insertString(document.getLength(), "\n", null);
99
+                }
100
+            } catch (BadLocationException ex) {
101
+                running = false;
102
+            } catch (IOException ex) {
103
+                running = false;
104
+            }
105
+        }
106
+    }
107
+
108
+    /**
109
+     * Starts the thread adding text to the document.
110
+     */
111
+    public void start() {
112
+        final Thread thread = new Thread(this,
113
+                "System stream redirector (" + stream + ")");
114
+        thread.setDaemon(true);
115
+        thread.start();
116
+    }
117
+
118
+    /**
119
+     * Cancels the thread adding text to the document.
120
+     */
121
+    public void cancel() {
122
+        running = false;
123
+    }
124
+
125
+    /**
126
+     * Is this thread running?
127
+     *
128
+     * @return true iif running
129
+     */
130
+    public boolean isRunning() {
131
+        return running;
132
+    }
133
+}

src/com/dmdirc/addons/ui_swing/TracingEventQueueThread.java → src/com/dmdirc/addons/swingdebug/TracingEventQueue.java Vedi File

@@ -24,12 +24,19 @@
24 24
  * POSSIBILITY OF SUCH DAMAGE.
25 25
  */
26 26
 
27
-package com.dmdirc.addons.ui_swing;
27
+package com.dmdirc.addons.swingdebug;
28
+
29
+import com.dmdirc.addons.ui_swing.DMDircEventQueue;
30
+import com.dmdirc.addons.ui_swing.SwingController;
31
+import com.dmdirc.config.IdentityManager;
32
+import com.dmdirc.interfaces.ConfigChangeListener;
33
+import com.dmdirc.plugins.Plugin;
28 34
 
29 35
 import java.awt.AWTEvent;
30 36
 import java.lang.management.ManagementFactory;
31 37
 import java.lang.management.ThreadInfo;
32 38
 import java.lang.management.ThreadMXBean;
39
+import java.util.Collections;
33 40
 import java.util.HashMap;
34 41
 import java.util.Map;
35 42
 import java.util.Set;
@@ -38,33 +45,52 @@ import javax.management.MBeanServer;
38 45
 import javax.management.ObjectName;
39 46
 
40 47
 /**
41
- * Event queue extention to monitor long running tasks on the EDT. Found at
42
- * http://today.java.net/lpt/a/433
48
+ * Event queue extention to monitor long running tasks on the EDT. Original
49
+ * code found at http://today.java.net/lpt/a/433 modified to work as a DMDirc
50
+ * plugin.
43 51
  */
44
-public class TracingEventQueueThread extends Thread {
52
+public class TracingEventQueue extends DMDircEventQueue implements
53
+        Runnable, ConfigChangeListener {
45 54
 
46
-    private final long thresholdDelay;
55
+    /** Threshold before event is considered long running. */
56
+    private long thresholdDelay;
57
+    /** Map of event to time started. */
47 58
     private final Map<AWTEvent, Long> eventTimeMap;
59
+    /** Thread bean, used to get thread info. */
48 60
     private ThreadMXBean threadBean;
61
+    /** boolean to end thread. */
49 62
     private boolean running = false;
63
+    /** Parent plugin. */
64
+    private final Plugin parentPlugin;
65
+    /** Tracing thread. */
66
+    private Thread tracingThread;
50 67
 
51 68
     /**
52 69
      * Instantiates a new tracing thread.
53
-     * 
54
-     * @param thresholdDelay
55
-     *            Length to consider a long running task
70
+     *
71
+     * @param parentPlugin Parent plugin
72
+     * @param controller Swing controller
56 73
      */
57
-    public TracingEventQueueThread(final long thresholdDelay) {
58
-        this.thresholdDelay = thresholdDelay;
59
-        eventTimeMap = new HashMap<AWTEvent, Long>();
74
+    public TracingEventQueue(final Plugin parentPlugin,
75
+            final SwingController controller) {
76
+        super(controller);
77
+        this.parentPlugin = parentPlugin;
78
+
79
+        eventTimeMap = Collections.synchronizedMap(
80
+                new HashMap<AWTEvent, Long>());
81
+        IdentityManager.getGlobalConfig().addChangeListener(
82
+                parentPlugin.getDomain(), "debugEDT", this);
83
+        IdentityManager.getGlobalConfig().addChangeListener(
84
+                parentPlugin.getDomain(), "slowedttaskthreshold", this);
85
+        checkTracing();
60 86
 
61 87
         try {
62 88
             final MBeanServer mbeanServer = ManagementFactory
63 89
                     .getPlatformMBeanServer();
64 90
             final ObjectName objName = new ObjectName(
65 91
                     ManagementFactory.THREAD_MXBEAN_NAME);
66
-            final Set<ObjectName> mbeans = mbeanServer
67
-                    .queryNames(objName, null);
92
+            final Set<ObjectName> mbeans = mbeanServer.queryNames(objName,
93
+                    null);
68 94
             for (final ObjectName name : mbeans) {
69 95
                 threadBean = ManagementFactory.newPlatformMXBeanProxy(
70 96
                         mbeanServer, name.toString(), ThreadMXBean.class);
@@ -74,28 +100,47 @@ public class TracingEventQueueThread extends Thread {
74 100
         }
75 101
     }
76 102
 
103
+    /** {@inheritDoc} */
104
+    @Override
105
+    protected void preDispatchEvent(final AWTEvent event) {
106
+        eventDispatched(event);
107
+    }
108
+
109
+    /** {@inheritDoc} */
110
+    @Override
111
+    protected void postDispatchEvent(final AWTEvent event) {
112
+        eventProcessed(event);
113
+    }
114
+
115
+
116
+
77 117
     /**
78 118
      * Marks the start time for the specified event.
79
-     * 
80
-     * @param event
81
-     *            Event to monitor
119
+     *
120
+     * @param event Event to monitor
82 121
      */
83
-    public synchronized void eventDispatched(final AWTEvent event) {
122
+    public void eventDispatched(final AWTEvent event) {
84 123
         eventTimeMap.put(event, System.currentTimeMillis());
85 124
     }
86 125
 
87 126
     /**
88 127
      * Marks the end time for the specified event.
89
-     * 
90
-     * @param event
91
-     *            Event to finish monitoring.
128
+     *
129
+     * @param event Event to finish monitoring.
92 130
      */
93
-    public synchronized void eventProcessed(final AWTEvent event) {
94
-        checkEventTime(event, System.currentTimeMillis(), eventTimeMap
95
-                .get(event));
131
+    public void eventProcessed(final AWTEvent event) {
132
+        checkEventTime(event, System.currentTimeMillis(),
133
+                eventTimeMap.get(event));
96 134
         eventTimeMap.put(event, null);
97 135
     }
98 136
 
137
+    /**
138
+     * Check how long an event took, if over threshold notify user.
139
+     *
140
+     * @param event Event to check
141
+     * @param currTime Current time
142
+     * @param startTime Start time
143
+     */
99 144
     private void checkEventTime(final AWTEvent event, final long currTime,
100 145
             final long startTime) {
101 146
         final long currProcessingTime = currTime - startTime;
@@ -112,11 +157,10 @@ public class TracingEventQueueThread extends Thread {
112 157
                             threadId, Integer.MAX_VALUE);
113 158
                     if (threadInfo != null
114 159
                             && threadInfo.getThreadName().startsWith(
115
-                                    "AWT-EventQueue")) {
160
+                            "AWT-EventQueue")) {
116 161
                         System.out.println(threadInfo.getThreadName() + " / "
117 162
                                 + threadInfo.getThreadState());
118
-                        final StackTraceElement[] stack = threadInfo
119
-                                .getStackTrace();
163
+                        final StackTraceElement[] stack = threadInfo.getStackTrace();
120 164
                         for (final StackTraceElement stackEntry : stack) {
121 165
                             System.out.println("\t" + stackEntry.getClassName()
122 166
                                     + "." + stackEntry.getMethodName() + " ["
@@ -125,8 +169,7 @@ public class TracingEventQueueThread extends Thread {
125 169
                     }
126 170
                 }
127 171
 
128
-                final long[] deadlockedThreads = threadBean
129
-                        .findDeadlockedThreads();
172
+                final long[] deadlockedThreads = threadBean.findDeadlockedThreads();
130 173
                 if (deadlockedThreads != null && deadlockedThreads.length > 0) {
131 174
                     System.out.println("Deadlocked threads:");
132 175
                     for (final long threadId : deadlockedThreads) {
@@ -134,8 +177,7 @@ public class TracingEventQueueThread extends Thread {
134 177
                                 threadId, Integer.MAX_VALUE);
135 178
                         System.out.println(threadInfo.getThreadName() + " / "
136 179
                                 + threadInfo.getThreadState());
137
-                        final StackTraceElement[] stack = threadInfo
138
-                                .getStackTrace();
180
+                        final StackTraceElement[] stack = threadInfo.getStackTrace();
139 181
                         for (final StackTraceElement stackEntry : stack) {
140 182
                             System.out.println("\t" + stackEntry.getClassName()
141 183
                                     + "." + stackEntry.getMethodName() + " ["
@@ -153,7 +195,7 @@ public class TracingEventQueueThread extends Thread {
153 195
         running = true;
154 196
         while (running) {
155 197
             final long currTime = System.currentTimeMillis();
156
-            synchronized (this) {
198
+            synchronized (eventTimeMap) {
157 199
                 for (final Map.Entry<AWTEvent, Long> entry : eventTimeMap
158 200
                         .entrySet()) {
159 201
                     final AWTEvent event = entry.getKey();
@@ -165,7 +207,7 @@ public class TracingEventQueueThread extends Thread {
165 207
                 }
166 208
             }
167 209
             try {
168
-                Thread.sleep(100);
210
+                Thread.sleep(thresholdDelay);
169 211
             } catch (final InterruptedException ie) {
170 212
                 // Ignore
171 213
             }
@@ -178,4 +220,24 @@ public class TracingEventQueueThread extends Thread {
178 220
     public void cancel() {
179 221
         running = false;
180 222
     }
181
-}
223
+
224
+    private void checkTracing() {
225
+        final boolean tracing = IdentityManager.getGlobalConfig().
226
+                getOptionBool(parentPlugin.getDomain(), "debugEDT");
227
+        thresholdDelay = IdentityManager.getGlobalConfig().
228
+                getOptionInt(parentPlugin.getDomain(), "slowedttaskthreshold");
229
+        if (tracing) {
230
+            running = true;
231
+            tracingThread = new Thread(this);
232
+            tracingThread.start();
233
+        } else {
234
+            running = false;
235
+        }
236
+    }
237
+
238
+    /** {@inheritDoc} */
239
+    @Override
240
+    public void configChanged(final String domain, final String key) {
241
+        checkTracing();
242
+    }
243
+}

+ 35
- 0
src/com/dmdirc/addons/swingdebug/plugin.config Vedi File

@@ -0,0 +1,35 @@
1
+# This is a DMDirc configuration file.
2
+
3
+# This section indicates which sections below take key/value
4
+# pairs, rather than a simple list. It should be placed above
5
+# any sections that take key/values.
6
+keysections:
7
+  metadata
8
+  updates
9
+  version
10
+  defaults
11
+  requires
12
+
13
+metadata:
14
+  author=Greg <greg@dmdirc.com>
15
+  mainclass=com.dmdirc.addons.swingdebug.SwingDebugPlugin
16
+  description=Debugging plugin for DMDirc.
17
+  name=swingdebug
18
+  nicename=Swing debug
19
+  unloadable=yes
20
+
21
+updates:
22
+  id=60
23
+
24
+version:
25
+  friendly=0.1
26
+
27
+requires:
28
+    parent=ui_swing
29
+
30
+required-services:
31
+    swing ui
32
+
33
+defaults:
34
+    debugEDT=false
35
+    slowedttaskthreshold=100

+ 40
- 128
src/com/dmdirc/addons/ui_swing/DMDircEventQueue.java Vedi File

@@ -28,8 +28,6 @@ import com.dmdirc.addons.ui_swing.actions.CopyAction;
28 28
 import com.dmdirc.addons.ui_swing.actions.CutAction;
29 29
 import com.dmdirc.addons.ui_swing.actions.PasteAction;
30 30
 
31
-import com.dmdirc.config.IdentityManager;
32
-import com.dmdirc.interfaces.ConfigChangeListener;
33 31
 import java.awt.AWTEvent;
34 32
 import java.awt.Component;
35 33
 import java.awt.EventQueue;
@@ -46,47 +44,27 @@ import javax.swing.SwingUtilities;
46 44
 import javax.swing.text.JTextComponent;
47 45
 
48 46
 /**
49
- * Custom event queue to add common functionality to certain components and 
50
- * monitor the EDT for long running tasks.  The monitoring code was taken from
51
- * TracingEventQueue by Kirill Grouchnikov (http://today.java.net/lpt/a/433).
47
+ * Custom event queue to add common functionality to certain components.
52 48
  */
53
-public final class DMDircEventQueue extends EventQueue implements
54
-        ConfigChangeListener {
49
+public class DMDircEventQueue extends EventQueue {
55 50
 
56 51
     /** Swing Controller. */
57
-    private SwingController controller;
58
-    /** Tracing thread. */
59
-    private TracingEventQueueThread tracingThread;
52
+    private final SwingController controller;
60 53
 
61
-    /** 
62
-     * Instantiates the DMDircEventQueue. 
63
-     * 
54
+    /**
55
+     * Instantiates the DMDircEventQueue.
56
+     *
64 57
      * @param controller Swing controller
65 58
      */
66 59
     public DMDircEventQueue(final SwingController controller) {
67 60
         super();
68 61
 
69 62
         this.controller = controller;
70
-        checkTracing();
71
-        IdentityManager.getGlobalConfig().addChangeListener(
72
-                controller.getDomain(), "debugEDT", this);
73 63
     }
74 64
 
75 65
     /** {@inheritDoc} */
76 66
     @Override
77 67
     protected void dispatchEvent(final AWTEvent event) {
78
-        if (tracingThread == null) {
79
-            super.dispatchEvent(event);
80
-        } else {
81
-            if (tracingThread != null) {
82
-                tracingThread.eventDispatched(event);
83
-            }
84
-            super.dispatchEvent(event);
85
-            if (tracingThread != null) {
86
-                tracingThread.eventProcessed(event);
87
-            }
88
-        }
89
-
90 68
         if (event instanceof MouseEvent) {
91 69
             handleMouseEvent((MouseEvent) event);
92 70
         } else if (event instanceof KeyEvent) {
@@ -94,112 +72,54 @@ public final class DMDircEventQueue extends EventQueue implements
94 72
         } else if (event instanceof WindowEvent) {
95 73
             handleWindowEvent((WindowEvent) event);
96 74
         }
75
+        preDispatchEvent(event);
76
+        super.dispatchEvent(event);
77
+        postDispatchEvent(event);
97 78
     }
98 79
 
99
-    private void checkTracing() {
100
-        final boolean tracing = IdentityManager.getGlobalConfig().
101
-                getOptionBool(controller.getDomain(), "debugEDT");
102
-        if (tracing) {
103
-            tracingThread = new TracingEventQueueThread(100);
104
-            tracingThread.start();
105
-        } else {
106
-            if (tracingThread != null) {
107
-                tracingThread.cancel();
108
-                tracingThread = null;
109
-            }
110
-        }
80
+    /**
81
+     * Triggered before the event is dispatched to AWT.
82
+     *
83
+     * @param event Event about to be dispatched
84
+     */
85
+    protected void preDispatchEvent(final AWTEvent event) {
86
+        //Do nothing
87
+    }
88
+
89
+    /**
90
+     * Called just after an event is dispatched to AWT.
91
+     *
92
+     * @param event Event that has been dispatched
93
+     */
94
+    protected void postDispatchEvent(final AWTEvent event) {
95
+        //Do nothing
111 96
     }
112 97
 
113 98
     /**
114 99
      * Handles key events.
115
-     * 
100
+     *
116 101
      * @param ke Key event
117 102
      */
118 103
     private void handleKeyEvent(final KeyEvent ke) {
119
-        switch (ke.getKeyChar()) {
120
-            case KeyEvent.VK_F1:
121
-            //Fallthrough
122
-            case KeyEvent.VK_F2:
123
-            //Fallthrough
124
-            case KeyEvent.VK_F3:
125
-            //Fallthrough
126
-            case KeyEvent.VK_F4:
127
-            //Fallthrough
128
-            case KeyEvent.VK_F5:
129
-            //Fallthrough
130
-            case KeyEvent.VK_F6:
131
-            //Fallthrough
132
-            case KeyEvent.VK_F7:
133
-            //Fallthrough
134
-            case KeyEvent.VK_F8:
135
-            //Fallthrough
136
-            case KeyEvent.VK_F9:
137
-            //Fallthrough
138
-            case KeyEvent.VK_F10:
139
-            //Fallthrough
140
-            case KeyEvent.VK_F11:
141
-            //Fallthrough
142
-            case KeyEvent.VK_F12:
143
-            //Fallthrough
144
-            case KeyEvent.VK_F13:
145
-            //Fallthrough
146
-            case KeyEvent.VK_F14:
147
-            //Fallthrough
148
-            case KeyEvent.VK_F15:
149
-            //Fallthrough
150
-            case KeyEvent.VK_F16:
151
-            //Fallthrough
152
-            case KeyEvent.VK_F17:
153
-            //Fallthrough
154
-            case KeyEvent.VK_F18:
155
-            //Fallthrough
156
-            case KeyEvent.VK_F19:
157
-            //Fallthrough
158
-            case KeyEvent.VK_F20:
159
-            //Fallthrough
160
-            case KeyEvent.VK_F21:
161
-            //Fallthrough
162
-            case KeyEvent.VK_F22:
163
-            //Fallthrough
164
-            case KeyEvent.VK_F23:
165
-            //Fallthrough
166
-            case KeyEvent.VK_F24:
167
-                ActionManager.processEvent(CoreActionType.CLIENT_KEY_PRESSED,
168
-                        null, KeyStroke.getKeyStroke(ke.getKeyChar(),
169
-                        ke.getModifiers()));
170
-                break;
171
-            default:
172
-                if (ke.getModifiers() != 0) {
173
-                    ActionManager.processEvent(CoreActionType.CLIENT_KEY_PRESSED,
174
-                            null, KeyStroke.getKeyStroke(ke.getKeyChar(),
175
-                            ke.getModifiers()));
176
-                }
177
-                break;
178
-        }
104
+        ActionManager.processEvent(CoreActionType.CLIENT_KEY_PRESSED, null,
105
+                KeyStroke.getKeyStroke(ke.getKeyChar(), ke.getModifiers()));
179 106
     }
180 107
 
181 108
     /**
182 109
      * Handles mouse events.
183
-     * 
110
+     *
184 111
      * @param me Mouse event
185 112
      */
186 113
     private void handleMouseEvent(final MouseEvent me) {
187
-        if (!me.isPopupTrigger()) {
188
-            return;
189
-        }
190
-
191
-        if (me.getComponent() == null) {
114
+        if (!me.isPopupTrigger() || me.getComponent() == null) {
192 115
             return;
193 116
         }
194 117
 
195 118
         final Component comp = SwingUtilities.getDeepestComponentAt(
196 119
                 me.getComponent(), me.getX(), me.getY());
197 120
 
198
-        if (!(comp instanceof JTextComponent)) {
199
-            return;
200
-        }
201
-
202
-        if (MenuSelectionManager.defaultManager().getSelectedPath().length > 0) {
121
+        if (!(comp instanceof JTextComponent) || MenuSelectionManager
122
+                .defaultManager().getSelectedPath().length > 0) {
203 123
             return;
204 124
         }
205 125
 
@@ -215,25 +135,17 @@ public final class DMDircEventQueue extends EventQueue implements
215 135
     }
216 136
 
217 137
     /**
218
-     * Handles window events
219
-     * 
220
-     * @param windowEvent Window event
138
+     * Handles window events.
139
+     *
140
+     * @param we Window event
221 141
      */
222 142
     private void handleWindowEvent(final WindowEvent we) {
223
-        if (we.getSource() instanceof Window) {
224
-            if (controller.hasMainFrame()) {
225
-                if (we.getID() == WindowEvent.WINDOW_OPENED) {
226
-                    controller.addTopLevelWindow((Window) we.getSource());
227
-                } else if (we.getID() == WindowEvent.WINDOW_CLOSED) {
228
-                    controller.delTopLevelWindow((Window) we.getSource());
229
-                }
143
+        if ((we.getSource() instanceof Window) && controller.hasMainFrame()) {
144
+            if (we.getID() == WindowEvent.WINDOW_OPENED) {
145
+                controller.addTopLevelWindow((Window) we.getSource());
146
+            } else if (we.getID() == WindowEvent.WINDOW_CLOSED) {
147
+                controller.delTopLevelWindow((Window) we.getSource());
230 148
             }
231 149
         }
232 150
     }
233
-
234
-    /** {@inheritDoc} */
235
-    @Override
236
-    public void configChanged(final String domain, final String key) {
237
-        checkTracing();
238
-    }
239 151
 }

+ 0
- 1
src/com/dmdirc/addons/ui_swing/MainFrame.java Vedi File

@@ -53,7 +53,6 @@ import java.awt.event.WindowListener;
53 53
 import java.lang.reflect.InvocationTargetException;
54 54
 
55 55
 import javax.swing.ImageIcon;
56
-import javax.swing.JDesktopPane;
57 56
 import javax.swing.JFrame;
58 57
 import javax.swing.JPanel;
59 58
 import javax.swing.JSplitPane;

+ 154
- 0
src/com/dmdirc/addons/ui_swing/components/CheckBoxMenuItem.java Vedi File

@@ -0,0 +1,154 @@
1
+/*
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.ui_swing.components;
24
+
25
+import javax.swing.Action;
26
+import javax.swing.Icon;
27
+import javax.swing.JCheckBoxMenuItem;
28
+import javax.swing.MenuElement;
29
+import javax.swing.MenuSelectionManager;
30
+import javax.swing.event.ChangeEvent;
31
+import javax.swing.event.ChangeListener;
32
+
33
+/**
34
+ * Extention of a normal JCheckboxMenuItem that stays open when clicked.
35
+ */
36
+public class CheckBoxMenuItem extends JCheckBoxMenuItem {
37
+
38
+    /** Menu path to use when clicked. */
39
+    private static MenuElement[] path;
40
+
41
+    /**
42
+     * Constructs a new checkbox menu item.
43
+     *
44
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem()
45
+     */
46
+    public CheckBoxMenuItem() {
47
+        super();
48
+        getModel().addChangeListener(new StayOpenListener());
49
+    }
50
+
51
+    /**
52
+     * Constructs a new checkbox menu item with the specified action.
53
+     *
54
+     * @param a Action to use
55
+     *
56
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(Action)
57
+     */
58
+    public CheckBoxMenuItem(final Action a) {
59
+        super(a);
60
+        getModel().addChangeListener(new StayOpenListener());
61
+    }
62
+
63
+    /**
64
+     * Constructs a new checkbox menu item with the specified action.
65
+     *
66
+     * @param icon Icon to use
67
+     *
68
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(Icon)
69
+     */
70
+    public CheckBoxMenuItem(final Icon icon) {
71
+        super(icon);
72
+        getModel().addChangeListener(new StayOpenListener());
73
+    }
74
+
75
+    /**
76
+     * Constructs a new checkbox menu item with the specified text.
77
+     *
78
+     * @param text Text to use
79
+     *
80
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(String)
81
+     */
82
+    public CheckBoxMenuItem(final String text) {
83
+        super(text);
84
+        getModel().addChangeListener(new StayOpenListener());
85
+    }
86
+
87
+    /**
88
+     * Constructs a new checkbox menu item with the specified text and selected
89
+     * state.
90
+     *
91
+     * @param text Text to use
92
+     * @param selected Initial selection state
93
+     *
94
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(String, boolean)
95
+     */
96
+    public CheckBoxMenuItem(final String text, final boolean selected) {
97
+        super(text, selected);
98
+        getModel().addChangeListener(new StayOpenListener());
99
+    }
100
+
101
+    /**
102
+     * Constructs a new checkbox menu item with the specified text and icon.
103
+     *
104
+     * @param text Text to use
105
+     * @param icon Icon to use
106
+     *
107
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(String, Icon)
108
+     */
109
+    public CheckBoxMenuItem(final String text, final Icon icon) {
110
+        super(text, icon);
111
+        getModel().addChangeListener(new StayOpenListener());
112
+    }
113
+
114
+    /**
115
+     * Constructs a new checkbox menu item with the specified text icon and
116
+     * initial selected state.
117
+     *
118
+     * @param text Text to use
119
+     * @param icon Icon to use
120
+     * @param selected Initial selection state
121
+     *
122
+     * @see JCheckBoxMenuItem#JCheckBoxMenuItem(String, Icon, boolean)
123
+     */
124
+    public CheckBoxMenuItem(final String text, final Icon icon,
125
+            final boolean selected) {
126
+        super(text, icon, selected);
127
+        getModel().addChangeListener(new StayOpenListener());
128
+    }
129
+
130
+    /**
131
+     * Overridden to reopen the menu.
132
+     *
133
+     * @param pressTime the time to "hold down" the button, in milliseconds
134
+     */
135
+    @Override
136
+    public void doClick(final int pressTime) {
137
+        super.doClick(pressTime);
138
+        MenuSelectionManager.defaultManager().setSelectedPath(path);
139
+    }
140
+
141
+    /**
142
+     * Listener to restore the saved path when clicked.
143
+     */
144
+    private class StayOpenListener implements ChangeListener {
145
+
146
+        /** {@inheritDoc} */
147
+        @Override
148
+        public void stateChanged(final ChangeEvent e) {
149
+            if (getModel().isArmed() && isShowing()) {
150
+                path = MenuSelectionManager.defaultManager().getSelectedPath();
151
+            }
152
+        }
153
+    }
154
+}

+ 13
- 3
src/com/dmdirc/addons/ui_swing/components/MenuBar.java Vedi File

@@ -77,6 +77,8 @@ public class MenuBar extends JMenuBar implements ActionListener, MenuListener {
77 77
     private final SwingController controller;
78 78
     /** Main frame. */
79 79
     private final MainFrame mainFrame;
80
+    /** Normal menu count. */
81
+    private int menuItemCount = 0;
80 82
 
81 83
     /**
82 84
      * Instantiates a new menu bar.
@@ -97,16 +99,24 @@ public class MenuBar extends JMenuBar implements ActionListener, MenuListener {
97 99
         initSettingsMenu();
98 100
         add(new WindowMenuFrameManager(controller));
99 101
         initHelpMenu();
100
-        add(Box.createHorizontalGlue(), "growx, pushx");
101
-        add(new MDIBar(controller, mainFrame));
102
-        add(Box.createHorizontalStrut(PlatformDefaults.getPanelInsets(1)
102
+        menuItemCount = getComponentCount();
103
+        super.add(Box.createHorizontalGlue(), "growx, pushx");
104
+        super.add(new MDIBar(controller, mainFrame));
105
+        super.add(Box.createHorizontalStrut(PlatformDefaults.getPanelInsets(1)
103 106
                 .getUnit()));
107
+        menuItemCount = getComponentCount() - menuItemCount;
104 108
 
105 109
         getActionMap().setParent(null);
106 110
         getActionMap().clear();
107 111
         menuSelected(null);
108 112
     }
109 113
 
114
+    /** {@inheritDoc} */
115
+    @Override
116
+    public JMenu add(final JMenu c) {
117
+        return (JMenu) super.add(c, getComponentCount() - menuItemCount);
118
+    }
119
+
110 120
     /**
111 121
      * Initialises the server menu.
112 122
      */

+ 0
- 1
src/com/dmdirc/addons/ui_swing/plugin.config Vedi File

@@ -27,7 +27,6 @@ provides:
27 27
   swing ui
28 28
 
29 29
 defaults:
30
-    debugEDT=false
31 30
     windowMenuItems=30
32 31
     windowMenuScrollInterval=250
33 32
     showtopicbar=true

Loading…
Annulla
Salva