操作体系

原文链接:
http://www.jetbrains.org/intellij/sdk/docs/basics/action_system.html

执行和更新操作

操作体系允许插件向IDEA添加自己的菜单项和工具栏按钮。一个操作就是一个派生自AnAction类的类,当选择菜单项或点击工具栏按钮时,它的actionPerformed方法就会被调用。例如,其中一个操作类就是负责文件|打开文件...菜单项和打开文件 工具栏按钮的。

操作被组织成组,其又可以包含其他组。 一组操作可以形成工具栏或菜单。
组的子组可以形成菜单的子菜单。

每个操作和操作组都有一个唯一的标识符。标准IDEA操作的标识符在IdeActions类中定义。

每个操作都可以包含在多个组中,因此一个操作会出现在IDEA用户界面中的多个位置。操作可以出现的位置由ActionPlaces接口中的常量定义。 操作出现的每个地方都会新建一个Presentation。因此相同的操作在不同位置可以有不同的文本和图标。 操作的不同presentation可以通过复制AnAction.getTemplatePresentation()方法返回的presentation创建。

IDEA通过定期调用AnAction.update()方法更新操作的状态。传递给此方法的AnActionEvent对象携带了操作当前上下文的信息,特别是需要更新的指定presentation。

使用AnActionEvent.getData()方法可以获取当前IDE的信息,包括活动项目、所选文件、编辑器中的选择等。可以传递给此方法的数据键在CommonDataKeys类中定义。

AnActionEvent实例也会传递给actionPerformed方法。

注册操作

目前有两种注册操作的方法:在plugin.xml文件的<actions>部分列出或通过Java代码。

在plugin.xml文件中注册操作

以下是在plugin.xml中注册操作的方法,其演示了所有可以在<actions>部分使用的元素,并描述了每个元素的含义。

<!-- Actions -->
<actions>
  <!-- <action>定义要注册的操作
       "id"属性指定操作的唯一标识符
       "class"属性指定操作实现类的完全限定名
       "text"属性指定操作的文本(工具栏按钮提示或菜单项文本)
       "use-shortcut-of"属性(可选)指定此操作将要使用的快捷键的操作的ID
       "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"属性指定此操作要添加到的组的ID,这个组必须被DefaultActionGroup类的实例实现
         "anchor"属性指定操作相对于组里其它操作的位置,它的只可以为"first",、"last",、"before"和"after"
         如果"anchor"的值设置为"before"和"after","relative-to-action"属性是必须的,
         它指定当前操作要插入在那个操作之前或之后 -->
    <add-to-group group-id="ToolsMenu" relative-to-action="GenerateJavadoc" anchor="after"/>
      <!-- <keyboard-shortcut>节点指定操作的快捷键,一个操作可以有多个快捷键
           "first-keystroke"属性指定操作的首选快捷键,键位由常规Swing规则指定
           "second-keystroke"属性(可选)指定操作的备选快捷键
           "keymap"属性指定快捷方式所属的键位映射方案,标准键位映射方案的ID
           在com.intellij.openapi.keymap.KeymapManager类中的常量定义 -->
      <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/>
      <!-- <mouse-shortcut>节点指定操作的鼠标快捷方式,一个操作可以有多个鼠标快捷方式
           "keystroke"属性指定操作的点击方式
           它可以定义为以空格分隔的单词序列: 
           鼠标按钮:"button1", "button2", "button3" 
           键位修饰:"shift", "control", "meta", "alt", "altGraph"
           如果操作需要键位双击激活使用"doubleClick" 
           "keymap"属性指定快捷方式所属的键位映射方案,标准键位映射方案的ID
           在com.intellij.openapi.keymap.KeymapManager类中的常量定义 -->
    <mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
  </action>
  <!-- <group>定义一个操作组,其中定义的<action>、<group>和<separator>元素会自动包括在组里
       "id"属性指定操作组的唯一标识符
       "class"属性(可选)指定实现操作组类的完全限定名
       如果未指定,则默认使用com.intellij.openapi.actionSystem.DefaultActionGroup
       "text"属性(可选)指定操作组的文本(显示子菜单的菜单项的文本)
       "description"属性(可选)指定焦点在操作组上时显示在状态栏的描述
       "icon"属性(可选)指定显示在工具栏按钮或操作组旁边的图标
       "popup"属性(可选)指定如何在菜单中显示操作组
       如果值为"true",操作显示在子菜单中
       如果值为"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="TestActionSubGroup"/>
    <!-- <reference>元素允许添加现存的操作
         "ref"属性指定操作的ID -->
    <reference ref="EditorCopy"/>
    <add-to-group group-id="MainMenu" relative-to-action="HelpMenu" anchor="before"/>
  </group>
</actions>

从代码中注册操作

从代码中注册操作,有两个步骤:

  • 首先,必须往ActionManager类的registerAction方法传入一个派生自AnAction类的实例,将操作与ID关联;
  • 然后,操作需要添加进一个或多个组。要通过ID获取一个操作组的实例,需要调用 ActionManager.getAction()并将返回值转换为DefaultActionGroup类。

你可以使用以下方法创建一个在IDEA启动时注册操作的插件。

在IDEA启动时注册操作

  • 新建一个实现ApplicationComponent接口的类;
  • 在这个类中重写getComponentNameinitComponentdisposeComponent方法;
  • plugin.xml文件的<application-components>部分注册这个类。

要阐明以上过程,查看以下实例Java类MyPluginRegistration,它注册了一个由TextBoxes类定义的操作并将其添加到主菜单的Window菜单组:

public class MyPluginRegistration implements ApplicationComponent {
  // 返回组件名称(唯一字符串)
  @NotNull public String getComponentName() {
    return "MyPlugin";
  }


  // 如果你在plugin.xml文件的<application-components>部分注册了MyPluginRegistration类,
  // 这个方法将在IDEA启动时被调用
  public void initComponent() {
    ActionManager am = ActionManager.getInstance();
    TextBoxes action = new TextBoxes();

    // 将TextBoxes类的实例传入ActionManager类的registerAction方法
    am.registerAction("MyPluginAction", action);

    // 获取WindowMenu操作组的实例
    DefaultActionGroup windowM = (DefaultActionGroup) am.getAction("WindowMenu");

    // 添加一个分隔符和操作到主菜单的WindowMenu操作组
    windowM.addSeparator();
    windowM.add(action);
  }

  // Disposes system resources.
  public void disposeComponent() {
  }
}

注意:TextBoxes类的实现可以查看创建操作.

plugin.xml文件的<application-components>部分做以下更改确保你的插件在IDEA启动时被初始化:

<application-components>
  <!-- 添加应用组件 -->
  <component>
    <implementation-class>MypackageName.MyPluginRegistration</implementation-class>
  </component>
</application-components>

从操作中构建UI

如果插件需要包括一个工具栏或弹出菜单,它是在自己的UI上从操作组中构建的,可以使用ActionPopupMenuActionToolbar类实现。这些对象可以通过调用ActionManager.createActionPopupMenuActionManager.createActionToolbar方法创建。要从这样的对象上获取Swing组件可以简单调用getComponent()方法。

如果你对操作工具栏要附加到指定组件上(例如,工具窗口的面板),你通常需要调用ActionToolbar.setTargetComponent() 方法,并将相关组件的实例作为参数传入。这样可以确保工具栏按钮的状态依赖于相关组件而不是IDE框架内当前焦点位置的状态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,072评论 25 707
  • Swift版本点击这里欢迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh阅读 25,365评论 7 249
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,093评论 4 62
  • 面对独特的客户需求,你发现了就出了一张牌,这就是商业模式。 实际上不止是一手牌,要不断抓进新的牌,这种模式才能玩得...
    马唐阅读 253评论 0 0
  • 我也伴着雨声清醒了大半夜 从滂沱 到淅沥 从淅沥 到滂沱 天空之上 究竟堆积了多少不快的黑云 倾泻而下 却依旧未曾...
    沐璎阅读 246评论 0 4