So-net無料ブログ作成

ウィジェットのデザイン(メニュー) [Dashboardウィジェット]

前回飛ばした、メニューについてのガイドラインです。以前の記事で「Aquaを使うな」と書かれていることを紹介したと思いますが、ウィジェット用の部品が用意されているのではなく、どうやら、自分で作成する必要がある様です。

こちらでは、「Voices」と言うサンプルコード(があるんだと思われます。まだ、未調査。)内で使われているポップアップメニューが例示されていて、次の3つの要素を作る必要があるとのことです。

  1. ポップアップメニューの外観を表現する画像
  2. 現在選択されている項目を示す文字列
  3. 選択項目を定義する<select>タグの要素


項目1はメニュー全体の画像を自分で作る必要がある様です。上下の三角形に関する規定が書かれていませんが、一応統一感を持たせる必要はあるんじゃないかと思われます。

続いて、サンプルコードが示されていましたので、それを参照します。まずは、HTMLファイル

<img class="popupMenuImage" src="Images/Menu.png" />
<div id="popupMenuText">Available Voices</div>
<select id='popupMenu' onchange='popupChanged(this);'>
        <option value="One">One</option>
        <option value="Two">Two</option>
</select>


項目1〜3の要素を羅列していますね。それぞれにCSSで配置を決めるための「class」もしくは「id」のアトリビュートをが設定されています。でも、まだ「class」と「id」の使い分けが良くわかっていません。CSSでこれらの位置を定義して、メニューの要素の配置を決めている様ですね。

また、<select>要素で設定されている、「onchange」と言うアトリビュートでJavaScriptの関数(メソッド?)を呼び出している様です。後に出てくるJavaScriptのソースを見たところ、popupChanged()という関数に渡されている「this」と言う引数は、<select>要素そのものを指している様ですね・・。

次に、これらの位置を決めるCSSのソースです。

.popupMenuImage {
    position: absolute;
    left: 28px;
    top: 169px;
    z-index: 18;
}

#popupMenuText {
    font: 13px "Helvetica Neue";
    font-weight: Bold;
    color: white;
    text-shadow: black 0px 1px 0px;
    position: absolute;
    left: 44px;
    top: 176px;
    z-index: 19;
}

#popupMenu {
    position:absolute;
    top: 169px;
    left: 28px;
    width: 163px;
    height: 30px;
    opacity: 0.0;
    z-index: 20;
}


全ての要素の位置は固定値で設定されています。まあ、popupMenuImageとpopupMenuTextはそれでもいいと思いますが、popupMenuがちょっと気になりました。サンプルコードではありませんが、標準で入っている「辞書」で動作を確認してみたところ、現在選択されている要素とウィジェット本体の位置によって、メニューの選択肢の表示位置は変わっていますね。ここの#popupMenuで設定している値は暫定でしょうか? と思って、「辞書」のソースを見たところ、ダイレクトに設定されていない様に見えます。まだ、良くわかっていないので、見る場所が間違っているかもしれませんが・・・。まあ、今は気にしないことにします。

ところで、今まで気づきませんでしたが、改めて見てみると、ポップアップメニューの動作はいまいちですね・・。


そして、最後にHTMLソース中の<select>要素から呼び出されていたJavaScriptの関数のソースです。

function popupChanged(elem)
{
    var chosenOption = elem.options[elem.selectedIndex].value;
    document.getElementById("popupMenuText").innerText = chosenOption;
 
    // Other code that handles the menu selection change
}


このソースを見て、HTMLソース中の<select>要素で選択された選択肢の中身を<div>要素のテキストとして設定してるんやなぁ・・。と想像はつきますが、まず、<select>要素の中身へのアクセスの仕方、また「document」中の要素への書き込みの仕方はどこで定義されてるんですかね・・? JavaScriptの仕様として書かれているんでしょうか? この辺りがわからないと、自分でコードを書く時に不自由してしまう気がします・・。


と言うことで、やっとウィジェットの設計方針については終わりです。そろそろDashcodeを触りたくなってきましたね。

ウィジェットのデザイン(その他) [Dashboardウィジェット]

前回からずいぶん間があいてしまいましたが、ウィジェットのデザインの最終回です。その他の項目。と行きたいところでしたが、ここで書かれているメニューについての内容が割とボリュームがあったので、そこだけ、次回にまわすことにしました。と言うことで、最終回の1回目。

それはさておき、Dashboardの件で他に検索をかけていましたら、読んでる文書の日本語版が偶然ひっかかりました。おかしいですねぇ。ADCの日本語版のページには無かったはずなのに・・・。と思ったらありました。まあ、ちょっと古い様なので、一応、英語版の方で読み進めることにしますが・・。

さて、まずはウィジェットバーに表示されるアイコンです。「ウィジェットバンドル」の記事にもまとめましたが、「Icon.png」と言うファイルで、下記の条件で作成する必要がある様です。影を自作する必要があるのには、ちょっと驚いてしまいました。どのアイコンも作者の方が自前で影をつけてるんですか・・。

  • 本体:75x75 pixel
  • 影:
    • 透過度 50%
    • 角度 90°上方
    • オフセット 3pixel(ソースから)
    • サイズ 3pixel (ガウスぼかし)


アイコン本体のサイズはこの通りですが、影や透明部分を含めたアイコン画像自体のサイズは特に見当たりません。巨大なのを作ったらどうなるのかちょっと気になります(切られるだけか?)。後、オフセットの意味が良くわかっていません。ソースってどこ? 影をつけるときの常識なのかもしれませんが・・・。ツールで自動で選べるんでしょうかね? と思ったら、Dashcode のアイコン作成機能に何らかの編集機能がありそうです。ま、この辺りは、実際にDashcodeを使う時に見てみたいと思います。

それはさておき、次はプログラミング時の注意点です。

  1. できる限り、JavaScriptを使用すること
  2. カスタムウィジェットやWebKit plug-insの使用は控えること
  3. Javaアプレット、Flashアニメーション、QuickTimeムービーの使用は避けること


とにかく、JavaScriptを使いなさい。と言うことの様です。スピード、メモリの観点からの様ですが、これはアレですね。たぶん、Dashboard自体が裏で常に動作しているため、そんなもんを使うと常時重くなりますよ。と言うことの様な気がします。(勘です。調査してませんのであしからず。)


次は、メニューについてですが、冒頭にも書きました通り、この項目は次回に持ち越しにします。と言うことで、次は検索フィールド。

Dashboardのエンジンとして使われているWebKitですが、ウィジェットには検索フィールドが設置される場面が多いであろうとの配慮から、<input>要素のtypeアトリビュートの値に「search」と言う値を追加しているそうです。と言うことで、ここは通常のWebページのテクノロジではなく、ウィジェット独自の項目になりますね(たぶん、Safariでも有効)。で、このアトリビュートは「<input type="search">」の様に指定する様です。このtypeを選択した場合、以下のアトリビュートも設定できるとのこと。

placeholder検索キーが入力される前の文字列。
results検索語の保存数。
onsearchenterキーもしくは、returnキーが押されたときのハンドラ。
incrementalこのアトリビュートが設定されている時、文字が人文字入力される度にonsearchで設定されたハンドラが呼ばれる。
onkeypress任意のキーが押されたときのハンドラ。


続いて、ヘルプタグ。各要素の上にマウスカーソルが来た時、ヘルプタグを表示すべきとのことです。ヘルプタグはtitleアトリビュートを設定すれば表示されるとのこと。「<div id="helloText" title="This is a helpful explanation of this element">Hello, World!</div>」とこんな感じですね。

最後にユニバーサルアクセスについて。Mac OS X 10.4(Tiger)から、VoiceOverと言う機能が盛り込まれています。目の不自由な方のために音声で現在のウィンドウを知らせる機能の様です。これに対応するため、下記の2点を盛り込む必要があるとのことです。

  • HTMLファイル中に記述する各要素は、上(もしくは左)に配置するものから順に記述すること。
  • <img>要素にはaltアトリビュートを設定すること。


要素の記述順については、普通に書けばそうなりそうな気もします。CSSで配置をぐちゃぐちゃにすることも可能なんですかね・・。まあ、そういうことはするなと言うことですね。また、<img>要素のaltアトリビュートはVoiceOverにて読み上げられるらしいです。でも、たぶん英語だけ?


以上、メニューについては切りましたが、それでも長い記事になってしまいましたね・・。と言うことで、次回はメニュー(ポップアップメニュー)についてです。


【参考】
Dashboardプログラミングトピックの紹介


助十郎 Ver.0.2.1 リリース [Zaurus]

延々と自分用のメモにしかなっていないデバグの様子をアップしてきましたが、併設しているぐうたラボで、助十郎のバージョン0.2.1をようやくリリースしました。

次の点を修正しました。

  • 1か月画面の今月のスケジュール表示内で期間スケジュールのタイトル表示位置がおかしいものがあったのを修正。
  • 1か月画面の今月のスケジュール表示内で期間スケジュールの期間を示すバーの表示位置を画面をより有効利用できる様に修正。
  • 1か月画面の翌月のスケジュール表示内と6か月画面でスケジュールのタイトル表示位置がおかしいものがあったのを修正。
  • 春分の日、秋分の日が正しく表示されない場合があったのを修正。
  • 期間スケジュールの色を変更
  • データリロード時、休日関連データも読み込む様に修正


最近、期間スケジュールを多用し始めたんですが、多数の期間スケジュールを登録すると、ちょっと使えないレベルな気がしたので、修正することにしました。もう2年ぶりなんですよね。いまさらですが、期間スケジュールの表示に関しては、かなりましになったと思います。後、独自データベースに切り替えてスケジュールの登録もできるようにしたいとは思ってるんですが、まあ、放置状態です・・。

この2年の間、スマートフォンは出てますが、PDAはもうまったく出てこないですね~。ネットブックは出てますが、あれでもでかすぎますし、電池の持ちからしてPDAとは違いますしね・・。Android搭載の端末がキャリアの縛りなし(というか個人的には公衆網はなくていいんですが・・)で出てくればうれしいんですが、日本のメーカーからはそれもないですかね・・。そろそろZaurusの電源スイッチの当たりが怪しくなってきているんで、代替の機種が欲しいんですけどねぇ・・・。

ちなみに、前回の記事で放置すると決めたバグですが、割と簡単に発生しますね・・。また出ました。と言う事で、どうしようかな〜。


1ヶ月画面での期間スケジュールの表示の修正 Part 6 [Zaurus]

前回の記事の修正でやっとリリースできると思ってリリース準備を進めていたんですが、使っているとまた不具合がでました・・・。もう、見なかった事にしようかと思いましたが、また、2年もほっとくとなると、気になって仕方がなくなりそうなので、一応追って行きます・・・。

ちなみに、不具合はこんな感じ。

sukejuro_bug6.png
ある公爵夫人の生涯購入・・・


わかりますでしょうか? って、見たらすぐに気がつくと思いますが、2段目で期間スケジュールのタイトルがかぶってしまっています。タイトルの重なりの検出に失敗してるんですかねぇ・・。「ある公爵夫人の生涯」が上に来ているので、その下の「〜購入」と言うスケジュールの方が先に位置が決まってしまっていると思われます。他のスケジュールと合わせてみると「ある公爵夫人の生涯」は表示場所が無くて、ここになってしまった感じがありますね・・。これ、解決できるんかな・・??

さて、期間スケジュールのタイトルの位置は、「skmonth.rb」の中の「SkMonth#getTitlePos」で決定しています。で、中を見て行くと重複がある場合は、さらに「SkMonth#makeTitlePosCandidates」に遷移して行く様です。ここでoverlapを見てますね。また、これの扱いが怪しそうです。とりあえず「SkMonth#makeTitlePosCandidates」の中身をいちいち見て行く事にします。

まず、冒頭です。

  # 初期化
  pos = PeriodTitlePos.new(info.event.description, false, info.level)
  pos.x = startFrame.x


まず、タイトルの表示位置(pos)を生成していますね。ちなみに、PeriodTitlePosの定義は下記の通りです。

 # 構造体
 PeriodTitlePos = Struct.new(:title, :conflict, :level, :x, :y, :titleWidth, :periodWidth)  # 期間スケジュールタイトル描画位置


で、その後、重複のチェックとやらをやってます。これ、何をやってるんでしょう?? if文の条件式の意味もわかりません。

  if (overlap[info.start] != 1) then
   pos.conflict = isConflict(info.start, info.level, overlap)   # 重複チェック
  end


まず、overlapって何でしょう? たどってみると、SkFixedPeriodDataの@overlapメンバの様です。各日付のスケジュールが入っているハッシュのようですが、それだとこの比較はおかしいですね・・・。「overlap[info.start].size != 1」とでもしたかったんでしょうか?

で、条件に当てはまるときに呼ばれているのが、こちら「SkMonth#isConflict」です。

 def isConflict(day, level, overlap)
  ret = false
  
  targetLevel = level + (((level % 3) == 1) ? 1 : (-1))	  # 重複対象レベル
  overlap[day].each { |item|
   if (item.level == targetLevel) then
    ret = true
    break
   end
  }
  
  return ret
 end


ちょっと、意味不明でしたが、今、注目しているデータと重複対象(段内で今見ているデータのレベルが1ならば2のデータ、レベルが2ならば1のデータ)になるデータのレベルを「targetLevel」と言う変数に落とし込んで、そういうデータがこの日の中に存在しているのかどうかを確認しているようですね。

となると、先ほどの条件文の中の式はどうなんでしょうね・・・? まず、このメソッドに来るデータは期間内のいずれかの日に他の期間スケジュールと重複があるデータです。で、各日付で重複があるかどうかを調べる必要があるのは今のデータ以外のデータが存在する日。ですね。だから、条件式の中の式は「overlap[info.start].size != 1」でよさそうです。取りあえず、それは修正。


次は、期間の2つ日目から最終日までをなめて行って、重複している箇所と重複の無い箇所のそれぞれを分割して行っている様です。

  # 期間の分類
  ret = Array.new
  cx = pos.x    # 現在の日付のフレーム座標
  week = 0    # 開始週からの週差
  (info.start + 1).upto(info.fin) { |n|
   wday = Time.mktime(@date.year, @date.month, n).wday
   if (wday == 0) then						# 新しい週に入った


・・・ん〜、ソースを眺めていたら、どうやらこの関数は以前に掲載した期間スケジュールのタイトルの位置に関するルールに従って、表示位置の候補を優先順位順に抽出してるだけですね。

で、呼び出し元の「SkMonth#getTitlePos」では、何も考えずに一番優先順位の高いものを選択しています。そもそも、ここには現在注目している一つの期間スケジュールのみが来ているので、他のデータとの比較、位置調整をしようと思ったらちょっと大事ですね・・・。ここ、バグと言うよりかは手抜きレアケースのための割り切り仕様と言ったところでしょうか・・。どうしましょうかねぇ・・・。


ん〜〜〜〜・・・、と悩みましたが、もうこれはこのままにしとくことにします。

助十郎のデータリロード時の休日データ読み込み [Zaurus]

前回、リリース作業に入るとか書きましたが、もう一点、データをリロードする際に休日データの読み込みを忘れていた点を修正しておきます。前々から気にはなっていたので、ついでです。

リロードの処理は「Sukejuro#procReloadSignal」で実行されています。ここから「SkData#reloadData」を呼び出していますね。一方、起動時は「SkData#initialize」で「SkHolidays.new」を呼び出しており、ここでメンバ変数「@holidays」に休日のデータを読み込んで完了となっています。

 @holidays = SkHolidays.new    # 祝日情報


一番簡単なのは、リロード実行時に呼び出される「SkData#reloadData」で初期化時と同様、「@holidays」へ新規に生成した「SkHolidays」のインスタンスを設定する事ですね。休日データのみをリロードできるようにしたい気もしますが、今回はこれだけにしときます。


以上。

助十郎のサイドスケジュールの修正 Part 3 [Zaurus]

内容が横道にそれまくっていますが、この記事で決着をつけたいですねぇ・・・。

今回、気になっている現象は次の様にスケジュールのタイトルが期間スケジュールの線でつぶされてしまっている現象です。

sukejuro_bug4.png
左に寄り過ぎ


ちなみに、これもバグじゃあないかと思っています。

sukejuro_bug5.png
やや右に寄り過ぎ


本来は、こうあるべきだと思います。

sukejuro_sample1.png
線にぴったり


スケジュールの表示位置を決める値は「skcompactmonth.rb」の「SkCompactMonth#getDisplayData」で設定されている様です。下記の様に決められていますね。

 level = periodData.overlap[period.start].size  # 線の数


単純に線の数で位置を決めていますが、今回の修正で線の位置が左に戻る事もあるため、ちゃんと各日付の最大levelを見る必要がありますね。って、これ、修正前でもこの決め方じゃあだめですね。と思って、過去の動作を見てみたら、やっぱりだめでした。あんまり気にしてなかっただけか・・。

と言う事で、ここで各日付の最大レベルを見る様にしましたが、概ねうまく言っている様に見えますが、完全にはうまくいっていません。よく見てみたら期間の開始日だけで判断していました。さらにこの関数をよく見てみましたが、なんか処理に無駄がありそうな気がします。この関数の処理を見直す事にしました。

今のSkCompactMonth#getDisplayDataの処理はおおざっぱに書いて、下記の様な感じです。

sukejuro_algo1.png
無駄とバグあり


無駄と感じているのは右側のループの中。「level決定」と「該当期間のlevel設定」です。また、これがバグの原因となっています。ここは各期間スケジュールについて、スケジュールタイトルの位置を決定するのが主目的ですが、ここでlevel設定もしているので、この期間のスケジュールは、重複しているスケジュールの回数分level設定されている事になります。ちなみに、動作上、同じlevelが何回も設定されていると思われます。

これをこんな感じに修正しようかと思います。

sukejuro_algo2.png
バグは消えるけど・・。


2回ループを回しているので、効率が良くなっているのかどうかわからないんですが、取りあえず、無駄はなくなったと思います。ついでにバグも無くなりました。

sukejuro_fix2.pngsukejuro_fix3.png
ぴったり!ぴったり!



と言う事で、今度こそリリースに移ります。

助十郎のサイドスケジュールの修正 Part 2 [Zaurus]

前回、予想外に「春分の日」「秋分の日」の設定内容が反映されない件についての修正ができました。ほんとは、一か月画面横にある翌月のスケジュール内の通常スケジュールの表示を修正したいんですが、前回の修正の後、また落ちる現象が出てきました。今度は、nilに対して、何か操作しようとしていると怒られています。

 ./skcompactmonth.rb:359: in `getDisplayData': undefined method `year' for nil:NilClass (NoMethodError)


ログを取ってみたところ、末尾に妙なデータがついてますね。2つ付いてたんですが、片方は終了日が無く、片方は開始日がありません。また、双方とも該当日は該当月から外れています。

・・・そういえば、そういうデータの存在も検討した様な記憶がありますね。どういう扱いにするんでしたっけ?? その前にデータを良く見てみたら、これらのデータはこの月にしか入っていない様です。また、開始日のみの方はその開始日が2007/8/22、終了日のみの方は終了日が2007/1/31。今月のデータを見ていたので、ここにこれらのデータが紛れ込んでるのが、そもそもおかしいですね。

この現象は、なんとなく今回触ったところとは何の関係もなさそうな気がします。助十郎の期間スケジュール表示の修正 Part 3でちらっと書きましたが、今は現在の最新ソース(ローカルでいろいろ触ってたソース)に対して、バグ修正を施して行ってるんですが、この最新ソースは何か機能追加をしようとした痕跡があるんですよね。って、私がしようとしてしたんですが、記憶に全くありません。ファイルのタイムスタンプを見たら、2年前くらいに何かしようとしてた様です。で、たぶん途中で飽きてほったらかしたと言う感じですね。ど〜しようかなぁ。

・・・と考えましたが、せっかく書き足したコードを消すのももったいないですし、今更古いソースとの差分を見ながら差分を当て直すのも面倒なので、このまま最新ソースを修正して行く事にします。ただし、追加していた機能は抑制する方向で修正して行きます。収拾が付かなくなりそうなので・・・(というか、たぶん収拾がつかなくなって放置した様な気もする)。と言う事で、今後の記事(とこれより前の記事)に転記しているソースは、既に配布しているソースとは中身が異なってる可能性もありますので、ご了承願います(って、たぶん見てる人はいないと思いますが・・)。

さて、最新ソースを見ていると「skdata.rb」の中身がかなりいじられています。今回、関係ありそうなのはこのファイル内の「SkData#getScheduleOfTheMonth」なのですが、ここに影響してそうな追加があったので、それをコメントアウトしてみました。


で、落ちなくなりました。横道にそれまくりですが、直ったので、次から本題の修正に入ります。

つづく。



助十郎のサイドスケジュールの修正 [Zaurus]

前回の修正でリリースしようと思ったんですが、実は1か月画面横に表示されている翌月のスケジュール(このパーツは6か月画面でも使用されています)の通常スケジュールの表示もおかしい点があったので、ついでに直そうかと言う気になりました。で、データを取ろうと思って動作させていたところ・・、落ちてしまいました。エラーメッセージは下記の通りです。次々にバグが出ますねぇ・・・。

./skcompactmonth.rb:301:in `drawData': undefined method `-' for "20":String (NoMethodError)


該当箇所は「skcompactmonth.rb」に定義されている「SkCompactMonth#drawData」の中。下記の様になっています。

 y = @topMargin + @frameHeight * (title.day - 1) + 1


「title.day」がInteger型である事が想定されているのに、String型になっている様ですね・・。このtitleを設定しているのは、「SkCompactMonth#getDisplayData」の様です。titleに設定されているデータの型は下記の通りに定義されています。

 SkCmonthData = Struct.new(:day, :level, :title, :holiday, :period)


各要素は順に「日にち、タイトルの左マージン、タイトル、休日フラグ、期間データフラグ」となっています。

さて、「SkCompactMonth#getDisplayData」の中身を見ていると、処理としては「該当月のスケジュールデータの取得」→「通常データと期間データの振り分け」→「通常データのタイトル設定」→「休日データの設定」→「期間データの設定」と言う感じで進んでいます。

「通常データのタイトル設定」の所のソースは下記の様な感じです。

 dayEvent.each { |event|
  if (titles[event.start.day] == nil) then
   title = SkCmonthData.new(event.start.day, 0, event.description, false)
   titles[event.start.day] = title   # タイトル設定
  end
 }


「event.start.day」は普通に読み込んできた値が入っているので、String型に変わる場合が良くわかりません。ちなみに、先ほどのエラーは毎回出ている訳ではなく、今回操作していたら突然発生したものですので、全データがそうなっている訳ではなく、特定のデータがそうなっていた様です。

コードを見てもわからないので、ログを仕込んで動かす事にします。デバッガが無いので面倒です・・。

*
ターミナルで日本語が化け化けです。以前、設定した様な気がするんですけどねぇ・・。と言う事で、どのスケジュールが問題を引き起こしているのかは、わからないんですが、問題が出ている日付に通常スケジュールが存在していません。仕方が無いので、ログをファイルに落として確認したところ、「春分の日」が入ってました・・・。なんで、春分の日??

他の月のデータも見てみたら、祝日は入っています。祝日が入る事自体は問題ない様ですね。で、他の月の祝日のデータは問題が発生していないので、問題は「春分の日」にあるんだと思われます。実は、「春分の日」と「秋分の日」はその年によって日が異なるため、別の設定ファイルを読み込んで日を決定しています。

そういえば、今年の春分の日はそのファイルの設定が反映されてなかったですね・・。「あ〜、なんかずれてるなぁ。」と思いつつ、放置していました。でも以前は反映はされないものの特に落ちる事はなかったんですが、なんで今回は落ちる様になったのかが良くわかりません。

その春分の日のデータを読み込んでいるところは、「skholidays.rb」内の「SkHolidays#readDataFile」です。

 def readDateFile(fname, year)
  # ファイルには各行に年度と日にちがスペースで区切られた状態で記載されている
  day = nil
  
  # 該当年度の日付読み込み
  File.open(fname, 'r') { |file|
   file.each_line { |line|
    dayInfo = line.split(' ')
    if (dayInfo[0].to_i == year) then
     day = dayInfo
     break
    end
   }
  }
  
  # 戻り値設定
  if (day == nil) then
   ret = nil
  else
   ret = day[1]
  end
  
  return ret
 end


下の方の「戻り値設定」の所で、day[1]をIntegerに変換するのを忘れてますね・・。上の方でyearと比較しているところはちゃんとIntegerに変換してるのに・・。

   ret = day[1].to_i


戻り値を Integer に変換する事により、問題はなくなりました。

これから、気になっていたスケジュールの表示の修正に入ります。って、またなんか出そうで嫌ですねぇ。適当に作ったんで仕方が無いと言えば、仕方が無いですが・・。今、直して行ってるのも、かなり適当ですが・・・。

・・・と書いているうちに、また落ちました。今度はなんだ??

つづく・・・。

助十郎の通常スケジュール表示の修正 [Zaurus]

前回の記事で期間スケジュールの配置は修正できましたが、実行してみると、通常スケジュールの配置に変な現象が出てしまいました。

sukejuro_bug3.png
期間スケジュールの線と重なってしまった・・


モザイクをかけてしまってるのでわかりにくいかもしれませんが、期間スケジュールの線の部分に通常スケジュールがかぶさってしまっています。

通常スケジュールの描画は「skmonth.rb」の「SkMonth#drawSchedule」で行われていました。描画位置の決定はこの辺りですね。

   # 単発スケジュール描画
   painter.setFont(QFont.new('lcfont', FONT_SIZE_DAY))   # ペインタ準備
   dayEvent.each { |event|    
    # 描画位置決定
    frame = getFramePosition(event.start.day)
    if (counter[event.start.day] == nil) then
     counter[event.start.day] = 1
    else
     counter[event.start.day] += 1
    end    


「counter[]」という変数が鍵の様ですが、この変数には各日付の一番下にあるスケジュールの位置を格納しようとしている様です。当初はスケジュールの個数にしようとしてたんですかね。現在、名前と内容が異なってますね・・・。

同じ関数内の下記の場所で「counter[]」を設定しています。

  periodData.overlap.each { |day, overlap|  # counter更新
   counter[day] = overlap.last.level / 3 + 1
  }


ここがまずいですね。「preodData」は前回のエントリで見ていたSkFixedPeriodData型のインスタンスです。ここから、各日付に設定されているスケジュールをひっぱってきていますが、これも前回同様「overlap.last」しか見ていません。最後の要素が一番下に来ていると言う前提ですね。前回の修正で、期間スケジュールの表示位置は、上にスペースが空いている場合、上に移動させる様にしたので、最後の要素が一番下とは限りません。一番下の位置をちゃんと探さないとだめですね。と言う事は、潜在してたんじゃなくて、修正したために出て来たデグレですね・・・。

ここで、全部チェックする様に変更するか、期間スケジュールの配置を決める際に修正前と同じ様に最後の要素が一番下である事を保証する様に変更するか、どっちがいいですかねぇ・・。

前者の場合は、各日付の counter を設定する際に、その日付の最下位のスケジュールの位置を判定する事になりますね。後者の場合、全ての期間スケジュールの位置が決まってから、overlap の各要素をソートをするのが効率良さそうですが、そうすると、overlap の中身は常にソートされているとは限らないと言う事になりますね。仕様的には overlap の各要素は順不同と言う事になってしまいます。

前者も後者も処理を行う位置と処理量にはそれほど差がある様に思えませんが、後者の場合は仕様的にいまいちな感じがする(順不同なのにここではソートされている前提で処理している)ので、前者でいく事にします。overlap の中身は順不同と言うのが仕様ですね。

と言う事で、上記の処理内容を下記の様に変えます。ループに渡される要素「overlap」は何となくややこしい気がしたので、「info」に変えました(それでも、余り妥当でないかも・・)。

  periodData.overlap.each { |day, info| # counter更新
   largestLevel = info.max { |a, b|
        a.level <=> b.level
       }
   counter[day] = largestLevel.level / 3 + 1
  }



以上で、取りあえず今気にしているところは直ったので、リリース作業にうつろうかと思います。

ブログを作る(無料) powered by So-netブログ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。