チェンジセット 1306: as3/ThreadViewer

差分発生行の前後
無視リスト:
コミット日時:
2008/09/13 18:51:11 (3 年前)
コミッタ:
daoki2
ログメッセージ:

機能追加&アイコン作成

ファイル:

凡例:

変更無し
追加
削除
更新
コピー
移動
  • as3/ThreadViewer/ThreadViewer-app.xml

    r1207 r1306  
    22<application xmlns="http://ns.adobe.com/air/application/1.0"> 
    33<id>org.libspark.ThreadViewer</id> 
    4 <version>0.5</version> 
     4<version>0.6</version> 
    55<filename>ThreadViewer</filename> 
    66<name>Thread Viewer</name> 
    7 <description>This is ActionScript Thread Viewer application</description> 
     7<description>This is ActionScript Thread Library Viewer Application</description> 
    88<copyright>(c) daoki2 2008</copyright> 
    99 
     
    1414  <transparent>false</transparent> 
    1515  <visible>false</visible> 
    16   <width>640</width> 
    17   <height>510</height> 
     16  <width>780</width> 
     17  <height>520</height> 
    1818</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> 
    1925</application> 
  • as3/ThreadViewer/ThreadViewer.as

    r1207 r1306  
    33 * 
    44 * @author      Copyright (c) 2008 daoki2 
    5  * @version     0.5 
    6  * @link        http://snippets.libspark.org/ 
     5 * @version     0.6 
     6 * @link        http://www.libspark.org/wiki/daoki2/ThreadViewer 
    77 * @link        http://homepage.mac.com/daoki2/ 
    88 * 
     
    3232import flash.data.*; 
    3333import flash.desktop.NativeApplication; 
     34import flash.net.LocalConnection; 
    3435 
    3536import mx.events.*; 
    3637import mx.collections.ArrayCollection; 
    37 import mx.controls.Label; 
    38 import mx.controls.VRule; 
    39 import flash.net.LocalConnection; 
     38import mx.controls.*; 
     39 
    4040import org.libspark.snippets.AIRUtils.PreferenceUtil; 
    4141import org.libspark.thread.ThreadState; 
     
    4343import org.libspark.snippets.controls.ChartData.FusionCharts.SingleChartData; 
    4444 
    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; 
     45private static const LEFT_PADD:uint = 38; // スレッド名のX座標 
     46private var _conn:LocalConnection; // LocalConnection接続用 
     47private var threadList:ArrayCollection = new ArrayCollection(); // スレッドリスト 
     48private var threadNameLabel:ArrayCollection = new ArrayCollection(); // スレッド名Labelのリスト 
     49private var threadStatus:ArrayCollection = new ArrayCollection(); // スレッド状態のリスト 
     50private var threadLog:ArrayCollection = new ArrayCollection(); // スレッド遷移グラフのリスト 
     51private var pos_x:Number = 0; // スレッド遷移グラフのX座標 
     52private var isLogging:Boolean = false; // ログ収集中か否か 
     53private var framePerSecond:uint = 24; // フレーム/秒 
     54private var frameInterval:Number = 1000/24; // 時間(ms)/フレーム 
     55private var _dbconn:SQLConnection; // ローカルデータベース接続用 
     56 
     57/* ######## アプリケーション関連のハンドラ ######## */ 
    5858 
    5959/* 
     
    6161 */ 
    6262private function init():void { 
     63    // イベントハンドラの登録 
    6364    addEventListener(Event.CLOSING, onAppClosing); 
     65    addEventListener(FlexNativeWindowBoundsEvent.WINDOW_RESIZE, onWinResize); 
     66    threadName.addEventListener(MouseEvent.MOUSE_DOWN, threadName_MouseDownHandler); 
     67 
     68    // プリファレンス(初期値)の読み込み 
    6469    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 
    7182    this.visible = true; 
    72     //trace(this.width, this.height); 
     83 
     84    // LocalConnectionの作成 
    7385    _conn = new LocalConnection(); 
    7486    _conn.client = this; 
     87 
    7588    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の生成 
    7994        createNop(); 
     95 
     96        // ローカルデータベースをオープン 
    8097        var dbFile:File = File.applicationDirectory.resolvePath("thread.db"); 
    8198        _dbconn = new SQLConnection(); 
    8299        _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の作業ファイルを設定 
    85104        threadStateHtml = File.applicationStorageDirectory.resolvePath("threadState.html"); 
    86105        threadStateData = File.applicationStorageDirectory.resolvePath("threadState.xml"); 
     
    95114 
    96115/* 
    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 */ 
     118private 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 */ 
     136private 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関連のイベントハンドラ ######## */ 
    114148 
    115149/* 
     
    117151 */ 
    118152public function threadEntryHandler(name:String, newThread:Boolean = true):void { 
    119     //trace("threadEntryHandler", name); 
     153     
     154    // ログ収集中でなければ終わる 
    120155    if (!isLogging) 
    121156        return; 
    122  
     157     
     158    // スレッドリスト中にあるか? 
    123159    if (threadList.contains(name)) { 
    124         trace("Thread", name, "already exists"); 
     160        trace("Thread", name, "already exists"); // 既に同名のスレッドが存在する 
    125161    } else { 
     162        // スレッド名のLabelを生成 
    126163        var t:Label = new Label(); 
    127164        t.x = LEFT_PADD; 
    128         t.y = threadList.length * 12
     165        t.y = threadList.length * 16
    129166        t.text = name; 
    130167        threadName.addChild(t); 
    131168        threadNameLabel.addItem(t); 
    132         threadList.addItem(name); 
    133         var s:Label = new Label(); 
     169         
     170        // スレッド状態のImageを生成 
     171        var s:Image = new Image(); 
    134172        s.x = 8; 
    135         s.y = t.y
     173        s.y = threadList.length * 16 + 1
    136174        if (newThread) 
    137             s.text = "[N]"; 
     175            s.source = "icons/NEW.png"; // 新規のスレッド 
    138176        else 
    139             s.text = "[R]"; 
     177            s.source = "icons/RUNNABLE.png"; //既存のスレッド 
     178         
    140179        threadName.addChild(s); 
    141180        threadStatus.addItem(s); 
     181         
     182        // スレッドリストに登録 
     183        threadList.addItem(name); 
    142184    }    
    143185} 
     
    147189 */ 
    148190public function threadNameHandler(name:String, newName:String):void { 
    149     //trace("threadNameHandler", name, newName); 
     191 
     192    // ログ収集中でなければ終わる 
    150193    if (!isLogging) 
    151194        return; 
    152195 
     196    // スレッドリスト中にあるか? 
    153197    if (!threadList.contains(name)) 
    154         threadEntryHandler(name, false); 
     198        threadEntryHandler(name, false); // 無いので、既存のスレッドとして登録 
     199 
     200    // スレッドリストに登録されてるスレッド名を変更 
    155201    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"も含むので、ひとつ引く 
    159207    n.text = newName; 
    160208} 
     
    164212 */ 
    165213public 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    // ログ収集中でなければ終わる 
    167220    if (!isLogging) 
    168221        return; 
    169222 
     223    // スレッドリスト中にあるか? 
    170224    if (!threadList.contains(name)) 
    171         threadEntryHandler(name, false); 
     225        threadEntryHandler(name, false); // 無いので、既存のスレッドとして登録 
     226 
     227    // 状態リストから該当のImageを取得して、画像を更新する 
    172228    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    // ローカルデータベースに情報を記録 
    194233    SqlUtil.executeSQLStatement(_dbconn, "insert into threadState(name, state, time) values ('" + name + "', " + status + ", " + time + ")"); 
    195234} 
    196235 
    197 private var b_color:uint = 0x0000ff; 
     236private var b_color:uint = 0x0000ff; // スレッド遷移グラフのデフォルト色 
    198237 
    199238/* 
     
    201240 */ 
    202241public function threadTimeHandler(name:String, startTime:int, endTime:int):void { 
    203     //trace("threadTimeHandler", name, time); 
     242 
     243    // ログ収集中でなければ終わる 
    204244    if (!isLogging) 
    205245        return; 
    206246 
    207     var pos_y:Number = 0; 
     247    // スレッドリスト中にあるか? 
    208248    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    // スレッド遷移グラフの生成 
    211254    var b:VBox = new VBox(); 
    212255    b.x = pos_x; 
     
    214257    b.toolTip = String(endTime - startTime) + "ms"; 
    215258    b.width = (endTime - startTime) * hsScale.value; 
    216     b.height = 12
     259    b.height = 16
    217260    b.setStyle("backgroundColor", b_color); 
    218261    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"が来る 
    221268    if (name == "nop") { 
     269        checkInterval(endTime, endTime - startTime); // フレーム同期間隔の確認 
     270 
     271        // フレーム毎に色を入れ替える 
    222272        if (b_color == 0x0000ff) 
    223273                b_color = 0x8888ff; 
     
    225275                b_color = 0x0000ff; 
    226276    } 
    227     //drawGrid(pos_x); 
     277 
     278    // ローカルデータベースに情報を記録 
    228279    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 */ 
     288private function bRecordStop_ClickHandler(event:MouseEvent):void { 
     289 
     290    hsScale.enabled = isLogging; // 縮尺スケーラを有効/無効にする 
     291 
     292    // もしログ収集中だったら? 
    254293    if (isLogging) { 
    255         bStartStop.label = "Start"; 
    256         threadList.removeItemAt(0); 
     294        // ログ収集を止める 
     295        bRecordStop.toolTip = "Record"; // ログ収集を止めるから次回は"Record"。ややこしい...  
     296        threadList.removeItemAt(0); // スレッドリストから"nop"を削除 
     297        // もしスレッドが1つでもあれば 
    257298        if (threadList.length != 0) { 
     299            // スレッド選択コンボボックスの更新 
    258300            cbThread.dataProvider = threadList; 
    259301            cbThread.selectedItem = threadList.getItemAt(0); 
     302 
     303            // スレッド状態Chartの作成 
    260304            createThreadStateChart(String(threadList.getItemAt(0))); 
     305 
     306            // スレッド実行時間のアップデート 
    261307            updateThreadTimes(String(threadList.getItemAt(0))); 
     308 
     309            // スレッド実行時間Chartの作成 
    262310            createThreadTimeChart(); 
    263311        } 
    264312    } 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ボタンを無効/有効にする 
    269318} 
    270319 
     
    273322 */ 
    274323private function bClear_ClickHandler(event:MouseEvent):void { 
    275     //trace("clear"); 
     324 
     325    // 管理リストの削除 
    276326    threadLog.removeAll(); 
    277327    threadList.removeAll(); 
    278328    threadNameLabel.removeAll(); 
    279329    threadStatus.removeAll(); 
     330 
     331    // スレッド遷移グラフの削除 
    280332    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; 
    284338    cbThread.dataProvider = null; 
    285     createNop(); 
    286339    tIssue.text = ""; 
    287340    tElapse.text = ""; 
     
    291344    htmlState.htmlText = ""; 
    292345    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    // ローカルデータベースの古いデータを削除 
    293365    SqlUtil.executeSQLStatement(_dbconn, "delete from threadTime"); 
    294366    SqlUtil.executeSQLStatement(_dbconn, "delete from threadState"); 
    295     //firstNop = -1; 
    296     //grid_x = 0; 
     367 
     368    // nopを生成 
     369    createNop(); 
    297370} 
    298371 
     
    301374 */ 
    302375private function hsScale_ChangeHandler(event:SliderEvent):void { 
    303     //trace(event.value); 
     376 
     377    // 描画X座標を先頭に戻す 
    304378    pos_x = 0; 
     379 
     380    // スレッド遷移グラフの位置とサイズを更新 
    305381    for each (var val:* in threadLog) { 
    306382        var b:VBox = VBox(val.bar); 
    307383        var time:int = int(val.time); 
    308384        b.x = pos_x; 
    309         b.width = time * event.value; 
     385        b.width = time * event.value; // 縮尺と時間からサイズを計算 
    310386        pos_x += b.width; 
    311387    } 
    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 */ 
    324388} 
    325389 
     
    328392 */ 
    329393private function cbThread_CloseHandler(event:Event):void { 
     394     
     395    // スレッド状態Chartの作成 
    330396    createThreadStateChart(String(ComboBox(event.target).selectedItem)); 
     397 
     398    // スレッド実行時間の更新 
    331399    updateThreadTimes(String(ComboBox(event.target).selectedItem)); 
    332400} 
    333401 
    334402/* 
     403 * インフォメーション表示 
     404 */ 
     405private function bInfo_ClickHandler(event:MouseEvent):void { 
     406    // Publisher IDをアラートで表示 
     407    Alert.show(NativeApplication.nativeApplication.publisherID, 'Publisher ID'); 
     408} 
     409 
     410/* 
     411 * Interval Maxラベルのクリックハンドラ 
     412 */ 
     413private function tElapseMax_ClickHandler(event:MouseEvent):void { 
     414    // フレーム同期間隔が最大の場所にスクロール 
     415    threadTimeContainer.horizontalScrollPosition = maxIntPos * hsScale.value; 
     416} 
     417 
     418/* 
     419 * Interval Minラベルのクリックハンドラ 
     420 */ 
     421private function tElapseMin_ClickHandler(event:MouseEvent):void { 
     422    // フレーム同期間隔が最小の場所にスクロール 
     423    threadTimeContainer.horizontalScrollPosition = minIntPos * hsScale.value; 
     424} 
     425 
     426/* 
     427 * threadNameのドラッグ制御 
     428 */ 
     429private var m_x:Number; 
     430private var m_y:Number; 
     431private 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 
     442private var chata:Array = new Array(1, -1); // チャタリング防止用のバッファ 
     443private var chata_cancel:int = 0; // チャタリング防止キャンセルのカウンタ 
     444private 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 
     489private 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/* 
    335504 * スレッドの状態の割合グラフの生成 
    336505 */ 
    337 private var threadStateHtml:File = null; 
    338 private var threadStateData:File = null; 
     506private var threadStateHtml:File = null; // 作業ファイル 
     507private var threadStateData:File = null; // 作業ファイル 
    339508private function createThreadStateChart(name:String):void { 
    340     //trace("createThreadStateChart", name); 
     509 
     510    // それぞれのスレッド状態の時間を求める 
    341511    var result:ArrayCollection = getThreadStateTime(name); 
     512 
     513    // スレッドの状態が1つ以上あればChartを生成 
    342514    if (result.length != 0) { 
    343515        var chartData:SingleChartData = new SingleChartData(); 
     
    345517        chartData.graphAttribute.formatNumberScale = "0"; 
    346518        for each (var val:* in result) { 
    347             //trace(val.name, val.value, val.color); 
    348519            chartData.addSetElement(val); 
    349520        } 
    350         //trace(threadStateHtml.nativePath); 
    351521        chartData.createHtmlFile(threadStateHtml, "Doughnut2D", htmlState.width, htmlState.height, threadStateData.nativePath); 
    352522        chartData.createDataFile(threadStateData); 
    353523        htmlState.location = "file:///" + threadStateHtml.nativePath; 
    354524    } else 
    355         htmlState.htmlText = ""; 
     525        htmlState.htmlText = ""; // 空のHTMLを表示 
    356526} 
    357527 
     
    360530 */ 
    361531private 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    // 該当スレッドの状態データを取得 
    365539    var result:Array = SqlUtil.getData(_dbconn, "select name, state, time from threadState where name == '" + name + "'"); 
     540 
    366541    var currentState:int = 0; 
    367542    var lastTime:int = 0; 
    368543    var value:ArrayCollection = new ArrayCollection(); 
     544 
     545    // もし状態データが存在すれば 
    369546    if (result[1].data != null) { 
    370547        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); // スレッドの状態時間を計算する 
    373549            currentState = val.state; 
    374550            lastTime = val.time; 
    375551        } 
     552        // スレッドの状態遷移が1つ以上あれば 
    376553        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]}); 
    382557        } else { 
     558            // 無ければスレッドの状態時間は正しく求められないので、仕方ないからスレッドの実行時間を状態時間として求める 
    383559            var result2:Array = SqlUtil.getData(_dbconn, "select sum(elapse) as value from threadTime where name =='" + name + "'"); 
    384560            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]}); // ダミーデータ 
    386562                value.addItem({name: stateName[currentState], value: result2[1].data[0].value, color: stateColor[currentState]}); 
    387563            } 
     
    395571 */ 
    396572private function updateThreadTimes(name:String):void { 
     573    // 該当スレッドの実行回数を取得 
    397574    var result:Array = SqlUtil.getData(_dbconn, "select count(*) as issue from threadTime where name == '" + name + "'"); 
     575 
     576    // もしデータがあれば 
    398577    if (result[1].data != null) { 
     578        // スレッドの実行回数 
    399579        tIssue.text = result[1].data[0].issue; 
     580 
     581        // スレッドの総実行時間を取得 
    400582        result = SqlUtil.getData(_dbconn, "select sum(elapse) as value from threadTime where name == '" + name + "'"); 
    401583        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        // スレッドの最長実行時間を取得 
    403589        result = SqlUtil.getData(_dbconn, "select max(elapse) as value from threadTime where name == '" + name + "'"); 
    404590        tMaxTime.text = result[1].data[0].value; 
     591 
     592        // スレッドの最短実行時間を取得 
    405593        result = SqlUtil.getData(_dbconn, "select min(elapse) as value from threadTime where name == '" + name + "'"); 
    406594        tMinTime.text = result[1].data[0].value; 
    407595    } else { 
     596        // データ無い... 
    408597        tIssue.text = ""; 
    409598        tElapse.text = ""; 
     
    420609private var threadTimeData:File = null; 
    421610private function createThreadTimeChart():void { 
     611 
     612    // スレッドの実行時間データを求める 
    422613    var result:ArrayCollection = getThreadElapseTime(); 
     614 
     615    // スレッドの実行時間Chartの生成 
    423616    var chartData:SingleChartData = new SingleChartData(); 
    424617    chartData.graphAttribute.decimalPrecision = "0"; 
    425618    chartData.graphAttribute.formatNumberScale = "0"; 
    426619    for each (var val:* in result) { 
    427         //trace(val.name, val.value, val.color); 
    428620        chartData.addSetElement(val); 
    429621    } 
    430     //trace(threadStateHtml.nativePath); 
    431622    chartData.createHtmlFile(threadTimeHtml, "Bar2D", htmlTime.width, htmlTime.height, threadTimeData.nativePath); 
    432623    chartData.createDataFile(threadTimeData); 
     
    438629 */ 
    439630private function getThreadElapseTime():ArrayCollection { 
     631 
     632    // それぞれのスレッドの実行時間の合計を得る 
    440633    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 
    442639    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 
    446654    return value; 
    447655} 
    448656 
    449657/* 
    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 */ 
     660private var frameGet:Boolean = false; // フレーム同期を既に受け取ったか 
     661private var lastNopTime:int = 0; // 最後にnopが来た時間 
     662private var maxInterval:int = 0; // フレーム間隔の最大値 
     663private var maxIntPos:int = 0; // 最大フレーム間隔が発生した時間 
     664private var minInterval:int = 10000; // フレーム間隔の最小値 デフォルト値:10秒 
     665private var minIntPos:int = 0; // 最小フレーム間隔が発生した時間 
     666private var totalInterval:int = 0; // 総フレーム間隔時間 
     667private var intervalCount:int = 0; // フレーム同期回数 
     668private 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 */ 
     704private 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 */ 
     727private 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 */ 
     737public function frameInfoHandler(fps:uint):void { 
     738    framePerSecond = fps; 
     739    frameInterval = 1000/framePerSecond; 
     740
     741 
  • as3/ThreadViewer/ThreadViewer.mxml

    r1207 r1306  
    22<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()"> 
    33  <mx:Script source="ThreadViewer.as"/> 
     4  <mx:Style source="style.css"/> 
    45  <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"/> 
    817    </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> 
    1635    <mx:Canvas width="100%" height="240"> 
    1736      <mx:ComboBox id="cbThread" left="8" y="10" width="142" close="cbThread_CloseHandler(event)"/> 
  • as3/ThreadViewer/org/libspark/snippets/AIRUtils/PreferenceUtil.as

    r898 r1306  
    7474                        setupProperties(obj[val.name()], val.children(), txt == null ? null : txt + "." + val.name()); 
    7575                    } else { 
    76                         //trace(val.name()); 
    77                         if (obj[val.name()] is Boolean) { 
    78                             //trace("Boolean"); 
     76                        if (obj[val.name()] is Boolean) 
    7977                            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) 
    8279                            obj[val.name()] = Number(val); 
    83                         } else if (obj[val.name()] is ArrayCollection) { 
    84                             //trace("ArrayCollection"); 
     80                        else if (obj[val.name()] is ArrayCollection) 
    8581                            obj[val.name()] = Base64ToArrayCollection(val); 
    86                         } else if (obj[val.name()] is Array) { 
    87                             //trace("Array"); 
     82                        else if (obj[val.name()] is Array) 
    8883                            obj[val.name()] = Base64ToArray(val); 
    89                         } else if (obj[val.name()] is XML) { 
    90                             //trace("XML"); 
     84                        else if (obj[val.name()] is XML) 
    9185                            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 
    9787                            obj[val.name()] = val; 
    98                         } 
    9988                    } 
    10089                }