001package arcommon.progress; 002 003import java.awt.event.ActionEvent; 004import java.awt.event.ActionListener; 005import java.util.ArrayList; 006import java.util.Iterator; 007 008import arcommon.MyTimer; 009 010public class ProgressThreadData { 011 012 public static int updateInterval = 10; 013 014 private static ArrayList<ProgressThreadData> progressThreadDataList; 015 016 public static void addProgressActionListenerForCurrentThread(ProgressActionListener pprogressActionListener) { 017 ProgressThreadData progressThreadData = findProgressThreadData(true); 018 progressThreadData.addProgressActionListener(pprogressActionListener); 019 } 020 021 public static void addProgressActionListener(Thread thread, ProgressActionListener pprogressActionListener) { 022 ProgressThreadData progressThreadData = findProgressThreadData(thread, true); 023 progressThreadData.addProgressActionListener(pprogressActionListener); 024 } 025 026 public static ProgressState createProgressState() { 027 ProgressThreadData progressThreadData = findProgressThreadData(false); 028 if (progressThreadData == null) { 029 return null; 030 } 031 032 progressThreadData.checkIfThereShouldBeNotified(); 033 return progressThreadData.createProgressStateLocal(); 034 } 035 036 public static void disposeProgressState(ProgressState progressState) { 037 if (progressState == null) { 038 return ; 039 } 040 041 ProgressThreadData progressThreadData = findProgressThreadData(false); 042 if (progressThreadData == null) { 043 return ; 044 } 045 046 progressThreadData.disposeProgressStateLocal(progressState); 047 progressThreadData.checkIfThereShouldBeNotified(); 048 } 049 050 public static void removeAllProgressStates() { 051 ProgressThreadData progressThreadData = findProgressThreadData(false); 052 if (progressThreadData == null) { 053 return ; 054 } 055 056 if (progressThreadData.progressStates == null) { 057 return ; 058 } 059 060 Iterator<ProgressState> i = new ArrayList<ProgressState>(progressThreadData.progressStates).iterator(); 061 while (i.hasNext()) { 062 ProgressState progressState = i.next(); 063 progressThreadData.disposeProgressStateLocal(progressState); 064 } 065 } 066 067 public static ProgressThreadData getCurrentProgressThreadData() { 068 return findProgressThreadData(true); 069 } 070 071 public static ProgressThreadData getProgressThreadData(Thread thread) { 072 return findProgressThreadData(thread, true); 073 } 074 075 private static ProgressThreadData findProgressThreadData(boolean create) { 076 return findProgressThreadData(Thread.currentThread(), create); 077 } 078 079 private static ProgressThreadData findProgressThreadData(Thread forThread, boolean create) { 080 if (progressThreadDataList == null) { 081 if (!create) { 082 return null; 083 } 084 085 progressThreadDataList = new ArrayList<ProgressThreadData>(); 086 } 087 088 synchronized (progressThreadDataList) { 089 Iterator<ProgressThreadData> i = progressThreadDataList.iterator(); 090 while (i.hasNext()) { 091 ProgressThreadData progressThreadData = i.next(); 092 if (progressThreadData.thread == forThread) { 093 return progressThreadData; 094 } 095 } 096 097 if (!create) { 098 return null; 099 } 100 101 ProgressThreadData progressThreadData = new ProgressThreadData(forThread); 102 progressThreadDataList.add(progressThreadData); 103 return progressThreadData; 104 } 105 } 106 107 public static void dispose() { 108 if (progressThreadDataList == null) { 109 return ; 110 } 111 112 synchronized (progressThreadDataList) { 113 Iterator<ProgressThreadData> i = progressThreadDataList.iterator(); 114 while (i.hasNext()) { 115 ProgressThreadData progressThreadData = i.next(); 116 if (progressThreadData.timerActionListener != null) { 117 MyTimer.removeActionListener(progressThreadData.timerActionListener); 118 } 119 } 120 } 121 } 122 123 private Thread thread; 124 125 private ArrayList<ProgressActionListener> progressActionListeners; 126 private ArrayList<ProgressState> progressStates; 127 private Object data; 128 private ActionListener timerActionListener; 129 130 private String progressStateString; 131 132 public ProgressThreadData(Thread pthread) { 133 thread = pthread; 134 } 135 136 public Thread getThread() { 137 return thread; 138 } 139 140 public ProgressState createProgressStateLocal() { 141 if (progressStates == null) { 142 progressStates = new ArrayList<ProgressState>(); 143 } 144 145 synchronized (progressStates) { 146 if (progressStates.size() == 0) { 147 if (timerActionListener == null) { 148 timerActionListener = new ActionListener() { 149 public void actionPerformed(ActionEvent e) { 150 synchronized (progressStates) { 151 for (ProgressState progressState : progressStates) { 152 progressState.incNotifyCounter(); 153 } 154 } 155 } 156 }; 157 } 158 MyTimer.addActionListener(1, timerActionListener); 159 } 160 161 ProgressState progressState = new ProgressState(this); 162 progressStates.add(progressState); 163 return progressState; 164 } 165 } 166 167 public void checkIfThereShouldBeNotified() { 168 if (progressStates == null) { 169 return ; 170 } 171 172 boolean notify = false; 173 synchronized (progressStates) { 174 for (ProgressState progressState : progressStates) { 175 int notifyCounter = progressState.getNotifyCounter(); 176 if (notifyCounter >= updateInterval) { 177 notify = true; 178 break; 179 } 180 } 181 } 182 183 if (notify) { 184 progressStateString = calculateProgressStateString(); 185 186 fireProgressActionListener(); 187 188 // Placed after fireProgressActionListener because calculateProgressStateString() depends on progressState.notifyCounter. 189 synchronized (progressStates) { 190 for (ProgressState progressState : progressStates) { 191 progressState.resetNotifyCounter(); 192 } 193 } 194 } 195 } 196 197 public void disposeProgressStateLocal(ProgressState progressState) { 198 if (progressStates == null) { 199 return ; 200 } 201 202 synchronized (progressStates) { 203 progressStates.remove(progressState); 204 if (progressStates.size() == 0) { 205 MyTimer.removeActionListener(timerActionListener); 206 } 207 } 208 } 209 210 public String getProgressStateString() { 211 return progressStateString; 212 } 213 214 private String calculateProgressStateString() { 215 if (progressStates == null) { 216 return ""; 217 } 218 219 synchronized (progressStates) { 220 Iterator<ProgressState> i = new ArrayList<ProgressState>(progressStates).iterator(); 221 if (!i.hasNext()) { 222 return ""; 223 } 224 String progressStatesToString = progressStatesToString(i); 225 if (progressStatesToString.length() == 0) { 226 System.out.println("asd"); 227 } 228 return progressStatesToString; 229 } 230 } 231 232 private String progressStatesToString(Iterator<ProgressState> i) { 233 ProgressState progressState = i.next(); 234 int notifyCounter = progressState.getNotifyCounter(); 235 if (notifyCounter < updateInterval) { 236 // Only notify on slow enough progressStates. 237 return ""; 238 } 239 240 String result = progressState.toString(); 241 if (i.hasNext()) { 242 String progressStatesToString = progressStatesToString(i); 243 if (progressStatesToString.length() > 0) { 244 result = result + " (" + progressStatesToString + ")"; 245 } 246 } 247 248 return result; 249 } 250 251 public Object getData() { 252 return data; 253 } 254 255 public void setData(Object pdata) { 256 data = pdata; 257 } 258 259 public void addProgressActionListener(ProgressActionListener pprogressActionListener) { 260 if (progressActionListeners == null) { 261 progressActionListeners = new ArrayList<ProgressActionListener>(); 262 } 263 progressActionListeners.add(pprogressActionListener); 264 } 265 266 public void removeProgressActionListener(ProgressActionListener pprogressActionListener) { 267 if (progressActionListeners == null) { 268 return ; 269 } 270 progressActionListeners.remove(pprogressActionListener); 271 if (progressActionListeners.size() == 0) { 272 progressActionListeners = null; 273 } 274 } 275 276 public void fireProgressActionListener() { 277 if (progressActionListeners == null) { 278 return ; 279 } 280 281 ArrayList<ProgressActionListener> sendTo = new ArrayList<ProgressActionListener>(); 282 synchronized (progressActionListeners) { 283 sendTo.addAll(progressActionListeners); 284 } 285 286 ProgressAction progressAction = new ProgressAction(this); 287 for (int i = 0; i < sendTo.size(); i++) { 288 ProgressActionListener progressActionListener = sendTo.get(i); 289 progressActionListener.progressChanged(progressAction); 290 } 291 } 292}