APL標準コマンド(キャラクターディスプレイ)
キャラクターディスプレイでは、Pagerでの作業用やコンポーネントプロパティ値の変更用として、ごく一部の標準コマンドがサポートされます。APLコマンド全般の動作については、APLコマンドを参照してください。
共通プロパティ
1つのコマンドは1つのJSONオブジェクトとしてエンコードされます。どのAPL-Tコマンドにも次の共通プロパティがあります。
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
type | 文字列 | 必須 | コマンドの型です。 |
description | 文字列 | "" | このコマンドのオプションのドキュメントです。 |
delay | 整数 | 0 | このコマンドが実行されるまでの遅延時間(ミリ秒単位)です。負以外の値にする必要があります。 |
screenLock | ブール値 | false | trueの場合、interaction_timer を無効にします。 |
when | ブール値 | true | 条件式です。評価結果がfalseの場合、コマンドをスキップします。 |
type
特定のコマンドを実行するように指定します。定義済みのプリミティブコマンドタイプやユーザー定義コマンドを使用することもできます。
delay
delayはこのコマンドが実行される前に挿入されるミリ秒単位の時間です。delayは負以外の値にする必要があります。指定されない場合、delayのデフォルトは0です。コマンドのwhen
プロパティがfalseに解決された場合、delayの値は無視されます。また、コマンドがイベントハンドラー内部で実行された場合も、delayは無視されます。
screenLock
screenLockプロパティは、APL-Tドキュメントのlifecycle_section
に適用されます。trueの場合、このコマンドが実行されている間、interaction_timer
が無効になります。screenLock=true
のコマンドの実行が終了すると、interaction_timer
はゼロにリセットされます。
screenLockは、定義されたdelay
を含むコマンドの範囲全体に適用されます。たとえば、次のコマンドは画面ロックを30秒間保持します。
{
"type": "Idle",
"delay": 30000,
"screenLock": true
}
when
trueの場合、コマンドが実行されます。falseの場合、コマンドは無視されます。無視されたコマンドもscreenLock
プロパティを無視します。
AutoPageコマンド
Pagerコンポーネントの連続するページを自動的に進めて表示させます。AutoPageコマンドは、リクエストされた時間内で最終ページを表示した後に終了します。AutoPageコマンドには、標準的なコマンドプロパティに加えて以下のプロパティがあります。
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
componentId | 文字列 | SELF | コンポーネントのIDです。 |
count | 整数 | <ALL> | 表示するページ数です。デフォルトは全ページです。 |
duration | 整数 | 0 | ページ間で待機する時間です(ミリ秒単位)。 |
たとえば、sports pagerで自動的に次ページを表示するには次のようにします。
{
"type": "AutoPage",
"componentId": "mySportsPager",
"delay": 500,
"duration": 1000
}
上記の例では、最初に500ミリ秒間一時停止(delayプロパティ)します。その後、次のページに進んで1000ミリ秒間一時停止(durationプロパティ)し、最後の一時停止が終了するまで、引き続きページを変えては一時停止します。この例のPagerが3ページあり、最初のページから開始した場合、AutoPageコマンドでは、500ミリ秒間の一時停止、2ページ目の表示、1000ミリ間秒の一時停止、3ページ目の表示、最後に1000ミリ秒間の一時停止を順に行います。
countが正の数でない場合、AutoPageコマンドを実行しても何も起きません。
AutoPageコマンドの終了時に、AutoPageコマンドシークエンスが50%以上完了していればターゲットページに進み、50%未満の場合は前のページに戻ります。onPageChangeコマンドは、ページが変更された場合に新しいページで1回実行されます。
AutoPageコマンドは、高速モードでは無視されます。
componentId
PagerコンポーネントのIDです。省略すると、AutoPageコマンドを発行するコンポーネントが使われます。
count
表示するページ数です。指定しない場合、このデフォルトは残りのページ数となります。ラッピングには対応していません。値は最小値が0、最大値がpager.children.length – pager.currentIndex – 1の範囲に収まるように調整されます。
duration
次のページに進んだ後に待機する時間です。ページ間のアニメーション遷移は時間に含まれないため、コマンドの実行時間が全体的に長くなります。
Idleコマンド
Idleコマンドを実行しても何も起きません。これはプレースホルダーになっているか、長い一連のコマンドに計算された遅延を挿入するために使用されます。たとえば、次のコマンドを考えてみましょう。
{
"type": "Sequential",
"commands": [
{
"type": "SetValue",
"componentId": "myText",
"property": "text",
"value": "Hi"
},
{
"type": "Idle",
"delay": 3000
},
{
"type": "SetValue",
"property": "myText",
"value": "you"
}
]
}
このコマンド例では、idが「myText
」と等しいText
コンポーネントのテキスト「Hi」が3秒間表示されてから、テキストが「you」に切り替わります。
Idleコマンドの型は「Idle」です。Idle
コマンドに共通のコマンドプロパティ以外のプロパティはありません。
Parallelコマンド
一連のコマンドを並列に実行します。Parallelコマンドはすべての子コマンドを同時に実行開始します。Parallelコマンドは、すべての子コマンドが終了したときに実行完了と見なされます。Parallelコマンドが早く終了すると、その時点で実行中のコマンドはすべて終了します。
Parallelコマンドの型は「Parallel」です。Parallelコマンドには、共通のコマンドプロパティに加えて以下のプロパティがあります。
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
commands | コマンドの配列 | 必須 | 並行して実行する順序不同のコマンドのリストです。 |
高速モードでは、parallelコマンドはすべてのサブコマンドを並列に実行しますが、遅延が発生することはありません(実質的な時間はゼロです)。
commands
並行して実行する順序不同のコマンド配列です。すべてのコマンドの実行が終了すると、Parallelコマンドは終了します。Parallelコマンドの遅延と、各コマンドの遅延は累積で加算されます。次の例のようなコマンドについて考えてみましょう。
{
"type": "Parallel",
"delay": 500,
"commands": [
{
"type": "SetValue",
"delay": 1000
},
{
"type": "SetValue",
"delay": 250
}
]
}
上記のコマンドでは、最初のSetValueは1500ミリ秒後に、2番目は750ミリ秒後(最初のSetValueよりも前)に実行されます。
Sequentialコマンド
Sequentialコマンドは、一連のコマンドを順番に実行します。前のコマンドが終了するのを待ってから、次のコマンドを実行します。Sequentialコマンドは、すべての子コマンドが終了すると完了します。
Sequentialコマンドの型は「Sequential」です。Sequentialコマンドには、共通のコマンドプロパティに加えて以下のプロパティがあります。
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
catch | コマンドの配列 | [] | このシークエンスが途中で終了した場合に実行する、順番に並んだコマンドのリストです。 |
commands | コマンドの配列 | 必須 | 連続して実行する順番に並んだコマンドのリストです。 |
finally | コマンドの配列 | [] | 通常のコマンドとcatchコマンドの後に実行する、順番に並んだコマンドのリストです。 |
repeatCount | 整数 | 0 | これらのコマンドを追加で実行する回数です。 |
Sequentialコマンドは次のアルゴリズムで実行されます。
function executeSequential(command, mode):
if mode == "normal":
for (i = 0 ; i <= repeatCount ; i++):
for cmd in command.commands:
execute cmd
wait for cmd to finish
if cmd was terminated:
return doCatch()
elif mode == "fast":
for cmd in commands:
fastExecute cmd
return doFinally(mode)
function doCatch():
for cmd in command.catch:
fastExecute cmd
return doFinally("fast")
function doFinally(mode):
for cmd in command.finally:
if mode == "normal":
execute cmd
wait for cmd to finish
if cmd was terminated: // 高速モードに切り替え
mode = "fast"
elif mode == "fast":
fastExecute cmd
このアルゴリズムには次のような特徴があります。
- 通常モードでは、commandsは順番に実行され、その後にfinallyコマンドが続きます。repeatCountは通常のコマンドにのみ適用されます。
- 高速モードでは、commandsは繰り返さずに順番に実行され、その後にfinallyコマンドが続きます。
- commandsのいずれかが先に(通常モードで)終了した場合、catchコマンドとfinallyコマンドは高速モードで実行されます。
- 通常モードでの実行中にfinallyコマンドのいずれかが終了した場合、残りのfinallyコマンドは高速モードで実行されます。
catch
他のコマンドが実行されたことでsequentialコマンドが終了した場合、catchコマンドが実行されます。catchコマンドは「高速」モードで実行されます。すべてのdurationは無視され、各コマンドはdurationで指定した時間の最終値までジャンプします。catchコマンドは、finallyコマンドの前に実行されます。
catchコマンドは1回しか実行されません。repeatCountプロパティは、catchコマンドには適用されません。
commands
実行するコマンド配列です。コマンドは順番に実行され、各コマンドが終了しない限り次のコマンドは開始されません。Sequentialコマンドの遅延とシーケンスの最初のコマンドの遅延は、それぞれ加算されることに注意してください。次の例のようなコマンドについて考えてみましょう。
{
"type": "Sequential",
"delay": 1000,
"repeatCount": 2,
"commands": [
{
"type": "SetValue",
"delay": 2000
},
{
"type": "SetValue",
"delay": 2000
}
]
}
上記の例では、最初のSetValueが3000ミリ秒後に実行されます。
finally
finallyコマンドは、通常のsequentialコマンドが終了した後、または早期終了によりcatchコマンドが実行された後に実行されます。(a)sequentialコマンド全体が高速モードで実行された場合、または(b)sequentialコマンドが早く終了した場合を除き、finallyコマンドは通常モードで実行されます。
finallyコマンドは1回しか実行されません。repeatCountプロパティは、finallyコマンドには適用されません。
repeatCount
この一連のコマンドを繰り返す回数です。デフォルトは0です。負の値は無視されます。
Sequentialコマンド全体に割り当てられた遅延は初回だけ適用されることに注意してください。たとえば、前のセクションのサンプルのSequentialコマンドでは、最初のSetValueが3000ミリ秒後に実行、次のSetValueは5000ミリ秒後に実行、最初のSetValueがもう一度7000ミリ秒後に実行、という具合に続きます。
SetPageコマンド
Pagerコンポーネントで表示されるページを変更します。SetPageコマンドは、項目全体が表示されると終了します。SetPageコマンドには、標準的なコマンドプロパティに加えて以下のプロパティがあります。
プロパティ | 型 | デフォルト | 説明 | |
---|---|---|---|---|
componentId | 文字列 | SELF | コンポーネントのIDです。 | |
position | relative | absolute | absolute | 値は相対補正値か絶対補正値のいずれかです。 |
value | 整数 | 必須 | 移動距離です。絶対値または相対値で指定できます。 |
PagerにNページある場合、トップページのインデックスは0で、最後のページのインデックスはN-1となります。相対位置の場合、現在のページを基準にして移動します。たとえば、1ページ先に進めるには次のようにします。
{
"type": "SetPage",
"componentId": "myWeatherPager",
"position": "relative",
"value": 1
}
絶対位置の場合、現在のページにインデックスが付けられます。負の絶対位置はリスト末尾からのオフセットです。たとえば、最後のページに移動するには次のようにします。
{
"type": "SetPage",
"componentId": "myWeatherPager",
"position": "absolute",
"value": -1
}
2ページ間で切り替える場合、間のページは表示されません。たとえば現在のページが3ページで、SetPageをposition="relative"、value=-2で実行した場合、2ページは表示しないで3ページから1ページに移動します。
SetPageコマンドはあらゆるページを表示するように設定できます。Pagerコンポーネントで許可された移動方向は考慮されません。 ただし、ラップ動作はページ切り替えの計算に影響します。valueセクションを参照してください。
SetPageコマンドの終了時に、SetPageコマンドシークエンスが50%以上完了していればターゲットページにジャンプし、50%未満の場合は前のページに戻ります。onPageChangeコマンドは、ページが最終ページから変更された場合に終了時に1回実行されます。
SetPageコマンドは、高速モードでは無視されます。
componentId
PagerコンポーネントのIDです。省略すると、SetPageコマンドを発行するコンポーネントが使われます。
position
positionが「relative」の場合、valueは現在のページから移動する相対的なページ数を指定します。positionが「absolute」の場合、valueは絶対値で表される移動先のページ番号を指定します。
value
移動するページ数か、絶対値で表される移動先のページ番号のいずれかです。
最終的な位置と向きを計算するアルゴリズムの概要は以下のとおりです。
if (command.position == 'absolute') { // 絶対値での移動
let index = command.value < 0 ? pager.children.length + command.value : command.value;
index = Math.max(0, Math.min(pager.children.length – 1, index)); // 範囲を固定
// 最後のインデックスと移動の方向を返します。
if (index == pager.currentIndex)
return NO_MOVE
return (index, index < pager.currentIndex ? "LEFT" : "RIGHT");
}
else { // 相対値の移動
let index = pager.currentIndex + command.value;
// 相対値の移動が範囲外になり、ラッピングに対応していない場合、コマンドは無視されます
if (pager.navigation != "wrap" && (index < 0 || index >= pager.children.length))
return NO_MOVE;
// 適切にラップする
index = ((index % pager.children.length) + pager.children.length) % pager.children.length;
if (index == pager.currentIndex)
return NO_MOVE;
return (index, command.value < 0 ? "LEFT" : "RIGHT");
}
Pagerアニメーションは返された方向に動きます。
このアルゴリズムにはいくつか特徴があります。
- 絶対値は有効なページの範囲内に固定されます。directionは現在のページと相対的な方向になります。
- ラッピングしているPagerの相対値は任意にラップします。directionはコマンドで与えられた値によって決まります。ラッピングでは方向は変更されません。
- ラッピングしていないPagerの相対値は、値が範囲外の場合は無視されます。
SetValueコマンド
コンポーネントのプロパティまたはバインディングを変更します。各コンポーネントには設定可能な動的プロパティのセットが定義されています。各コンポーネントでは、名前付きバインディングも使用できます。設定可能な値については、各コンポーネントの仕様を参照してください。
SetValueコマンドには、標準的なコマンドプロパティに加えて以下のプロパティがあります。
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
componentId | 文字列 | SELF | 値を設定する必要があるコンポーネントのIDです。 |
property | 文字列 | 必須 | 設定するプロパティの名前です。 |
value | 任意 | 必須 | プロパティに設定する値です。 |
たとえば、ジョークのオチを表示する場合は以下のとおりです。
{
"type": "SetValue",
"componentId": "jokePunchline",
"property": "text",
"value": "反対側に渡るため。"
}
SetValueコマンドでは、コンポーネントのプロパティの値またはコンポーネントのバインディングが変更されます。次のルールが適用されます。
- コンポーネントに、propertyで指定された名前を持つ動的なプロパティがある場合、そのプロパティが更新され、新しい値が設定されます。
- そうでない場合、その名前を持つ
bind
プロパティがコンポーネントにある場合、そのバインドされているプロパティが更新されます。 - バインドされているプロパティの値が変わると、そのプロパティに依存しているコンポーネントの動的なプロパティはすべて更新されます。
バインドしている値の更新の例を以下に示します。
{
"type": "Container",
"bind": [
{
"name": "MyCounter",
"value": 0,
"type": "number"
}
],
"item": {
"type": "Text",
"text": "Ct:${MyCounter}"
},
"onMount": {
"type": "Sequential",
"repeatCount": 10,
"commands": [
{
"type": "SetValue",
"delay": 500,
"property": "MyCounter",
"value": "${value + 1}"
}
]
}
}
上記の例では、カウンターを500ミリ秒ごとに、カウントが10になるまで増分していきます。
SetValueコマンドは、遅延なしに高速モードで実行されます。
componentId
値が変更されるコンポーネントのIDです。このプロパティが省略された場合、SetValueコマンドを発行するコンポーネントが受け取り側となります。
property
変更されるプロパティの名前です。ビルトインのプロパティまたはバインディングを指定できます。
value
valueはコマンドの実行時に評価されます。そのため、既存のコンポーネントのプロパティを活用できます。次に例を示します:
{
"type": "SetValue",
"property": "MyCounter",
"value": "${value + 1}"
}
このコマンドにより、Containerにバインドされているカウンターであるターゲットコンポーネントの値が増分されます。