MenuConfig

MenuConfig 是一个特殊的类,根据 jmix.ui.menu-config 应用程序属性的定义加载主菜单结构。

使用 Studio 菜单设计器 定义菜单结构。

当使用 Studio 新建项目时,会生成包含应用程序主菜单结构的 menu.xml 文件。

<menu-config xmlns="http://jmix.io/schema/ui/menu">
    <menu id="application"
          caption="msg://ui.ex2/menu.application"
          description="Application menu items"
          expanded="true"
          icon="VIEW_ACTION"
          insertBefore="administration">
        <item id="User.browse"/>
        <separator/>
        <item screen="sample_CustomerScreen"
              caption="msg://ui.ex2.screen.customer/customerScreen.caption"/>
        <item screen="sample_City.browse" id="cities"/>
    </menu>
</menu-config>

有两种加载菜单结构定义文件的 模式:composite(默认)和 single。

使用 jmix.ui.composite-menu 应用程序属性切换这两种模式。

下面详细了解 menu.xml 文件的内容。

menu-config 是 XML 根元素。menu-config 内部的元素组成了一个树状结构,其中 menu 元素是分枝而 itemseparator 元素是叶子结点。

menumenu-config 的内部元素。具有下列属性:

  • id - 元素的唯一标识符。

  • caption - menu 元素的标题。如果未设置,则会用 下面 介绍的规则确定标题。

  • description - 鼠标悬停时展示的提示文字。可以使用 消息包 中的本地化消息。

  • icon - menu 元素的图标。参阅 图标 章节了解详情。

  • insertBeforeinsertAfter - 将当前菜单放在某个特定元素或指定了 id 的菜单项之前或之后。这些属性用来将一个菜单项放置于 扩展组件 中定义菜单中的合适位置。不要同时使用 insertBeforeinsertAfter

  • stylename - 定义菜单项的样式名。参阅 主题 了解详情。

  • expanded - 定义是否在打开主界面时展开此 menu 元素。默认为 false

示例:

<menu id="application"
      caption="msg://ui.ex2/menu.application"
      description="Application menu items"
      expanded="true"
      icon="VIEW_ACTION"
      insertBefore="administration">
</menu>

item 属性

itemmenu 的内部元素。具有下列属性:

  • id - 元素的唯一标识符。如果没有定义 screenbeanclass 属性,则可以使用 id 指向同名界面。当用户点击时,会在 主界面 打开相应的界面。

    <item id="User.browse"/>
  • caption - item 元素的标题。如果未设置,则会用 下面 介绍的规则确定标题。

    <item screen="sample_CustomerScreen"
          caption="msg://ui.ex2.screen.customer/customerScreen.caption"/>
  • description - 鼠标悬停时展示的提示文字。可以使用 消息包 中的本地化消息。

  • screen - 界面标识符。可以用来在多个菜单打开同一界面。当用户点击时,会在 主界面 打开相应的界面。

    <item screen="sample_City.browse" id="cities"/>
    <item screen="sample_City.browse" id="cities2"/>
  • bean - bean 名称。必须与 beanMethod 一起使用。当用户点击时,执行 bean 方法。

    menu.xml
    <item bean="sample_MenuBean"
          beanMethod="showCityBrowse"
          caption="Show Cities"/>
    MenuBean.java
    @Component("sample_MenuBean")
    public class MenuBean {
        @Autowired
        private ScreenBuilders screenBuilders;
    
        public void showCityBrowse(){
            final Screen frameOwner = AppUI.getCurrent()
                    .getTopLevelWindowNN().getFrameOwner();
            screenBuilders.screen(frameOwner)
                    .withScreenClass(CityBrowse.class)
                    .build()
                    .show();
        }
    }

    使用 properties 内部元素可以从菜单项传递参数至 bean 方法。示例:

    menu.xml
    <item bean="sample_MenuBean" beanMethod="openLink"
          id="openBeanWithParams" caption="OpenBeanWithParams">
        <properties>
            <property name="url" value="https://jmix.io"/>
        </properties>
    </item>
    MenuBean.java
    @Component("sample_MenuBean")
    public class MenuBean {
    
        @Autowired
        private ObjectProvider<WebBrowserTools> webBrowserToolsProvider;
    
        public void openLink(Map<String, Object> parameters) {
            String url = (String) parameters.get("url");
            if (url == null) {
                return;
            }
    
            webBrowserToolsProvider.getObject().showWebPage(
                    url, ParamsMap.of("target", "_blank"));
        }
    }
  • class - 一个实现了 MenuItemRunnable 接口的类全限定名称。当用户点击时,会创建指定类的实例并执行接口方法。

    menu.xml
    <item class="ui.ex2.app.CustomMenu" id="jmix" caption="Open page"/>
    CustomMenu.java
    public class CustomMenu implements MenuItemRunnable, ApplicationContextAware {
    
        private ApplicationContext applicationContext;
    
        public void openLink(String url) {
            applicationContext.getBean(WebBrowserTools.class)
                    .showWebPage(url, ParamsMap.of("target", "_blank"));
        }
    
        @Override
        public void run(FrameOwner origin, MenuItem menuItem) {
            if (menuItem.getId().equals("jmix")) {
                openLink("https://jmix.io");
            } else {
                openLink("https://google.com");
            }
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext)
                throws BeansException {
            this.applicationContext = applicationContext;
        }
    }
  • shortcut - 菜单项的键盘快捷键。可选的修饰键:ALTCTRLSHIFT,由“-”字符分隔。示例:

    <item screen="sample_City.browse"
          id="cities3"
          shortcut="ALT-C"/>

    快捷键可以在 application.properties 文件配置,在 menu.xml 文件使用:

    menu.xml
    <item screen="sample_City.browse"
          id="cities4"
          shortcut="${sample.menu.city}"/>
    application.properties
    sample.menu.city=ALT-CTRL-C
  • openMode 属性定义界面打开的方式。对应 OpenMode 枚举,支持:NEW_TABDIALOGNEW_WINDOW。默认值为 NEW_TAB

    <item screen="sample_City.browse"
          id="cities5"
          openMode="DIALOG"/>
  • icon - item 元素的图标。参阅 图标 章节了解详情。

  • insertBeforeinsertAfter - 将当前菜单放在某个特定元素或指定了 id 的菜单项之前或之后。

  • resizable - 仅在以 DIALOG 模式打开界面有效。控制弹窗是否可改变大小。可设置为 truefalse。默认情况下,主菜单对窗口是否可以改变大小没有限制。

  • stylename - 定义菜单项的样式名。参阅 主题 了解详情。

item 的元素

propertiesitem 的内部元素。用于定义传递给界面公共 setter 的一组属性参数。每个属性参数在 property 元素内使用 name 属性定义,名称对应于一个 setter 方法。框架在界面的 AfterInitEventBeforeShowEvent 事件之间调用 setter。

property 属性:

  • name - 属性名称。

  • value - 非实体属性的属性值。

  • entityClass - 实体属性的类。

  • entityId - 实体属性的 id。

  • entityFetchPlan - 可选参数,设置用于加载实体属性的 fetch plan

例如,menu.xml 中的 filterVisible 布尔属性对应界面控制器中的 void setFilterVisible(Boolean value) 方法:

menu.xml
<item screen="sample_City.browse" id="cities6">
    <properties>
        <property name="filterVisible" value="false"/>
    </properties>
</item>
CityBrowse.java
public void setFilterVisible(Boolean value){
    isFilterVisible = value;
}

使用实体属性的示例:

<item screen="User.edit" caption="User screen">
    <properties>
        <property name="user"
                  entityClass="ui.ex2.entity.User"
                  entityId="60885987-1b61-4247-94c7-dff348347f93"
                  entityFetchPlan="_base"/>
    </properties>
</item>

定义菜单标题

如果 caption 属性未定义,则 menuitem 元素的本地化名称通过这种方式定义:以 menu-config 作为前缀,再加上元素的 id,中间以 “.” 分隔。形成的字符串作为 消息包 的键值。示例:

messages.properties
menu-config.User.browse = Users
menu-config.cities = Cities

如果 id 未设置,则标题会使用类名(如果设置了 class 属性)或 bean 名称及方法(如果设置了 bean 属性)生成。因此,我们推荐最好设置 id 属性。