如何在e4中同步“检查”直接菜单项的所选状态和首选项?

时间:2017-03-03 09:53:46

标签: eclipse-plugin eclipse-rcp e4

我在var myapp = angular.module("mymodule",["ngRoute"]).config(function($routeprovider){$routeprovider .when("/Students",{ templateUrl:"Students.html", controller:"studentcontroller" }) .when("/Course",{ templateUrl:"Course.html", controller:"CourseController" })}); myapp.controller("studentcontroller",["$scope",function($scope){ $scope.message="Hello Welcome to students page";}]); myapp.controller("CourseController",["$scope",function($scope){ $scope.alert="Welcome to course page";}]) 中提供了“检查”直接菜单项。它的选择状态应该反映布尔首选项的值。在fragment.e4xmi方法中设置首选项可以正常工作:

@Execute

但是从首选项初始化@Execute public void execute(MMenuItem item, @Preference IEclipsePreferences preferences) { preferences.putBoolean("selected", item.isSelected()); } 的选定状态不起作用:

DirectMenuItem

调用@PostConstruct public void init(MMenuItem item, @Preference("selected") boolean selected) { item.setSelected(selected); } 方法时,与处理程序链接的@PostConstruct尚未出现在当前上下文中。

此外,将MMenuItem电话移至setSelected似乎不起作用;所做的更改没有在UI中反映出来。

那么,如何在e4中解决这个问题(将菜单项的选定状态与布尔首选项相关联)?

3 个答案:

答案 0 :(得分:1)

在使用Handled Menu Item而不是Direct Menu Item时,在@CanExecute中执行此操作。在直接处理程序中,有些UI事情似乎不太好用。

答案 1 :(得分:0)

根据您的问题和 https://dev.eclipse.org/mhonarc/lists/e4-dev/msg09498.html 中的讨论,我为 DirectToolItem 实施了以下解决方案。

@Inject
public void initialize(EModelService modelService, MPart part){
    MUIElement toolItem = modelService
         .find("a.b.c.d.toolitemId", part.getToolbar());
    isActive = ((MDirectToolItem) toolItem).isSelected();
}

@Inject 方法被调用一次,我知道 MDirectToolItem 的位置。我可以注射零件。这似乎足以同步 e4 应用程序模型和我的模型。

答案 2 :(得分:0)

为了记录,我想出了以下附加组件:

/**
 * The basis for an add-on which synchronizes the {@linkplain MItem#isSelected()
 * selection state} of {@link MItem}s tagged with one of the tags passed to
 * {@link ItemSelectionSynchronizationAddonBase#ItemSelectionSynchronizationAddonBase(String...)}
 * with some external source.
 * <p>
 * Subclasses need to implement {@link #getSelection(String)} to retrieve the
 * desired selection state for a given tag.
 */
public abstract class ItemSelectionSynchronizationAddonBase {

    private EModelService modelService;
    private MApplication application;

    private final List<String> tags;

    public ItemSelectionSynchronizationAddonBase(String... tags) {
        this.tags = new ArrayList<>(asList(tags));
    }

    /**
     * Injects all objects necessary to work with the E4 Application Model. Not done
     * in the constructor simply to keep subclasses unburdened by the knowledge
     * about the exact objects needed.
     */
    @PostConstruct
    public void injectUiModel(EModelService modelService, MApplication application) {
        this.modelService = modelService;
        this.application = application;
    }

    /**
     * Synchronizes the selection state of all {@link MItem}s found in the
     * Application Model when startup is complete. This does <strong>not</strong>
     * include items that exist only in part descriptors, but no concrete parts yet.
     * These items will be synchronized when the part gets created and
     * {@link #partActivated(Event)}.
     */
    @Inject
    @Optional
    public void applicationStartupComplete(
            @EventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) @SuppressWarnings("unused") Event event) {
        synchronizeSelections(application, tags,
                EModelService.ANYWHERE | EModelService.IN_MAIN_MENU | EModelService.IN_PART);
    }

    /**
     * Synchronizes the selection state of all {@link MItem}s found in the
     * Application Model for the part that was just activated.
     */
    @Inject
    @Optional
    public void partActivated(@EventTopic(UIEvents.UILifeCycle.ACTIVATE) Event event) {
        MPart part = (MPart) event.getProperty(UIEvents.EventTags.ELEMENT);
        synchronizeSelections(part, tags, EModelService.IN_PART);
    }

    /**
     * Synchronizes the selection state of all {@link MItem}s with the given tags.
     * Should be called by the subclass when the value changes in the external
     * source.
     */
    protected void synchronizeSelections(List<String> tags) {
        synchronizeSelections(application, tags,
                EModelService.ANYWHERE | EModelService.IN_MAIN_MENU | EModelService.IN_PART);
    }

    private void synchronizeSelections(MUIElement searchScope, List<String> tags, int searchFlags) {
        List<MItem> items = modelService.findElements(searchScope, null, MItem.class, tags, searchFlags);
        for (MItem item : items) {
            for (String tag : tags) {
                if (item.getTags().contains(tag)) {
                    item.setSelected(getSelection(tag));
                }
            }
        }
    }

    /** Gets the current selection state associated with the given tag. */
    protected abstract boolean getSelection(String tag);
}

然后子类可以覆盖 getSelection 以例如使用标记作为检索首选项或(如我的代码中所做的那样)从 Java bean 获取值的基础。请注意,getSelection 只负责一个同步方向(拉)。每当发生需要 UI 更新的事件(推送,例如由 synchronizeSelections 引起)时,子类还需要调用 PropertyChangeEvent