This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Currently, if a module wants to provide an editing capability for a file, the most convenient way to do this is to use the DataEditorSupport class. However, this class depends on the DataSystems API, which is pretty much deprecated. If the desire is not to use the datasystems API, there should be a simple way to provide editing support with the knowledge of the FileObject only. I am attaching a zip file which attempts to do just that. There is a base abstract superclass called org.openide.text.FileEditorSupport, which does the basic operations such as reading and writing to the file. Then there is a specialized subclass called org.netbeans.api.projects.ide.ProjectEditorSupport2, which implements specific functionality needed by the F.E.S., such as getting the lookup for the FileObject. (I named this class ProjectEditorSupport2 only because ProjectEditorSupport is already taken - we can later rename this). I can imagine that there could be other non- abstract subclasses of F.E.S., e.g. one which would rely on the FSExtensions API. This implementation is only a sketch, so it does not implement a lot of the functionality currently provided by DataEditorSupport, such as listening on rename/move operations of the file, providing information about the file in the Line objects, or detecting an external change of the file. Here are some points regarding the design of the classes: 1) Currently DataObject has a role which does not have a direct counterpart in the DataObject-less world: holding the information about whether the file is modified, listening on the changes of the modified/unmodified state, and some support for locking found in the MultiDataObject.Entry class (the takeLock() method - note that I don't really know what it's for and what it does). I am not sure where this should be put - for now I created a class called ModifiedSupport, which has these roles. The intent is that an instance of this class would be present in the Lookup of every fileobject (by registering it to MIME type ""). If we go ahead with this (or similar class), then DataObject should delegate to it, so we don't hold the state twice. 2) The FileEditorSupport class is dependent on Lookup and on Node for the FileObject, and it is expected that subclasses will provide these. I can imagine two possible ways to add lookup or Node for a FileObject: the Projects API and the FSExtensions API. The Lookup is used to get the ModifiedSupport class, and to find the instance of the FileEditorSupport after component deserialization (which does not work in my prototype). The Node is used to get the icon and display name of the editor. I am not sure how this can be replaced if in the future the Nodes API is deprecated in favor of Looks. 3) Currently, subclasses of DataEditorSupport (e.g. org.netbeans.modules.text.TXTEditorSupport) use a hack to add SaveCookie to the DataObject. This hack is both undesirable and impossible in the DataObject-less world. To implement the addition of SaveCookie into the lookup for the file, one has to do another not-very-nice thing: this is implemented by the static method FileEditorSupport.createLookup(...). The returned lookup should be used by module authors for the FileObject, rather than directly putting an instance of the F.E.S. into the object's lookup. I can't think of a more elegant solution. 4) Shouldn't there be a similar class for opening files in general (without the dependency on DataSystems), e.g. FileOpenSupport ?
Created attachment 10776 [details] Zip file containing the new files for DataObject-less editing
Thanx. Something like this will be needed and is mentioned as open issue on FSExtension page. At the moment this is on back burner for me. It is important and I hope to get to it ASAP but realistically not in next couple of weeks.
IMHO this should be deferred and done as a natural part of the FS Extensions API. Projects might need to extend that support a bit (but perhaps not, at least for simple cases). FS Ext should cover: - modification state of the file - locking using plain FileLock's - which is all takeLock normally does anyway - general lookup for the file object ("cookies"), including the editor support, and also permitting pluggable lookup factories which would permit the SaveCookie to be added/removed by the support (or, a SaveCookie2 could be introduced with an isModified / PROP_MODIFIED extension to SaveCookie, so the editor support could directly implement it) Looks API, working together with FS Ext, should cover: - display name etc. for the file - can get this directly from the Look, no need to ask for a Node
I agree that a lot of the functionality can be implemented using the FSExtensions and Looks APIs, esp. the lookup part and the display name/icon part. I don't know what you mean by saying that FS Ext will cover the modification state of the file: is it just that FS Ext will provide lookup that will hold SaveCookie/SaveCookie2, or something different ? Regarding SaveCookie2, it seems that you are suggesting that SaveCookie2 would be present on the object permanently, regardless of whether the file is modified or not, right? (Unlike currently SaveCookie, which is added or removed dynamically.) Well, that's an option, but I was worried about breaking code like: if (myNode.getCookie(SaveCookie.class) != null) { displayMessage("The object is modified. Your action will be cancelled!"); } Would SaveCookie2 be backward compatible for the above code? Also, are you saying that you see no value in having a common superclass implementing the FileObject aspect, but independent of the Nodes, Looks and FSExtension APIs ? Do you think all this should be implemented directly with the dependency on FSExtensions, with no abstract superclass ? Also, where do you think the FS Ext-based EditorSupport should be located ? I am assuming that you don't want to introduce a dependency of FS Ext on Looks or vice versa.
I suppose that FS Ext would not directly provide the lookup facilities for SaveCookie. Rather, it would provide a single centralized lookup for each file, with contributions taken from arbitrary factories that can be registered. One such factory would be supplied by the file editor support (or perhaps by some more generic ModificationSupport, TBD) and would contribute a SaveCookie when and only when the file was modified. This part of the API is yet to be designed in detail, I think. Re. compatibility concerns for "SaveCookie2" - yes, this could be a problem. I don't know if such a change could be introduced compatibly. It is not really necessary, but might simplify things a bit since it would avoid the most common case where the cookies on a file need to change on the fly. "Also, are you saying that you see no value in having a common superclass implementing the FileObject aspect, but independent of the Nodes, Looks and FSExtension APIs? Do you think all this should be implemented directly with the dependency on FSExtensions, with no abstract superclass?" - definitely I think the main superclass should directly use FSExtensions. Perhaps use of Looks (as I said Nodes should be unnecessary) could be factored into a separate subclass, if desired. I don't think there is any proposal yet for what the revised Editor API should depend on - we just cleaned up the Datasystems API dep, but DataEditorSupport still uses Nodes. Anyway CloneableEditorSupport is still the neutral superclass, with some proposed file editor support just a convenience subclass, so I think factoring out API dependencies from it is less critical than from other places.
Yes, most of the stuff in this area is still TBD.
Currently org.openide.text does not depend on filesystems API. I suggest not to add such dependency and keep the package clean.
Ok, point taken. Now I am convinced that the base superclass should be tied to FSExt. Jesse, I still don't understand how FSExt would help providing the SaveCookie-enabled lookup. At best, FSxt could provide a LookupContentFactory, but the module would still need to register this factory for this particular object's MIME type. To me, that does not sound like a huge improvement over the static method: static Lookup createLookup(SomeEditorSupport supp) that is in my prototype. What in particular do you mean here? Also, there can be some problems with the use of Looks instead of Nodes: - The support will still need to call cloneableEditor.setActivatedNodes(...); (the windows package depends on Nodes quite heavily) - The support will need to listen on changes in the Look and LookSelector, which is not possible currently (but straightforward to remedy) - The editor will need to get hold of a look instance. I don't think it is in Lookup normally - should it be ? Can this be relied on ?
Re. SaveCookie - no, the module would not register the factory. The file object editor support class would register a singleton factory potentially contributing SaveCookie to any file; for a file that it in fact had modified, it would add it. Not generally wise from a performance standpoint to register a lookup factory for every file, but in this case such a large number of files could potentially use it (since so many files will have EditorCookie) that it seems acceptable to me. Alternately, you could request that the module which registers the factory for the EditorCookie also delegate to a factory for SaveCookie provided by the editor support. Syntax TBD based on how FS Ext factories look. I guess that is more or less what your prototype is already doing, which doesn't seem too bad to me; just one extra step to do when adding an editor support. (In the old days, adding a simple editor support consisted of one line of code in a DataObject constructor. Since then it has gotten more clever, and essentially impossible to figure out without a detailed template. Ideally we should restore the simplicity of the original system for the simple cases, I think. E.g. register Files/Lookup/text/x-mytype/ed-factory.instance with a couple of attrs saying it is a factory to create EditorCookie using a certain impl class, and you are done.) Re. cloneableEditor.setActivatedNodes - true, the window system currently relies on the Nodes API, but this might be generalized in the future (e.g. setActivatedObjects? where the Object is rendered by a Look) so better to keep the editor support clear of it, if possible. Not sure how the editor should find the best Look for the "file" (or whatever it is editing). It could grab the value of the StreamDescriptionProperty from the Document and use Selectors.defaultTypes to find a Look for it. Maybe there is a better way though. Probably it should be overridable by support subclasses with special needs.
Also related to issues 34814, 34815. http://www.netbeans.org/issues/show_bug.cgi?id=34814 http://www.netbeans.org/issues/show_bug.cgi?id=34815
Oh, I should've known about this... I've resurrected the DS_II idea, updated the branch to registry and looks/2 and currently I'm trying to rewrite the text module to be fully DO-free. I have working editor support over FOs and even fully functional SaveCookie storage. Although not reading Jesse's advices before, I've implemented it in very similar way: FSExt have registered (for mime currently) an EdSup factory which is then instructed by the EdSup to add/remove the SaveCookie. I've also met the Node problem, currently I'm plying with defaultTypes Selector for it. Generally, If we want to go Nodes-free, we also need to have some replacement for selected nodes (selected representedObject? selected enviroment/lookup?) in WS API/implementation. IMO selectedObject is too narow, lookup would be more general and better allow for BW compatibility (you can easily find the Node there, the real representedObject (e.g. FO), interesting cookies, the ContextAwareAction uses Lookup for this purpose already and e.g. WS started using TCLookup.lookup(SaveCookie) for recognizing "modified" TopComponent)
Sure, "selected lookup" may work - for compat, if you select a Node in an explorer view, Node.lookup is used (which includes the Node itself plus all its cookies), probably via Looks.proxy. If we do a pure Look explorer, just Look.lookupItems can be proxied to. (May still need some way to get the representedObject out of the Lookup - TBD whether this is actually required.)
Reassigning to new module owner mslama.