「逆引きリファレンス」カテゴリーアーカイブ

Curl と Webシステム間の認証連携(SSO)

CurlアプリとWebアプリ間で、SSOを実現するために、認証クッキーを共有する方法を採用する場合、以下のような連携方法があります。

先にWebシステム認証済みの状態で、Curlアプリへログインする場合
連携方法:

デタッチトアプレットの起動ファイル(.dcurl)をサーバーサイドで動的に作成し、通信が発生する可能性がある処理の前処理として、{set-insecure-http-cookie 「サーバーサイドで作成した認証クッキー情報」}, {set-secure-http-cookie 「サーバーサイドで作成した認証クッキー情報」} 等を利用して、アプレットに必要な認証クッキーをアプレットコードに埋め込み、Curlアプリを実行する時にサーバーと通信する前にクッキー情報が設定され、それ以降サーバーとの通信が該当クッキーが利用されるようになり、SSO認証が実現可能になります。

Curlアプリでログイン後、認証クッキーをWebシステムに渡してSSOを実現する場合
連携方法1:

CurlアプレットからWebシステムのリンクを開くときに、認証クッキーをGETパラメータでWebシステム側に渡すして、Webシステム側のJavascriptコードでクッキーとして設定し、それ以降Webシステムサーバー側へアクセスできるようになります。

連携方法2:

クリップボードを活用すれば、CurlアプリとWebシステム間で相互にデータの引き渡しができるため、認証クッキーの共有もお互いに可能になります。
この方法の詳細はこちらのページでご確認ください

CurlORB 0.9 リリースノート

orb.png

Curl ORB for javaとは

Curl ORB for javaとは、CurlとJavaをシームレスに結合し、高速なデータ通信を実現するためのツールです。Curl ORBを利用することで、CurlアプリケーションからPOJO(Plain Old Java Object)で作成されたjavaオブジェクトのメソッドをコールし、戻り値をCurlアプリケーションで受け取ることができます。また、サーバサイドのjavaクラスからCurlのソースコードを自動生成することも可能です。このツールを用いれば、Curlとサーバサイドjavaとの連携を利用したシステム開発が容易になります。Curl ORB for javaはオープンソースプロジェクト(Apache License2.0)として公開されています。

orb.jpg

(上図説明)
コード自動生成ツールにてJavaのクラスからCurlコードを自動生成します。(CORBAなどのIDLは不要で、その代わりにCurlのスタブクラスを生成。)クライアントサイドでは、自動生成されたCurlクラス(サービスクラス)を実行しますと、自動的にサーバサイドのサービスクラスをコールし、処理を実施して結果をクライアントへ返します。 またこの際、Spring frameworkやSeasar2などのDIコンテナで管理されているJavaオブジェクトに対してもコールすることが可能となっています。

CurlORB for javaバージョン0.9 新機能

  • モバイル開発環境「Caede」のサポート (参考ページ)
  • 【注意点】CurlRTE 6.0, 7.0は未サポート(バージョン0.8をご利用ください)
  • その他、バグフィックス …など

CurlORB for javaバージョン0.8 新機能

  • CurlRTE8.0対応(6.0, 7.0も対応)
  • Valueクラスのサポート
  • Decimal型のサポート(Curl8.0以上)
  • クライアントキャッシュ機能
  • 【注意点】 パッケージ名の変更(COM.CURLAP.ORB → COM.CURL.ORB)
  • その他、バグフィックス …など

CurlORB for javaバージョン0.7 新機能

  • CurlRTE7.0対応(6.0も対応)
  • サーバプッシュ・インターオペラビリティ(Cometフレームワーク Atmosphere などとの連携)
  • チューニングパラメータ(@DoNotShareアノテーション) (参考ページ
  • NotNull機能(@NotNull, @DefaultNotNull, @Nullableアノテーション) (参考ページ)
  • サロゲートペア対応
  • SerializableなRecordDataサポート(参考ページ
  • その他、バグフィックス …など

CurlORB for javaバージョン0.6 新機能

  • 追加されたデータ型として、java.math.BigInteger, java.math.BigDecimal, java.sql.Date, java.sql.Timestamp, java.sql.Time, java.sql.Blob, java.sql.Clobを対応 (参考ページ
  • Apache Jmeterなど負荷試験用のORBクライアント (参考ページ
  • 新しいセキュリティ設定 (参考ページ
  • データ通信の圧縮・解凍参考ページ
  • クライアント・インターセプター(AOPのような) (参考ページ
  • コード生成ツールのユーザビリティ向上(クラスの一覧検索、デフォルト値の設定など) (参考ページ
  • サービスクラス機能追加(引数にリモートのクラスを指定可能、セッションKILLなど) (参考ページ)
  • サービスオブジェクトのコンテナ管理 (参照ページ
  • その他、各種名称変更及びバグフィックス、パフォーマンス向上 …など

CurlORB for javaバージョン0.5までの機能

  • CurlからPOJOで作成されたサービスクラスをコール(ステートフル、ステートレス)
  • 高速なデータ通信(バイナリデータを使って通信します。)
  • コード生成ツール
  • 各種データ型(プリミティブ型、String、配列、List、Map、ユーザ定義クラス、RecordSetなど)を対応
  • 非同期同期通信
  • 例外ハンドリング(サーバ例外をクライアントでCatchできます。) …など

モバイル開発環境「Caede」のサポートについて

バージョン0.9からモバイル開発環境「Caede」でもORBの機能を利用できるようになりました。

以下にCaedeでの利用方法、サポートしているデータ型、制限事項を記載します。

なおCaede バージョン3.0.0で利用する場合、別途注意事項があります。こちらのページを参照してください。

Caedeでの利用方法

  • SorceForgeからcurl-orb-V0.9.zipをダウンロードします。
  • Eclipse開発環境へCurl ORBをセットアップし、以下の手順でCaedeとJavaを連携するアプリケーションを構築します。以下の手順の詳細についてはCurl ORB for Javaのクイックスタートを参照してください。
    1. サーバサイドのサービスクラス(POJO)作成
    2. サーバサイドのサービスクラス(POJO)からCurlコードを自動生成
  • 新しいCaedeプロジェクトを作成します。Caedeプロジェクトの作成の詳細はデベロッパーセンターのCaedeのドキュメントを参照してください。
  • CaedeプロジェクトにCurl ORBクライアントを取り込むため、ダウンロードしたCurl ORBディレクトリのcurl/COM.CURL.ORB-V0.9/8.0/manifest.mcurlをデリゲート先として選択します。
  • Caedeプロジェクトのmanifest.mcurlにダウンロードしたCurl ORBディレクトリのcurl/COM.CURL.ORB.CAEDE-V0.9/8.0/COM.CURL.ORB.CAEDE/load.pcurlを追加します。
    (以下はC:/curl-orb-V0.9にダウンロードした場合の例です)
    {component package COM.CURL.ORB.CAEDE,     location = "C:/curl-orb-V0.9/curl/COM.CURL.ORB.CAEDE-V0.9/8.0/COM.CURL.ORB.CAEDE/load.pcurl" }
  • Caedeプロジェクトにクライアントコードを記述します。
  • あとは通常のCaedeプロジェクトと同じようにCaedeアプリケーションに変換します。

サポートしているデータ型

Caede ORBのデータ通信には以下のデータ型を利用することができます。

Curl Java
int int
int8 byte
int16 short
int32 int
int64 long
float float
double double
bool boolean
char char
String java.lang.String
FastArray-of データ型 配列
Array (Array-of any) List, ArrayList
HashTable (HashTable-of any) Map, HashMap
COM.CURL.ORB.TYPE.Date java.util.Date
COM.CURL.ORB.TYPE.CDate java.sql.Date
COM.CURL.ORB.TYPE.CTime java.sql.Time
COM.CURL.ORB.TYPE.CTimestamp java.sql.Timestamp
COM.CURL.ORB.TYPE.BigInteger java.math.BigInteger
COM.CURL.ORB.TYPE.BigDecimal java.math.BigDecimal
ユーザ定義型(フィールドは上記のものに限る) ユーザ定義型(フィールドは上記のものに限る)

CaedeORBでは以下の変換はサポートしていません。

Curl Java
DateTime java.util.Date
ByteArray com.curl.io.serialize.types.ByteArray
COM.CURL.ORB.TYPE.SerializableRecordSet com.curl.orb.type.SerializableRecordSet
COM.CURL.ORB.TYPE.SerializableRecordField com.curl.orb.type.SerializableRecordField
COM.CURL.ORB.TYPE.SerializableRecordData com.curl.orb.type.SerializableRecordData
COM.CURL.ORB.TYPE.Blob java.sql.Blob
COM.CURL.ORB.TYPE.Clob java.sql.Clob

またValueクラス、Decimal型もサポートしていません。

利用できない機能

Caede側の制限により、以下の機能は現在利用できません。

  • get-jsessionid-in-cookies/clear-jsessionid-in-cookies
  • Exceptionバインディング(bind-exception/bind-exceptions/get-exception/get-exceptions/remove-exception/clear-exceptions)
  • クライアントキャッシュ
  • クライアント・インターセプター
  • データ通信の圧縮・解凍
  • ヘッダー情報の送信
  • サービスクラスをクライアントでコンテナ管理する機能
  • パフォーマンス改善アノテーション(@DoNotShare)
  • NotNull機能(@NotNull, @DefaultNotNull, @Nullableアノテーション)
  • transient属性のフィールドを含むユーザ定義型クラス

Caede バージョン3.0.0でCurl ORB for Java 0.9を利用する場合の注意事項

Caede バージョン3.0.0でCurl ORB for Java 0.9を利用する場合は、最初に1回だけ事前準備の作業 が必要です。
こちらに記載された手順を実行する前に以下の作業を行ってください。

  • Caede SDKをインストールしたフォルダの下にある以下のファイルを退避した後、ダウンロードしたCurl ORBディレクトリに含まれているCOM.CURL.CAEDE.JSON-ORB.jsをコピーしてください。

    libcommonjscaede-libCOM.CURL.CAEDE.JSON-ORB.js


  • すでにCOM.CURL.CAEDEライブラリがインストール済みのライブラリに含まれている場合は、再度ライブラリのインストールを行ってください。

※元のファイルは必ず退避して保存してください。元の環境に戻す場合は退避したファイルを元に戻してください。

APIの説明・サンプル(assetモジュールアップデート機能)

Caed3.0.0より、assetモジュールアップデートの機能が追加されました。

assetモジュールアップデート機能の利用方法

assetモジュールアップデート機能はアプリケーションのインストール・アンインストールを行わずにアプリケーションを
アップデートする機能です。

開発者(あるいはエンドユーザー)が指定したURLに新しいassetモジュールを配置しておくと、アプリケーションが
バックグラウンドで自動的にアップデートを行い、アプリの次回起動時に新しいassetモジュールがロードされます。

利用手順

アプリケーションの初版を作成する時の作業

ソースコードに asset モジュールを更新するためのアップデートサーバーの格納URLを登録する処理を追加してください。

register-update-module-directoryプロシージャを呼び出して、アップデートするassetモジュールを配置する
サーバーのディレクトリのURLを登録します。

例) || Register {self.register-bt.add-event-handler     {on Action do         {register-update-module-directory             {url "http://www.xxxxx.com/Update/Caede/AppDemo"}         }     } } 

新しいバージョンを作成する時の作業

Eclipse上でassetモジュールを作成した後、アップデートサーバーにCDLファイル、assetモジュール、
アップデートモジュール情報ファイルを配置します。

1. Eclipse上でソースコードを修正した後、[Caedeアプリケーションに変換]で新しいモジュールを作成します。

2. 以下のディレクトリをzipファイルにしてください。

– Androidアプリを作成する場合

Android/assets/android-native-web

– iOSアプリを作成する場合

iOS/assets/ios-native-web

3. アップデートサーバー用CDL(caede-licese-1.dat)ファイルを用意します。
アップデートサーバー用CDLファイルの発行については弊社にお問い合わせください。

4. 以下のファイルをアプリケーションからアクセスできるサーバーに配置します。

– アップデートサーバー用CDL(caede-licese-1.dat)ファイル
CDLファイルはサーバーのルートディレクトリに配置してください。

– 2.で作成したzipファイル(android-native-web.zipまたはios-native-web.zip)
「アプリケーションの初版を作成する時の作業」の例の場合は以下の場所に配置します。

android-native-web.zip) http://www.xxxxx.com/Update/Caede/AppDemo/android-native-web.zip  ios-native-web.zip) http://www.xxxxx.com/Update/Caede/AppDemo/ios-native-web.zip 

– アップデートモジュール情報ファイル(update.xml)
update.xmlにはアップデートモジュールのバージョン情報を記載します。
zipファイルと同じディレクトリに配置してください。
update.xmlのフォーマットは以下の通りです。

< ?xml version="1.0" encoding="utf-8"? >   <caedeUpdate>   <rev>1</rev> </caedeUpdate> 

revは正の数値であれば何でも構いません(“20140929″のような日付でも可)。
新しいバージョンをリリースした場合は必ずインクリメントしなければなりません。

この後、端末上でアプリを起動するとバックグラウンドで自動的にアップデートが行われ、
アプリの次回起動時にサーバーに配置したassetモジュールがロードされます。

注意事項

assetモジュールのアップデートはアプリケーションの起動時にバックグラウンドで
行われるため、すぐには反映されません。
update.xmlのrevの値は必ず正の数値を指定してください。不正な値が入っていた
場合アップデートは行われません。
Caede SDKのバージョンアップを行った場合は、アプリケーション自体を再インストール
する必要があります。
これはSDKのバージョンアップによりassetモジュールのAPIとアプリケーション本体
のAPIの互換性がなくなるためです。SDKバージョンの異なるassetモジュールが配置
されていた場合アップデートは失敗します。
なおアップデートが失敗するのはマイナーバージョン以上のバージョンアップの時
(3.0.0から3.1.0など)です。
マイナーバージョン未満の場合(3.0.0から3.0.1など)はAPIの互換性があるため失敗
しません。

APIの説明・サンプル(ローカルストレージの暗号化)

ローカルストレージの暗号化

Caede ver.3.0よりローカルストレージクラス(KvsStorage, RdbStorage)では、256ビットAES暗号による暗号化をサポートしました。

暗号化機能を有効にするには、上記のストレージクラスの使用前に Application クラスの
enable-secure-storage メソッドで暗号化/復号化に使用するキーを生成するためのパスワードを指定します。

使用例

    def app = {get-the-application}     || パスワードを設定します     {app.enable-secure-storage "password"}          || Storage の利用方法は今まで通りです     def storage = {StorageConnection.open                       "testdb",                       type = StorageType.rdb                   }.storage asa RdbStorage          {storage.execute-update         "CREATE TABLE IF NOT EXISTS rdbtest (ID INTEGER, Name TEXT, Value INTEGER);"     } 

なお、暗号化機能を使用しない場合にはenable-secure-storage を呼び出さないか、パスワードに
空文字列(“”)を指定して呼び出してください。

注意事項

  1. 暗号化機能は、そのCaedeアプリケーション全体で有効/無効のどちらかになります。
    一部のみ暗号化することはできません。
  2. 暗号化を有効にした場合、そのパスワードは途中で変更できません。
    Storageクラスのdestroy-by-nameプロシージャ等でストレージを削除してから、別のパスワードでストレージを再生成する必要があります。
  3. 暗号化を有効にすると、無効にしている状態よりもストレージアクセスに時間が掛かります。

APIの説明・サンプル(プッシュ通知API)

プッシュ通知API

Caede3.0より、プッシュ通知関連のAPIが対応されました。

Caedeでは、APNs(iOS)またはGCM(Android)を利用したプッシュ通知に関する機能(デバイスからサービスへの登録・登録解除、また、通知受信時のイベント登録)を提供します。

例えばサーバー側でデバイストークン(デバイスを一意に識別するID)を管理し、各サービスへプッシュ通知をリクエストすることで、デバイス側でプッシュ通知を受信することができます。

[ プッシュ通知受信時にダイアログを表示]

notification01.png
本機能は以下のサービスを利用することを前提としています。
プッシュ通知サービスを利用するためには、各サービスを利用するための準備が必要です。各サービスのリファレンスを参照してください。

ソースコードイメージ

            || GCMの設定:Google consoleで取得したProjectID (SENDER_ID)を設定             def gcm-config = {GCMNotificationConfig "xxxxxxxxxxx"}             || APNsの設定:APNsNotificationTypeを使い、通知タイプを設定             def notifi-types = {{Set-of APNsNotificationType}                                    APNsNotificationType.alert,                                    APNsNotificationType.badge                                }              def apns-config = {APNsNotificationConfig                                   notifi-types                               }             def notification-configs = {{Set-of NotificationConfig}                                            gcm-config,                                            apns-config                                        }             || プロバイダに通知登録             {register-for-notification                 notification-configs,                 {on nr:NotificationRegistered do                     || 通知登録時の処理                     {if-non-null ex = nr.exception then                         {output ex.message}                      else                         set self.registerd-token = nr.token                         || プロバイダーサーバーにトークンをアップロード                     }                 },                 {on rn:NotificationReceived do                     || 通知受信時の処理                     {popup-message rn.alert}                 }             } 

詳細はCaede API リファレンスを確認してください。

APIの説明・サンプル(アニメーションダイアログ)

Caede3.0.0で追加されたアニメーションダイアログのサンプルをご紹介します。

アニメーションダイアログ

Caede3.0で横から、上から、下からスライドして表示されるアニメーションダイアログが追加されました。
モバイルアプリでよく見かけるボタンを押すと左からにゅうっとスライドして出てくるメニューのようなダイアログです。
表示させる場所も上から下から右から左からと任意の場所に表示させることが可能です。

以下のようにして使用できます。
代表的なオプションを指定してあります。

let sid:TransitionDialog =                     {TransitionDialog                         geometry =                             {DialogGeometrySpec                                 ||このダイアログをどこに表示するか指定します                                 ||以下の場合、左から表示されます                                 align-left? = true,                                 align-right? = false,                                 align-top? = false,                                 align-bottom? = false                             },                         ||表示時のアニメーションを指定します                         show-transition =                             {StandardTransitionAnimationSpec                                 ||アニメーションの表示時間                                 transition-duration = 0.5s,                                 ||回転させながら表示させます                                 rotation = 0deg                             },                         ||ダイアログの透明度                         opacity = 100%,                         ||ダイアログが表示されているときの背景の透明度                         cover-opacity = 0%,                         ||ダイアログが表示されているときの背景色                         cover-color = "black",                         ||ダイアログを表示する親オブジェクト                         ||このオブジェクト上に表示されます                         parent-object = ui-holder                     } 

以下のようにしてアニメーションダイアログに表示するオブジェクトを追加します。

{sid.add         {ScrollBox             hscroll? = false,             background = "#e9eaed",             {VBox                  width = 200px,                 margin = 10px,                  spacing = 5px,                 background = "#e9eaed",                                  {Fill height = 5px},                                  {CommandButton                     style = "label-only",                     height = 40px,                     width = {make-elastic},                     label = {TextFlowBox                                      color = "#333333",                                     "ゲーム"                               },                     {on Action do                         {sid.close}                                              }                 },                 {CommandButton                     style = "label-only",                     height = 40px,                     width = {make-elastic},                     label = {TextFlowBox                                      color = "#333333",                                     "音楽"                               },                     {on Action do                         {sid.close}                                              }                 }             }         } } 

animation-dialog01.png

このように左側にダイアログを表示することができます。

指定したアニメーションを行いながら”にゅう”っと表示されます。
また、今回ご紹介したオプションだけでなく多くのオプションも用意されていますので
お好みのアニメーションをさせながら表示することが可能です。

フレームワークの使い方(Caede SDKのみ利用)

Caedeアプリケーションを開発するには、Caedeフレームワークを利用します。ここでは、フレームワークの利用方法をご説明します。

事前に環境のセットアップはCaedeのページよりGettingStarted を参照して実施してください。

当ページでは、Caede Eclipse plug-inを利用せずに開発するための手順を示しています。

Caede Eclipse plug-in利用時のフレームワークの使い方は、こちらをご覧下さい。

フレームワーク作成の手順は以下の通りです。

① 新しいプロジェクトを作成します。(Curl)

② COM.CURL.CAEDE.FRAMEWORKをデリゲートします。

③ manifest.mcurlを編集します。

④ start.curlを編集します。

⑤ 画面クラス、画面コントロールクラスを作成します。

⑥ Curlソースコードをデプロイします。(Caedeアプリケーションに変換)

⑦ 各ターゲットプラットフォームで実行するためのパッケージング化を行います。

①新しいプロジェクトを作成します。

Eclipseのファイルメニューから New -> Curlプロジェクトを選択します。

new_curlpj.jpg

②COM.CURL.CAEDEをデリゲートします。

Caedeフレームワークを利用できるように、COM.CURL.CAEDEを読み込みます。

1.Curlプロジェクトを右クリックし、「Properties」を選択。
2.Properties for XXX(Curlプロジェクト)ダイアログにて「Curl -> ライブラリ」を選択。
3.「外部ライブラリを追加」ボタンをクリックし、ダウンロードしたCaedeディレクトリ配下のmanifest.mcurlを選択。
例 : c:/caede-2.0.0/COM.CURL.CAEDE.2.0.0/manifest.mcurl
4.「OK」ボタンをクリックします。

caede-fw-delegate.png

③manifest.mcurlを編集します。

モバイル環境で稼動させるために、manifest.mcurl内の start.curl部分に以下のコードを記述します。

caede-client-applet? = true

caede-manifest.png

④start.curlを編集します。

start.curlにもmanifest.mcurlと同じコードを記述します。

caede-client-applet? = true

また、startupプロシージャに最初に起動するトップ画面のScreenクラスを記述します。

{startup 画面コントロールクラス名}

caede-start-curl.png

以下で作成する起動画面のクラス名はGamenAScreenなので

{startup GamenAScreen}

となります。

⑤ Graphicクラス、Screenクラスを作成します。

まず、Caedeフレームワークでは、GraphicクラスとScreenクラスを各画面ごとに作成します。GraphicクラスはUI部分で、Screenクラスはロジック部分となります。

ここでは画面Aとそこからの遷移先画面BのGraphicクラスとScreenクラスをそれぞれ別ファイルとして作成し、パッケージファイル(load.scurl)に集約(include)します。(includeせずに、パッケージファイルにすべてのクラスを直接記述しても問題ありません。)

パッケージファイル (load.scurl)

{curl 8.0 package}
{package MYPACKAGE,
{compiler-directives careful? = true}
}
{import * from COM.CURL.CAEDE.FRAMEWORK.STANDARD}
{import * from COM.CURL.CAEDE.GUI}
{import * from CURL.GUI.BASE}

|| 画面A
{include “Ag.scurl”} || 画面クラス
{include “As.scurl”} || 画面コントロールクラス

|| 画面B
{include “Bg.scurl”} || 画面クラス
{include “Bs.scurl”} || 画面コントロールクラス

{client
|| 画面A
{screen-graphic-reference “gamena”, GamenAGraphic},
|| 画面B
{screen-graphic-reference “gamenb”, GamenBGraphic}
}

clientプロシージャを使って、作成される画面とその任意の名前を定義します。

画面A

画面Aの完成イメージは下図のとおりです。(実際のものとは異なります)

GamenAImagePart.png


画面AのGraphicクラス (Ag.scurl)

Curlのコントロールやコンテナを使い、画面を作成します。このとき、必ずロジック(Sceenクラス)からアクセスしたいオブジェクトには、”name”プロパティを付与してください。

|| Graphicクラス
{define-class public GamenAGraphic
{inherits Frame}

{constructor public {default}
{construct-super
{VBox
width = 200px, 
halign = “center” ,
{RadioFrame
name = “rf1”,
value = “Lizard”,
{VBox
width = 300px,
{RadioButton name = “rb1”, radio-value = “Antelope”},
{RadioButton name = “rb2”, radio-value = “Lizard”},
{RadioButton name = “rb3”, radio-value = “Vulture”}
}
},
{Fill height = 10px},
{CheckButton
name = “cb1”
label = “CheckButton1”
width = 300px
},
{Fill height = 10px},
|| 遷移先へ渡すパラメータの値
{TextField 
name = “atf1” ,
width = 100px,
value = “この値を渡す”
},
{Fill height = 10px},
|| 遷移先画面Bに遷移する
{CommandButton
name = “anextscreen”,
width = 300pt,
label = “次の画面に遷移”
},
{Fill}
}
}
}
}

画面AのScreenクラス (As.scurl)

Screenクラスでは、{Screen-of Graphicクラス名}を継承して作成してください。Screen-ofクラスのfind-graphic-by-nameメソッドを利用することで、Graphicクラスのオブジェクトを取得することができます。以下の例では、name=”atf1″というTextFieldをfind-graphic-by-nameにて取得し、自分のフィールドatf1:TextFieldにセットしています。

|| Screenクラス
{define-class public GamenAScreen
{inherits {Screen-of GamenAGraphic}}

field atf1:TextField
field anextscreen:CommandButton

{constructor public {default}
set self.atf1 = {self.find-graphic-by-name “atf1”} asa TextField
set self.anextscreen = {self.find-graphic-by-name “anextscreen”} asa CommandButton
{self.anextscreen.add-event-handler
{on Action do
|| 遷移先画面Bに遷移し、その際に値を渡す。
{self.change-page GamenBScreen, data = self.atf1.value}
}
}
}
}

画面遷移には、Screen-ofのchange-pageメソッドを利用します。遷移後の画面に値を渡したい場合には、dataというキーワード引数を利用できます。

{change-page 遷移先Screenクラス名, data = 遷移先画面へ渡すデータ}

画面B

次に画面Bの完成イメージは下図のとおりです。

GamenBImagePart.png


画面BのGraphicクラス (Bg.scurl)

Graphicクラスを画面Aと同様に、Curlのコントロール・コンテナを用いて作成します。

|| 画面クラス(遷移先)
{define-class public GamenBGraphic
{inherits Frame}

{constructor public {default}
{construct-super
{VBox
width = 600px,
height = 500px,
{TextDisplay 
name = “td1” ,
width = 100px,
value = “遷移しました”
},
{Fill height = 10px},
{HBox
{TextDisplay
name = “td2” ,
width = 200px,
value = “遷移元の値:”
},
{Fill},
{TextDisplay
name = “td3” ,
width = 200px,
value = “this “
}
},
{Fill}
}
}
}
}

画面BのScreenクラス (Bs.scurl)

こちらも同様に{Screen-of Graphicクラス名}を継承して、クラスを定義します。

|| 画面コントロールクラス(遷移先)
{define-class public GamenBScreen
{inherits {Screen-of GamenBGraphic}}

field td1:TextDisplay
field td2:TextDisplay
field td3:TextDisplay

{constructor public {default}
set self.td1 = {self.find-graphic-by-name “td1”} asa TextDisplay
set self.td2 = {self.find-graphic-by-name “td2”} asa TextDisplay
set self.td3 = {self.find-graphic-by-name “td3”} asa TextDisplay
}

{method public {on-page-changed data:any}:void
|| 遷移元画面Aより渡されたパラメータを設定する。
set self.td3.value = data asa String
}
}

遷移元画面Aより渡されたデータを遷移先画面Bにて受取るには、on-page-changedメソッドをオーバーライドします。

また、画面遷移毎に処理を実行させたい場合は、on-page-changedに記述してください。

⑥Caedeトランスレータにて変換する方法

①ダウンロードしたcaedeのbin/graphical-deploy-tool.dcurlをダブルクリックしてトランスレータを起動します。

caede21caede-graphical-deploy-tool.png


[ Client Project ] : Caedeアプリケーションに変換したい対象のCurlプロジェクト( manifest.mcurl) を指定します。
[ DeploymentSettings ]
[ DeploymentPath ] : Caedeアプリケーションに変換した結果のファイルを配置する場所を指定します
[ TargetPlatforms ] : 変換先のプラットフォームをAndroid/iOS/WinRTから選択します。
[ CompileOptions ] : optimiz eを選択するとコードの最適化が行われます。debugを選択すると例外発生時スタックトレースを表示することができます。
[ Logging ] : 表示するログレベルを指定します。
[ Deploy ] ボタン : 押下すると、Caedeアプリケーションに変換されます。 変換時のログは画面上に表示されますが、Curlコントロールパネル-「Curl RTEコンソール」でも確認できます。

生成結果について

正常に生成された場合は、

caede-deployment-completed.png

このような画面が表示され、Console(Curlコンソール)上で[INFO]メッセージのみが出力されます。

DeploymentSettingsにて指定した場所にファイルが生成されていますので、このファイルをシミュレータ等で実行することになります。

生成ができない場合は、

caede-deployment-aborted.png

このような画面が表示され、Console(Curlコンソール)上で[ERROR]メッセージが出力されます。

シンタックスエラーや、CurlでサポートしているがCaedeでサポートしていないAPIを利用している場合にエラーとなります。

エラーの内容は、Console(Curlコントロールパネルのコンソール)上で確認できます。

最適化モード

トランスレータによって生成されたJavaScriptファイルを、最適化(ミニマイズ)するためにには、node.jsをダウンロードし、Caedeディレクトリのexternal/optimizerディレクトリ配下にnode.exeを置いてください。

⑦各ターゲットでのパッケージング化と実行

Caedeがサポートするプラットフォームで実行させるためにパッケージング化します。

詳細な手順はこちらより確認できます。(Android,iOS,WinRT)

フレームワークの使い方(Caede Development Tools利用時)

Caedeアプリケーションを開発するには、Caedeフレームワークを利用します。ここでは、フレームワークの利用方法をご説明します。

事前に環境のセットアップはCaedeのページよりGettingStarted を参照して実施してください。

 

フレームワーク作成の手順は以下の通りです。

以下は、Caede Development Toolsを使った場合の手順です。

Caede Development Toolsを使わない場合の手順はこちらをご覧下さい。

 

① 新しいプロジェクトを作成します。(Caede)

② start.curlを編集します。

③ 画面クラス、画面コントロールクラスを作成します。

④ Curlソースコードをデプロイします。(Caedeアプリケーションに変換)

⑤各ターゲットプラットフォームで実行するためのパッケージング化を行います。

※当内容は、Caede2.1.0で稼動させた時のイメージにしております。

※Caede Development Toolsの他の機能はこちらをご覧ください。

①新しいプロジェクトを作成します。

Eclipseのファイルメニューから New -> Caedeプロジェクトを選択します。

caede21devtoolsCreatepj.png

②start.curlを編集します。

startupプロシージャに最初に起動するトップ画面のScreenクラスを記述します。

{startup 画面コントロールクラス名}

cdestartCurlfile.png

以下で作成する起動画面のクラス名はGamenAScreenなので

{startup GamenAScreen}

となります。

③ Graphicクラス、Screenクラスを作成します。

まず、Caedeフレームワークでは、GraphicクラスとScreenクラスを各画面ごとに作成します。
GraphicクラスはUI部分で、Screenクラスはロジック部分となります。
ここでは画面Aとそこからの遷移先画面BのGraphicクラスとScreenクラスをそれぞれ別ファイルとして作成し、
パッケージファイル(load.scurl)に集約(include)します。
(includeせずに、パッケージファイルにすべてのクラスを直接記述しても問題ありません。)

 

パッケージファイル (load.scurl)

{curl 8.0 package}
{package MYPACKAGE,
  {compiler-directives careful? = true}
}
{import * from COM.CURL.CAEDE.FRAMEWORK.STANDARD}
{import * from COM.CURL.CAEDE.GUI}
{import * from CURL.GUI.BASE}

|| 画面A
{include “Ag.scurl”} || 画面クラス
{include “As.scurl”} || 画面コントロールクラス

|| 画面B
{include “Bg.scurl”} || 画面クラス
{include “Bs.scurl”} || 画面コントロールクラス

{client
|| 画面A
  {screen-graphic-reference “gamena”, GamenAGraphic},
|| 画面B
  {screen-graphic-reference “gamenb”, GamenBGraphic}
}

clientプロシージャを使って、作成される画面とその任意の名前を定義します。

 

画面A

画面Aの完成イメージは下図のとおりです。(実際のものとは異なります)

GamenAImagePart.png


画面AのGraphicクラス (Ag.scurl)

Curlのコントロールやコンテナを使い、画面を作成します。
このとき、必ずロジック(Sceenクラス)からアクセスしたいオブジェクトには、”name”プロパティを付与してください。

|| Graphicクラス
{define-class public GamenAGraphic
  {inherits Frame}

  {constructor public {default}
    {construct-super
      {VBox
        width = 200px, 
        halign = “center” ,
          {RadioFrame
            name = “rf1”,
            value = “Lizard”,
            {VBox
              width = 300px,
              {RadioButton name = “rb1”, radio-value = “Antelope”},
              {RadioButton name = “rb2”, radio-value = “Lizard”},
              {RadioButton name = “rb3”, radio-value = “Vulture”}
            }
          },
          {Fill height = 10px},
          {CheckButton
            name = “cb1”
            label = “CheckButton1”
            width = 300px
          },
          {Fill height = 10px},
          || 遷移先へ渡すパラメータの値
          {TextField 
            name = “atf1” ,
            width = 100px,
            value = “この値を渡す”
          },
          {Fill height = 10px},
          || 遷移先画面Bに遷移する
          {CommandButton
            name = “anextscreen”,
            width = 300pt,
            label = “次の画面に遷移”
          },
        {Fill}
      }
    }
  }
}

画面AのScreenクラス (As.scurl)

Screenクラスでは、{Screen-of Graphicクラス名}を継承して作成してください。
Screen-ofクラスのfind-graphic-by-nameメソッドを利用することで、Graphicクラスのオブジェクトを取得することができます。
以下の例では、name=”atf1″というTextFieldをfind-graphic-by-nameにて取得し、自分のフィールドatf1:TextFieldにセットしています。

|| Screenクラス
{define-class public GamenAScreen
 {inherits {Screen-of GamenAGraphic}}

 field atf1:TextField
 field anextscreen:CommandButton

 {constructor public {default}
  set self.atf1 = {self.find-graphic-by-name “atf1”} asa TextField
  set self.anextscreen = {self.find-graphic-by-name “anextscreen”} asa CommandButton
  {self.anextscreen.add-event-handler
    {on Action do
      || 遷移先画面Bに遷移し、その際に値を渡す。
      {self.change-page GamenBScreen, data = self.atf1.value}
    }
  }
 }
}

画面遷移には、Screen-ofのchange-pageメソッドを利用します。
遷移後の画面に値を渡したい場合には、dataというキーワード引数を利用できます。

{change-page 遷移先Screenクラス名, data = 遷移先画面へ渡すデータ}

 

画面B

次に画面Bの完成イメージは下図のとおりです。

GamenBImagePart.png


画面BのGraphicクラス (Bg.scurl)

Graphicクラスを画面Aと同様に、Curlのコントロール・コンテナを用いて作成します。

 

|| 画面クラス(遷移先)
{define-class public GamenBGraphic
{inherits Frame}

  {constructor public {default}
    {construct-super
      {VBox
        width = 600px,
        height = 500px,
        {TextDisplay 
          name = “td1” ,
          width = 100px,
          value = “遷移しました”
        },
        {Fill height = 10px},
        {HBox
          {TextDisplay
            name = “td2” ,
            width = 200px,
            value = “遷移元の値:”
          },
          {Fill},
          {TextDisplay
            name = “td3” ,
            width = 200px,
            value = “this “
          }
        },
        {Fill}
      }
    }
  }
}

画面BのScreenクラス (Bs.scurl)

こちらも同様に{Screen-of Graphicクラス名}を継承して、クラスを定義します。

 

|| 画面コントロールクラス(遷移先)
{define-class public GamenBScreen
{inherits {Screen-of GamenBGraphic}}

  field td1:TextDisplay
  field td2:TextDisplay
  field td3:TextDisplay

  {constructor public {default}
    set self.td1 = {self.find-graphic-by-name “td1”} asa TextDisplay
    set self.td2 = {self.find-graphic-by-name “td2”} asa TextDisplay
    set self.td3 = {self.find-graphic-by-name “td3”} asa TextDisplay
  }

  {method public {on-page-changed data:any}:void
  || 遷移元画面Aより渡されたパラメータを設定する。
    set self.td3.value = data asa String
  }
}

遷移元画面Aより渡されたデータを遷移先画面Bにて受取るには、on-page-changedメソッドをオーバーライドします。

また、画面遷移毎に処理を実行させたい場合は、on-page-changedに記述してください。

 

手順④ Caedeプロジェクトをデプロイする。(Caedeアプリケーションに変換)

プロジェクトを右クリック -> Caedeアプリケーションに変換を選択してください。
モバイル用のソースコードが生成されます。

※事前に以下の設定を行う必要がございます。
 1.各ターゲットプラットフォームのビルド環境
 2.トランスレータの設定
 3.ターゲットプラットフォームの設定
 4.build.xmlの編集と実行の設定

【各ターゲットプラットフォームのビルド環境】

Caedeアプリケーションに変換後、Caedeがサポートするプラットフォームで実行させるためにはビルド(パッケージング化)が必要です。

そのため、Caedeアプリケーションに変換を行う前に、各ターゲットプラットフォームでのパッケージング化を行う環境を構築しておく

必要があります。(Android:ADT、iOS:XCODE、WinRT:VisualStudio)

ビルド環境をセットアップするための手順:(Android,iOS,WinRT)

 

【トランスレータの設定】

 Caedeプロジェクトのプロパティ -> Caede -> トランスレータより、
 Caedeアプリケーションに変換時のオプションを設定することができます。
 optimizeを選択するとコードの最適化が行われます。
 debugを選択すると例外発生時スタックトレースを表示することができます。

 

【ターゲットプラットフォームの設定】

プロジェクトエクスプローラ上で、プロジェクトを右クリック しコンテキストメニューから [ Properties ] を選択します。
表示されるダイアログの [ Caede ] ページでターゲットプラットフォームを設定します。

caede21devtoolsTargetOS.png

 

 

【build.xmlの編集と実行】

build.xmlを編集することで
各ターゲットプラットフォーム用のビルドツール(AndroidPJ/XCODE/VisualStudio)へのコピーを自動で行うことが可能です。

Androidの場合

ターゲットプラットフォームがAndroidの場合、AndroidプロジェクトにCaedeアプリケーションをコピーする為に
Androidプロジェクトのロケーションを設定する必要があります。

Androidプロジェクトのロケーションは、build.xmlの [ android.prj ] プロパティに設定してください。

ワークスペース上に [ AndroidPrj ] というAndroidプロジェクトが存在する場合、以下のように設定します。  

 caede21gs_development2.png

 

 

 

 

iOSの場合

ターゲットプラットフォームがiOSの場合、MacにCaedeアプリケーションをscpでコピーする為に
以下のMacの情報をbuild.xmlのプロパティに設定する必要があります。

[ mac.host.name ] プロパティ : Macのホスト名およびIPアドレス (例:mymac.curl.com)

[ mac.dest.dir ] プロパティ : Caedeアプリケーションの保存先ディレクトリ (例:/Users/curl/caede-app)

[ mac.user ] プロパティ : MacのユーザーID (例:curl)

[ mac.password ] プロパティ : Macのパスワード (例:password)

caede21gs_development3.png

 

 

 

 

 

 

 

 

注意: build.xmlからscpを使用する場合、Antのランタイムにjschを設定する必要があります。

Eclipseのメニューバーから、 [ Windows ] > [ Preferences ] > [ Ant ] > [ Runtime ] を選択します。

[ Runtime ]ページの [ Classpath ] タブの [ Global Entries ] を選択し、 [ Add ExternalJARs… ] を選択します。

caede21gs_development4.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Eclipseのインストールフォルダのpluginsフォルダを開き、[ com.jcraft.jsch_*.jar ]を選択します。

caede21gs_development5.png

 

 

 

 

これでbuild.xmlからscpを使用する事ができるようになります。  

 

WinRTの場合:

ターゲットプラットフォームがWinRTの場合、Visual StudioのプロジェクトにCaedeアプリケーションをコピーする為に
Visual Studioのプロジェクトのロケーションを設定する必要があります。

Visual Studioのプロジェクトのロケーションは、build.xmlの [ vs.prj ] プロパティに設定してください。

caede21gs_development6.png

 

 

 

 

 

 

 

 

build.xmlの編集後、Caedeアプリケーションに変換を選択してください。以下のダイアログが表示されます。

caede21gs_development7.png

 

 

 

 

 

 

 

 

 

各ターゲットプラットフォームの開発ツールをセットアップしている場合は、[ YES ] を押下してください。

セットアップしていない場合、ここでは [ No ] を選択し、

各ターゲットプラットフォームの開発ツールをセットアップ後に再度Caedeアプリケーションに変換より選択し、build.xmlを実行してください。

 

 

 

⑤各ターゲットプラットフォームでのパッケージング化と実行

【各ターゲットプラットフォームで動作させる場合】

Caedeがサポートするプラットフォームで実行させるためにパッケージング化します。

詳細な手順はこちらより確認できます。(Android,iOS,WinRT)

【Caedeアプリケーションプレビューで確認する場合】

Caede2.0.0にて、Caedeアプリケーションプレビュー機能が実装されました。
同機能にて、AndroidやiOSのシミュレータ/実機で動かした場合と同様の内容を確認することができます。

プロジェクトを右クリック -> Caedeアプリケーションプレビュー を選択してください。
Caedeアプリケーションプレビューが起動されます。

 

CDE(Caede Development Tools)の主な機能

このページでは、フレームワークの使い方(Caede Development Tools)では説明していない

Caede Development Toolsの機能について紹介します。

 

Caedeアプリケーションプレビュー

Caede2.0.0で追加された機能です。

Caedeアプリケーションを実行する方法として、

各プラットフォームのエミュレータと、実機がありましたが、

Caede側でアプリケーションをプレビューする機能が実装されました。

「Caedeプロジェクトにて右クリック -> Caedeアプリケーションプレビュー」

と選択することでCaedeアプリケーションを起動することができます。

apppreview1.png

Caedeアプリケーションプレビュー画面のメニュー上の「デバイスの向き」、「画面サイズ」を操作することにより、

デバイスの向き(縦・横)の変更、Caedeであらかじめ用意している画面サイズに変更することが可能です。

(ユーザが任意の画面サイズを変更することも可能です。)

apppreview3.png

 

Caede用テンプレート

Caede2.0.0で追加された機能です。

Caedeプロジェクト作成時に選択できるテンプレートについて機能について紹介します。

予め用意されているテンプレートを利用することで、プログラミングを効率よく行うことが可能です。

※Caede2.0.0の画面イメージです。

templatepj.png 

Caedeプロジェクト画面にて 「テンプレート」より選択して頂くことで利用可能です。

テンプレートを選択してプロジェクトを作成すると、テンプレートのソースプログラムが自動で生成されます。

templatelogin.png

 

Caedeマイグレーション

Caede2.0.0で追加された機能です。

 マイグレーション機能はワークスペース上に存在する旧バージョンのCaedeプロジェクトを新バージョンの構成に変換する機能です。

 Eclipseメニューにて Project > Caede マイグレーション を選択することで起動できます。

 migration.png

OKボタンを押下すると新しいバージョンに対応したCaedeプロジェクトの構成に変更されます。

APIの説明:Curl基本構文とライブラリ

CaedeではCurl基本構文及びCurl標準ライブラリをご利用いただくことが可能です。

但し、Curl言語のすべての機能はサポートしておらず、機能制限があります。

サポートされるCurl言語仕様 (2013年10月22日現在)

  • 変数宣言 (def, let, set) ※グローバル変数も対応
  • ループ (for, while, unlessなど)
  • 条件式 (if, if-non-null, switch, type-switchなど)
  • プロシージャ、クロージャ
  • クラス、列挙型、valueクラス、パラメータ化クラス、implicit
  • マクロ
  • キャスト・型判定 (isa, asa, type-of)
  • 例外(try, catch, finally, throw, 各種Exception)
  • 翻訳(host-locale,lmessageなど)
  • …etc

 

サポートされるデータ型 (2013年10月22日現在)

  • プリミティブ型
  • Decimal
  • 文字列(String, StringBuf)
  • 日付型(DateTime)
  • コレクション(FastArray-of, Array-of, HashTable-ofなど)
  • …etc

サポートされるCurl標準API (2013年10月22日現在)

  • 数学関数、ランダム
  • 正規表現
  • ネットワーキング(URL、HTTP)
  • コンソール・フォーマット(output, formatなど)
  • JSON (JsonValue-parse, JsonValue-to-Stringなど)
  • イベント (EventTarget, EventHandler, Event)
  • システム(exit …)
  • …etc

 

対応しているすべてのAPIにつきましては、Caede API リファレンスを参照ください。

今後、さらなる機能拡張をユーザニーズに併せて実施していく予定ですので、ご要望をコミュニティ・サイトに投稿いただければと思います。

 

APIの説明:GUIコンポーネント

CaedeではCurl標準GUIコンポーネント及びモバイル用コンポーネントをご利用いただくことが可能です。

但し、Curl言語のすべての機能はサポートしておらず、機能制限があります。またモバイル用として作成されますのでシミュレータや実機で確認した場合、見た目や動きが変わることもあります。

サポートされる標準GUIコンテナ (2013年10月22日現在)

 

サポートされる標準GUIコントロール (2013年10月22日現在)

  • TextField, TextArea, PasswordField
  • CommandButton
  • RadioButton, CheckButton
  • DropdownList
  • …etc

 

サポートされる標準GUIイベント (2013年10月22日現在)

  • Action
  • Swipe
  • Taphold
  • KeyPress
  • AttachEvent
  • …etc

 

サポートされるモバイル用GUIコンポーネント (2013年10月22日現在)

 

対応しているすべてのGUIコンポーネントにつきましては、Caede API リファレンスを参照ください。

今後、さらなる機能拡張をユーザニーズに併せて実施していく予定ですので、ご要望をコミュニティ・サイトに投稿いただければと思います。

 

APIの説明:デバイス・インターフェース

はじめに

デバイスインターフェースを利用するには、COM.CURL.CAEDE.NATIVE-INTERFACEパッケージが必要になります。(フレームワークの使い方に記載しているCOM.CURL.CAEDEをデリゲートすれば利用可能です)

 

COM.CURL.CAEDE.NATIVE-INTERFACEパッケージをimportしてください。

{import * from COM.CURL.CAEDE.NATIVE-INTERFACE}

 

デバイス情報の取得

get-the-deviceプロシージャを使ってDeviceオブジェクトを取得することで情報を取得できます。

def d = {get-the-device}
{output
  {format “name=%s platform=%s version=%s”, d.name, d.platform, d.version}
}

 

カメラ

run-cameraプロシージャを使ってデバイスに付属しているカメラを起動します。写真取得後に画像のUrlを取得するために、CameraFinishedEventハンドラ―を登録します。

{run-camera
  {on e:CameraFinishedEvent do
    {if not e.canceled? then
      {output e.media-url.name}
    }
  }
}

 

ローカルストレージ

永続的データとしてデータの保存ができます。

KvsStorage

let conn:StorageConnection = {StorageConnection.open
                                                        “testdb”, || 任意の名前
                                                        type = StorageType.kvs
                                                    }
def s = conn.storage asa KvsStorage

|| set (値のセット)
set s[“key1”] = “val1” || or {s.set “key1”, “val1”}
set s[“key2”] = “val2” || or {s.set “key2”, “val2”}

|| get (値の取得)
{output s[“key2”]} || or {s.get “key2”}

|| find (部分一致検索)
{for v key k in {s.find “key”} do
  {output k, v} || 2件がヒットする
}

 

RdbStorage

def con = {StorageConnection.open “testRDBdb”} ||任意の名前
def storage = con.storage asa RdbStorage

||(SQLによる) テーブル作成、初期データ作成
{storage.execute-update “DROP TABLE IF EXISTS TEST”}
{storage.execute-update “CREATE TABLE TEST (COL1 integer, COL2 text)”}
{con.begin}
{for i = 0 below 5 do
    {storage.execute-update “INSERT INTO TEST values(?, ?)”, i, “DATA” & i}
}
{con.commit} || commit

||(SQLによる)データ取得
def rows = {storage.execute-query “SELECT * FROM TEST”}
{for r in rows do
    {output 
        {format
            “RDB test col1=%s col2=%s”, 
            {r.get-int “COL1”}, 
            {r.get-String “COL2”}
        }
    }
}
{storage.execute-update “DROP TABLE IF EXISTS TEST”}
{popup-message “Please see the console log.”}

 

 

 

GPS

start-location-notifierを使って、GPSを起動します。GPSで値を取得したらLocationChangedEventが発生します。また、GPSを止める場合は、stop-location-notifierを利用します。

{start-location-notifier
  {on e:LocationChangedEvent do
    def loc = e.location || Locationオブジェクト
    {output {format “lat=%s, lng=%s”, loc.latitude, loc.longitude}}
  }
}

 

加速度センサー

start-accelerometer-notifierを使って、加速度センサーを起動します。加速度センサーからの通知があった場合にはAccelerometerEventが発生します。また、加速度センサーを止める場合には、stop-accelerometer-notifierを利用します。

{start-accelerometer-notifier
  {on e:AccelerometerEvent do
    {output {format “x=%s y=%s z=%s”, e.x, e.y, e.z}}
  }
}

 

ネットワークのオンラインチェック

ネットワークがオンラインかどうかをチェックするには、network-online?プロシージャを利用します。

 

コンタクト

連絡帳データを取得したり、電話コール、メール送信をことができます。

 

def c-list = {find-contact-list “AB”} || 前方一致する連絡帳データ取得。
|| あるいは{get-contact-list}で連絡帳データ全件取得
{for c in c-list do
    {output {format “%s %s”, c.id, c.name}} || c.phones, c.emailsプロパティもある。
}

{call-phone “03123456789”}

{send-email {StringArray abc@curl.com}, “Test!”, “This is a test.”}

APIの説明・サンプル(Screen-of)

Screen-ofクラス

Caede の “Screen” を定義するための基本クラスです。

説明
これは Caede アプリケーションの “Screen” を表すすべてのクラスの基本クラスです。スクリーンクラスは、このクラスのサ
ブクラスでなければならず、Screen-of パラメータ化型テンプレートのパラメータとして、対応する “Graphic” クラスを指定
しなければなりません。そして、このクラスは、画面の操作や画面上のステータス変更の通知を受けるためのインターフェ
イス用メソッドを提供します。

コンストラクタ
  default
      public {Screen-of.default}

プロパティ
  cacheable? : このインスタンスがキャッシュ可能かどうかを示します。
    getter public ScreenUtilsMixin.cacheable?:bool

  first-active-control
    public ScreenUtilsMixin.first-active-control:#ActiveTraversor

  screen-slot
    getter public ScreenUtilsMixin.screen-slot:#ScreenSlot

メソッド
  change-page : 現在のページから、別のページにページを変更します。
    public {ScreenUtilsMixin.change-page
      screen:ScreenFeed,
      data:any = null,
      transition:PageTransition = PageTransition.fade,
      reverse?:bool = false
    }:void

  find-graphic-by-name :バインドされたグラフィックから指定された name のグラフィック要素を取得します。
      public {BaseScreen.find-graphic-by-name name:String}:#Graphic

  find-shape-by-name :バインドされたグラフィック BaseScreen.graphicから指定された name のShapeを取得します。
      public {BaseScreen.find-shape-by-name name:String}:#Shape

  find-shape-by-name-in-box :バインドされたグラフィックBaseScreen.graphicから指定されたnameのShapeを取得します。
    public {BaseScreen.find-shape-by-name-in-box
        name:String,
        shapebox:#ShapeBox = null,
        shapebox-name:String = “”
    }:#Shape

  on-page-changed : 画面遷移が発生したときに呼び出されます。
        public {BaseScreen.on-page-changed data:any}:void

 

実行イメージとソース

 画面遷移する簡単なサンプルコードと開発環境を紹介したページがございますので、こちらをご覧ください。

 

 

APIの説明・サンプル(GUIコンポーネント詳細)

画像コントロール

||manifestファイルに指定します
{component file logo1,
  location = “curl/images/logo1.png”
}

|| simple-imageプロシージャ
{simple-image
  name = “new_image_g”,
  {manifest-url “file”, “logo1”}

}

|| SimpleImageGraphicクラス
set self.image-g = {self.find-graphic-by-name “new_image_g”} asa SimpleImageGraphic

|| ボタン押下時に画像を入れ替える
{self.logo12btn.add-event-handler
  {on Action do
    set self.image-g.source = {manifest-url “file”, “logo2”}

  }
}

 

 

|| デスクトップ版で御馴染みのpopup-message

def pm = {self.find-graphic-by-name “popup-message”} asa CommandButton
{pm.add-event-handler
  {on Action do
    {popup-message “Hello!” }
  }
}

|| show-toastプロシージャ

def toast = {self.find-graphic-by-name “toast”} asa CommandButton
{toast.add-event-handler
  {on Action do
    {show-toast “This is message.”}
  }
}

|| インジケータ
def indicator = {self.find-graphic-by-name “indicator”} asa CommandButton
{indicator.add-event-handler
  {on Action do
    {with-busy-indicator
      message = “WAIT…..”
    do
      {for i = 0 below 10000 do
        def i = 1000 * 0.2 * 20
      }
    }
  }

 

show-toast、with-mobile-processing-messageを使う場合は、以下のパッケージをインポートする必要があります。

{import * from COM.CURL.CAEDE.GUI}

 

MAP(GOOGLE-MAP)

||画面(グラフィック)クラス——————————————————————-

|| マップを表示するために、GoogleMapを画面クラスに配置します。

{GoogleMap
  name = “map”,
  width = 400px,
  height = 500px
}

||ロジック(スクリーン)クラス—————————————————————-

|| GoogleMapの初期表示座標、ズーム、マップタイプなどを設定します。
def map = {self.find-graphic-by-name “map”} asa GoogleMap
{map.init-map
  {MapOptions
    center = {Location
                   35.024052390233784, 
                   135.76209587478638,
                   0.0, 
                   0.0, 
                   {DateTime}, 
                   0.0, 
                   0.0
                 },
    zoom = 14,
    map-type-control = true,
    map-type-id = MapTypeId.ROADMAP
  }
}

|| イベント追加は通常のコントロールへのイベント追加と同様です。
{map.add-event-handler
  {on e:MapClickEvent do
    {popup-message “”Clicked Map!”}
  }
}
 

MAP(GOOGLE-MAP)を使う場合は、以下のパッケージをインポートする必要があります。

{import * from COM.CURL.CAEDE.WEB-SERVICE.GOOGLE-MAPS}

 

 

Movie

||画面(グラフィック)クラス——————————————————————-

|| 画面にVideoPlayerコントロール用のオブジェクトを配置する。

{VideoPlayer
  name = “video”,
  width = 320px,
  height = 200px
}

 

||ロジック(スクリーン)クラス—————————————————————-
|| VideoPlayer、MOVIEの選択
def video = {self.find-graphic-by-name “video”} asa VideoPlayer
set video.controls = true
def mg-movie = {self.find-graphic-by-name “run-mg-movie”} asa CommandButton
{mg-movie.add-event-handler
  {on Action do
    {run-media-gallery
      type = MediaType.video,
      {on e:MediaGalleryFinishedEvent do
        {if not e.canceled? then
          set video.source = {url e.media-url.name}
          {video.add-event-handler
            {on MediaPauseEvent do
              {output “Paused video.”}
            }
          }
        }
      }
    }
  }
}
 

 

MOVIEを使う場合は、以下のパッケージをインポートする必要があります。

{import * from COM.CURL.CAEDE.MEDIA}

 

対応しているすべてのGUIコンポーネントにつきましては、Caede API リファレンスを参照ください。

今後、さらなる機能拡張をユーザニーズに併せて実施していく予定ですので、ご要望をコミュニティ・サイトに投稿いただければと思います。

 

APIの説明・サンプル(ScalableScrollBox)

ScalableScrollBox (クラス)

public ScalableScrollBox {inherits ScrollBox}

スケール可能なスクロールボックスです。
その内容を拡大/縮小することができます。


ScalableScrollBoxの使用法は、追加のオプション以外はScrollBoxと同じです。

{ScalableScrollBox
  width = 200px,
  height = 200px,
  scalable? = true,
  min-scale = 0.5,
  max-scale = 4.0,
    {simple-image
      width = 400px,
      height = 400px,
    {url “curl://install/docs/default/images/adria.jpg”}
  }
}

注意事項

一般的なスクロール機能の詳細については、ScrollBoxを参照してください。
ダブルタップでのズームイン/アウトもサポートされています。

コンストラクタ

default : 新しい ScaleableScrollBoxを初期化します。

public  {ScalableScrollBox.default
                          scalable?:bool = true,
                          scale:double = 1.0,
                          min-scale:double = 1.0,
                          max-scale:double = 1.0, …}

新しい ScalableScrollBoxを初期化します。
scalable?: trueに設定すると、ピンチイン/アウトによるズームを行えます。
scale: スケールの初期値
min-scale: スケールの最小値
max-scale: スケールの最大値
…: このコンストラクタの追加引数は、既定の ScrollBoxコンストラクタに提供できる引数と同じです。

ローカルオプション

scalable?

public ScalableScrollBox.scalable?:bool = true
ピンチイン/アウトによるズームを有効または無効にします。既定は trueです。

scale

public ScalableScrollBox.scale:double =1.0
現在のスケール値です。

min-scale

public ScalableScrollBox.min-scale:double =1.0
スケールの最小値です。

max-scale

public ScalableScrollBox.max-scale:double =1.0
スケールの最大値です。

 

 実行イメージとソース

pre.png

post.png

|| 画面クラス
{define-class public MySampleGraphic{inherits Frame}
  {constructor public {default}
    {construct-super
        {ScalableScrollBox
            name = “scalable-scroll-box”,
            scalable? = true,
            scale = 1.0,
            min-scale = 0.25,
            max-scale = 8.0,
            {simple-image
                {{manifest-url “directory”, “images”}.concat “map.jpg”},
                width = 8.46cm, height = 4.68cm
            }
        }
    }
  }
}

|| ロジッククラス
{define-class public MySampleScreen {inherits {Screen-of MySampleGraphic}}
  {constructor public {default}}
}

APIの説明・サンプル(ListViewer、Chart、Shape)

Caede2.0.0で追加されたリストビューア、チャート、シェイプのサンプルをご紹介します。

リストビューア

Caede2.0.0ではリストビューア(ListViewer)が実装されました。
これをもちましてリストビュー(ListView)は非推奨となり、Caede2.1.0にて廃止されました。

|| ListViewerクラス (フレームワークのGraphicクラスに定義)

{ListViewer
  width = {make-elastic preferred-size = 100cm},
  height = {make-elastic preferred-size = 100cm},
  name = “sample-list-viewer”
}

|| 以下はScreenクラスに記述します

def list-viewer = {self.find-graphic-by-name “sample-list-viewer”} asa ListViewer

|| list-item-creation-proc オプションを定義します。
|| list-item-creation-proc オプションは{proc {val:any}:ListItem}型で、
|| val変数に渡されてくる各行のデータを
|| どのようにレイアウトするかを定義します。
|| ListViewItemDataのlabelアクセサに
|| {HBox}などのコンテナクラスを使用して自由に定義できます。

set list-viewer.list-item-creation-proc = 
  {proc {val:any}:ListItem
    def label = {HBox val & ” 番目のデータ”, valign = “center”}
    {return 
      {ListViewItemData 
        width = 1m, 
        label = label,
        {on Action do
          {popup-message val & ” 番目のデータ”}
        }
      }
    }
  }

|| data-modelオプションを定義します。
|| data-modelオプションはListModelView型で、
|| 表示されるデータを管理しています。
|| データはListModelViewのdata-sourceアクセサに
|| ConnectedListModel型のオブジェクトで持ち、
|| データの追加はこのオブジェクトに対して行います。
|| ListModelViewSetCountRequestイベントハンドラでは、
|| ListViewer下部で上向きにフリックしたときの
|| 動作について定義ができます。
|| ここでは項目を10件追加しています。

def connected-list-model = {ConnectedListModel}
set list-viewer.data-model =
  {DefaultListModelView
    page-size = 10,
    max-source-index = 9,
    connected-list-model,
    {on e:ListModelViewSetCountRequest do
      def read-from = connected-list-model.size
      {for i:int = read-from below read-from + 10 do
        {connected-list-model.append-quietly i}
      }
    }
  }
set list-viewer.pull-up-handle.ready-message = “続きを読む”
{for i:int = 0 below 10 do
  {connected-list-model.append-quietly i}
}
{list-viewer.data-model.set-item-count 10}

以上のコーディングで以下のような動作が実現できます。

起動時。10件が読み込まれています。

末尾で上に向けてフリックすると、

追加で10件が読み込まれます。

チャート

|| 使用するデータとして以下のRecordSetを用意します。
|| North、East、South、West各地域の1月から4月までのデータ列です。

def record-set:RecordSet = 
  {RecordSet 
    {RecordFields 
      {RecordField “Region”, domain = String},
      {RecordField “M1”, caption = “1月”, domain = int},
      {RecordField “M2”, caption = “2月”, domain = int},
      {RecordField “M3”, caption = “3月”, domain = int},
      {RecordField “M4”, caption = “4月”, domain = int}
    },
    {RecordData Region = “North”, M1 = 100, M2 = 140, M3 = 130, M4 = 90},
    {RecordData Region = “East”, M1 = 110, M2 = 140, M3 = 170, M4 = 150},
    {RecordData Region = “South”, M1 = 140, M2 = 100, M3 = 130, M4 = 190},
    {RecordData Region = “West”, M1 = 160, M2 = 190, M3 = 140, M4 = 160}
  }

|| BarLayerを使用して棒グラフを表示します。
|| LineLayerを使用すれば折れ線グラフで表示できます。
|| legend-location = “bottom”として、凡例を下部に表示しています。

let chart-box:ChartBox =
  {ChartBox
    {LayeredChart
      legend-location = “bottom”,
      width = 4.5cm,
      height = 7.5cm,
      {BarLayer
        record-set,
        “M1”,
        “M2”,
        “M3”,
        “M4”,
        x-axis-data = {ChartDataSeries record-set, “Region”}
      }
    }
  }

以上のコーディングでこのような棒グラフが表示できます。

chart1.png

BarLayerの代わりにLineLiyerとすると、同じデータから折れ線グラフが表示できます。

chart2.png

シェイプ

Curlと同様にShapeが使用できます。

def canvas = {Canvas background = “aqua”}
{canvas.add
  {ShapeGroup
    || 四角形
    {RectangleShape
      {GRect 0in, 1in, 0in, 0.6in},
      color = “pink”
      border-color = “brown”
      border-width = 3px
    },
    || 四角形(境界が点線)
    {RectangleShape
      {GRect 0.5in, 0.6in, 0in, .2in},
      translation = {Distance2d 0.6in, 0.3in},
      color = “transparent
      border-color = “brown”,
      border-width = 1px
      border-line-style = “dot”
    },
    || 文字
    {TextShape
      “RectangleShape”,
      translation = {Distance2d 0.6in, 0.3in},
      color = “brown”,
      valign = “top”
      halign = “center
    },
    translation = {Distance2d 0.3in, 1.4in}
  }
}
{canvas.add
  {ShapeGroup
    || 円
    {EllipseShape
      {GRect .5in, .5in, .5in, .5in},
      border-width = 2px, 
      border-color = “brown”,
      color = “skyblue”,
      translation = {Distance2d .6in, .6in}
    },
    || 扇形
    {EllipseShape
      {GRect .5in, .5in, .5in, .5in},
      border-width = 2px,
      border-color = “brown”,
      color = “orange”,
      start-angle = 45deg,
      stop-angle = 120deg,
      wedge? = false,
      translation = {Distance2d .6in, .6in}
    },
    || 文字(60度傾斜)
    {TextShape
      “EllipseShape”,
      translation = {Distance2d .5in, .5in},
      color = “brown”,
      rotation = -60deg,
      valign = “top”
      halign = “center”
    }
  }
}

上記のコードで以下のような画面を表示できます

shapes.png

APIの説明・サンプル(ダイナミックレイアウト用API)

Caede2.1.0にてデバイスの画面サイズにダイナミックにレイアウトを変更するためのAPIが提供されました。

これにより、ソースコード1つで、各デバイスの画面ごとに最適なレイアウトを提供することが可能になります。

 

実行イメージ

 下記イメージは、 3つのパーツ メニュー部分(赤枠)、検索部分(黄色枠)、結果部分(緑色枠)を 

  タブレットでは、1つの画面に収めたレイアウト

  スマートフォンでは3つパーツ単位に画面遷移するような構成

です。

 

タブレット

caede21-resweb-tab.jpg

 

 

 

 

 

 

 

 

 

 

 

 

 

スマートフォン

caede21-resweb-sp1.jpgcaede21-resweb-sp2.jpgcaede21-resweb-sp3.jpg

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Caedeには、ロジック部分を管理するScreenクラス、レイアウト部分を管理するGraphicより構成されていますが、

レスポンシブWebデザインには、この2つにブロックと呼ばれる概念が加わります。

上記イメージでは、 

  メニュー部分(赤枠)、検索部分(黄色枠)、結果部分(緑色枠)

がブロックに該当します。

 

 


 

実装手順

1.ブロック用のクラスを定義する

  【ブロック(グラフィック)部分】
  【ブロック(ロジック)部分】

 2.タブレット用/スマートフォン用のGraphicクラスを定義する

 タブレット用/スマートフォン用のGraphicクラスを定義し、1で作成したブロッククラス(グラフィック)と紐付ける。

  【スマートフォン用Graphicクラスのソースコード】
  【タブレット用Graphicクラスのソースコード】

3.タブレット用/スマートフォン用のScreencクラスを定義する(ブロッククラスとの紐付け)

 タブレット用/スマートフォン用のScreenクラスを定義し、1で作成したブロッククラス(ロジック)と紐付ける。

  【タブレット用Screenクラスのソースコード】
  【スマートフォン用Screenクラスのソースコード】

4.起動時の実装(startup)

 起動時用のスクリーンクラスを定義し、タブレット用/ スマートフォン用の画面サイズとサイズ設定の名称を定義する。

 

 

1.ブロック用のクラスを定義

  まず、3つのブロックを定義します。 ブロックは、タブレット/スマートフォンで共通利用するオブジェクトです。

 ブロックにもレイアウトを定義する部分とロジックを定義する部分に分離されます。

 

【ブロック(グラフィック)部分】

 以下はレイアウトを定義するソースコードです。Graphicクラスの書き方とほぼ同じです。

 ||メニューブロック
{define-class public MenuBlock {inherits Frame}
  {constructor public {default …}
    {construct-super
        name = “menublock”,
        {VBox
            width = {make-elastic},           
            margin = 20px,
            halign = “center”,
            height = {make-elastic},
            background = “darkblue”,
            color = “white”,
            border-width = 5px,
            border-color = “red”,
            spacing = 15px,
           
            {CommandButton
                name = “menu-bt1”,
                label = “メニュー1”,
                height = 40px,
                width = {make-elastic}
            },
            {CommandButton
                name = “menu-bt2”,
                label = “メニュー2”,
                height = 40px,
                width = {make-elastic}
            },
            {CommandButton
                name = “menu-bt3”,
                label = “メニュー3”,
                height = 40px,
                width = {make-elastic}
            }
        },
        {splice …}
    }
    set self.margin = 10px
  }
 
}

||検索ブロック
{define-class public SearchBlock {inherits Frame}

~省略~

}

||結果ブロック
{define-class public ResultBlock {inherits Frame}  

~省略~

}

 

【ブロック(ロジック)部分】

 次に、ブロック用のスクリーンクラスを定義します。

 タブレット/スマートフォンでオブジェクトは共通ですが、タブレット/スマートフォン毎に分岐したロジックを実装可能です。 

 

たとえば上記実行イメージでは、

 スマートフォンの場合、メニューボタン、検索ボタンを押下した場合画面遷移しますが、これを実装しています。

  

  ブロック用のスクリーンクラスは、BlockScreen-of クラスを継承して定義します。※下線部

 parent-screenメソッド、activate-blockメソッドが提供されており、

  これを用いることでタブレット/スマートフォンの各々のロジックを分岐した実装が可能です。

   BlockScreen-of.parent-screenメソッド : 親のスクリーンクラスを取得するメソッド。

   BlockScreen-of.activate-blockメソッド : 画面遷移を伴わないchange-pageメソッド。

 

||メニューブロック用 スクリーンクラス
{define-class public MenuBlockScreen {inherits {BlockScreen-of MenuBlock}}
 
  {constructor public {default graphic:#Graphic = null}
    {construct-super graphic = graphic}
   
    {dump “MenuBlockScreeeen constructor”}
   
    def menu-bt1 = {self.find-graphic-by-name “menu-bt1”} asa CommandButton
    {menu-bt1.add-event-handler
        {on Action do

            || 
            ||親のスクリーンを取得する
            ||

            {dump self.parent-screen}           
            {if self.parent-screen isa SmartphoneMenuScreen then

                || スマートフォンの場合
                ||画面遷移します
                ||

                {self.change-page
                    SmartphoneSearchScreen,
                    data = “menu1”
                }
             else
                || スマートフォン以外の場合
                ||画面遷移はしないが、BlockScreen間でon-page-changedメソッドを呼び出すことが可能
                ||※画面遷移を伴わないon-page-changed。

                {self.activate-block
                    SearchBlockScreen,
                    data = “menu1”
                }
            }
        }
    }
  }
 
  {method public {on-page-changed data:any}:void
    {dump ” MenuBlockScreeeen.on-page-chaged”}
  }
 
}

||検索ブロック
{define-class public SearchBlockScreen {inherits {BlockScreen-of SearchBlock}}

~省略~ 

}

||結果ブロック
{define-class public ResultBlockScreen {inherits {BlockScreen-of ResultBlock}
  
~省略~

}

 


 2.タブレット用/スマートフォン用のGraphicクラスを定義する

次に、 タブレット用/スマートフォン用のGraphicクラスを定義します。

上記実行イメージでは、 タブレット用はGraphicクラスを1つ、スマートフォン用のGraphicクラスを3つ作成することになります。

タブレット用/スマートフォン用のGraphicクラスの中では、先ほど定義したブロック(グラフィック)を実装したい画面

レイアウトにあわせて呼び出します。(※下線

 

【タブレット用Graphicクラスのソースコード】

||
||タブレット用Graphicクラス
||

{define-class public TabletGraphic {inherits Frame} 
  {constructor public {default …}
    {construct-super
        {VBox
            width = {make-elastic preferred-size = 1024px},
            height = {make-elastic preferred-size = 1024px},
            {HeaderBlock},
            {HBox
                  {MenuBlock},
                {VBox
                    {SearchBlock},
                    {ResultBlock}

                }
            }
        }
    }
  }
}
}

  

【スマートフォン用Graphicクラスのソースコード】

||
||スマートフォン用Graphicクラス(メニュー)
||

{define-class public SmartphoneMenuGraphic {inherits Frame}
 
  {constructor public {default …}
    {construct-super
        {VBox
            width = {make-elastic preferred-size = 767px},
            height = {make-elastic preferred-size = 1024px},
                {HeaderBlock},
                {MenuBlock }
        }
    }
  }
}

||
||スマートフォン用Graphicクラス(検索)
||

{define-class public SmartphoneSearchGraphic {inherits Frame}
 
~省略~
}

||
||スマートフォン用Graphicクラス(結果)
||

{define-class public SmartphoneResultGraphic {inherits Frame}
 
~省略~
}

 

 

 

3.タブレット用/スマートフォン用のScreencクラスを定義する

次に、 タブレット用/スマートフォン用のScreencクラスを定義します。

上記実行イメージでは、 タブレット用/スマートフォン用のGraphicクラスと同様に

タブレット用はScreenクラスを1つ、スマートフォン用のScreenクラスを3つ作成することになります。

タブレット用/スマートフォン用のScreenクラスの中では、先ほど定義したブロック(スクリーン)クラスをを登録します。

Screen-ob.regist-block-screenメソッドを用いることで、スクリーンクラスの構成要素となる、

ブロックのスクリーンクラスを登録します。(※下線

 

【タブレット用Screenクラスのソースコード】

||
||タブレット用Screenクラス
||

{define-class public TabletScreen {inherits {Screen-of TabletGraphic}}
 
  {constructor public {default}

    ||BlockScreenクラスと関連するグラフィックオブジェクト
    def header-block = {self.find-graphic-by-name “headerblock”} asa HeaderBlock
    def menu-block = {self.find-graphic-by-name “menublock”} asa MenuBlock
    def search-block = {self.find-graphic-by-name “searchblock”} asa SearchBlock
    def result-block = {self.find-graphic-by-name “resultblock”} asa ResultBlock
    
    ||当クラスの構成要素となる、ブロックのスクリーンクラスを登録する。
    {self.regist-block-screen HeaderBlockScreen, header-block}
    {self.regist-block-screen SearchBlockScreen, search-block}
    {self.regist-block-screen MenuBlockScreen, menu-block}
    {self.regist-block-screen ResultBlockScreen, result-block}   
  }
}

【スマートフォン用Screenクラスのソースコード】

||
||スマートフォン用Screenクラス(メニュー)
||SmartphoneMenuGraphicの対となるクラス
||

{define-class public SmartphoneMenuScreen {inherits {Screen-of SmartphoneMenuGraphic}}
 
  {constructor public {default} 
    def header-block = {self.find-graphic-by-name “headerblock”} asa HeaderBlock
    def menu-block = {self.find-graphic-by-name “menublock”} asa MenuBlock
    
    ||当クラスの構成要素となる、ブロックのスクリーンクラスを登録する。
   {self.regist-block-screen HeaderBlockScreen, header-block}
   {self.regist-block-screen MenuBlockScreen, menu-block}
   
  }

  {method public {on-page-changed data:any}:void
    {dump “SPMenuScreen.on-page-chaged”}
  }
}

||
||スマートフォン用Screenクラス(検索)
||SmartphoneMenuGraphicの対となるクラス
||

{define-class public SmartphoneSearchScreen {inherits {Screen-of SmartphoneSearchGraphic}} 
 ~省略~
}

||
||スマートフォン用Screenクラス(結果)
||

{define-class public SmartphoneResultScreen {inherits {Screen-of SmartphoneResultGraphic}}  
   ~省略~
}

 

 

 

4.起動時の実装(startup)

最後に、タブレット用のクラス/スマートフォン用クラスを呼び分けるための実装を行います。

start.curlファイルにあるstartupプロシージャ(block-layout-thresholdsパラメータ)にて定義します。

 

【ソースコード】

{startup
    SmartphoneMenuScreen,  ||①起動時のスクリーンクラス 
    block-layout-thresholds =
        {BlockLayoutThresholds

            ||② 画面サイズとサイズ設定の名前の定義
            “SMART_PHONE_size”, 0px,    ||A
            “TABLET_size”, 768px,        ||B

            ||③ 起動時のスクリーンクラス①に対する実際に動作するタブレット/スマートフォン用のスクリーンクラス
            “COM.CURL.CAEDE.RESPONSIVE-SAMPLE.SmartphoneMenuScreen”||C
            {{HashTable-of String, String}
                “SMART_PHONE_size”, “COM.CURL.CAEDE.RESPONSIVE-SAMPLE.SmartphoneMenuScreen”, ||D
                “TABLET_size”,      “COM.CURL.CAEDE.RESPONSIVE-SAMPLE.TabletScreen”                       ||E

            }
        }
}

上記コード①

 通常のCaedeアプリケーションフレームワーク利用時のロジックと同様に起動時スクリーンクラスを定義します。

 

上記コード②

 アプリケーション起動時のデバイスの横幅サイズが0px~767pxの場合、スマートフォン用のクラス(SMART_PHONE_size):A

 アプリケーション起動時のデバイスの横幅サイズが768pxの場合、タブレット用のクラス(TABLET_size):B

として判定され、動作します。

 

上記コード③

 起動時のスクリーンクラスとして定義したSmartphoneMenuScreen(①)の

  ”COM.CURL.CAEDE.RESPONSIVE-SAMPLE.SmartphoneMenuScreen”(C)

対して、

SMART_PHONE_sizeと判定された場合、

  ”COM.CURL.CAEDE.RESPONSIVE-SAMPLE.SmartphoneMenuScreen”(D)

TABLET_sizeと判定された場合、

  ”COM.CURL.CAEDE.RESPONSIVE-SAMPLE.TabletScreen”(E)

が起動するように定義しています。

 ※C,D,Eは 完全修飾クラス名で指定します。

 

 


 

サンプル

ダイナミックレイアウトに関するサンプル(テンプレート)は、Caede Development Toolsをお使い場合、Caedeプロジェクト作成時のテンプレートとして、さまざまなパターンを用意しておりますので、こちらを参考にすることができます。

 

 

APIの説明・サンプル(グリッド)

Caede2.1.0にてグリッド用の関連APIが提供されました。

対応API

+ テーブル本体
  SimpleDataTable

+テーブルに登録する行のオブジェクト
  SingleSimpleDataRow
 CompoundSimpleDataRow
 ※CompoundSimpleDataRowは複数行にまたがるセル(rowspan)を設定するに使用

+行オブジェクトに登録するセルのオブジェクト
  SimpleDataTableContent
 ※ボタン、チェックボタン、画像を指定する際に使用

+テーブルに登録する列のオブジェクト
  SimpleDataColumn
 ※列単位で背景色やボーダを指定する際に使用します。

+ テーブル本体がフィールドとして持つ、行と列のコレクション
  SimpleDataColumnCollection
  SimpleDataRowCollection

 ※SimpleDataTableの行列を管理するコレクションのフィールド名
  header-rows、footer-rows、rows、columns

+イベント
  SimpleDataCellTap
  SimpleDataRowTap
  SimpleDataRowTapHold

+RecordSetとの結合
  SimpleDataConnecter

 

実行イメージ

caede21-grid1.jpg

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ソースコード(SimpleDataTableの定義)

グリッドはSimpleDataTableクラスを用いて実装します。

通常、レイアウト部分のクラスは Graphicクラスに定義しますが、SimpleDataTableでは、Screenクラスにて定義します。

SimpleDataTableにイベントも定義可能です。

||
|| レイアウト部分
|| Graphicクラス(GridGraphic)
||

{define-class public GridGraphic {inherits Frame}
  {constructor public {default}
    {construct-super
        {VBox
            halign = “center”,
            width = {make-elastic preferred-size = 1m},
            || Header
            {HBox
                valign = “center”,
                width = {make-elastic},
                height = 70px,
                margin = 5px,
                background = “#232323”,
                {TextFlowBox
                    name = “tflb-001”,
                    color = “red”,
                    “伝票番号”
                },
                {Fill width = 30px},
                {TextField
                    name = “kensakukey01”
                },
                {Fill width = 15px},
                {CommandButton
                    name = “cb1”,
                    height = 70px,
                    width = 200px,
                    label = “検索(SingleSimpleDataRow)”
                },
                {CommandButton
                    name = “cb2”,
                    height = 70px,
                    width = 200px,
                    label = “検索(CompoundSimpleDataRow)”
                },
                {Fill}
            },
            || Body(グリッドを格納する部分)
            {VBox
                halign = “center”,
                background = “#f3f3f3”,
               
                {VBox
                    name = “vb-result-list”
                }
            }
        }
    }
  }
}

||
|| ロジック部分
|| Screenクラス(GridScreen)
||

{define-class public GridScreen {inherits {Screen-of GridGraphic}}
 
  {constructor public {default}
   
    def cb1 = {self.find-graphic-by-name “cb1”} asa CommandButton
    def cb2 = {self.find-graphic-by-name “cb2”} asa CommandButton
    def vb-result-list = {self.find-graphic-by-name “vb-result-list”} asa VBox

    || SimpleDataTable
    def simple-data-table = {SimpleDataTable
                                name = “sdt1”,
                                width =
                                    {make-elastic
                                        minimum-size = 10cm,
                                        preferred-size = 1m
                                    },
                                height =
                                    {make-elastic
                                        minimum-size = 10cm,
                                        preferred-size = 1m
                                    }
                                ,{on e:SimpleDataCellTap do
                                     {dump                                      
                                         “SimpleDataCellTap”,
                                         e, ” “, e.row, ” “, e.internal-row-index,
                                         ” “, {simple-data-table.rows.find e.row}}
                                    
                                     {show-toast “SimpleDataCellTap”}
                                     {popup-message “SimpleDataCellTap”}
                                    
                                 },
                                {on e:SimpleDataRowTap do
                                    {dump
                                        “SimpleDataRowTap”,
                                        e, ” “, e.row, ” “, e.internal-row-index,
                                        ” “, {simple-data-table.rows.find e.row}}
                                   
                                    {show-toast “SimpleDataRowTap”}
                                    {popup-message “SimpleDataRowTap”}
                                   
                                },
                                {on e:SimpleDataRowTapHold do
                                    {dump
                                        “SimpleDataRowTapHold”,
                                        e, ” “, e.row, ” “, e.internal-row-index,
                                        ” “, {simple-data-table.rows.find e.row}
                                    }
                                    {show-toast “SimpleDataRowTapHold”}
                                    {popup-message “SimpleDataRowTapHold”}
                                }
                            }

            {self.create-colums simple-data-table}
            {self.create-header-row simple-data-table}

  {method private {create-header-row simple-data-table:SimpleDataTable}:void
    || Header
    def header-row = {SingleSimpleDataRow
                         height = {any-to-Distance 50px},
                         border-width = 1px,
                         background = “#68665c”
                     }
   
    {header-row.set-cell
        1,
        border-width = 1px,
        {String “コード”}
    }
    {header-row.set-cell
        2,
        border-width = 1px,
        {String “商品名”}
    }
    {header-row.set-cell
        3,
        border-width = 1px,
        {String “画像”}
    }
    {header-row.set-cell
        4,
        border-width = 1px,
        {String “詳細”}
    }
    {simple-data-table.header-rows.append header-row}
   
  }
 

||
|| 行の定義
|| SimpleDataColumn
||

  {method private {create-colums simple-data-table:SimpleDataTable}:void
    {simple-data-table.columns.append
        {SimpleDataColumn
            width = 40px,
            border-color = “#cccccc”,
            border-width = 1px
        }
    }
    {simple-data-table.columns.append
        {SimpleDataColumn
            width = 300px,
            border-color = “#cccccc”,
            border-width = 1px
        }
    }
    {simple-data-table.columns.append
        {SimpleDataColumn
            width = 300px,
            border-color = “#cccccc”,
            border-width = 1px
        }
    }
    {simple-data-table.columns.append
        {SimpleDataColumn
            width = 20px,
            border-color = “#cccccc”,
            border-width = 1px
        }
    }
  }
   
}

 

 ソースコード(データ表示ロジック) 単一行オブジェクト

以下のコードのように、SimpleDataTableContentクラスを用いるこでセルのコンテンツを定義可能です。

また、SimpleDataTableContent.check-buttonなど、一部のコンテンツでは、セルのコンテンツ定義時にイベント(プロシージャ)を定義可能です。

    ||
    ||SingleSimpleDataRow
    ||

    {cb1.add-event-handler
        {on Action do
            {for i = 0 below 30 do

                ||単一行オブジェクト
                def test-row-0 = {SingleSimpleDataRow}

                ||セルコンテンツ(チェックボタン)
                {test-row-0.set-cell
                    0,
                    border-width = 1px,
                    halign = “center”,
                    {SimpleDataTableContent.check-button
                        “”,
                        {proc {b:bool}:void
                            {popup-message “チェックボタンが押下されました。:” & {String b}}
                        }
                    }
                }

                ||セルコンテンツ(文字列)
                {test-row-0.set-cell
                    1,
                    border-width = 1px,
                    {String “ISU-XXXX” & i}
                }
                {test-row-0.set-cell
                    2,
                    border-width = 1px,
                    {String “木材の椅子 “}
                }

                ||セルコンテンツ(画像)
                {test-row-0.set-cell
                    3,
                    {SimpleDataTableContent.image
                        {{manifest-url “directory”, “image”}.concat
                            “isu.png”}
                    }
                }

                ||セルコンテンツ(ボタン)
                {test-row-0.set-cell
                    4,
                    border-width = 1px,
                    {SimpleDataTableContent.button
                        “詳細”,
                        {proc {}:void
                            {popup-message “ボタンが押下されました。”}
                        }
                    }
                }
                {simple-data-table.rows.append test-row-0}
            }
        }
    } 
    
  
  

 

 

   ソースコード(データ表示ロジック) 複数行オブジェクト

 複数行オブジェクトも実装可能です。

実行イメージ

  caede21-grid-span.jpg

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 ソースコード

 CompoundSimpleDataRow クラスを用いることにより複数行に結合セルを定義することが可能です。 

    ||
    ||CompoundSimpleDataRow
    ||

    {cb2.add-event-handler
        {on Action do
           
            def data-cols = 4
            def internal-row-num = 3
           
            {for i = 0 below 10 do

                ||複数行オブジェクト
                def test-row-0 = {CompoundSimpleDataRow internal-row-num}
               
                set test-row-0.height = 0.5in
                set test-row-0.border-color = “gray”
                set test-row-0.border-style = “flat”
                set test-row-0.border-width = {OffsetSpec 1px, 0px, 1px, 0px}
               
                ||
                ||rowspanを使った設定
                ||
                {test-row-0.set-cell
                    0,
                    0,
                    rowspan = internal-row-num,
                    {String “[” & i & “,0,0,rspan=3]”},
                    background = “red”,
                    font-weight = “bold”,
                    font-size = 18pt,
                    halign = “center”
                }
               
                {test-row-0.set-cell
                    0,
                    1,
                    rowspan = 2,
                    {String “[” & i & “,0,1,rspan=2]”},
                    background = “blue”,
                    font-weight = “bold”,
                    font-size = 18pt,
                    halign = “center”
                }
               
                {test-row-0.set-cell
                    1,
                    2,
                    rowspan = 2,
                    {String “[” & i & “,1,2,rspan=2]”},
                    background = “yellow”,
                    font-weight = “bold”,
                    font-size = 18pt,
                    halign = “center”
                }
               
                ||
                ||内部の行毎の処理
                ||

                {for j = 0 below internal-row-num do
                    def fixed-j = j
                    {test-row-0.set-cell
                        j,
                        3,
                        {String “[” & i & “,” & j &”,i-rnum=3]”},
                        background = “green”,
                        halign = “center”
                    }
                    {test-row-0.set-cell
                        j,
                        4,
                        {SimpleDataTableContent.check-button
                            “”,
                            {proc {b:bool}:void
    
                            }
                        },
                        halign = “center”
                    }
                   
                    ||
                    ||内部の行毎、列毎の処理
                    ||

                    {for c = 5 to (data-cols + 2) do
                        {test-row-0.set-cell
                            j,
                            c,
                            {String “[” & i & “,” & j &”,i-rnum=” & c &”]”},
                            font-style = “italic”,
                            color = “blue”,
                            halign = “center”
                        }
                    }
                   
                    ||
                    ||colpanを使った設定
                    ||
                    {if j == 0 then
                        {test-row-0.set-cell
                            j,
                            data-cols + 3,
                            {String “[” & i & “,” & j & “,” & data-cols + 3 &”]”},
                            font-style = “italic”,
                            background = “red”,
                            halign = “center”
                        }
                        {test-row-0.set-cell
                            j,
                            data-cols + 3 + 1,
                            {String “[” & i & “,” & j & “,” & data-cols + 3 + 1 &”]”},
                            font-style = “italic”,
                            background = “red”,
                            halign = “center”
                        }
                        {test-row-0.set-cell
                            j,
                            data-cols + 3 + 2,
                            {String “[” & i & “,” & j & “,” & data-cols + 3 + 2 &”]”},
                            font-style = “italic”,
                            background = “red”,
                            halign = “center”
                        }
                     elseif j == 1 then
                        {test-row-0.set-cell
                            j,
                            data-cols + 3,
                            {String “[” & i & “,” & j & “,” & data-cols + 3 &”]”},
                            font-style = “italic”,
                            background = “red”,
                            halign = “center”
                        }
                        {test-row-0.set-cell
                            j,
                            data-cols + 3 + 1,
                            colspan = 2,
                            {String “[” & i & “,” & j &”,cspan=” & 2 &”]”},
                            font-style = “italic”,
                            background = “pink”,
                            halign = “center”
                        }
                     else
                        {test-row-0.set-cell
                            j,
                            data-cols + 3,
                            colspan = 3,
                            {String “[” & i & “,” & j &”,cspan=” & 3 &”]”},
                            font-style = “italic”,
                            background = “green”,
                            halign = “center”
                        }
                    }
                   
                  
                }
                {simple-data-table.rows.append test-row-0}
            }
        }
    }
   
    {vb-result-list.add
        simple-data-table
    }
   
  }
  

 

  

 

SimpleDataConnectorを使ったRecordSetとの結合

Curlと同様にRecordSetを使うことも可能です。

ソースコード

||
|| RecordSetを使ったサンプル
||

    {cb1.add-event-handler
        {on Action do
            def record-set =
                {RecordSet
                    {RecordFields
                        {RecordField
                            “First”, caption = “First Name”, domain = String
                        },
                        {RecordField
                            “Last”, caption = “Last Name”, domain = String
                        },
                        {RecordField
                            “Age”, domain = int
                        }
                    },
                    {RecordData First = “John”, Last = “Smith”, Age = 25},
                    {RecordData First = “Jane”, Last = “Smith”, Age = 29},
                    {RecordData First = “Jane”, Last = “Jones”, Age = 28}
                }
           
            def connector = {SimpleDataConnector record-set, simple-data-table}
        }
       
    }
   
    {vb-result-list.add
        simple-data-table
    }