Community
Participate
Working Groups
Composing workbench parts, including editors, should be easier. MultiPage editor is one way to combine editors, but it's really hard to use the class. The "part pattern" is really useful and could be leveraged more often. To do this, JFace could be enhanced to support more than just the single level of parts it currently supports. Instead of: + root (the Page) |=outline |=navigator |=editorpart you could have: + root |=outline |=navigator + editor |= source editing part |= visual editing part The editor becomes a part container similar to PartSashContainer. When the focused pane in the editor switches, the editor would indicate this to the page, and eveyone would be notified that the active part (or more appropriately a "part path") has changed. This means views like the outline would flip to the IOutlinePage corresponding to the source or visual part automatically. Similarly, keybinding contexts would change, global action handlers would change, and tons of other things which are currently a nightmare for such editors. Not recognizing deeper levels of composition of parts in JFace means that clients have to re-implement things like outline page-flipping within their own top-level outline page. It also means that the part pattern is not reused when it could be.
Randy, please do not directly assign newly created PRs directly to developers. It skirts around our process for routing PRs to the appropriate person.
Am assigning to [Workbench] component primarily as this PR affects a variety of components: - JFace - EditorMgmt - ViewMgmt - KeyBindings - etc.
For an example of the type of workarounds being employed, one client is faking a bogus Shell Activated event to trick the workbench window into re-activating the focused part.
Re comment #3, why can't he just do a page.activate(topLevelEditor)? Ideally parts wouldn't have to talk to the page, but would interact with the outer workbench only through their site. This would simplify nesting. For example, to determine whether an editor is active, you can do page.getActiveEditor() == myEditor, but this only works for top level editors. It would be better if you could do myEditor.getEditorSite().isActiveEditor(). Both the site for top-level editors and the site for nested editors would implement this appropriately. As for the original comments in this PR, the semantics for composing workbench parts is usually more complex than simply delegating everything to the nested part. E.g. for a multi-page editor, usually the top level editor wants to handle some actions, but delegate others to the currently active nested editor.
I don't know why Nick's suggestion wouldnt' work. The part (not always and editorpart) is already active. Maybe there is a check for this which causes nothing to happen. Anyway, there is still the issue of things which go on outside of the editorpart itself, such as outline, properties, and in WSAD lots of other views which are part-sensitive. What I am suggesting is a part tree, where there would be an active "part path", not just an active "leaf" in the tree. If the parent part (the multi- page editor) registered a global action handler for "Save", it would somehow take priority over its leaves doing the same thing. I suppose it could also be possible for the parent itself to be the active part. Most clients interested in the active part would not need to know the entire "path" which is active, but just the end of the path.
Marking for investigation in 3.1. We've started looking into an improved service model, which is an essential ingredient for improved composition / nesting. If anybody knows of good approaches to this, please contribute. e.g. anybody familiar with OSGi service model, Apache Avalon, etc.
What is meant by service model? Is it the PartSite and the combination of SelectionService, KeybindingService, PartService, etc.?
Essentially, yes. The site will isolate a part from its containing context. All access to the containing context will go through services provided by the site. But in order to support nesting, we'll need to make it possible to implement the site interface. We don't want to hardwire a fixed set of services, or require that new methods be added for each new service. We'll need something more open-ended like IAdaptable.
The draft version of the component framework spec is here: http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/components-proposal/ComponentFrameworkProposal.html However, the part of greatest relevance to this PR (ie: how to create views and editors and what services will be available to them) isn't written yet. :-p
I've been using the [Services] tag to help group together items that might influence the new component and service design.
Thanks, Doug... this has given me some good use-cases to check against.
For those of you that wanted to check this out over x-mas, I'm attaching my current work-in-progress here. I know there's still a lot to do, so please don't email me about everything that isn't working yet (I already know :-p ) or the horrible names/organization/javadoc... but I would be interested in feedback on the examples. So far, there are examples of: - Comparison between new style / old style "hello world" view - A view being opened by ID in a dialog. - A UI component being instantiated programmatically (can be used to construct reusable UI building-blocks that aren't views or editors, or to instantiate certain parts outside the workbench). - A view that allows any file to be opened in an embedded editor - An old-style view that uses new-style services (yes, existing views/editors can use all of the new services). - A view that contains two other embedded views - Demonstration that (without modification) any part can be used as a view, an editor, or embedded within another part (regardless of whether they implement IViewPart, IEditorPart, or use constructor injection). - A view that multiplexes its site between four child parts (it's toolbar/menus/trim/selection/etc. come from whichever child has focus).
Created attachment 16829 [details] UI component examples plugin This is the most interesting attachment. This is a project exported from my workspace, not an installable plugin.
Created attachment 16830 [details] Component framework plugin Component framework plugin (exported source from workspace).
Created attachment 16831 [details] o.e.ui.tests patch Some additional examples and error scenarios here.
Created attachment 16832 [details] o.e.core.runtime patch
Created attachment 16833 [details] o.e.ui.workbench patch This patch is necessary to get the examples working, but it's still under heavy flux.
Merry christmas :-)
Created attachment 17006 [details] org.eclipse.core.components plugin Latest version components plugin. Significant cleanup + JavaDoc.
Created attachment 17007 [details] Examples plugin
Created attachment 17008 [details] o.e.core.runtime patch
Created attachment 17009 [details] o.e.ui.workbench patch
I'm not attaching the tests patch because it's a bit out-of-date.
Created attachment 17019 [details] Latest component plugin
Created attachment 17020 [details] latest examples
Created attachment 17021 [details] o_e_core_runtime patch
Created attachment 17022 [details] o_e_ui_workbench patch
For what it's worth you might want to look at how themes accomplish nesting of colour and font registries.
When you attach patches, can you mention which version of the workbench to patch? Thanks.
The latest patches were against HEAD on Jan 7, 2005. The patches I attached on Friday weren't the latest version, which is why I reattached them on Sunday.
Here's the latest version. Almost everything works now. Much more in the way of javadoc, examples, organization, etc. Things remaining to do: - editorActions extension doesn't nest yet (viewActions are working) - keybindings service doesn't multiplex yet - IEditorActionBarContributor isn't being created for nested editors - top-level editors are going to need their own action bars (rather than the purely shared instance they have now). - Editors and views aren't completely interchangeable yet because of their different treatment of IActionBars. Based on my discussions with Nick, I'm also planning to make the following changes: - Refactor the scoping system so that it is possible to resolve scopes from extension point XML without loading any Java classes. - Rather than disallowing components from depending on a type they implement, treat this as a reference to an implementation from an outer context. This should simplify the multiplexer code. This will simplify the multiplexer code. - Allow the components extension point and ContainerContext to register a factory for multiple interfaces. This will the same instance to satisfy multiple dependencies. Dirk suggested including as split-pane editor as an example, but I will still need to fix the keybindings before this will work in any useful way. This will be going into head before M5, so now would be a good time to make any suggestions on the APIs if you have them.
Created attachment 17313 [details] components plugin Latest org.eclipse.core.component plugin
Created attachment 17314 [details] Pascal's patch for org.eclipse.core.runtime
Created attachment 17315 [details] org.eclipse.jdt.ui patch (fixes compile errors)
Created attachment 17316 [details] component examples plugin
Created attachment 17317 [details] org.eclipse.ui.workbench patch Note: all of the patches were generated against HEAD at approx 6:30pm on Wed Jan 19, 2005. The zip files are exported projects.
Pascal, the component framework works fine with your patch. Could you please commit the patch you sent me for org.eclipse.core.runtime?
Regarding the original PR: The patch will allow parts to be easily nested and composed in arbitrary ways. Rather than exposing a part path, parts are opaque to their containing context and make use of a Multiplexer object to reuse things like outline page flipping. Randy, I'd appreciate if you could check out the examples plugin and let me know if it solves your original problems, even though the implementation is somewhat different.
Created attachment 17318 [details] Rough draft for a revised proposal Here's a new proposal for components framework. Based on the feedback I got on the original, I completely rewrote it in order to focus on views, editors, and nesting rather than the framework itself. This is unedited and the examples and terminology have changed slightly... but even in this rough form it should be useful for making sense of the patch. I'll put it up on the website once the editing is finished.
The proposal looks very promising. But I'm a bit concerned about performance. If I got everthing right there is a lot of Reflection to be done etc. If you need a Dialog once a year, but you have to declare it in your Constructor, the Dialog will consume construction Time and memory everytime this part is constructed. I know that the possibility remains to do it the old way. But it looks like it will be overused.
I agree with the comment #40. Indeed IMHO it seems to me that this is such a big change in the workbench (I somehow compare it to the change of runtime last year) that some performance test should be done even before releasing the code.
If it's anything like the runtime change last year, the API stays the same, but the implementation gets 10% faster :-)
(More correctly, the API is compatible, while a new API is introduced). The proposal looks very promising and seems to address 80% of the goals. The other 20% might be there but I just can't see it. I have comments about names of course(like "site" and "containercontext", which seems to repeat itself) and some of the services, but I'll focus on what might be missing for now. Nesting is invisible to the outside world. How will external components track nested component "focus". For example, the Outline View might need to query a different content outline for each nested part. Bug 72556 might also want to track nested components instead of just parts. How does a composite part partially override the multiplexed services of its components. In Nick's example, a multipage "editor" would want to override CTRL+S for Save, and several other commands, while allowing the composed editors' other keybindings to work. I guess this is done using a special IActionBars implementation? Is that interface going to be available in pieces too? For example, I want to be able to provide just the StatusBar service to the active tool in GEF. Are workbench pages going to eventually be one of these new components? What will become of IViewPart, IEditorPart, IOutlinePage, etc. Should I forget about there interfaces ;-). Is it possible to create an editor which is not an IEditorPart? Regarding comment 40: This looks like the same amount of reflection already used to instantiate parts in 3.0. The dialog is a lightweight service, which only creates the SWT dialog if it's needed. Some services will be singletons, or perhaps shell/workbenchwindow-local. Some of these are created already in 3.0. They are just made available passively instead of via the constructor.
Performance: comment 40 is good to keep in mind. It can never hurt to have performance tests in order to ensure there are no regressions (BTW, if anyone wants to contribute any performance tests, I'd be grateful and will be sure to run them.) Personally, I'm more worried about the cost of service lookup (ContainerContext) than the actual reflective calls. If anyone can suggest a more efficient alternative, I'd be glad to hear it. Names: Randy, if you have any name change suggestions now is a good time to make them. I'll be working on finalizing the proposal soon. FYI, the terminology in the patch is more up-to-date than the proposal. Multiplexing: Parts don't expose their children. If a part wants the outline view to show the outline for its active child, it offers a single outline page to its outer context and swaps the actual contents in and out. So that every client doesn't need to code this themself, the Multiplexer class lets someone write the swapping-in-and-out code once and then reuse it everywhere. Workbench pages will not be components (at least not for 3.1)... It is now possible to create an editor that isn't an IEditorPart. IEditorPart and IViewPart can be used interchangeably with constructor-injected components. IOutlinePage hasn't changed and is still necessary. Although many services *could* be window/plugin local, all of the services in the current implementation are either singletons or part-local. The IMessageDialogs service is a good example of where window-local services would improve performance further.
The changes in runtime have been released.
JavaDoc->"All components must have exactly one constructor". Does this imply that all exposed components should either be declared final, or that their dependencies can never change/grow over time? If I wanted to create a PaletteComponent, if it needs some new service in the future, I must add it to the constructor, which would break any client subclass.
Good point. It would make sense to enforce that they must be final. Nick and I also discussed adding optional XML markup that would allow you to specify a particular constructor for classes where a choice exists... but that's not for the first cut.
Basically, we're just using java reflection as the way to extract meta info about a component. An alternative would be to declare the meta info some other way, such as specificying a component's dependencies in XML. IMO, this seems more like the Eclipse "way". The requirements could then be passed to the constructor, or even a traditional init(...) method, using a Map or List or something which could be extended. Expressing dependencies would be under your control and could be richer than what reflection allows. It could include things like optional dependencies, which would allow a baseclass to evolve over time and maintain binary compatibility.
Randy, I think this may be the straw that breaks the camel's back. The constructor dependency injection seems to be the least-popular aspect of this proposal, so I'm going to investigate alternatives.
I'm attaching the latest version of the patch here. We're waiting on the webmaster to create the new CVS project, but assuming we get it in time, this patch should be pretty close to what goes into M5. --------------- I've settled on the following terminology: A "component" is any java object created by a ComponentFactory. The term doesn't refer to a special kind of object - it refers to an object that was created in a specific way. A "service" is any java object that can be returned by a ServiceProvider. The term does not refer to a special kind of object, but an object that is used in a specific way. In other words, a component is something that can have dependencies and a service is something that can satisfy dependencies. If an object is created by the framework and used to satisfy dependencies, then it is both a component and a service. The extension point and classes have been renamed accordingly. ----------- The framework is no longer based around constructor injection. It is based around factories. Anyone who wants to create a component supplies a factory class that implements a "createHandle" method. The factory explicitly looks up whatever services are needed by their component. For those that like constructor injection, the framework includes a standard factory called ReflectionFactory that tries to instantiate the class by examining its constructor arguments. ReflectionFactory permits multiple constructors. If there is more than one, it will try them all starting with the one that takes the most arguments. Clients can choose not to use this helper class in situations where the choice of constructors would not be obvious. For example, the following markup creates MultiplexAllView by constructor injection: <view class="org.eclipse.core.components.ReflectionFactory:org.eclipse.ui.examples.components.views.context.MultiplexAllView" category="org.eclipse.ui.examples.components.context" name="MultiplexAllView" id="org.eclipse.ui.examples.components.views.context.MultiplexAllView"/> ---------- Other notable changes: - The framework now includes a formal scoping system. There is a scope for plugin-wide services and we could potentially create scopes for services shared across a workbench page, window, etc. The old "initializers" are gone. - IErrorContext has been broken into two services: ISystemLog which handles logging and IStatusFactory which constructs status messages. - IContainer is gone, although the concrete Container class is still around. A new IServiceProvider interface has been added that provides access to services but does not necessarily contain them. - I've temporarily commented out the IActionBars service. It is causing too many problems. Hopefully, Doug's work on commands will offer a good replacement for M6. Until then, toolbars, keybindings, and all the other stuff that happens through IActionBars won't work for nested components. If anyone has any last-minute suggestions (in particular, regarding class names), now would be a good time to make them. :-) Patches will follow.
Created attachment 17881 [details] component framework plugin
Created attachment 17882 [details] component examples plugin
Created attachment 17883 [details] workbench patch
Created attachment 17884 [details] components framework
Created attachment 17885 [details] examples plugin
Created attachment 17886 [details] o.e.ui.workbench patch
Created attachment 17887 [details] o.e.ui patch
Created attachment 17888 [details] o.e.ui.tests patch (incomplete)
Basic nesting support is now in head. The Multiplexer is internal for the moment until it is more extensively tested.
I'm a bit annoyed by the overloading of the term service, especially since we are osgi based. Given that the relation between this new framework and the osgi service and declarative service are unclear, I have a question: will this new API be marked as experimental for 3.1?
It's experimental. I'd be happy to consider alternative terminology if someone can suggest it.
Experimental meaning 3.2 might not be compatible with 3.1? Out of curiousity, in what place does this get documented as experimental?
Yes, meaning 3.2 might not be compatible with 3.1. I think I added the "EXPERIMENTAL" tag to the javadoc all the new classes. Please let me know if I missed any.
The component framework has been moved out of the core namespace because of terminology conflicts with OSGi. The code currently resides in o.e.ui.workbench. Re: OSGi terminology conflicts We can use the term "pluggable" instead of "component", and the term "connector" instead of "service". Re: similarities with OSGi This framework is a loosely coupled way for a part to communicate with its enclosing context. OSGi is a way to dynamically install and uninstall bits of application functionality.
I don't see how OSGi's use of the word "Service" precludes additional (correct) uses. Most programmers do not deal OSGi directly anyway. SelectionService, PartService, etc. already establish this naming convention so we should just stick with it. How many ways are the terms "part", "command", "policy", "strategy", or "provider" used?
Defer until 3.2. We are still discussing moving the component framework into core, and the Eclipse UI has not had a chance to use the nesting support internally for any real-world problems. Most of the support is now in place and appears to be working, but there is not enough time to finalize the new API before the 3.1 API freeze. For this reason, the component framework and nesting support is moving into internal packages. It will be moved back to API post-3.1.
FYI, almost everything is working. I will be checking in support for nested keybindings, toolbars, IEditorActionBars, and status lines when the code moves to internal packages.
Is there a difference between internal and marking as "experimental"?
Our company will be using this feature in our product based on 3.1. Moving the API to internal packages will make it harder for us to maintain compatibility with both 3.1 and 3.2.
Re: comment 68 The difference between "experimental" and "internal". Experimental isn't officially recognized. It's just a note that the programmer attaches to his code to tell people that it's still in flux, and might have breaking changes until the next release. If something ends up in an API package in a release (like 3.1), it's officially supported (presumably forever), regardless of the experimental tag. "internal" means the class isn't API and shouldn't be used by clients. Re: comment 69 What aspect of the patch were you using? (Ie: the new utility services, the new view/editor API, the capability to embed parts using IWorkbenchPartFactory, or the capability to embed parts programmatically?). Are you shipping your own RCP app or an Eclipse plugin? Nick, can you make a recommendation here?
> Nick, can you make a recommendation here? I'd have to hear the scenario first.
Re: second part of comment 70 We haven't yet started to use the embedding feature. We will be using it to embed a subclass of CompilationUnitEditor to give user ability to edit java code snippets.
If you're writing an RCP app, you can just hack the platform and ship on the hack. You could isolate the breakage by writing a quick wrapper for IWorkbenchPartFactory that has this method: Composite createEditor(String ID, Composite parent, IEditorInput input, IWorkbenchPartSite siteToInheritSomeServicesFrom) ...in that case, you'll only have one method that breaks when 3.2 ships. There's probably some clever way of sticking this in a compatibility plugin so that in 3.2 you can conditionally select the right implementation for your version of Eclipse.
for 3.2
This bug should remain as LATER pending a final 3.2 plan.
Hopefully, you took that as a request that this be fixed in 3.2. I'm not trying to do your planning (i.e. the target milestone field).
Shouldn't this be reopened and pushed to HEAD pretty soon if it's going into 3.2? See also bug 36968.
The platform plan is being worked on right now and this item is not going to be re-opened for 3.2.
Re #78: If you have time, could you elaborate just a little on the state of this and rationale please? Looking back over the comments it seems that the code actually got pushed into 3.1 but was made all internal. Will it ever be API? Is it being used internally now or just sitting there (i.e., has the old way been refactored to use it)? Enquiring minds want to know... The idea seems really useful and a lot of effort was put into it so it would be a shame to see it not used. It also appears to be blocking several defects/enhancements.
The code that went into 3.1 was built on top of the older code. The internals have not yet been refactored to use the new stuff. It is currently unused, except by the code in the component examples plugin (you can find it in CVS to get a feel for the state of the current implementation). I'm no longer working full time in the Eclipse UI, so someone else needs to take over this (rather major) refactoring. If I understand correctly, the UI team is still very interested in this but it will take longer than 3.2 for someone to get the deep understanding of both this area of the workbench internals and my work in progress. Work hasn't completely stopped. I have continued to work on the component framework for my own (closed source) projects, and am now using more refined version for real development. If I can get through all the usual legal red-tape, I would be interested in contributing it back to Eclipse once others on the UI team are ready to look at it and take over the internal refactoring. (Note: when and if I contribute this back to Eclipse, there will still be a lot of munging around with workbench internals before all existing views and editors will be nestable with 100% functionality) At least three other UI comitters have talked with me about how to refactor their areas of the workbench to make them more component-friendly, so I suspect that development is moving in the right direction, even if we don't see any new API for 3.1.
That should have read "even if we don't see any new API for 3.2".
Ed, regarding comment 79, no problem, I'll have a little time later to do this.
The lack of this function probably costs clients (commercial and within Eclipse) more resources than any other missing function or bug. I see so many posts about multipage editors on the GEF forums that I have run out of replies.
> I have continued to work on the component > framework for my own (closed source) projects, and am now using more refined > version for real development. If I can get through all the usual legal red-tape, > I would be interested in contributing it back to Eclipse... Actually, since the original version is in EPL, if the more refined version is used in a product then they'll have to let you contribute it back or it'll be a license violation.
*** Bug 71125 has been marked as a duplicate of this bug. ***
overdue response promised in comment #82 Work on general support for this has been deferred for 3.2. There were a number of reasons. First, after a careful evaluation and investigation it was clear that making these changes would be highly invasive for UI and essentially be creating yet another layer for code to go through. We are not afraid of the code but it meant a serious effort and more then one person working on it for most of 3.2. Balancing this off with other plan items, such as the JFace Data Bindings work which had persons lined up and ready to contribute code in a short amount of time determined that this was not the best use of our time. Stefan has mentioned that he is still using it on his own, I encourage this and think that could pave the way for easier future adoption. He mentions that there would still be lot of work in the workbench, as writing the framework is different then porting the workbench to it.
please consider finishing the partial internal implementation of this feature in 3.3, and making it API.
+1
It is very unlikely that we will be able to do anything about this for 3.3 since it didn't make it into the 3.3 plan. If we were to attack this again, we won't try to solve the hard problem of being able to nest existing parts (views or editors) inside others. I am thinking more along the lines of defining a way to nest pieces of UI, i.e. being able to host such pieces inside of others, with well-defined nesting behaviour for things like focus, keybindings, contributed actions/command handlers/menus/toolitems, providing selection, being able to drop into, etc.
Just a reminder that bug 8009, the 2nd most voted for bug in the system, has been marked as dependent on 46207. I hope that the intense desire for a solution to 8009 can light a fire under this one.
> If we were to attack this again, we won't try to solve the hard problem of > being able to nest existing parts (views or editors) inside others. But that is the whole point of this bug. And, clients have been hacking at this ever since MultiPageEditorPart was released in v1.0. I would guess that you are actually much closer to reaching the real goal than you give yourselves credit for. With expressions, servicelocators, and the new set of services, all that is missing is the ability to create servicelocator branches, and turn them on and off.
I see two hard problems that prevent us from solving the general problem (being able to nest arbitrary existing parts): 1. Existing parts don't always use their site to access their context, but reach out to singletons like PlatformUI.getWorkbench(). This prevents nesting. 2. Part listeners (IPartListener/IPartListener2) are notified about changes to "the active part", and they are given an IWorkbenchPart/IWorkbenchPartReference. With nesting, you would activate a "part path", and I don't see a way to shoehorn this into the existing part listening logic.
Removing bogus milestone. Bug is still open. Need to reconsider this in 4.0 stream.
In response to the latest webinar from Eric[1] I would like to "reopen this defect" and ask for the status. I wonder if Eclipse 4 at its current shape gives any hope of fixing bug 278005. [1] http://live.eclipse.org/node/1061
The status as I see it is that this is basically done...you can: - put multiple stacks in a Detached Window (including min/max support - Move editors out of the editor area (or views into it) - Split editors (bug 8009) The underlying e4 modeled ui is easily flexible enough to support many (but not all) different 'shapes'. The only thing we are lacking is the ability to split views IMO. If you think that there are other things that we've missed please -do- re-open the defect with suggestions...
Verified in 4.4.0.I20140429-2000.