Curl Sonntag チュートリアル
ここでは簡単なサンプルプログラムをもとに Curl Sonntag の基本的な使い方を説明します。サンプルプログラムは以下のリンクからダウンロードできます。(サンプルには pcurl 版の Curl Sonntag 0.6 が含まれています)
サンプルプログラム
サンプルの実行
ダウンロードした zip ファイルを特権のある任意のフォルダに解凍します。中に含まれる start.dcurl を実行(ダブルクリック)すると以下のようなログイン画面(を模したウィンドウ)が起動します。
ユーザIDに「sonntag」、パスワードに「curl」と入力してログインボタンを押すと画面遷移します。
以下からこのサンプルプログラムのソースコードを説明していきます。
はじめに
Sonntag では画面毎に以下の3種類のクラスを作成します。
- スクリーングラフィック
- スクリーン
- スクリーンコマンド
スクリーングラフィックは、静的な画面レイアウトを表すクラスです。アプリケーションロジックは記述しません。アプリケーションロジックはスクリーンとスクリーンコマンドに持たせます。スクリーンはスクリーングラフィックと1対1で定義するクラスです。このクラスには、スクリーングラフィック上のコントロールにアクセス(値の取得、設定など)する処理や、動的に変わるレイアウトの処理などを記述します。画面上のボタンが押された場合の処理など、アプリケーションにおける主要なロジックについてはそれぞれをスクリーンコマンドとして定義します。
フレームワークパッケージのインポート
以下はサンプルプログラムに含まれる screens/load.scurl の内容です。SONNTAG.EX1.SCREENS というパッケージを定義しています。このパッケージ中に上述した3種類のクラスが含まれています。Sonntag を利用するために COM.CURLAP.SONNTAG.STANDARD パッケージをインポートしています。
{curl 6.0 package} {curl-file-attributes character-encoding = “shift-jis”} {package SONNTAG.EX1.SCREENS, {compiler-directives careful? = true} }
{import * from COM.CURLAP.SONNTAG.STANDARD}
{include ・・・(略)}
|
スクリーングラフィックの定義
画面の作成する場合は、最初にスクリーングラフィックを定義します。スクリーングラフィックは一般的な Curl プログラムと同様、以下のいずれかの方法で定義できます。(Sonntag 固有のスーパークラスなどを継承する必要はありません)
- Frame や Dialog などを継承して Curl のグラフィッククラスとして定義する
- VLE を使ってレイアウトを作成する
screens/login/graphic.scurl ファイルにログイン画面のスクリーングラフィックが定義されています。Ex1LoginGraphic という名前の Frame のサブクラスです。
{define-class public Ex1LoginGraphic {inherits Frame} {constructor public {default} ・・・(略) } }
|
このクラスのコンストラクタでは、ユーザIDやパスワードの入力フィールドおよびログインボタン、クリアボタンを生成・配置しています。
{define-class public Ex1LoginGraphic {inherits Frame}
{constructor public {default} def vbox = {spaced-vbox margin = 5pt, {Table columns = 2, “ユーザID”, {TextField}, “パスワード”, {PasswordField} }, {spaced-hbox {CommandButton width = 3cm, label = “ログイン” }, {CommandButton width = 3cm, label = “クリア” } } } {self.add vbox} } }
|
このように、なるべくスクリーングラフィックはレイアウトのコードのみとなるように作成します。(上記のコードは、後ほど説明するコードを省略してあるため screens/login/graphic.scurl ファイルの内容とは若干異なります)
スクリーンの定義
次は screens/login/screen.scurl に定義されたスクリーンクラスです。Sonntag が提供する Screen-of というクラスを継承しています。Screen-of はパラメータ化クラスで、引数にスクリーングラフィッククラス(この例では Ex1LoginGraphic)を指定しています。
{define-class public Ex1LoginScreen {inherits {Screen-of Ex1LoginGraphic}}
・・・(略) }
|
補足: スクリーングラフィックを VLE で作成した場合は Screen-of の代わりに VScreen-of というスーパークラスを使用します。VScreen-of の場合も同様に、パラメータで VLE のレイアウトクラスを指定します。Sonntag で VLE を利用する方法については、今後別の記事で解説する予定です。
スクリーンからスクリーングラフィックへのアクセス
スクリーンはスクリーングラフィックに対する論理的なインターフェースを提供するように作成します。ログイン画面の例では、スクリーングラフィック上のユーザIDとパスワードのフィールドに対する入力値を取得するためのメソッド(Ex1LoginScreen.get-inputs メソッド)を定義しています。
このメソッドを作成するためにまず、Ex1LoginGraphic クラス上の TextField と PasswordField に name を設定しています。
{define-class public Ex1LoginGraphic {inherits Frame}
{constructor public {default} def vbox = {spaced-vbox margin = 5pt, {Table columns = 2, “ユーザID”, {TextField name = “userid-tf”}, “パスワード”, {PasswordField name = “password-pf”} }, ・・・(略) } }
|
スクリーンからはこの名前を使ってコントロールにアクセスできます。Ex1LoginScreen クラスのコンストラクタで、スーパークラスで定義された find-graphic-by-name というメソッドを使ってフィールドにユーザIDとパスワードのフィールドをセットしています。
{define-class public Ex1LoginScreen {inherits {Screen-of Ex1LoginGraphic}}
field userid-tf:TextField field password-pf:PasswordField
{constructor public {default} set self.userid-tf = {self.find-graphic-by-name “userid-tf” } asa TextField set self.password-pf = {self.find-graphic-by-name “password-pf” } asa PasswordField } ・・・(略) }
|
このフィールドを使用して Ex1LoginScreen.get-inputs メソッドは以下のように定義されます。
{method {get-inputs}:(userid:String, password:String) {return self.userid-tf.value, self.password-pf.value } }
|
スクリーンコマンドの定義
3種類目のスクリーンコマンドは screens/login/commands.scurl ファイルに定義されています。このファイルには、ログイン画面のログインボタンとクリアボタンに対応して、2つのスクリーンコマンドが含まれます。ここでは、先ほど説明した Ex1LoginScreen.get-inputs メソッドを使用するログインボタンのスクリーンコマンドについて見ていきます。
スクリーンコマンドは define-screen-command という Sonntag のマクロを使用して定義します。ログインボタンの処理に対応するスクリーンコマンドの定義は以下のようになっています。
||| Ex1LoginScreen の “login” スクリーンコマンドの定義 {define-screen-command login of screen:Ex1LoginScreen do ・・・(コマンドの処理) }
|
このマクロの構文は {define-screen-command コマンド名 of [変数名:]スクリーンクラス do ・・・} です。(詳細は API リファレンスを参照してください) 上記の例は、「login」という名前の Ex1LoginScreen に関連付けされたスクリーンコマンドの定義になります。do キーワード以降には任意の Curl ステートメントを記述できます。このステートメント中では、指定した変数名(上記の例では「screen」)でスクリーンを参照することができます。「login」コマンドでは以下の赤字部分でスクリーンのメソッドを呼び出しています。
{define-screen-command login of screen:Ex1LoginScreen do || Ex1LoginScreen.get-inputsメソッドを呼出して || ユーザIDとパスワードの入力値を取得する def (userid, password) = {screen.get-inputs} || ユーザID:sonntag、パスワード:curlでログイン {if userid == “sonntag” and password == “curl” then || 次画面に遷移する {screen.replace-with Ex1NextScreen} else {popup-message “ユーザID「sonntag」、パスワード「curl」を入力してください。” } } }
|
2番目の赤字部分で呼び出している replace-with というメソッドはスクリーンのスーパークラスで定義されているものです。このメソッドはスクリーンを引数にとり(正確には ScreenFeed を引数にとる。API リファレンス参照)、その画面に表示を切り替えます。
スクリーングラフィックからスクリーンコマンドへのバインド
以上で説明したスクリーンコマンドは、スクリーングラフィック上の CommandButton に以下のような記述を加えることによってボタン押下時に実行されるようになります。
{define-class public Ex1LoginGraphic {inherits Frame} {constructor public {default} ・・・(略) {spaced-hbox {CommandButton width = 3cm, label = “ログイン”, {bind-screen-command “login”} }, {CommandButton width = 3cm, label = “クリア”, {bind-screen-command “clear”} } } ・・・(略) } }
|
bind-screen-command というマクロの呼び出しを CommandButton のコンストラクタ引数に含めます。マクロの引数で、スクリーンコマンドの名前を文字列で指定します。
スクリーンの表示(スクリーンスロット)
最後に、Sonntag を利用して作成した画面を表示する方法について説明します。Sonntag は画面を表示するためのスクリーンスロットというオブジェクトを提供しています。start.dcurl 内では、以下のように独立型アプレット用の View を作成している箇所で ScreenSlot というクラスを使用しています。
{View {Dialog {ScreenSlot Ex1LoginScreen} }, ・・・(略), {on WindowClose do {exit} } }
|
ScreenSlot はスクリーンを表示するために使用できる BaseFrame です。上記では、コンストラクタ引数で Ex1LoginScreen を指定しており、これによってログイン画面が表示されます。(上述の replace-with メソッドと同様 ScreenSlot も ScreenFeed を受け取ります。API リファレンスを参照してください)