Community
Participate
Working Groups
This may be a regression of bug 25806, but the behaviour is very odd so I believe it warrants a separate PR. build no: I20021127 The edit accelerators ctrl-a, ctrl-c, ctrl-v are not working correctly in the description editor of both the Definition and Documentation pages of the Schema Editor. The quirky part of this bahaviour is that if you never look at the source page, the accelerators work properly, but once you flip to the source page and then back to the GUI, the accelerators are broken. steps to reproduce problem with ctrl-A: 1. Open a new schema editor with the Definition page visible. 2. Click on the description editor and hit ctrl-a RESULT: contents of description editor are highlighted as expected 3. Click on the source tab to bring up the source page 4. Click on the Definition tab to being back the definition page 5. Click on the description editor and hit ctrl-a. RESULT: contents of description editor are *not* highlighted. In fact, if you click on the source tab, you'll find the contents of the source page are highlighted instead. Similar behaviour was found with ctrl-c and ctrl-v; once the source page has been viewed, these accelerators only work on the source page, not on the decription editor. Performing the action from the edit or context menu works properly. So even while the user in looking at the GUI, ctrl-c will copy whatever is highlighted on the cource page, and ctrl-v will paste clipboard contents to the source page. Since this happens while the user is on the GUI, all they see is nothing happening, while their source file is being modified.
I beleive this is a key bindings problem. If you execute the same actions from the 'Edit' menu, the correct behaviour can be observed. It is only the keyboard accelerator for the action that is not passed to the right action. When pages are switched, PDE updates the global action handlers using: IActionBars.setGlobalActionHandler() When source page is switched, we call this method to link global actions with action handlers in the source page. When GUI pages are selected, we redirect global actions to GUI action handlers, that simply delegate the global action execution to the current GUI page/current section. This mechanism is working well when executing actions from the menu, but for some reason keyboard mappings are not updated at the same time.
on the first press of Ctrl+A on the description page, the action that the key binding service invokes is an instance of PDEEditorContributor$GlobalAction with the id parameter "selectAll". moving to the source page, back to the description page, deselecting with the mouse, and pressing Ctrl+A once again, the action is an instance of org.eclipse.ui.texteditor.TextOperationAction. the implementation of KeyBindingService checks for any actions explicitly registered with it, if not, it reverts to its parent, WWinKeyBindingService, for other handlers - this is where the global action handlers are found. when the text editor component is created for the source page (lazy creation seems to be at work here), the text editor registers all of its actions, including global actions, with the key binding service and never unregisters them with the keybinding service. (for instance, when the source page closes). returning to the description page, the menu item correctly identifies the global action handler for select all in PDE, but the key binding service sitll finds an explicit registration for the text editor to receive select all. because of the built in association between global actions and WWinKeyBinding service, there seems to be no need for Kai to register global actions with the key binding service directly, or at least they should be unregistered from the key binding service when the text editor loses focus, etc. as a quick hack, i changed AbstractTextEditor$ActivationCodeTrigger.registerActionForKeyActivation to reject actions with the action definition id ITextEditorActionDefinitionIds.SELECT_ALL and everything worked correctly. passing to Kai to fix, and adding you on the CC: since our coop student, the reporter of this bug, has left OTI.
This affects all PDE editors, but is particularly visible in schema editor where users frequently toggle between source and form pages. Once they switch to the source page for the first time, they loose the form page key bindings, and open defects against PDE about global commands not working. I am rising the severity for this defect.
It seems to me that a change in the text editor area is not appropriate to solve this problem. It’s looking like an architectural issue. Here is why I think so. I am using the PDE schema editor as one example. A text editor is an editor part. It assumes to live in a well-defined context. Part of this context is the editor site providing several services to the editor. For example, the editor can register its context menu with its site. Also, the editor can register its actions with the site’s key binding service. It is part of the definition of the editor’s context that after having registered its actions, the editor is freed from further management. This means that the editor does not have to track its activation status in order to bind its actions to retarget menu bar or tool bar actions. The PDE schema editor is a multi-page editor. It uses the text editor (AbstractTextEditor) as the content of one of its pages. Thus, it is the multi- pages editor’s responsibility to create the context for the embedded text editor. Since the multi-page editor already provides several pieces of the infrastructure including a multi-page editor site this should be possible without requesting additional API from the embedded editor. Following Chris’ proposal to not register actions with the key binding service would not be sufficient it seems. It would still be the schema editor’s responsibility to track activation/deactivation and to force the embedded editor to set or remove its actions as global action handlers. This would require new API on text editors that would then be available for everybody. New API could be avoided by making activation tracking the embedded editor’s task. But doing so (probably based on widget focus) is not optimal for three reasons: It would contradict the assumption described above. It would contradict the architectural model of editors in which the editor contributor tracks the active editor. It would introduce the “same” functionality at two different layers (workbench and text editor) and which for all single page editors would be executed twice on each activation change. Moving to Platform UI.
Please note that PDE is NOT using multi-page editor provided by platform UI (historic reasons - we will rework our editors in 2.2 and switch then). Assuming that we are willing to do what is required in PDE, what would that be? We already have our sub-managers that track page switching, and register global action handlers for form or source pages on switching. I think that this part is not a problem - the switching works fine. However, since text editor registers key binding service explicitly, it does not let it go on switching. What is it that we need to do reset the key binding service set explicitly by the text editor in the source page?
If we changed the text editor to not register its global action handlers in the keybinding service, then this would solve the problem for the global actions (cut, copy, paste, undo, redo, select all, etc). This would be an expedient solution for 2.1, but it goes against how we would like to do this in the future, where we would like to have a single command service rather than both a global action service and a keybinding service. As Kai points out, though, this does not solve the problem in general. Other actions registered by the text editor with the keybinding service (e.g. prev/next line) would not get reassigned when switching pages. To fix this properly, in the part site provided to the nested editor, you need to provide a "virtual" key binding service. The multipage editor then must update the real keybinding service for the active page (removing bindings for the previously active page, and adding ones for the newly active page). This needs to be fixed up in MultiPageEditorSite as well, but it's unlikely we'll get to this for 2.1.
Can you point us at the code we need to mimic in order to get the key binding switching in our multi-page editor?
Here is a quick and evil fix provided by Nick Dr. Evel Edgar: When we create an initialize source page, we immediately turn around and unregister actions registered with the key binding service that we care about (cliboard, select all, undo/redo etc.). These are the same actions we actively manage as global action handlers. Since these actions are unregisted, from the service, they default mechanism (global actions) are now handling them. Text editor still receives all the commands from the user, only that they arrive to it through the global action accelerators, not the key binding service. I tested this on couple of our editors and all seems to work well without any loss of function in the source page. I will move this defect to 'Later' to be reactivated in 2.2 as we rehost PDE editors to multi-page editor support from the platform.
Can anyone advise as to the status of this bug? In particular, PDE's rehosting of editors in 2.2. platform-ui is approaching the editor switching problem for 3.0. See Bug 37612.
Reopening. Text and other teams need recommendations from us on how to do this properly. Nesting of services is a general problem. I see two possible paths: 1) Keep the current model whereby a part's site provides services, but extend it so that: (a) set of services is extensible without requiring changes to the site API (perhaps by having the site implement IAdaptable), and (b) services know how to nest themselves, through a generic API (e.g. INestableService.getNestedService()). 2) Reverse the flow of control so that the workbench calls in to the part, rather than the part reaching out to its site, and allow the part to delegate to nested parts (a la chain-of-responsibility pattern). Details to be worked out <g>.
What's left of this bug is now represented by Bug 37612. *** This bug has been marked as a duplicate of 37612 ***
As a note, MultiPageEditorPart and MultiPageEditorSite now support nested key binding services. This means that it should support switching of contexts and handlers based on the currently active page.
This is very timely, because Eclipse Forms have this support for multi-page form editor (meaning we can delete classes :-). Can you give us some pointers of what needs to be done to use this?
The long answer you didn't really want, but you'll get anyway.... I have currently hacked this together using the old KeyBindingService. I will describe this method first, since it is something we can guarantee support for (its going into 2.1.3). The new API Chris has put together is much more succinct, but is probably still too new for use. (Plus, you'd probably want to make a helper class to handle the switching anyway.) [Note: I don't have an Eclipse running right now, so my naming and typing maybe a little off.] I rewrote MultiPageEditorSite.getKeyBindingService. You can see the changes in CVS. Basically, it attempts to get a nested key binding service (associated with the multi-page editor site). If it fails, then it falls back on the old key binding service (provided by the editor site). In the dispose method on MultiPageEditorSite, I clean up after myself (important to remember!). The relevant API is: INestableKeyBindingService.getKeyBindingService(IWorkbenchSite) INestableKeyBindingService.removeKeyBindingService(IWorkbenchSite) In MultiPageEditorPart, I hacked the setFocus() methods to call: INestableKeyBindingService.activateKeyBindingService(IWorkbenchSite) when appropriate. A lot of the code is just checking to make sure that nothing is null or of the wrong type. In practice, this should never really happen. Under the covers, this is calling into the IWorkbenchContextSupport and IWorkbenchCommandSupport code. It creates HandlerSubmissions and EnabledSubmissions, handles the switching, and makes sure to "spoof" the IWorkbenchSite with something these classes can recognize. (The problem here is that the workbench has no concept of nesting, per se, and so only reports the top-level site as being active. This leads to confusion when the submissions are trying to sort out whether they are active or not.)
Moving duplicate resolved (but not fixed) bugs to verified for M8.