チェンジセット 1306: as3/ThreadViewer
- コミット日時:
- 2008/09/13 18:51:11 (3 年前)
- ファイル:
-
- as3/ThreadViewer/ThreadViewer-app.xml (更新) (2 diffs)
- as3/ThreadViewer/ThreadViewer.air (更新) (変更前)
- as3/ThreadViewer/ThreadViewer.as (更新) (20 diffs)
- as3/ThreadViewer/ThreadViewer.mxml (更新) (1 diff)
- as3/ThreadViewer/icons (追加)
- as3/ThreadViewer/icons/NEW.png (追加)
- as3/ThreadViewer/icons/RUNNABLE.png (追加)
- as3/ThreadViewer/icons/TERMINATED.png (追加)
- as3/ThreadViewer/icons/TIMED_WAITING.png (追加)
- as3/ThreadViewer/icons/ThreadViewer_128.png (追加)
- as3/ThreadViewer/icons/ThreadViewer_16.png (追加)
- as3/ThreadViewer/icons/ThreadViewer_32.png (追加)
- as3/ThreadViewer/icons/ThreadViewer_48.png (追加)
- as3/ThreadViewer/icons/WAITING.png (追加)
- as3/ThreadViewer/icons/clear_downSkin.png (追加)
- as3/ThreadViewer/icons/clear_overSkin.png (追加)
- as3/ThreadViewer/icons/clear_upSkin.png (追加)
- as3/ThreadViewer/icons/info_downSkin.png (追加)
- as3/ThreadViewer/icons/info_overSkin.png (追加)
- as3/ThreadViewer/icons/info_upSkin.png (追加)
- as3/ThreadViewer/icons/rec_disabledSkin.png (追加)
- as3/ThreadViewer/icons/rec_downSkin.png (追加)
- as3/ThreadViewer/icons/rec_selectedDownSkin.png (追加)
- as3/ThreadViewer/icons/rec_selectedSkin.png (追加)
- as3/ThreadViewer/icons/rec_upSkin.png (追加)
- as3/ThreadViewer/org/libspark/snippets/AIRUtils/PreferenceUtil.as (更新) (1 diff)
- as3/ThreadViewer/style.css (追加)
- as3/ThreadViewer/thread.db (更新) (変更前)
凡例:
- 変更無し
- 追加
- 削除
- 更新
- コピー
- 移動
as3/ThreadViewer/ThreadViewer-app.xml
r1207 r1306 2 2 <application xmlns="http://ns.adobe.com/air/application/1.0"> 3 3 <id>org.libspark.ThreadViewer</id> 4 <version>0. 5</version>4 <version>0.6</version> 5 5 <filename>ThreadViewer</filename> 6 6 <name>Thread Viewer</name> 7 <description>This is ActionScript Thread Viewer application</description>7 <description>This is ActionScript Thread Library Viewer Application</description> 8 8 <copyright>(c) daoki2 2008</copyright> 9 9 … … 14 14 <transparent>false</transparent> 15 15 <visible>false</visible> 16 <width> 640</width>17 <height>5 10</height>16 <width>780</width> 17 <height>520</height> 18 18 </initialWindow> 19 <icon> 20 <image16x16>icons/ThreadViewer_16.png</image16x16> 21 <image32x32>icons/ThreadViewer_32.png</image32x32> 22 <image48x48>icons/ThreadViewer_48.png</image48x48> 23 <image128x128>icons/ThreadViewer_128.png</image128x128> 24 </icon> 19 25 </application> as3/ThreadViewer/ThreadViewer.as
r1207 r1306 3 3 * 4 4 * @author Copyright (c) 2008 daoki2 5 * @version 0. 56 * @link http:// snippets.libspark.org/5 * @version 0.6 6 * @link http://www.libspark.org/wiki/daoki2/ThreadViewer 7 7 * @link http://homepage.mac.com/daoki2/ 8 8 * … … 32 32 import flash.data.*; 33 33 import flash.desktop.NativeApplication; 34 import flash.net.LocalConnection; 34 35 35 36 import mx.events.*; 36 37 import mx.collections.ArrayCollection; 37 import mx.controls.Label; 38 import mx.controls.VRule; 39 import flash.net.LocalConnection; 38 import mx.controls.*; 39 40 40 import org.libspark.snippets.AIRUtils.PreferenceUtil; 41 41 import org.libspark.thread.ThreadState; … … 43 43 import org.libspark.snippets.controls.ChartData.FusionCharts.SingleChartData; 44 44 45 private static const LEFT_PADD:uint = 38; 46 private var _conn:LocalConnection; 47 private var threadList:ArrayCollection = new ArrayCollection(); 48 private var threadNameLabel:ArrayCollection = new ArrayCollection(); 49 private var threadStatus:ArrayCollection = new ArrayCollection(); 50 private var threadLog:ArrayCollection = new ArrayCollection(); 51 private var pos_x:Number = 0; 52 private var isLogging:Boolean = false; 53 private var framePerSecond:uint = 24; 54 private var frameInterval:Number = 1000/24; 55 //private var firstNop:Number = -1; 56 57 private var _dbconn:SQLConnection; 45 private static const LEFT_PADD:uint = 38; // スレッド名のX座標 46 private var _conn:LocalConnection; // LocalConnection接続用 47 private var threadList:ArrayCollection = new ArrayCollection(); // スレッドリスト 48 private var threadNameLabel:ArrayCollection = new ArrayCollection(); // スレッド名Labelのリスト 49 private var threadStatus:ArrayCollection = new ArrayCollection(); // スレッド状態のリスト 50 private var threadLog:ArrayCollection = new ArrayCollection(); // スレッド遷移グラフのリスト 51 private var pos_x:Number = 0; // スレッド遷移グラフのX座標 52 private var isLogging:Boolean = false; // ログ収集中か否か 53 private var framePerSecond:uint = 24; // フレーム/秒 54 private var frameInterval:Number = 1000/24; // 時間(ms)/フレーム 55 private var _dbconn:SQLConnection; // ローカルデータベース接続用 56 57 /* ######## アプリケーション関連のハンドラ ######## */ 58 58 59 59 /* … … 61 61 */ 62 62 private function init():void { 63 // イベントハンドラの登録 63 64 addEventListener(Event.CLOSING, onAppClosing); 65 addEventListener(FlexNativeWindowBoundsEvent.WINDOW_RESIZE, onWinResize); 66 threadName.addEventListener(MouseEvent.MOUSE_DOWN, threadName_MouseDownHandler); 67 68 // プリファレンス(初期値)の読み込み 64 69 var result:Object = PreferenceUtil.load(this, "preference.xml"); 65 this.minWidth = 780; 66 this.minHeight = 520; 67 if (this.width < this.minWidth) 68 this.width = this.minWidth; 69 if (this.height < this.minHeight) 70 this.height = this.minHeight; 70 if (!result.status) 71 trace(result.message); 72 73 // 注:最小サイズを設定した時の動作が謎すぎるので、とりあえずコメントアウト 74 //this.minWidth = 780; 75 //this.minHeight = 520; 76 // ウィンドウサイズが最小サイズより小さければ是正 77 //if (this.width < this.minWidth) 78 // this.width = this.minWidth + 16; 79 //if (this.height < this.minHeight) 80 // this.height = this.minHeight + 16; 81 71 82 this.visible = true; 72 //trace(this.width, this.height); 83 84 // LocalConnectionの作成 73 85 _conn = new LocalConnection(); 74 86 _conn.client = this; 87 75 88 try { 76 //tIssue.text = NativeApplication.nativeApplication.publisherID; 77 _conn.connect("AS3ThreadLibV1"); 78 _conn.allowDomain("*"); 89 // LocalConnectionに接続 90 _conn.connect("AS3ThreadLibV1"); // 接続名 91 _conn.allowDomain("*"); // どこからの接続でも許す 92 93 // nopの生成 79 94 createNop(); 95 96 // ローカルデータベースをオープン 80 97 var dbFile:File = File.applicationDirectory.resolvePath("thread.db"); 81 98 _dbconn = new SQLConnection(); 82 99 _dbconn.open(dbFile, SQLMode.UPDATE); 83 SqlUtil.executeSQLStatement(_dbconn, "delete from threadTime"); 84 SqlUtil.executeSQLStatement(_dbconn, "delete from threadState"); 100 SqlUtil.executeSQLStatement(_dbconn, "delete from threadTime"); // 古いデータを削除 101 SqlUtil.executeSQLStatement(_dbconn, "delete from threadState"); // 古いデータを削除 102 103 // Chartの作業ファイルを設定 85 104 threadStateHtml = File.applicationStorageDirectory.resolvePath("threadState.html"); 86 105 threadStateData = File.applicationStorageDirectory.resolvePath("threadState.xml"); … … 95 114 96 115 /* 97 * nopを生成 98 */ 99 private function createNop():void { 100 threadList.addItem("nop"); 101 var t:Label = new Label(); 102 t.x = LEFT_PADD; t.y = 0; t.text = "nop"; 103 threadName.addChild(t); 104 } 105 106 /* 107 * Frame Per Second(FPS)情報の取得ハンドラ 108 */ 109 public function frameInfoHandler(fps:uint):void { 110 framePerSecond = fps; 111 frameInterval = 1000/framePerSecond; 112 //trace("frameInfoHandler", framePerSecond, frameInterval); 113 } 116 * アプリケーションの終了ハンドラ 117 */ 118 private function onAppClosing(event:Event):void { 119 120 // プリファレンス(初期値)の書き込み 121 var prefList:ArrayCollection = new ArrayCollection(); 122 prefList.addItem("nativeWindow.x"); // X座標 123 prefList.addItem("nativeWindow.y"); // Y座標 124 prefList.addItem("width"); // ウィンドウの幅 125 prefList.addItem("height"); // ウィンドウの高さ 126 PreferenceUtil.save(this, prefList, "preference.xml"); 127 128 // LocalConnectionをクローズ 129 if (_dbconn != null) 130 _dbconn.close(); 131 } 132 133 /* 134 * Windowのリサイズハンドラ 135 */ 136 private function onWinResize(event:FlexNativeWindowBoundsEvent):void { 137 138 // スレッド名、スレッド遷移グラフの場所を元に戻す 139 threadName.y = 0; 140 threadTime.y = 0; 141 142 // もしログ収集を止めてたら、スレッド実行時間のグラフを再描画 143 if (!isLogging && threadList.length != 0) 144 createThreadTimeChart(); 145 } 146 147 /* ######## LocalConnection関連のイベントハンドラ ######## */ 114 148 115 149 /* … … 117 151 */ 118 152 public function threadEntryHandler(name:String, newThread:Boolean = true):void { 119 //trace("threadEntryHandler", name); 153 154 // ログ収集中でなければ終わる 120 155 if (!isLogging) 121 156 return; 122 157 158 // スレッドリスト中にあるか? 123 159 if (threadList.contains(name)) { 124 trace("Thread", name, "already exists"); 160 trace("Thread", name, "already exists"); // 既に同名のスレッドが存在する 125 161 } else { 162 // スレッド名のLabelを生成 126 163 var t:Label = new Label(); 127 164 t.x = LEFT_PADD; 128 t.y = threadList.length * 1 2;165 t.y = threadList.length * 16; 129 166 t.text = name; 130 167 threadName.addChild(t); 131 168 threadNameLabel.addItem(t); 132 threadList.addItem(name); 133 var s:Label = new Label(); 169 170 // スレッド状態のImageを生成 171 var s:Image = new Image(); 134 172 s.x = 8; 135 s.y = t .y;173 s.y = threadList.length * 16 + 1; 136 174 if (newThread) 137 s. text = "[N]";175 s.source = "icons/NEW.png"; // 新規のスレッド 138 176 else 139 s.text = "[R]"; 177 s.source = "icons/RUNNABLE.png"; //既存のスレッド 178 140 179 threadName.addChild(s); 141 180 threadStatus.addItem(s); 181 182 // スレッドリストに登録 183 threadList.addItem(name); 142 184 } 143 185 } … … 147 189 */ 148 190 public function threadNameHandler(name:String, newName:String):void { 149 //trace("threadNameHandler", name, newName); 191 192 // ログ収集中でなければ終わる 150 193 if (!isLogging) 151 194 return; 152 195 196 // スレッドリスト中にあるか? 153 197 if (!threadList.contains(name)) 154 threadEntryHandler(name, false); 198 threadEntryHandler(name, false); // 無いので、既存のスレッドとして登録 199 200 // スレッドリストに登録されてるスレッド名を変更 155 201 var index:int = threadList.getItemIndex(name); 156 threadList.removeItemAt(index); 157 threadList.addItemAt(newName, index); 158 var n:Label = Label(threadNameLabel.getItemAt(index - 1)); //threadList contains "nop" 202 threadList.removeItemAt(index); // 古いスレッド名を削除 203 threadList.addItemAt(newName, index); // 新しいスレッド名を登録 204 205 // Labelリストから該当のLabelを取得して、スレッド名を更新する 206 var n:Label = Label(threadNameLabel.getItemAt(index - 1)); // threadListは"nop"も含むので、ひとつ引く 159 207 n.text = newName; 160 208 } … … 164 212 */ 165 213 public function threadStateHandler(name:String, status:uint, time:int):void { 166 //trace("threadStateHandler", name, status); 214 215 // スレッド状態画像のファイル名 注:TERMINATINGとTERMINATEDは同じ画像を使う 216 var StateImageFiles:Array = new Array("icons/NEW.png", "icons/RUNNABLE.png", "icons/WAITING.png", 217 "icons/TIMED_WAITING.png", "icons/TERMINATED.png", "icons/TERMINATED.png"); 218 219 // ログ収集中でなければ終わる 167 220 if (!isLogging) 168 221 return; 169 222 223 // スレッドリスト中にあるか? 170 224 if (!threadList.contains(name)) 171 threadEntryHandler(name, false); 225 threadEntryHandler(name, false); // 無いので、既存のスレッドとして登録 226 227 // 状態リストから該当のImageを取得して、画像を更新する 172 228 var index:int = threadList.getItemIndex(name); 173 var s:Label = Label(threadStatus.getItemAt(index - 1)); //threadList contains "nop" 174 switch(status) { 175 case ThreadState.NEW: 176 s.text = "[N]"; 177 break; 178 case ThreadState.RUNNABLE: 179 s.text = "[R]"; 180 break; 181 case ThreadState.WAITING: 182 case ThreadState.TIMED_WAITING: 183 s.text = "[W]"; 184 break; 185 case ThreadState.TERMINATING: 186 case ThreadState.TERMINATED: 187 s.text = "[T]"; 188 break; 189 default: 190 s.text = "[?]"; 191 trace("Unknown state", status); 192 break; 193 } 229 var s:Image = Image(threadStatus.getItemAt(index - 1)); // threadListは"nop"も含むので、ひとつ引く 230 s.source = StateImageFiles[status]; 231 232 // ローカルデータベースに情報を記録 194 233 SqlUtil.executeSQLStatement(_dbconn, "insert into threadState(name, state, time) values ('" + name + "', " + status + ", " + time + ")"); 195 234 } 196 235 197 private var b_color:uint = 0x0000ff; 236 private var b_color:uint = 0x0000ff; // スレッド遷移グラフのデフォルト色 198 237 199 238 /* … … 201 240 */ 202 241 public function threadTimeHandler(name:String, startTime:int, endTime:int):void { 203 //trace("threadTimeHandler", name, time); 242 243 // ログ収集中でなければ終わる 204 244 if (!isLogging) 205 245 return; 206 246 207 var pos_y:Number = 0;247 // スレッドリスト中にあるか? 208 248 if (!threadList.contains(name)) 209 threadEntryHandler(name, false); 210 pos_y = threadList.getItemIndex(name) * 12; 249 threadEntryHandler(name, false); // 無いので、既存のスレッドとして登録 250 251 var pos_y:int = threadList.getItemIndex(name) * 16; // スレッド遷移グラフのY座標 252 253 // スレッド遷移グラフの生成 211 254 var b:VBox = new VBox(); 212 255 b.x = pos_x; … … 214 257 b.toolTip = String(endTime - startTime) + "ms"; 215 258 b.width = (endTime - startTime) * hsScale.value; 216 b.height = 1 2;259 b.height = 16; 217 260 b.setStyle("backgroundColor", b_color); 218 261 threadTime.addChild(b); 219 threadLog.addItem({bar:b, time:(endTime - startTime)}); 220 pos_x += b.width; 262 threadLog.addItem({bar:b, time:(endTime - startTime)}); // スレッド遷移グラフリストへ登録 263 264 pos_x += b.width; // 次回の描画X座標の計算 265 266 // もしフレーム同期ハンドラが呼ばれた直後だったら? 267 // 注:フレーム同期の直後は"nop"が来る 221 268 if (name == "nop") { 269 checkInterval(endTime, endTime - startTime); // フレーム同期間隔の確認 270 271 // フレーム毎に色を入れ替える 222 272 if (b_color == 0x0000ff) 223 273 b_color = 0x8888ff; … … 225 275 b_color = 0x0000ff; 226 276 } 227 //drawGrid(pos_x); 277 278 // ローカルデータベースに情報を記録 228 279 SqlUtil.executeSQLStatement(_dbconn, "insert into threadTime(name, startTime, endTime, elapse) values ('" + name + "', " + startTime + ", " + endTime + ", " + (endTime - startTime) + ")"); 229 } 230 231 /* 232 private var grid_x:uint = 0; 233 234 private function drawGrid(pos_x:uint):void { 235 //trace("drawGrid", grid_x, pos_x); 236 while(grid_x < pos_x) { 237 var r:VRule = new VRule(); 238 r.x = grid_x; r.y = 0; 239 r.width = 1; 240 r.height = threadTime.height; 241 r.setStyle("strokeColor", 0x888888); 242 threadTime.addChild(r); 243 grid_x += frameInterval * hsScale.value; 244 } 245 } 246 */ 247 248 /* 249 * Start/Stopボタンのクリックハンドラ 250 */ 251 private function bStartStop_ClickHandler(event:MouseEvent):void { 252 //trace("startstop"); 253 hsScale.enabled = isLogging; 280 tElapseTime.text = convertElapseTime(pos_x); 281 } 282 283 /* ######## コンポーネントのイベントハンドラ ######## */ 284 285 /* 286 * Record/Stopボタンのクリックハンドラ 287 */ 288 private function bRecordStop_ClickHandler(event:MouseEvent):void { 289 290 hsScale.enabled = isLogging; // 縮尺スケーラを有効/無効にする 291 292 // もしログ収集中だったら? 254 293 if (isLogging) { 255 bStartStop.label = "Start"; 256 threadList.removeItemAt(0); 294 // ログ収集を止める 295 bRecordStop.toolTip = "Record"; // ログ収集を止めるから次回は"Record"。ややこしい... 296 threadList.removeItemAt(0); // スレッドリストから"nop"を削除 297 // もしスレッドが1つでもあれば 257 298 if (threadList.length != 0) { 299 // スレッド選択コンボボックスの更新 258 300 cbThread.dataProvider = threadList; 259 301 cbThread.selectedItem = threadList.getItemAt(0); 302 303 // スレッド状態Chartの作成 260 304 createThreadStateChart(String(threadList.getItemAt(0))); 305 306 // スレッド実行時間のアップデート 261 307 updateThreadTimes(String(threadList.getItemAt(0))); 308 309 // スレッド実行時間Chartの作成 262 310 createThreadTimeChart(); 263 311 } 264 312 } else { 265 bStartStop.label = "Stop"; 266 } 267 isLogging = !isLogging; 268 bStartStop.enabled = isLogging; 313 bRecordStop.toolTip = "Stop"; // ログ収集を始めるから次回は"Stop"。やっぱりややこしい... 314 } 315 316 isLogging = !isLogging; // ログ収集中なら止める。収集してなかったら、始める。 317 bRecordStop.enabled = isLogging; // Recordボタンを無効/有効にする 269 318 } 270 319 … … 273 322 */ 274 323 private function bClear_ClickHandler(event:MouseEvent):void { 275 //trace("clear"); 324 325 // 管理リストの削除 276 326 threadLog.removeAll(); 277 327 threadList.removeAll(); 278 328 threadNameLabel.removeAll(); 279 329 threadStatus.removeAll(); 330 331 // スレッド遷移グラフの削除 280 332 threadName.removeAllChildren(); 281 threadTime.removeAllChildren(); 282 pos_x = 0; 283 bStartStop.enabled = true; 333 threadTime.removeAllChildren(); 334 pos_x = 0; // 描画X座標を先頭に戻す 335 336 // 画面に表示されてるコンポーネント関連を初期化 337 bRecordStop.enabled = true; 284 338 cbThread.dataProvider = null; 285 createNop();286 339 tIssue.text = ""; 287 340 tElapse.text = ""; … … 291 344 htmlState.htmlText = ""; 292 345 htmlTime.htmlText = ""; 346 tElapseTime.text = "00:00:00.000"; 347 tElapseMax.text = "Max 00.000"; 348 tElapseMin.text = "Min 00.000"; 349 tElapseAve.text = "Ave 00.000"; 350 tFPS.text = "FPS: 000"; 351 threadName.y = 0; 352 threadTime.y = 0; 353 354 // 内部変数の初期化 355 frameGet = false; 356 maxInterval = 0; 357 maxIntPos = 0; 358 minInterval = 10000; 359 minIntPos = 0; 360 lastNopTime = 0; 361 totalInterval = 0; 362 intervalCount = 0; 363 364 // ローカルデータベースの古いデータを削除 293 365 SqlUtil.executeSQLStatement(_dbconn, "delete from threadTime"); 294 366 SqlUtil.executeSQLStatement(_dbconn, "delete from threadState"); 295 //firstNop = -1; 296 //grid_x = 0; 367 368 // nopを生成 369 createNop(); 297 370 } 298 371 … … 301 374 */ 302 375 private function hsScale_ChangeHandler(event:SliderEvent):void { 303 //trace(event.value); 376 377 // 描画X座標を先頭に戻す 304 378 pos_x = 0; 379 380 // スレッド遷移グラフの位置とサイズを更新 305 381 for each (var val:* in threadLog) { 306 382 var b:VBox = VBox(val.bar); 307 383 var time:int = int(val.time); 308 384 b.x = pos_x; 309 b.width = time * event.value; 385 b.width = time * event.value; // 縮尺と時間からサイズを計算 310 386 pos_x += b.width; 311 387 } 312 313 /*314 var f:VBox = VBox(threadTime.getChildAt(firstNop));315 grid_x = f.x + f.width;316 var children:Array = threadTime.getChildren();317 for each (val in children) {318 if (val is VRule) {319 val.x = grid_x;320 grid_x += frameInterval * event.value;321 }322 }323 */324 388 } 325 389 … … 328 392 */ 329 393 private function cbThread_CloseHandler(event:Event):void { 394 395 // スレッド状態Chartの作成 330 396 createThreadStateChart(String(ComboBox(event.target).selectedItem)); 397 398 // スレッド実行時間の更新 331 399 updateThreadTimes(String(ComboBox(event.target).selectedItem)); 332 400 } 333 401 334 402 /* 403 * インフォメーション表示 404 */ 405 private function bInfo_ClickHandler(event:MouseEvent):void { 406 // Publisher IDをアラートで表示 407 Alert.show(NativeApplication.nativeApplication.publisherID, 'Publisher ID'); 408 } 409 410 /* 411 * Interval Maxラベルのクリックハンドラ 412 */ 413 private function tElapseMax_ClickHandler(event:MouseEvent):void { 414 // フレーム同期間隔が最大の場所にスクロール 415 threadTimeContainer.horizontalScrollPosition = maxIntPos * hsScale.value; 416 } 417 418 /* 419 * Interval Minラベルのクリックハンドラ 420 */ 421 private function tElapseMin_ClickHandler(event:MouseEvent):void { 422 // フレーム同期間隔が最小の場所にスクロール 423 threadTimeContainer.horizontalScrollPosition = minIntPos * hsScale.value; 424 } 425 426 /* 427 * threadNameのドラッグ制御 428 */ 429 private var m_x:Number; 430 private var m_y:Number; 431 private function threadName_MouseDownHandler(event:MouseEvent):void { 432 433 // 現座標の登録 434 m_x = event.stageX; 435 m_y = event.stageY; 436 437 // イベントハンドラの登録 438 threadName.addEventListener(MouseEvent.MOUSE_MOVE, threadName_MouseMoveHandler); 439 threadName.addEventListener(MouseEvent.MOUSE_UP, threadName_MouseUpHandler); 440 } 441 442 private var chata:Array = new Array(1, -1); // チャタリング防止用のバッファ 443 private var chata_cancel:int = 0; // チャタリング防止キャンセルのカウンタ 444 private function threadName_MouseMoveHandler(event:MouseEvent):void { 445 446 // もしスレッド名が表示領域に収まらないなら 447 if (threadName.height > threadName.parent.height) { 448 var delta_y:Number = event.stageY - m_y; // 移動量の計算 449 var pos_y:Number = threadName.y + delta_y; // Y座標を求める 450 451 // チャタリング防止のアルゴリズム: 452 // 過去2回のドラッグ方向(上もしくは下)と違ったらチャタリングと判断してキャンセル 453 // ただし、同じ方向に2回続けば、チャタリングじゃないと判断 454 if (chata[0] < 0 && chata[1] < 0) { 455 if (delta_y >= 0 && chata_cancel < 2) { 456 pos_y = 1; 457 chata_cancel++; 458 } else { 459 chata[0] = chata[1]; 460 chata[1] = delta_y; 461 chata_cancel = 0; 462 } 463 } else if (chata[0] >=0 && chata[1] >= 0) { 464 if (delta_y < 0 && chata_cancel < 2) { 465 pos_y = 1; 466 chata_cancel++; 467 } else { 468 chata[0] = chata[1]; 469 chata[1] = delta_y; 470 chata_cancel = 0; 471 } 472 } else { 473 chata[0] = chata[1]; 474 chata[1] = delta_y; 475 } 476 477 // 移動可能か? 478 if ((pos_y <= 0) && (pos_y > (threadName.parent.height - threadName.height))) { 479 threadName.y = pos_y; 480 threadTime.y = pos_y; 481 } 482 } 483 484 // 現座標を更新 485 m_x = event.stageX; 486 m_y = event.stageY; 487 } 488 489 private function threadName_MouseUpHandler(event:MouseEvent):void { 490 491 // イベントハンドラを削除 492 threadName.removeEventListener(MouseEvent.MOUSE_MOVE, threadName_MouseMoveHandler); 493 threadName.removeEventListener(MouseEvent.MOUSE_UP, threadName_MouseUpHandler); 494 495 // チャタリング防止解除 496 chata[0] = 1; 497 chata[1] = -1; 498 chata_cancel = 0; 499 } 500 501 /* ######## ローカル関数 ####### */ 502 503 /* 335 504 * スレッドの状態の割合グラフの生成 336 505 */ 337 private var threadStateHtml:File = null; 338 private var threadStateData:File = null; 506 private var threadStateHtml:File = null; // 作業ファイル 507 private var threadStateData:File = null; // 作業ファイル 339 508 private function createThreadStateChart(name:String):void { 340 //trace("createThreadStateChart", name); 509 510 // それぞれのスレッド状態の時間を求める 341 511 var result:ArrayCollection = getThreadStateTime(name); 512 513 // スレッドの状態が1つ以上あればChartを生成 342 514 if (result.length != 0) { 343 515 var chartData:SingleChartData = new SingleChartData(); … … 345 517 chartData.graphAttribute.formatNumberScale = "0"; 346 518 for each (var val:* in result) { 347 //trace(val.name, val.value, val.color);348 519 chartData.addSetElement(val); 349 520 } 350 //trace(threadStateHtml.nativePath);351 521 chartData.createHtmlFile(threadStateHtml, "Doughnut2D", htmlState.width, htmlState.height, threadStateData.nativePath); 352 522 chartData.createDataFile(threadStateData); 353 523 htmlState.location = "file:///" + threadStateHtml.nativePath; 354 524 } else 355 htmlState.htmlText = ""; 525 htmlState.htmlText = ""; // 空のHTMLを表示 356 526 } 357 527 … … 360 530 */ 361 531 private function getThreadStateTime(name:String):ArrayCollection { 362 var stateName:Array = new Array("NEW", "RUNNABLE", "WAITING", "TIMED_WAITING", "TERMINATING", "TEMINATED"); 363 var stateColor:Array = new Array("AAAAAA", "AFD8F8", "F6BD0F", "8BBA00", "FF8E46", "008E8E"); 364 var elapse:Array = new Array(0, 0, 0, 0, 0, 0); 532 533 // Chart用の情報 534 var stateName:Array = new Array("NEW", "RUNNABLE", "WAITING", "TIMED_WAITING", "TERMINATING", "TEMINATED"); // スレッドの状態名 535 var stateColor:Array = new Array("E1E1E1", "00FF00", "FF0000", "FFFF00", "656565", "656565"); // スレッドの状態色 536 var elapse:Array = new Array(0, 0, 0, 0, 0, 0); // スレッドの状態時間 537 538 // 該当スレッドの状態データを取得 365 539 var result:Array = SqlUtil.getData(_dbconn, "select name, state, time from threadState where name == '" + name + "'"); 540 366 541 var currentState:int = 0; 367 542 var lastTime:int = 0; 368 543 var value:ArrayCollection = new ArrayCollection(); 544 545 // もし状態データが存在すれば 369 546 if (result[1].data != null) { 370 547 for each (var val:* in result[1].data) { 371 //trace(val.name, val.state, val.time); 372 elapse[currentState] += (val.time - lastTime); 548 elapse[currentState] += (val.time - lastTime); // スレッドの状態時間を計算する 373 549 currentState = val.state; 374 550 lastTime = val.time; 375 551 } 552 // スレッドの状態遷移が1つ以上あれば 376 553 if (result[1].data.length > 1) { 377 value.addItem({name: stateName[1], value: elapse[1], color: stateColor[1]}); 378 value.addItem({name: stateName[2], value: elapse[2], color: stateColor[2]}); 379 value.addItem({name: stateName[3], value: elapse[3], color: stateColor[3]}); 380 value.addItem({name: stateName[4], value: elapse[4], color: stateColor[4]}); 381 value.addItem({name: stateName[5], value: elapse[5], color: stateColor[5]}); 554 // スレッドの状態時間をChart用データに登録 555 for (var i:uint = 1; i < 6; i++) 556 value.addItem({name: stateName[i], value: elapse[i], color: stateColor[i]}); 382 557 } else { 558 // 無ければスレッドの状態時間は正しく求められないので、仕方ないからスレッドの実行時間を状態時間として求める 383 559 var result2:Array = SqlUtil.getData(_dbconn, "select sum(elapse) as value from threadTime where name =='" + name + "'"); 384 560 if (result2[1].data != null) { 385 value.addItem({name: stateName[0], value: 0, color: stateColor[0]}); 561 value.addItem({name: stateName[0], value: 0, color: stateColor[0]}); // ダミーデータ 386 562 value.addItem({name: stateName[currentState], value: result2[1].data[0].value, color: stateColor[currentState]}); 387 563 } … … 395 571 */ 396 572 private function updateThreadTimes(name:String):void { 573 // 該当スレッドの実行回数を取得 397 574 var result:Array = SqlUtil.getData(_dbconn, "select count(*) as issue from threadTime where name == '" + name + "'"); 575 576 // もしデータがあれば 398 577 if (result[1].data != null) { 578 // スレッドの実行回数 399 579 tIssue.text = result[1].data[0].issue; 580 581 // スレッドの総実行時間を取得 400 582 result = SqlUtil.getData(_dbconn, "select sum(elapse) as value from threadTime where name == '" + name + "'"); 401 583 tElapse.text = result[1].data[0].value; 402 tAveTime.text = "" + int(tElapse.text) / int(tIssue.text) 584 585 // スレッドの平均実行時間を計算 586 tAveTime.text = "" + int(tElapse.text) / int(tIssue.text); 587 588 // スレッドの最長実行時間を取得 403 589 result = SqlUtil.getData(_dbconn, "select max(elapse) as value from threadTime where name == '" + name + "'"); 404 590 tMaxTime.text = result[1].data[0].value; 591 592 // スレッドの最短実行時間を取得 405 593 result = SqlUtil.getData(_dbconn, "select min(elapse) as value from threadTime where name == '" + name + "'"); 406 594 tMinTime.text = result[1].data[0].value; 407 595 } else { 596 // データ無い... 408 597 tIssue.text = ""; 409 598 tElapse.text = ""; … … 420 609 private var threadTimeData:File = null; 421 610 private function createThreadTimeChart():void { 611 612 // スレッドの実行時間データを求める 422 613 var result:ArrayCollection = getThreadElapseTime(); 614 615 // スレッドの実行時間Chartの生成 423 616 var chartData:SingleChartData = new SingleChartData(); 424 617 chartData.graphAttribute.decimalPrecision = "0"; 425 618 chartData.graphAttribute.formatNumberScale = "0"; 426 619 for each (var val:* in result) { 427 //trace(val.name, val.value, val.color);428 620 chartData.addSetElement(val); 429 621 } 430 //trace(threadStateHtml.nativePath);431 622 chartData.createHtmlFile(threadTimeHtml, "Bar2D", htmlTime.width, htmlTime.height, threadTimeData.nativePath); 432 623 chartData.createDataFile(threadTimeData); … … 438 629 */ 439 630 private function getThreadElapseTime():ArrayCollection { 631 632 // それぞれのスレッドの実行時間の合計を得る 440 633 var result:Array = SqlUtil.getData(_dbconn, "select name, sum(elapse) as value from threadTime group by name order by value desc"); 441 var value:ArrayCollection = new ArrayCollection(); 634 635 var value:ArrayCollection = new ArrayCollection(); // Chart用データ 636 var cnt:int = 0; 637 var etc_time:int = 0; // TOP 10以外のスレッドの実行時間の合計 638 442 639 for each (var val:* in result[1].data) { 443 //trace(val.name, val.value); 444 value.addItem({name: val.name, value: val.value}); 445 } 640 // まだTOP 10が求まってなければ 641 if (cnt < 10) { 642 value.addItem({name: val.name, value: val.value}); // 実行時間をChartデータに登録 643 } else { 644 // TOP 10以外のスレッドの実行時間を足す 645 etc_time += val.value; 646 } 647 cnt++; 648 } 649 650 // スレッドが10個以上あれば 651 if (cnt >= 10) 652 value.addItem({name: "etc.", value: etc_time}); // TOP 10以外のスレッドの実行時間をChartデータに登録 653 446 654 return value; 447 655 } 448 656 449 657 /* 450 * アプリケーションの終了ハンドラ 451 */ 452 private function onAppClosing(event:Event):void { 453 var prefList:ArrayCollection = new ArrayCollection(); 454 prefList.addItem("nativeWindow.x"); 455 prefList.addItem("nativeWindow.y"); 456 prefList.addItem("width"); 457 prefList.addItem("height"); 458 PreferenceUtil.save(this, prefList, "preference.xml"); 459 if (_dbconn != null) 460 _dbconn.close(); 461 } 658 * フレーム同期間隔の確認/更新 659 */ 660 private var frameGet:Boolean = false; // フレーム同期を既に受け取ったか 661 private var lastNopTime:int = 0; // 最後にnopが来た時間 662 private var maxInterval:int = 0; // フレーム間隔の最大値 663 private var maxIntPos:int = 0; // 最大フレーム間隔が発生した時間 664 private var minInterval:int = 10000; // フレーム間隔の最小値 デフォルト値:10秒 665 private var minIntPos:int = 0; // 最小フレーム間隔が発生した時間 666 private var totalInterval:int = 0; // 総フレーム間隔時間 667 private var intervalCount:int = 0; // フレーム同期回数 668 private function checkInterval(t:int, period:int):void { 669 var intervalTime:int = 0; 670 671 // もしフレーム同期を既に取得済みなら 672 if (frameGet) { 673 intervalTime = t - lastNopTime; // 同期間隔を求める 674 } else { 675 intervalTime = period; 676 frameGet = true; 677 } 678 totalInterval += intervalTime; 679 intervalCount++; 680 681 // もし現在の最大値より大きかったら 682 if (intervalTime > maxInterval) { 683 maxInterval = intervalTime; 684 maxIntPos = pos_x - intervalTime; 685 tElapseMax.text = "Max " + convertElapseTime(maxInterval).substring(6); 686 } 687 688 // もし現在の最小値よりも小さかったら 689 if (intervalTime < minInterval) { 690 minInterval = intervalTime; 691 minIntPos = pos_x - intervalTime; 692 tElapseMin.text = "Min " + convertElapseTime(minInterval).substring(6); 693 } 694 695 var ave_time:int = totalInterval/intervalCount; // 平均フレーム間隔時間を求める 696 tElapseAve.text = "Ave " + convertElapseTime(ave_time).substring(6); 697 tFPS.text = "FPS: " + int(1000 / ave_time); // FPSを計算 698 lastNopTime = t; // 現在時間の更新 699 } 700 701 /* 702 * 時間(ms)を文字列 "HH:MM:SS.SSS" に変換 703 */ 704 private function convertElapseTime(time:int):String { 705 var elapseTime:Date = new Date(time); 706 var value:String = ""; 707 if (elapseTime.hoursUTC < 10) 708 value += "0"; 709 value += (elapseTime.hoursUTC + ":"); 710 if (elapseTime.minutesUTC < 10) 711 value += "0"; 712 value += (elapseTime.minutesUTC + ":"); 713 if (elapseTime.secondsUTC < 10) 714 value += "0"; 715 value += (elapseTime.secondsUTC + "."); 716 if (elapseTime.millisecondsUTC < 100) 717 value += "0"; 718 if (elapseTime.millisecondsUTC < 10) 719 value += "0"; 720 value += (elapseTime.millisecondsUTC + ""); 721 return value; 722 } 723 724 /* 725 * nopを生成 726 */ 727 private function createNop():void { 728 threadList.addItem("nop"); // スレッドリストに"nop"を登録 729 var t:Label = new Label(); 730 t.x = LEFT_PADD; t.y = 0; t.text = "nop"; 731 threadName.addChild(t); 732 } 733 734 /* 735 * Frame Per Second(FPS)情報の取得ハンドラ 736 */ 737 public function frameInfoHandler(fps:uint):void { 738 framePerSecond = fps; 739 frameInterval = 1000/framePerSecond; 740 } 741 as3/ThreadViewer/ThreadViewer.mxml
r1207 r1306 2 2 <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()"> 3 3 <mx:Script source="ThreadViewer.as"/> 4 <mx:Style source="style.css"/> 4 5 <mx:VBox width="100%" height="100%"> 5 <mx:Canvas width="100%" height="44"> 6 <mx:Button x="8" y="8" id="bStartStop" width="60" label="Start" click="bStartStop_ClickHandler(event)"/> 7 <mx:Button x="76" y="8" id="bClear" label="Clear" click="bClear_ClickHandler(event)"/> 6 <mx:Canvas width="100%" height="48"> 7 <mx:Button x="8" y="8" id="bRecordStop" styleName="RecordStopIconBtn" toggle="true" toolTip="Record" click="bRecordStop_ClickHandler(event)"/> 8 <mx:Label id="tElapseTime" x="48" y="15" text="00:00:00.000" styleName="TimeLabel"/> 9 <mx:Button id="bClear" x="174" y="11" click="bClear_ClickHandler(event)" styleName="ClearIconBtn" toolTip="Clear record"/> 10 <mx:Label x="210" y="14" text="Interval Time:" styleName="InfoLabel"/> 11 <mx:Label id="tElapseMax" x="314" y="14" text="Max 00.000" click="tElapseMax_ClickHandler(event)" styleName="InfoLabel"/> 12 <mx:Label id="tElapseMin" x="404" y="14" text="Min 00.000" click="tElapseMin_ClickHandler(event)" styleName="InfoLabel"/> 13 <mx:Label id="tElapseAve" x="490" y="14" text="Ave 00.000" styleName="InfoLabel"/> 14 <mx:Label id="tFPS" x="580" y="14" text="FPS: 000" styleName="InfoLabel"/> 15 <mx:Button id="bInfo" right="12" y="11" click="bInfo_ClickHandler(event)" styleName="InfoIconBtn" toolTip="Show information"/> 16 <mx:HRule y="47" width="100%" strokeWidth="1" strokeColor="#555555"/> 8 17 </mx:Canvas> 9 <mx:HBox width="100%" height="100%"> 10 <mx:VBox width="150" height="100%"> 11 <mx:Canvas id="threadName" width="100%" height="100%" verticalScrollPolicy="off"/> 12 <mx:HSlider width="150" height="20" id="hsScale" minimum="0.25" maximum="4" snapInterval="0.25" value="1.0" change="hsScale_ChangeHandler(event)"/> 13 </mx:VBox> 14 <mx:Canvas id="threadTime" width="100%" height="100%" verticalScrollPolicy="off"/> 15 </mx:HBox> 18 <mx:Canvas width="100%" height="100%"> 19 <mx:HDividedBox width="100%" height="100%"> 20 <mx:VBox id="vbThread" width="150" height="100%" minWidth="150"> 21 <mx:Canvas width="100%" height="100%" verticalScrollPolicy="off" horizontalScrollPolicy="off"> 22 <mx:Canvas id="threadName"/> 23 </mx:Canvas> 24 <mx:HBox width="100%" height="18" verticalAlign="center"> 25 <!-- mx:Image source="@Embed('icons/ZoomMin.png')" left="8"/ --> 26 <mx:HSlider width="{vbThread.width}" height="100%" id="hsScale" minimum="0.25" maximum="4" snapInterval="0.25" value="1.0" change="hsScale_ChangeHandler(event)"/> 27 <!-- mx:Image source="@Embed('icons/ZoomMax.png')" right="8"/ --> 28 </mx:HBox> 29 </mx:VBox> 30 <mx:Canvas id="threadTimeContainer" width="100%" height="100%" verticalScrollPolicy="off"> 31 <mx:Canvas id="threadTime"/> 32 </mx:Canvas> 33 </mx:HDividedBox> 34 </mx:Canvas> 16 35 <mx:Canvas width="100%" height="240"> 17 36 <mx:ComboBox id="cbThread" left="8" y="10" width="142" close="cbThread_CloseHandler(event)"/> as3/ThreadViewer/org/libspark/snippets/AIRUtils/PreferenceUtil.as
r898 r1306 74 74 setupProperties(obj[val.name()], val.children(), txt == null ? null : txt + "." + val.name()); 75 75 } else { 76 //trace(val.name()); 77 if (obj[val.name()] is Boolean) { 78 //trace("Boolean"); 76 if (obj[val.name()] is Boolean) 79 77 obj[val.name()] = val == "true" ? true : false; 80 } else if (obj[val.name()] is Number) { 81 //trace("Number"); 78 else if (obj[val.name()] is Number) 82 79 obj[val.name()] = Number(val); 83 } else if (obj[val.name()] is ArrayCollection) { 84 //trace("ArrayCollection"); 80 else if (obj[val.name()] is ArrayCollection) 85 81 obj[val.name()] = Base64ToArrayCollection(val); 86 } else if (obj[val.name()] is Array) { 87 //trace("Array"); 82 else if (obj[val.name()] is Array) 88 83 obj[val.name()] = Base64ToArray(val); 89 } else if (obj[val.name()] is XML) { 90 //trace("XML"); 84 else if (obj[val.name()] is XML) 91 85 obj[val.name()] = Base64toXML(val); 92 } else if (obj[val.name()] is String) { 93 //trace("String"); 94 obj[val.name()] = String(val); 95 } else { 96 //trace("Unknown"); 86 else 97 87 obj[val.name()] = val; 98 }99 88 } 100 89 }

