flashcast:フリーで働くITエンジニア集団のブログ: google翻訳APIを使ったAIRアプリを作る!(Twitterに投稿編)の続きです。
前回、翻訳結果をtwitterに投稿する部分を実装しました。いろいろテストしているうちに、クリップボードを監視する部分に問題があることがわかりました。
今の仕様では、クリップボードの中身に変化がないと、アイコンが回転しません。アイコンが回転しないと翻訳ができないため、2回連続で同じ文字をコピーした際には、アイコンが回転せず、翻訳ができないのです。
これはよろしくない。
ということで、以下のような仕様に変更することにしました。
- クリップボードの監視をやめる。
- アイコンをクリックした時に、クリップボードの文字列を翻訳する。
- 翻訳後には、(とりあえず)10秒間アイコンを回転させ、回転中のアイコンをクリックされたらtwitterに翻訳結果を投稿する。
- 10秒間、クリックされなければ回転を止める。
こうすることで、前回課題として残った、
twitterに翻訳結果を投稿しないと、次の翻訳はできないので不便です。その点は、今後、改善していきたいと思います。
の点も、改善できると思います。
まず、1.の仕様変更により、クリップボードを監視するクラスは不要になりました。それにともない、そのインスタンスも不要になります。
続いて、2.の部分の、アイコンをクリックされた時のロジックを追加します。46行目になります。
package {
// ~ 省略 ~
public class IconManager extends EventDispatcher
{
// ~ 省略 ~
private var isAnimate:Boolean = false;
private var isSecond:Boolean = false;
private var isDecrement:Boolean = false;
private var isReverse:Boolean = false;
private var _gmodel:TranslateModel;
private var _timer:Timer;
public function IconManager():void {
}
public function initIconManager(gmodel:TranslateModel):void {
_gmodel = gmodel;
_timer = new Timer(10000);
_timer.addEventListener(TimerEvent.TIMER, onTimerHandler);
initIcon();
}
// ~ 省略 ~
private function onIconClick(event:Event):void {
if (isSecond) {
if (isAnimate) {
if (NativeApplication.supportsSystemTrayIcon) {
setIcon(newIconBitmap);
}
isAnimate = false;
}
else {
if (!Clipboard.generalClipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)) {
return;
}
_gmodel.Original = Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT) as String;
}
dispatchEvent(new TranslatorSampleEvent(TranslatorSampleEvent.ICON_CLICK));
}
else {
isSecond = true;
}
}
// ~ 省略 ~
private function onTimerHandler(event:TimerEvent):void {
isAnimate = false;
if (NativeApplication.supportsSystemTrayIcon) {
setIcon(newIconBitmap);
}
dispatchEvent(new TranslatorSampleEvent(TranslatorSampleEvent.ICON_TIMER));
}
public function timerStart():void {
_timer.start();
}
public function timerStop():void {
_timer.stop();
}
}
}
ここでは、アイコンをクリックされた時に、クリップボードの中身を取得するようにしています。また、仕様変更4.の10秒間、クリックされなければ回転を止める部分は、Timerクラスを使って実装しています。
メインのロジックは、以下のようになります。
package
{
import flash.events.Event;
import mx.binding.utils.ChangeWatcher;
import mx.core.Application;
import mx.events.PropertyChangeEvent;
public class TranslatorSample7Base extends Application
{
private var imanager:IconManager;
private var gmanager:TranslateManager;
private var tmanager:TwitterManager;
private var gmodel:TranslateModel;
private var tweet:Boolean;
public function TranslatorSample7Base():void {
}
public function initApp():void {
gmodel = new TranslateModel();
imanager = new IconManager();
gmanager = new TranslateManager();
tmanager = new TwitterManager();
imanager.initIconManager(gmodel);
gmanager.initTranslateManager(gmodel);
tmanager.initTwitterManager();
ChangeWatcher.watch(gmodel, '_result', onResultChangeHandler);
imanager.addEventListener(TranslatorSampleEvent.ICON_CLICK, onIconClick);
imanager.addEventListener(TranslatorSampleEvent.ICON_TIMER, onIconTimerHandler);
}
private function onIconClick(event:TranslatorSampleEvent):void {
if (tweet) {
this.removeEventListener(Event.ENTER_FRAME, imanager.iconAnimate);
imanager.timerStop();
tmanager.Tweet(gmodel.Translated.substr(0, 140));
tweet = false;
}
else {
gmodel.Result = false;
gmanager.Translate("1.0", gmodel.Original, "en", "ja");
}
}
private function onResultChangeHandler(event:PropertyChangeEvent):void {
if (event.newValue as Boolean) {
this.addEventListener(Event.ENTER_FRAME, imanager.iconAnimate);
imanager.timerStart();
tweet = true;
}
}
private function onIconTimerHandler(event:TranslatorSampleEvent):void {
this.removeEventListener(Event.ENTER_FRAME, imanager.iconAnimate);
imanager.timerStop();
tweet = false;
}
}
}
仕様変更3.の翻訳後に、(とりあえず)10秒間アイコンを回転させる部分は、前回まで、
ChangeWatcher.watch(gmodel, '_translated', onTranslatedChangeHandler);
のように、「翻訳結果」の変化をウォッチするようにしていました。今回の仕様変更で、翻訳結果にも変化がないケースも発生するようになるので、新たにModelクラスに「翻訳処理の実行結果(正常終了/異常終了)」を格納するためのメンバーを追加し、それをウォッチするようにしました。
ChangeWatcher.watch(gmodel, '_result', onResultChangeHandler);
メンバーを追加したModelクラスです。
package
{
[Bindable]
public class TranslateModel
{
public var _original:String;
private var _translated:String;
public var _result:Boolean;
public function TranslateModel()
{
}
public function set Original(original:String):void {
_original = original;
}
public function get Original():String {
return _original;
}
public function set Translated(translated:String):void {
_translated = translated;
}
public function get Translated():String {
return _translated;
}
public function set Result(result:Boolean):void {
_result = result;
}
public function get Result():Boolean {
return _result;
}
}
}
翻訳実行後に、正常終了したら変化が起こるよう、翻訳直前に、このメンバーを初期化しています。
gmodel.Result = false;
gmanager.Translate("1.0", gmodel.Original, "en", "ja");
こうすることで、翻訳結果が正常だったときのみ、アイコンを回転させるようにできます。
実行時のデバックトレースです。つぶやいた翻訳結果を出力しています。
※ 3回つぶやいてますが、twitterには1回しか投稿されませんでした。連続した同じつぶやきは無視するというtwitterの仕様だと思います。
これでクリップボードを常時Timerで監視する必要なくなったため、アプリも軽くなり、ロジックもシンプルになりました!
サンプルソース
サンプルソースをダウンロードできるようにしておきます。
- TranslatorSample7:ダウンロード
