JavaFX Scene Builder integration

This commit is contained in:
Alexander Lobas
2014-01-31 23:22:30 +04:00
parent 86bb6f407c
commit 32b9577e20
10 changed files with 87 additions and 23 deletions
Binary file not shown.
@@ -7,6 +7,8 @@ import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelC
import com.oracle.javafx.scenebuilder.kit.editor.panel.library.LibraryPanelController;
import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
@@ -21,13 +23,14 @@ import java.net.URL;
*/
public class SceneBuilderImpl implements SceneBuilder {
private final URL myFileURL;
private final ErrorHandler myErrorHandler;
private final EditorCallback myEditorCallback;
private final JFXPanel myPanel = new JFXPanel();
private EditorController myEditorController;
private ChangeListener<Number> myListener;
public SceneBuilderImpl(URL url, ErrorHandler errorHandler) {
public SceneBuilderImpl(URL url, EditorCallback editorCallback) {
myFileURL = url;
myErrorHandler = errorHandler;
myEditorCallback = editorCallback;
Platform.runLater(new Runnable() {
@Override
@@ -45,6 +48,7 @@ public class SceneBuilderImpl implements SceneBuilder {
LibraryPanelController palette = new LibraryPanelController(myEditorController);
loadFile();
startChangeListener();
SplitPane leftPane = new SplitPane();
leftPane.setOrientation(Orientation.VERTICAL);
@@ -73,19 +77,38 @@ public class SceneBuilderImpl implements SceneBuilder {
Platform.runLater(new Runnable() {
@Override
public void run() {
create();
// TODO: restore state
loadFile();
}
});
}
}
private void startChangeListener() {
myListener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
myEditorCallback.saveChanges(myEditorController.getFxmlText());
}
};
myEditorController.getJobManager().revisionProperty().addListener(myListener);
}
@Override
public void close() {
if (myEditorController != null) {
myEditorController.getJobManager().revisionProperty().removeListener(myListener);
}
}
private void loadFile() {
try {
String fxmlText = FXOMDocument.readContentFromURL(myFileURL);
myEditorController.setFxmlTextAndLocation(fxmlText, myFileURL);
}
catch (Throwable e) {
myErrorHandler.handle(e);
myEditorCallback.handleError(e);
}
}
}
@@ -14,7 +14,7 @@ import java.util.HashSet;
* @author Alexander Lobas
*/
public class SceneBuilderKitWrapper {
public static SceneBuilder create(URL url, ErrorHandler errorHandler) throws Exception {
public static SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
// JavaFX -> Swing drag&drop fix
Field identifier = DataFormat.class.getDeclaredField("identifier");
identifier.setAccessible(true);
@@ -24,6 +24,6 @@ public class SceneBuilderKitWrapper {
// JavaFX class loading fix
FXMLLoader.setDefaultClassLoader(SceneBuilderKitWrapper.class.getClassLoader());
return new SceneBuilderImpl(url, errorHandler);
return new SceneBuilderImpl(url, editorCallback);
}
}
@@ -0,0 +1,10 @@
package org.jetbrains.plugins.javaFX.sceneBuilder;
/**
* @author Alexander Lobas
*/
public interface EditorCallback {
void saveChanges(String content);
void handleError(Throwable e);
}
@@ -1,8 +0,0 @@
package org.jetbrains.plugins.javaFX.sceneBuilder;
/**
* @author Alexander Lobas
*/
public interface ErrorHandler {
void handle(Throwable e);
}
@@ -18,7 +18,7 @@ public class ErrorSceneBuilderCreator implements SceneBuilderCreator {
}
@Override
public SceneBuilder create(URL url, ErrorHandler errorHandler) throws Exception {
public SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
throw new UnsupportedOperationException();
}
}
@@ -9,4 +9,6 @@ public interface SceneBuilder {
JComponent getPanel();
void reloadFile();
void close();
}
@@ -8,5 +8,5 @@ import java.net.URL;
public interface SceneBuilderCreator {
State getState();
SceneBuilder create(URL url, ErrorHandler errorHandler) throws Exception;
SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception;
}
@@ -30,9 +30,9 @@ public class SceneBuilderCreatorImpl implements SceneBuilderCreator {
}
@Override
public SceneBuilder create(URL url, ErrorHandler errorHandler) throws Exception {
public SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
Class<?> wrapperClass = Class.forName("org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderKitWrapper", false, myClassLoader);
return (SceneBuilder)wrapperClass.getMethod("create", URL.class, ErrorHandler.class).invoke(null, url, errorHandler);
return (SceneBuilder)wrapperClass.getMethod("create", URL.class, EditorCallback.class).invoke(null, url, editorCallback);
}
@Override
@@ -2,6 +2,8 @@ package org.jetbrains.plugins.javaFX.sceneBuilder;
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
@@ -27,7 +29,7 @@ import java.net.URL;
/**
* @author Alexander Lobas
*/
public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor, ErrorHandler {
public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor, EditorCallback {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderEditor");
private final static String SCENE_CARD = "scene_builder";
@@ -43,6 +45,7 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false));
private final HyperlinkLabel myErrorLabel = new HyperlinkLabel();
private final Document myDocument;
private final ExternalChangeListener myChangeListener;
private SceneBuilderCreator myBuilderCreator;
@@ -54,6 +57,7 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
myFile = file;
myCreatorProvider = creatorProvider;
myDocument = FileDocumentManager.getInstance().getDocument(file);
myChangeListener = new ExternalChangeListener();
createErrorPage();
@@ -101,7 +105,37 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
@Override
public void handle(Throwable e) {
public void saveChanges(final String content) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
if (mySceneBuilder != null) {
try {
myChangeListener.setRunState(false);
// XXX: strange behavior with undo/redo
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
myDocument.setText(content);
}
}, "JavaFX Scene Builder edit operation", null);
}
});
}
finally {
myChangeListener.setRunState(true);
}
}
}
});
}
@Override
public void handleError(Throwable e) {
showErrorPage(null, e);
}
@@ -163,6 +197,7 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
if (mySceneBuilder != null) {
myPanel.remove(mySceneBuilder.getPanel());
mySceneBuilder.close();
mySceneBuilder = null;
}
}
@@ -248,12 +283,10 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
private class ExternalChangeListener extends DocumentAdapter {
private final Document myDocument;
private volatile boolean myRunState;
private String myContent;
public ExternalChangeListener() {
myDocument = FileDocumentManager.getInstance().getDocument(myFile);
myDocument.addDocumentListener(this);
}
@@ -271,6 +304,10 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
}
public void setRunState(boolean state) {
myRunState = state;
}
public void dispose() {
myDocument.removeDocumentListener(this);
}