Просмотр исходного кода

Merge branch 'dcc-architecture'

Fixes issue 4035

Change-Id: I7c29ec0d55ba00295e85c94e7364ad59bf9bbaa3
Reviewed-on: http://gerrit.dmdirc.com/1220
Automatic-Compile: DMDirc Local Commits <dmdirc@googlemail.com>
Reviewed-by: Gregory Holmes <greg@dmdirc.com>
tags/0.6.4
Chris Smith 14 лет назад
Родитель
Сommit
a2f55161fa

src/com/dmdirc/addons/dcc/DCCChatWindow.java → src/com/dmdirc/addons/dcc/ChatContainer.java Просмотреть файл

@@ -22,8 +22,10 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
+import com.dmdirc.addons.dcc.io.DCCChat;
25 26
 import com.dmdirc.actions.ActionManager;
26 27
 import com.dmdirc.addons.dcc.actions.DCCActions;
28
+import com.dmdirc.ui.WindowManager;
27 29
 import com.dmdirc.ui.interfaces.InputWindow;
28 30
 
29 31
 /**
@@ -31,7 +33,7 @@ import com.dmdirc.ui.interfaces.InputWindow;
31 33
  *
32 34
  * @author Shane 'Dataforce' McCormack
33 35
  */
34
-public class DCCChatWindow extends DCCFrame<InputWindow> implements DCCChatHandler {
36
+public class ChatContainer extends DCCFrameContainer<InputWindow> implements DCCChatHandler {
35 37
 
36 38
     /** The DCCChat object we are a window for */
37 39
     private final DCCChat dcc;
@@ -51,7 +53,7 @@ public class DCCChatWindow extends DCCFrame<InputWindow> implements DCCChatHandl
51 53
      * @param nick My Current Nickname
52 54
      * @param targetNick Nickname of target
53 55
      */
54
-    public DCCChatWindow(final DCCPlugin plugin, final DCCChat dcc,
56
+    public ChatContainer(final DCCPlugin plugin, final DCCChat dcc,
55 57
             final String title, final String nick, final String targetNick) {
56 58
         super(plugin, title, "dcc-chat-inactive", InputWindow.class,
57 59
                 DCCCommandParser.getDCCCommandParser());
@@ -60,9 +62,7 @@ public class DCCChatWindow extends DCCFrame<InputWindow> implements DCCChatHandl
60 62
         nickname = nick;
61 63
         otherNickname = targetNick;
62 64
 
63
-        plugin.addWindow(this);
64
-
65
-        setTitle(title);
65
+        WindowManager.addWindow(plugin.getContainer(), this);
66 66
     }
67 67
 
68 68
     /**

+ 2
- 0
src/com/dmdirc/addons/dcc/DCCChatHandler.java Просмотреть файл

@@ -22,6 +22,8 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
+import com.dmdirc.addons.dcc.io.DCCChat;
26
+
25 27
 /**
26 28
  * This interfaces allows DCC Chat Windows to receive data from a DCCChat
27 29
  *

+ 6
- 3
src/com/dmdirc/addons/dcc/DCCCommand.java Просмотреть файл

@@ -22,6 +22,9 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
+import com.dmdirc.addons.dcc.io.DCCTransfer;
26
+import com.dmdirc.addons.dcc.io.DCC;
27
+import com.dmdirc.addons.dcc.io.DCCChat;
25 28
 import com.dmdirc.FrameContainer;
26 29
 import com.dmdirc.Main;
27 30
 import com.dmdirc.Server;
@@ -97,7 +100,7 @@ public final class DCCCommand extends ServerCommand implements IntelligentComman
97 100
             if (type.equalsIgnoreCase("chat")) {
98 101
                 final DCCChat chat = new DCCChat();
99 102
                 if (myPlugin.listen(chat)) {
100
-                    final DCCChatWindow window = new DCCChatWindow(myPlugin, chat,
103
+                    final ChatContainer window = new ChatContainer(myPlugin, chat,
101 104
                             "*Chat: " + target, myNickname, target);
102 105
 
103 106
                     parser.sendCTCP(target, "DCC", "CHAT chat "
@@ -189,7 +192,7 @@ public final class DCCCommand extends ServerCommand implements IntelligentComman
189 192
 
190 193
                     if (IdentityManager.getGlobalConfig().getOptionBool(
191 194
                             myPlugin.getDomain(), "send.reverse")) {
192
-                        new DCCTransferWindow(myPlugin, send, "Send: "
195
+                        new TransferContainer(myPlugin, send, "Send: "
193 196
                                 + target, target, server);
194 197
                         parser.sendCTCP(target, "DCC", "SEND \""
195 198
                                 + jc.getSelectedFile().getName() + "\" "
@@ -198,7 +201,7 @@ public final class DCCCommand extends ServerCommand implements IntelligentComman
198 201
                                 + (send.isTurbo() ? " T" : ""));
199 202
                     } else {
200 203
                         if (myPlugin.listen(send)) {
201
-                            new DCCTransferWindow(myPlugin, send, "*Send: "
204
+                            new TransferContainer(myPlugin, send, "*Send: "
202 205
                                     + target, target, server);
203 206
                             parser.sendCTCP(target, "DCC", "SEND \""
204 207
                                     + jc.getSelectedFile().getName() + "\" "

src/com/dmdirc/addons/dcc/DCCFrame.java → src/com/dmdirc/addons/dcc/DCCFrameContainer.java Просмотреть файл

@@ -24,20 +24,12 @@ package com.dmdirc.addons.dcc;
24 24
 
25 25
 import com.dmdirc.Server;
26 26
 import com.dmdirc.WritableFrameContainer;
27
-import com.dmdirc.addons.ui_swing.components.frames.InputTextFrame;
28
-import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
29
-import com.dmdirc.addons.ui_swing.SwingController;
30
-import com.dmdirc.commandparser.PopupType;
31 27
 import com.dmdirc.commandparser.parsers.CommandParser;
32
-import com.dmdirc.commandparser.parsers.GlobalCommandParser;
33 28
 import com.dmdirc.config.IdentityManager;
34 29
 import com.dmdirc.ui.WindowManager;
35 30
 import com.dmdirc.ui.input.TabCompleter;
36 31
 import com.dmdirc.ui.interfaces.InputWindow;
37
-
38
-import java.awt.Container;
39
-
40
-import javax.swing.JPopupMenu;
32
+import com.dmdirc.ui.interfaces.Window;
41 33
 
42 34
 /**
43 35
  * This class links DCC objects to a window.
@@ -45,68 +37,7 @@ import javax.swing.JPopupMenu;
45 37
  * @param <T> The type of window which corresponds to this DCC frame
46 38
  * @author Shane 'Dataforce' McCormack
47 39
  */
48
-public abstract class DCCFrame<T extends InputWindow> extends WritableFrameContainer<T> {
49
-
50
-    /**
51
-     * Empty Frame.
52
-     */
53
-    static class EmptyFrame extends InputTextFrame {
54
-
55
-        /** A version number for this class. */
56
-        private static final long serialVersionUID = 200711271;
57
-
58
-        /**
59
-         * Creates a new instance of EmptyFrame.
60
-         *
61
-         * @param owner The frame container that owns this frame
62
-         */
63
-        public EmptyFrame(final SwingController controller, final WritableFrameContainer<?> owner) {
64
-            super(controller, owner);
65
-            setTextPane(null);
66
-            pack();
67
-        }
68
-
69
-        /**
70
-         * Retrieves the command Parser for this input window.
71
-         *
72
-         * @return This window's command parser
73
-         */
74
-        @Override
75
-        public final CommandParser getCommandParser() {
76
-            return GlobalCommandParser.getGlobalCommandParser();
77
-        }
78
-
79
-        /** {@inheritDoc} */
80
-        @Override
81
-        public PopupType getNicknamePopupType() {
82
-            return null;
83
-        }
84
-
85
-        /** {@inheritDoc} */
86
-        @Override
87
-        public PopupType getChannelPopupType() {
88
-            return null;
89
-        }
90
-
91
-        /** {@inheritDoc} */
92
-        @Override
93
-        public PopupType getHyperlinkPopupType() {
94
-            return null;
95
-        }
96
-
97
-        /** {@inheritDoc} */
98
-        @Override
99
-        public PopupType getNormalPopupType() {
100
-            return null;
101
-        }
102
-
103
-        /** {@inheritDoc} */
104
-        @Override
105
-        public void addCustomPopupItems(final JPopupMenu popupMenu) {
106
-            //Add no custom popup items
107
-        }
108
-
109
-    }
40
+public abstract class DCCFrameContainer<T extends InputWindow> extends WritableFrameContainer<T> {
110 41
 
111 42
     /** The dcc plugin that owns this frame */
112 43
     protected final DCCPlugin plugin;
@@ -123,7 +54,7 @@ public abstract class DCCFrame<T extends InputWindow> extends WritableFrameConta
123 54
      * @param windowClass The class of window to use for this container
124 55
      * @param parser Command parser to use for this window
125 56
      */
126
-    public DCCFrame(final DCCPlugin plugin, final String title, final String icon,
57
+    public DCCFrameContainer(final DCCPlugin plugin, final String title, final String icon,
127 58
             final Class<T> windowClass, final CommandParser parser) {
128 59
         super(icon, title, title, windowClass, IdentityManager.getGlobalConfig(), parser);
129 60
         this.plugin = plugin;
@@ -149,15 +80,6 @@ public abstract class DCCFrame<T extends InputWindow> extends WritableFrameConta
149 80
         return 512;
150 81
     }
151 82
 
152
-    /**
153
-     * Returns the content pane of the internal frame associated with this object.
154
-     *
155
-     * @return The content pane of the internal frame associated with this object
156
-     */
157
-    public Container getContentPane() {
158
-        return ((TextFrame) getFrame()).getContentPane();
159
-    }
160
-
161 83
     /**
162 84
      * Returns the server instance associated with this container.
163 85
      *
@@ -189,15 +111,14 @@ public abstract class DCCFrame<T extends InputWindow> extends WritableFrameConta
189 111
         windowClosing = true;
190 112
 
191 113
         // 1: Make the window non-visible
192
-        getFrame().setVisible(false);
114
+        for (Window window : getWindows()) {
115
+            window.setVisible(false);
116
+        }
193 117
 
194 118
         // 2: Remove any callbacks or listeners
195 119
         // 3: Trigger any actions neccessary
196 120
         // 4: Trigger action for the window closing
197
-
198 121
         // 5: Inform any parents that the window is closing
199
-        plugin.delWindow(this);
200
-
201 122
         // 6: Remove the window from the window manager
202 123
         WindowManager.removeWindow(this);
203 124
     }

+ 26
- 121
src/com/dmdirc/addons/dcc/DCCPlugin.java Просмотреть файл

@@ -22,19 +22,16 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
-import com.dmdirc.FrameContainer;
25
+import com.dmdirc.addons.dcc.io.DCCTransfer;
26
+import com.dmdirc.addons.dcc.io.DCC;
27
+import com.dmdirc.addons.dcc.io.DCCChat;
26 28
 import com.dmdirc.Main;
27 29
 import com.dmdirc.Server;
28 30
 import com.dmdirc.actions.ActionManager;
29 31
 import com.dmdirc.actions.CoreActionType;
30 32
 import com.dmdirc.actions.interfaces.ActionType;
31
-import com.dmdirc.addons.dcc.DCCFrame.EmptyFrame;
32 33
 import com.dmdirc.addons.dcc.kde.KFileChooser;
33 34
 import com.dmdirc.addons.dcc.actions.DCCActions;
34
-import com.dmdirc.addons.ui_swing.MainFrame;
35
-import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
36
-import com.dmdirc.addons.ui_swing.components.text.TextLabel;
37
-import com.dmdirc.addons.ui_swing.dialogs.StandardQuestionDialog;
38 35
 import com.dmdirc.commandparser.CommandManager;
39 36
 import com.dmdirc.config.Identity;
40 37
 import com.dmdirc.config.IdentityManager;
@@ -51,11 +48,8 @@ import com.dmdirc.parser.interfaces.Parser;
51 48
 import com.dmdirc.plugins.Plugin;
52 49
 import com.dmdirc.ui.WindowManager;
53 50
 
54
-import java.awt.Dialog.ModalityType;
55 51
 import java.io.File;
56 52
 import java.io.IOException;
57
-import java.util.ArrayList;
58
-import java.util.List;
59 53
 import java.net.InetAddress;
60 54
 import java.net.UnknownHostException;
61 55
 
@@ -74,10 +68,7 @@ public final class DCCPlugin extends Plugin implements ActionListener {
74 68
     private DCCCommand command;
75 69
 
76 70
     /** Our DCC Container window. */
77
-    private DCCFrame container;
78
-
79
-    /** Child Frames. */
80
-    private final List<DCCFrame> childFrames = new ArrayList<DCCFrame>();
71
+    private PlaceholderContainer container;
81 72
 
82 73
     /**
83 74
      * Creates a new instance of the DCC Plugin.
@@ -164,7 +155,7 @@ public final class DCCPlugin extends Plugin implements ActionListener {
164 155
                         }
165 156
                     }
166 157
                     if (reverse && !token.isEmpty()) {
167
-                        new DCCTransferWindow(DCCPlugin.this, send, "*Receive: " + nickname, nickname, null);
158
+                        new TransferContainer(DCCPlugin.this, send, "*Receive: " + nickname, nickname, null);
168 159
                         send.setToken(token);
169 160
                         if (resume) {
170 161
                             if (IdentityManager.getGlobalConfig().getOptionBool(getDomain(), "receive.reverse.sendtoken")) {
@@ -180,7 +171,7 @@ public final class DCCPlugin extends Plugin implements ActionListener {
180 171
                             }
181 172
                         }
182 173
                     } else {
183
-                        new DCCTransferWindow(DCCPlugin.this, send, "Receive: " + nickname, nickname, null);
174
+                        new TransferContainer(DCCPlugin.this, send, "Receive: " + nickname, nickname, null);
184 175
                         if (resume) {
185 176
                             parser.sendCTCP(nickname, "DCC", "RESUME " + sendFilename + " " + send.getPort() + " " + jc.getSelectedFile().length());
186 177
                         } else {
@@ -261,7 +252,7 @@ public final class DCCPlugin extends Plugin implements ActionListener {
261 252
                             return;
262 253
                         }
263 254
                         final String myNickname = ((Server) arguments[0]).getParser().getLocalClient().getNickname();
264
-                        final DCCFrame f = new DCCChatWindow(this, chat, "Chat: " + nickname, myNickname, nickname);
255
+                        final DCCFrameContainer<?> f = new ChatContainer(this, chat, "Chat: " + nickname, myNickname, nickname);
265 256
                         f.addLine("DCCChatStarting", nickname, chat.getHost(), chat.getPort());
266 257
                         chat.connect();
267 258
                     } else {
@@ -394,7 +385,7 @@ public final class DCCPlugin extends Plugin implements ActionListener {
394 385
 
395 386
                         // Now look for a dcc that matches.
396 387
                         for (DCCTransfer send : DCCTransfer.getTransfers()) {
397
-                            if (send.port == port && (new File(send.getFileName())).getName().equalsIgnoreCase(filename)) {
388
+                            if (send.getPort() == port && (new File(send.getFileName())).getName().equalsIgnoreCase(filename)) {
398 389
                                 if ((!token.isEmpty() && !send.getToken().isEmpty()) && (!token.equals(send.getToken()))) {
399 390
                                     continue;
400 391
                                 }
@@ -429,59 +420,34 @@ public final class DCCPlugin extends Plugin implements ActionListener {
429 420
     }
430 421
 
431 422
     /**
432
-     * Create the container window.
433
-     */
434
-    protected void createContainer() {
435
-        container = new PlaceholderDCCFrame(this);
436
-        final TextLabel label = new TextLabel("This is a placeholder window to group DCCs together.");
437
-        label.setText(label.getText() + "\n\nClosing this window will close all the active DCCs");
438
-        ((TextFrame) container.getFrame()).getContentPane().add(label);
439
-        WindowManager.addWindow(container);
440
-        container.getFrame().open();
441
-    }
442
-
443
-    /**
444
-     * Add a window to the container window.
423
+     * Retrieves the container for the placeholder.
445 424
      *
446
-     * @param window Window to remove
425
+     * @since 0.6.4
426
+     * @return This plugin's placeholder container
447 427
      */
448
-    protected synchronized void addWindow(final DCCFrame window) {
449
-        if (window == container) {
450
-            return;
451
-        }
428
+    public synchronized PlaceholderContainer getContainer() {
452 429
         if (container == null) {
453 430
             createContainer();
454 431
         }
455 432
 
456
-        WindowManager.addWindow(container, window);
457
-        childFrames.add(window);
458
-        window.getFrame().open();
433
+        return container;
459 434
     }
460 435
 
461 436
     /**
462
-     * Remove a window from the container window.
437
+     * Removes the cached container.
463 438
      *
464
-     * @param window Window to remove
439
+     * @since 0.6.4
465 440
      */
466
-    protected synchronized void delWindow(final DCCFrame window) {
467
-        if (container == null) {
468
-            return;
469
-        }
470
-        if (window == container) {
471
-            container = null;
472
-            for (DCCFrame win : childFrames) {
473
-                if (win != window) {
474
-                    win.close();
475
-                }
476
-            }
477
-            childFrames.clear();
478
-        } else {
479
-            childFrames.remove(window);
480
-            if (childFrames.isEmpty()) {
481
-                container.close();
482
-                container = null;
483
-            }
484
-        }
441
+    public synchronized void removeContainer() {
442
+        container = null;
443
+    }
444
+
445
+    /**
446
+     * Create the container window.
447
+     */
448
+    protected void createContainer() {
449
+        container = new PlaceholderContainer(this);
450
+        WindowManager.addWindow(container);
485 451
     }
486 452
 
487 453
     /** {@inheritDoc} */
@@ -621,65 +587,4 @@ public final class DCCPlugin extends Plugin implements ActionListener {
621 587
                 "Show the current percentage of transfers in the DCC window title"));
622 588
     }
623 589
 
624
-}
625
-
626
-/**
627
- * Creates a placeholder DCC Frame.
628
- */
629
-class PlaceholderDCCFrame extends DCCFrame<EmptyFrame> {
630
-
631
-    /**
632
-     * Creates a placeholder dcc frame.
633
-     *
634
-     * @param plugin Parent plugin
635
-     */
636
-    public PlaceholderDCCFrame(final DCCPlugin plugin) {
637
-        super(plugin, "DCCs", "dcc", EmptyFrame.class, DCCCommandParser.getDCCCommandParser());
638
-    }
639
-
640
-    @Override
641
-    public void close() {
642
-        int dccs = 0;
643
-        for (FrameContainer<?> window : getChildren()) {
644
-            if (window instanceof DCCTransferWindow) {
645
-                if (((DCCTransferWindow) window).getDCC().isActive()) {
646
-                    dccs++;
647
-                }
648
-            } else if (window instanceof DCCChatWindow) {
649
-                if (((DCCChatWindow) window).getDCC().isActive()) {
650
-                    dccs++;
651
-                }
652
-            }
653
-        }
654
-
655
-        if (dccs > 0) {
656
-            new StandardQuestionDialog(
657
-                    (MainFrame) Main.getUI().getMainWindow(),
658
-                    ModalityType.MODELESS, "Close confirmation",
659
-                    "Closing this window will cause all existing DCCs " +
660
-                    "to terminate, are you sure you want to do this?") {
661
-                /**
662
-                 * A version number for this class. It should be changed whenever the class
663
-                 * structure is changed (or anything else that would prevent serialized
664
-                 * objects being unserialized with the new class).
665
-                 */
666
-                private static final long serialVersionUID = 1;
667
-
668
-                /** {@inheritDoc} */
669
-                @Override
670
-                public boolean save() {
671
-                    PlaceholderDCCFrame.super.close();
672
-                    return true;
673
-                }
674
-
675
-                /** {@inheritDoc} */
676
-                @Override
677
-                public void cancelled() {
678
-                }
679
-            }.display();
680
-        } else {
681
-            super.close();
682
-        }
683
-    }
684
-}
685
-
590
+}

+ 2
- 0
src/com/dmdirc/addons/dcc/DCCTransferHandler.java Просмотреть файл

@@ -22,6 +22,8 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
+import com.dmdirc.addons.dcc.io.DCCTransfer;
26
+
25 27
 /**
26 28
  * This interfaces allows DCC Transfer Windows to receive data from a
27 29
  * DCCTransfer.

+ 0
- 419
src/com/dmdirc/addons/dcc/DCCTransferWindow.java Просмотреть файл

@@ -1,419 +0,0 @@
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.dcc;
24
-
25
-import com.dmdirc.Server;
26
-import com.dmdirc.ServerState;
27
-import com.dmdirc.actions.ActionManager;
28
-import com.dmdirc.addons.dcc.DCCFrame.EmptyFrame;
29
-import com.dmdirc.addons.dcc.actions.DCCActions;
30
-import com.dmdirc.config.IdentityManager;
31
-import com.dmdirc.logger.ErrorLevel;
32
-import com.dmdirc.logger.Logger;
33
-import com.dmdirc.parser.interfaces.Parser;
34
-import com.dmdirc.parser.interfaces.callbacks.SocketCloseListener;
35
-
36
-import java.awt.Desktop;
37
-import java.awt.event.ActionEvent;
38
-import java.awt.event.ActionListener;
39
-import java.io.File;
40
-import java.io.IOException;
41
-import java.util.Date;
42
-
43
-import javax.swing.JButton;
44
-import javax.swing.JLabel;
45
-import javax.swing.JOptionPane;
46
-import javax.swing.JProgressBar;
47
-
48
-import net.miginfocom.swing.MigLayout;
49
-
50
-/**
51
- * This class links DCC Send objects to a window.
52
- *
53
- * @author Shane 'Dataforce' McCormack
54
- */
55
-public class DCCTransferWindow extends DCCFrame<EmptyFrame> implements DCCTransferHandler,
56
-        ActionListener, SocketCloseListener {
57
-
58
-    /** The DCCSend object we are a window for */
59
-    private final DCCTransfer dcc;
60
-
61
-    /** Other Nickname */
62
-    private final String otherNickname;
63
-
64
-    /** Total data transfered */
65
-    private volatile long transferCount = 0;
66
-
67
-    /** Time Started */
68
-    private long timeStarted = 0;
69
-
70
-    /** Progress Bar */
71
-    private final JProgressBar progress = new JProgressBar();
72
-
73
-    /** Status Label */
74
-    private final JLabel status = new JLabel("Status: Waiting");
75
-
76
-    /** Speed Label */
77
-    private final JLabel speed = new JLabel("Speed: Unknown");
78
-
79
-    /** Time Label */
80
-    private final JLabel remaining = new JLabel("Time Remaining: Unknown");
81
-
82
-    /** Time Taken */
83
-    private final JLabel taken = new JLabel("Time Taken: 00:00");
84
-
85
-    /** Button */
86
-    private final JButton button = new JButton("Cancel");
87
-
88
-    /** Open Button */
89
-    private final JButton openButton = new JButton("Open");
90
-
91
-    /** Plugin that this send belongs to. */
92
-    private final DCCPlugin myPlugin;
93
-
94
-    /** IRC Parser that caused this send */
95
-    private Parser parser = null;
96
-
97
-    /** Server that caused this send */
98
-    private Server server = null;
99
-
100
-    /** Show open button. */
101
-    private boolean showOpen = Desktop.isDesktopSupported() &&
102
-            Desktop.getDesktop().isSupported(Desktop.Action.OPEN);
103
-
104
-    /**
105
-     * Creates a new instance of DCCTransferWindow with a given DCCTransfer object.
106
-     *
107
-     * @param plugin the DCC Plugin responsible for this window
108
-     * @param dcc The DCCTransfer object this window wraps around
109
-     * @param title The title of this window
110
-     * @param targetNick Nickname of target
111
-     * @param server The server that initiated this send
112
-     */
113
-    public DCCTransferWindow(final DCCPlugin plugin, final DCCTransfer dcc,
114
-            final String title, final String targetNick, final Server server) {
115
-        super(plugin, title, dcc.getType() == DCCTransfer.TransferType.SEND
116
-                ? "dcc-send-inactive" : "dcc-receive-inactive",
117
-                EmptyFrame.class, DCCCommandParser.getDCCCommandParser());
118
-        this.dcc = dcc;
119
-        this.server = server;
120
-        this.parser = server == null ? null : server.getParser();
121
-        this.myPlugin = plugin;
122
-
123
-        if (parser != null) {
124
-            parser.getCallbackManager().addNonCriticalCallback(SocketCloseListener.class, this);
125
-        }
126
-        dcc.setHandler(this);
127
-
128
-        otherNickname = targetNick;
129
-
130
-        getContentPane().setLayout(new MigLayout("hidemode 0"));
131
-
132
-        progress.setMinimum(0);
133
-        progress.setMaximum(100);
134
-        progress.setStringPainted(true);
135
-        progress.setValue(0);
136
-
137
-        if (dcc.getType() == DCCTransfer.TransferType.SEND) {
138
-            getContentPane().add(new JLabel("Sending: " + dcc.getShortFileName()), "wrap");
139
-            getContentPane().add(new JLabel("To: " + targetNick), "wrap");
140
-        } else {
141
-            getContentPane().add(new JLabel("Recieving: " + dcc.getShortFileName()), "wrap");
142
-            getContentPane().add(new JLabel("From: " + targetNick), "wrap");
143
-        }
144
-        getContentPane().add(status, "wrap");
145
-        getContentPane().add(speed, "wrap");
146
-        getContentPane().add(remaining, "wrap");
147
-        getContentPane().add(taken, "wrap");
148
-        getContentPane().add(progress, "growx, wrap");
149
-
150
-        button.addActionListener(this);
151
-        openButton.addActionListener(this);
152
-        openButton.setVisible(false);
153
-
154
-        getContentPane().add(openButton, "split 2, align right");
155
-        getContentPane().add(button, "align right");
156
-
157
-        plugin.addWindow(this);
158
-    }
159
-
160
-    /** {@inheritDoc} */
161
-    @Override
162
-    public void onSocketClosed(final Parser tParser, final Date date) {
163
-        // Remove our reference to the parser (and its reference to us)
164
-        parser.getCallbackManager().delAllCallback(this);
165
-        parser = null;
166
-        // Can't resend without the parser.
167
-        if ("Resend".equals(button.getText())) {
168
-            button.setText("Close Window");
169
-        }
170
-    }
171
-
172
-    /**
173
-     * Get the DCCSend Object associated with this window
174
-     *
175
-     * @return The DCCSend Object associated with this window
176
-     */
177
-    public DCCTransfer getDCC() {
178
-        return dcc;
179
-    }
180
-
181
-    /**
182
-     * {@inheritDoc}
183
-     *
184
-     * @param e Action event
185
-     */
186
-    @Override
187
-    public void actionPerformed(final ActionEvent e) {
188
-        if (e.getActionCommand().equals("Cancel")) {
189
-            if (dcc.getType() == DCCTransfer.TransferType.SEND) {
190
-                button.setText("Resend");
191
-            } else {
192
-                button.setText("Close Window");
193
-            }
194
-            status.setText("Status: Cancelled");
195
-            dcc.close();
196
-        } else if (e.getActionCommand().equals("Resend")) {
197
-            button.setText("Cancel");
198
-            status.setText("Status: Resending...");
199
-            synchronized (this) {
200
-                transferCount = 0;
201
-            }
202
-            dcc.reset();
203
-            if (parser != null && server.getState() == ServerState.CONNECTED) {
204
-                final String myNickname = parser.getLocalClient().getNickname();
205
-                // Check again incase we have changed nickname to the same nickname that
206
-                // this send is for.
207
-                if (parser.getStringConverter().equalsIgnoreCase(otherNickname, myNickname)) {
208
-                    final Thread errorThread = new Thread(new Runnable() {
209
-
210
-                        /** {@inheritDoc} */
211
-                        @Override
212
-                        public void run() {
213
-                            JOptionPane.showMessageDialog(null,
214
-                                    "You can't DCC yourself.", "DCC Error",
215
-                                    JOptionPane.ERROR_MESSAGE);
216
-                        }
217
-
218
-                    });
219
-                    errorThread.start();
220
-                    return;
221
-                } else {
222
-                    if (IdentityManager.getGlobalConfig().getOptionBool(
223
-                            plugin.getDomain(), "send.reverse")) {
224
-                        parser.sendCTCP(otherNickname, "DCC", "SEND \"" +
225
-                                new File(dcc.getFileName()).getName() + "\" "
226
-                                + DCC.ipToLong(myPlugin.getListenIP(parser))
227
-                                + " 0 " + dcc.getFileSize() + " " + dcc.makeToken()
228
-                                + ((dcc.isTurbo()) ? " T" : ""));
229
-                        return;
230
-                    } else if (plugin.listen(dcc)) {
231
-                        parser.sendCTCP(otherNickname, "DCC", "SEND \""
232
-                                + new File(dcc.getFileName()).getName() + "\" "
233
-                                + DCC.ipToLong(myPlugin.getListenIP(parser)) + " "
234
-                                + dcc.getPort() + " " + dcc.getFileSize()
235
-                                + ((dcc.isTurbo()) ? " T" : ""));
236
-                        return;
237
-                    }
238
-                }
239
-            } else {
240
-                status.setText("Status: Resend failed.");
241
-                button.setText("Close Window");
242
-            }
243
-        } else if (e.getActionCommand().equals("Close Window")) {
244
-            close();
245
-        } else if (e.getSource() == openButton) {
246
-            final File file = new File(dcc.getFileName());
247
-            try {
248
-                Desktop.getDesktop().open(file);
249
-            } catch (IllegalArgumentException ex) {
250
-                    Logger.userError(ErrorLevel.LOW, "Unable to open file: " +
251
-                            file, ex);
252
-                    openButton.setEnabled(false);
253
-            } catch (IOException ex) {
254
-                try {
255
-                    Desktop.getDesktop().open(file.getParentFile());
256
-                } catch (IllegalArgumentException ex1) {
257
-                    Logger.userError(ErrorLevel.LOW, "Unable to open folder: " +
258
-                            file.getParentFile(), ex1);
259
-                    openButton.setEnabled(false);
260
-                } catch (IOException ex1) {
261
-                    Logger.userError(ErrorLevel.LOW, "No associated handler " +
262
-                            "to open file or directory.", ex1);
263
-                    openButton.setEnabled(false);
264
-                }
265
-            }
266
-        }
267
-    }
268
-
269
-    /**
270
-     * Called when data is sent/recieved
271
-     *
272
-     * @param dcc The DCCSend that this message is from
273
-     * @param bytes The number of new bytes that were transfered
274
-     */
275
-    @Override
276
-    public void dataTransfered(final DCCTransfer dcc, final int bytes) {
277
-        final double percent;
278
-        synchronized (this) {
279
-            transferCount += bytes;
280
-            percent = (100.00 / dcc.getFileSize()) * (transferCount + dcc.getFileStart());
281
-        }
282
-
283
-        boolean percentageInTitle = IdentityManager.getGlobalConfig().getOptionBool(
284
-                            plugin.getDomain(), "general.percentageInTitle");
285
-
286
-        if (dcc.getType() == DCCTransfer.TransferType.SEND) {
287
-            status.setText("Status: Sending");
288
-        } else {
289
-            status.setText("Status: Recieving");
290
-        }
291
-
292
-        if (percentageInTitle) {
293
-            final StringBuilder title = new StringBuilder();
294
-            if (dcc.isListenSocket()) { title.append("*"); }
295
-            title.append(dcc.getType() == DCCTransfer.TransferType.SEND ? "Sending: " : "Recieving: ");
296
-            title.append(otherNickname);
297
-            title.append(" ("+ String.format("%.0f", Math.floor(percent)) +"%)");
298
-            setName(title.toString());
299
-            setTitle(title.toString());
300
-        }
301
-
302
-        updateSpeedAndTime();
303
-
304
-        progress.setValue((int) Math.floor(percent));
305
-
306
-        ActionManager.processEvent(DCCActions.DCC_SEND_DATATRANSFERED, null, this, bytes);
307
-    }
308
-
309
-    /**
310
-     * Update the transfer speed, time remaining and time taken labels.
311
-     */
312
-    public void updateSpeedAndTime() {
313
-        final long time = (System.currentTimeMillis() - timeStarted) / 1000;
314
-        final double bytesPerSecond;
315
-        synchronized (this) {
316
-            bytesPerSecond = (time > 0) ? (transferCount / time) : transferCount;
317
-        }
318
-
319
-        if (bytesPerSecond > 1048576) {
320
-            speed.setText(String.format("Speed: %.2f MB/s", (bytesPerSecond / 1048576)));
321
-        } else if (bytesPerSecond > 1024) {
322
-            speed.setText(String.format("Speed: %.2f KB/s", (bytesPerSecond / 1024)));
323
-        } else {
324
-            speed.setText(String.format("Speed: %.2f B/s", bytesPerSecond));
325
-        }
326
-
327
-        final long remaningBytes;
328
-        synchronized (this) {
329
-            remaningBytes = dcc.getFileSize() - dcc.getFileStart() - transferCount;
330
-        }
331
-        final double remainingSeconds = bytesPerSecond > 0
332
-                ? (remaningBytes / bytesPerSecond) : 1;
333
-
334
-        remaining.setText(String.format("Time Remaining: %s", duration(
335
-                (int) Math.floor(remainingSeconds))));
336
-        taken.setText(String.format("Time Taken: %s", timeStarted == 0
337
-                ? "N/A" : duration(time)));
338
-    }
339
-
340
-    /**
341
-     * Get the duration in seconds as a string.
342
-     *
343
-     * @param secondsInput to get duration for
344
-     * @return Duration as a string
345
-     */
346
-    private String duration(final long secondsInput) {
347
-        final StringBuilder result = new StringBuilder();
348
-        final long hours = (secondsInput / 3600);
349
-        final long minutes = (secondsInput / 60 % 60);
350
-        final long seconds = (secondsInput % 60);
351
-
352
-        if (hours > 0) {
353
-            result.append(hours + ":");
354
-        }
355
-        result.append(String.format("%0,2d:%0,2d", minutes, seconds));
356
-
357
-        return result.toString();
358
-    }
359
-
360
-    /**
361
-     * Called when the socket is closed
362
-     *
363
-     * @param dcc The DCCSend that this message is from
364
-     */
365
-    @Override
366
-    public void socketClosed(final DCCTransfer dcc) {
367
-        ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETCLOSED, null, this);
368
-        if (!isWindowClosing()) {
369
-            synchronized (this) {
370
-                if (transferCount == dcc.getFileSize() - dcc.getFileStart()) {
371
-                    status.setText("Status: Transfer Compelete.");
372
-
373
-                    if (showOpen && dcc.getType() == DCCTransfer.TransferType.RECEIVE) {
374
-                        openButton.setVisible(true);
375
-                    }
376
-                    progress.setValue(100);
377
-                    setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
378
-                            ? "dcc-send-done" : "dcc-receive-done");
379
-                    button.setText("Close Window");
380
-                } else {
381
-                    status.setText("Status: Transfer Failed.");
382
-                    setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
383
-                            ? "dcc-send-failed" : "dcc-receive-failed");
384
-                    if (dcc.getType() == DCCTransfer.TransferType.SEND) {
385
-                        button.setText("Resend");
386
-                    } else {
387
-                        button.setText("Close Window");
388
-                    }
389
-                }
390
-            }
391
-            updateSpeedAndTime();
392
-        }
393
-    }
394
-
395
-    /**
396
-     * Called when the socket is opened
397
-     *
398
-     * @param dcc The DCCSend that this message is from
399
-     */
400
-    @Override
401
-    public void socketOpened(final DCCTransfer dcc) {
402
-        ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETOPENED, null, this);
403
-        status.setText("Status: Socket Opened");
404
-        timeStarted = System.currentTimeMillis();
405
-        setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
406
-                ? "dcc-send-active" : "dcc-receive-active");
407
-    }
408
-
409
-    /**
410
-     * Closes this container (and it's associated frame).
411
-     */
412
-    @Override
413
-    public void windowClosing() {
414
-        super.windowClosing();
415
-        dcc.removeFromTransfers();
416
-        dcc.close();
417
-    }
418
-
419
-}

+ 140
- 0
src/com/dmdirc/addons/dcc/PlaceholderContainer.java Просмотреть файл

@@ -0,0 +1,140 @@
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.dcc;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.Main;
27
+import com.dmdirc.Server;
28
+import com.dmdirc.addons.dcc.ui.PlaceholderWindow;
29
+import com.dmdirc.addons.ui_swing.MainFrame;
30
+import com.dmdirc.addons.ui_swing.dialogs.StandardQuestionDialog;
31
+import com.dmdirc.config.IdentityManager;
32
+import com.dmdirc.ui.WindowManager;
33
+import com.dmdirc.ui.interfaces.Window;
34
+import java.awt.Dialog.ModalityType;
35
+
36
+/**
37
+ * Creates a placeholder DCC Frame.
38
+ */
39
+public class PlaceholderContainer extends FrameContainer<PlaceholderWindow> {
40
+
41
+    /** The plugin which owns this placeholder. */
42
+    private final DCCPlugin plugin;
43
+
44
+    /**
45
+     * Creates a placeholder dcc frame.
46
+     *
47
+     * @param plugin The plugin which owns this placeholder
48
+     */
49
+    public PlaceholderContainer(final DCCPlugin plugin) {
50
+        super("dcc", "DCCs", "DCCs", PlaceholderWindow.class, IdentityManager.getGlobalConfig());
51
+
52
+        this.plugin = plugin;
53
+    }
54
+
55
+    /** {@inheritDoc} */
56
+    @Override
57
+    public void close() {
58
+        int dccs = 0;
59
+        for (FrameContainer<?> window : getChildren()) {
60
+            if (window instanceof TransferContainer) {
61
+                if (((TransferContainer) window).getDCC().isActive()) {
62
+                    dccs++;
63
+                }
64
+            } else if (window instanceof ChatContainer) {
65
+                if (((ChatContainer) window).getDCC().isActive()) {
66
+                    dccs++;
67
+                }
68
+            }
69
+        }
70
+
71
+        if (dccs > 0) {
72
+            new StandardQuestionDialog(
73
+                    (MainFrame) Main.getUI().getMainWindow(),
74
+                    ModalityType.MODELESS, "Close confirmation",
75
+                    "Closing this window will cause all existing DCCs " +
76
+                    "to terminate, are you sure you want to do this?") {
77
+                /**
78
+                 * A version number for this class. It should be changed whenever the class
79
+                 * structure is changed (or anything else that would prevent serialized
80
+                 * objects being unserialized with the new class).
81
+                 */
82
+                private static final long serialVersionUID = 1;
83
+
84
+                /** {@inheritDoc} */
85
+                @Override
86
+                public boolean save() {
87
+                    PlaceholderContainer.super.close();
88
+                    return true;
89
+                }
90
+
91
+                /** {@inheritDoc} */
92
+                @Override
93
+                public void cancelled() {
94
+                }
95
+            }.display();
96
+        } else {
97
+            super.close();
98
+        }
99
+    }
100
+
101
+    /** {@inheritDoc} */
102
+    @Override
103
+    public Server getServer() {
104
+        return null;
105
+    }
106
+
107
+    /** {@inheritDoc} */
108
+    @Override
109
+    public void windowClosing() {
110
+        // 1: Make the window non-visible
111
+        for (Window window : getWindows()) {
112
+            window.setVisible(false);
113
+        }
114
+
115
+        // 2: Remove any callbacks or listeners
116
+        // 3: Trigger any actions neccessary
117
+        // 4: Trigger action for the window closing
118
+        // 5: Inform any parents that the window is closing
119
+        plugin.removeContainer();
120
+
121
+        // 6: Remove the window from the window manager
122
+        WindowManager.removeWindow(this);
123
+    }
124
+
125
+    /** {@inheritDoc} */
126
+    @Override
127
+    public void windowClosed() {
128
+        // 7: Remove any references to the window and parents
129
+    }
130
+
131
+    /** {@inheritDoc} */
132
+    @Override
133
+    public void removeChild(final FrameContainer<?> child) {
134
+        super.removeChild(child);
135
+
136
+        if (getChildren().isEmpty()) {
137
+            close();
138
+        }
139
+    }
140
+}

+ 381
- 0
src/com/dmdirc/addons/dcc/TransferContainer.java Просмотреть файл

@@ -0,0 +1,381 @@
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.dcc;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.Server;
27
+import com.dmdirc.ServerState;
28
+import com.dmdirc.actions.ActionManager;
29
+import com.dmdirc.addons.dcc.actions.DCCActions;
30
+import com.dmdirc.addons.dcc.io.DCC;
31
+import com.dmdirc.addons.dcc.io.DCCTransfer;
32
+import com.dmdirc.addons.dcc.ui.TransferWindow;
33
+import com.dmdirc.config.IdentityManager;
34
+import com.dmdirc.parser.interfaces.Parser;
35
+import com.dmdirc.parser.interfaces.callbacks.SocketCloseListener;
36
+import com.dmdirc.ui.WindowManager;
37
+import com.dmdirc.ui.interfaces.Window;
38
+
39
+import java.awt.Desktop;
40
+import java.io.File;
41
+import java.util.Date;
42
+
43
+import javax.swing.JOptionPane;
44
+
45
+/**
46
+ * This class links DCC Send objects to a window.
47
+ *
48
+ * @author Shane 'Dataforce' McCormack
49
+ */
50
+public class TransferContainer extends FrameContainer<TransferWindow> implements
51
+        DCCTransferHandler, SocketCloseListener {
52
+
53
+    /** The dcc plugin that owns this frame */
54
+    protected final DCCPlugin plugin;
55
+
56
+    /** The Window we're using. */
57
+    private boolean windowClosing = false;
58
+
59
+    /** The DCCSend object we are a window for */
60
+    private final DCCTransfer dcc;
61
+
62
+    /** Other Nickname */
63
+    private final String otherNickname;
64
+
65
+    /** Total data transfered */
66
+    private volatile long transferCount = 0;
67
+
68
+    /** Time Started */
69
+    private long timeStarted = 0;
70
+
71
+    /** Plugin that this send belongs to. */
72
+    private final DCCPlugin myPlugin;
73
+
74
+    /** IRC Parser that caused this send */
75
+    private Parser parser = null;
76
+
77
+    /** Server that caused this send */
78
+    private Server server = null;
79
+
80
+    /** Show open button. */
81
+    private boolean showOpen = Desktop.isDesktopSupported() &&
82
+            Desktop.getDesktop().isSupported(Desktop.Action.OPEN);
83
+
84
+    /**
85
+     * Creates a new instance of DCCTransferWindow with a given DCCTransfer object.
86
+     *
87
+     * @param plugin the DCC Plugin responsible for this window
88
+     * @param dcc The DCCTransfer object this window wraps around
89
+     * @param title The title of this window
90
+     * @param targetNick Nickname of target
91
+     * @param server The server that initiated this send
92
+     */
93
+    public TransferContainer(final DCCPlugin plugin, final DCCTransfer dcc,
94
+            final String title, final String targetNick, final Server server) {
95
+        super(dcc.getType() == DCCTransfer.TransferType.SEND
96
+                ? "dcc-send-inactive" : "dcc-receive-inactive",
97
+                title, title, TransferWindow.class, IdentityManager.getGlobalConfig());
98
+        this.plugin = plugin;
99
+        this.dcc = dcc;
100
+        this.server = server;
101
+        this.parser = server == null ? null : server.getParser();
102
+        this.myPlugin = plugin;
103
+
104
+        if (parser != null) {
105
+            parser.getCallbackManager().addNonCriticalCallback(SocketCloseListener.class, this);
106
+        }
107
+        dcc.addHandler(this);
108
+
109
+        otherNickname = targetNick;
110
+
111
+        WindowManager.addWindow(plugin.getContainer(), this);
112
+    }
113
+
114
+    /** {@inheritDoc} */
115
+    @Override
116
+    public void onSocketClosed(final Parser parser, final Date date) {
117
+        // Remove our reference to the parser (and its reference to us)
118
+        this.parser.getCallbackManager().delAllCallback(this);
119
+        this.parser = null;
120
+    }
121
+
122
+    /**
123
+     * Get the DCCSend Object associated with this window
124
+     *
125
+     * @return The DCCSend Object associated with this window
126
+     */
127
+    public DCCTransfer getDCC() {
128
+        return dcc;
129
+    }
130
+
131
+    /**
132
+     * Retrieves the nickname of the other party involved in this transfer.
133
+     *
134
+     * @return The other party's nickname
135
+     * @since 0.6.4
136
+     */
137
+    public String getOtherNickname() {
138
+        return otherNickname;
139
+    }
140
+
141
+    /**
142
+     * Called when data is sent/recieved
143
+     *
144
+     * @param dcc The DCCSend that this message is from
145
+     * @param bytes The number of new bytes that were transfered
146
+     */
147
+    @Override
148
+    public void dataTransfered(final DCCTransfer dcc, final int bytes) {
149
+        final double percent;
150
+        synchronized (this) {
151
+            transferCount += bytes;
152
+            percent = getPercent();
153
+        }
154
+
155
+        boolean percentageInTitle = IdentityManager.getGlobalConfig().getOptionBool(
156
+                            plugin.getDomain(), "general.percentageInTitle");
157
+
158
+        if (percentageInTitle) {
159
+            final StringBuilder title = new StringBuilder();
160
+            if (dcc.isListenSocket()) { title.append("*"); }
161
+            title.append(dcc.getType() == DCCTransfer.TransferType.SEND ? "Sending: " : "Recieving: ");
162
+            title.append(otherNickname);
163
+            title.append(" ("+ String.format("%.0f", Math.floor(percent)) +"%)");
164
+            setName(title.toString());
165
+            setTitle(title.toString());
166
+        }
167
+
168
+        ActionManager.processEvent(DCCActions.DCC_SEND_DATATRANSFERED, null, this, bytes);
169
+    }
170
+
171
+    /**
172
+     * Retrieves the current percentage progress of this transfer.
173
+     *
174
+     * @since 0.6.4
175
+     * @return The percentage of this transfer that has been completed
176
+     */
177
+    public double getPercent() {
178
+        return (100.00 / dcc.getFileSize()) * (transferCount + dcc.getFileStart());
179
+    }
180
+
181
+    /**
182
+     * Retrieves the current transfer speed of this transfer.
183
+     *
184
+     * @since 0.6.4
185
+     * @return The speed of this transfer in Bytes/Sec
186
+     */
187
+    public double getBytesPerSecond() {
188
+        final long time = getElapsedTime();
189
+
190
+        synchronized (this) {
191
+            return time > 0 ? (transferCount / time) : transferCount;
192
+        }
193
+    }
194
+
195
+    /**
196
+     * Retrieves the estimated time remaining for this transfer.
197
+     *
198
+     * @since 0.6.4
199
+     * @return The number of seconds estimated for this transfer to complete
200
+     */
201
+    public double getRemainingTime() {
202
+        final double bytesPerSecond = getBytesPerSecond();
203
+        final long remaningBytes;
204
+
205
+        synchronized (this) {
206
+            remaningBytes = dcc.getFileSize() - dcc.getFileStart() - transferCount;
207
+        }
208
+
209
+        return bytesPerSecond > 0 ? (remaningBytes / bytesPerSecond) : 1;
210
+    }
211
+
212
+    /**
213
+     * Retrieves the timestamp at which this transfer started.
214
+     *
215
+     * @since 0.6.4
216
+     * @return The timestamp (milliseconds since 01/01/1970) at which this transfer started.
217
+     */
218
+    public long getStartTime() {
219
+        return timeStarted;
220
+    }
221
+
222
+    /**
223
+     * Retrieves the number of seconds that this transfer has been running for.
224
+     *
225
+     * @since 0.6.4
226
+     * @return The number of seconds elapsed since this transfer started
227
+     */
228
+    public long getElapsedTime() {
229
+        return (System.currentTimeMillis() - timeStarted) / 1000;
230
+    }
231
+
232
+    /**
233
+     * Determines whether this transfer is complete or not.
234
+     *
235
+     * @since 0.6.4
236
+     * @return True if the transfer is complete, false otherwise
237
+     */
238
+    public boolean isComplete() {
239
+        return transferCount == dcc.getFileSize() - dcc.getFileStart();
240
+    }
241
+
242
+    /**
243
+     * Determines whether the "Open" button should be displayed for this
244
+     * transfer.
245
+     *
246
+     * @since 0.6.4
247
+     * @return True if the open button should be displayed, false otherwise
248
+     */
249
+    public boolean shouldShowOpenButton() {
250
+        return showOpen && dcc.getType() == DCCTransfer.TransferType.RECEIVE;
251
+    }
252
+
253
+    /**
254
+     * Called when the socket is closed
255
+     *
256
+     * @param dcc The DCCSend that this message is from
257
+     */
258
+    @Override
259
+    public void socketClosed(final DCCTransfer dcc) {
260
+        ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETCLOSED, null, this);
261
+        if (!windowClosing) {
262
+            synchronized (this) {
263
+                if (transferCount == dcc.getFileSize() - dcc.getFileStart()) {
264
+                    setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
265
+                            ? "dcc-send-done" : "dcc-receive-done");
266
+                } else {
267
+                    setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
268
+                            ? "dcc-send-failed" : "dcc-receive-failed");
269
+                }
270
+            }
271
+        }
272
+    }
273
+
274
+    /**
275
+     * Called when the socket is opened
276
+     *
277
+     * @param dcc The DCCSend that this message is from
278
+     */
279
+    @Override
280
+    public void socketOpened(final DCCTransfer dcc) {
281
+        ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETOPENED, null, this);
282
+        timeStarted = System.currentTimeMillis();
283
+        setIcon(dcc.getType() == DCCTransfer.TransferType.SEND
284
+                ? "dcc-send-active" : "dcc-receive-active");
285
+    }
286
+
287
+    /**
288
+     * Attempts to resend the transfer.
289
+     *
290
+     * @since 0.6.4
291
+     * @return True if the transfer could be resent, false otherwise
292
+     */
293
+    public boolean resend() {
294
+        synchronized (this) {
295
+            transferCount = 0;
296
+        }
297
+        dcc.reset();
298
+
299
+        if (server != null && server.getState() == ServerState.CONNECTED) {
300
+            final String myNickname = server.getParser().getLocalClient().getNickname();
301
+            // Check again incase we have changed nickname to the same nickname that
302
+            // this send is for.
303
+            if (server.getParser().getStringConverter().equalsIgnoreCase(
304
+                    otherNickname, myNickname)) {
305
+                final Thread errorThread = new Thread(new Runnable() {
306
+
307
+                    /** {@inheritDoc} */
308
+                    @Override
309
+                    public void run() {
310
+                        JOptionPane.showMessageDialog(null,
311
+                                "You can't DCC yourself.", "DCC Error",
312
+                                JOptionPane.ERROR_MESSAGE);
313
+                    }
314
+
315
+                });
316
+                errorThread.start();
317
+            } else {
318
+                if (IdentityManager.getGlobalConfig().getOptionBool(
319
+                        plugin.getDomain(), "send.reverse")) {
320
+                    parser.sendCTCP(otherNickname, "DCC", "SEND \"" +
321
+                            new File(dcc.getFileName()).getName() + "\" "
322
+                            + DCC.ipToLong(myPlugin.getListenIP(parser))
323
+                            + " 0 " + dcc.getFileSize() + " " + dcc.makeToken()
324
+                            + ((dcc.isTurbo()) ? " T" : ""));
325
+                } else if (plugin.listen(dcc)) {
326
+                    parser.sendCTCP(otherNickname, "DCC", "SEND \""
327
+                            + new File(dcc.getFileName()).getName() + "\" "
328
+                            + DCC.ipToLong(myPlugin.getListenIP(parser)) + " "
329
+                            + dcc.getPort() + " " + dcc.getFileSize()
330
+                            + ((dcc.isTurbo()) ? " T" : ""));
331
+                }
332
+            }
333
+
334
+            return true;
335
+        }
336
+
337
+        return false;
338
+    }
339
+
340
+    /**
341
+     * Closes this container (and it's associated frame).
342
+     */
343
+    @Override
344
+    public void windowClosing() {
345
+        windowClosing = true;
346
+
347
+        // 1: Make the window non-visible
348
+        for (Window window : getWindows()) {
349
+            window.setVisible(false);
350
+        }
351
+
352
+        // 2: Remove any callbacks or listeners
353
+        // 3: Trigger any actions neccessary
354
+        dcc.removeFromTransfers();
355
+        
356
+        // 4: Trigger action for the window closing
357
+        // 5: Inform any parents that the window is closing
358
+        // 6: Remove the window from the window manager
359
+        WindowManager.removeWindow(this);
360
+    }
361
+
362
+    /** {@inheritDoc} */
363
+    @Override
364
+    public void windowClosed() {
365
+        // 7: Remove any references to the window and parents
366
+    }
367
+
368
+    public void addSocketCloseCallback(final SocketCloseListener listener) {
369
+        if (server != null && server.getParser() != null) {
370
+            server.getParser().getCallbackManager()
371
+                    .addNonCriticalCallback(SocketCloseListener.class, listener);
372
+        }
373
+    }
374
+
375
+    /** {@inheritDoc} */
376
+    @Override
377
+    public Server getServer() {
378
+        return null;
379
+    }
380
+
381
+}

+ 9
- 9
src/com/dmdirc/addons/dcc/actions/DCCEvents.java Просмотреть файл

@@ -25,8 +25,8 @@ package com.dmdirc.addons.dcc.actions;
25 25
 import com.dmdirc.Server;
26 26
 import com.dmdirc.actions.interfaces.ActionMetaType;
27 27
 
28
-import com.dmdirc.addons.dcc.DCCChatWindow;
29
-import com.dmdirc.addons.dcc.DCCTransferWindow;
28
+import com.dmdirc.addons.dcc.ChatContainer;
29
+import com.dmdirc.addons.dcc.TransferContainer;
30 30
 
31 31
 import java.io.File;
32 32
 
@@ -42,19 +42,19 @@ public enum DCCEvents implements ActionMetaType {
42 42
     /** DCC Chat Request Sent. */
43 43
     DCC_CHAT_REQUEST_SENT(new String[]{"server", "client"}, Server.class, String.class),
44 44
     /** DCC Message from another person. */
45
-    DCC_CHAT_MESSAGE(new String[]{"DCCChatWindow", "Nickname", "Message"}, DCCChatWindow.class, String.class, String.class),
45
+    DCC_CHAT_MESSAGE(new String[]{"DCCChatWindow", "Nickname", "Message"}, ChatContainer.class, String.class, String.class),
46 46
     /** DCC Message to another person. */
47
-    DCC_CHAT_SELFMESSAGE(new String[]{"DCCChatWindow", "Message"}, DCCChatWindow.class, String.class),
47
+    DCC_CHAT_SELFMESSAGE(new String[]{"DCCChatWindow", "Message"}, ChatContainer.class, String.class),
48 48
     /** DCC Chat Socket Closed. */
49
-    DCC_CHAT_SOCKETCLOSED(new String[]{"DCCChatWindow"}, DCCChatWindow.class),
49
+    DCC_CHAT_SOCKETCLOSED(new String[]{"DCCChatWindow"}, ChatContainer.class),
50 50
     /** DCC Chat Socket Opened. */
51
-    DCC_CHAT_SOCKETOPENED(new String[]{"DCCChatWindow"}, DCCChatWindow.class),
51
+    DCC_CHAT_SOCKETOPENED(new String[]{"DCCChatWindow"}, ChatContainer.class),
52 52
     /** DCC Send Socket Closed. */
53
-    DCC_SEND_SOCKETCLOSED(new String[]{"DCCSendWindow"}, DCCTransferWindow.class),
53
+    DCC_SEND_SOCKETCLOSED(new String[]{"DCCSendWindow"}, TransferContainer.class),
54 54
     /** DCC Send Socket Opened. */
55
-    DCC_SEND_SOCKETOPENED(new String[]{"DCCSendWindow"}, DCCTransferWindow.class),
55
+    DCC_SEND_SOCKETOPENED(new String[]{"DCCSendWindow"}, TransferContainer.class),
56 56
     /** DCC Send Data Transfered */
57
-    DCC_SEND_DATATRANSFERED(new String[]{"DCCSendWindow", "Bytes Transfered"}, DCCTransferWindow.class, int.class),
57
+    DCC_SEND_DATATRANSFERED(new String[]{"DCCSendWindow", "Bytes Transfered"}, TransferContainer.class, int.class),
58 58
     /** DCC Send Request. */
59 59
     DCC_SEND_REQUEST(new String[]{"server", "client", "file"}, Server.class, String.class, String.class),
60 60
     /** DCC Send Request Sent. */

src/com/dmdirc/addons/dcc/DCC.java → src/com/dmdirc/addons/dcc/io/DCC.java Просмотреть файл

@@ -20,7 +20,7 @@
20 20
  * SOFTWARE.
21 21
  */
22 22
 
23
-package com.dmdirc.addons.dcc;
23
+package com.dmdirc.addons.dcc.io;
24 24
 
25 25
 import java.net.Socket;
26 26
 import java.net.ServerSocket;
@@ -206,7 +206,7 @@ public abstract class DCC implements Runnable {
206 206
     /**
207 207
      * Called to close the socket
208 208
      */
209
-    protected void close() {
209
+    public void close() {
210 210
         boolean haveSLS = false;
211 211
 
212 212
         while (!serverSocketSem.tryAcquire() && !(haveSLS = serverListeningSem.tryAcquire())) {

src/com/dmdirc/addons/dcc/DCCChat.java → src/com/dmdirc/addons/dcc/io/DCCChat.java Просмотреть файл

@@ -20,8 +20,9 @@
20 20
  * SOFTWARE.
21 21
  */
22 22
 
23
-package com.dmdirc.addons.dcc;
23
+package com.dmdirc.addons.dcc.io;
24 24
 
25
+import com.dmdirc.addons.dcc.DCCChatHandler;
25 26
 import java.io.BufferedReader;
26 27
 import java.io.IOException;
27 28
 import java.io.InputStreamReader;

src/com/dmdirc/addons/dcc/DCCTransfer.java → src/com/dmdirc/addons/dcc/io/DCCTransfer.java Просмотреть файл

@@ -20,7 +20,10 @@
20 20
  * SOFTWARE.
21 21
  */
22 22
 
23
-package com.dmdirc.addons.dcc;
23
+package com.dmdirc.addons.dcc.io;
24
+
25
+import com.dmdirc.addons.dcc.DCCTransferHandler;
26
+import com.dmdirc.util.ListenerList;
24 27
 
25 28
 import java.io.DataInputStream;
26 29
 import java.io.DataOutputStream;
@@ -52,8 +55,8 @@ public class DCCTransfer extends DCC {
52 55
     /** The File transfer type for this file. */
53 56
     private TransferType transferType = TransferType.RECEIVE;
54 57
 
55
-    /** The handler for this DCCSend. */
56
-    private DCCTransferHandler handler;
58
+    /** The handlers for this DCCSend. */
59
+    private final ListenerList handlers = new ListenerList();
57 60
 
58 61
     /** Used to send data out the socket. */
59 62
     private DataOutputStream out;
@@ -326,8 +329,8 @@ public class DCCTransfer extends DCC {
326 329
      *
327 330
      * @param handler A class implementing DCCTransferHandler
328 331
      */
329
-    public void setHandler(final DCCTransferHandler handler) {
330
-        this.handler = handler;
332
+    public void addHandler(final DCCTransferHandler handler) {
333
+        handlers.add(DCCTransferHandler.class, handler);
331 334
     }
332 335
 
333 336
     /** {@inheritDoc} */
@@ -342,7 +345,8 @@ public class DCCTransfer extends DCC {
342 345
             }
343 346
             out = new DataOutputStream(socket.getOutputStream());
344 347
             in = new DataInputStream(socket.getInputStream());
345
-            if (handler != null) {
348
+
349
+            for (DCCTransferHandler handler : handlers.get(DCCTransferHandler.class)) {
346 350
                 handler.socketOpened(this);
347 351
             }
348 352
         } catch (IOException ioe) {
@@ -368,7 +372,8 @@ public class DCCTransfer extends DCC {
368 372
         }
369 373
         out = null;
370 374
         in = null;
371
-        if (handler != null) {
375
+        
376
+        for (DCCTransferHandler handler : handlers.get(DCCTransferHandler.class)) {
372 377
             handler.socketClosed(this);
373 378
         }
374 379
         // Try to delete empty files.
@@ -408,7 +413,7 @@ public class DCCTransfer extends DCC {
408 413
             readSize = readSize + bytesRead;
409 414
 
410 415
             if (bytesRead > 0) {
411
-                if (handler != null) {
416
+                for (DCCTransferHandler handler : handlers.get(DCCTransferHandler.class)) {
412 417
                     handler.dataTransfered(this, bytesRead);
413 418
                 }
414 419
                 fileOut.write(data, 0, bytesRead);
@@ -453,7 +458,7 @@ public class DCCTransfer extends DCC {
453 458
             readSize = readSize + bytesRead;
454 459
 
455 460
             if (bytesRead > 0) {
456
-                if (handler != null) {
461
+                for (DCCTransferHandler handler : handlers.get(DCCTransferHandler.class)) {
457 462
                     handler.dataTransfered(this, bytesRead);
458 463
                 }
459 464
                 out.write(data, 0, bytesRead);

+ 81
- 0
src/com/dmdirc/addons/dcc/ui/EmptyWindow.java Просмотреть файл

@@ -0,0 +1,81 @@
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.dcc.ui;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.addons.ui_swing.SwingController;
27
+import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
28
+import com.dmdirc.commandparser.PopupType;
29
+
30
+import javax.swing.JPopupMenu;
31
+
32
+/**
33
+ * Empty Frame.
34
+ */
35
+public class EmptyWindow extends TextFrame {
36
+
37
+    /** A version number for this class. */
38
+    private static final long serialVersionUID = 2l;
39
+
40
+    /**
41
+     * Creates a new empty window for the specified UI controller and owner.
42
+     *
43
+     * @param controller The UIController that owns this window
44
+     * @param owner The frame container that owns this window
45
+     */
46
+    public EmptyWindow(final SwingController controller, final FrameContainer<?> owner) {
47
+        super(owner, controller);
48
+        setTextPane(null);
49
+        pack();
50
+    }
51
+
52
+    /** {@inheritDoc} */
53
+    @Override
54
+    public PopupType getNicknamePopupType() {
55
+        return null;
56
+    }
57
+
58
+    /** {@inheritDoc} */
59
+    @Override
60
+    public PopupType getChannelPopupType() {
61
+        return null;
62
+    }
63
+
64
+    /** {@inheritDoc} */
65
+    @Override
66
+    public PopupType getHyperlinkPopupType() {
67
+        return null;
68
+    }
69
+
70
+    /** {@inheritDoc} */
71
+    @Override
72
+    public PopupType getNormalPopupType() {
73
+        return null;
74
+    }
75
+
76
+    /** {@inheritDoc} */
77
+    @Override
78
+    public void addCustomPopupItems(final JPopupMenu popupMenu) {
79
+        //Add no custom popup items
80
+    }
81
+}

+ 56
- 0
src/com/dmdirc/addons/dcc/ui/PlaceholderWindow.java Просмотреть файл

@@ -0,0 +1,56 @@
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.dcc.ui;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.addons.ui_swing.SwingController;
27
+import com.dmdirc.addons.ui_swing.components.text.TextLabel;
28
+
29
+/**
30
+ * A virtually empty window which serves as a top-level placeholder for other
31
+ * DCC windows.
32
+ * 
33
+ * @author chris
34
+ * @since 0.6.4
35
+ */
36
+public class PlaceholderWindow extends EmptyWindow {
37
+
38
+    /** A version number for this class. */
39
+    private static final long serialVersionUID = 1l;
40
+
41
+    /**
42
+     * Creates a new placeholder window for the specified UI controller and owner.
43
+     *
44
+     * @param controller The UIController that owns this window
45
+     * @param owner The frame container that owns this window
46
+     */
47
+    public PlaceholderWindow(final SwingController controller,
48
+            final FrameContainer<?> owner) {
49
+        super(controller, owner);
50
+
51
+        add(new TextLabel(
52
+                "This is a placeholder window to group DCCs together."
53
+                + "\n\nClosing this window will close all the active DCCs"));
54
+    }
55
+
56
+}

+ 278
- 0
src/com/dmdirc/addons/dcc/ui/TransferWindow.java Просмотреть файл

@@ -0,0 +1,278 @@
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.dcc.ui;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.addons.dcc.DCCTransferHandler;
27
+import com.dmdirc.addons.dcc.TransferContainer;
28
+import com.dmdirc.addons.dcc.io.DCCTransfer;
29
+import com.dmdirc.addons.ui_swing.SwingController;
30
+import com.dmdirc.addons.ui_swing.UIUtilities;
31
+import com.dmdirc.logger.ErrorLevel;
32
+import com.dmdirc.logger.Logger;
33
+import com.dmdirc.parser.interfaces.Parser;
34
+import com.dmdirc.parser.interfaces.callbacks.SocketCloseListener;
35
+
36
+import java.awt.Desktop;
37
+import java.awt.event.ActionEvent;
38
+import java.awt.event.ActionListener;
39
+import java.io.File;
40
+import java.io.IOException;
41
+import java.util.Date;
42
+
43
+import javax.swing.JButton;
44
+import javax.swing.JLabel;
45
+import javax.swing.JProgressBar;
46
+
47
+import net.miginfocom.swing.MigLayout;
48
+
49
+/**
50
+ * A window for displaying the progress of DCC transfers.
51
+ *
52
+ * @author chris
53
+ * @since 0.6.4
54
+ */
55
+public class TransferWindow extends EmptyWindow implements ActionListener,
56
+        SocketCloseListener, DCCTransferHandler {
57
+
58
+    /** A version number for this class. */
59
+    private static final long serialVersionUID = 1l;
60
+
61
+    /** Progress Bar */
62
+    private final JProgressBar progress = new JProgressBar();
63
+
64
+    /** Status Label */
65
+    private final JLabel status = new JLabel("Status: Waiting");
66
+
67
+    /** Speed Label */
68
+    private final JLabel speed = new JLabel("Speed: Unknown");
69
+
70
+    /** Time Label */
71
+    private final JLabel remaining = new JLabel("Time Remaining: Unknown");
72
+
73
+    /** Time Taken */
74
+    private final JLabel taken = new JLabel("Time Taken: 00:00");
75
+
76
+    /** Button */
77
+    private final JButton button = new JButton("Cancel");
78
+
79
+    /** Open Button */
80
+    private final JButton openButton = new JButton("Open");
81
+
82
+    /** The transfer that this window is showing. */
83
+    private final DCCTransfer dcc;
84
+
85
+    /**
86
+     * Creates a new transfer window for the specified UI controller and owner.
87
+     *
88
+     * @param controller The UIController that owns this window
89
+     * @param owner The frame container that owns this window
90
+     */
91
+    public TransferWindow(final SwingController controller, final FrameContainer<?> owner) {
92
+        super(controller, owner);
93
+        
94
+        final TransferContainer container = (TransferContainer) owner;
95
+        dcc = container.getDCC();
96
+
97
+        dcc.addHandler(this);
98
+        container.addSocketCloseCallback(this);
99
+
100
+        setLayout(new MigLayout("hidemode 0"));
101
+
102
+        if (dcc.getType() == DCCTransfer.TransferType.SEND) {
103
+            add(new JLabel("Sending: " + dcc.getShortFileName()), "wrap");
104
+            add(new JLabel("To: " + container.getOtherNickname()), "wrap");
105
+        } else {
106
+            add(new JLabel("Recieving: " + dcc.getShortFileName()), "wrap");
107
+            add(new JLabel("From: " + container.getOtherNickname()), "wrap");
108
+        }
109
+
110
+        add(status, "wrap");
111
+        add(speed, "wrap");
112
+        add(remaining, "wrap");
113
+        add(taken, "wrap");
114
+        add(progress, "growx, wrap");
115
+
116
+        button.addActionListener(this);
117
+        openButton.addActionListener(this);
118
+        openButton.setVisible(false);
119
+
120
+        add(openButton, "split 2, align right");
121
+        add(button, "align right");
122
+    }
123
+
124
+    /** {@inheritDoc} */
125
+    @Override
126
+    public void actionPerformed(final ActionEvent e) {
127
+        if (e.getActionCommand().equals("Cancel")) {
128
+            if (dcc.getType() == DCCTransfer.TransferType.SEND) {
129
+                button.setText("Resend");
130
+            } else {
131
+                button.setText("Close Window");
132
+            }
133
+            status.setText("Status: Cancelled");
134
+            dcc.close();
135
+        } else if (e.getActionCommand().equals("Resend")) {
136
+            button.setText("Cancel");
137
+            status.setText("Status: Resending...");
138
+
139
+            if (!((TransferContainer) frameParent).resend()) {
140
+                status.setText("Status: Resend failed.");
141
+                button.setText("Close Window");
142
+            }
143
+        } else if (e.getActionCommand().equals("Close Window")) {
144
+            close();
145
+        } else if (e.getSource() == openButton) {
146
+            final File file = new File(dcc.getFileName());
147
+            try {
148
+                Desktop.getDesktop().open(file);
149
+            } catch (IllegalArgumentException ex) {
150
+                Logger.userError(ErrorLevel.LOW, "Unable to open file: " + file, ex);
151
+                openButton.setEnabled(false);
152
+            } catch (IOException ex) {
153
+                try {
154
+                    Desktop.getDesktop().open(file.getParentFile());
155
+                } catch (IllegalArgumentException ex1) {
156
+                    Logger.userError(ErrorLevel.LOW, "Unable to open folder: " +
157
+                            file.getParentFile(), ex1);
158
+                    openButton.setEnabled(false);
159
+                } catch (IOException ex1) {
160
+                    Logger.userError(ErrorLevel.LOW, "No associated handler " +
161
+                            "to open file or directory.", ex1);
162
+                    openButton.setEnabled(false);
163
+                }
164
+            }
165
+        }
166
+    }
167
+
168
+    /** {@inheritDoc} */
169
+    @Override
170
+    public void onSocketClosed(final Parser parser, final Date date) {
171
+        // Can't resend without the parser.
172
+        if ("Resend".equals(button.getText())) {
173
+            button.setText("Close Window");
174
+        }
175
+    }
176
+
177
+    /** {@inheritDoc} */
178
+    @Override
179
+    public void socketClosed(final DCCTransfer dcc) {
180
+        UIUtilities.invokeLater(new Runnable() {
181
+
182
+            private final TransferContainer container = (TransferContainer) frameParent;
183
+
184
+            /** {@inheritDoc} */
185
+            @Override
186
+            public void run() {
187
+                if (container.isComplete()) {
188
+                    status.setText("Status: Transfer Compelete.");
189
+
190
+                    if (container.shouldShowOpenButton()) {
191
+                        openButton.setVisible(true);
192
+                    }
193
+                    
194
+                    progress.setValue(100);
195
+                    button.setText("Close Window");
196
+                } else {
197
+                    status.setText("Status: Transfer Failed.");
198
+                    if (dcc.getType() == DCCTransfer.TransferType.SEND) {
199
+                        button.setText("Resend");
200
+                    } else {
201
+                        button.setText("Close Window");
202
+                    }
203
+                }
204
+            }
205
+        });
206
+    }
207
+
208
+    /** {@inheritDoc} */
209
+    @Override
210
+    public void socketOpened(final DCCTransfer dcc) {
211
+        UIUtilities.invokeLater(new Runnable() {
212
+
213
+            /** {@inheritDoc} */
214
+            @Override
215
+            public void run() {
216
+                status.setText("Status: Socket Opened");
217
+            }
218
+
219
+        });
220
+    }
221
+
222
+    /** {@inheritDoc} */
223
+    @Override
224
+    public void dataTransfered(final DCCTransfer dcc, final int bytes) {
225
+        UIUtilities.invokeLater(new Runnable() {
226
+
227
+            private final TransferContainer container = (TransferContainer) frameParent;
228
+
229
+            /** {@inheritDoc} */
230
+            @Override
231
+            public void run() {
232
+                if (dcc.getType() == DCCTransfer.TransferType.SEND) {
233
+                    status.setText("Status: Sending");
234
+                } else {
235
+                    status.setText("Status: Recieving");
236
+                }
237
+
238
+                progress.setValue((int) container.getPercent());
239
+
240
+                final double bytesPerSecond = container.getBytesPerSecond();
241
+
242
+                if (bytesPerSecond > 1048576) {
243
+                    speed.setText(String.format("Speed: %.2f MiB/s", bytesPerSecond / 1048576));
244
+                } else if (bytesPerSecond > 1024) {
245
+                    speed.setText(String.format("Speed: %.2f KiB/s", bytesPerSecond / 1024));
246
+                } else {
247
+                    speed.setText(String.format("Speed: %.2f B/s", bytesPerSecond));
248
+                }
249
+
250
+                remaining.setText(String.format("Time Remaining: %s",
251
+                        duration((int) container.getRemainingTime())));
252
+                taken.setText(String.format("Time Taken: %s", container.getStartTime() == 0
253
+                        ? "N/A" : duration(container.getElapsedTime())));
254
+            }
255
+        });
256
+    }
257
+
258
+    /**
259
+     * Get the duration in seconds as a string.
260
+     *
261
+     * @param secondsInput to get duration for
262
+     * @return Duration as a string
263
+     */
264
+    private String duration(final long secondsInput) {
265
+        final StringBuilder result = new StringBuilder();
266
+        final long hours = (secondsInput / 3600);
267
+        final long minutes = (secondsInput / 60 % 60);
268
+        final long seconds = (secondsInput % 60);
269
+
270
+        if (hours > 0) {
271
+            result.append(hours + ":");
272
+        }
273
+        result.append(String.format("%0,2d:%0,2d", minutes, seconds));
274
+
275
+        return result.toString();
276
+    }
277
+
278
+}

+ 1
- 0
test/com/dmdirc/addons/dcc/IpToLongTest.java Просмотреть файл

@@ -22,6 +22,7 @@
22 22
 
23 23
 package com.dmdirc.addons.dcc;
24 24
 
25
+import com.dmdirc.addons.dcc.io.DCC;
25 26
 import java.util.Arrays;
26 27
 import java.util.List;
27 28
 

Загрузка…
Отмена
Сохранить