/*=============================================================================# # Copyright (c) 2000-2016 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # IBM Corporation - initial API and implementation #=============================================================================*/ package de.walware.ecommons.ltk.ui.sourceediting; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.AbstractInformationControl; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.EditorsUI; import de.walware.ecommons.ui.util.LayoutUtil; /** * Information control to show sources or other text in a source viewer. */ public class SourceViewerInformationControl extends AbstractInformationControl { private static final int MODE_SIMPLE = 1; private static final int MODE_FOCUS = 2; private final int fMode; private Composite fContentComposite; /** The control's text widget */ private StyledText fText; /** The control's source viewer */ private SourceViewer fViewer; private final SourceEditorViewerConfigurator fConfigurator; private IInformationControlCreator fInformationCreator; /** * The orientation of the shell */ private final int fOrientation; /** * Creates a source viewer information control with the given shell as parent. The given * styles are applied to the created styled text widget. The status field will * contain the given text or be hidden. * * @param parent the parent shell * @param configurator used to configure the source viewer of the hover * @param informationConfigurator used to configure the source viewer of the information presenter * @param orientation the orientation */ public SourceViewerInformationControl(final Shell parent, final SourceEditorViewerConfigurator configurator, final int orientation, final IInformationControlCreator informationCreator) { super(parent, EditorsUI.getTooltipAffordanceString()); assert (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT || orientation == SWT.NONE); fMode = MODE_SIMPLE; fConfigurator = configurator; fOrientation = orientation; fInformationCreator = informationCreator; create(); } public SourceViewerInformationControl(final Shell parent, final SourceEditorViewerConfigurator configurator, final int orientation) { super(parent, true); assert (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT || orientation == SWT.NONE); fMode = MODE_FOCUS; fConfigurator = configurator; fOrientation = orientation; create(); } @Override protected void createContent(final Composite parent) { fContentComposite = new Composite(parent, SWT.NONE) { @Override public Point computeSize(final int width, final int height, final boolean changed) { return super.computeSize(width, height, changed || width != getSize().x); } }; fContentComposite.setBackground(parent.getBackground()); final GridLayout gridLayout = LayoutUtil.createCompositeGrid(1); fContentComposite.setLayout(gridLayout); final int vIndent = Math.max(1, LayoutUtil.defaultVSpacing() / 4); final int hIndent = Math.max(2, LayoutUtil.defaultHSpacing() / 3); // Source viewer fViewer = new SourceViewer(fContentComposite, null, null, false, (fMode == MODE_FOCUS ? (SWT.V_SCROLL | SWT.H_SCROLL) : SWT.NONE) | SWT.MULTI | SWT.READ_ONLY | fOrientation); fViewer.setEditable(false); final ViewerSourceEditorAdapter editor = new ViewerSourceEditorAdapter(fViewer, fConfigurator); fConfigurator.setTarget(editor); fText = fViewer.getTextWidget(); final GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); fText.setLayoutData(gd); fText.setFont(JFaceResources.getTextFont()); fText.setIndent(hIndent); // fText.addKeyListener(new KeyListener() { // public void keyPressed(final KeyEvent e) { // if (e.character == 0x1B) // ESC // fShell.dispose(); // } // public void keyReleased(final KeyEvent e) {} // }); setBackgroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); setForegroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); } @Override public void setBackgroundColor(final Color background) { super.setBackgroundColor(background); fText.setBackground(background); } @Override public void setForegroundColor(final Color foreground) { super.setForegroundColor(foreground); fText.setForeground(foreground); } @Override public void setInformation(String content) { if (content == null) { fViewer.setInput(null); return; } if (content.length() > 2 && content.charAt(content.length()-1) == '\n') { if (content.charAt(content.length()-2) == '\r') { content = content.substring(0, content.length()-2); } else { content = content.substring(0, content.length()-1); } } final IDocument document = new Document(content); fConfigurator.getDocumentSetupParticipant().setup(document); fViewer.setInput(document); } @Override public final void dispose() { if (fConfigurator != null) { fConfigurator.unconfigureTarget(); } super.dispose(); fText = null; } @Override public void setFocus() { fText.setFocus(); super.setFocus(); } @Override public boolean hasContents() { return fText.getCharCount() > 0; } protected ISourceViewer getViewer() { return fViewer; } @Override public Point computeSizeHint() { final Point sizeConstraints = getSizeConstraints(); final Rectangle trim = computeTrim(); int widthHint = fText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x + LayoutUtil.defaultHSpacing(); final int widthMax = ((sizeConstraints != null && sizeConstraints.x != SWT.DEFAULT) ? sizeConstraints.x : LayoutUtil.hintWidth(fText, null, 80)) - trim.width; if (widthHint > widthMax) { widthHint = widthMax; } final int heightMax = ((sizeConstraints != null && sizeConstraints.y != SWT.DEFAULT) ? sizeConstraints.y : fText.getLineHeight()*12) - trim.height; final Point size = fContentComposite.computeSize(widthHint, SWT.DEFAULT, false); size.x = Math.max(Math.min(size.x, widthMax), 200) + trim.width; size.y = Math.max(Math.min(size.y, heightMax), 80) + trim.height; return size; } @Override public Rectangle computeTrim() { final Rectangle trim = super.computeTrim(); final Rectangle textTrim = fText.computeTrim(0, 0, 0, 0); trim.x += textTrim.x; trim.y += textTrim.y; trim.width += textTrim.width; trim.height += textTrim.height; return trim; } @Override public Point computeSizeConstraints(final int widthInChars, final int heightInChars) { final GC gc = new GC(fText); gc.setFont(JFaceResources.getDialogFont()); final int width = gc.getFontMetrics().getAverageCharWidth() * widthInChars; final int height = gc.getFontMetrics().getHeight() * heightInChars; gc.dispose(); return new Point(width, height); } @Override public IInformationControlCreator getInformationPresenterControlCreator() { return fInformationCreator; } }