1/*
2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package java.awt.dnd;
26
27import java.awt.AWTEventMulticaster;
28import java.io.ObjectOutputStream;
29import java.io.IOException;
30import java.util.EventListener;
31
32
33/**
34 * A class extends {@code AWTEventMulticaster} to implement efficient and
35 * thread-safe multi-cast event dispatching for the drag-and-drop events defined
36 * in the java.awt.dnd package.
37 *
38 * @since       1.4
39 * @see AWTEventMulticaster
40 */
41
42class DnDEventMulticaster extends AWTEventMulticaster
43    implements DragSourceListener, DragSourceMotionListener {
44
45    /**
46     * Creates an event multicaster instance which chains listener-a
47     * with listener-b. Input parameters {@code a} and {@code b}
48     * should not be {@code null}, though implementations may vary in
49     * choosing whether or not to throw {@code NullPointerException}
50     * in that case.
51     *
52     * @param a listener-a
53     * @param b listener-b
54     */
55    protected DnDEventMulticaster(EventListener a, EventListener b) {
56        super(a,b);
57    }
58
59    /**
60     * Handles the {@code DragSourceDragEvent} by invoking
61     * {@code dragEnter} on listener-a and listener-b.
62     *
63     * @param dsde the {@code DragSourceDragEvent}
64     */
65    public void dragEnter(DragSourceDragEvent dsde) {
66        ((DragSourceListener)a).dragEnter(dsde);
67        ((DragSourceListener)b).dragEnter(dsde);
68    }
69
70    /**
71     * Handles the {@code DragSourceDragEvent} by invoking
72     * {@code dragOver} on listener-a and listener-b.
73     *
74     * @param dsde the {@code DragSourceDragEvent}
75     */
76    public void dragOver(DragSourceDragEvent dsde) {
77        ((DragSourceListener)a).dragOver(dsde);
78        ((DragSourceListener)b).dragOver(dsde);
79    }
80
81    /**
82     * Handles the {@code DragSourceDragEvent} by invoking
83     * {@code dropActionChanged} on listener-a and listener-b.
84     *
85     * @param dsde the {@code DragSourceDragEvent}
86     */
87    public void dropActionChanged(DragSourceDragEvent dsde) {
88        ((DragSourceListener)a).dropActionChanged(dsde);
89        ((DragSourceListener)b).dropActionChanged(dsde);
90    }
91
92    /**
93     * Handles the {@code DragSourceEvent} by invoking
94     * {@code dragExit} on listener-a and listener-b.
95     *
96     * @param dse the {@code DragSourceEvent}
97     */
98    public void dragExit(DragSourceEvent dse) {
99        ((DragSourceListener)a).dragExit(dse);
100        ((DragSourceListener)b).dragExit(dse);
101    }
102
103    /**
104     * Handles the {@code DragSourceDropEvent} by invoking
105     * {@code dragDropEnd} on listener-a and listener-b.
106     *
107     * @param dsde the {@code DragSourceDropEvent}
108     */
109    public void dragDropEnd(DragSourceDropEvent dsde) {
110        ((DragSourceListener)a).dragDropEnd(dsde);
111        ((DragSourceListener)b).dragDropEnd(dsde);
112    }
113
114    /**
115     * Handles the {@code DragSourceDragEvent} by invoking
116     * {@code dragMouseMoved} on listener-a and listener-b.
117     *
118     * @param dsde the {@code DragSourceDragEvent}
119     */
120    public void dragMouseMoved(DragSourceDragEvent dsde) {
121        ((DragSourceMotionListener)a).dragMouseMoved(dsde);
122        ((DragSourceMotionListener)b).dragMouseMoved(dsde);
123    }
124
125    /**
126     * Adds drag-source-listener-a with drag-source-listener-b and
127     * returns the resulting multicast listener.
128     *
129     * @param a drag-source-listener-a
130     * @param b drag-source-listener-b
131     */
132    public static DragSourceListener add(DragSourceListener a,
133                                         DragSourceListener b) {
134        return (DragSourceListener)addInternal(a, b);
135    }
136
137    /**
138     * Adds drag-source-motion-listener-a with drag-source-motion-listener-b and
139     * returns the resulting multicast listener.
140     *
141     * @param a drag-source-motion-listener-a
142     * @param b drag-source-motion-listener-b
143     */
144    @SuppressWarnings("overloads")
145    public static DragSourceMotionListener add(DragSourceMotionListener a,
146                                               DragSourceMotionListener b) {
147        return (DragSourceMotionListener)addInternal(a, b);
148    }
149
150    /**
151     * Removes the old drag-source-listener from drag-source-listener-l
152     * and returns the resulting multicast listener.
153     *
154     * @param l drag-source-listener-l
155     * @param oldl the drag-source-listener being removed
156     */
157    public static DragSourceListener remove(DragSourceListener l,
158                                            DragSourceListener oldl) {
159        return (DragSourceListener)removeInternal(l, oldl);
160    }
161
162    /**
163     * Removes the old drag-source-motion-listener from
164     * drag-source-motion-listener-l and returns the resulting multicast
165     * listener.
166     *
167     * @param l drag-source-motion-listener-l
168     * @param ol the drag-source-motion-listener being removed
169     */
170    @SuppressWarnings("overloads")
171    public static DragSourceMotionListener remove(DragSourceMotionListener l,
172                                                  DragSourceMotionListener ol) {
173        return (DragSourceMotionListener)removeInternal(l, ol);
174    }
175
176    /**
177     * Returns the resulting multicast listener from adding listener-a
178     * and listener-b together.
179     * If listener-a is null, it returns listener-b;
180     * If listener-b is null, it returns listener-a
181     * If neither are null, then it creates and returns
182     * a new AWTEventMulticaster instance which chains a with b.
183     * @param a event listener-a
184     * @param b event listener-b
185     */
186    protected static EventListener addInternal(EventListener a, EventListener b) {
187        if (a == null)  return b;
188        if (b == null)  return a;
189        return new DnDEventMulticaster(a, b);
190    }
191
192    /**
193     * Removes a listener from this multicaster and returns the
194     * resulting multicast listener.
195     * @param oldl the listener to be removed
196     */
197    protected EventListener remove(EventListener oldl) {
198        if (oldl == a)  return b;
199        if (oldl == b)  return a;
200        EventListener a2 = removeInternal(a, oldl);
201        EventListener b2 = removeInternal(b, oldl);
202        if (a2 == a && b2 == b) {
203            return this;        // it's not here
204        }
205        return addInternal(a2, b2);
206    }
207
208    /**
209     * Returns the resulting multicast listener after removing the
210     * old listener from listener-l.
211     * If listener-l equals the old listener OR listener-l is null,
212     * returns null.
213     * Else if listener-l is an instance of AWTEventMulticaster,
214     * then it removes the old listener from it.
215     * Else, returns listener l.
216     * @param l the listener being removed from
217     * @param oldl the listener being removed
218     */
219    protected static EventListener removeInternal(EventListener l, EventListener oldl) {
220        if (l == oldl || l == null) {
221            return null;
222        } else if (l instanceof DnDEventMulticaster) {
223            return ((DnDEventMulticaster)l).remove(oldl);
224        } else {
225            return l;           // it's not here
226        }
227    }
228
229    protected static void save(ObjectOutputStream s, String k, EventListener l)
230      throws IOException {
231        AWTEventMulticaster.save(s, k, l);
232    }
233}
234