Creative Suite SDKによるマルチアプリケーション向けエクステンションパネルの作成

ご無沙汰しています。まあ、クソ忙しいです。でも他の人ほどではありません。まあそんな事はどうでもよいですね。
え〜、CSSDKではマルチなアプリケーション向けにエクステンションを作るという芸当が可能です。どういう事かというと、ひとつのインストーラーでAIやID、PSにエクステンションをインストール出来ると言う事です。
まあ、全然説明になってませんが、ひとつサンプルをご覧下さい。

以前にやったフリッカーから画像引っぱってきてどうのこうのってヤツなのですが、これをAIやPSでも使えるようにします。
まずAIです。

mltai.png

こちらはID

mltid.png

そしてPS

mltps.png

これらは1つのエクステンションです。エクステンションマネージャーで見てみると、

emai.png

emid.png

emps.png

ご覧のように全て同じ拡張機能名でインストールされているのが分かります。
さて、それぞれくせの強いアプリケーションでありオブジェクトモデルに関しても全く互換性のかけらもありません。いったいどうやって一つのエクステンションでまかなうかというと、それぞれのオブジェクトモデルに対応したコードを別々に用意するだけです。めんどくせぇ〜
ということでコードを見てみましょう。

#main.mxml
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication
    xmlns:mx=”http://www.adobe.com/2006/mxml&#8221;
    xmlns:aral=”*”
    creationComplete=”photoService.send();”>
    <mx:HTTPService id=”photoService”
        url=”http://api.flickr.com/services/feeds/photos_public.gne&#8221;
        resultFormat=”e4x”
        result=”photoResultHandler(event);”
        fault=”photoFaultHandler(event);”>
        <mx:request>
            <format>atom</format>
        </mx:request>
    </mx:HTTPService>

    <mx:Script>
        <![CDATA[
            import flash.net.*;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import flash.events.*;
            import flash.filesystem.*;

            private var hostName:String = HostObject.mainExtension;
            private var fileName:String;
            private var FileGet:URLLoader;
            private namespace atom = “http://www.w3.org/2005/Atom&#8221;;
            use namespace atom;

            [Bindable]
            private var photoFeed:XML;

            private function parseImageUrl(fromHtml:XMLList):String
            {    
                var pattern:RegExp = /img src=”(.+?)” /;
                var results:Array = pattern.exec(fromHtml);
                var imageURL:String = results[1];
                return imageURL;
            }

            private function photoResultHandler(event:ResultEvent):void
            {
                photoFeed = event.result as XML;
            }

            private function photoFaultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.message, “Could not load photo feed”);
            }

            private function getCon(evt:MouseEvent):void
            {
                FileGet = new URLLoader();
                FileGet.dataFormat = URLLoaderDataFormat.BINARY;
                FileGet.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
                FileGet.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
                FileGet.addEventListener(Event.COMPLETE, onComplete);
                var pattern:RegExp = /http:\/\/.+\/.+\/(.+\..+)/;
                var fNm:Array = pattern.exec(evt.currentTarget.source);
                fileName = fNm[1].replace(“m.”,”b.”);
                var tgtadd:String = String(evt.currentTarget.source).replace(“m.”,”b.”);
                var request:URLRequest = new URLRequest(tgtadd);
                FileGet.load(request);
            }

            private function onIOError(evt:IOErrorEvent):void
            {    
                trace(“An IO Error occured.\r”);
                trace(“Could not place Image.\r”);
            }

            private function onSecurityError(evt:Event):void
            {
                trace(“Security error occured.\r”);
            }

            private function onComplete(evt:Event):void
            {
                var desktop_file : File = File.desktopDirectory;
                var file : File = desktop_file.resolvePath(fileName);
                var stream:FileStream = new FileStream();
                try
                {
                    stream.open(file,FileMode.WRITE);
                    stream.writeBytes(FileGet.data);
                    var getFileNm:String = file.nativePath;
                }
                catch(error:IOError)
                {
                    trace(“File Output Error.\r”);
                }
                finally
                {
                  &nbs
p; stream.close();
                    if (hostName.indexOf(“illustrator”)>-1)
                    {
                        flickrThumbnailIllustrator.place(file);
                    }
                    else if (hostName.indexOf(“indesign”)>-1)
                    {
                        flickrThumbnailInDesign.place(file);
                    }
                    else if (hostName.indexOf(“photoshop”)>-1)
                    {
                        flickrThumbnailPhotoshop.openFile(file);
                    }
                }
            }
        ]]>
    </mx:Script>

    <mx:Fade id=”fadeIn” duration=”1500″ alphaFrom=”0″ alphaTo=”1″/>
    <mx:Fade id=”fadeOut” duration=”1500″ alphaFrom=”1″ alphaTo=”0″/>
    <mx:VBox height=”100%” width=”100%” verticalAlign=”top” horizontalAlign=”right”>
        <mx:Button id=”monButton” label=”refresh” click=”photoService.send();”/>
        <mx:Tile width=”100%” height=”100%”>
            <mx:Repeater id=”photos” dataProvider=”{photoFeed.entry}”>
                <mx:Box
                    xmlns:mx=”http://www.adobe.com/2006/mxml&#8221;
                    textAlign=”center”>
                    <mx:Image id=”myImage”
                        source=”{parseImageUrl(photos.currentItem.content)}”
                        completeEffect=”{fadeIn}”
                        scaleX=”0.3″ scaleY=”0.3″ click=”getCon(event);”/>
                </mx:Box>    
            </mx:Repeater>
        </mx:Tile>
        <mx:ControlBar horizontalAlign=”center”>
        </mx:ControlBar>
    </mx:VBox>
</mx:WindowedApplication>

MVCの切り分けがなってないっていうのはナシの方向で。ややこしい「フィード拾ってファイルをダウンロードして保存する」一連の処理は以前の記事を参照下さい。今回の大事な部分は

if (hostName.indexOf(“illustrator”)>-1)
{
    flickrThumbnailIllustrator.place(file);
}
else if (hostName.indexOf(“indesign”)>-1)
{
    flickrThumbnailInDesign.place(file);
}
    else if (hostName.indexOf(“photoshop”)>-1)
{
    flickrThumbnailPhotoshop.openFile(file);
}

のところです。ホストアプリケーションの見分け方はCSXSインターフェースを解説した時にやっているので細かい事はそちらをご覧下さい。
はしょりますが、HostObject.mainExtensionにホストアプリケーションが含まれます。
例えばイラストレータであれば帰ってくるのは

com.adobe.illustrator

という具合ですね。今回はこれをindexOfで引っ掛けて判別します。
振り分けは各アプリケーション用のクラスを用意します。

#flickrThumbnailIllustrator.as
package
{
    import com.adobe.csawlib.illustrator.Illustrator;
    import com.adobe.illustrator.*;
    import flash.filesystem.File;
    
    public class flickrThumbnailIllustrator
    {
        public static function place(file:File):void
        {
            var app:Application = Illustrator.app;
            if (app.documents.length>0)
            {
            var doc:Document = app.activeDocument;
            var obj:PlacedItem = doc.placedItems.add();
                obj.file = file;
                obj.height = obj.height*0.5;
                obj.width = obj.width*0.5;
                obj.left = 50;
                obj.top = 100 – obj.height;
            }
        }
    }
}

これがIllustrator用です。アクティブドキュメントに対して50%の縮小率で配置します。オブジェクトモデルの構造はExtendScriptとほぼ同一ですのでぱっとみJavascriptと変わりませんね。

#flickrThumbnailInDesign.as
package
{
    import com.adobe.csawlib.indesign.InDesign;
    import com.adobe.indesign.*;
    import flash.filesystem.File;

    public class flickrThumbnailInDesign
    {    
        public static function place(file:File):void
        {
            var app:Application = InDesign.app;
            if (app.documents.length>0)
            {
                var doc:Document = app.activeDocument;
                doc.placeGuns.loadPlaceGun(file);
            }
        }
    }
}

こちらはインデザインです。アクティブドキュメント上でプレースガンに画像を追加して行きます。

#flickrThumbnailPhotoshop.as
package
{
    import com.adobe.csawlib.photoshop.Photoshop;
    import com.adobe.photoshop.*;
    import flash.filesystem.File;
    
    public class flickrThumbnailPhotoshop
    {
        public static function openFile(file:File):void
        {
            var app:Application = Photoshop.app;
            app.open(file);
            
        }
    }
}

最後にPhotoshopです。こちらは単純にダウンロードしたイメージをオープンします。

もう一つ重要なのはmanifestファイルです。こちらの定義が重要なのは以前から書いている通りです。
仕組み的にはswfファイルは部品に過ぎません。この部品をどのホストにどのように盛り込むのかを記述するのがこのmanifestファイルなのです。

#manifest.xml
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?><ExtensionManifest xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; ExtensionBundleId=”net.sytes.chuwa.flickrthumbnail” ExtensionBundleVersion=”1.0″ Version=”2.0″>
    <Author>
        <![CDATA[Ten]]>
    </Author>
    <ExtensionList>
        <Extension Id=”net.sytes.chuwa.flickrthumbnail.test1″ Version=”1.0″/>
    </ExtensionList>
    <ExecutionEnvironment>
        <HostList>
            <Host Name=”ILST” Version=”15.0″/>
            <Host Name=”PHXS” Version=”12.0″/>
            <Host Name=”PHSP” Version=”12.0″/>
            <Host Name=”IDSN” Version=”7.0″/>
        </HostList>
        <LocaleList>
            <Locale Code=”All”/>
        </LocaleList>
        <RequiredRuntimeList>
            <RequiredRuntime Name=”CSXS” Version=”2.0″/>
        </RequiredRuntimeList>
    </ExecutionEnvironment>
    <DispatchInfoList>
        <Extension Id=”net.sytes.chuwa.flickrthumbnail.test1″>
            <DispatchInfo>
                <Resources>
                    <SwfPath>./main.swf</SwfPath>
                </Resources>
                <Lifecycle>
                    <AutoVisible>true</AutoVisible>
                </Lifecycle>
                <UI>
                    <Type>Panel</Type>
                    <Menu>FlickrThumbnail</Menu>
                    <Geometry>
                        <Size>
                            <Height>400</Height>
                            <Width>300</Width>
                        </Size>
                    </Geometry>
                    <Icons>
                        <Icon Type=”Normal”>./icons/CC_regular.png</Icon>
                        <Icon Type=”RollOver”>./icons/CC_active.png</Icon>
                        <Icon Type=”Disabled”>./icons/CC_disable.png</Icon>
                    </Icons>
                </UI>
            </DispatchInfo>
        </Extension>
    </DispatchInfoList>
</ExtensionManifest>

ホスト関係は以下のリスト部分

        <HostList>
            <Host Name=”ILST” Version=”15.0″/>
            <Host Name=”PHXS” Version=”12.0″/>
            <Host Name=”PHSP” Version=”12.0″/>
            <Host Name=”IDSN” Version=”7.0″/>
        </HostList>

上のはバージョンをダイレクトに記述していますが、ハイフンで範囲指定も可能です。
もうひとつ、この前のAICS6のアップデートでラインタイムのバージョンが上がっています。
CS6用の場合は

<RequiredRuntime Name=”CSXS” Version=”3.0″/>

CSXSのランタイムバージョンが3.0となりますご注意下さい。
ついでですが、バンドルIDはリバースドメインネームで記述する方がよろしいです。
最後にzxpも置いておきますね。

frickrThumbnail.zxp

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中