IntelliJ IDEAプラグイン開発。 パート2

Intellij IDEAドキュメントとの不平等な戦いを続けています。 前の部分はこちらです。


プラグイン構成ファイル



プラグインによって提供されるすべての機能、および作成者に関する説明と情報はplugin.xmlファイルにリストされています。

ほとんどすべての重要な要素が存在するファイルの構造を検討してください。



<!-- url="..."  URL    (  Welcome Screen    "Plugins") --> <idea-plugin url="http://www.jetbrains.com/idea"> <!--   --> <name>VssIntegration</name> <!--   .       .   ,  -  <name> --> <id>VssIntegration</id> <!--   --> <description>Vss integration plugin</description> <!--     .      Web- --> <change-notes>Initial release of the plugin.</change-notes> <!--   --> <version>1.0</version> <!--  .   "url"     .   "email"     .   "logo"    1616,   JAR --> <vendor url="http://www.jetbrains.com" email="support@jetbrains.com" logo="icons/plugin.png">Foo Inc.</vendor> <!--        --> <depends>MyFirstPlugin</depends> <!--   --> <depends optional="true" config-file="mysecondplugin.xml">MySecondPlugin</depends> <!--       ( JavaHelp )  IDEA.  "file"   JAR   "help".  "path"     helpset. --> <helpset file="myhelp.jar" path="/Help.hs" /> <!--     ,    --> <idea-version since-build="3000" until-build="3999"/> <!--      --> <resource-bundle>messages.MyPluginBundle</resource-bundle> <!--    --> <application-components> <component> <!--  --> <interface-class>com.foo.Component1Interface</interface-class> <!--    --> <implementation-class>com.foo.impl.Component1Impl</implementation-class> </component> </application-components> <!--    --> <project-components> <component> <!--     --> <interface-class>com.foo.Component2</interface-class> <!--  "workspace"   "true",     *.iws   *.ipr (     JDOMExternalizable). --> <option name="workspace" value="true" /> <!--    "loadForDefaultProject",     - --> <loadForDefaultProject> </component> </project-components> <!--    --> <module-components> <component> <interface-class>com.foo.Component3</interface-class> </component> </module-components> <!--  --> <actions> <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Collect _Garbage" description="Run garbage collector"> <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/> </action> </actions> <!--  ,   .        .  "beanClass"  ,   . --> <extensionPoints> <extensionPoint name="testExtensionPoint" beanClass="com.foo.impl.MyExtensionBean"/> </extensionPoints> <!-- ,      ,    IDEA   .  "defaultExtensionNs"   ID    "com.intellij"     IDEA Core.    <extensions>      --> <extensions xmlns="VssIntegration"> <testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/> </extensions> </idea-plugin>
      
      





アクションを実行および更新する



アクションシステムにより、プラグインは独自のメニュー項目とIDEAツールバーを追加できます。 アクションは、メニュー項目またはそれに対応するツールバーボタンが選択されたときにactionPerformed()メソッドが呼び出されるAnActionから継承されたクラスです。 たとえば、同じアクションクラスがメニュー項目「ファイル| [ファイルを開く...]およびツールバーの[ファイルを開く]ボタン。



アクションはグループにまとめることができ、グループにはサブグループが含まれる場合があります。

各アクションまたはグループには一意の識別子を割り当てる必要があります。 ほとんどの標準アクションの識別子は、クラスcom.intellij.openapi.actionSystem.IdeActionsで定義されています。

各アクションは複数のグループに含めることができるため、ユーザーインターフェイスのさまざまな場所に表示できます。 アクションを表示できる場所は、ActionPlacesインターフェイス(同じパッケージから)で定数として定義されます。 プレゼンテーションクラスのインスタンスは場所ごとに作成されるため、同じアクションは、インターフェイス上のさまざまな場所で異なるテキストまたはアイコンを持つことができます。 AnAction.getTemplatePresentation()メソッドから戻り値をコピーすることにより、さまざまな表現が作成されます。



アクションのステータスを更新するには、AnAction.update()メソッドが定期的に呼び出されます。 AnActionEvent型のオブジェクトがメソッドに渡され、現在のコンテキスト、特に更新する必要がある特定のビューに関する情報が提供されます。



アクティブなプロジェクト、選択したファイル、エディターで選択したテキストなど、IDEの現在の状態に関する情報を取得するには、AnActionEvent.getData()メソッドを使用できます。 このメソッドで受け入れられるさまざまなキーは、DataKeysクラスで説明されています。 AnActionEvent型のオブジェクトもactionPerformed()メソッドに渡されます。



アクション記録



アクションを登録するには、plugin.xmlファイルにリストするか、コンポーネントの初期化段階で手動で登録するかの2つのオプションがあります。

最初のオプションを検討してください。

 <actions> <!--  <action>  ,    .   "id"    .   "class"   ,  .   "text"      .   "use-shortcut-of"    ,       .   "description"     .   "icon"     . --> <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Collect _Garbage" description="Run garbage collector" icon="icons/garbage.png"> <!--  <add-to-group> ,        ( ).   "group-id"    .     DefaultActionGroup.   "anchor"    ("first", "last", "before"  "after").  "relative-to-action" ,  anchor  "before"  "after". --> <add-to-group group-id="ToolsMenu" relative-to-action="GenerateJavadoc" anchor="after"/> <!--  <keyboard-shortcut>   .   "first-keystroke"   .     Swing-.   "second-keystroke"   .   "keymap"  .     com.intellij.openapi.keymap.KeymapManager. --> <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/> <!--  <mouse-shortcut>     .     ,  : "button1", "button2", "button3"  ; "shift", "control", "meta", "alt", "altGraph"  ; "doubleClick" –   . --> <mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/> </action> <!--  <group>  .  <action>, <group>  <separator>      .   "popup" ,    .  popup="true",    ;  popup="false",     . --> <group class="com.foo.impl.MyActionGroup" id="TestActionGroup" text="Test Group" description="Group with test actions" icon="icons/testgroup.png" popup="true"> <action id="VssIntegration.TestAction" class="com.foo.impl.TestAction" text="My Test Action" description="My test action"/> <!--  <separator>    .      <add-to-group>. --> <separator/> <group id="TestActionGroup"/> <!--  <reference>      .   "ref"   . --> <reference ref="EditorCopy"/> <add-to-group group-id="MainMenu" relative-to-action="HelpMenu" anchor="before"/> </group> </actions>
      
      





Javaコードから直接アクションを登録する場合、2つのステップを実行する必要があります。 まず、AnActionから派生したクラスのインスタンスをActionManager.registerAction()メソッドに渡して、識別子バインディングを作成する必要があります。 次に、アクションを1つ以上のグループに追加する必要があります。 グループのインスタンスを識別子で取得するには、ActionManager.getAction()を呼び出して、結果をDefaultActionGroup型にキャストします。

IDEAの起動中にアクションを登録するには、次の一連の手順が必要です。

  1. ApplicationComponentインターフェイスを実装するクラスを作成します。
  2. getComponentName、initComponent、およびdisposeComponentメソッドをオーバーライドします。
  3. plugin.xmlファイルの<application-components>



    セクションにクラスを登録します。


わかりやすくするために、説明した手順を実行するコード例を示します。

 public class MyPluginRegistration implements ApplicationComponent { //      @NotNull public String getComponentName() { return "MyPlugin"; } //    MyPluginRegistration   <application-components> //      IDEA. public void initComponent() { ActionManager am = ActionManager.getInstance(); TextBoxes action = new TextBoxes(); //  . am.registerAction("MyPluginAction", action); //  ,      . DefaultActionGroup windowM = (DefaultActionGroup) am.getAction("WindowMenu"); //      . windowM.addSeparator(); windowM.add(action); } //      . public void disposeComponent() { } }
      
      





アクションのインターフェースを作成する



プラグインが特定のインターフェイスでツールバーまたはポップアップメニューを表示する必要がある場合、ActionPopupMenuクラスとActionToolbarクラスを使用してこれを実行できます。 それらのオブジェクトは、ActionManager.createActionPopupMenu()およびActionManager.createActionToolbar()メソッドを呼び出すことで作成できます。



アクションが特定のコンポーネント(パネルなど)に含まれている場合、通常はActionToolbar.setTargetComponent()を呼び出して、コンポーネントのインスタンスをパラメーターとして渡す必要があります。 これにより、ツールバーボタンの状態が、IDEフレームのフォーカスではなく、関連するコンポーネントの状態にのみ依存するようになります。



コンポーネントの状態の保存



IntelliJ IDEAは、コンポーネントまたはサービスがIDEの起動間で状態を維持できるようにするAPIを提供します。 PersistentStateComponentインターフェイスを使用して、プリミティブ型と複合オブジェクトの両方を保存できます。



PropertiesComponentを使用して単純な値を保存する


いくつかのプリミティブ型のみを保存する場合、これを実現する最も簡単な方法は、com.intellij.ide.util.PropertiesComponentサービスを使用することです。 アプリケーションレベルとプロジェクトレベルの両方の値を保存するために使用できます(データはワークスペースファイルに配置されます)。

PropertiesComponent.getInstance()メソッドを使用してアプリケーションレベルの値を保存し、PropertiesComponent.getInstance(プロジェクト)をプロジェクトレベルの値に使用します。



PersistentStateComponentインターフェイスの使用


PersistentStateComponentインターフェイスは、保存された値、その形式、および保存場所を管理するためのより柔軟なオプションを提供します。 それを使用するには、サービスまたはコンポーネントにインターフェース自体を実装し、状態を担当するクラスを定義し、 @State



アノテーションを使用して保存場所を指定する必要があります。

拡張インスタンスは、PersistentStateComponentを使用して状態を維持できないことに注意してください。 必要に応じて、この拡張機能の状態の管理を担当する別のサービスを作成することをお勧めします。



PersistentStateComponentインターフェイスの実装


インターフェイスを実装する場合、状態を記述するクラスをパラメーター化する必要があります。 状態クラスは、通常のJavaBeanクラスにすることも、独自にPersistentStateComponentを実装することもできます。

最初のケースでは、状態クラスのインスタンスは通常、コンポーネントクラスのフィールドとして保存されます。

 class MyService implements PersistentStateComponent<MyService.State> { class State { public String value; } State myState; public State getState() { return myState; } public void loadState(State state) { myState = state; } }
      
      





2番目のケースでは、次のテンプレートを使用できます。

 class MyService implements PersistentStateComponent<MyService> { public String stateValue; public MyService getState() { return this; } public void loadState(MyService state) { XmlSerializerUtil.copyBean(state, this); } }
      
      





状態クラスの実装


保存する前に、BeanクラスのパブリックフィールドとプロパティはXML形式でシリアル化されます。 次のタイプを保存できます。



シリアル化可能な値からパブリックフィールドを除外するには、 @Transient



アノテーションでマークする必要があります。

状態クラスには、すべてのフィールドをデフォルト値で初期化するパラメーターなしのコンストラクターが必要です(これは、XMLファイルに保存する前にクラスを一貫した状態にするために必要です)。



保管場所


データを保存する場所を具体的に指定するには、 @State



アノテーションをコンポーネントクラスに追加する必要があります。ここで、次のフィールドを指定する必要があります。



@Storage



アノテーションの使用例:



@Storage



アノテーションの「id」 @Storage



使用して、特定の形式にシリアル化するときにフィールドを除外できます。 何も除外する必要がない場合は、パラメータに任意の文字列値を割り当てることができます。

ファイルパラメータにさまざまな値を定義することで、さまざまなファイルに状態を保存できます。 ディレクトリベースのプロジェクト形式を使用するときに値を保存する場所を決定する必要がある場合は、 StorageScheme.DIRECTORY_BASED



に等しい「scheme」パラメータ値を持つ2番目の@Storage



アノテーションを追加する必要があります。

 @State( name = "AntConfiguration", storages = { @Storage(id = "default", file = StoragePathMacros.PROJECT_FILE), @Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/ant.xml", scheme = StorageScheme.DIRECTORY_BASED) } )
      
      







XML形式の設定


永続化された状態が単純なJavaBeanにマップされない場合、org.jdom.Elementから状態クラスを継承できます。 この場合、getState()メソッドを使用して、任意の構造を持つXML要素を構築します。 loadState()メソッドでは、JDOM要素をデシリアライズする必要があります。

Beanクラスの標準シリアル化をカスタム形式と組み合わせて使用​​するには、アノテーション@Tag, @Attribute, @Property, @MapAnnotation, @AbstractCollection



使用できます。



次の部分では、プロジェクト構造、VFS。



サイクルのすべての記事: 1、2、3、4、5、6、7



All Articles