Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Schindl2016-03-10 21:16:21 +0000
committerTom Schindl2016-03-10 21:16:21 +0000
commit56381a61f80547963ca4062df7586b1dc7da9c82 (patch)
treec8abccfd66b38d81aae10a7a4ed5630dce1e235c
parent161e137b03d6fc0fa351e94208528e3cecd65f94 (diff)
parent5ef4a6745e2107eede6e789a625cc108eec53607 (diff)
downloadorg.eclipse.efxclipse-56381a61f80547963ca4062df7586b1dc7da9c82.tar.gz
org.eclipse.efxclipse-56381a61f80547963ca4062df7586b1dc7da9c82.tar.xz
org.eclipse.efxclipse-56381a61f80547963ca4062df7586b1dc7da9c82.zip
Merge branch 'master' of ssh://tschindl@git.eclipse.org:29418/efxclipse/org.eclipse.efxclipse
-rw-r--r--bundles/code/org.eclipse.fx.code.editor.fx.themes/css/dark-highlight.css35
-rw-r--r--bundles/code/org.eclipse.fx.code.editor.fx.themes/css/highlight.css35
-rw-r--r--bundles/code/org.eclipse.fx.code.editor.fx/META-INF/MANIFEST.MF1
-rw-r--r--bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/CompletionProposalPresenter.java4
-rw-r--r--bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/internal/DefaultSourceViewerConfiguration.java26
-rw-r--r--bundles/code/org.eclipse.fx.code.editor/META-INF/MANIFEST.MF1
-rw-r--r--bundles/code/org.eclipse.fx.code.editor/src/org/eclipse/fx/code/editor/services/HoverInformationProvider.java10
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/META-INF/MANIFEST.MF1
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewer.java18
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/TextViewerHoverManager.java152
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentAssistant.java88
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentProposalPopup.java54
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContextInformationPopup.java13
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverPresenter.java16
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverWindowPresenter.java14
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverPresenter.java44
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverWindowPresenter.java134
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/AnnotationModelSupport.java5
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/InvisibleCharSupport.java10
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/LineNumberSupport.java12
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleSmartIndent.java84
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/TextAnnotationPresenterWrapper.java34
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedLineRulerAnnotationPresenter.java9
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedTextAnnotationPresenter.java5
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/ILineRulerAnnotationPresenter.java3
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewer.java38
-rw-r--r--bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewerConfiguration.java14
-rw-r--r--bundles/code/org.eclipse.fx.text/META-INF/MANIFEST.MF3
-rw-r--r--bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/AnnotationHoverProvider.java8
-rw-r--r--bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DefaultHoverInfoType.java14
-rw-r--r--bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DocumentHoverProvider.java9
-rw-r--r--bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfo.java69
-rw-r--r--bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfoType.java5
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/StyledTextArea.java12
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/HoverSupport.java65
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/StyledTextBehavior.java37
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/HoverTarget.java94
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/TextHoverEvent.java75
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/ContentView.java34
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineNode.java82
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineRuler.java14
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/model/Annotation.java1
-rw-r--r--bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/skin/StyledTextSkin.java16
43 files changed, 1261 insertions, 137 deletions
diff --git a/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/dark-highlight.css b/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/dark-highlight.css
index 9ad8aa231..4e0fc4837 100644
--- a/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/dark-highlight.css
+++ b/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/dark-highlight.css
@@ -46,13 +46,46 @@
-fx-stroke: #c7c7c7;
}
+.styled-text-hover .errors {
+ -fx-background-color: darkred;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .warnings {
+ -fx-background-color: darkorange;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .infos {
+ -fx-background-color: blanchediamond;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .docs {
+ -fx-background-color: darkblue;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .others {
+ -fx-background-color: gray;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+
+.styled-text-hover .context-info {
+ -fx-background-color: #393939;
+ -fx-border-color: black;
+ -fx-border-width: thin;
+}
+
.styled-text-hover-text {
-fx-text-fill: #b8c4d1;
}
.styled-text-hover {
- -fx-background-color: #2b5696;
+/* -fx-background-color: #2b5696;
-fx-background-radius: 5;
-fx-padding: 10;
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 10, 0.0 , 0 , 3 );
+*/
} \ No newline at end of file
diff --git a/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/highlight.css b/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/highlight.css
index 05673d98a..b25c6418e 100644
--- a/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/highlight.css
+++ b/bundles/code/org.eclipse.fx.code.editor.fx.themes/css/highlight.css
@@ -23,9 +23,42 @@
-source-editor-markup-extra: rgb(128, 128, 128);
}
+.styled-text-hover .errors {
+ -fx-background-color: red;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .warnings {
+ -fx-background-color: darkorange;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .infos {
+ -fx-background-color: blanchediamond;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .docs {
+ -fx-background-color: aliceblue;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+.styled-text-hover .others {
+ -fx-background-color: gray;
+ -fx-padding: 10;
+ -fx-background-radius: 5;
+}
+
+.styled-text-hover .context-info {
+ -fx-background-color: antiquewhite;
+ -fx-border-color: black;
+ -fx-border-width: thin;
+}
+
.styled-text-hover {
- -fx-background-color: #ecebec;
+/* -fx-background-color: #ecebec;
-fx-background-radius: 5;
-fx-padding: 10;
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 10, 0.0 , 0 , 3 );
+*/
} \ No newline at end of file
diff --git a/bundles/code/org.eclipse.fx.code.editor.fx/META-INF/MANIFEST.MF b/bundles/code/org.eclipse.fx.code.editor.fx/META-INF/MANIFEST.MF
index b5ae15982..ea1facf96 100644
--- a/bundles/code/org.eclipse.fx.code.editor.fx/META-INF/MANIFEST.MF
+++ b/bundles/code/org.eclipse.fx.code.editor.fx/META-INF/MANIFEST.MF
@@ -11,6 +11,7 @@ Import-Package: javax.inject,
org.eclipse.fx.core;version="2.3.0",
org.eclipse.fx.core.di;version="2.3.0",
org.eclipse.fx.core.preferences;version="2.3.0",
+ org.eclipse.fx.text.hover,
org.eclipse.fx.text.rules;version="2.3.0",
org.eclipse.fx.text.ui;version="2.3.0",
org.eclipse.fx.text.ui.contentassist;version="2.3.0",
diff --git a/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/CompletionProposalPresenter.java b/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/CompletionProposalPresenter.java
index 94741605a..aa42c39b0 100644
--- a/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/CompletionProposalPresenter.java
+++ b/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/CompletionProposalPresenter.java
@@ -6,4 +6,8 @@ import org.eclipse.fx.text.ui.contentassist.ICompletionProposal;
@SuppressWarnings("restriction")
public interface CompletionProposalPresenter {
public ICompletionProposal createProposal(CompletionProposal proposal);
+
+ public default String getAutoTriggers() {
+ return "";
+ }
}
diff --git a/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/internal/DefaultSourceViewerConfiguration.java b/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/internal/DefaultSourceViewerConfiguration.java
index 3feefb7c1..51240797f 100644
--- a/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/internal/DefaultSourceViewerConfiguration.java
+++ b/bundles/code/org.eclipse.fx.code.editor.fx/src/org/eclipse/fx/code/editor/fx/services/internal/DefaultSourceViewerConfiguration.java
@@ -17,6 +17,7 @@ import org.eclipse.fx.code.editor.services.HoverInformationProvider;
import org.eclipse.fx.code.editor.services.ProposalComputer;
import org.eclipse.fx.code.editor.services.ProposalComputer.ProposalContext;
import org.eclipse.fx.core.preferences.Preference;
+import org.eclipse.fx.text.hover.HoverInfo;
import org.eclipse.fx.text.ui.Feature;
import org.eclipse.fx.text.ui.ITextHover;
import org.eclipse.fx.text.ui.ITextViewer;
@@ -33,6 +34,7 @@ import org.eclipse.fx.text.ui.source.SourceViewerConfiguration;
import org.eclipse.fx.ui.controls.styledtext.TextSelection;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import javafx.beans.property.SetProperty;
@@ -135,6 +137,25 @@ public class DefaultSourceViewerConfiguration extends SourceViewerConfiguration
}
@Override
+ public Set<HoverInfo> getDocumentHoverInfo(IDocument document, int offset) {
+ if (hoverInformationProvider != null) {
+ return hoverInformationProvider.getDocumentHoverProvider().getHoverInfo(document, offset);
+ }
+ return super.getDocumentHoverInfo(document, offset);
+ }
+
+ @Override
+ public Set<HoverInfo> getAnnotationHoverInfo(Annotation annotation) {
+ if (hoverInformationProvider != null) {
+ return hoverInformationProvider.getAnnotationHoverProviders().stream()
+ .filter(p->p.isApplicable(annotation.getClass()))
+ .map(p->p.getHoverInfo(annotation))
+ .collect(Collectors.toSet());
+ }
+ return super.getAnnotationHoverInfo(annotation);
+ }
+
+ @Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
if( hoverInformationProvider != null ) {
return new ITextHover() {
@@ -213,4 +234,9 @@ public class DefaultSourceViewerConfiguration extends SourceViewerConfiguration
return null;
}
}
+
+ @Override
+ public String getContentAssistAutoTriggers() {
+ return proposalPresenter.getAutoTriggers();
+ }
}
diff --git a/bundles/code/org.eclipse.fx.code.editor/META-INF/MANIFEST.MF b/bundles/code/org.eclipse.fx.code.editor/META-INF/MANIFEST.MF
index e01ccb14d..5ee6d1018 100644
--- a/bundles/code/org.eclipse.fx.code.editor/META-INF/MANIFEST.MF
+++ b/bundles/code/org.eclipse.fx.code.editor/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@ Import-Package: javax.inject,
org.eclipse.fx.core.adapter;version="2.3.0",
org.eclipse.fx.core.event;version="2.3.0",
org.eclipse.fx.core.function;version="2.3.0",
+ org.eclipse.fx.text.hover,
org.eclipse.jface.text.rules,
org.osgi.service.component.annotations;version="1.2.0"
Require-Bundle: org.eclipse.text;bundle-version="3.5.400",
diff --git a/bundles/code/org.eclipse.fx.code.editor/src/org/eclipse/fx/code/editor/services/HoverInformationProvider.java b/bundles/code/org.eclipse.fx.code.editor/src/org/eclipse/fx/code/editor/services/HoverInformationProvider.java
index 87ec6cc8f..a83d35abf 100644
--- a/bundles/code/org.eclipse.fx.code.editor/src/org/eclipse/fx/code/editor/services/HoverInformationProvider.java
+++ b/bundles/code/org.eclipse.fx.code.editor/src/org/eclipse/fx/code/editor/services/HoverInformationProvider.java
@@ -1,8 +1,18 @@
package org.eclipse.fx.code.editor.services;
+import java.util.Set;
+
+import org.eclipse.fx.text.hover.AnnotationHoverProvider;
+import org.eclipse.fx.text.hover.DocumentHoverProvider;
+import org.eclipse.fx.text.hover.HoverInfo;
+import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
public interface HoverInformationProvider {
public CharSequence getHoverInformation(String partitionType, IRegion region);
public IRegion getHoverRegion(String partitionType, int offset);
+
+ DocumentHoverProvider getDocumentHoverProvider();
+ Set<AnnotationHoverProvider> getAnnotationHoverProviders();
+
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/META-INF/MANIFEST.MF b/bundles/code/org.eclipse.fx.text.ui/META-INF/MANIFEST.MF
index 3778e4a18..e4b5b683c 100644
--- a/bundles/code/org.eclipse.fx.text.ui/META-INF/MANIFEST.MF
+++ b/bundles/code/org.eclipse.fx.text.ui/META-INF/MANIFEST.MF
@@ -18,6 +18,7 @@ Export-Package: org.eclipse.fx.text.ui;version="2.3.0";x-internal:=true,
Bundle-Vendor: Eclipse.org
Import-Package: com.google.common.collect;version="15.0.0",
org.eclipse.fx.core;version="2.3.0",
+ org.eclipse.fx.text.hover,
org.eclipse.fx.ui.controls.list;version="2.3.0",
org.eclipse.fx.ui.controls.styledtext;version="2.3.0",
org.eclipse.fx.ui.controls.styledtext.events;version="2.3.0",
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 d3d56b1d0..156eefe85 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
@@ -14,15 +14,18 @@ package org.eclipse.fx.text.ui;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.fx.core.Subscription;
import org.eclipse.fx.core.Util;
+import org.eclipse.fx.text.hover.HoverInfo;
import org.eclipse.fx.text.ui.internal.InvisibleCharSupport;
import org.eclipse.fx.text.ui.internal.LineNumberSupport;
import org.eclipse.fx.ui.controls.styledtext.StyleRange;
@@ -49,6 +52,7 @@ import org.eclipse.jface.text.SlaveDocumentEvent;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.projection.ChildDocument;
import org.eclipse.jface.text.projection.ChildDocumentManager;
+import org.eclipse.jface.text.source.Annotation;
import javafx.beans.property.SetProperty;
import javafx.beans.property.SimpleSetProperty;
@@ -151,6 +155,14 @@ public class TextViewer extends AnchorPane implements ITextViewer, ITextViewerEx
return this.fUndoManager;
}
+ public Set<HoverInfo> getHoverInfo(int offset) {
+ return Collections.emptySet();
+ }
+
+ public Set<HoverInfo> getHoverInfo(Annotation annotation) {
+ return Collections.emptySet();
+ }
+
/**
* Create the text control
*/
@@ -183,7 +195,7 @@ public class TextViewer extends AnchorPane implements ITextViewer, ITextViewerEx
return kc;
}
- private void onVerify(VerifyEvent event) {
+ protected void onVerify(VerifyEvent event) {
// if (event.isControlDown() && getKeyCode(event) == KeyCode.L) {
// if (getFeatures().contains(Feature.SHOW_LINE_NUMBERS)) {
@@ -192,7 +204,7 @@ public class TextViewer extends AnchorPane implements ITextViewer, ITextViewerEx
// else {
// getFeatures().add(Feature.SHOW_LINE_NUMBERS);
// }
-// System.err.println(getFeatures().get());
+// System.err.println("SETTING FEATURES: " + getFeatures().get());
// }
//
// if (event.isControlDown() && getKeyCode(event) == KeyCode.K) {
@@ -202,7 +214,7 @@ public class TextViewer extends AnchorPane implements ITextViewer, ITextViewerEx
// else {
// getFeatures().add(Feature.SHOW_HIDDEN_SYMBOLS);
// }
-// System.err.println(getFeatures().get());
+// System.err.println("SETTING FEATURES: " + getFeatures().get());
// }
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 eb0df6c1c..f89418916 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
@@ -10,20 +10,50 @@
*******************************************************************************/
package org.eclipse.fx.text.ui;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.fx.text.hover.DocumentHoverProvider;
+import org.eclipse.fx.text.hover.HoverInfo;
+import org.eclipse.fx.text.ui.hover.HoverPresenter;
+import org.eclipse.fx.text.ui.hover.HoverWindowPresenter;
+import org.eclipse.fx.text.ui.hover.internal.DefaultHoverPresenter;
+import org.eclipse.fx.text.ui.hover.internal.DefaultHoverWindowPresenter;
import org.eclipse.fx.ui.controls.styledtext.StyledTextArea;
+import org.eclipse.fx.ui.controls.styledtext.events.HoverTarget;
import org.eclipse.fx.ui.controls.styledtext.events.TextHoverEvent;
+import org.eclipse.fx.ui.controls.styledtext.model.Annotation;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.PopupWindow;
public class TextViewerHoverManager {
+
+ List<DocumentHoverProvider> providers = new ArrayList<>();
+
+ DefaultHoverWindowPresenter windowPresenter;
+ List<HoverPresenter> hoverPresenters = new ArrayList<>();
+
private final TextViewer textViewer;
private final PopupWindow popup;
private final BorderPane root;
public TextViewerHoverManager(TextViewer textViewer) {
+
+ this.windowPresenter = new DefaultHoverWindowPresenter(textViewer.getTextWidget());
+ this.hoverPresenters.add(new DefaultHoverPresenter());
+ this.windowPresenter.setHoverPresenter(this.hoverPresenters);
+
this.textViewer = textViewer;
this.popup = new PopupWindow() {
};
@@ -52,31 +82,115 @@ public class TextViewerHoverManager {
return root;
}
+
+
public void install(StyledTextArea styledTextArea) {
styledTextArea.addEventHandler(TextHoverEvent.HOVER, e -> {
+ System.err.println(e.getOffset() + " " + e);
if( e.getOffset() > 0 ) {
- final ITextHover hover= getTextViewer().getTextHover(e.getOffset(), /*getHoverEventStateMask()*/ ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
- if( hover != null ) {
- String text = hover.getHoverInfo(getTextViewer(), hover.getHoverRegion(getTextViewer(), e.getOffset()));
- if( text != null && ! text.isEmpty() ) {
- Label value = new Label(text);
- value.getStyleClass().add("styled-text-hover-text");
- getRoot().setCenter(value);
- Point2D locationAtOffset = getTextViewer().getTextWidget().getLocationAtOffset(e.getOffsetTokenStart());
- double x = e.getScreenX();
- if( locationAtOffset != null ) {
- x = getTextViewer().getTextWidget().localToScreen(locationAtOffset.getX(),0).getX();
- }
- getPopup().show(getTextViewer().getTextWidget().getScene().getWindow(), x, e.getScreenY()+5);
- } else {
- getPopup().hide();
+ final IDocument document = getTextViewer().getDocument();
+ final int offset = e.getOffset();
+
+
+ List<HoverInfo> hovers = new ArrayList<>();
+
+ hovers.addAll(getTextViewer().getHoverInfo(e.getOffset()));
+
+ hovers.addAll(this.providers.stream().flatMap(p->p.getHoverInfo(document, offset).stream()).collect(Collectors.toSet()));
+
+ Set<HoverTarget> annotationTargets = e.getHoverTargets().stream()
+ .filter(t->t.model instanceof Annotation)
+ .collect(Collectors.toSet());
+
+ Set<HoverInfo> annotationHovers = e.getHoverTargets().stream()
+ .filter(t->t.model instanceof Annotation)
+ .map(t->(Annotation) t.model)
+ .filter(a->a.getModel() instanceof org.eclipse.jface.text.source.Annotation)
+ .map(a->(org.eclipse.jface.text.source.Annotation)a.getModel())
+ .flatMap(a->getTextViewer().getHoverInfo(a).stream())
+ .collect(Collectors.toSet());
+
+ System.err.println("AnnotationHovers: " + annotationHovers);
+ hovers.addAll(annotationHovers);
+
+
+
+// if( e.getOffset() > 0 ) {
+// final ITextHover hover= getTextViewer().getTextHover(e.getOffset(), /*getHoverEventStateMask()*/ ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
+// if( hover != null ) {
+// String text = hover.getHoverInfo(getTextViewer(), hover.getHoverRegion(getTextViewer(), e.getOffset()));
+// if( text != null && ! text.isEmpty() ) {
+// Label value = new Label(text);
+// value.getStyleClass().add("styled-text-hover-text");
+// getRoot().setCenter(value);
+// Point2D locationAtOffset = getTextViewer().getTextWidget().getLocationAtOffset(e.getOffsetTokenStart());
+// double x = e.getScreenX();
+// if( locationAtOffset != null ) {
+// x = getTextViewer().getTextWidget().localToScreen(locationAtOffset.getX(),0).getX();
+// }
+// getPopup().show(getTextViewer().getTextWidget().getScene().getWindow(), x, e.getScreenY()+5);
+// } else {
+// getPopup().hide();
+// }
+// } else {
+// getPopup().hide();
+// }
+// } else {
+// getPopup().hide();
+// }
+
+ System.err.println("found hover infos: " + hovers);
+
+
+
+
+ if (!hovers.isEmpty()) {
+ // TODO on multiple hovers we need to determine which screenAnchor to use°!!
+ Point2D anchor = e.getHoverTargets().get(0).screenAnchor;
+ Bounds bounds = e.getHoverTargets().get(0).screenBounds;
+ if (!annotationHovers.isEmpty()) {
+ HoverTarget next = annotationTargets.iterator().next();
+ anchor = next.screenAnchor;
+ bounds = next.screenBounds;
}
- } else {
- getPopup().hide();
+
+ System.err.println("showing @ " + anchor);
+
+
+ this.windowPresenter.show(anchor, bounds, hovers);
+ }
+ else {
+ this.windowPresenter.hide();
}
- } else {
- getPopup().hide();
}
+ else {
+ this.windowPresenter.hide();
+ }
+
+
+// if( e.getOffset() > 0 ) {
+// final ITextHover hover= getTextViewer().getTextHover(e.getOffset(), /*getHoverEventStateMask()*/ ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
+// if( hover != null ) {
+// String text = hover.getHoverInfo(getTextViewer(), hover.getHoverRegion(getTextViewer(), e.getOffset()));
+// if( text != null && ! text.isEmpty() ) {
+// Label value = new Label(text);
+// value.getStyleClass().add("styled-text-hover-text");
+// getRoot().setCenter(value);
+// Point2D locationAtOffset = getTextViewer().getTextWidget().getLocationAtOffset(e.getOffsetTokenStart());
+// double x = e.getScreenX();
+// if( locationAtOffset != null ) {
+// x = getTextViewer().getTextWidget().localToScreen(locationAtOffset.getX(),0).getX();
+// }
+// getPopup().show(getTextViewer().getTextWidget().getScene().getWindow(), x, e.getScreenY()+5);
+// } else {
+// getPopup().hide();
+// }
+// } else {
+// getPopup().hide();
+// }
+// } else {
+// getPopup().hide();
+// }
});
}
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentAssistant.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentAssistant.java
index 046158db3..6c2fdf1c5 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentAssistant.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentAssistant.java
@@ -11,13 +11,19 @@
package org.eclipse.fx.text.ui.contentassist;
import java.util.List;
+import java.util.Optional;
import java.util.function.Function;
-import javafx.geometry.Point2D;
-import javafx.scene.input.KeyCode;
-
import org.eclipse.fx.text.ui.ITextViewer;
+import org.eclipse.fx.ui.controls.styledtext.StyledTextArea.LineLocation;
import org.eclipse.fx.ui.controls.styledtext.VerifyEvent;
+import org.eclipse.jface.text.IDocument;
+
+import javafx.animation.Timeline;
+import javafx.application.Platform;
+import javafx.geometry.Point2D;
+import javafx.scene.input.KeyCode;
+import javafx.util.Duration;
public class ContentAssistant implements IContentAssistant {
private final Function<ContentAssistContextData, List<ICompletionProposal>> proposalComputer;
@@ -25,6 +31,11 @@ public class ContentAssistant implements IContentAssistant {
private ContentProposalPopup fProposalPopup;
private ContextInformationPopup fContextInfoPopup;
+ private String autoTriggers = null;
+ public void setAutoTriggers(String autoTriggers) {
+ this.autoTriggers = autoTriggers;
+ }
+
public ContentAssistant(Function<ContentAssistContextData, List<ICompletionProposal>> proposalComputer) {
this.proposalComputer = proposalComputer;
}
@@ -33,7 +44,8 @@ public class ContentAssistant implements IContentAssistant {
public void install(ITextViewer textViewer) {
if( this.fViewer == null ) {
this.fViewer = textViewer;
- this.fProposalPopup = new ContentProposalPopup(this, textViewer,proposalComputer);
+ this.fProposalPopup = new ContentProposalPopup(this, textViewer, proposalComputer);
+
textViewer.getTextWidget().addEventHandler(VerifyEvent.VERIFY, this::handleVerify);
fContextInfoPopup = new ContextInformationPopup(this, textViewer);
@@ -41,31 +53,67 @@ public class ContentAssistant implements IContentAssistant {
}
private void handleVerify(VerifyEvent event) {
- if( !(event.isControlDown() && event.getCode() == KeyCode.SPACE) ) {
+
+ boolean autoTrigger = !event.getText().isEmpty() && autoTriggers != null && autoTriggers.contains(event.getText());
+ boolean defaultTrigger = event.isControlDown() && event.getCode() == KeyCode.SPACE;
+
+ if( !(autoTrigger || defaultTrigger) ) {
return;
}
- event.consume();
- final int offset = this.fViewer.getTextWidget().getCaretOffset();
+ if (defaultTrigger) {
+ // we cannot consume auto triggers, since they need to be inserted into the document
+ event.consume();
+ }
+
+ // the proposal needs to be delayed until the char was typed
+ Platform.runLater(()-> {
- List<ICompletionProposal> proposals = proposalComputer.apply(new ContentAssistContextData(offset, this.fViewer.getDocument()/*,""*/));
+ final int offset = this.fViewer.getTextWidget().getCaretOffset();
- if( proposals.size() == 1) {
- ICompletionProposal completionProposal = proposals.get(0);
+ System.err.println("caret offset = " + offset);
- completionProposal.apply(this.fViewer.getDocument());
+ List<ICompletionProposal> proposals = proposalComputer.apply(new ContentAssistContextData(offset, this.fViewer.getDocument()/*,""*/));
- showContextInformation(completionProposal.getContextInformation(), offset);
- //this.fViewer.getTextWidget().setSelection(proposals.get(0).getSelection(this.fViewer.getDocument()));
- } else if( ! proposals.isEmpty() ) {
-// System.err.println(this.viewer.getTextWidget().getCaretLocation());
- System.err.println();
- Point2D p = this.fViewer.getTextWidget().getLocationAtOffset(this.fViewer.getTextWidget().getCaretOffset());
- System.err.println(p);
- this.fProposalPopup.displayProposals(proposals, this.fViewer.getTextWidget().getCaretOffset(), this.fViewer.getTextWidget().localToScreen(p));
- }
+ if( proposals.size() == 1) {
+ ICompletionProposal completionProposal = proposals.get(0);
+
+ completionProposal.apply(this.fViewer.getDocument());
+
+ showContextInformation(completionProposal.getContextInformation(), offset);
+
+ //this.fViewer.getTextWidget().setSelection(proposals.get(0).getSelection(this.fViewer.getDocument()));
+ } else if( ! proposals.isEmpty() ) {
+ // System.err.println(this.viewer.getTextWidget().getCaretLocation());
+ System.err.println();
+
+ Point2D p = this.fViewer.getTextWidget().getLocationAtOffset(this.fViewer.getTextWidget().getCaretOffset(), LineLocation.BELOW);
+ System.err.println(p);
+
+ Point2D coords = this.fViewer.getTextWidget().localToScreen(p);
+ System.err.println(coords);
+
+ Optional<ICompletionProposal> chosenProposal = this.fProposalPopup.displayProposals(proposals, this.fViewer.getTextWidget().getCaretOffset(), coords);
+ System.err.println("Chosen: " + chosenProposal.map(c->c.getLabel()));
+
+ chosenProposal.ifPresent(proposal->{
+ IDocument document = this.fViewer.getDocument();
+ // apply the proposal
+ proposal.apply(document);
+ this.setAutoTriggers(autoTriggers);
+ this.fViewer.getTextWidget().setSelection(proposal.getSelection(document));
+
+ if (proposal.getContextInformation() != null) {
+ showContextInformation(proposal.getContextInformation(), fViewer.getTextWidget().getCaretOffset());
+ }
+
+ });
+ }
+
+ fViewer.getTextWidget().layout();
+ });
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentProposalPopup.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentProposalPopup.java
index b2409f4b5..e7c687374 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentProposalPopup.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContentProposalPopup.java
@@ -12,6 +12,8 @@ package org.eclipse.fx.text.ui.contentassist;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.eclipse.fx.text.ui.ITextViewer;
@@ -22,6 +24,8 @@ import org.eclipse.fx.ui.controls.styledtext.TextChangingEvent;
import org.eclipse.fx.ui.controls.styledtext.VerifyEvent;
import org.eclipse.jface.text.IDocument;
+import com.sun.javafx.tk.Toolkit;
+
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
@@ -35,6 +39,7 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.PopupWindow;
+import javafx.stage.Stage;
public class ContentProposalPopup implements IContentAssistListener {
ITextViewer viewer;
@@ -47,7 +52,9 @@ public class ContentProposalPopup implements IContentAssistListener {
private ContentAssistant fContentAssistant;
private ChangeListener<Number> selectionChange;
- private boolean proposalApplyInProgress;
+
+
+ private ICompletionProposal chosenProposal = null;
public ContentProposalPopup(ContentAssistant assistant, ITextViewer viewer, Function<ContentAssistContextData, List<ICompletionProposal>> proposalComputer) {
this.viewer = viewer;
@@ -56,7 +63,8 @@ public class ContentProposalPopup implements IContentAssistListener {
this.selectionChange = this::onSelectionChange;
}
- public void displayProposals(List<ICompletionProposal> proposalList, int offset, Point2D position) {
+ public Optional<ICompletionProposal> displayProposals(List<ICompletionProposal> proposalList, int offset, Point2D position) {
+
setup();
this.prefix = ""; //$NON-NLS-1$
this.offset = offset;
@@ -72,6 +80,17 @@ public class ContentProposalPopup implements IContentAssistListener {
this.stage.setOnHidden(this::unsubscribe);
this.stage.show(this.viewer.getTextWidget().getScene().getWindow());
+
+
+ chosenProposal = null;
+ Toolkit.getToolkit().checkFxUserThread();
+ Toolkit.getToolkit().enterNestedEventLoop(this);
+
+ return Optional.ofNullable(chosenProposal);
+ }
+
+ public void close() {
+ this.stage.hide();
}
private void subscribe(Event e) {
@@ -110,9 +129,6 @@ public class ContentProposalPopup implements IContentAssistListener {
};
private void updateProposals() {
- if( this.proposalApplyInProgress ) {
- return;
- }
List<ICompletionProposal> list = this.proposalComputer.apply(new ContentAssistContextData(this.offset,this.viewer.getDocument()/*,prefix*/));
if( ! list.isEmpty() ) {
this.proposalList.setItems(FXCollections.observableArrayList(list));
@@ -125,25 +141,15 @@ public class ContentProposalPopup implements IContentAssistListener {
}
private void cancelProposal() {
- this.stage.hide();
+ this.chosenProposal = null;
+ close();
}
private void applySelectedProposal() {
- try {
- this.proposalApplyInProgress = true;
- ICompletionProposal selectedItem = this.proposalList.getSelectionModel().getSelectedItem();
- if( selectedItem != null ) {
- IDocument document = this.viewer.getDocument();
- selectedItem.apply(document);
-
- this.viewer.getTextWidget().setSelection(selectedItem.getSelection(document));
- this.stage.hide();
-
- this.fContentAssistant.showContextInformation(selectedItem.getContextInformation(), offset);
- }
- } finally {
- this.proposalApplyInProgress = false;
- }
+ ICompletionProposal selectedItem = this.proposalList.getSelectionModel().getSelectedItem();
+
+ this.chosenProposal = selectedItem;
+ close();
}
private void handleMouseClicked(MouseEvent event) {
@@ -227,6 +233,12 @@ public class ContentProposalPopup implements IContentAssistListener {
this.stage.setOnHidden((o) -> {
this.stage = null;
});
+
+ this.stage.showingProperty().addListener((x, o, n) -> {
+ if (!n) {
+ Toolkit.getToolkit().exitNestedEventLoop(this, null);
+ }
+ });
}
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContextInformationPopup.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContextInformationPopup.java
index 7c9c56143..b3c03786a 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContextInformationPopup.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/contentassist/ContextInformationPopup.java
@@ -16,6 +16,7 @@ import java.util.Stack;
import javax.swing.text.html.HTMLDocument.HTMLReader.HiddenAction;
import org.eclipse.fx.text.ui.ITextViewer;
+import org.eclipse.fx.ui.controls.styledtext.StyledTextArea.LineLocation;
import org.eclipse.fx.ui.controls.styledtext.VerifyEvent;
import javafx.geometry.Point2D;
@@ -124,13 +125,15 @@ class ContextInformationPopup implements IContentAssistListener {
if( viewer.getTextWidget().getScene() != null ) {
fContextInfoPopup.getScene().getStylesheets().setAll(viewer.getTextWidget().getScene().getStylesheets());
}
-
});
+ if( viewer.getTextWidget().getScene() != null ) {
+ fContextInfoPopup.getScene().getStylesheets().setAll(viewer.getTextWidget().getScene().getStylesheets());
+ }
fRoot = new BorderPane();
fRoot.getStyleClass().add("styled-text-hover");
fContent = new Label();
fRoot.setCenter(fContent);
- fContent.getStyleClass().add("styled-text-hover-text");
+ fContent.getStyleClass().add("context-info");
fContextInfoPopup.getScene().setRoot(fRoot);
}
@@ -155,10 +158,12 @@ class ContextInformationPopup implements IContentAssistListener {
public void showContextInformation(final IContextInformation info, final int offset) {
if (info != null && info.getInformationDisplayString() != null && !info.getInformationDisplayString().isEmpty()) {
fContent.setText(info.getInformationDisplayString());
- Point2D locationAtOffset = fViewer.getTextWidget().getLocationAtOffset(offset);
+ Point2D locationAtOffset = fViewer.getTextWidget().getLocationAtOffset(offset, LineLocation.ABOVE);
locationAtOffset = fViewer.getTextWidget().localToScreen(locationAtOffset);
+ System.err.println("CoNTEXT INFO @ " + locationAtOffset);
if (locationAtOffset != null) {
- fContextInfoPopup.show(fViewer.getTextWidget().getScene().getWindow(), locationAtOffset.getX(), locationAtOffset.getY());
+ double y = locationAtOffset.getY() - fContextInfoPopup.getHeight();
+ fContextInfoPopup.show(fViewer.getTextWidget().getScene().getWindow(), locationAtOffset.getX(), y);
}
}
else {
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverPresenter.java
new file mode 100644
index 000000000..0f0d80cc5
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverPresenter.java
@@ -0,0 +1,16 @@
+package org.eclipse.fx.text.ui.hover;
+
+import org.eclipse.fx.text.hover.HoverInfo;
+
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+import javafx.scene.Node;
+
+public interface HoverPresenter {
+
+ int getOrder();
+
+ boolean isApplicable(Class<? extends HoverInfo> hover);
+
+ Node createHoverContent(HoverInfo hover);
+}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverWindowPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverWindowPresenter.java
new file mode 100644
index 000000000..1d4e0e97f
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/HoverWindowPresenter.java
@@ -0,0 +1,14 @@
+package org.eclipse.fx.text.ui.hover;
+
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.fx.text.hover.HoverInfo;
+
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+
+public interface HoverWindowPresenter {
+ void show(Point2D anchor, Bounds bounds, List<HoverInfo> hover);
+ void hide();
+}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverPresenter.java
new file mode 100644
index 000000000..a52d93094
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverPresenter.java
@@ -0,0 +1,44 @@
+package org.eclipse.fx.text.ui.hover.internal;
+
+import org.eclipse.fx.text.hover.DefaultHoverInfoType;
+import org.eclipse.fx.text.hover.HoverInfo;
+import org.eclipse.fx.text.ui.hover.HoverPresenter;
+
+import javafx.geometry.Insets;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.layout.HBox;
+import javafx.scene.paint.Color;
+
+public class DefaultHoverPresenter implements HoverPresenter {
+
+ @Override
+ public int getOrder() {
+ return -1000;
+ }
+
+ @Override
+ public boolean isApplicable(Class<? extends HoverInfo> hover) {
+ return true;
+ }
+
+ @Override
+ public Node createHoverContent(HoverInfo hover) {
+ HBox b = new HBox();
+ b.setSpacing(10);
+
+ Label icon = new Label();
+ icon.setText("*");
+
+ Label content = new Label();
+ content.setText(hover.getHoverText());
+
+ b.getChildren().setAll(icon, content);
+
+ return b;
+ }
+
+}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverWindowPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverWindowPresenter.java
new file mode 100644
index 000000000..a685e01ef
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/hover/internal/DefaultHoverWindowPresenter.java
@@ -0,0 +1,134 @@
+package org.eclipse.fx.text.ui.hover.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.fx.text.hover.DefaultHoverInfoType;
+import org.eclipse.fx.text.hover.HoverInfo;
+import org.eclipse.fx.text.ui.hover.HoverPresenter;
+import org.eclipse.fx.text.ui.hover.HoverWindowPresenter;
+
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+import javafx.scene.control.Control;
+import javafx.scene.layout.VBox;
+import javafx.stage.PopupWindow;
+
+public class DefaultHoverWindowPresenter implements HoverWindowPresenter {
+
+ private List<HoverPresenter> presenters = new ArrayList<>();
+
+ private final Control parent;
+
+ private final PopupWindow popup;
+ private final VBox root;
+
+ private List<HoverInfo> currentVisible;
+
+ public DefaultHoverWindowPresenter(Control parent) {
+ this.parent = parent;
+ this.popup = new PopupWindow() {
+ };
+ this.popup.setAutoFix(false);
+ this.popup.setAutoHide(false);
+ parent.sceneProperty().addListener( e -> {
+ if( parent.getScene() != null ) {
+ popup.getScene().getStylesheets().setAll(parent.getScene().getStylesheets());
+ }
+ else {
+ this.popup.getScene().getStylesheets().clear();
+ }
+ });
+ this.root = new VBox();
+ this.root.setSpacing(3);
+ this.root.getStyleClass().add("styled-text-hover");
+ this.popup.getScene().setRoot(this.root);
+// this.popup.setAnchorLocation(AnchorLocation.CONTENT_BOTTOM_LEFT);
+
+ }
+
+ private Optional<HoverPresenter> findPresenter(HoverInfo hover) {
+ return this.presenters.stream().filter(p->p.isApplicable(hover.getClass()))
+ .sorted((a,b)->a.getOrder()-b.getOrder())
+ .findFirst();
+ }
+
+ private int compare(HoverInfo a, HoverInfo b) {
+ return a.getHoverText().compareTo(b.getHoverText());
+ }
+
+ private void populate(List<HoverInfo> hovers) {
+ if (this.currentVisible != null && this.currentVisible.equals(hovers)) {
+ return;
+ }
+ this.root.getChildren().clear();
+
+ List<HoverInfo> errors = hovers.stream().filter(h->h.getType() == DefaultHoverInfoType.ERROR).sorted(this::compare).collect(Collectors.toList());
+ List<HoverInfo> warnings = hovers.stream().filter(h->h.getType() == DefaultHoverInfoType.WARNING).sorted(this::compare).collect(Collectors.toList());
+ List<HoverInfo> infos = hovers.stream().filter(h->h.getType() == DefaultHoverInfoType.INFO).sorted(this::compare).collect(Collectors.toList());
+ List<HoverInfo> docs = hovers.stream().filter(h->h.getType() == DefaultHoverInfoType.DOCUMENTATION).sorted(this::compare).collect(Collectors.toList());
+ List<HoverInfo> others = hovers.stream().filter(h->!errors.contains(h) && !warnings.contains(h) && !infos.contains(h) && !docs.contains(h)).sorted(this::compare).collect(Collectors.toList());
+
+ if (!errors.isEmpty()) {
+ VBox errorNode = new VBox();
+ errorNode.getStyleClass().add("errors"); //$NON-NLS-1$
+ errorNode.getChildren().addAll(errors.stream().map(e->findPresenter(e).map(p->p.createHoverContent(e))).filter(x->x.isPresent()).map(x->x.get()).collect(Collectors.toList()));
+ this.root.getChildren().add(errorNode);
+ }
+
+ if (!warnings.isEmpty()) {
+ VBox warnNode = new VBox();
+ warnNode.getStyleClass().add("warnings"); //$NON-NLS-1$
+ warnNode.getChildren().addAll(warnings.stream().map(e->findPresenter(e).map(p->p.createHoverContent(e))).filter(x->x.isPresent()).map(x->x.get()).collect(Collectors.toList()));
+ this.root.getChildren().add(warnNode);
+ }
+
+ if (!infos.isEmpty()) {
+ VBox infoNode = new VBox();
+ infoNode.getStyleClass().add("infos"); //$NON-NLS-1$
+ infoNode.getChildren().addAll(infos.stream().map(e->findPresenter(e).map(p->p.createHoverContent(e))).filter(x->x.isPresent()).map(x->x.get()).collect(Collectors.toList()));
+ this.root.getChildren().add(infoNode);
+ }
+
+ if (!docs.isEmpty()) {
+ VBox docsNode = new VBox();
+ docsNode.getStyleClass().add("docs"); //$NON-NLS-1$
+ docsNode.getChildren().addAll(docs.stream().map(e->findPresenter(e).map(p->p.createHoverContent(e))).filter(x->x.isPresent()).map(x->x.get()).collect(Collectors.toList()));
+ this.root.getChildren().add(docsNode);
+ }
+
+ if (!others.isEmpty()) {
+ VBox othersNode = new VBox();
+ othersNode.getStyleClass().add("others"); //$NON-NLS-1$
+ othersNode.getChildren().addAll(others.stream().map(e->
+ findPresenter(e)
+ .map(p->p.createHoverContent(e))
+ )
+ .filter(x->x.isPresent())
+ .map(x->x.get())
+ .collect(Collectors.toList())
+ );
+ this.root.getChildren().add(othersNode);
+ }
+
+
+ this.currentVisible = hovers;
+ }
+
+ @Override
+ public void show(Point2D screenAnchor, Bounds screenBounds, List<HoverInfo> hover) {
+ populate(hover);
+ this.popup.show(this.parent.getScene().getWindow(), screenAnchor.getX(), screenAnchor.getY());
+ }
+
+ @Override
+ public void hide() {
+ this.popup.hide();
+ }
+
+ public void setHoverPresenter(List<HoverPresenter> hoverPresenters) {
+ this.presenters = hoverPresenters;
+ }
+}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/AnnotationModelSupport.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/AnnotationModelSupport.java
index 70767a407..51eaa697a 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/AnnotationModelSupport.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/AnnotationModelSupport.java
@@ -56,6 +56,11 @@ public class AnnotationModelSupport {
}
@Override
+ public Object getModel() {
+ return annotation;
+ }
+
+ @Override
public Range<Integer> getRange() {
return range;
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/InvisibleCharSupport.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/InvisibleCharSupport.java
index 3beab1fd3..0f5d6e6b4 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/InvisibleCharSupport.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/InvisibleCharSupport.java
@@ -41,6 +41,11 @@ public class InvisibleCharSupport implements IFeature {
return symbol;
}
+ @Override
+ public Object getModel() {
+ return symbol;
+ }
+
public InvisibleCharAnnotation(String symbol, Range range) {
this.symbol = symbol;
this.range = range;
@@ -113,6 +118,11 @@ public class InvisibleCharSupport implements IFeature {
t.setText(a.getSymbol());
}
+ @Override
+ public String toString() {
+ return "InvisibleCharAP@" + hashCode(); //$NON-NLS-1$
+ }
+
}
public class InvisibleCharAnnotationProvider implements AnnotationProvider {
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/LineNumberSupport.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/LineNumberSupport.java
index 2a43a3861..10ba6e662 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/LineNumberSupport.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/LineNumberSupport.java
@@ -32,6 +32,12 @@ public class LineNumberSupport implements IFeature {
public int getNr() {
return nr;
}
+
+ @Override
+ public Object getModel() {
+ return nr;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -107,7 +113,10 @@ public class LineNumberSupport implements IFeature {
});
}
-
+ @Override
+ public String toString() {
+ return "LineNrAP@" + hashCode(); //$NON-NLS-1$
+ }
}
@@ -152,4 +161,5 @@ public class LineNumberSupport implements IFeature {
};
}
+
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleSmartIndent.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleSmartIndent.java
new file mode 100644
index 000000000..d3b545ba4
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/SimpleSmartIndent.java
@@ -0,0 +1,84 @@
+package org.eclipse.fx.text.ui.internal;
+
+import org.eclipse.fx.text.ui.TextViewer;
+import org.eclipse.fx.ui.controls.styledtext.ActionEvent;
+import org.eclipse.fx.ui.controls.styledtext.ActionEvent.ActionType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+public class SimpleSmartIndent {
+
+ private TextViewer viewer;
+
+ public SimpleSmartIndent(TextViewer viewer) {
+ this.viewer = viewer;
+ this.viewer.getTextWidget().addEventHandler(ActionEvent.ACTION, this::handle);
+ }
+
+ public void dispose() {
+ this.viewer.getTextWidget().removeEventHandler(ActionEvent.ACTION, this::handle);
+ }
+
+ private int findIndentAt(int index) {
+ String beforeEnter = viewer.getDocument().get().substring(0, index);
+
+ int count = 0;
+ for (int idx = 0; idx < beforeEnter.length(); idx++) {
+ char curChar = beforeEnter.charAt(idx);
+ if (curChar == '{') {
+ count ++;
+ }
+ if (curChar == '}') {
+ count --;
+ }
+ }
+
+ return Math.max(0, count);
+ }
+
+ private void handle(ActionEvent event) {
+
+ if (event.type == ActionType.NEW_LINE) {
+ try {
+ IDocument doc = viewer.getDocument();
+ int caret = viewer.getTextWidget().getCaretOffset();
+
+ int count = findIndentAt(caret);
+
+ int replaceAt = caret;
+ int replaceLen = 0;
+ String replace = "\n";
+ for (int i = 0; i < count; i++) {
+ replace += "\t";
+ }
+
+
+ // endfix
+ int indent = findIndentAt(caret);
+ int lineBegin = doc.getLineInformationOfOffset(caret).getOffset();
+ String before = doc.get().substring(lineBegin, caret);
+ if (before.matches("^\\s*}")) {
+ String tabs = "";
+ for (int i = 0; i < indent; i++) {
+ tabs += "\t";
+ }
+ replaceAt = lineBegin;
+ replaceLen = before.length();
+ replace = tabs + '}' + replace;
+ }
+
+
+ viewer.getDocument().replace(replaceAt, replaceLen, replace);
+ viewer.getTextWidget().setCaretOffset(caret - replaceLen + replace.length());
+ event.consume();
+
+
+ }
+ catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/TextAnnotationPresenterWrapper.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/TextAnnotationPresenterWrapper.java
deleted file mode 100644
index 460bd42ed..000000000
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/TextAnnotationPresenterWrapper.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.eclipse.fx.text.ui.internal;
-
-import org.eclipse.fx.ui.controls.styledtext.model.Annotation;
-import org.eclipse.fx.ui.controls.styledtext.model.TextAnnotationPresenter;
-
-import javafx.scene.Node;
-
-public class TextAnnotationPresenterWrapper implements TextAnnotationPresenter {
-
- @Override
- public boolean isApplicable(Annotation annotation) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public Node createNode() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public boolean isVisible(Annotation annotation) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void updateNode(Node node, Annotation annotation) {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedLineRulerAnnotationPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedLineRulerAnnotationPresenter.java
index 9d57b36a7..4e8cb7a76 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedLineRulerAnnotationPresenter.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedLineRulerAnnotationPresenter.java
@@ -50,11 +50,9 @@ public class WrappedLineRulerAnnotationPresenter implements LineRulerAnnotationP
return wrapped.createNode();
}
- DoubleProperty TODO = new SimpleDoubleProperty(16);
@Override
public DoubleProperty getWidth() {
- // TODO
- return TODO;
+ return this.wrapped.getWidth();
}
@Override
@@ -67,4 +65,9 @@ public class WrappedLineRulerAnnotationPresenter implements LineRulerAnnotationP
wrapped.updateNode(node, unwrap(annotation));
}
+ @Override
+ public String toString() {
+ return "WAP("+wrapped+")@" + hashCode(); //$NON-NLS-2$
+ }
+
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedTextAnnotationPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedTextAnnotationPresenter.java
index 986f89e6e..cb2296053 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedTextAnnotationPresenter.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/internal/WrappedTextAnnotationPresenter.java
@@ -48,4 +48,9 @@ public class WrappedTextAnnotationPresenter implements TextAnnotationPresenter {
wrapped.updateNode(node, unwrap(annotation));
}
+ @Override
+ public String toString() {
+ return "WAP("+wrapped+")@" + hashCode();
+ }
+
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/ILineRulerAnnotationPresenter.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/ILineRulerAnnotationPresenter.java
index f992240b6..3be3fc1aa 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/ILineRulerAnnotationPresenter.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/ILineRulerAnnotationPresenter.java
@@ -4,6 +4,7 @@ import java.util.Set;
import org.eclipse.jface.text.source.Annotation;
+import javafx.beans.property.DoubleProperty;
import javafx.scene.Node;
public interface ILineRulerAnnotationPresenter extends IAnnotationPresenter {
@@ -19,4 +20,6 @@ public interface ILineRulerAnnotationPresenter extends IAnnotationPresenter {
void updateNode(Node node, Set<Annotation> annotation);
LayoutHint getLayoutHint();
+
+ DoubleProperty getWidth();
}
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewer.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewer.java
index cedd32775..38055949e 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewer.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewer.java
@@ -12,15 +12,23 @@
*******************************************************************************/
package org.eclipse.fx.text.ui.source;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.eclipse.fx.text.hover.HoverInfo;
import org.eclipse.fx.text.ui.Feature;
import org.eclipse.fx.text.ui.ITextViewerExtension2;
import org.eclipse.fx.text.ui.TextViewer;
+import org.eclipse.fx.text.ui.contentassist.ContentAssistant;
import org.eclipse.fx.text.ui.contentassist.IContentAssistant;
import org.eclipse.fx.text.ui.internal.AnnotationModelSupport;
+import org.eclipse.fx.text.ui.internal.SimpleSmartIndent;
import org.eclipse.fx.text.ui.internal.WrappedLineRulerAnnotationPresenter;
import org.eclipse.fx.text.ui.internal.WrappedTextAnnotationPresenter;
import org.eclipse.fx.text.ui.presentation.IPresentationReconciler;
import org.eclipse.fx.text.ui.reconciler.IReconciler;
+import org.eclipse.fx.ui.controls.styledtext.VerifyEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ISynchronizable;
@@ -40,6 +48,10 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
private Annotation fRangeIndicator;
+
+ private BiFunction<IDocument, Integer, Set<HoverInfo>> documentHoverInfoLookup = null;
+ private Function<Annotation, Set<HoverInfo>> annotationHoverInfoLookup = null;
+
@Override
public void configure(SourceViewerConfiguration configuration) {
if (getTextWidget() == null)
@@ -55,6 +67,9 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
getTextWidget().getStyleClass().add(configuration.getStyleclassName());
+ this.documentHoverInfoLookup = configuration::getDocumentHoverInfo;
+ this.annotationHoverInfoLookup = configuration::getAnnotationHoverInfo;
+
// if( configuration.getDefaultStylesheet().getValue() != null ) {
// getTextWidget().getStylesheets().add(configuration.getDefaultStylesheet().getValue().toExternalForm());
// }
@@ -68,6 +83,10 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
// }
// });
+ if (configuration.getContentAssist() instanceof ContentAssistant) {
+ ((ContentAssistant)configuration.getContentAssist()).setAutoTriggers(configuration.getContentAssistAutoTriggers());
+ }
+
setDocumentPartitioning(configuration.getConfiguredDocumentPartitioning(this));
// install content type independent plug-ins
@@ -213,6 +232,9 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
// });
}
+
+ new SimpleSmartIndent(this);
+
}
// private Node annotationFactory(StyledTextLine l) {
@@ -234,6 +256,22 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
// return null;
// }
+ @Override
+ public Set<HoverInfo> getHoverInfo(int offset) {
+ if (this.documentHoverInfoLookup != null) {
+ return this.documentHoverInfoLookup.apply(getDocument(), offset);
+ }
+ return super.getHoverInfo(offset);
+ }
+
+ @Override
+ public Set<HoverInfo> getHoverInfo(Annotation annotation) {
+ if (this.annotationHoverInfoLookup != null) {
+ return this.annotationHoverInfoLookup.apply(annotation);
+ }
+ return super.getHoverInfo(annotation);
+ }
+
/**
* Disposes the visual annotation model.
*
diff --git a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewerConfiguration.java b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewerConfiguration.java
index 96ea2f7d1..144414baf 100644
--- a/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewerConfiguration.java
+++ b/bundles/code/org.eclipse.fx.text.ui/src/org/eclipse/fx/text/ui/source/SourceViewerConfiguration.java
@@ -14,6 +14,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
+import org.eclipse.fx.text.hover.HoverInfo;
import org.eclipse.fx.text.ui.DefaultUndoManager;
import org.eclipse.fx.text.ui.Feature;
import org.eclipse.fx.text.ui.ITextHover;
@@ -24,6 +25,7 @@ import org.eclipse.fx.text.ui.presentation.PresentationReconciler;
import org.eclipse.fx.text.ui.reconciler.IReconciler;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import javafx.beans.property.SetProperty;
@@ -73,8 +75,20 @@ public abstract class SourceViewerConfiguration {
return null;
}
+ public Set<HoverInfo> getDocumentHoverInfo(IDocument document, int offset) {
+ return Collections.emptySet();
+ }
+
+ public Set<HoverInfo> getAnnotationHoverInfo(Annotation annotation) {
+ return Collections.emptySet();
+ }
+
public String[] getConfiguredContentTypes(SourceViewer sourceViewer) {
return new String[] { IDocument.DEFAULT_CONTENT_TYPE };
}
+ public String getContentAssistAutoTriggers() {
+ return ".";
+ }
+
}
diff --git a/bundles/code/org.eclipse.fx.text/META-INF/MANIFEST.MF b/bundles/code/org.eclipse.fx.text/META-INF/MANIFEST.MF
index 51021d3a9..1985562d3 100644
--- a/bundles/code/org.eclipse.fx.text/META-INF/MANIFEST.MF
+++ b/bundles/code/org.eclipse.fx.text/META-INF/MANIFEST.MF
@@ -4,7 +4,8 @@ Bundle-Name: Basic Text extension
Bundle-SymbolicName: org.eclipse.fx.text
Bundle-Version: 2.3.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.eclipse.fx.text.rules;version="2.3.0";x-internal:=true
+Export-Package: org.eclipse.fx.text.hover,
+ org.eclipse.fx.text.rules;version="2.3.0";x-internal:=true
Require-Bundle: org.eclipse.text;bundle-version="3.5.300",
org.eclipse.equinox.common;bundle-version="3.6.200"
Bundle-Vendor: Eclipse.org
diff --git a/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/AnnotationHoverProvider.java b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/AnnotationHoverProvider.java
new file mode 100644
index 000000000..6267fb675
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/AnnotationHoverProvider.java
@@ -0,0 +1,8 @@
+package org.eclipse.fx.text.hover;
+
+import org.eclipse.jface.text.source.Annotation;
+
+public interface AnnotationHoverProvider {
+ boolean isApplicable(Class<? extends Annotation> annotationType);
+ HoverInfo getHoverInfo(Annotation annotation);
+}
diff --git a/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DefaultHoverInfoType.java b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DefaultHoverInfoType.java
new file mode 100644
index 000000000..b682f050c
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DefaultHoverInfoType.java
@@ -0,0 +1,14 @@
+package org.eclipse.fx.text.hover;
+
+public enum DefaultHoverInfoType implements HoverInfoType {
+ DOCUMENTATION,
+ ERROR,
+ WARNING,
+ INFO;
+
+ @Override
+ public String getType() {
+ return name();
+ }
+
+}
diff --git a/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DocumentHoverProvider.java b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DocumentHoverProvider.java
new file mode 100644
index 000000000..668adc8a5
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/DocumentHoverProvider.java
@@ -0,0 +1,9 @@
+package org.eclipse.fx.text.hover;
+
+import java.util.Set;
+
+import org.eclipse.jface.text.IDocument;
+
+public interface DocumentHoverProvider {
+ Set<HoverInfo> getHoverInfo(IDocument document, int offset);
+}
diff --git a/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfo.java b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfo.java
new file mode 100644
index 000000000..1caeb9724
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfo.java
@@ -0,0 +1,69 @@
+package org.eclipse.fx.text.hover;
+
+import org.eclipse.jface.text.IRegion;
+
+public class HoverInfo {
+
+ private final HoverInfoType type;
+ private final IRegion region;
+ private final String hoverText;
+ private final Object hoverModel;
+
+ public HoverInfo(HoverInfoType type, IRegion region, String hoverText, Object hoverModel) {
+ this.type = type;
+ this.region = region;
+ this.hoverText = hoverText;
+ this.hoverModel = hoverModel;
+ }
+
+ public HoverInfoType getType() {
+ return type;
+ }
+
+ public IRegion getRegion() {
+ return region;
+ }
+
+ public String getHoverText() {
+ return hoverText;
+ }
+
+ public Object getHoverModel() {
+ return hoverModel;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((hoverText == null) ? 0 : hoverText.hashCode());
+ result = prime * result + ((region == null) ? 0 : region.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ HoverInfo other = (HoverInfo) obj;
+ if (hoverText == null) {
+ if (other.hoverText != null)
+ return false;
+ } else if (!hoverText.equals(other.hoverText))
+ return false;
+ if (region == null) {
+ if (other.region != null)
+ return false;
+ } else if (!region.equals(other.region))
+ return false;
+ return true;
+ }
+
+
+
+
+}
diff --git a/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfoType.java b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfoType.java
new file mode 100644
index 000000000..e0a6b0ca8
--- /dev/null
+++ b/bundles/code/org.eclipse.fx.text/src/org/eclipse/fx/text/hover/HoverInfoType.java
@@ -0,0 +1,5 @@
+package org.eclipse.fx.text.hover;
+
+public interface HoverInfoType {
+ String getType();
+}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/StyledTextArea.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/StyledTextArea.java
index 4aaa496ec..d0133df46 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/StyledTextArea.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/StyledTextArea.java
@@ -1518,18 +1518,26 @@ public class StyledTextArea extends Control {
return this.editableProperty;
}
+ public static enum LineLocation {
+ BELOW,
+ ABOVE,
+ CENTER
+ }
+
/**
* Check the location at the given offset
*
* @param offset
* the offset
+ * @param locationHint
+ * hint for y coordinate relative to line
* @return the point
*/
- public @Nullable Point2D getLocationAtOffset(int offset) {
+ public @Nullable Point2D getLocationAtOffset(int offset, LineLocation locationHint) {
if (offset < 0 || offset > getCharCount()) {
throw new IllegalArgumentException();
}
- return ((StyledTextSkin) getSkin()).getCaretLocation(offset);
+ return ((StyledTextSkin) getSkin()).getCaretLocation(offset, locationHint);
}
/**
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/HoverSupport.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/HoverSupport.java
index 40c470734..367eabcf9 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/HoverSupport.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/HoverSupport.java
@@ -11,10 +11,16 @@
*******************************************************************************/
package org.eclipse.fx.ui.controls.styledtext.behavior;
+import java.util.List;
+
import org.eclipse.fx.ui.controls.Util;
+import org.eclipse.fx.ui.controls.styledtext.events.HoverTarget;
import org.eclipse.fx.ui.controls.styledtext.events.TextHoverEvent;
+import org.eclipse.fx.ui.controls.styledtext.internal.ContentView;
+
import javafx.event.Event;
+import javafx.geometry.Point2D;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.util.Duration;
@@ -27,6 +33,8 @@ public class HoverSupport {
private Region control;
private TextHoverEvent lastHover;
+ private TextHoverEvent curHover;
+
/**
* Create a hover support instance
*
@@ -44,7 +52,7 @@ public class HoverSupport {
this.control.addEventHandler(MouseEvent.MOUSE_PRESSED, this::onMousePressed);
this.control.addEventHandler(MouseEvent.MOUSE_MOVED, this::onMouseMoved);
this.control.addEventHandler(MouseEvent.MOUSE_EXITED, this::onMouseExited);
- Util.installHoverCallback(this.control, Duration.millis(1000), this::handleHover);
+ Util.installHoverCallback(this.control, Duration.millis(300), this::handleHover);
}
/**
@@ -61,26 +69,38 @@ public class HoverSupport {
}
private void onMouseExited(MouseEvent event) {
- if (this.lastHover != null) {
- Event.fireEvent(this.control, new TextHoverEvent(event, -1, -1, -1, "")); //$NON-NLS-1$
- this.lastHover = null;
- }
+ Event.fireEvent(this.control, new TextHoverEvent(event, -1, -1, -1, "")); //$NON-NLS-1$
+ this.lastHover = null;
+ this.curHover = null;
}
private void onMouseMoved(MouseEvent event) {
- if (this.lastHover != null) {
- TextHoverEvent hoverEvent = createHoverEvent(event);
- if (this.lastHover.getOffsetTokenStart() != hoverEvent.getOffsetTokenStart()) {
+// if (this.lastHover != null) {
+// TextHoverEvent hoverEvent = createHoverEvent(event);
+// if (this.lastHover.getOffsetTokenStart() != hoverEvent.getOffsetTokenStart()) {
+// Event.fireEvent(this.control, new TextHoverEvent(event, -1, -1, -1, "")); //$NON-NLS-1$
+// this.lastHover = null;
+// }
+// }
+
+ if (this.curHover != null) {
+ List<HoverTarget> hoverTargets = ((ContentView)this.control).findHoverTargets(new Point2D(event.getX(), event.getY()));
+ TextHoverEvent e = new TextHoverEvent(event, hoverTargets);
+ if (!e.equals(curHover)) {
Event.fireEvent(this.control, new TextHoverEvent(event, -1, -1, -1, "")); //$NON-NLS-1$
- this.lastHover = null;
+ this.curHover = null;
}
}
+
+
+
}
private void onMousePressed(MouseEvent event) {
if (this.lastHover != null) {
Event.fireEvent(this.control, new TextHoverEvent(event, -1, -1, -1, "")); //$NON-NLS-1$
this.lastHover = null;
+ curHover = null;
}
}
@@ -121,15 +141,24 @@ public class HoverSupport {
* Create a hover even from the hover mouse event
* @param e the event
*/
- protected void handleHover(MouseEvent e) {
- TextHoverEvent event = createHoverEvent(e);
- if (this.lastHover == null || this.lastHover.getOffsetTokenStart() != event.getOffsetTokenStart()) {
- Event.fireEvent(this.control, event);
- if (event.getOffset() == -1) {
- this.lastHover = null;
- } else {
- this.lastHover = event;
- }
+ protected void handleHover(MouseEvent event) {
+// TextHoverEvent event = createHoverEvent(e);
+// if (this.lastHover == null || this.lastHover.getOffsetTokenStart() != event.getOffsetTokenStart()) {
+// Event.fireEvent(this.control, event);
+// if (event.getOffset() == -1) {
+// this.lastHover = null;
+// } else {
+// this.lastHover = event;
+// }
+// }
+
+
+ List<HoverTarget> hoverTargets = ((ContentView)this.control).findHoverTargets(new Point2D(event.getX(), event.getY()));
+ TextHoverEvent e = new TextHoverEvent(event, hoverTargets);
+ if (this.curHover == null || !e.equals(curHover)) {
+ System.err.println("FIRING HOVER");
+ Event.fireEvent(this.control, e);
+ curHover = e;
}
}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/StyledTextBehavior.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/StyledTextBehavior.java
index 9bfa11465..2f25be6c5 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/StyledTextBehavior.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/behavior/StyledTextBehavior.java
@@ -997,6 +997,41 @@ public class StyledTextBehavior {
moveCaretRelative(-1, select);
}
+ protected final StyledTextInputAction ACTION_NAVIGATE_TO_LINE = new StyledTextInputAction(this::defaultNavigateToLine);
+ protected void defaultNavigateToLine() {
+ try {
+
+// s-> {
+// try {
+// int num = Integer.parseInt(s);
+// int lineCount = getControl().getContent().getLineCount();
+// if (num < 0 || num >= lineCount) {
+// return Optional.of("Must be between 0 and " + lineCount);
+// }
+// }
+// catch (NumberFormatException e) {
+// return Optional.of(e.getMessage());
+// }
+// return Optional.empty();
+// }
+
+ Optional<Integer> num = ((StyledTextSkin)getControl().getSkin()).fastQuery("Goto Line", "Line Number", Integer::parseInt);
+ num.ifPresent((n)->defaultNavigateToLine(n-1));
+
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void defaultNavigateToLine(int lineIndex) {
+ if (lineIndex >= 0 && lineIndex <= getControl().getContent().getLineCount()) {
+ int offset = getControl().getContent().getOffsetAtLine(lineIndex);
+ getControl().setCaretOffset(offset);
+ }
+ }
+
+
/**
* Action to move caret right
*/
@@ -1425,6 +1460,8 @@ public class StyledTextBehavior {
// action for insert tab support
keyMapping.mapKey(new KeyCombo(TAB), () -> getControl().insert("\t")); //$NON-NLS-1$
+
+ keyMapping.mapKey(new KeyCombo(KeyCode.L, ControlKey), this.ACTION_NAVIGATE_TO_LINE);
}
// /**
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/HoverTarget.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/HoverTarget.java
new file mode 100644
index 000000000..87787ee4a
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/HoverTarget.java
@@ -0,0 +1,94 @@
+package org.eclipse.fx.ui.controls.styledtext.events;
+
+import com.google.common.collect.Range;
+
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+
+public class HoverTarget {
+
+ /**
+ * lower left point of the first letter
+ */
+ public final Point2D screenAnchor;
+
+
+ /**
+ * the associated model element.
+ */
+ public final Object model;
+
+ /**
+ * the range in the text
+ */
+ public final Range<Integer> textRange;
+
+ /**
+ * bounds of text in screen coordinates.
+ * <p>
+ * if the text spans over multiple lines, this is <code>null</code>
+ * </p>
+ *
+ */
+ public final Bounds screenBounds;
+
+
+
+ public HoverTarget(Object model, Range<Integer> textRange, Point2D screenAnchor, Bounds screenBounds) {
+ this.screenAnchor = screenAnchor;
+ this.model = model;
+ this.textRange = textRange;
+ this.screenBounds = screenBounds;
+ }
+
+ @Override
+ public String toString() {
+ return "HoverTarget(@"+textRange+", "+model+")";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((model == null) ? 0 : model.hashCode());
+ result = prime * result + ((screenAnchor == null) ? 0 : screenAnchor.hashCode());
+ result = prime * result + ((screenBounds == null) ? 0 : screenBounds.hashCode());
+ result = prime * result + ((textRange == null) ? 0 : textRange.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ HoverTarget other = (HoverTarget) obj;
+ if (model == null) {
+ if (other.model != null)
+ return false;
+ } else if (!model.equals(other.model))
+ return false;
+ if (screenAnchor == null) {
+ if (other.screenAnchor != null)
+ return false;
+ } else if (!screenAnchor.equals(other.screenAnchor))
+ return false;
+ if (screenBounds == null) {
+ if (other.screenBounds != null)
+ return false;
+ } else if (!screenBounds.equals(other.screenBounds))
+ return false;
+ if (textRange == null) {
+ if (other.textRange != null)
+ return false;
+ } else if (!textRange.equals(other.textRange))
+ return false;
+ return true;
+ }
+
+
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/TextHoverEvent.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/TextHoverEvent.java
index 689552f4f..158dcd5c6 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/TextHoverEvent.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/events/TextHoverEvent.java
@@ -10,6 +10,12 @@
*******************************************************************************/
package org.eclipse.fx.ui.controls.styledtext.events;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.collect.Range;
+
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.input.MouseEvent;
@@ -40,6 +46,29 @@ public class TextHoverEvent extends MouseEvent {
private final String tokenText;
private final int offset;
+ private final List<HoverTarget> hoverTargets;
+
+
+
+ public TextHoverEvent(MouseEvent source, List<HoverTarget> hoverTargets) {
+ super(HOVER, source.getSceneX(), source.getSceneY(), source.getScreenX(), source.getScreenY(), source.getButton(), source.getClickCount(), source.isShiftDown(), source.isControlDown(), source.isAltDown(), source.isMetaDown(), source.isPrimaryButtonDown(), source.isMiddleButtonDown(),
+ source.isSecondaryButtonDown(), source.isSynthesized(), source.isPopupTrigger(), source.isStillSincePress(), source.getPickResult());
+
+ this.hoverTargets = Collections.unmodifiableList(hoverTargets);
+
+ Optional<Range<Integer>> range = this.hoverTargets.stream().map(t->t.textRange).findFirst();
+
+ // TODO remove me
+ this.tokenText = null;
+ this.offsetTokenStart = range.isPresent() ? range.get().lowerEndpoint() : 0;;
+ this.offsetTokenEnd = range.isPresent() ? range.get().upperEndpoint() : 0;;
+ this.offset = range.isPresent() ? range.get().lowerEndpoint() : 0;
+ }
+
+ public List<HoverTarget> getHoverTargets() {
+ return this.hoverTargets;
+ }
+
/**
* Create a new hover event from the original mouse event
*
@@ -64,6 +93,8 @@ public class TextHoverEvent extends MouseEvent {
this.offsetTokenEnd = offsetTokenEnd;
this.tokenText = tokenText;
this.offset = offset;
+
+ this.hoverTargets = null;
}
/**
@@ -96,4 +127,48 @@ public class TextHoverEvent extends MouseEvent {
public int getOffset() {
return this.offset;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((hoverTargets == null) ? 0 : hoverTargets.hashCode());
+ result = prime * result + offset;
+ result = prime * result + offsetTokenEnd;
+ result = prime * result + offsetTokenStart;
+ result = prime * result + ((tokenText == null) ? 0 : tokenText.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TextHoverEvent other = (TextHoverEvent) obj;
+ if (hoverTargets == null) {
+ if (other.hoverTargets != null)
+ return false;
+ } else if (!hoverTargets.equals(other.hoverTargets))
+ return false;
+ if (offset != other.offset)
+ return false;
+ if (offsetTokenEnd != other.offsetTokenEnd)
+ return false;
+ if (offsetTokenStart != other.offsetTokenStart)
+ return false;
+ if (tokenText == null) {
+ if (other.tokenText != null)
+ return false;
+ } else if (!tokenText.equals(other.tokenText))
+ return false;
+ return true;
+ }
+
+
+
+
}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/ContentView.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/ContentView.java
index 0c429ec2a..6e6f0eb9e 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/ContentView.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/ContentView.java
@@ -10,20 +10,25 @@
*******************************************************************************/
package org.eclipse.fx.ui.controls.styledtext.internal;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.eclipse.fx.ui.controls.Util;
import org.eclipse.fx.ui.controls.styledtext.StyledTextArea;
+import org.eclipse.fx.ui.controls.styledtext.StyledTextArea.LineLocation;
import org.eclipse.fx.ui.controls.styledtext.StyledTextContent;
import org.eclipse.fx.ui.controls.styledtext.StyledTextContent.TextChangeListener;
+import org.eclipse.fx.ui.controls.styledtext.events.HoverTarget;
import org.eclipse.fx.ui.controls.styledtext.TextChangedEvent;
import org.eclipse.fx.ui.controls.styledtext.TextChangingEvent;
import org.eclipse.fx.ui.controls.styledtext.TextSelection;
@@ -170,6 +175,18 @@ public class ContentView extends Pane {
}
+
+ public List<HoverTarget> findHoverTargets(Point2D localLocation) {
+ ContiguousSet<Integer> visibleIndexes = ContiguousSet.create(ContentView.this.visibleLines.get(), DiscreteDomain.integers());
+ return visibleIndexes.stream()
+ .map(lineIndex->getVisibleNode(lineIndex))
+ .filter(x->x.isPresent())
+ .filter(x->x.get().getBoundsInParent().contains(localLocation))
+ .flatMap(x->x.get().findHoverTargets(x.get().parentToLocal(localLocation)).stream())
+ .collect(Collectors.toList());
+ }
+
+
// protected void permutate(int a, int b) {
// LineNode nodeA = existingNodes.get(a);
// LineNode nodeB = existingNodes.get(b);
@@ -181,6 +198,10 @@ public class ContentView extends Pane {
// }
}
+ public List<HoverTarget> findHoverTargets(Point2D localLocation) {
+ return this.lineLayer.findHoverTargets(localLocation);
+ }
+
private StackPane contentBody = new StackPane();
private LineLayer lineLayer = new LineLayer(()->new LineNode(), (n, m)->{
@@ -812,13 +833,22 @@ public class ContentView extends Pane {
// }
- public Optional<Point2D> getLocationInScene(int globalOffset) {
+ public Optional<Point2D> getLocationInScene(int globalOffset, LineLocation locationHint) {
+ applyCss();
+ layout();
+
int lineIndex = getContent().getLineAtOffset(globalOffset);
Optional<LineNode> node = this.lineLayer.getVisibleNode(lineIndex);
return node.map(n->{
double x = n.getCharLocation(globalOffset - n.getStartOffset());
- Point2D p = new Point2D(x, 0);
+ double y = 0;
+ switch (locationHint) {
+ case BELOW: y = 0; break;
+ case ABOVE: y = -getLineHeight(); break;
+ case CENTER: y = -getLineHeight() / 2.0; break;
+ }
+ Point2D p = new Point2D(x, y);
return n.localToScene(p);
});
}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineNode.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineNode.java
index efe3ab490..11b6830bb 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineNode.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineNode.java
@@ -11,6 +11,8 @@
package org.eclipse.fx.ui.controls.styledtext.internal;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -20,13 +22,17 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
+import org.eclipse.fx.ui.controls.styledtext.events.HoverTarget;
import org.eclipse.fx.ui.controls.styledtext.model.TextAnnotation;
import org.eclipse.fx.ui.controls.styledtext.model.TextAnnotationPresenter;
+import com.google.common.collect.Range;
+
import javafx.animation.Animation;
import javafx.animation.Animation.Status;
import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
+import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Node;
@@ -201,6 +207,40 @@ public class LineNode extends StackPane {
return b.toString();
}
+ private int getStartOffset(Segment segment) {
+ int result = 0;
+ for (Segment s : this.currentContent) {
+ if (s == segment) {
+ break;
+ }
+ result += s.text.length();
+ }
+ return result;
+ }
+
+ private int getLength(Segment segment) {
+ return segment.text.length();
+ }
+
+ public Collection<? extends HoverTarget> findHoverTargets(Point2D localLocation) {
+ for (TextNode t : this.currentTextNodes) {
+ Bounds segmentBounds = t.getBoundsInParent();
+ if (segmentBounds.contains(localLocation)) {
+ Segment segment = this.currentContent.get(currentTextNodes.indexOf(t));
+ Point2D anchor = new Point2D(segmentBounds.getMinX(), segmentBounds.getMaxY());
+
+ int segmentBegin = getStartOffset(segment);
+ int segmentEnd = segmentBegin + getLength(segment);
+ Range<Integer> range = Range.closed(segmentBegin, segmentEnd);
+
+ HoverTarget segmentTarget = new HoverTarget(segment, toGlobal(range), localToScreen(anchor), localToScreen(segmentBounds));
+ return Collections.singletonList(segmentTarget);
+ }
+ }
+
+ return Collections.emptyList();
+ }
+
}
public class SelectionLayer extends Region {
@@ -460,6 +500,22 @@ public class LineNode extends StackPane {
}
}
+ public Collection<? extends HoverTarget> findHoverTargets(Point2D localLocation) {
+ return this.usedNodes.entrySet().stream()
+ .filter(e->e.getValue().getBoundsInParent().contains(localLocation))
+ .map(e->{
+ TextAnnotation annotation = e.getKey();
+
+ Bounds bounds = e.getValue().getBoundsInLocal();
+ Point2D anchor = new Point2D(bounds.getMinX(), bounds.getMaxY());
+
+ HoverTarget annotationTarget = new HoverTarget(annotation, toGlobal(annotation.getRange()), e.getValue().localToScreen(anchor), e.getValue().localToScreen(bounds));
+
+ return annotationTarget;
+ })
+ .collect(Collectors.toList());
+ }
+
}
Map<TextAnnotationPresenter, AnnotationOverlay> overlays = new HashMap<>();
@@ -510,6 +566,25 @@ public class LineNode extends StackPane {
super.layoutChildren();
}
+
+ public Collection<? extends HoverTarget> findHoverTargets(Point2D localLocation) {
+ List<HoverTarget> hoverTargets = new ArrayList<>();
+ for (AnnotationOverlay overlay : this.overlays.values()) {
+ hoverTargets.addAll(overlay.findHoverTargets(localLocation));
+ }
+ return hoverTargets;
+ }
+
+ }
+
+ protected Range<Integer> toGlobal(Range<Integer> range) {
+ int lineOffset = this.lineHelper.getOffset(index);
+ return Range.range(lineOffset + range.lowerEndpoint(), range.lowerBoundType(), lineOffset + range.upperEndpoint(), range.upperBoundType());
+ }
+
+ protected Range<Integer> toLocal(Range<Integer> range) {
+ int lineOffset = - this.lineHelper.getOffset(index);
+ return Range.range(lineOffset + range.lowerEndpoint(), range.lowerBoundType(), lineOffset + range.upperEndpoint(), range.upperBoundType());
}
TextLayer textLayer = new TextLayer();
@@ -656,6 +731,13 @@ public class LineNode extends StackPane {
return this.textLayer.getCharLocation(charOffset);
}
+ public List<HoverTarget> findHoverTargets(Point2D localLocation) {
+ List<HoverTarget> results = new ArrayList<>();
+ results.addAll(this.textLayer.findHoverTargets(localLocation));
+ results.addAll(this.annotationLayer.findHoverTargets(localLocation));
+ return results;
+ }
+
/**
* Check if the offset is between the start and end
*
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineRuler.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineRuler.java
index 71bee41e2..670871f00 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineRuler.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/internal/LineRuler.java
@@ -28,7 +28,8 @@ import javafx.scene.Node;
public class LineRuler extends VerticalLineFlow<Integer, Annotation>{
private LineRulerAnnotationPresenter.LayoutHint h;
- private DoubleProperty absoluteMinWidth = new SimpleDoubleProperty(this, "absoluteMinWidth"); //$NON-NLS-1$
+
+ private DoubleProperty fixedWidth = new SimpleDoubleProperty(this, "fixedWidth"); //$NON-NLS-1$
private DoubleProperty yOffset = new SimpleDoubleProperty(this, "yOffset"); //$NON-NLS-1$
@@ -44,11 +45,16 @@ public class LineRuler extends VerticalLineFlow<Integer, Annotation>{
@Override
protected double computeMinWidth(double height) {
- return Math.max(this.absoluteMinWidth.get(), super.computePrefWidth(height));
+ return this.fixedWidth.get();
+ }
+
+ @Override
+ protected double computeMaxWidth(double height) {
+ return this.fixedWidth.get();
}
- public DoubleProperty absoluteMinWidthProperty() {
- return this.absoluteMinWidth;
+ public DoubleProperty fixedWidthProperty() {
+ return this.fixedWidth;
}
@Override
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/model/Annotation.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/model/Annotation.java
index 01a7e1db2..a31b47fe4 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/model/Annotation.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/model/Annotation.java
@@ -11,4 +11,5 @@
package org.eclipse.fx.ui.controls.styledtext.model;
public interface Annotation {
+ public Object getModel();
}
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/skin/StyledTextSkin.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/skin/StyledTextSkin.java
index 53c8aa960..081583e8f 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/skin/StyledTextSkin.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext/skin/StyledTextSkin.java
@@ -27,6 +27,7 @@ import org.eclipse.fx.ui.controls.styledtext.StyledTextArea;
import org.eclipse.fx.ui.controls.styledtext.StyledTextContent.TextChangeListener;
import org.eclipse.fx.ui.controls.styledtext.TextChangedEvent;
import org.eclipse.fx.ui.controls.styledtext.TextChangingEvent;
+import org.eclipse.fx.ui.controls.styledtext.StyledTextArea.LineLocation;
import org.eclipse.fx.ui.controls.styledtext.behavior.StyledTextBehavior;
import org.eclipse.fx.ui.controls.styledtext.internal.ContentView;
import org.eclipse.fx.ui.controls.styledtext.internal.FXBindUtil;
@@ -53,6 +54,7 @@ import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.SkinBase;
+import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
@@ -272,7 +274,7 @@ public class StyledTextSkin extends SkinBase<StyledTextArea> {
// flow.getModel().bindContent(this.getModel());
- flow.absoluteMinWidthProperty().bind(ap.getWidth());
+ flow.fixedWidthProperty().bind(ap.getWidth());
// flow.prefWidthProperty().bind(ap.getWidth());
flow.prefWidthProperty().addListener((x, o, n) -> {
@@ -358,6 +360,14 @@ public class StyledTextSkin extends SkinBase<StyledTextArea> {
}
+ public <T> Optional<T> fastQuery(String label, String fieldText, Function<String, T> converter) {
+ TextInputDialog diag = new TextInputDialog();
+ diag.setTitle(label);
+ diag.setHeaderText(label);
+ diag.setContentText(fieldText);
+ return diag.showAndWait().map(converter);
+ }
+
private void scrollLineIntoView(int lineIndex) {
this.scroller.scrollIntoView(lineIndex);
}
@@ -388,12 +398,12 @@ public class StyledTextSkin extends SkinBase<StyledTextArea> {
* the position
* @return the point
*/
- public Point2D getCaretLocation(int caretPosition) {
+ public Point2D getCaretLocation(int caretPosition, LineLocation locationHint) {
if (caretPosition < 0) {
return null;
}
- Optional<Point2D> location = this.content.getLocationInScene(caretPosition);
+ Optional<Point2D> location = this.content.getLocationInScene(caretPosition, locationHint);
return location.map(l -> this.rootContainer.sceneToLocal(l)).map(l -> new Point2D(l.getX(), l.getY() + this.content.getLineHeight())).orElse(null);

Back to the top