Adobe AIR 2.6 マスターシリーズの連載してます

僭越ながら Adobe Developer Connection にて Adobe AIR 2.6 マスターシリーズの連載をさせていただいております。 第1回 ネイティブ機能の拡張 カーソルやメニューなどデスクトップ系の機能追加をメインに紹介しています。 第2回 iOSやAndroid向けモバイルアプリ開発環境の新機能 iOS 4 のサポート, Android の USB デバッグなど AIR for iOS, Android 開発の新しい機能について紹介しています。 http://www.adobe.com/jp/joc/devnet/air/articles/adobe_air_03.html CameraUI, カメラロール, マイクなどモバイルアプリケーション向けAPIについて紹介しています。 (2011/07/06) http://www.adobe.com/jp/joc/devnet/air/articles/adobe_air_04.html StageWebView、仮想キーボードについて紹介しています。 (2011/08/24) 上記の全4回が公開中です。

2011年6月18日 · Toshimitsu Takahashi

Win CS5 Web Premium の Flash Builder 4 を Premium 版にアップグレードし Mac にも入れた

Adobe Creative Suite 5 Web Premium (以下、Master Collectionも含む) には Flash Builder 4 Standard が入っています。ただ残念ながら、Web Premium なのに Flash Builder 4 は Standard 版です。Adobe は CS5 Web Premium の所有者に、Flash Builder 4 Premium へのアップグレードライセンスを提供しているので、これを購入することで Premium にできます。ちなみに60,000円とそれ程安くはないです。 先にポイントを Windows 版 CS5 Web Premium パッケージを持っている人が Flash Builder 4 Premium アップグレードライセンスを購入すると、 Eclipse プラグイン版 Flash Builder が使える。 Mac OS X でも Flash Builder を使える。 以上が可能になる。 アップグレードライセンスの購入 http://www.adobe.com/go/flashbuilder_upgrade 上記のページで CS5 Web Premium, CS5 Master Collectionからのアップグレード を選択して購入します。 購入後に、WIN/MAC どちらもスタンドアローン版とプラグイン版がダウンロードできます。あと Cold Fusion Builder も。 私はパッケージ版の Windows 版 CS5 を持っていますが、Mac OS X でもアップグレードした Flash Builder 4 Premium が使えるようです。 ...

2010年9月6日 · Toshimitsu Takahashi

Adobe AIR 2.0 airhttpd でサーバ側でロードした swf のフレームショットをHTML5対応ブラウザで簡易アニメ表示させてみた

なんか airhttpd を使って面白いものを作れないかと思い、SWFLoader を使って外部 swf ファイルをロードし、そのフレームのスナップショットをHTTPクライアントに返すサーバーアプリを思いついた。 HTML 5 の Canvas 対応をブラウザであればそれを JavaScript で描画していくことができる。 開発環境とライブラリ Flex 3.5 Adobe AIR 2.0 β2 airhttpd - http://code.google.com/p/airhttpd/ ファイル構成 lib/ airhttpd-0.5.swc src/ docroot/ index.html webapp/ CGIService.as Main.mxml CGI処理 airhttpd の FileService クラスを継承して CGIService クラスを作ります。 package webapp { import com.tilfin.airthttpd.server.HttpRequest; import com.tilfin.airthttpd.server.HttpResponse; import com.tilfin.airthttpd.services.FileService; import flash.filesystem.File; public class CGIService extends FileService { private var _snapShotFunc:Function; public function CGIService(snapShotFunc:Function, docroot:File) { super(docroot); _snapShotFunc = snapShotFunc; } override public function doService(request:HttpRequest, response:HttpResponse):void { if (request.path == “/action”) { response.contentType = “image/png”; response.body = _snapShotFunc(); return; } super.doService(request, response); } } } ...

2010年2月21日 · Toshimitsu Takahashi

Debug 版 Flash Player で Trace ログを出力するには

設定方法のメモ 参考)デバッガ版の Flash Player の構成 http://livedocs.adobe.com/flex/3_jp/html/help.html?content=logging_04.html mm.cfg の設定 %USERPROFILE%\mm.cfg をテキストエディタで作成して下記を定義する。 ErrorReportingEnable=1 TraceOutputFileEnable=1 ログの出力場所 Windows XP %USERPROFILE%\Application Data[Macromedia](http://d.hatena.ne.jp/keyword/Macromedia)\Flash Player\Logs\flashlog.txt Windows Vista %USERPROFILE%\AppData\Roaming[Macromedia](http://d.hatena.ne.jp/keyword/Macromedia)\Flash Player\Logs\flashlog.txt

2009年2月23日 · Toshimitsu Takahashi

Flex で HTTP リクエストのカスタム ヘッダを使うときの注意事項

Flash Player のバージョンによってブロックされるヘッダがある。 Adobe - カスタマーサポートからのお知らせ GET ではカスタムヘッダがサポートされない flash.net.URLRequestHeader (Flex 3.2) ブラウザの制限により、カスタム HTTP リクエストヘッダは POST リクエストだけをサポートし、GET リクエストはサポートしません。 ※ AIR では可能。 クロスドメインではカスタムヘッダの許可が必要 Flash Player 9およびFlash Player 10ベータのポリシーファイル変更点への対応 | デベロッパーセンター

2009年2月16日 · Toshimitsu Takahashi

Ajax Web アプリケーションを Adobe AIR に移植しようとして気づいたこと

Web サービス(Ajax アプリケーション)を Adobe AIR に移植しようとして気づいたことをメモしておく。 ruby-MySQL のサーバーサイド(ビジネスロジックはなくストレージ機能)は AIR の SQLite データベースで実現する。 気づいたことを徒然なるままに。 AIR は Webkit ベースなので、IE, Firefox, Safari, Opera, Chrome × Win, Mac ブラウザで動いていた Ajax が余裕でそのまま動くと思っていたが、『jQuery のプラグインが動かなかったり、 eval が上手く使えなかったり、:hover が適用されない。』と手痛いことが多い。 Ajax AIR はデバッグがきつい。Firebug が使えないので Trace 地獄になる。Flex (Builder) で開発させたいのが本音だろうなぁ。 ローカルストレージが SQLite なのも微妙。これは Gears でも思ったがローカルストレージを RDB にする意味がわからない。REST や webDAV みたいにあくまでも ターゲット URI を切り替えて使えるような I/F の方が好ましいと思う。 Flex 版も含めての話だが、正式な証明書ではないとしてもインストール時に制作者を表示してほしい。UNKNOWN になってしまうのは。。。 ということでインターフェイスの切り替えで済むような移植を考えていましたが断念しました。 Flex 同様、AIR も バージョン 2 あたりから期待した方がいいかもしれない。 ※蛇足だが Aptana Studio をアップデートしたら AIR の出力がエラーで不能になってしまった。

2009年2月15日 · Toshimitsu Takahashi

Flex でダイナミックにフォームアイテムの並び順とサイズをカスタマイズ可能にしたデモ

遡ること二年前、http://d.hatena.ne.jp/tilfin/20070224/1172319344 というエントリを書きました。 これを強化して公開することにしました。 デモは http://hatena.tilfin.net/CustomizeForm/ です。 左上にフロートするように並べられているフォームです。カスタマイズモードにすると フォームのアイテムをドラッグアンドドロップで並び替えることが可能。 フォームアイテムの右端をドラッグして横幅サイズを変えることが可能。(サイズは最大横幅を 1 として 1/4, 1/3, 1/2, 2/3, 3/4, 1 のいずれか) が可能になります。 特に目的があって作ったわけではないのでコンポーネントとしてきっちり作りこんではいません。ソースはべた貼りしておきます。改変などはご自由にどうぞ。 以前は Flex 2 で今回は Flex 3 です。設計が微妙なのは除いておいて(わかっています)、「ここはもっと簡略して書けるよ!」的なコメントお待ちしています(用意されているプロパティを使っていないとか)。 ファイル構成 src/ net/tilfin/custom/ images/hresize.gif // 横幅変更カーソル DraggingRegion.as DynamicFormExtender.as FormItemsLayoutManager.as Main.mxml メイン MXML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:custom="net.tilfin.custom.*"> <mx:Panel title="Demo / customize form items" x="0" y="0" width="100%" height="100%" cornerRadius="0"> <mx:VBox width="100%"> <mx:VBox width="100%"> <mx:HBox> <mx:Button id="buttonToggle" toggle="true" label="Customize Mode" click="dfe.customizeMode = buttonToggle.selected"/> </mx:HBox> </mx:VBox> <mx:Panel width="100%" height="100%" layout="absolute" title="Music Track Data"> <mx:Form id="form" width="100%" height="100%" backgroundColor="#f9fbfe"> <mx:VBox width="100%"> <mx:HBox width="100%"> <mx:FormItem label="Title" width="50%" labelWidth="80"> <mx:TextInput id="textTitle" text="GIFT" width="100%"></mx:TextInput> </mx:FormItem> <mx:FormItem label="Artist" width="50%" labelWidth="80"> <mx:TextInput id="textArtist" text="Mr.Children" width="100%"></mx:TextInput> </mx:FormItem> </mx:HBox> </mx:VBox> <mx:VBox width="100%"> <mx:HBox width="100%"> <mx:FormItem label="リリース日" width="50%" labelWidth="80"> <mx:DateField id="dateRelease" formatString="YYYY/MM/DD" selectedDate="{new Date(2008, 12, 10)}" width="100%"/> </mx:FormItem> <mx:FormItem label="Album" width="50%" labelWidth="80"> <mx:TextInput text="SUPERMARKET FANTASY" width="100%"></mx:TextInput> </mx:FormItem> </mx:HBox> </mx:VBox> <mx:VBox width="100%"> <mx:HBox width="100%"> <mx:FormItem label="Stars" width="33%" labelWidth="80"> <mx:TextInput text="☆☆☆☆☆" width="100%"></mx:TextInput> </mx:FormItem> <mx:FormItem label="Track" width="33%" labelWidth="80"> <mx:TextInput text="13" width="100%"></mx:TextInput> </mx:FormItem> <mx:FormItem label="Length" width="33%" labelWidth="80"> <mx:TextInput text="5:51" width="100%"></mx:TextInput> </mx:FormItem> </mx:HBox> </mx:VBox> <mx:VBox width="100%"> <mx:HBox width="100%"> <mx:FormItem label="Memo" width="100%" labelWidth="80"> <mx:TextInput text="TOY'S FACTORY Inc.(VAP)" width="100%"></mx:TextInput> </mx:FormItem> </mx:HBox> </mx:VBox> </mx:Form> <custom:DynamicFormExtender id="dfe" x="0" y="0" width="100%" height="100%" backgroundAlpha="0.12" backgroundColor="#222222" targetForm="{form}"> <custom:effectOnSelect> <mx:Fade duration="180" alphaFrom="0.0" alphaTo="1.0"/> </custom:effectOnSelect> <custom:effectOnDrop> <mx:Glow duration="720" alphaFrom="0.6" alphaTo="0.0" blurXFrom="30" blurXTo="15" blurYFrom="30" blurYTo="15" color="#ff22aa"/> </custom:effectOnDrop> </custom:DynamicFormExtender> </mx:Panel> </mx:VBox> </mx:Panel> </mx:Application> DraggingRegion package net.tilfin.custom { import mx.containers.Canvas; import mx.controls.Label; internal class DraggingRegion extends Canvas { private var labelSelectItemDisplay:Label; public function DraggingRegion() { labelSelectItemDisplay = new Label(); this.addChild(labelSelectItemDisplay); labelSelectItemDisplay.move(0, 0); this.width = 0; this.height = 0; } public function set textColor(color:String):void { labelSelectItemDisplay.setStyle("color", color); } public function setItemName(itemname:String):void { labelSelectItemDisplay.text = itemname; } } } DynamicFormExtender package net.tilfin.custom { import flash.display.*; import flash.events.*; import flash.geom.Point; import mx.containers.*; import mx.core.*; import mx.effects.*; import mx.events.FlexEvent; import mx.events.MoveEvent; import mx.events.ResizeEvent; /** \* 動的にフォームアイテムのレイアウトを変更可能にするアタッチメントクラス \* \* @author toshi */ \[Event(name="targetItemChanged", type="flash.events.Event")\] public class DynamicFormExtender extends Container { \[Embed("images/hresize.gif")\] private var hResizeCursor:Class; private var manager:FormItemsLayoutManager; private var _targetForm:Form; private var targetMaker:Canvas; private var dropLine:Canvas; private var draggingRegion:DraggingRegion; private var operation:Canvas; private var formInnerWidth:Number; private var offsetMouseX:int = 0; private var offsetMouseY:int = 0; private var draging:Boolean = false; private var downObject:DisplayObject = null; private var isClicked:Boolean = false; private var selectedItem:FormItem; private var dropAt:Number; private var selItemAt:Number; private var selecteffect:Effect; private var dropeffect:Effect; /** * コンストラクタ */ public function DynamicFormExtender() { this.visible = false; dropLine = new Canvas(); dropLine.width = 2; dropLine.height = 30; dropLine.setStyle("backgroundColor", "#ff1122"); dropLine.setStyle("backgroundAlpha", "0.8"); dropLine.visible = false; targetMaker = new Canvas(); targetMaker.setStyle("cornerRadius", "3"); targetMaker.setStyle("borderStyle", "solid"); targetMaker.setStyle("borderThickness", "1"); targetMaker.setStyle("borderColor", "#776699"); targetMaker.setStyle("backgroundColor", "#9988aa"); targetMaker.setStyle("backgroundAlpha", "0.3"); targetMaker.visible = false; draggingRegion = new DraggingRegion(); draggingRegion.setStyle("cornerRadius", 3); draggingRegion.setStyle("borderStyle", "solid"); draggingRegion.setStyle("backgroundAlpha", "0.5"); draggingRegion.setStyle("backgroundColor", "#e6c6fb"); draggingRegion.textColor = "#000066"; operation = new Canvas(); operation.addEventListener(MouseEvent.MOUSE\_DOWN, operation\_mouseDown); operation.addEventListener(MouseEvent.MOUSE\_MOVE, operation\_mouseMove); operation.addEventListener(MouseEvent.MOUSE\_UP, operation\_mouseUp); } /** \* 変更対象アイテムを選択したときに選択範囲を示すブロックに施すエフェクトをセット \* \* @param effect エフェクト */ public function set effectOnSelect(effect:Effect):void { selecteffect = effect; selecteffect.target = targetMaker; } /** \* アイテムの位置を変更したときに起こすエフェクトをセット \* \* @param effect エフェクト */ public function set effectOnDrop(effect:Effect):void { dropeffect = effect; } /** \* カスタマイズモードを切り替える。 \* \* @param value trueならオン */ public function set customizeMode(value:Boolean):void { this.visible = value; if (!value) { selectedItem = null; invisible(targetMaker); } } /** \* @return 変更対象のアイテムを取得できる */ public function get targetItem():DisplayObject { return selectedItem; } /** \* カスタマイズ可能にするフォームをセットする。 \* \* @param target 対象フォーム */ public function set targetForm(target:Form):void { _targetForm = target; _targetForm.addEventListener(FlexEvent.CREATION\_COMPLETE, customForm\_creationComplete); } // ターゲットフォーム初期化後のアイテムセットアップ private function customForm_creationComplete(event:FlexEvent):void { this.addChild(targetMaker); this.addChild(dropLine); this.addChild(draggingRegion); draggingRegion.visible = false; this.addChild(operation); this.move(\_targetForm.x, \_targetForm.y); operation.width = _targetForm.width \- operation.x; operation.height = _targetForm.height \- operation.y; operation.visible = true; _targetForm.addEventListener(ResizeEvent.RESIZE, \_targetForm\_resize); _targetForm.addEventListener(MoveEvent.MOVE, \_targetForm\_resize); manager = new FormItemsLayoutManager(_targetForm); calcFormInnerWidth(); } private function changeItemPercentWidth(percent:Number):void { invisible(targetMaker); manager.restructWithResizing(selectedItem, percent); dropeffect.target = selectedItem; dropeffect.play(); } private function calcFormInnerWidth():void { formInnerWidth = _targetForm.width \- Number(_targetForm.getStyle("paddingLeft")) \- Number(_targetForm.getStyle("paddingRight")); } private function \_targetForm\_resize(e:ResizeEvent):void { this.width = _targetForm.width \- _targetForm.x; this.height = _targetForm.height \- _targetForm.y; operation.width = this.width; operation.height = this.height; calcFormInnerWidth(); } private function operation_mouseDown(e:MouseEvent):void { if (!e.buttonDown) return; var returnPt:Point = new Point(0, 0); downObject = getChildTargetItem(_targetForm, new Point(e.localX, e.localY), returnPt); if (downObject != null) { offsetMouseX = e.localX \- returnPt.x; offsetMouseY = e.localY \- returnPt.y; if (downObject != selectedItem) { setSelectedItem(downObject, returnPt); } else { isClicked = true; } } else if (!resizing) { draggingRegion.visible = false; targetMaker.visible = false; selectedItem = null; } } private var resizing:Boolean; private var perwid:Number; private function operation_mouseMove(e:MouseEvent):void { if (selectedItem == null) return; if (!e.buttonDown) { var xpos:Number = selectedItem.contentMouseX; if (xpos >= selectedItem.width \- 4 && xpos <= selectedItem.width \+ 2) { cursorManager.setCursor(hResizeCursor, 4, -10); resizing = true; } else { cursorManager.removeAllCursors(); resizing = false; } return; } if (resizing) { // サイズ変更 var x:Number = _targetForm.contentMouseX - selectedItem.x; if (x < formInnerWidth * 0.29) { perwid = 25; targetMaker.width = formInnerWidth * 0.25; } else if (x < formInnerWidth * 0.42) { perwid = 33; targetMaker.width = formInnerWidth * 0.33; } else if (x < formInnerWidth * 0.58) { perwid = 50; targetMaker.width = formInnerWidth * 0.50; } else if (x < formInnerWidth * 0.71) { perwid = 67; targetMaker.width = formInnerWidth * 0.67; } else if (x < formInnerWidth * 0.87) { perwid = 75; targetMaker.width = formInnerWidth * 0.75; } else { perwid = 100; targetMaker.width = formInnerWidth; } return; } if (!draging) { // ドラッグ開始 draging = true; draggingRegion.width = selectedItem.width; draggingRegion.height = selectedItem.height; draggingRegion.visible = true; } else { var ret:Array; ret = findInsertTargetItem(_targetForm, new Point(e.stageX, e.stageY)); dropAt = ret\[0\]; if (ret\[1\] == 1) { dropLine.visible = true; } else if (selItemAt < dropAt) { dropLine.visible = (dropAt - 1 != selItemAt); } else { dropLine.visible = (dropAt != selItemAt); } } draggingRegion.move(e.localX - offsetMouseX, e.localY - offsetMouseY); } private function operation_mouseUp(e:MouseEvent):void { if (resizing) { changeItemPercentWidth(perwid); resizing = false; } else if (draging) { invisible(draggingRegion); dropLine.visible = false; draging = false; invisible(targetMaker); var perwid:Number = -1; // 段の間に挿入するときは幅をいっぱいにする if (dropLine.width == formInnerWidth) perwid = 100; if (manager.insertItemAt(selectedItem, dropAt, perwid)) { dropeffect.target = selectedItem; dropeffect.play(); } selectedItem = null; selItemAt = -1; dropAt = -1; } else if (isClicked) { invisible(targetMaker); selectedItem = null; } isClicked = false; downObject = null; } // 再帰的に ptの位置にある FormItem を探して返す。returnptにはフォームアイテムの相対的位置がセットされる。 private function getChildTargetItem(parent:Container, pt:Point, returnpt:Point):DisplayObject { for each (var element:DisplayObject in parent.getChildren()) { if (getObjectContains(element, pt)) { pt.x -= element.x; pt.y -= element.y; returnpt.x += element.x; returnpt.y += element.y; if (element is FormItem) { return element; } else { return getChildTargetItem(Container(element), pt, returnpt); } } } return null; } // StagePointの位置から FormItem の挿入位置を探す。 // ドロップマーカーの位置も同時にセット。 private function findInsertTargetItem(parent:Container, sPt:Point):Array { var zeroPt:Point = new Point(0, 0); var gFormPt:Point = _targetForm.contentToGlobal(zeroPt); var pre_item:FormItem = null; var x:Number; var y:Number; var i:Number = 0; for each (var item:FormItem in manager.itemList) { var gPt:Point = item.localToGlobal(zeroPt); if (sPt.y < gPt.y) { if (pre_item) { y = pre_item.localToGlobal(zeroPt).y; if (sPt.y < y + pre_item.height) { dropLine.move(pre_item.localToGlobal(zeroPt).x - gFormPt.x + pre_item.width, y - gFormPt.y); dropLine.setActualSize(2, pre_item.height \+ 2); return \[i, 0\]; } } dropLine.move(Number(_targetForm.getStyle("paddingLeft")), gPt.y - gFormPt.y - 3); dropLine.setActualSize(formInnerWidth, 2); return \[i, 1\]; } if (sPt.y <= gPt.y + item.height) { if (sPt.x <= gPt.x + item.width \* 0.5) { dropLine.move(gPt.x - gFormPt.x, gPt.y - gFormPt.y); dropLine.setActualSize(2, item.height \+ 2); return \[i, 0\]; } } pre_item = item; i++; } if (pre_item) { y = pre_item.localToGlobal(zeroPt).y; if (sPt.y < y + pre_item.height) { dropLine.move(pre_item.localToGlobal(zeroPt).x - gFormPt.x + pre_item.width, y - gFormPt.y); dropLine.setActualSize(2, pre_item.height \+ 2); return \[i, 0\]; } dropLine.move(Number(_targetForm.getStyle("paddingLeft")), gPt.y - gFormPt.y + pre_item.height \+ 2); } else { dropLine.move(0, 0); } dropLine.setActualSize(formInnerWidth, 2); return \[i, 1\]; } /** private function findInsertTargetItem(parent:Container, pt:Point, returnpt:Point):DisplayObject { for each (var element:DisplayObject in parent.getChildren()) { if (getObjectContains(element, pt)) { pt.x -= element.x; pt.y -= element.y; returnpt.x += element.x; returnpt.y += element.y; if (element is HBox) { return findInsertTargetItemFromHBox(Container(element), pt, returnpt); } else { return findInsertTargetItem(Container(element), pt, returnpt); } } } return null; } private function findInsertTargetItemFromHBox(hbox:Container, pt:Point, returnpt:Point):DisplayObject { var item:DisplayObject = null; for each (item in hbox.getChildren()) { if (pt.x <= item.x + item.width * 0.5) { returnpt.x += item.x; return FormItem(item); } } if (item == null) return null; returnpt.x += item.x + item.width; return FormItem(item); } */ private function getObjectContains(object:DisplayObject, pt:Point):Boolean { return (pt.x >= object.x && pt.x < object.x + object.width && pt.y >= object.y && pt.y < object.y + object.height); } private function setSelectedItem(target:DisplayObject, pt:Point):void { selectedItem = FormItem(target); selItemAt = manager.itemList.getItemIndex(selectedItem); draggingRegion.setItemName(selectedItem.label); targetMaker.move(pt.x, pt.y); targetMaker.width = target.width \+ 4; targetMaker.height = target.height \+ 4; targetMaker.visible = true; selecteffect.play(); dispatchEvent(new Event("targetItemChanged")); } private function invisible(object:DisplayObject):void { object.width = 0; object.height = 0; object.visible = false; } } } #### FormItemsLayoutManager package net.tilfin.custom { import flash.display.*; import flash.events.*; import mx.collections.ArrayCollection; import mx.containers.*; import mx.core.*; /** \* フォームアイテムの配置を管理するクラス \* \* @author toshi */ internal class FormItemsLayoutManager { private var form:Form; private var itemlist:ArrayCollection; /** \* コンストラクタ \* \* @param target 対象フォーム */ public function FormItemsLayoutManager(target:Form) { this.form = target; findItems(); } /** \* dest の位置に src を 挿入します。 \* \* @param src 移動するアイテム \* @param dest 挿入位置のアイテム。nullの場合は最後に追加。 */ public function insertItemAt(src:FormItem, destIndex:Number, perwid:Number = -1):Boolean { var obj:Object; var removedIdx:int = itemlist.getItemIndex(src); if (removedIdx < destIndex) destIndex--; if (perwid == -1 && removedIdx == destIndex) return false; if (destIndex < itemList.length) { obj = itemlist.removeItemAt(removedIdx); itemlist.addItemAt(obj, destIndex); } else { obj = itemlist.removeItemAt(removedIdx); itemlist.addItem(obj); } if (perwid != -1) { FormItem(obj).percentWidth = perwid; } restruct(); return true; } public function isMakerAfter(src:FormItem, dest:FormItem):Boolean { return (itemlist.getItemIndex(src) + 1 <= itemlist.getItemIndex(dest)); } public function get itemList():ArrayCollection { return itemlist; } /** \* フォームのアイテム配置を再構築します。 */ public function restruct():void { restructWithResizing(null, 0); } /** \* 幅を変更してフォーム内のアイテム配置を再構築します。 \* 段組みにするための HBox を自動的に組み入れます。 \* \* @param item 幅を変更するアイテム \* @param newwid 新しいPercentWidth */ public function restructWithResizing(item:FormItem, newwid:Number):void { form.removeAllChildren(); var len:Number = 0; var box:HBox = createBox(); for each (var fi:FormItem in itemlist) { var itempw:Number; if (fi == item) { itempw = newwid; } else { itempw = fi.percentWidth; } if (len + itempw > 100) { box = createBox(); len = 0; } box.addChild(fi); if (fi == item) { fi.percentWidth = itempw; } len += itempw; if (len >= 90) { len = 0; box = createBox(); } } } private function findItems():void { itemlist = new ArrayCollection(); findItemsRecusively(form); } private function findItemsRecusively(parent:Container):void { for each (var element:DisplayObject in parent.getChildren()) { if (element is FormItem) { itemlist.addItem(element); } else { findItemsRecusively(Container(element)); } } } private function createBox():HBox { var vbox:VBox = new VBox(); vbox.percentWidth = 100; var hbox:HBox = new HBox(); hbox.percentWidth = 100; form.addChild(vbox); vbox.addChild(hbox); vbox.visible = true; hbox.visible = true; return hbox; } } }

2009年2月11日 · Toshimitsu Takahashi

Adobe AIR の SQL 機能を試してみるためにデモアプリを作ってみた

AIR には Flex(MXML/ActionScript) と Ajax(HTML/JavaScript) の二つの作成方法があるが、今回は後者を選んだ。 http://help.adobe.com/ja_JP/AIR/1.5/devappshtml/ http://www.adobe.com/jp/devnet/air/ajax/ 開発環境は Aptana Studio を使った。 デモアプリはテキストエリアに SQL 文を書いて実行すると、結果が表示されるというもの。SELECT であればテーブルに結果が表示される。テーブルの表示は、Adobe だけに Spry のデータセット機能を使ってみることにした。 Aptana Studio でプロジェクトを作成 File -> New.. -> Project -> Adobe AIR Project を選択する。 プロジェクトに「AirSQLiteTest」を設定する。 Import JavaScript Library までそのまま [Next] をクリック。 Adobe Spry 1.6 にチェックを入れて [Finish] をクリック。 ソースコード AirSQLiteTest.html が AIR 本体を構成する。ソースコードは以下。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 <html> <head> <title>AIR SQL Test</title> <script type="text/javascript" src="lib/air/AIRAliases.js"></script> <script type="text/javascript" src="lib/spry/includes/SpryData.js"></script> <style type="text/css"> div { margin:16px; } #textSql { width:100%; height:120px; } #textResult { width:100%; height:60px; } p { margin:4px 0; } table th, table td { border:1px solid gray; } th, td { padding:8px } th { cursor: default; } </style> <script type="text/javascript"> /** \* AIR SQL を操作する DBClient \* \* @param {String} dbname データベース名 \* @param {Function} closure クロージャ(省略可能) \* 指定された場合はクロージャ引数にこのオブジェクトが渡り、 \* 処理終了とともに接続が閉じられる。 */ function DBClient(dbname, closure){ if (closure) { var dbc = new DBClient(dbname); closure(dbc); dbc.close(); } else { this.open(dbname); } } DBClient.prototype = { /* \* データベースを開く \* \* @param {String} dbname データベース名 */ open: function(dbname){ try { this.conn = new air.SQLConnection(); var dbfile = null; if (dbname) { dbfile = air.File.applicationStorageDirectory.resolvePath(dbname + ".db"); } this.conn.open(dbfile); } catch (error) { statustext.innerText = "Error opening database"; air.trace("error.message:", error.message); air.trace("error.details:", error.details); return; } }, /* \* データベース接続を開じる */ close: function(){ if (this.conn) { this.conn.close(); this.conn = null; } }, /* \* SQL文を実行する \* \* @param {String} sqltext SQL文 \* @param {Function} cbsuccess クエリ成功時のコールバック関数 \* @param {Function} cberror クエリ失敗時のコールバック関数 */ execute: function(sqltext, cbsuccess, cberror){ try { var stmt = new air.SQLStatement(); stmt.sqlConnection = this.conn; stmt.text = sqltext; stmt.execute(); cbsuccess(stmt.getResult()); return true; } catch (error) { if (cberror) cberror(error); return false; } } } </script> </head> <body> <div> <div> <p>SQL Statement:</p> <textarea id="textSql">CREATE TABLE IF NOT EXISTS sample ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, score INTEGER )</textarea> </div> <div> <button id="buttonExecute">execute SQL</button> </div> <div> <p>Query Result:</p> <textarea id="textResult"></textarea> </div> <div> <table spry:region="Results"> <caption>Select Result</caption> <thead> <tr> <th spry:sort="{ds_RowNumberPlus1}">#</th> <th spry:sort="id">id</th> <th spry:sort="content">content</th> <th spry:sort="score">score</th> </tr> </thead> <tbody spry:repeatchildren="Results"> <tr> <td>{ds_RowNumberPlus1}</td><td>{id}</td><td>{content}</td><td>{score}</td> </tr> </tbody> </table> </div> </div> <script type="text/javascript"><!-- function $(id) { return document.getElementById(id) }; var Results = new Spry.Data.DataSet(); $("buttonExecute").onclick = function(e){ // SQLを実行する DBClient("sampledb", function(dbh){ dbh.execute($("textSql").value, function(result){ // 成功 $("textResult").value = "QUERY OK, " \+ result.rowsAffected + " rows affected"; Results.data = result.data ? result.data : {}; Results.loadData(); }, function(error){ // 失敗 $("textResult").value = error.message + "\\n" \+ error.detailID + ": " \+ error.details; }); }); }; //--> </script> </body> </html> 試してみる プロジェクトを選択した状態で、Run -> Run… デフォルトで SQL 文には CREATE TABLE が入っている。 データをインサート。 SELECT でテーブルを表示。 ...

2009年1月30日 · Toshimitsu Takahashi

Vista で Adobe Updater を実行したらブルースクリーン

Windows Vista Ultimate に Adoebe CS 3.3 Web Premium をインストールして、Adobe Updater を実行したらインストール中にブルースクリーンで終わってしまった。さらにそのまま強制的に再起動したもののログオン後にまたもやブルースクリーンに。。。 Adobe - カスタマーサポートからのお知らせ を見ると、Adobe Updater は使わない方がいいようだ。とりあえず現状ではどうしようもないので、システムの復元をしてみることにした。 Windows をセーフモードで起動する。 「システムの復元」を開く。 ポイントを選択して、復元を開始する。 再び、再起動。しかしまたもやブルースクリーン。 再度、セーフモードで msconfig から「システムの設定」を開く。Adobe 系のサービスとスタートアップを全て無効にして再起動。 %AppData% の Adobe 内にエクスプローラでアクセスしたところ、ブルースクリーン。どうもファイルシステムの部分でおかしくなっているようだ。 Windows をセーフモード+コマンドプロンプトで起動する。 cd %AppData% Roming, Local, LocalLow の全ての Adobe フォルダを削除。(>rmdir /S /Q Adobe) 再び起動、ブルースクリーン。。。 キレそうなんですが。。。 もうHDDがヤバいのかもしれない。 (2008/11/19 追記) 結局、OSから入れなおしました。そして Vista の Comeplete PC バックアップを試し始めました。Firefox が相変わらずクラッシュしまくりなのも変わらないです。

2008年11月18日 · Toshimitsu Takahashi

Adobe Creative Suite 4 が12月中旬に日本語版発売

英語版は既に発売している。ようやく日本語版が発表され、先行予約が始まっている。 http://www.adobe.com/jp/ CS3を今日 11/11 以降、買った場合は無償アップグレードができるそうだ。 http://support.adobe.co.jp/faq/faq/qadoc.sv?740+001 いい値段だが Web Premium がほしい。Flex Builder も付いていたらと思う。。。

2008年11月11日 · Toshimitsu Takahashi