| /*=============================================================================# |
| # Copyright (c) 2000, 2020 IBM Corporation and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 |
| # |
| # Contributors: |
| # IBM Corporation - org.eclipse.jdt: initial API and implementation |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.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 org.eclipse.statet.ecommons.ui.util.LayoutUtils; |
| |
| |
| /** |
| * 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 mode; |
| |
| private Composite contentComposite; |
| |
| /** The control's text widget */ |
| private StyledText text; |
| /** The control's source viewer */ |
| private SourceViewer viewer; |
| |
| private final SourceEditorViewerConfigurator configurator; |
| |
| private IInformationControlCreator informationCreator; |
| |
| /** |
| * The orientation of the shell |
| */ |
| private final int orientation; |
| |
| |
| /** |
| * 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); |
| |
| this.mode= MODE_SIMPLE; |
| this.configurator= configurator; |
| this.orientation= orientation; |
| this.informationCreator= 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); |
| |
| this.mode= MODE_FOCUS; |
| this.configurator= configurator; |
| this.orientation= orientation; |
| create(); |
| } |
| |
| @Override |
| protected void createContent(final Composite parent) { |
| this.contentComposite= 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); |
| } |
| }; |
| this.contentComposite.setBackground(parent.getBackground()); |
| |
| final GridLayout gridLayout= LayoutUtils.newCompositeGrid(1); |
| this.contentComposite.setLayout(gridLayout); |
| |
| final int vIndent= Math.max(1, LayoutUtils.defaultVSpacing() / 4); |
| final int hIndent= Math.max(2, LayoutUtils.defaultHSpacing() / 3); |
| |
| // Source viewer |
| this.viewer= new SourceViewer(this.contentComposite, null, null, false, (this.mode == MODE_FOCUS ? |
| (SWT.V_SCROLL | SWT.H_SCROLL) : SWT.NONE) | SWT.MULTI | SWT.READ_ONLY | this.orientation); |
| this.viewer.setEditable(false); |
| final ViewerSourceEditorAdapter editor= new ViewerSourceEditorAdapter(this.viewer, this.configurator); |
| this.configurator.setTarget(editor); |
| |
| this.text= this.viewer.getTextWidget(); |
| final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true); |
| this.text.setLayoutData(gd); |
| this.text.setFont(JFaceResources.getTextFont()); |
| this.text.setIndent(hIndent); |
| |
| // this.text.addKeyListener(new KeyListener() { |
| // public void keyPressed(final KeyEvent e) { |
| // if (e.character == 0x1B) // ESC |
| // this.shell.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); |
| this.text.setBackground(background); |
| } |
| |
| @Override |
| public void setForegroundColor(final Color foreground) { |
| super.setForegroundColor(foreground); |
| this.text.setForeground(foreground); |
| } |
| |
| @Override |
| public void setInformation(String content) { |
| if (content == null) { |
| this.viewer.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); |
| this.configurator.getDocumentSetupParticipant().setup(document); |
| this.viewer.setInput(document); |
| } |
| |
| @Override |
| public final void dispose() { |
| if (this.configurator != null) { |
| this.configurator.unconfigureTarget(); |
| } |
| super.dispose(); |
| this.text= null; |
| } |
| |
| @Override |
| public void setFocus() { |
| this.text.setFocus(); |
| super.setFocus(); |
| } |
| |
| @Override |
| public boolean hasContents() { |
| return this.text.getCharCount() > 0; |
| } |
| |
| protected ISourceViewer getViewer() { |
| return this.viewer; |
| } |
| |
| @Override |
| public Point computeSizeHint() { |
| final Point sizeConstraints= getSizeConstraints(); |
| final Rectangle trim= computeTrim(); |
| |
| int widthHint= this.text.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x + LayoutUtils.defaultHSpacing(); |
| final int widthMax= ((sizeConstraints != null && sizeConstraints.x != SWT.DEFAULT) ? |
| sizeConstraints.x : LayoutUtils.hintWidth(this.text, null, 80)) - trim.width; |
| if (widthHint > widthMax) { |
| widthHint= widthMax; |
| } |
| |
| final int heightMax= ((sizeConstraints != null && sizeConstraints.y != SWT.DEFAULT) ? |
| sizeConstraints.y : |
| this.text.getLineHeight()*12) - trim.height; |
| |
| final Point size= this.contentComposite.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= this.text.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(this.text); |
| gc.setFont(JFaceResources.getDialogFont()); |
| final double width= gc.getFontMetrics().getAverageCharacterWidth() * widthInChars; |
| final int height= gc.getFontMetrics().getHeight() * heightInChars; |
| gc.dispose(); |
| |
| return new Point((int)Math.round(width + 0x1.FFFFFp-2), height); |
| } |
| |
| @Override |
| public IInformationControlCreator getInformationPresenterControlCreator() { |
| return this.informationCreator; |
| } |
| |
| } |