メニューについて

概要

  • この記事ではスクラッチのメニューについて説明します。
  • メニューにはプルダウンメニューやコンテキストメニューがあります。
  • いずれも CustomMenu オブジェクトにメニュー項目を追加し、 #invokeOn: メッセージ等を送って表示します。

プルダウンメニュー

スクラッチのプルダウンメニューは、ScratchFrameMorph の#createMenuPanel メソッドで作られ、menuPanel インスタンス変数に格納されます。
また、メニュー項目に関するメソッドは、同じクラスの menu/button access メソッドカテゴリに集約されています。
#createMenuPanel メソッドを見てみるとmenuSpecs という配列に各メニューの情報が設定されていることがわかります。

menuSpecs := #(
  "name selector"
  (File fileMenu:)
  (Edit editMenu:)
  (Help helpMenu:)
).

この配列の要素は、メニューとして表示される文字列と選択された時に実行されるメソッドによる配列で、後で ScratchMenuTitleMorph のオブジェクトを生成する際に使われます。
メニューがクリックされると、配列で指定したScratchFrameMorph クラス内のメソッドが実行されます。このとき、引き数として(クリックされたメニューの)ScratchMenuTitleMorph オブジェクトが与えられます。

fileMenu: メソッド

Fileメニューがクリックされた場合は、Fileメニューを表すScratchMenuTitleMorph オブジェクトを引き数として #fileMenu: メッセージが呼ばれます。
実際の #fileMenu: メソッドは ScratchFrameMorph クラスで定義されています。冒頭部分は以下の通りです。

fileMenu: aMenuTitleMorph
    | menu |
    menu := CustomMenu new.
    menu add: 'New' action: #newScratchProject.
    menu add: 'Open' action: #openScratchProject.
    menu add: 'Save' action: #saveScratchProjectNoDialog.
    menu add: 'Save As' action: #saveScratchProject.

#fileMenu: メソッドでは、まず CustomMenu オブジェクトが生成され、 #add:action メッセージにより、さまざまなメニュー項目が追加されていきます。#add:action: はメニューに表示する項目名と、項目が選ばれた時に実行するメッセージを登録します。実行するメッセージのレシーバは特に指定しない限り self となります。

    menu addLine.
    menu add: 'Quit' action: #quitScratch.
    menu localize.
    #(2 4) do: [:n |
        menu labels at: n put:
        ((menu labels at: n) copyFrom: 1 to: (menu labels at: n) size - 1), ScratchTranslator ellipsesSuffix].
    menu invokeOn: self at: aMenuTitleMorph bottomLeft + (0@10).

上は #fileMenu: メソッドの後半部分です。Quit メニュー項目を追加した後の #localize メッセージで、言語設定に従ってメニューをローカライズします。
その後の3行ではメニュー項目の2番目(Open)と4番目(Save As)に、ScratchTranslator ellipsesSuffix (・・・の文字)を加えています。
最後の #invokeOn:at: で、メニューを指定した位置に表示させています。

開発者メニュー

#fileMenu: メソッドの中ほどには以下のようなコードがあります。

    Sensor shiftPressed ifTrue: [ "developer menu"
        menu addLine.
        menu add: 'Write Project Summary' action: #writeSummaryFile.
        menu add: 'Write Multiple Project Summaries' action: #writeMultipleSummaries.

Sensor shiftPressed は、シフトキーが押されているかどうか調べるメッセージ式です。この結果が真、つまりシフトキーが押されている間だけいくつかのメニュー項目が追加されます。このようなコードは #editMenu: メソッドの中にも見ることができます。

コンテキストメニュー

ブロックやスクリプトエディタ、ステージ等で右クリックすると、コンテキストメニューが表示されます。これらのメニューは、それぞれのモーフが管理していますが、どれも #rightButtonMenu というメソッドで実装されています。
ワークスペースを開いて、 rightButtonMenu と入力したら、この単語を全て選択して(ワークスペースの)コンテキストメニューを表示させます。一番下にある more… という項目を選び、更に implementers of it という項目を選ぶと、rightButtonMenu を実装している全てのメソッドが表示されます。

各メソッドを見れば、様々な場面におけるコンテキストメニューの作り方がわかります。基本的な考え方はプルダウンメニューと同じなので説明は省略します。