「ポップアップメニューを「n*十件ずつ」のサブメニューに自動分割する」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
Sukemaru (トーク | 投稿記録)
ページを新規作成
 
Sukemaru (トーク | 投稿記録)
画像を追加
1行目: 1行目:
== 分割サブメニュー ==
== 分割サブメニュー ==


ポップアップメニューの'''アイテム数が非常に多いとき'''、メニューの上下に配置されたスピンドル ▲▼ でスクロールさせるのは効率が悪いので、「1 - 20 件目 ▸」「21 - 40 件目 ▸」のかたちでサブメニュー項目に分割して表示するためのサンプルコードです。
ポップアップメニューの'''アイテム数が非常に多いとき'''、メニューの上下に配置されたスピンハンドル ▲ ▼ でスクロールさせるのは効率が悪いので、「1 - 20 件目 ▸」「21 - 40 件目 ▸」のかたちでサブメニュー項目に分割して表示するためのサンプルコードです。


アイテム数にあわせて「1 - 20 件目 ▸」「21 - 40 件目 ▸」の'''分割サブメニュー項目を自動的に生成'''しますので、ポップアップメニューのアイテム数が増減する「検索」「抽出」系のマクロに仕込むと便利かも。
アイテム数にあわせて「1 - 20 件目 ▸」「21 - 40 件目 ▸」の'''分割サブメニュー項目を自動的に生成'''しますので、ポップアップメニューのアイテム数が増減する「検索」「抽出」系のマクロに仕込むと便利かも。
15行目: 15行目:
  '''''[ ["アイテム1",id_1], ["アイテム2",id_2], ["アイテム3",id_3], ["アイテム4",id_4] ... ]'''''  
  '''''[ ["アイテム1",id_1], ["アイテム2",id_2], ["アイテム3",id_3], ["アイテム4",id_4] ... ]'''''  
の形式の'''配列で用意してください。'''任意で ''flags'' を配列に入れてもよいでしょう。<br> for() 文のループ処理でポップアップメニュー項目に変換します。
の形式の'''配列で用意してください。'''任意で ''flags'' を配列に入れてもよいでしょう。<br> for() 文のループ処理でポップアップメニュー項目に変換します。
;サンプルコードのポップアップメニュー画像
[[ファイル:Mery_分割サブメニュー_SS(1).png|frameless|362px|thumb|left|subMenuEnable = 1]]
[[ファイル:Mery_分割サブメニュー_SS(2).png|frameless|254px|thumb|subMenuEnable = 2]]
<br clear=all>




22行目: 29行目:


* 設定項目用の変数 ''subMenuHeight'' で、サブメニュー内の分割行数を指定します。
* 設定項目用の変数 ''subMenuHeight'' で、サブメニュー内の分割行数を指定します。
* もうひとつの設定変数 ''subMenuEnable'' は、分割サブメニュー「1 - 20 件目 ▸」「21 - 40 件目 ▸」の項目を表示 するか/しないか と、メニュー項目「20 件ずつ表示 ▸」の配下に置くか/メインのメニュー直下に置くか を指定するためのものです。
* もうひとつの設定変数 ''subMenuEnable'' は、分割サブメニュー「1 - 20 件目 ▸」「21 - 40 件目 ▸」の項目を表示 するか/しないか と、メニュー項目「20 件ずつ表示 ▸」の配下に置く(画像:左)/メインのメニュー直下に置く(画像:右) を指定するためのものです。




74行目: 81行目:
var lineText, lines = d.GetLines( 0 );
var lineText, lines = d.GetLines( 0 );
for ( var y = 1; y <= lines; y++ ) {
for ( var y = 1; y <= lines; y++ ) {
  lineText = d.GetLine( y, 0 ).replace( /\t+|\s{4,}|[ ]{2,}/g, " › " )
          // 空白文字を詰め、「&」記号を保守する
                              .replace( /&/g, "&&" ).slice( 0, 30 );
  lineText = d.GetLine( y, 0 )
                      .replace( /\t+|[ ]{4,}|[ ]{2,}/g, " › " )
              .replace( /&/g, "&&" ).slice( 0, 30 );
  itemArray.push( [ ":  " + lineText, y ] );
  itemArray.push( [ ":  " + lineText, y ] );
}
}
81行目: 90行目:
   // 「アイテム」数
   // 「アイテム」数
   var len = itemArray.length;
   var len = itemArray.length;
   // 「アイテム数」のケタ数 ※ケタ埋めに使用する
   // 「アイテム数」のケタ数(※ケタ埋めに使用する)
   var lenWidth = len.toString().length;
   var lenWidth = len.toString().length;


87行目: 96行目:
     // ポップアップメニューの準備
     // ポップアップメニューの準備
     var menu = CreatePopupMenu();
     var menu = CreatePopupMenu();


     /**
     /**
95行目: 105行目:
       DevidedSubMenu();
       DevidedSubMenu();
     }
     }


     // subMenuEnable = 1 またはアイテム数が「分割単位」の 2 倍以下なら
     // subMenuEnable = 1 またはアイテム数が「分割単位」の 2 倍以下なら
104行目: 115行目:


         // 配列の「アイテム」をメインメニュー直下に追加する
         // 配列の「アイテム」をメインメニュー直下に追加する
         menu.Add( Pad( itemArray[i][1], 2 ) + itemArray[i][0], itemArray[i][1] );
         menu.Add( Pad( itemArray[i][1], 2 )
                + itemArray[i][0]
                , itemArray[i][1] );
       }
       }
       // 最下行に「キャンセル」をピン止めする(Space キーでスクロール可)
       // 最下行に「キャンセル」をピン止めする(Space キーでスクロール可)
110行目: 123行目:
       menu.Add( Pad() + "キャンセル\t& ", 0 );
       menu.Add( Pad() + "キャンセル\t& ", 0 );
     }
     }


     // ステータスバーにメニューの件数と処理時間を表示する
     // ステータスバーにメニューの件数と処理時間を表示する
138行目: 152行目:
   *  
   *  
   * ※呼び出し元のスコープが閉じている場合は
   * ※呼び出し元のスコープが閉じている場合は
   *  設定変数2つと menu itemArray を引き渡すこと
   *  設定変数 subMenuHeight と menu , itemArray を引き渡すこと
   *  e.g. DevidedSubMenu( objPopupMenu, items )
   *  e.g. DevidedSubMenu( objPopupMenu, items, height )
   *   len = itemArray.length と lenWith = len.toString().length は
   * len = itemArray.length と lenWith = len.toString().length は
   *   関数のなかで再定義できる
   * 関数のなかで再定義できる
   */
   */
   function DevidedSubMenu() {
   function DevidedSubMenu() {
148行目: 162行目:
     if ( subMenuEnable == 1 ) {
     if ( subMenuEnable == 1 ) {
       // 「※ 20* 件ずつ表示 ※  ▶」をピン止め
       // 「※ 20* 件ずつ表示 ※  ▶」をピン止め
       menu.AddPopup( " ※ " + subMenuHeight + " 行ずつ表示(&D) ※", subMenu );
       menu.AddPopup( " ※ " + subMenuHeight
                  + " 行ずつ表示(&D) ※"
                  , subMenu );
     }
     }
     // 「キャンセル」をピン止め
     // 「キャンセル」をピン止め
161行目: 177行目:
         // 配列にメニュー項目「_from - _to 件目  ▶」を生成する
         // 配列にメニュー項目「_from - _to 件目  ▶」を生成する
         smArray.push( CreatePopupMenu() );
         smArray.push( CreatePopupMenu() );
         // 「_from - _to 件目  ▶」メニューの index
         // 「_from - _to 件目」メニューの index
         smId = smArray.length - 1;
         smId = smArray.length - 1;
         //  _from と _to の値
         //  _from と _to の値
         _from = smId * subMenuHeight + 1;
         _from = smId * subMenuHeight + 1;
         _to = Math.min( smArray.length * subMenuHeight, len );
         _to = Math.min( smArray.length * subMenuHeight, len );
         // 「_from - _to 件目  ▶」メニュー項目
         // 「_from - _to 件目」メニュー項目
         popupMenu.AddPopup( Pad( _from, 1 ) + " - "
         popupMenu.AddPopup( Pad( _from, 1 ) + " - "
                            + Pad( _to ) + " 件目"
                          + Pad( _to ) + " 件目"
                            , smArray[smId] );
                          , smArray[smId] );
       }
       }


       // 「_from - _to 件目  ▶」メニュー配下の 10件 ごとにセパレータと
       // 「_from - _to 件目」メニュー配下の 10件 ごとにセパレータと
       // 先頭に「キャンセル」行(Space キーでキャンセル可)
       // 先頭に「キャンセル」行(Space キーでキャンセル可)
       AddCancelLines( smArray[smId], i, subMenuHeight );
       AddCancelLines( smArray[smId], i, subMenuHeight );


       // 「アイテム」の配列から「 _from - _to 件目  ▶ 」メニューに配下追加する
       // 「アイテム」の配列から「_from - _to 件目」メニュー配下に追加する
       // ※ smArray[smId] は CreatePopupMenu オブジェクト
       // ※ smArray[smId] は CreatePopupMenu オブジェクト
       smArray[smId].Add( Pad( itemArray[i][1], 2 )
       smArray[smId].Add( Pad( itemArray[i][1], 2 )
182行目: 198行目:
                       , itemArray[i][1] );
                       , itemArray[i][1] );


       // 「_from - _to 件目  ▶」のさいごに「キャセル」行を追加する
       // 「_from - _to 件目」のさいごに「キャセル」行を追加する
       if ( i == len - 1 ) {
       if ( i == len - 1 ) {
         popupMenu.Add( "", 0, meMenuSeparator );
         popupMenu.Add( "", 0, meMenuSeparator );

2019年4月21日 (日) 21:39時点における版

分割サブメニュー

ポップアップメニューのアイテム数が非常に多いとき、メニューの上下に配置されたスピンハンドル ▲ ▼ でスクロールさせるのは効率が悪いので、「1 - 20 件目 ▸」「21 - 40 件目 ▸」のかたちでサブメニュー項目に分割して表示するためのサンプルコードです。

アイテム数にあわせて「1 - 20 件目 ▸」「21 - 40 件目 ▸」の分割サブメニュー項目を自動的に生成しますので、ポップアップメニューのアイテム数が増減する「検索」「抽出」系のマクロに仕込むと便利かも。


  • 「1 - 20 件目 ▸」「21 - 40 件目 ▸」の項目は、サブメニュー項目「20 件ずつ表示 ▸」配下の "孫" メニュー項目にすることもでき、分割サブメニュー内の行数「20 件目」の部分は設定項目で任意の数値に変更できます(10 件ごとにセパレータを挿入するので、10 の倍数を推奨)。
  • 「分割サブメニュー」を使用するかしないかは設定項目で選択できますが、「使用する」に設定した場合でもアイテム数が「分割する単位」の 2 倍以下のときは「分割サブメニュー」で表示せず、メインメニューの直下にアイテムを列挙します。


ポップアップメニューに列挙するアイテムは
PopupMenu.Add( "文字列", id [, flags ] ) メソッドの記法にあわせて

[ ["アイテム1",id_1], ["アイテム2",id_2], ["アイテム3",id_3], ["アイテム4",id_4] ... ] 

の形式の配列で用意してください。任意で flags を配列に入れてもよいでしょう。
for() 文のループ処理でポップアップメニュー項目に変換します。


サンプルコードのポップアップメニュー画像
subMenuEnable = 1
subMenuEnable = 1

subMenuEnable = 2


組み込み関数 DevidedSubMenu()

ポップアップメニューに列挙するアイテムとして用意した配列から「分割サブメニュー」を生成する関数コードです。

  • 設定項目用の変数 subMenuHeight で、サブメニュー内の分割行数を指定します。
  • もうひとつの設定変数 subMenuEnable は、分割サブメニュー「1 - 20 件目 ▸」「21 - 40 件目 ▸」の項目を表示 するか/しないか と、メニュー項目「20 件ずつ表示 ▸」の配下に置く(画像:左)/メインのメニュー直下に置く(画像:右) を指定するためのものです。


※設定変数や、ポップアップメニューに列挙するアイテムの配列は、関数から参照できる階層のスコープにおいてください。

  • AddCancelLines() 関数は、「キャンセル」行の表示
  • Pad() 関数は、連番の「ケタ埋め」(右揃え)

のための "おまけコード" です。
※ケタ埋めの空白文字は EN SPACE「 」(U+2002) にしてありますが、PCのコントロールパネル設定で指定した「メニュー」用のフォント種によっては半角数字との幅が合わないことがあります。


サンプルコード

アイテム数が多い/アイテム数が変動するサンプルとして、アクティブなタブのすべての論理行をポップアップメニューに表示する【仮】マクロです。
「キャンセル」行の表示や、行番号の「ケタ埋め」するためのコードも入れているで読みづらいかも知れませんが、 /* ... */ で説明をつけた部分が「分割サブメニュー」用のコードです。

配列の中身や、menu.Track(); 以降の動作コードの部分を、任意のコードに差し替えてお使いください。


「分割サブメニュー」に表示される「キャンセル」のアイテムは Space キーをアクセラレータにしてあるので、Escape キーで多階層のメニューを繰り上がりをせずにポップアップメニューを一発キャンセルできます。
メインメニュー直下に全アイテムを列挙しているときは、Space キーで「キャンセル」アイテムをトグル移動しながらメニュー全体をスクロールできます(Escape キーでポップアップメニューをキャンセル)。


#title = "論理行をポップアップメニューにリストアップ"

// ( function() {
  var start = new Date();	// 所要時間計測(開始)


// ---------- ▼ 設定項目 ▼ ----------

/* ■「分割サブメニュー」を使用するか? */
var subMenuEnable = 1;
  // 0: 使用しない(メインメニュー直下に全アイテムを列挙する)
  // 1: メインメニュー直下には「20 件ずつ表示」と全アイテムの列挙
  //   「20 件ずつ表示」の配下に「1-20 件目」「21-40 件目」の"孫"メニューを置く
  // 2: メインメニュー直下に「1-20 件目」「21-40 件目」のサブメニューを置く

/* ■ 分割する単位 (初期値: 20  >> 20件ずつに分割) */
// ※ subMenuHeight の 2 倍より多いアイテムがあれば分割サブメニューを適用する
var subMenuHeight = 20;


// ---------- ▼ メインのコード ▼ ----------

  // ポップアップメニューに表示する「アイテム」の配列
  var itemArray = new Array();

	// 【仮】 論理行数の連番アイテム(文字列と行番号)を生成する
	var d = editor.ActiveDocument;
	var lineText, lines = d.GetLines( 0 );
	for ( var y = 1; y <= lines; y++ ) {
          // 空白文字を詰め、「&」記号を保守する
	  lineText = d.GetLine( y, 0 )
                      .replace( /\t+|[ ]{4,}|[ ]{2,}/g, " › " )
	              .replace( /&/g, "&&" ).slice( 0, 30 );
	  itemArray.push( [ ":  " + lineText, y ] );
	}

  // 「アイテム」数
  var len = itemArray.length;
  // 「アイテム数」のケタ数(※ケタ埋めに使用する)
  var lenWidth = len.toString().length;

  if ( len > 0 ) {
    // ポップアップメニューの準備
    var menu = CreatePopupMenu();


    /**
     * 「アイテム数」が「分割単位」の 2 倍より多いなら
     * 「分割サブメニュー」を生成する
     */ 
    if ( subMenuEnable && len > subMenuHeight * 2 ) {
      DevidedSubMenu();
    }


    // subMenuEnable = 1 またはアイテム数が「分割単位」の 2 倍以下なら
    // メインメニュー直下に全アイテムを列挙する
    if ( subMenuEnable < 2 || len <= subMenuHeight * 2 ) {
      for ( var i = 0; i < len; i++ ) {
        // 10 件ごとにセパレータ、20* 件ごとに「キャンセル」行を追加する
        AddCancelLines( menu, i, subMenuHeight );

        // 配列の「アイテム」をメインメニュー直下に追加する
        menu.Add( Pad( itemArray[i][1], 2 )
                + itemArray[i][0]
                , itemArray[i][1] );
      }
      // 最下行に「キャンセル」をピン止めする(Space キーでスクロール可)
      menu.Add( "", 0, meMenuSeparator );
      menu.Add( Pad() + "キャンセル\t& ", 0 );
    }


    // ステータスバーにメニューの件数と処理時間を表示する
    var elapsedSec = ( ( new Date() - start ) / 1000 ).toFixed( 3 );
    Status = " メニューのアイテム: " + len + " 件 "
           + "  [ " + elapsedSec + " 秒 ]";

    // ポップアップメニューを表示する
    var yy = menu.Track( mePosMouse );

	  	// 【仮】 メニューの連番の論理行にジャンプする
	  	if ( yy > 0 ) {
	  	  d.selection.SetActivePoint( mePosLogical, 1, yy );
	  	}

  }	// if( len > 0 ) 閉じ


  // ---------- ▼ 関数 ▼ ----------
  // 関数は呼び出し元のスコープに配置する
  // ※ 呼び出し元のスコープが閉じていると変数を参照できなくなる

  /**
   * 関数 DevidedSubMenu()
   * サブメニュー「※ 20* 件ずつ表示 ※  ▶」/「1 - 20* 件目  ▶」に
   * 配列の「アイテム」を分割表示する
   * ※「20*」の部分の数値は設定用変数 subMenuHeight で指定
   * 
   * ※呼び出し元のスコープが閉じている場合は
   *  設定変数 subMenuHeight と menu , itemArray を引き渡すこと
   *   e.g. DevidedSubMenu( objPopupMenu, items, height )
   *  len = itemArray.length と lenWith = len.toString().length は
   *  関数のなかで再定義できる
   */
  function DevidedSubMenu() {
    var subMenu = CreatePopupMenu();
    var popupMenu = ( subMenuEnable == 1 ) ? subMenu : menu;
    if ( subMenuEnable == 1 ) {
      // 「※ 20* 件ずつ表示 ※  ▶」をピン止め
      menu.AddPopup( " ※ " + subMenuHeight
                   + " 行ずつ表示(&D) ※"
                   , subMenu );
    }
    // 「キャンセル」をピン止め
    popupMenu.Add( Pad() + "キャンセル", 0 );
    popupMenu.Add( "", 0, meMenuSeparator );

    // 配列のアイテムをポップアップメニューに追加していく
    var smArray = [];	// SubMenu Array
    var smId , _from , _to;
    for ( var i = 0; i < len; i++ ) {
      if ( i % subMenuHeight == 0 ) {
        // 配列にメニュー項目「_from - _to 件目  ▶」を生成する
        smArray.push( CreatePopupMenu() );
        // 「_from - _to 件目」メニューの index
        smId = smArray.length - 1;
        //  _from と _to の値
        _from = smId * subMenuHeight + 1;
        _to = Math.min( smArray.length * subMenuHeight, len );
        // 「_from - _to 件目」メニュー項目
        popupMenu.AddPopup( Pad( _from, 1 ) + " - "
                          + Pad( _to ) + " 件目"
                          , smArray[smId] );
      }

      // 「_from - _to 件目」メニュー配下の 10件 ごとにセパレータと
      // 先頭に「キャンセル」行(Space キーでキャンセル可)
      AddCancelLines( smArray[smId], i, subMenuHeight );

      // 「アイテム」の配列から「_from - _to 件目」メニュー配下に追加する
      // ※ smArray[smId] は CreatePopupMenu オブジェクト
      smArray[smId].Add( Pad( itemArray[i][1], 2 )
                       + itemArray[i][0]
                       , itemArray[i][1] );

      // 「_from - _to 件目」のさいごに「キャセル」行を追加する
      if ( i == len - 1 ) {
        popupMenu.Add( "", 0, meMenuSeparator );
        // (Space キーでキャンセル可)
        popupMenu.Add( Pad() + "キャンセル\t& ", 0 );
      }
    }
  }

  /**
   * 関数 AddCancelLines( objPopupMenu, id, distance )
   * 10 件ごとにセパレータと
   * 20* 件ごとに「キャンセル」行を追加する
   * ※Space キーでキャンセル可(またはスクロール)
   * 
   * 第1引数は ポップアップメニューオブジェクト
   * 第2引数は 呼び出し元の for() 文の「 i 」
   * 第3引数は 「キャンセル」行を表示する間隔*
   * (省略した場合は設定項目の変数 subMenuHeight)
   */
  function AddCancelLines( objPopupMenu, id, distance ) {
    var distance = distance || subMenuHeight || 30;
    // 10 件ごとにセパレータを追加 && id % distance != 0
    if ( id % 10 == 0 ) {
      objPopupMenu.Add( "", 0, meMenuSeparator );
    }
    // 30* 件(distance)ごとに「キャンセル」行を追加
    if ( id % distance == 0 ) {
      objPopupMenu.Add( Pad() + "キャンセル\t& ", 0 );
      objPopupMenu.Add( "", 0, meMenuSeparator );
    }
  }

  /**
   * 関数 Pad( num, amp )
   * EN SPACE「 」でケタ埋めして右揃えにする
   * ※ケタ数にはグローバルスコープの変数 lenWidth を使用する
   * 
   * 第1引数は ケタ埋め対象の数字
   * 第2引数は アクセラレータ用の「&」の指定
   * (1 なら先頭の数字、2 なら末尾の数字をアクセラレータにする)
   */
  function Pad( num, amp ) {
    num = num || "";
    var pad = ( amp == 1 )
              ? ( "          &" + num )
              : ( amp == 2 )
                ? ( "          " + num ).replace( /(\d)$/, "&$1" )
                : ( "          " + num );
    amp = amp ? "&" : "";
    return pad.slice( - lenWidth - amp.length );
  }

// }() );
スポンサーリンク