probably a really easy newbie question but I can't manage to get it for already a pair of days, so I'll aks it here. My scope: I have an RCP application with some Graphical Editors (extensions of EditorPart). In my editor I want to catch any changes and save them directly. For that I catch the moment in which my CommandStack gets changed and start a doSave method. The problem is that my save method calls a CommadStack change event and if i skip this call than my changes are saved but my editor has still got a dirty flag. My wished behaviour would be that the dirty flag is away(like a normal save behaviour).
Both my CommandStack change and my doSave method are below. Could you please help me?
#Override
public void commandStackChanged(EventObject event) {
firePropertyChange(IEditorPart.PROP_DIRTY);
doSave(null);
setDirty(false);
}
public void doSave(final IProgressMonitor progressMonitor) {
editorSaving = true;
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
IFile targetFile = getFile();
List<GraphicalEditPart> editParts = DiagramUtil.getAllEditParts(NetEditor.this);
Rectangle offsetBounds = DiagramUtil.getBounds(editParts);
saveDiagramProperties();
List<INetTransition> transitionsToExpand = saveSubdiagramGroups();
FileUtil.saveDiagram(getNetDiagram(), targetFile,
NetEditor.this);
getCommandStack().markSaveLocation();
for (INetTransition trans : transitionsToExpand) {
trans.setExpanded(true);
}
}
});
setDirty(false);
editorSaving = false;
}
With getCommandStack().markSaveLocation() I call once more the commandStackChanged and get in a loop. How can I solve this problem? Without it my editor remains dirty after save.
Thanks and Greets,
Jeff
How about adding IPropertyListener to your Editor and listen for IEditorPart.PROP_DIRTY. For the listener implementation perform save if editor is dirty otherwise do nothing.
Related
I'm fixing a JavaFX application on JDK 8. The app shows multiple images using something like "jLabel.setIcon(new Image(...))". I know their is a component to show images in JavaFX but it is not the issue (because I'm not allowed to modify neither that part from the source nor the FXML files).
My problem is when minimize or change the window ((using ALT+TAB)) and wait some time (even up 1 hour approx) to come back to the window, this doesn't show the images anymore. However, if I move the window, the images come back.
In an attempt to fix the problem (independently of use the minimize button or ALT+TAB), I added in the final of the init() method this piece of code:
public void init() {
...
stage.focusedProperty().addListener((observable, oldvalue, newvalue) -> {
if (newvalue) repaintImages();
});
}
private void repaintImages() {
Object obj = new Object();
synchronized (obj) {
jLabel.repaint();
jLabel.revalidate();
obj.notify();
}
try {
obj.wait();
} catch (Exception e) {
}
}
The code before runs repaintImages() after the windows is focused. I used synchronized with the idea to be ensured the code is executed in thread-safe (independently of lag), Anyway that doesn't fix the problem (images are missing yet). After that, I change this the code to use runLater():
public void init() {
...
stage.focusedProperty().addListener((observable, oldvalue, newvalue) -> {
if (newvalue) Platform.runLater(()->{repaintImages();});
});
}
private void repaintImages() {
Platform.runLater(() -> {
jLabel.repaint();
jLabel.revalidate();
});
}
And it doesn't work either. Please, any suggestion is welcome.
I know, I wrote a long question, but maybe a suggestion could be to move the window when it is focused. In that case, please give the correct way to do this because I tried and not worked too (using synchronized and runLater()). This is the piece of code I used to move the window (placing this into a synchronized block or in the lambda function in runLater()):
Translate elements = null;
if (positive_flag) {
elements = new Translate(1, 0, 0);
positive_flag = false;
} else {
elements = new Translate(-1, 0, 0);
positive_flag = true;
}
anchorPane.getTransforms().addAll(elements);
Finally, consider that to prove if any solution works, I need to wait even up 1h.
I'm new to vaadin and I'm a bit confused with the save and cancel button when setEditorEnabled = true.
Do you need to provide additional codes in order to save the data or it automatically saves all the data to the database when you click on save?
If there are aditional codes, how do I add a listener to the save and cancel buttons?
Thanks!
If you use buffered mode, the edited values are written to the source object when you press the Save button. If you use unbuffered mode, the edition is written instantly, so the Save and Cancel button becomes meaningless.
If you want to write the edited object back to a database, you will need to add that functionality manually. It is practical to use buffered mode in this case and add the database calling method to a method that is called when the save button is pressed.
Besides adding it to a CommitHandler's postCommit method, like Daniel Dubec writes, you can also override the saveEditor() and doCancelEditor() methods of the Grid.
class MyGrid extends Grid {
public MyGrid() {
setEditorEnabled(true);
setEditorBuffered(true);
}
#Override
public void saveEditor() throws CommitException {
super.saveEditor();
// You can persist your data here.
Notification.show("Item " + getEditedItemId() + " was edited.");
}
// Be aware that doCancelEditor() is called whenever super.saveEditor() is called!
#Override
protected void doCancelEditor() {
super.doCancelEditor();
// editedItemId was already set to 'null'.
Notification.show("Cancel button was pressed");
}
}
What super.saveEditor() does is actually calling the commit() method on the editorFieldGroup. But this is only meaningful, if the editable grid is in buffered mode. Read more on Field Buffering here.
So what happens is, when you press the save button, and super.saveEditor() is called, then first the pre-commit event is fired, then the the changes in the editor field values are updated to the data source (that is the commit itself), then the post-commit event is fired. The doCancelEditor() method is called whenever the editor itself is closed, this is why it is called after a save too.
Or use saveListener. I am not sure if this is the best way, but it works for me.
Grid<Bean> grid;
grid.getEditor().addSaveListener(new EditorSaveListener<Bean>() {
#Override
public void onEditorSave(EditorSaveEvent<Bean> event) {
// You can persist your data here
persistBean(event.getBean());
}
});
try to add CommitHandler for FieldGroup
grid.setEditorEnabled(true);
// register save listener
grid.getEditorFieldGroup().addCommitHandler(new CommitHandler() {
#Override
public void preCommit(CommitEvent commitEvent) throws CommitException {
}
#Override
public void postCommit(CommitEvent commitEvent) throws CommitException {
// You can persist your data here
Notification.show("Item " + grid.getEditedItemId() + " was edited.");
}
});
For school, I'm attempting to recreate Microsoft's Notepad program using Java's Swing. I'm working on the saving and opening of .txt files, and I'm trying to figure out a way for the program to detect when a change has been made to the document. If a change has been detected and the user chooses to open or create a new file, I want the program to prompt the user if they would like to save their changes before continuing.
My thought for this was to create a flag, called documentChanged, that would initially be false, and which would be set to true whenever a change was made to the JTextArea. To detect this change, I thought of using a TextListener as follows:
public class JNotepad implements ActionListener
{
boolean documentChanged;
JTextArea notepad;
JNotepad()
{
documentChanged = false;
notepad = new JTextArea();
notepad.addTextListener(new TextListener() {
public void textValueChanged(TextEvent te) {
documentChanged = true;
}
});
}
}
However, I learned that Java classes are unable to implement multiple interfaces at once, and I'm already using ActionListeners to implement the items of my notepad's menu bar.
My question is, is there any way to use both TextListener and ActionListener (or any other listener) simultaneously in the same class? If not, what would be my best plan of action for detecting a change in the document?
It was answer in another post. See Text Changed event in JTextArea? How to?
And also see How to Write a Document Listener (DocumentListener) in Oracle, you will see an applet example.
How does your this even compile
notepad = new JTextArea();
notepad.addTextListener(new TextListener() {
// ....
}
since TextListeners are not defined to work with JTextAreas but rather with TextAreas, a completely different beast.
You should add a DocumentListener to your JTextArea's Document.
notepad.getDocument().addDocumentListener(new DocumentListener() {
void insertUpdate(DocumentEvent e) {
documentChanged = true;
}
void removeUpdate(DocumentEvent e) {
documentChanged = true;
}
void changedUpdate(DocumentEvent e) {
documentChanged = true;
}
});
Regarding
My question is, is there any way to use both TextListeners and ActionListeners (or any other listener) simultaneously in the same class?
Use of a DocumentListener has nothing to do with ActionListeners used elsewhere in your program since their domains are orthogonal to each other, i.e., the one has absolutely nothing to do with the other.
I need to do something when an editor for a particular document is closed. I have a following code:
FileObject fobj = FileUtil.toFileObject(file);
final DataObject dobj = DataObject.find(fobj);
if (dobj != null) {
EditorCookie ec = dobj.getLookup().lookup(EditorCookie.class);
StyledDocument doc = ec.openDocument();
// Here I would like to add a listener for close event, for the editor window that was opened
}
Is there a way of doing this? Or can I at least hook a listener for global editor closing, so that I get notified of each editor window being closed? I guess in that case I would be somehow able to decide whether the given editor window is the one I am interested in.
OK, I found a working solution, however, it still feels like an ugly workaround. I do not understand why all solutions to my problems with NetBeans IDE look so ugly. I can see that the platform aims to prepare a nice space for creating new editors and other pluggable components, however, when one wants just to listen to existing components (Editors, etc.), it becomes a nightmare.
In my current solution I add a property change listener to TopComponent Registry and listen for a "tcClosed" property to change, and then I test whether it has an EditorCookie (so whether it is an editor) and whether the cookie is the same one that I want to listen to:
TopComponent.getRegistry().addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("tcClosed") && evt.getOldValue() == null) {
EditorCookie cookie = ((TopComponent) evt.getNewValue()).getLookup().lookup(EditorCookie.class);
// I have to remember editor cookie to compare it to the one that is closed
// so that I can find out whether it is the editor I want to listen to
if (cookie != null && cookie.equals(ParentClass.this.getRememberedEditorCookie())) {
// Do my stuff
}
}
}
});
However, if anyone knows a better solution, I will be happy to hear about it.
By accident I stumbled about something which may help you:
EditorCookie.Observable cookie = dataObject.getLookup().lookup(EditorCookie.Observable.class);
cookie.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// Do your stuff
}
});
I have a seemingly simple problem. I am working with imagebuttons inside a linearlayout which is inside a scrollview. I have set an onClickListener for one of the buttons which switches the color to red then transparent and then back again. I have tried calling performClick() and manually coding a routine to fire when a condition is met. The problem I am having is no matter how I try to do this the method(s) that are calling .setBackgroundColor() are all exiting when it's called. I don't even get to see a return statement in my Log. here is the code. I am sure this is a simple fix but I am not familiar very familiar with these things. Also I am not using any XML and would like to avoid it if possible so please keep that in mind when posting suggestions. Thanks in advance!
I will try to clarify what I am trying to accomplish. I am attempting to emulate the events that are fired during a click event WITHOUT a click event happening. I have tried this with performClick() and in the way I have here. In both cases I have the call to .setBackgroundColor() not firing and prematurely exiting the method that is calling it and it is called in.
After messing around a bit I found that the method will fire the setBackgroundColor() AND continue the method when I use Color.RED when it is already the color red. If I try any other colors it doesn't work. So it appears to not want to change the color in this fashion. Any ideas anyone?
here is the handler:
IBFireBall.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "in onClick");
if (Fireball.activated) {
Fireball.activated = false;
AbilityWidget.IBFireBall.setBackgroundColor(0);
Log.d(TAG, "was activated");
} else {
Level.fireBall = new Fireball(context);
Fireball.activated = true;
AbilityWidget.IBFireBall.setBackgroundColor(Color.RED);
Log.d(TAG, "wasn't activated");
}
}
});
here is the other method Log only prints out 1 and 2:
public static void resetButton(String id) {
if (id.equals("Fireball")) {
if (Fireball.activated) {
Log.d(TAG,"inside resetbutton 1");
Fireball.activated = false;
Log.d(TAG,"inside resetbutton2" );
AbilityWidget.IBFireBall.setBackgroundColor(0);
Log.d(TAG,"inside resetbutton4" );
} else {
Level.fireBall = new Fireball(context);
Fireball.activated = true;
AbilityWidget.IBFireBall.setBackgroundColor(Color.RED);
Log.d(TAG, "wasn't activated");
}
}
}
1. First never use "=="`` to compare Objects, use.equals()`.
2. You are Not calling the resetButton() method from the onClick(), how will this method be invoked, if its not called.
It appears that the problem lies in threading. You can't update UI outside UI thread. Case closed :) I'll link some documentation on subject later.