Ring Controls v1.0.0の公開

Windows Phone用のコントロールRing Controls」を公開しました。
先日「Ring Clock」というアプリを作成した、というブログを書いてそのアプリで使ったコントロールを公開するといっていましたが、ようやくここにきて公開することができました。Windows Phone 7.x用に作ってあります。8だと動くかしら??
Ring Controls


Ring Controlsを使えば下の画像のようなドーナツの形状をしたコントロールを使うことができます(このアプリはプロジェクトにサンプルとして含まれています)。

この画像は時計を表していますが、円の中には数字だけでなく画像や動画などのコンテンツはなんでも配置できるので、他にもいろいろな用途に使えると思います。デザインもWindows Phoneに合わせてソリッドな感じになっているので、普通に配置してもデザインを損なわずにむしろ新しいデザインとしてフィットします。手っ取り早くどんな動きをするのか知りたい人は、このRingを使ったアプリ「Ring Clock」を公開しているので、そちらをダウンロードして見てもらうと分かりやすいです(ステマ)。

使い方

使い方を簡単に説明します。

  1. まずはCode Plexにある「Ring Controls」のダウンロードページからバイナリをダウンロードします。
  2. 次にそのファイルを解凍してRingControls.dllをプロジェクトの参照に加えます。
  3. その後に、Ringを使いたいXAML上でnamespaceを追加し、コントロールを配置します。

namespaceの追加:

xmlns:rcontrols="clr-namespace:RingControls;assembly=RingControls"

コントロールの追加:

<rcontrols:Ring
    x:Name="MyRing"
    Max="12"
    Radius="75"
    Thickness="20"
    Foreground="#B9CDE5"
    Highlight="#0070C0"
    IndexChanged="IndexChanged">
</rcontrols:Ring>

Ringコントロールの各プロパティは以下の画像の通りです。

基本的にはこれだけで使えるのですが、ここには書いてないプロパティもあるのでその説明を少し。

プロパティ
  • Indexプロパティ
    • Ringの青い部分はIndexプロパティを変えることで変わってきます。0〜MAXの値で数値を指定すればその位置まで表示されます。
  • IsEnabledTouchWheelプロパティ
    • IsEnabledTouchWheelというプロパティをTrueに設定すればユーザーがタッチホイールの感覚でRingのIndexを変更できます。
  • Cycleプロパティ
    • Cycleプロパティを変更すれば、何周でMAXになるかを調整することができます。例えば、時間を24時間表記からam/pm表記に変更したい場合にこのCycleを2に設定しておくと、2周することで24になります。つまり1周が12になるということです。
サンプルアプリ

円の中心に表示するコンテンツを更新するにはIndexChangedイベントを受け取って、そのIndexに応じてコンテンツを切り替えます。
プロジェクトに含まれるサンプルアプリの時計ではそれぞれ時・分・秒を表すRingをタイマーで更新し(Rxを使ってます)、Indexの更新があったときに起こるIndexChangedイベントを受け取ることで、Ringのコンテンツに時間を設定しています。

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    _disposer = Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1))
        .ObserveOnDispatcher()
        .Subscribe(value =>
        {
            Hour.Index = DateTime.Now.Hour;
            Minute.Index = DateTime.Now.Minute;
            Second.Index = DateTime.Now.Second;
        });
}

private void Hour_IndexChanged(object sender, RingControls.IndexChangedEventArgs args)
{
    Hour.Content = args.Index;
}

private void Minute_IndexChanged(object sender, RingControls.IndexChangedEventArgs args)
{
    Minute.Content = args.Index;
}

private void Second_IndexChanged(object sender, RingControls.IndexChangedEventArgs args)
{
    Second.Content = args.Index;
}

Indexに合わせてコンテンツを変更する場合はこのように設定します。


今後はこのRingを利用して他のコントロールを作成し公開していく予定です。
よろしくお願いします。

Fast App Resume for Windows Phone 8

Windows Phone 8 SDK Advent Calendarの5日目です。

Windows Phone 8で追加されたFast App Resumeについての紹介です。

Windows Phone 7.5(Mango)からFast App Switchingという機能のが追加されました。これは以前に動いていたアプリケーションをメモリ上に残すことで、バックボタンやタスクスイッチャーで元のアプリケーションに戻ってきた時に、なにもしなくても以前の状態のまま起動することができました。

Windowds Phone 8からはそれに付け加えFast App Resumeという機能が使えます。もともと利用できたFast App Switchingではタイルの画面からアプリケーションを起動すると、アプリケーションは新しいインスタンスを起動していましたが、Fast App Resumeではもしメモリ上にアプリケーションが残っていたらタイルの画面からアプリケーションを起動しても新しいインスタンスを生成せずに以前の状態を残して起動します。

Fast App ResumeはデフォルトではOffになっているので、もし有効にしたければWMAppManifest.xmlに以下のようにActivationPolicyをResumeに設定します。

<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume"/>

これだけでFast App Resumeの恩恵を受けることができます。


ただしこれは簡単に設定はできますが使うときは要注意です。というのもアプリケーションをどのように起動するかによって履歴を残すべきかどうか考慮する必要があるからです。
アプリケーションを起動するタイミングについて考えてみましょう。

  1. スタート画面のアプリケーションのリスト
  2. スタートに立てたピン
  3. アプリケーションから作成したセカンダリータイル
  4. トースト通知
  5. ...

このようにアプリケーションが起動するタイミングはたくさんあります。それぞれについて以前の状態を復元してよいのか考慮する必要があります。
例えばセカンダリタイルやトースト通知から起動したときはどうでしょう?これらは特定のページを開くための機能なので、過去の状態とは関係がありません。そのため過去の履歴は残っていてほしくないはずです。もしFast App Resumeを有効にすると過去の履歴が残っているので、そのときは自前で履歴を削除する必要があります。

このようにFast App Resumeはとても簡単に利用できるのですがプログラム上でさまざまな起動パターンを考慮しなければなりません。
次回はこの実装について見ていきたいと思います。

Lumia Geek 8 Week Challengeが開催されています!

Windows Phone GeekにてLumia Geek 8 Week Challengeが開催されています。
http://www.windowsphonegeek.com/Content/Nokia/competition-header-v3.jpg

いろいろな賞が用意されていて、1位になると2013年にバルセロナで開催されるMWCに行けるようです。しかも旅費は全部開催側でもってくれるようです!

2012年11月13日〜2013年1月8日までにWindows Phoneのアプリを作成するかアップデートした開発者を対象としています。一人につき複数のアプリを登録してもよいそうです。


登録するには以下の3ステップが必要になりますが、とても簡単です。まずはLumia Geek 8 Week Challenge のサイトへ行ってEnter Nowをクリックしましょう。

  1. Sign in - サインインする(TwitterFacebookのアカウントでOK)
  2. Tell us where you are - 国を選ぶ
  3. Enter link to your app in the marketplace - アプリへのリンクを登録

これだけです。5分とかかりません。私も先日作成した「Ring Clock」を登録しました。

登録したアプリは数日するとサイトに登録されます。


よかったらこちらからRing Clockの投票ができますので清き一票をよろしくお願いします。
http://www.windowsphonegeek.com/lumia-geek-8-week-challenge/ring-clock

とても楽しそうなイベントなので日本からもぜひ参加しましょう!

Ring Clockを作りました

ついでにWindows Phoneアプリ「Ring Clock」を作りました。なんのついでかは後にして先に宣伝を。

Ring Clockのメイン機能は時計です。ただそれだけだとさみしいのでタイマーとストップウォッチも機能に加えました。といっても機能は時計・タイマー・ストップウォッチといたってシンプルです。ただ唯一凝ったのがデザインです。デザイナーでない自分がデザインに凝ったということは、つまりものすごく時間がかかったということです。プログラムにかけた時間の5倍はかかってます。まじで。
ということでデザインに関する一部の機能は有料となっていますが、トライアル版でもほぼすべての機能が使えます。でも有料版を購入すると以下のことができるようになるのでお勧めです。

  • リングの色を変更できる
  • リングの厚みを変更できる
  • スクリーンのロックを解除できる(ロックがかからないようにできる)

いろいろと自分の好みに合わせてデザインを変えてみたい方はお試しください。

ダウンロードはこちらからです。


で、そもそもなんのついで作ったのかというと、タッチホイールを実現するためのカスタムコントロールを作成していてそれのサンプルアプリとして作り始めたのですが、思わず作りこんでしまいアプリとして公開することになりました。Ring Clockでタッチホイールを試すにはタイマーの機能のところで円をタッチしてぐるりと回せば時間を設定できるようになっているので、そこで試せます。

ということで後日こちらのコントロールの方を公開しますので、そちらの方もよろしくお願いします。

デフォルト引数の値を動的に変える

デフォルト引数は関数の引数にあらかじめ定義された値を入れておくことで、関数を呼ぶときに明示的に値を入れない場合はその値が使われるようになります。

static void Print(int n = 3 /* デフォルト引数 */)
{
    printf("%d\n", n);
}

// 引数を明示的に指定
Print(5); // => 5
// 引数を明示しないとデフォルト引数の3が引数に渡る
Print(); // => 3


これだけを見るとデフォルト引数の値は固定値を取りそうですが、実は式を取ることができるので値を動的に変えることができます。

例えばデフォルト引数の値を1〜100のランダムな数字にしてみます。

#include <stdlib.h>
#include <time.h>

static int GetNumber()
{
    return rand() % 100 + 1;
}

static void Print(int n = GetNumber())
{
    printf("%d\n", n);
}

srand((unsigned int)time(NULL));
Print(); // => 1〜100までのランダムな数字
Print(); // => 上とは違う値


こうすることでデフォルト引数の取り得る値は1〜100と動的に変わるわけです。

これを応用するといろいろな書き方ができます。

// 三項演算子
static void Print(int n = 0 ? 0 : 3*3) {}
// グローバル変数
int g_n = 0;
static void Print(int n = g_n) {}
static void Print(int n = g_n++) {}
static void Print(int n = g_n = 3) {}
// 関数
static void Printf(int n = printf("abc")) {}
static void Printf(int n = g_n = printf("abc")) {}

さらにカンマで区切ることで複数の式を実行することもできます。

static void Print(int n = (
    g_n = printf("abc\n"),
    g_n+1,
    g_n*g_n)
)
{
    printf("%d\n", n);	
}
Print(); // => 16


使い道は分かりませんが...


※環境は、VC++2010 Express

DataMapperでPostgreSQLのILIKE演算子を実装する

PostgreSQLのLIKE演算子は大文字と小文字を区別します。そこで大文字と小文字を区別しないための演算子として「ILIKE」という演算子が用意されています。

しかし、ORMはILIKE演算子を実装していない、結局力づくで直接SQLを発行しないとILIKE演算子を利用できない、なんてことがあります。当然RubyのORMであるDataMapperもILIKE演算子が使えません。それでは困るのでILIKE演算子を使えるように実装しました。

これでDataMapperを使ってこんな風にILIKE演算子を使うことができます。

model.all('title.ilike' => "%#{word}%")