Commit 5bd89d4e authored by Miklos Magyari's avatar Miklos Magyari
Browse files

Refactored hover and code peek handling


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 606962cc
package org.eclipse.titan.designer.editors.controls;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.Location;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Testcase;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Type;
import org.eclipse.titan.designer.declarationsearch.Declaration;
import org.eclipse.titan.designer.editors.ColorManager;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverContent.ContentType;
import org.eclipse.titan.designer.editors.ttcn3editor.CodeScanner;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
public class PeekSource {
public static String getPeekSource(IEditorPart targetEditor, IFile file, Declaration decl) {
if (decl == null) {
return null;
}
final Assignment ass = decl.getAssignment();
Location codeLoc = null;
if (ass instanceof Def_Type || ass instanceof Def_Function ||
ass instanceof Def_Testcase) {
codeLoc = ass.getLocation();
}
if (codeLoc != null) {
final IResource fileToLoad = codeLoc.getFile();
IResource actual = (IResource)file;
String codeText = null;
if (targetEditor instanceof ITextEditor)
{
ITextEditor textEditor = (ITextEditor) targetEditor;
IDocumentProvider provider = textEditor.getDocumentProvider();
IEditorInput input = targetEditor.getEditorInput();
IDocument document;
if (actual.getFullPath().equals(fileToLoad.getFullPath())) {
document = provider.getDocument(input);
StringBuilder code = new StringBuilder();
try {
for (int i = codeLoc.getOffset(); i <= codeLoc.getEndOffset(); i++) {
char c = document.getChar(i);
code.append(c);
}
} catch (Exception e) {
return null;
}
codeText = code.toString();
} else {
// external file
try {
RandomAccessFile f2 = new RandomAccessFile(fileToLoad.getLocation().toString(), "r");
final int size = codeLoc.getEndOffset() - codeLoc.getOffset();
byte[] buffer = new byte[size + 1];
f2.seek(codeLoc.getOffset());
f2.read(buffer, 0, size);
codeText = new String(buffer);
} catch (Exception e) {
return null;
}
}
return codeText;
}
}
return null;
}
public static void addStyledSource(String source, Ttcn3HoverContent viewer) {
if (source == null) {
viewer.addContent(ContentType.Source, source, null);
return;
}
/*
* We may need to strip some leading tabs/spaces from all lines except the first one
*
* This is because whitespaces are typically missing for the first line but all the other
* lines are indented
*/
String[] lines = source.split("\n");
int minspaces = Integer.MAX_VALUE;
int spacecount = 0;
if (lines.length > 1) {
StringBuilder notabs = new StringBuilder();
for (int i = 1; i < lines.length; i++) {
spacecount = 0;
for (int j = 0; j < lines[i].length(); j++) {
if (lines[i].charAt(j) == '\t') {
spacecount += 4;
notabs.append(" ");
} else if (lines[i].charAt(j) == ' ') {
spacecount++;
notabs.append(" ");
} else {
notabs.append(lines[i].substring(j));
break;
}
}
notabs.append("\n");
if (spacecount < minspaces) {
minspaces = spacecount;
}
}
StringBuilder stripped = new StringBuilder();
if (minspaces != Integer.MAX_VALUE && minspaces > 0) {
stripped.append(lines[0]);
lines = notabs.toString().split("\n");
for (int i = 0; i < lines.length; i++) {
stripped.append("\n");
stripped.append(lines[i].substring(minspaces));
}
source = stripped.toString();
}
}
//viewer.setText(source);
IDocument doc = new Document(source);
CodeScanner scanner = new CodeScanner(new ColorManager());
scanner.setRange(doc, 0, source.length());
IToken token;
List<StyleRange> ranges = new ArrayList<StyleRange>();
for (;;) {
token = scanner.nextToken();
if (token.isEOF())
break;
int len = scanner.getTokenLength();
int offs = scanner.getTokenOffset();
StyleRange range = new StyleRange();
range.start = offs;
range.length = len;
if (token.getData() instanceof TextAttribute) {
TextAttribute attrib = (TextAttribute)token.getData();
range.fontStyle = attrib.getStyle();
range.foreground = attrib.getForeground();
}
ranges.add(range);
}
viewer.addContent(ContentType.Source, source, ranges);;
}
}
......@@ -7,8 +7,9 @@
******************************************************************************/
package org.eclipse.titan.designer.editors.controls;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.custom.StyleRange;
......@@ -19,26 +20,37 @@ import org.eclipse.swt.custom.StyleRange;
* @author Miklos Magyari
*/
public class Ttcn3HoverContent {
private String text;
private List<StyleRange> ranges = new ArrayList<StyleRange>();
public String getText() {
return text;
private class Entry {
String text;
List<StyleRange> ranges;
Entry(String text, List<StyleRange> ranges) {
this.text = text;
this.ranges = ranges;
}
}
public void setText(String text) {
this.text = text;
}
public List<StyleRange> getRanges() {
return ranges;
public enum ContentType { Info, Source };
private Map<ContentType, Entry> map = new HashMap<ContentType, Entry>();
public void addContent(ContentType type, String text, List<StyleRange> range) {
final Entry mapentry = new Entry(text, range);
map.put(type, mapentry);
}
public void addRange(StyleRange range) {
ranges.add(range);
public String getText(ContentType type) {
final Entry mapentry = map.get(type);
if (mapentry == null) {
return null;
}
return mapentry.text;
}
public void addRangeAll(List<StyleRange> ranges) {
this.ranges.addAll(ranges);
public List<StyleRange> getRanges(ContentType type) {
final Entry mapentry = map.get(type);
if (mapentry == null) {
return null;
}
return mapentry.ranges;
}
}
......@@ -14,10 +14,14 @@ import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.titan.designer.editors.actions.SwitchHoverWindowContentAction;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverContent.ContentType;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.keys.IBindingService;
......@@ -33,6 +37,7 @@ public class Ttcn3HoverInfoControl extends AbstractInformationControl implements
private Ttcn3HoverContent content;
private Shell fShell;
private boolean isRich;
private ContentType actualType = ContentType.Info;
public Ttcn3HoverInfoControl(Shell parentShell, String string) {
super(parentShell, string);
......@@ -62,7 +67,7 @@ public class Ttcn3HoverInfoControl extends AbstractInformationControl implements
@Override
public boolean hasContents() {
return content.getText() != null;
return content != null;
}
@Override
......@@ -84,6 +89,14 @@ public class Ttcn3HoverInfoControl extends AbstractInformationControl implements
} else {
setStatusText("Hover to focus");
}
fShell.addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(MouseEvent e) {
// TODO Auto-generated method stub
int i = 0;
}
});
}
@Override
......@@ -100,8 +113,8 @@ public class Ttcn3HoverInfoControl extends AbstractInformationControl implements
public void setInput(Object input) {
if (input instanceof Ttcn3HoverContent) {
content = (Ttcn3HoverContent)input;
viewer.setText(content.getText());
for (StyleRange style : content.getRanges()) {
viewer.setText(content.getText(actualType));
for (StyleRange style : content.getRanges(actualType)) {
viewer.setStyleRange(style);
}
}
......
......@@ -9,12 +9,8 @@ package org.eclipse.titan.designer.editors.controls;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
......@@ -31,8 +27,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.titan.designer.editors.ColorManager;
import org.eclipse.titan.designer.editors.ttcn3editor.CodeScanner;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverContent.ContentType;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPart;
......@@ -115,77 +110,13 @@ public class Ttcn3SourceViewControl implements IInformationControl, IInformation
@Override
public void setInformation(String information) {
if (information == null) {
viewer.setText(null);
return;
}
/*
* We may need to strip some leading tabs/spaces from all lines except the first one
*
* This is because whitespaces are typically missing for the first line but all the other
* lines are indented
*/
String[] lines = information.split("\n");
int minspaces = Integer.MAX_VALUE;
int spacecount = 0;
if (lines.length > 1) {
StringBuilder notabs = new StringBuilder();
for (int i = 1; i < lines.length; i++) {
spacecount = 0;
for (int j = 0; j < lines[i].length(); j++) {
if (lines[i].charAt(j) == '\t') {
spacecount += 4;
notabs.append(" ");
} else if (lines[i].charAt(j) == ' ') {
spacecount++;
notabs.append(" ");
} else {
notabs.append(lines[i].substring(j));
break;
}
}
notabs.append("\n");
if (spacecount < minspaces) {
minspaces = spacecount;
}
}
StringBuilder stripped = new StringBuilder();
if (minspaces != Integer.MAX_VALUE && minspaces > 0) {
stripped.append(lines[0]);
lines = notabs.toString().split("\n");
for (int i = 0; i < lines.length; i++) {
stripped.append("\n");
stripped.append(lines[i].substring(minspaces));
}
information = stripped.toString();
}
}
viewer.setText(information);
IDocument doc = new Document(information);
CodeScanner scanner = new CodeScanner(new ColorManager());
scanner.setRange(doc, 0, information.length());
IToken token;
for (;;) {
token = scanner.nextToken();
if (token.isEOF())
break;
int len = scanner.getTokenLength();
int offs = scanner.getTokenOffset();
StyleRange range = new StyleRange();
range.start = offs;
range.length = len;
if (token.getData() instanceof TextAttribute) {
TextAttribute attrib = (TextAttribute)token.getData();
range.fontStyle = attrib.getStyle();
range.foreground = attrib.getForeground();
}
Ttcn3HoverContent content = new Ttcn3HoverContent();
PeekSource.addStyledSource(information, content);
viewer.setText(content.getText(ContentType.Source));
for (StyleRange range : content.getRanges(ContentType.Source)) {
viewer.setStyleRange(range);
}
final Point size = computeSizeHint();
setSize(size.x, size.y);
}
......
......@@ -8,6 +8,7 @@
package org.eclipse.titan.designer.editors.ttcn3editor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -47,13 +48,16 @@ import org.eclipse.titan.designer.AST.TTCN3.types.Referenced_Type;
import org.eclipse.titan.designer.editors.BaseTextHover;
import org.eclipse.titan.designer.editors.IReferenceParser;
import org.eclipse.titan.designer.editors.Stylers;
import org.eclipse.titan.designer.editors.controls.PeekSource;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverContent;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverContent.ContentType;
import org.eclipse.titan.designer.editors.controls.Ttcn3HoverInfoControl;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
import org.eclipse.titan.designer.parsers.GlobalParser;
import org.eclipse.titan.designer.parsers.ProjectSourceParser;
import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReferenceAnalyzer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
/**
......@@ -139,10 +143,13 @@ public final class TextHover extends BaseTextHover implements ITextHoverExtensio
}
}
Ttcn3HoverContent content = new Ttcn3HoverContent();
content.setText(tooltip.toString());
content.addRangeAll(styles);
return content;
Map<Ttcn3HoverContent.ContentType, Ttcn3HoverContent> contents = new HashMap<Ttcn3HoverContent.ContentType, Ttcn3HoverContent>(2);
Ttcn3HoverContent info = new Ttcn3HoverContent();
info.addContent(ContentType.Info, tooltip.toString(), styles);
PeekSource.addStyledSource(PeekSource.getPeekSource(editor, file, assignment.getDeclaration()), info);
//contents.put(ContentType.Source, source);
return info;
}
}
return "";
......@@ -157,7 +164,8 @@ public final class TextHover extends BaseTextHover implements ITextHoverExtensio
public String getHoverInfo(final ITextViewer textViewer, final IRegion hoverRegion) {
final Ttcn3HoverContent content = (Ttcn3HoverContent)getHoverInfo2(textViewer, hoverRegion);
return content != null ? content.getText() : "";
return null;
//return content != null ? content.getText() : "";
}
private String getIdentifier(IDocument doc, int pos) {
......@@ -313,6 +321,7 @@ public final class TextHover extends BaseTextHover implements ITextHoverExtensio
addStyledText(sb, styles, body.getIdentifier().getDisplayName(), boldRange());
sb.append("\n\n");
addClassMembers(sb, styles, dc, timestamp, body);
addAuthors(sb, styles, dc);
}
private void addClassMembers(StringBuilder sb, List<StyleRange> styles, DocumentComment dc, CompilationTimeStamp timestamp, ClassTypeBody body) {
......@@ -357,7 +366,7 @@ public final class TextHover extends BaseTextHover implements ITextHoverExtensio
}
sb.append(memberTypeName + " ");
addStyledText(sb, styles, def.getIdentifier().getDisplayName(), boldItalicRange());
sb.append(" " + memberText != null ? memberText : "");
sb.append(" " + (memberText != null ? memberText : ""));
sb.append("\n");
}
}
......
......@@ -7,18 +7,14 @@
******************************************************************************/
package org.eclipse.titan.designer.editors.ttcn3editor.actions;
import java.io.RandomAccessFile;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.custom.StyledText;
......@@ -27,15 +23,11 @@ import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.Location;
import org.eclipse.titan.designer.AST.Module;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Testcase;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Type;
import org.eclipse.titan.designer.consoles.TITANDebugConsole;
import org.eclipse.titan.designer.declarationsearch.Declaration;
import org.eclipse.titan.designer.declarationsearch.IdentifierFinderVisitor;
import org.eclipse.titan.designer.editors.controls.PeekSource;
import org.eclipse.titan.designer.editors.controls.Ttcn3SourceViewControl;
import org.eclipse.titan.designer.editors.ttcn3editor.TTCN3Editor;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
......@@ -44,11 +36,8 @@ import org.eclipse.titan.designer.parsers.ProjectSourceParser;
import org.eclipse.titan.designer.preferences.PreferenceConstants;
import org.eclipse.titan.designer.productUtilities.ProductConstants;
import org.eclipse.ui.IEditorActionDelegate;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* Action code for peek declaration feature
......@@ -126,75 +115,24 @@ public class PeekDeclaration extends AbstractHandler implements IEditorActionDel
final IdentifierFinderVisitor visitor = new IdentifierFinderVisitor(offset);
module.accept(visitor);
final Declaration decl = visitor.getReferencedDeclaration();
if (decl == null) {
if (reportDebugInformation) {
TITANDebugConsole.println("No visible elements found");
}
return;
}
Shell shell = targetEditor.getSite().getShell();
final Assignment ass = decl.getAssignment();
Location codeLoc = null;
if (ass instanceof Def_Type || ass instanceof Def_Function ||
ass instanceof Def_Testcase) {
codeLoc = ass.getLocation();
}
if (codeLoc != null) {
final IResource fileToLoad = codeLoc.getFile();
IResource actual = (IResource)file;
Shell shell = targetEditor.getSite().getShell();
String codeText = null;
if (targetEditor instanceof ITextEditor)
{
ITextEditor textEditor = (ITextEditor) targetEditor;
IDocumentProvider provider = textEditor.getDocumentProvider();
IEditorInput input = targetEditor.getEditorInput();
IDocument document;
if (actual.getFullPath().equals(fileToLoad.getFullPath())) {
document = provider.getDocument(input);
StringBuilder code = new StringBuilder();
try {
for (int i = codeLoc.getOffset(); i <= codeLoc.getEndOffset(); i++) {
char c = document.getChar(i);
code.append(c);
}
} catch (Exception e) {
return;
}
codeText = code.toString();
} else {
// external file
try {
RandomAccessFile f2 = new RandomAccessFile(fileToLoad.getLocation().toString(), "r");
final int size = codeLoc.getEndOffset() - codeLoc.getOffset();
byte[] buffer = new byte[size + 1];
f2.seek(codeLoc.getOffset());
f2.read(buffer, 0, size);
codeText = new String(buffer);
} catch (Exception e) {
return;
}
}
Ttcn3SourceViewControl con = Ttcn3SourceViewControl.getInstance();
con.createControl(shell);