hyperlink.java

来自「Python Development Environment (Python I」· Java 代码 · 共 651 行 · 第 1/2 页

JAVA
651
字号
/*
 * Author: atotic
 * Created on Mar 31, 2004
 * License: Common Public License v1.0
 */
package org.python.pydev.editor;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.editor.actions.PyOpenAction;
import org.python.pydev.editor.actions.refactoring.PyRefactorAction;
import org.python.pydev.editor.model.ItemPointer;
import org.python.pydev.editor.refactoring.IPyRefactoring;
import org.python.pydev.editor.refactoring.PyRefactoring;
import org.python.pydev.editor.refactoring.RefactoringRequest;
import org.python.pydev.parser.visitors.PythonLanguageUtils;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.ui.ColorCache;

/**
 * Hyperlink is a "Mouse highlight on ctrl".
 * The code here has been copied from JavaEditor::MouseClick.
 * I've just modified Python-specific code.
 */
public class Hyperlink implements KeyListener, MouseListener, MouseMoveListener,
	FocusListener, PaintListener, IDocumentListener, ITextInputListener {

	/** The session is active. */
	private boolean fActive;

	/** The currently active style range. */
	private IRegion fActiveRegion;
	/** The currently active style range as position. */
	private Position fRememberedPosition;
	/** The hand cursor. */
	private Cursor fCursor;
		
	/** The link color. */
	private Color fColor;
	/** The key modifier mask. */
	private int fKeyModifierMask;

	private ColorCache fColorCache;

	/************
	 * ALEKS ADDITIONS
	 */
	private ISourceViewer fSourceViewer;
	private PyEdit fEditor;
	
	public Hyperlink(ISourceViewer sourceViewer, PyEdit editor, ColorCache colorCache) {
		fSourceViewer = sourceViewer;
		fEditor = editor;
		fKeyModifierMask = SWT.CTRL;
		fColorCache = colorCache;
	}
	
	private ISourceViewer getSourceViewer() {
		return fSourceViewer;
	}	

	public void deactivate() {
		deactivate(false);
	}

	public void deactivate(boolean redrawAll) {
		if (!fActive)
			return;

		repairRepresentation(redrawAll);			
		fActive= false;
	}

	public void install() {

		ISourceViewer sourceViewer= getSourceViewer();
		if (sourceViewer == null)
			return;
				
		StyledText text= sourceViewer.getTextWidget();			
		if (text == null || text.isDisposed())
			return;
				
		updateColor(sourceViewer);

		sourceViewer.addTextInputListener(this);
			
		IDocument document= sourceViewer.getDocument();
		if (document != null)
			document.addDocumentListener(this);			

		text.addKeyListener(this);
		text.addMouseListener(this);
		text.addMouseMoveListener(this);
		text.addFocusListener(this);
		text.addPaintListener(this);
	}

	public void uninstall() {

		if (fColor != null) {
			fColor.dispose();
			fColor= null;
		}
			
		if (fCursor != null) {
			fCursor.dispose();
			fCursor= null;
		}
			
		ISourceViewer sourceViewer= getSourceViewer();
		if (sourceViewer == null)
			return;
				
		sourceViewer.removeTextInputListener(this);

		IDocument document= sourceViewer.getDocument();
		if (document != null)
			document.removeDocumentListener(this);
			
		StyledText text= sourceViewer.getTextWidget();
		if (text == null || text.isDisposed())
			return;
				
		text.removeKeyListener(this);
		text.removeMouseListener(this);
		text.removeMouseMoveListener(this);
		text.removeFocusListener(this);
		text.removePaintListener(this);
		}

	public void updateColor(ISourceViewer viewer) {
	
		StyledText text= viewer.getTextWidget();
		if (text == null || text.isDisposed())
			return;

		fColor = fColorCache.getNamedColor(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_HYPERLINK_COLOR);
	}

	private void repairRepresentation() {			
		repairRepresentation(false);
	}

	private void repairRepresentation(boolean redrawAll) {			

		if (fActiveRegion == null)
			return;
				
		ISourceViewer viewer= getSourceViewer();
		if (viewer != null) {
			resetCursor(viewer);

			int offset= fActiveRegion.getOffset();
			int length= fActiveRegion.getLength();

			// remove style
			if (!redrawAll && viewer instanceof ITextViewerExtension2)
				((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length);
			else
				viewer.invalidateTextPresentation();

			// remove underline				
			if (viewer instanceof ITextViewerExtension5) {
				ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
				offset= extension.modelOffset2WidgetOffset(offset);
			} else {
				offset -= viewer.getVisibleRegion().getOffset();
			}
				
			StyledText text= viewer.getTextWidget();
			try {
				text.redrawRange(offset, length, true);
			} catch (IllegalArgumentException x) {
				PydevPlugin.log(IStatus.ERROR, "Unexpected error in Hyperlink code", x);
			}
		}
			
		fActiveRegion= null;
	}

	// will eventually be replaced by a method provided by jdt.core		
	private IRegion selectWord(IDocument document, int anchor) {
		
		try {		
			int offset= anchor;
			char c;
	
			while (offset >= 0) {
				c= document.getChar(offset);
				if (!Character.isJavaIdentifierPart(c))
					break;
				--offset;
			}
	
			int start= offset;
	
			offset= anchor;
			int length= document.getLength();
	
			while (offset < length) {
				c= document.getChar(offset);
				if (!Character.isJavaIdentifierPart(c))
					break;
				++offset;
			}
				
			int end= offset;
				
			if (start == end)
				return new Region(start, 0);
			else
				return new Region(start + 1, end - start - 1);
				
		} catch (BadLocationException x) {
			return null;
		}
	}

    /**
     * This is the method that we have to implement that will return which region should be highlighted
     * when Ctrl is pressed.
     */
	private IRegion getCurrentTextRegion(ISourceViewer viewer) {
		int offset= getCurrentTextOffset(viewer);				
		if (offset == -1){
			return null;
        }

		IDocument doc = viewer.getDocument();
        IRegion word = selectWord(doc, offset);
        try {
            String selectedWord = doc.get(word.getOffset(), word.getLength());
            if(PythonLanguageUtils.isKeyword(selectedWord)){
                return null;
            }
        } catch (BadLocationException e) {
            PydevPlugin.log(e);
        }
        return word;	
	}

    /**
     * @return the start offset for the current selected text
     */
	private int getCurrentTextOffset(ISourceViewer viewer) {

		try {					
			StyledText text= viewer.getTextWidget();			
			if (text == null || text.isDisposed())
				return -1;

			Display display= text.getDisplay();				
			Point absolutePosition= display.getCursorLocation();
			Point relativePosition= text.toControl(absolutePosition);
				
			int widgetOffset= text.getOffsetAtLocation(relativePosition);
			if (viewer instanceof ITextViewerExtension5) {
				ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
				return extension.widgetOffset2ModelOffset(widgetOffset);
			} else {
				return widgetOffset + viewer.getVisibleRegion().getOffset();
			}

		} catch (IllegalArgumentException e) {
			return -1;
		}			
	}

	private void highlightRegion(ISourceViewer viewer, IRegion region) {

		if (region.equals(fActiveRegion))
			return;

		repairRepresentation();

		StyledText text= viewer.getTextWidget();
		if (text == null || text.isDisposed())
			return;

		// highlight region
		int offset= 0;
		int length= 0;
			
		if (viewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
			IRegion widgetRange= extension.modelRange2WidgetRange(region);
			if (widgetRange == null)
				return;
					
			offset= widgetRange.getOffset();
			length= widgetRange.getLength();
				
		} else {
			offset= region.getOffset() - viewer.getVisibleRegion().getOffset();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?