We are using NetBeans Platform 7.0.1, and have implemented support for a new language using this (now “obsolete”) tutorial.
Since all our contents are stored in a database, and not on files, we open them like this:
FileSystem fs = FileUtil.createMemoryFileSystem();
FileObject fo = fs.getRoot().createData(fileName, fileExtension);
… write contents from database to `fo` ….
DataObject data = MyMultiDataObject.find(fo);
EditorCookie.Observable cookie = data.getCookie(EditorCookie.Observable.class);
cookie.open();
… forces undock of editor window …
And, in our layer.xml, have added a custom button to Save that sends the content back to the database.
However, when the user closes the file (by either closing the tab or the window), we haven’t figured a way of saving it.
Adding a PropertyChangeListener to the Cookie and watching for PROP_DOCUMENT (and newValue() == null) seems to do the trick for when the window is closed. But how does one get the return value from the confirmation window (I’m referring to when the file is closed after changes, the message File xxx.xxx is modified. Save it?)?
Well, it seems we've been approaching the problem in the wrong way.
Since we are opening the file in-memory, it was suggested in the netbeans-dev list that we should listen for changes in the file itself, by using
fo.addFileChangeListener(new CustomFileChangeListener());
public class CustomFileChangeListener implements FileChangeListener {
#Override
public void fileChanged(FileEvent fe) {
... file has been saved in the editor, sync with database ...
}
}
And keep it synchronized that way, taking advantage of the built-in NetBeans Platform "save" functionality.
Related
I have a plugin which work with special json config files,and it can be runned by the Run button.
I make changes to the config without saving the file.
If I the hit the run button to try it out, plugin will use the config as it is on disk...
It would be nice if the tool would either save all files before running -
or at least give a warning message that tells me that some files are not saved..
How can i detect modified files and get a list of this files?
How can i save changes in this files?
You can look at all the editors which are marked 'dirty' (have modified data) using something like:
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
for (IWorkbenchWindow window : windows)
{
IWorkbenchPage[] pages = window.getPages();
for (IWorkbenchPage page : pages)
{
IEditorPart[] editors = page.getDirtyEditors();
for (IEditorPart editor : editors)
{
IEditorInput input = editor.getEditorInput();
if (input instanceof FileEditorInput)
{
IFile file = ((FileEditorInput)input).getFile();
// TODO ... deal with file
}
}
}
}
Note: Not all editors use FileEditorInput so you might need more code if the editor is using a different input.
When you have an IEditorPart you can call the
public void doSave(IProgressMonitor monitor);
method to get the editor to save its data - but you should confirm with the user first that they want to do this.
So, I’m currently developing a plugin for the eclipse IDE. In a nutshell, the plugin is a collaborative real time code editor where the editor is eclipse (which is something like Google documents but with the code and on eclipse). Meaning that when I install the plugin, I would be able to connect -using my Gmail account- eclipse to the partner’s eclipse. And when I start coding on my machine, my partner would be seeing what I write and vice versa.
The problem I’m currently facing is accessing eclipse’s editor. For example, I have to monitor all the changes in the active document so that every time a change happens, the other partner’s IDE would be notified with this change.
I found and read about the IDcoumentProvider, IDocument and IEditorInput classes and they’re somehow connected but I can’t understand this connection or how to use it. So if someone can explain this connection I would really appreciate it. Also if there is another way to achieve my goal?
You can access the IEditorPart via the IWorkbenchPage.
IEditorPart editor = ((IWorkbenchPage) PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage()).getActiveEditor();
From there, you have access to various other classes, including the editor's IEditorInput, the File loaded by that editor, or the underlying GUI Control element. (Note that depending on the kind of editor (text files, diagram, etc.) you may have to cast to different classes.)
FileEditorInput input = (FileEditorInput) editor.getEditorInput();
StyledText editorControl = ((StyledText) editor.getAdapter(Control.class));
String path = input.getFile().getRawLocationURI().getRawPath();
Now, you can add a listener to the Control, e.g. a KeyAdapter for monitoring all key strokes occurring in the respective editor.
editorControl.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Editing in file " + path);
}
});
Or, if monitoring all key strokes is too much, you can register an IPropertyListener to the editor. This listener will e.g. be notified whenever the editor gets 'dirty' or when it is saved. The meaning of propId can be found in IWorkbenchPartConstants.
editor.addPropertyListener(new IPropertyListener() {
#Override
public void propertyChanged(Object source, int propId) {
if (propId == IWorkbenchPartConstants.PROP_DIRTY) {
System.out.println("'Dirty' Property Changed");
}
}
});
The standard behavior of the Eclipse workbench is to preserve the set of open files between invocations, and attempt to reopen those same files on restart. If any of the files is missing, then a placeholder editor appears showing an error message about the missing file. We'd like to change the behavior of our Eclipse RCP application to just silently skip any missing files instead.
We're already writing our own IApplication, WorkbenchAdvisor, etc; these classes get to inject various behaviors into the platform, but I haven't found a way to accomplish these through these classes. How could we implement the desired behavior?
The way I've handled this is actually in the editor being created: Override setInput to examine the IEditorInput being passed in for validity by calling editorInput.exists() (which, in the case of a FileEditorInput, checks to see if the file exists) or if you're using custom editor inputs, any other validation you need.
If the editorInput fails validation, then close the editor asynchronously (Eclipse doesn't like it when an editor closes before it finishes opening):
public void close () {
Display.getDefault().asyncExec(new Runnable () {
public void run () {
getSite().getPage().closeEditor(YourEditorClass.this, false);
}
});
}
An alternative way of handling this issue is to just disable reopening the editors on startup - see In Eclipse, how to close the open files(editors) when exiting without auto-load in next startup
I have a CompareEditorInput shown in CompareEditor, it compares textual data. I need to reload CompareEditorInput when it is changed outside of CompareEditor.
Open compare editor (CompareUI.openCompareEditor(input))
Compare input is changed (ISteramContentAccessor.getContents() returns changed content)
Tell opened compare editor to reload CompareEditorInput <- needs to be implemented.
You could call setInput(sameInput) on CompareEditor, but since CompareEditor is internal and setInput() is not public in EditorPart then a workaround is to call IEditorPart.init(IEditorSite site, IEditorInput input).
IWorkbenchWindow wnd = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IEditorPart editor = wnd.getActivePage().findEditor(input);
editor.init((IEditorSite) editor.getSite(), input);
The new java io package java.nio.file package provides a file change notification API, called the Watch Service API. using this you can monitor the file on the disk and track for any changes. Check this for further reference
Create a separate thread which uses the WatchService API and monitors the file in the background and if finds any changes on disk, notify the user.
From within Java, I am opening an Excel file with the default file handler (MS Excel, in this case :-) ) using the method described in this stackoverflow question:
Desktop dt = Desktop.getDesktop();
dt.open(new File(filename));
However, the Excel program doesn't get the focus. Is there any easy way to do so?
Edit: There is a related stackoverflow question for C#, but I didn't find any similar Java method.
Edit 2: I've did some simple tests, and discovered that Excel starts and gets the focus whenever no instance of Excel is running. When Excel is already open en NOT minimized, the application doesn't get the focus. If instead the Excel Windows was minimized, the above code will trigger a maximization of the window and Excel getting the focus (or vice versa :-) ).
If you only care about Windows (implied in the question), you can change the way you invoke Excel: use "cmd start...".
I have been using this piece of code to launch Windows applications for some time now. Works every time. It relies on the file association in Windows to find the application. The launched application becomes the focused window on the desktop.
In your case, Excel should be associated with .xls, .csv and other typical extensions. If it is, Windows will launch Excel, passing your file to it.
Usage:
MyUtilClass.startApplication( "c:\\mydir\\myfile.csv", "my window title" );
file is the full path to the input file for Excel and title is the window title (the application may or may not take it - Excel changes the window title).
public static void startApplication( String file, String title )
{
try
{
Runtime.getRuntime().exec( new String[] { "cmd", "/c", "start", title, file } );
}
catch( Exception e )
{
System.out.println( e.getMessage() );
}
}
From a scala-program, which runs in the JVM too, I can open an application, and that get's the focus by default. (Tested with xUbuntu, which is a kind of Linux).
import java.awt.Desktop
val dt = Desktop.getDesktop ();
dt.open (new java.io.File ("euler166.svg"));
I can't say, whether this is specific for Linux, or maybe something else - however starting Inkscape in my example, excel in yours, may take a few seconds, while the user impatiently clicks in the javaprogram again, thereby claiming the cursor back. Did you check for that?
You could then change to the last application, at least on Linux and Windows with ALT-Tab aka Meta-Tab (again shown in scala code, which you can easily transform to javacode, I'm sure):
import java.awt.Robot
import java.awt.event._
val rob = new Robot ()
rob.keyPress (KeyEvent.VK_META)
rob.keyPress (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_META)
but unfortunately the unknown source off more trouble, also known as user, might do nothing, so switching would be the false thing to do. Maybe with a thread, which checks for a certain amount of time, whether the java-program has the focus, but it keeps a form of roulette, in an interactional environment, because the user may have a fast or slow machine, or change to a third application meanwhile, and so on. Maybe a hint before triggering the new app is the best you can do?