001package arcommon.event;
002
003import java.awt.event.ActionEvent;
004import java.awt.event.ActionListener;
005import java.util.HashSet;
006import java.util.Iterator;
007
008import arcommon.StringUtil;
009import arcommon.progress.ProgressState;
010import arcommon.progress.ProgressThreadData;
011
012public class ActionList {
013    public static int generalDoNotNotifyLevel;
014
015    private transient HashSet<ActionListener> actionListeners;
016    private transient boolean doNotNotify;
017    private transient int level;
018    
019    public ActionList() {
020        level = 10;
021    }
022
023    public int getLevel() {
024        return level;
025    }
026
027    public void setLevel(int plevel) {
028        level = plevel;
029    }
030    
031    public boolean getDoNotNotify() {
032        return doNotNotify;
033    }
034
035    public void setDoNotNotify(boolean pdoNotNotify) {
036        doNotNotify = pdoNotNotify;
037    }
038
039    public ActionList getActionList() {
040        return this;
041    }
042
043    public synchronized void setActionList(ActionList pactionList) {
044        actionListeners = pactionList.actionListeners;
045    }
046
047    public synchronized void removeAllActionListeners() {
048        if (actionListeners == null) {
049            return ;
050        }
051        actionListeners = null;
052    }
053
054    public void addActionListeners(ActionList actionList) {
055        if (actionList == null) {
056            return ;
057        }
058        if (actionList.actionListeners == null) {
059            return ;
060        }
061        synchronized (this) {
062            if (actionListeners == null) {
063                actionListeners = new HashSet<ActionListener>();
064            }
065            actionListeners.addAll(actionList.actionListeners);
066        }
067    }
068    
069    public void addActionListener(ActionListener pactionListener) {
070        if (pactionListener == null) {
071            throw new IllegalArgumentException("actionListener == null");
072        }
073        synchronized (this) {
074            if (actionListeners == null) {
075                actionListeners = new HashSet<ActionListener>();
076            }
077            actionListeners.add(pactionListener);
078        }
079    }
080
081    public boolean removeActionListener(ActionListener pactionListener) {
082        if (pactionListener == null) {
083            throw new IllegalArgumentException("actionListener == null");
084        }
085        synchronized (this) {
086            if (actionListeners == null) {
087                return false;
088            }
089            boolean removed = actionListeners.remove(pactionListener);
090            return removed;
091        }
092    }
093
094    public synchronized Iterator<ActionListener> actionListenersIterator() {
095        if (actionListeners == null) {
096            return new HashSet<ActionListener>().iterator();
097        }
098        return actionListeners.iterator();
099    }
100    
101    private static int printLevel = 0;
102    public static boolean print = false;
103    
104    public void fireActionListeners(String command) {
105        fireActionListeners(this, 0, command);
106    }
107    
108    public void fireActionListeners(Object o, int id, String command) {
109        fireActionListeners(o, id, command, doNotNotify);
110    }
111    
112    public void fireActionListeners(Object o, int id, String command, boolean pdoNotNotify) {
113        ActionEvent actionEvent = new ActionEvent(o, id, command);
114        fireActionListeners(actionEvent, pdoNotNotify);
115    }
116    
117    public void fireActionListeners(ActionEvent actionEvent) {
118        fireActionListeners(actionEvent, doNotNotify);
119    }
120    
121    public void fireActionListeners(ActionEvent actionEvent, boolean pdoNotNotify) {
122        HashSet<ActionListener> sendTo;
123        synchronized (this) {
124            if (actionListeners == null || pdoNotNotify || level < generalDoNotNotifyLevel) { // HACK
125                return ;
126            }
127            sendTo = new HashSet<ActionListener>();
128            sendTo.addAll(actionListeners);
129        }
130        String indent = "";
131        if (print) {
132            printLevel++;
133            indent = StringUtil.stringWithNumberOfChar(printLevel * 2, ' ');
134            System.out.println(indent + "sendTo.size() " + sendTo.size());
135        }
136        ProgressState progressState = null;
137        if (sendTo.size() > 100) {
138            progressState = ProgressThreadData.createProgressState();
139            if (progressState != null) {
140                progressState.setMaximum(sendTo.size());
141                progressState.setName("Notify (all)");
142            }
143        }
144        int number = 0;
145        Iterator<ActionListener> i = sendTo.iterator();
146        while (i.hasNext()) {
147            ActionListener actionListener = i.next();
148            if (progressState != null) {
149                progressState.setCurrent(number + 1);
150            }
151            if (print) {
152                System.out.println(indent + "number: " + number);
153                System.out.println(indent + "actionPerformed(");
154                System.out.println(indent + "  source: " + actionEvent.getSource());
155                System.out.println(indent + "  index: " + actionEvent.getID());
156                System.out.println(indent + "  action: " + actionEvent.getActionCommand());
157                System.out.println(indent + "  actionListener: " + actionListener);
158            }
159            actionListener.actionPerformed(actionEvent);
160            if (print) {
161                System.out.println(indent + ");");
162            }
163            number++;
164        }
165        ProgressThreadData.disposeProgressState(progressState);
166        if (print) {
167            printLevel--;
168        }
169    }
170
171    public void fireActionListenersSafeLog(String command) {
172        fireActionListenersSafeLog(this, 0, command);
173    }
174    
175    public void fireActionListenersSafeLog(Object o, int index, String command) {
176        HashSet<ActionListener> sendTo;
177        synchronized (this) {
178            if (actionListeners == null || doNotNotify || level < generalDoNotNotifyLevel) {
179                return ;
180            }
181            sendTo = new HashSet<ActionListener>();
182            sendTo.addAll(actionListeners);
183        }
184        ActionEvent actionEvent = new ActionEvent(o, index, command);
185        ProgressState progressState = null;
186        if (sendTo.size() > 100) {
187            progressState = ProgressThreadData.createProgressState();
188        }
189        if (progressState != null) {
190            progressState.setMaximum(sendTo.size());
191            progressState.setName("Notify (safe)");
192        }
193        int number = 0;
194        Iterator<ActionListener> i = sendTo.iterator();
195        while (i.hasNext()) {
196            ActionListener actionListener = i.next();
197            if (progressState != null) {
198                progressState.setCurrent(++number);
199            }
200            try {
201                actionListener.actionPerformed(actionEvent);
202            } catch (Exception e) {
203                throw new RuntimeException(e);
204            }
205        }
206        ProgressThreadData.disposeProgressState(progressState);
207    }
208
209    public boolean isActionListenersEmpty() {
210        return numberOfListeners() == 0;
211    }
212    
213    public String actionListenersToString() {
214        return actionListenersToString(0);
215    }
216    
217    public String actionListenersToString(int pprintLevel) {
218        HashSet<ActionListener> sendTo;
219        String result;
220        synchronized (this) {
221            if (actionListeners == null || actionListeners.size() == 0) {
222                return "";
223            }
224            
225            result = StringUtil.stringWithNumberOfChar(pprintLevel * 2, ' ') + "Number of actionListeners: " + actionListeners.size();
226            sendTo = new HashSet<ActionListener>();
227            sendTo.addAll(actionListeners);
228        }
229        pprintLevel++;
230        int number = 1;
231        Iterator<ActionListener> i = sendTo.iterator();
232        while (i.hasNext()) {
233            ActionListener actionListener = i.next();
234            if (result.length() != 0) {
235                result = result + "\n";
236            }
237            result = result + StringUtil.stringWithNumberOfChar(pprintLevel * 2, ' ') + (number++) + ": ";
238            if (actionListener instanceof MyActionListener) {
239                String temp = ((MyActionListener)actionListener).actionListenersToString(pprintLevel);
240                result = result + temp.trim();
241            } else {
242                result = result + actionListener.toString();
243            }
244            if (number >= 1000) {
245                System.out.println("THERE IS MORE THAN 1000. THE REMAINING IS NOT PRINTED!!!!!!!!!");
246                result = result + "THERE IS MORE THAN 1000. THE REMAINING IS NOT PRINTED!!!!!!!!!" + "\n";
247                result = result + "THERE IS MORE THAN 1000. THE REMAINING IS NOT PRINTED!!!!!!!!!" + "\n";
248                result = result + "THERE IS MORE THAN 1000. THE REMAINING IS NOT PRINTED!!!!!!!!!" + "\n";
249                result = result + "THERE IS MORE THAN 1000. THE REMAINING IS NOT PRINTED!!!!!!!!!" + "\n";
250                break;
251            }
252        }
253        return result;
254    }
255    
256    public void printActionListeners() {
257        printActionListeners(1);
258    }
259    
260    public void printActionListeners(int pprintLevel) {
261        System.out.println(StringUtil.stringWithNumberOfChar(pprintLevel * 2, ' ') + toString());
262        if (!isActionListenersEmpty()) {
263            System.out.println(StringUtil.stringWithNumberOfChar(pprintLevel * 2, ' ') + actionListenersToString(pprintLevel));
264        }
265    }
266
267    public synchronized int numberOfListeners() {
268        if (actionListeners == null) {
269            return 0;
270        }
271        return actionListeners.size();
272    }
273}