diff options
Diffstat (limited to 'bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx')
4 files changed, 155 insertions, 95 deletions
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/DefaultUndoManager.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/DefaultUndoManager.java index bf0302ee4..a5786c1e6 100644 --- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/DefaultUndoManager.java +++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/DefaultUndoManager.java @@ -62,64 +62,67 @@ public class DefaultUndoManager implements IUndoManager { } }; - private IDocumentUndoListener fDocumentUndoListener = new IDocumentUndoListener() { - - @Override - public void documentUndoNotification(DocumentUndoEvent event ){ - if (!isConnected()) return; - - int eventType= event.getEventType(); - if (((eventType & DocumentUndoEvent.ABOUT_TO_UNDO) != 0) || ((eventType & DocumentUndoEvent.ABOUT_TO_REDO) != 0)) { - if (event.isCompound()) { -// ITextViewerExtension extension= null; -// if (fTextViewer instanceof ITextViewerExtension) -// extension= (ITextViewerExtension) fTextViewer; -// -// if (extension != null) -// extension.setRedraw(false); - } - // TODO turn of auto edit strategies -// fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { -// @Override -// public void run() { -// if (fTextViewer instanceof TextViewer) -// ((TextViewer)fTextViewer).ignoreAutoEditStrategies(true); -// } -// }); - - } else if (((eventType & DocumentUndoEvent.UNDONE) != 0) || ((eventType & DocumentUndoEvent.REDONE) != 0)) { - // TODO turn on auto edit strategies -// fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { -// @Override -// public void run() { -// if (fTextViewer instanceof TextViewer) -// ((TextViewer)fTextViewer).ignoreAutoEditStrategies(false); -// } -// }); - if (event.isCompound()) { -// ITextViewerExtension extension= null; -// if (fTextViewer instanceof ITextViewerExtension) -// extension= (ITextViewerExtension) fTextViewer; -// -// if (extension != null) -// extension.setRedraw(true); - } - - // Reveal the change if this manager's viewer has the focus. - if (fTextViewer != null) { - StyledTextArea widget= fTextViewer.getTextWidget(); - // TODO select? -// if (widget != null && !widget.isDisposed() && (widget.isFocusControl()))// || fTextViewer.getTextWidget() == control)) - if( (eventType & DocumentUndoEvent.UNDONE) != 0 ) { - reveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); - } else { - selectAndReveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); + + private IDocumentUndoListener fDocumentUndoListener = createUndoListener(); + private IDocumentUndoListener createUndoListener() { + return new IDocumentUndoListener() { + @Override + public void documentUndoNotification(DocumentUndoEvent event ){ + if (!isConnected()) return; + + int eventType= event.getEventType(); + if (((eventType & DocumentUndoEvent.ABOUT_TO_UNDO) != 0) || ((eventType & DocumentUndoEvent.ABOUT_TO_REDO) != 0)) { + if (event.isCompound()) { + // ITextViewerExtension extension= null; + // if (fTextViewer instanceof ITextViewerExtension) + // extension= (ITextViewerExtension) fTextViewer; + // + // if (extension != null) + // extension.setRedraw(false); + } + // TODO turn of auto edit strategies + // fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { + // @Override + // public void run() { + // if (fTextViewer instanceof TextViewer) + // ((TextViewer)fTextViewer).ignoreAutoEditStrategies(true); + // } + // }); + + } else if (((eventType & DocumentUndoEvent.UNDONE) != 0) || ((eventType & DocumentUndoEvent.REDONE) != 0)) { + // TODO turn on auto edit strategies + // fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { + // @Override + // public void run() { + // if (fTextViewer instanceof TextViewer) + // ((TextViewer)fTextViewer).ignoreAutoEditStrategies(false); + // } + // }); + if (event.isCompound()) { + // ITextViewerExtension extension= null; + // if (fTextViewer instanceof ITextViewerExtension) + // extension= (ITextViewerExtension) fTextViewer; + // + // if (extension != null) + // extension.setRedraw(true); + } + + // Reveal the change if this manager's viewer has the focus. + if (fTextViewer != null) { + StyledTextArea widget= fTextViewer.getTextWidget(); + // TODO select? + // if (widget != null && !widget.isDisposed() && (widget.isFocusControl()))// || fTextViewer.getTextWidget() == control)) + if( (eventType & DocumentUndoEvent.UNDONE) != 0 ) { + reveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); + } else { + selectAndReveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); + } } } } - } - - }; + + }; + } /** * Selects and reveals the specified range. @@ -157,12 +160,16 @@ public class DefaultUndoManager implements IUndoManager { fDocumentUndoManager= DocumentUndoManagerRegistry.getDocumentUndoManager(fDocument); fDocumentUndoManager.connect(this); setMaximalUndoLevel(fUndoLevel); + if (fDocumentUndoListener == null) { + fDocumentUndoListener = createUndoListener(); + } fDocumentUndoManager.addDocumentUndoListener(fDocumentUndoListener); } } private void disconnectDocumentUndoManager() { if (fDocumentUndoManager != null) { + DocumentUndoManagerRegistry.disconnect(fDocument); fDocumentUndoManager.disconnect(this); fDocumentUndoManager.removeDocumentUndoListener(fDocumentUndoListener); fDocumentUndoListener= null; diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewer.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewer.java index 311e6f668..77420f690 100644 --- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewer.java +++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewer.java @@ -121,6 +121,12 @@ public class TextViewer extends AnchorPane implements ITextViewer, ITextViewerEx initActionMapping(); } + + public void dispose() { + if (this.fUndoManager != null) { + this.fUndoManager.disconnect(); + } + } protected TriggerActionMapping getActionMapping() { return actionMapping; diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewerHoverManager.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewerHoverManager.java index 7c87a45b9..84fce4444 100644 --- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewerHoverManager.java +++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewerHoverManager.java @@ -28,6 +28,7 @@ import org.eclipse.fx.ui.controls.styledtext.model.Annotation; import org.eclipse.jface.text.IDocument; import javafx.application.Platform; +import javafx.beans.value.ChangeListener; import javafx.geometry.Bounds; import javafx.geometry.Point2D; import javafx.scene.layout.BorderPane; @@ -44,6 +45,12 @@ public class TextViewerHoverManager { private final PopupWindow popup; private final BorderPane root; + private final ChangeListener<Boolean> windowFocusListener = (x, o, n)-> { + if (!n) { + this.windowPresenter.hide(); + } + }; + public TextViewerHoverManager(TextViewer textViewer) { this.windowPresenter = new DefaultHoverWindowPresenter(textViewer.getTextWidget()); @@ -52,17 +59,19 @@ public class TextViewerHoverManager { this.windowPresenter.setHoverPresenter(this.hoverPresenters); this.textViewer = textViewer; - // TODO FXBindings better observe scene -> window to install this listener - Platform.runLater(()->{ - this.textViewer.getScene().getWindow().focusedProperty().addListener((x, o, n)-> { - if (!n) { - this.windowPresenter.hide(); - } - }); + this.textViewer.sceneProperty().addListener((x, o, n)-> { + if (o != null) { + o.getWindow().focusedProperty().removeListener(windowFocusListener); + } + if (n != null) { + n.getWindow().focusedProperty().addListener(windowFocusListener); + } }); + if (this.textViewer.getScene() != null) { + this.textViewer.getScene().getWindow().focusedProperty().addListener(windowFocusListener); + } - this.popup = new PopupWindow() { - }; + this.popup = new PopupWindow() { }; this.popup.setAutoFix(false); this.popup.setAutoHide(false); this.textViewer.getTextWidget().sceneProperty().addListener( e -> { diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleHtmlViewer.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleHtmlViewer.java index cd0b357fb..80713627a 100644 --- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleHtmlViewer.java +++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleHtmlViewer.java @@ -7,16 +7,14 @@ import java.util.function.Consumer; import org.eclipse.fx.text.hover.HtmlString; import org.eclipse.fx.text.hover.LinkActionEvent; import org.w3c.dom.Document; -import org.w3c.dom.NodeList; -import org.w3c.dom.events.EventListener; -import org.w3c.dom.events.EventTarget; import org.w3c.dom.html.HTMLDocument; -import javafx.beans.binding.ObjectBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; +import javafx.concurrent.Worker.State; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.layout.Background; @@ -25,6 +23,7 @@ import javafx.scene.layout.Region; import javafx.scene.paint.Color; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; +import netscape.javascript.JSObject; @SuppressWarnings("javadoc") public class SimpleHtmlViewer extends BorderPane { @@ -85,6 +84,51 @@ public class SimpleHtmlViewer extends BorderPane { this(false, false); } + public static class WebBridge { + private HtmlString html; + + public WebBridge(HtmlString html) { + this.html = html; + } + + public void onLinkAction(String target, long screenX, long screenY) { + this.html.fireEvent(new LinkActionEvent(LinkActionEvent.LINK_ACTION, target, screenX, screenY)); + } + public void onLinkContext(String target, long screenX, long screenY) { + this.html.fireEvent(new LinkActionEvent(LinkActionEvent.LINK_CONTEXT, target, screenX, screenY)); + } + } + + private class WorkerStateChangeListener implements ChangeListener<Worker.State> { + @Override + public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { + if (newValue == Worker.State.SUCCEEDED) { + + // install WebBridge + JSObject window = (JSObject) webEngine.executeScript("window"); //$NON-NLS-1$ + window.setMember("java", new WebBridge(getContent())); //$NON-NLS-1$ + + // hook all links + webEngine.executeScript( + "var callback = function(e) {" + //$NON-NLS-1$ + " if (e.button == 0) {" + //$NON-NLS-1$ + " java.onLinkAction(e.target.href, e.screenX, e.screenY);" + //$NON-NLS-1$ + " }" + //$NON-NLS-1$ + " else if (e.button == 2) {" + //$NON-NLS-1$ + " java.onLinkContext(e.target.href, e.screenX, e.screenY);" + //$NON-NLS-1$ + " }" + //$NON-NLS-1$ + "};" + //$NON-NLS-1$ + "var allAnchors = document.getElementsByTagName('a');" + //$NON-NLS-1$ + "for (var i = 0; i < allAnchors.length; i++) {" + //$NON-NLS-1$ + " allAnchors[i].onmousedown = callback;" + //$NON-NLS-1$ + "}" //$NON-NLS-1$ + ); + } + } + } + + private WorkerStateChangeListener workerStateChangeListener = new WorkerStateChangeListener(); + // TODO 3.0.0 replace listeners with FXBindings public SimpleHtmlViewer(boolean noPaddingInBody, boolean inline) { this.inline = inline; @@ -109,7 +153,7 @@ public class SimpleHtmlViewer extends BorderPane { setPrefWidth(width + 20); } if (height != null) { - System.err.println("SET PREF HEIGHT " + height); +// System.err.println("SET PREF HEIGHT " + height); setPrefHeight(height + 4); } } @@ -142,29 +186,7 @@ public class SimpleHtmlViewer extends BorderPane { parentProperty().addListener(parentListener); // install the Link Callbacks - EventListener listener = event -> { - HtmlString html = getContent(); - if (html != null) { - if ("mouseup".equals(event.getType())) { //$NON-NLS-1$ - org.w3c.dom.events.MouseEvent ev = (org.w3c.dom.events.MouseEvent)event; - if (ev.getButton() == 0) { - System.err.println(ev.getScreenX() + "/" + ev.getScreenY()); - html.fireEvent(new LinkActionEvent(LinkActionEvent.LINK_ACTION, event.getCurrentTarget().toString(), ev.getScreenX(), ev.getScreenY())); - } - else if (ev.getButton() == 2) { - html.fireEvent(new LinkActionEvent(LinkActionEvent.LINK_CONTEXT, event.getCurrentTarget().toString(), ev.getScreenX(), ev.getScreenY())); - } - } - } - }; - this.webEngine.getLoadWorker().stateProperty().addListener((x, o, n)-> { - if (n == Worker.State.SUCCEEDED) { - NodeList links = this.webEngine.getDocument().getElementsByTagName("a"); //$NON-NLS-1$ - for (int i=0; i < links.getLength(); i++) { - ((EventTarget)links.item(i)).addEventListener("mouseup", listener, false); //$NON-NLS-1$ - } - } - }); + webEngine.getLoadWorker().stateProperty().addListener(workerStateChangeListener); // bind the content contentProperty().addListener((x, o, n) -> { @@ -177,9 +199,25 @@ public class SimpleHtmlViewer extends BorderPane { }); + + sceneProperty().addListener((x, o, n)->{ + if (o != null) { + o.getWindow().setOnHidden(null); + o.getWindow().setOnShown(null); + } + if (n != null) { + n.getWindow().setOnShown(e -> { + // install WebBridge + JSObject window = (JSObject) webEngine.executeScript("window"); //$NON-NLS-1$ + window.setMember("java", new WebBridge(getContent())); //$NON-NLS-1$ + }); + n.getWindow().setOnHidden(e-> { + // uninstall WebBridge + JSObject window = (JSObject) webEngine.executeScript("window"); //$NON-NLS-1$ + window.removeMember("java"); //$NON-NLS-1$ + }); + } + }); } - - - } |