Framing Gallery
以下は、Mac OS X 10.4.11 上の Xcode 2.5 で説明しています。BlankWidgetで解説したことは繰り返しませんので、そちらを参照してください。また、このサンプルで使われている Apple クラスのうち Animator は Stretcher で説明したので、その部分も繰り返しません。また、AppleButton と AppleInfoButton は、Fader で説明しています。
1 ウィジェット
Framing Gallery.wdgt をインストールすると、以下のような画面が表示されます。
ここで、「Flaming Gallery」という文字列が表示されている場所にマウスカーソルを移動させると、「Drag an image, show Dashboard, and drop it here.(画像をドラッグし、ダッシュボードを表示し、それをここにドラップしてください。)」というツールチップが表示されます。ドラッグしたまま、F12キーを押しダッシュボードを表示させ、ドロップします。このとき、マウスボタンは押したままです。サンプルでよく使われているマンドリルの画像をドロップしてみると、以下のようになります。
このようにドロップされた画像が表示されます。さらに、この画像はコンピューターを終了し、再び起動してダッシュボードを起動しても、そのまま表示されます。したがって、画像の情報が何らかの形で保存されていることがわかります。
「i」ボタンを押して裏面を表示させると、以下のようになります。
「Frame(枠)」では、まわりを囲む枠の色を指定できます。「Mat(マット・敷物)」では、画像と枠の間に表示される背景の色を指定できます。これらの設定もずっと保存されます。
2 ファイル構成
このサンプルのファイル構成は以下のようになります。
AppleClasses 内には、AppleAnimator.js、AppleButton.js、AppleInfoButton.js という 3 つの JavaScript ファイルがあります。Apple クラスの組み込みと Info.plist、そして AppleAnimator.js については、Stretcher を見てください。また、AppleButton.js、AppleInfoButton.js については、Fader を見てください。主要 HTML は FramingGallery.html に指定されています。
Default.png は、ウィジェットの背景が含まれている画像です。「Flaming Gallery」という文字列も画像内に含まれています。dnd.png は、マウスカーソルを移動させると表示されるツールチップ画像です。hanger.png は、裏面の環境設定を表示させたときに一番上に表示される画像です。kraft.jpg は裏面の背景を埋めている画像です。Splash.gif は、Dafault.png の中央部分のみの画像です。
CSS ファイルは FramingGallery.css です。スクリプトファイルは、Apple クラスを除けば、 FramingGallery.js です。
3 FramingGallery.html
それでは、主要 HTML ファイルを見てみます。
FramingGallery.html
<html>
<head>
<!-- スタイルシートのインクルード。HTMLからCSSを分離することは設計をローカル化することを可能にする。
これはより面倒な言語に対して便利。-->
<style type="text/css">
@import "FramingGallery.css";
</style>
<!-- ここでウィジェットのJavaScriptファイルをインクルード。JavaScriptは論理を提供。-->
<script type='text/javascript' src='FramingGallery.js' charset='utf-8'/>
<!-- 10.4.3 より前との互換性:
ウィジェットの一番上に AppleClass ディレクトリを含め、相対パスを使用 -->
<script type='text/javascript' src='AppleClasses/AppleButton.js' charset='utf-8'/>
<script type='text/javascript' src='AppleClasses/AppleInfoButton.js' charset='utf-8'/>
<script type='text/javascript' src='AppleClasses/AppleAnimator.js' charset='utf-8'/>
</head>
<!-- ウィジェット本体。ここでウィジェットユーザーインターフェースの様々な部分を詳述。
このウィジェットには2つの部分がある。フレームとマットを伴う画像、そして環境設定。-->
<body onload="setup();" >
<!-- 前面divまたはレイヤーは、ウィジェットの主要なユーザーインターフェースを提供。
マウスがウィジェット上にある時、DnDインジケータを表示するために使われる、
2つのイベントハンドラonmousemoveとonmouseoutをもつ。-->
<div id="front" onmouseover="fadeIn();" onmouseout="fadeOut();">
<!-- フレームとマットの効果を作るために5つの<div>タグが使われている。-->
<div class="outsideEdge">
<div id="frame">
<div class="middleEdge">
<div id="mat">
<div class="insideEdge">
<!-- 「picture」画像は、ユーザーに表示される主要ピクチャー。-->
<!-- これはさまざまなドラッグ操作に対するイベントハンドラを含む。-->
<img id="picture" src="Images/Splash.gif"
ondragenter='dragenter(event);' ondragover='dragover(event);'
ondrop='dragdrop(event)' ondragleave='dragleave(event)'>
</div>
</div>
</div>
</div>
</div>
<!-- 以下のdivはマウスが上にある時ウィジェットの右下に提示される情報ボタンを含む。
onloadハンドラはアートワークと動作を提供するコンストラクタを含む。-->
<div id='infoButton'></div>
<!-- ドラッグ&ドロップインジケーターは、ユーザーに、
ウィジェットにファイルをドロップできることを知らせる親切な視覚的なヒント。
これは標準、または必須ではないが、あると良い。-->
<img id='dndindicator' src='Images/dnd.png'>
<!-- 隠されたピクチャーはサイズ変更関数に画像サイズ情報を提供するために使われる。
この不透明度はスタイルシート内でゼロに設定されていて、そのため目に見えない。-->
<img id="hiddenPic" src="Images/Splash.gif">
</div>
<!-- 環境設定レイヤーはフレームとマットを選ぶインターフェースを提供し、
環境設定を終了させ、ピクチャを返す「done(完了)」ボタンを提供する。-->
<div id="back">
<div id="prefBox">
<!-- のこぎり状ハンガーはスタイル的な要素で、ほとんどの絵の背面でも見つかる。-->
<span id="hanger"><img src="Images/hanger.png"></span>
<!-- フレームポップアップメニューは、いくつかのフレーム選択と
メニューを変更するためのイベントハンドラを提供する。-->
<span id="frameText">Frame:</span>
<select id='framePopup' onchange='changeFrame(this);'>
<option value=1>Black</option>
<option value=2>Rosewood</option>
<option value=3>Oak</option>
<option value=4>Pine</option>
<option value=5>Gold</option>
</select>
<!-- マットポップアップメチューは、マット色の選択と
メニューを変更するためのイベントハンドラを提供する。-->
<span id="matText">Mat:</span>
<select id='matPopup' onchange='changeMat(this);'>
<option value=1>Arctic White</option>
<option value=2>Venetian Red</option>
<option value=3>Navy Blue</option>
<option value=4>Hunter Green</option>
<option value=5>Pumpkin Orange</option>
<option value=6>Royal Purple</option>
<option value=7>Sunset Yellow</option>
<option value=8>Raven Black</option>
</select>
<!-- 「Done」ボタンは環境設定を終了させる。-->
<!-- 以下のdiv は「Done」ボタンを含む。
onloadハンドラはアートワークと動作を提供するコンストラクタを含む。-->
<div id="doneButton"></div>
</div>
</div>
</body>
</html>
かなりくわしいコメントが書かれているので、だいだいわかると思います。どのような要素があるか、どれにハンドラが設定されているか、ということに注意してください。
4 FramingGallery.css
つぎにスタイルシートを見てみます。
FramingGallery.css
...
#hiddenPic {
opacity: 0.0;
}
...
#back {
display: none;
...
background-image: url("Images/kraft.jpg");
}
...
#dndindicator {
position: absolute;
opacity: 0.0;
}
表面については、各divに境界線や色などが設定されています。ここでは、注意しておく部分だけを掲載しました。実際の CSS についてはファイルを見てください。背面は最初表示されません。また、ツールチップも不透明度が 0.0 で目に見えないようになっています。
5 FramingGallery.js
5.1 グローバル変数と関数外コード
FramingGallery.js を見てみます。このファイル内ではハンドラなどかなりさまざまな関数が定義されています。まず、このファイルが読み込まれた時に設定され実行される変数と関数外コードを調べておきます。
FramingGallery.js > グローバル変数と関数外コード
// JavaScript 関数を通じて使われるグローバル変数
var height = 0;
var width = 0;
var glassDoneButton; // ガラスボタンを参照する変数
var infoButton; // 情報ボタンを参照する変数
...
// 以下は、ウィジェット特有のハンドラが宣言できる。このウィジェットは1つだけ使う。
// これは、ウィジェットがダッシュボードから除去された時に呼び出される
if(window.widget)
{
widget.onremove = onremove;
}
...
var currentAnimator;
var currentAnimation;
var globalFrom = 0;
一番先頭にグローバル変数があります。2つめのブロック以降はファイルの後半にありますが、これは関数外なので、このスクリプトが読み込まれた時に実行され、ここでウィジェットとしてダッシュボード内で実行されている場合だけ、除去時のハンドラを設定しています。その後で、このファイルで内部的に使うローカルなグローバル変数を宣言しています。
除去時に設定されたハンドラ onremove を見てみます。
FramingGallery.js > onremove
// onremove は、このウィジェットが持っているかもしれない環境設定を消去する
function onremove()
{
widget.setPreferenceForKey(null,makeKey("image"));
widget.setPreferenceForKey(null,makeKey("frameTop"));
widget.setPreferenceForKey(null,makeKey("frameRight"));
widget.setPreferenceForKey(null,makeKey("frameBottom"));
widget.setPreferenceForKey(null,makeKey("frameLeft"));
widget.setPreferenceForKey(null,makeKey("matColor"));
widget.setPreferenceForKey(null,makeKey("flipitColor"));
}
除去された時には環境設定を消去するようにしています。setPreferenceForKey はウィジェットオブジェクト特有のメソッドで環境設定を保存します。最初の引数は値で、2番目はキーとして使う文字列です。こうして設定された値は、preferenceForKey(key) というメソッドで取り出すことができます。ここでは、makeKey というユーティリィティ関数を使ってキーを作成しています。
FramingGallery.js > makeKey
// このウィジェットは自身の複数のインスタンスを許容するので、
// それぞれが独自の環境設定を保存する必要がある。
// ダッシュボードは各ウィジェットにログインの間も維持される一意的な識別子を提供する。
// このラッパーは一意的な識別子と結び付けられたプロパティを提供する。
function makeKey(key)
{
return widget.identifier + "-" + key;
}
環境設定はウィジェットごとに保存されますが、複数のインスタンスがあっても同じファイル内に格納されます。このファイルは通常ユーザーのライブラリ > Preferences 内にプロパティリストの形で保存されます。このウィジェットを操作した後で、ここを見てみると widget-com.apple.widget.framinggallery.plist というファイルが保存されているのがわかると思います。ここに環境設定値が保存されています。このファイルはテキストではありませんが、プロパティリストエディタで開くことができます。XML 形式でダンプ出力させると以下のようになっています。
widget-com.apple.widget.framinggallery.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>41aa6cb258cb7953-flipitColor</key>
<string>white</string>
<key>41aa6cb258cb7953-frameBottom</key>
<string>rgb(3, 3, 3)</string>
<key>41aa6cb258cb7953-frameLeft</key>
<string>rgb(26, 27, 26)</string>
<key>41aa6cb258cb7953-frameRight</key>
<string>rgb(26, 27, 26)</string>
<key>41aa6cb258cb7953-frameTop</key>
<string>rgb(3, 3, 3)</string>
<key>41aa6cb258cb7953-image</key>
<string>file://localhost/Users/XXX/Desktop/mandrill.jpg</string>
<key>41aa6cb258cb7953-matColor</key>
<string>rgb(24, 61, 137)</string>
</dict>
</plist>
デスクトップにある画像をドロップしたので、画像のパスが保存されていることに注意してください。
5.2 読み込み時の初期化
body 要素で読み込み時のハンドラとして setup() が設定されていました。これを見てみましょう。
FramingGallery.js > setup
// The setup 関数はウィジェットが読み込まれた時に呼ばれる。
// これは、環境設定があるなら、ウィジェットのさまざまな要素を初期化する。
// そうでなければ、デフォルトの設定が使われる。
// また、既存のdivに各ボタンを入れる AppleInfoButtonとAppleGlassButtonのコンストラクタも呼び出す。
function setup()
{
glassDoneButton = new AppleGlassButton(document.getElementById("doneButton"),
"Done", hidePrefs);
infoButton = new AppleInfoButton(document.getElementById("infoButton"),
document.getElementById("front"), "black", "black", showPrefs);
if(window.widget)
{
// フレーム環境設定を取得
var frameTop = widget.preferenceForKey(makeKey("frameTop"));
var frameRight = widget.preferenceForKey(makeKey("frameRight"));
var frameBottom = widget.preferenceForKey(makeKey("frameBottom"));
var frameLeft = widget.preferenceForKey(makeKey("frameLeft"));
if (frameTop && frameTop.length > 0) // 環境設定があれば
{
// それらを復元
frame.style.borderTopColor=frameTop;
frame.style.borderRightColor=frameRight;
frame.style.borderBottomColor=frameBottom;
frame.style.borderLeftColor=frameLeft;
}
// マット環境設定を取得
var matColor = widget.preferenceForKey(makeKey("matColor"));
if (matColor && matColor.length > 0) // 環境設定があれば
{
mat.style.borderColor=matColor; // このインスタンスに対してそれを復元
}
// 環境設定ボタンの環境設定を取得
var flipitColor = widget.preferenceForKey(makeKey("flipitColor"));
if (flipitColor && flipitColor.length > 0) // 環境設定があれば
{
prefArrowColor(flipitColor); // このインスタンスに対してそれを復元
}
// image 環境設定を取得
var picturesrc = widget.preferenceForKey(makeKey("image"));
if (picturesrc && picturesrc.length > 0) // 環境設定があれば
{
// 「picture」と「hiddenPic」(画像の寸法の確定に使用)に割り当て
var img, img2;
img = document.getElementById ("picture");
img2 = document.getElementById ("hiddenPic");
img.src = img2.src = picturesrc;
img.onload = preResize; // 画像が読み込まれた時の読み込みハンドラを割り当て
}
else { // 環境設定が見つからなかったら
preResize(); // ウィジェットをデフォルト画像にサイズ変更したほうがいい
}
}
}
まず最初にAppleが提供するボタンクラスを作成しています。Fader で説明しましたが、ガラスボタンのコンストラクタの引数は、順番に、ボタン要素、タイトル、クリックされた場合のハンドラです。情報ボタンのコンストラクタの引数は、順番に、ボタン要素、前面要素、前景色、背景色、裏面表示の際のハンドラです。
その次の if 文でダッシュボード内で起動されているかを確認し、そうである時だけ残りの作業を行います。これは、残りの部分で環境設定を取得しているためです。環境設定の取得は非常に簡単で、キーを渡してメソッドを呼び出すだけです。ここでも、makeKey を使って、個別ウィジェットインスタンスごとの一意的なキーを作成して、それを使っています。
フレームのサイズ情報はまず一時変数に取得し、環境設定が存在して、値がある場合だけ、それぞれの値を実際のスタイルへと割り当てています。それからマット色の環境設定を取得し、あるなら、スタイルへ割り当てます。
次に環境設定ボタンの色の設定を取得します。それがあれば prefArrowColor を使って設定します。
FramingGallery.js > prefArrowColor
// マットの右下に現れる環境設定シンボルはマット色にもとづいて白か黒にできる
// この関数はそれがどちらであるほうがいいか画像を調整し、環境設定を記録する
function prefArrowColor(color)
{
if(color == "white")
{
infoButton.setStyle("white", "white");
widget.setPreferenceForKey("white",makeKey("flipitColor"));
}
else {
infoButton.setStyle("black", "black");
widget.setPreferenceForKey("black",makeKey("flipitColor"));
}
}
これを見てわかるように、単に環境設定の文字色を白か黒かに変えるだけです。
さて、setup に戻ると、最後は画像の設定です。環境設定を取得して、あるなら、「picture」と「hiddenPic」のソースにそれを割り当てます。それから読み込み完了時のハンドラ preResize を割り当てています。見つからなかった場合も preResize を呼び出します。後の方は、デフォルトの画像でサイズ決定されることになります。
FramingGallery.js > preResize
// 新しいピクチャーが追加された時、「picture」とウィジェットウインドウをサイズ変更
function resize(x,y)
{
if(x >= 400) { // 最大画像幅は400px、そのため画像がより大きいなら縮小する必要がある
y = y * (400/x);
x = 400;
}
if(y >= 400) { // 最大画像高も400px
x = x * (400/y);
y = 400;
}
if(x < 180) { // 最小画像幅は180px、そのため画像がより小さいなら拡大する必要がある
y = y * (180/x);
x = 180;
}
if(y < 100) { // 最小画像高は100px
x = x * (100/y);
y = 100;
}
document.picture.width = x; // 寸法が決定されたら、
document.picture.height = y; // picture <img> はそれにしたがってサイズ設定される
height = y + 52; // フレームとマットは52px、そのため、
width = x + 52; // ウィジェットウインドウは画像より52px大きい
if(window.widget) // ウィジェットがダッシュボード内で実行されているかチェック
{
window.resizeTo(width,height); // そうならウィジェットウインドウをサイズ変更
}
back.style.height = height - 4; // 環境設定レイヤーも新しい寸法にあうようサイズ変更される
back.style.width = width - 6;
hanger.style.left = ( (width/2) - 50 ); // ウィジェットがサイズ変更されたとき、
framePopup.style.left = ( (width/2) - 50 ); //さまざまな環境設定要素も再配置される必要がある
frameText.style.left = ( (width/2) - 92);
matPopup.style.left = ( (width/2) - 50 );
matText.style.left = ( (width/2) - 80);
doneButton.style.left = ( (width/2) - 29);
dndindicator.style.left = ( (width/2) - 103 ); // ドラッグ&ドロップインジケーターも
dndindicator.style.bottom = 30; // 一番下中央に位置するよう再配置される必要がある
}
かなりくわしいコメントが付いているのでわかると思います。まず最初に画像の最大と最小サイズの制約にしたがって、画像サイズを調整しています。これは画像の縦横比を維持するためです。それから実際に picture に画像サイズを割り当てています。画像は picture と hiddenPic の2つに読み込まれましたが、これでわかるように、picture には調整されたサイズが、hiddenPic には元画像のサイズが入っていることになります。
つぎに画像外側のマットとフレームの幅を考慮して、ウインドウ全体のサイズを決定し、設定します。裏面になった時にサイズが変わらないよう、裏面のサイズも変更されています。それから大きさが変更された時に調整する必要があるスタイル要素を変更しています。最後にドラッグ&ドロップを行うように指示するツールチップの場所を調整しています。
5.3 ツールチップの表示
FramingGallery.html において、前面となる id が front の div で、onmouseover="fadeIn();" onmouseout="fadeOut();" が設定されていました。これは前面 div 上にマウスが入ったとき、それを離れた時に呼び出されます。
FramingGallery.js > fadeIn
// fadeIn() は、マウスがウィジェット上にあるとき呼ばれる
function fadeIn()
{
if(currentAnimator != undefined) {
// アニメーターが既にあるなら
currentAnimator.stop();
// 停止して
delete currentAnimator;
// 削除
}
currentAnimator = new AppleAnimator (500, 13);
// アニメーター作成
currentAnimator.oncomplete = dispose;
// 終了時のハンドラ設定
currentAnimation
= new AppleAnimation (globalFrom, 1.0, setOpacity)
// アニメーション作成
currentAnimator.addAnimation(currentAnimation);
// アニメーターに追加
currentAnimator.start();
// アニメーターに開始を指示
}
これはドラッグ&ドロップのツールチップを表示するためのものですが、それをアニメーションを使って少しずつフェードインしています。アニメーションについては、Stretcher でくわしく説明しました。最初にすでにアニメーションが進行中かを調べて、そうなら中止してアニメーターを削除します。
次にアニメーターを作成します。ここでは 500 ミリ秒で終了し、13 ミリ秒ごとに呼ばれるよう設定しています。それからアニメーターがアニメーションを終了したときに呼ばれるハンドラ関数 dispose を設定しています。
FramingGallery.js > dispose
function dispose()
{
delete currentAnimator;
delete currentAnimation;
}
このように、単にアニメーターとアニメーションを削除しているだけです。
つぎにアニメーションを作成します。globalFrom はグローバル変数の開始値で 1.0 は終了値、setOpacity はアニメーション実行時に呼ばれるハンドラです。globalFrom は最初 0 に設定されています。フェードインを行うため、最後の値は必ず 1.0 になります。ここでは先ほど作ったアニメーターにこのアニメーションを追加するので、13 ミリ秒ごとに setOpacity が呼ばれることになります。
FramingGallery.js > fadeOut
// fadeOut() は、マウスがウィジェットを離れた時に呼ばれる
function fadeOut()
{
if(currentAnimator != undefined) {
currentAnimator.stop();
delete currentAnimator;
}
currentAnimator = new AppleAnimator (500, 13);
currentAnimator.oncomplete = dispose;
currentAnimation = new AppleAnimation (globalFrom, 0.0, setOpacity)
currentAnimator.addAnimation(currentAnimation);
currentAnimator.start();
}
fadeIn とほぼ同様ですが、アニメーションの終了値が 0.0 である所だけが違います。たとえば、マウスが外に出て、すぐに内部に戻った場合、このフェードアウトアニメーションの途中で、フェードインが呼ばれることになります。その時に開始値を途中から始めるために globalFrom というグローバル変数が設定されていたわけです。
5.4 ドラッグ&ドロップ
さて、前面 div 内の img にもハンドラが設定されていました。これは ondragenter='dragenter(event);' ondragover='dragover(event);' ondrop='dragdrop(event)' ondragleave='dragleave(event)' で、これらはドラッグ&ドロップを扱うものです。
FramingGallery.js > dragenter・dragover・dragleave
// dragenter、dragover、dragleave関数は実装されているが使われない。
// これらはウィジェットに画像が進入したとき、画像を変更したいなら使うことができる
function dragenter (event)
{
event.stopPropagation();
event.preventDefault();
}
function dragover (event)
{
event.stopPropagation();
event.preventDefault();
}
function dragleave (event)
{
event.stopPropagation();
event.preventDefault();
}
このサンプルでは、単にこれ以上のイベントの伝播を防いでいるだけです。Grid で説明しましたが、stopPropagation() はイベントがこれ以上伝えられるのを防ぎます。preventDefault() は、イベントのキャンセルを通知します。これにより、イベントハンドラを呼び出した元が、そのイベントに対応するのを防ぎます。たとえば、通常のウェブページで、独自の動作を実装して、ブラウザの通常の動作をさせたくない場合などに使います。JavaScript の独自関数ですべてを行い、他で何らかの動作が入ってほしくない場合に呼び出します。画像がドロップされた場合には URL の取得など処理が必要です。
FramingGallery.js > dragdrop
// 画像ドロップに対するイベントハンドラ
// このハンドラは画像URLを取得しウィジェット内にそれを配置しようとする
function dragdrop (event)
{
var uri = null;
try {
uri = event.dataTransfer.getData("text/uri-list"); // 新しい画像URLを読み込もうとする
} catch (ex)
{
}
// 取得に成功したら
if (uri)
{
if(window.widget)
{
widget.setPreferenceForKey(uri,makeKey("image")); // 新しい画像に対する環境設定を設定
}
var img, img2;
img = document.getElementById ("picture"); // 新しい画像を「picture」
img2 = document.getElementById ("hiddenPic"); // と「hiddenPic」に割り当て
img.src = img2.src = uri;
img.onload = preResize; // 画像が読み込まれた場合の読み込みハンドラを設定
}
event.stopPropagation();
event.preventDefault();
}
ドラッグ&ドロップについては、Dropper で説明しました。まず、ドロップイベントの dataTransfer を使ってデータを取得しようとします。取得できれば、それを環境設定に追加し、それ以後は setup 関数で行っていたのと同じです。
このように、ドロップ対応自体は難しくありません。単に URL を取得して設定しているだけであることがわかったと思います。
5.5 裏面の動作
つぎに裏面のdivで設定されている動作を見てみます。2つのポップアップメニューに値が変更された場合のハンドラが設定されていました。これらは changeFrame(this) と changeMat(this) です。
FramingGallery.js > changeFrame
// changeFrame は、値が変更されたときフレームポップアップによって呼ばれる
// この関数はフレームに対する境界線色属性を変更し、さまざまな絵画枠スタイルをシミュレートする
function changeFrame(elem)
{
var frame = document.getElementById("frame"); // フレーム要素を取得
// ポップアップメニューの値にもとづいて、正しいフレーム色を適用
switch( parseInt(elem.options[elem.selectedIndex].value) )
{
case 1: // 黒色の場合
frame.style.borderTopColor="#030303";
frame.style.borderRightColor="#1A1B1A";
frame.style.borderBottomColor="#030303";
frame.style.borderLeftColor="#1A1B1A";
break;
case 2:
...
}
// フレームが変更されたら、新しいスタイルが環境設定として保存される
if(window.widget)
{
widget.setPreferenceForKey(frame.style.borderTopColor,makeKey("frameTop"));
widget.setPreferenceForKey(frame.style.borderRightColor,makeKey("frameRight"));
widget.setPreferenceForKey(frame.style.borderBottomColor,makeKey("frameBottom"));
widget.setPreferenceForKey(frame.style.borderLeftColor,makeKey("frameLeft"));
}
}
最初にフレーム要素を取得し、ポップアップメニューの値番号を取得して、それにしたがってフレーム要素のスタイルを変更しています。case 2 以降は同様なので省略しています。それから環境設定を保存しています。
FramingGallery.js > changeMat
// changeMat は、値が変更された時に、マットポップアップによって呼ばれる
// この関数はマットの境界線色属性を変更し、さまざまなマット色をシミュレートする
function changeMat(elem)
{
var mat = document.getElementById("mat"); // マット要素を取得
// ポップアップメニューの値にもとづいて、正しいマット色を適用
// 同様に正しい環境設定ボタン色もここで設定される
switch( parseInt(elem.options[elem.selectedIndex].value) )
{
case 1: // アークテックホワイト
mat.style.borderColor="#F8F7F1";
prefArrowColor("black");
break;
case 2:
...
}
// マットが変更されたら、新しいスタイルが環境設定として保存される
if(window.widget)
{
widget.setPreferenceForKey(mat.style.borderTopColor,makeKey("matColor"));
}
}
基本的にフレームと同じです。ただし、環境設定ボタンの色が、選択にしたがって黒か白のいずれかに設定されることに注意してください。
5.6 前面と裏面の切り替え
さて、setup 関数内で情報ボタンとガラスボタンに対してハンドラが設定されていました。情報ボタンに対しては showPrefs、裏面にあるガラスボタンに対しては hidePrefs です。
FramingGallery.js > showPrefs
// showPrefs 関数は環境設定ボタンがクリックされたときに呼ばれる
// これはウィジェットが環境設定を表示する準備をさせ、それから裏返す
// これについてのさらなる情報はダッシュボードドキュメントで見つかる
function showPrefs()
{
var front = document.getElementById("front"); // 最初に前面と裏面レイヤーを得る必要がある
var back = document.getElementById("back");
if(window.widget) // 現在見えているレイヤーを凍結
widget.prepareForTransition("ToBack");
front.style.display="none"; // 環境設定レイヤーを見えるようにして画像を隠す
back.style.display="block";
if(window.widget) // 前面の凍結側と裏面の環境設定で反転遷移を実行
setTimeout ('widget.performTransition();', 0);
}
これについては、『Dashboard プログラミングトピック』>「ウィジェットの裏面と環境設定」を見てください。また、Fader でも説明しました。裏面を表示するための基本的な動作を行っているだけです。
FramingGallery.js > hidePrefs
// 環境設定で「Done」ボタンがクリックされたとき、この関数が呼ばれる
// これは環境設定レイヤーを画像とフレームに切り替える
function hidePrefs()
{
document.getElementById("doneButton").src
= "Images/done.png"; // 通常の「Done」ボタンを復元
var front = document.getElementById("front"); // 前面と裏面レイヤーを取得する必要がある
var back = document.getElementById("back");
if (window.widget) // ユーザーが見ているレイヤーを凍結
widget.prepareForTransition("ToFront");
front.style.display="block"; // 環境設定レイヤーを隠し、主要な画像レイヤーを表示
back.style.display="none";
if (window.widget) // そして反転遷移を実行。UI を凍結するためにfinishEdit()が使われたので
setTimeout ('widget.performTransition();', 0); // 反対向きになることに注意
}
コメントがきちんとつけられているので、十分わかると思います。
これで FramingGallery.js 内で定義されている関数については、すべて説明しました。
管理人:神吉 秀典 E-mail: