Mercurial > projects > dwt-addons
view dwtx/jface/text/hyperlink/HyperlinkManager.d @ 153:f70d9508c95c
Fix java Collection imports
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 25 Aug 2008 00:27:31 +0200 |
parents | 000f9136b8f7 |
children | 7926b636c282 |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2008 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 * Steffen Pingel <steffen.pingel@tasktop.com> (Tasktop Technologies Inc.) - [navigation] hyperlink decoration is not erased when mouse is moved out of Text widget - https://bugs.eclipse.org/bugs/show_bug.cgi?id=100278 * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwtx.jface.text.hyperlink.HyperlinkManager; import dwtx.jface.text.hyperlink.IHyperlinkPresenterExtension; // packageimport import dwtx.jface.text.hyperlink.MultipleHyperlinkPresenter; // packageimport import dwtx.jface.text.hyperlink.URLHyperlink; // packageimport import dwtx.jface.text.hyperlink.IHyperlinkDetectorExtension2; // packageimport import dwtx.jface.text.hyperlink.IHyperlinkDetector; // packageimport import dwtx.jface.text.hyperlink.IHyperlinkPresenter; // packageimport import dwtx.jface.text.hyperlink.URLHyperlinkDetector; // packageimport import dwtx.jface.text.hyperlink.DefaultHyperlinkPresenter; // packageimport import dwtx.jface.text.hyperlink.AbstractHyperlinkDetector; // packageimport import dwtx.jface.text.hyperlink.IHyperlinkDetectorExtension; // packageimport import dwtx.jface.text.hyperlink.HyperlinkMessages; // packageimport import dwtx.jface.text.hyperlink.IHyperlink; // packageimport import dwt.dwthelper.utils; import dwtx.dwtxhelper.Collection; import dwt.DWT; import dwt.custom.StyledText; import dwt.events.FocusEvent; import dwt.events.FocusListener; import dwt.events.KeyEvent; import dwt.events.KeyListener; import dwt.events.MouseEvent; import dwt.events.MouseListener; import dwt.events.MouseMoveListener; import dwt.events.MouseTrackListener; import dwt.graphics.Point; import dwt.widgets.Display; import dwt.widgets.Event; import dwt.widgets.Listener; import dwtx.core.runtime.Assert; import dwtx.jface.text.IRegion; import dwtx.jface.text.ITextListener; import dwtx.jface.text.ITextViewer; import dwtx.jface.text.ITextViewerExtension5; import dwtx.jface.text.Region; import dwtx.jface.text.TextEvent; /** * Default implementation of a hyperlink manager. * * @since 3.1 */ public class HyperlinkManager : ITextListener, Listener, KeyListener, MouseListener, MouseMoveListener, FocusListener, MouseTrackListener { /** * Detection strategy. */ public static final class DETECTION_STRATEGY { String fName; private this(String name) { fName= name; } /* * @see java.lang.Object#toString() */ public String toString() { return fName; } } /** * The first detected hyperlink is passed to the * hyperlink presenter and no further detector * is consulted. */ public static const DETECTION_STRATEGY FIRST= new DETECTION_STRATEGY("first"); //$NON-NLS-1$ /** * All detected hyperlinks from all detectors are collected * and passed to the hyperlink presenter. * <p> * This strategy is only allowed if {@link IHyperlinkPresenter#canShowMultipleHyperlinks()} * returns <code>true</code>. * </p> */ public static const DETECTION_STRATEGY ALL= new DETECTION_STRATEGY("all"); //$NON-NLS-1$ /** * All detected hyperlinks from all detectors are collected * and all those with the longest region are passed to the * hyperlink presenter. * <p> * This strategy is only allowed if {@link IHyperlinkPresenter#canShowMultipleHyperlinks()} * returns <code>true</code>. * </p> */ public static const DETECTION_STRATEGY LONGEST_REGION_ALL= new DETECTION_STRATEGY("all with same longest region"); //$NON-NLS-1$ /** * All detected hyperlinks from all detectors are collected * and form all those with the longest region only the first * one is passed to the hyperlink presenter. */ public static const DETECTION_STRATEGY LONGEST_REGION_FIRST= new DETECTION_STRATEGY("first with longest region"); //$NON-NLS-1$ /** The text viewer on which this hyperlink manager works. */ private ITextViewer fTextViewer; /** The session is active. */ private bool fActive; /** The key modifier mask. */ private int fHyperlinkStateMask; /** * The active key modifier mask. * @since 3.3 */ private int fActiveHyperlinkStateMask; /** The active hyperlinks. */ private IHyperlink[] fActiveHyperlinks; /** The hyperlink detectors. */ private IHyperlinkDetector[] fHyperlinkDetectors; /** The hyperlink presenter. */ private IHyperlinkPresenter fHyperlinkPresenter; /** The detection strategy. */ private const DETECTION_STRATEGY fDetectionStrategy; /** * Creates a new hyperlink manager. * * @param detectionStrategy the detection strategy one of {{@link #ALL}, {@link #FIRST}, {@link #LONGEST_REGION_ALL}, {@link #LONGEST_REGION_FIRST}} */ public this(DETECTION_STRATEGY detectionStrategy) { Assert.isNotNull(detectionStrategy); fDetectionStrategy= detectionStrategy; } /** * Installs this hyperlink manager with the given arguments. * * @param textViewer the text viewer * @param hyperlinkPresenter the hyperlink presenter * @param hyperlinkDetectors the array of hyperlink detectors, must not be empty * @param eventStateMask the DWT event state mask to activate hyperlink mode */ public void install(ITextViewer textViewer, IHyperlinkPresenter hyperlinkPresenter, IHyperlinkDetector[] hyperlinkDetectors, int eventStateMask) { Assert.isNotNull(textViewer); Assert.isNotNull(hyperlinkPresenter); fTextViewer= textViewer; fHyperlinkPresenter= hyperlinkPresenter; Assert.isLegal(fHyperlinkPresenter.canShowMultipleHyperlinks() || fDetectionStrategy is FIRST || fDetectionStrategy is LONGEST_REGION_FIRST); setHyperlinkDetectors(hyperlinkDetectors); setHyperlinkStateMask(eventStateMask); StyledText text= fTextViewer.getTextWidget(); if (text is null || text.isDisposed()) return; text.getDisplay().addFilter(DWT.KeyUp, this); text.addKeyListener(this); text.addMouseListener(this); text.addMouseMoveListener(this); text.addFocusListener(this); text.addMouseTrackListener(this); fTextViewer.addTextListener(this); fHyperlinkPresenter.install(fTextViewer); } /** * Sets the hyperlink detectors for this hyperlink manager. * <p> * It is allowed to call this method after this * hyperlink manger has been installed. * </p> * * @param hyperlinkDetectors and array of hyperlink detectors, must not be empty */ public void setHyperlinkDetectors(IHyperlinkDetector[] hyperlinkDetectors) { Assert.isTrue(hyperlinkDetectors !is null && hyperlinkDetectors.length > 0); if (fHyperlinkDetectors is null) fHyperlinkDetectors= hyperlinkDetectors; else { synchronized (fHyperlinkDetectors) { fHyperlinkDetectors= hyperlinkDetectors; } } } /** * Sets the DWT event state mask which in combination * with the left mouse button triggers the hyperlink mode. * <p> * It is allowed to call this method after this * hyperlink manger has been installed. * </p> * * @param eventStateMask the DWT event state mask to activate hyperlink mode */ public void setHyperlinkStateMask(int eventStateMask) { fHyperlinkStateMask= eventStateMask; } /** * Uninstalls this hyperlink manager. */ public void uninstall() { deactivate(); StyledText text= fTextViewer.getTextWidget(); if (text !is null && !text.isDisposed()) { text.removeKeyListener(this); text.getDisplay().removeFilter(DWT.KeyUp, this); text.removeMouseListener(this); text.removeMouseMoveListener(this); text.removeFocusListener(this); text.removeMouseTrackListener(this); } fTextViewer.removeTextListener(this); fHyperlinkPresenter.uninstall(); fHyperlinkPresenter= null; fTextViewer= null; fHyperlinkDetectors= null; } /** * Deactivates the currently shown hyperlinks. */ protected void deactivate() { fHyperlinkPresenter.hideHyperlinks(); fActive= false; } /** * Finds hyperlinks at the current offset. * * @return the hyperlinks or <code>null</code> if none. */ protected IHyperlink[] findHyperlinks() { int offset= getCurrentTextOffset(); if (offset is -1) return null; bool canShowMultipleHyperlinks= fHyperlinkPresenter.canShowMultipleHyperlinks(); IRegion region= new Region(offset, 0); List allHyperlinks= new ArrayList(fHyperlinkDetectors.length * 2); synchronized (fHyperlinkDetectors) { for (int i= 0, length= fHyperlinkDetectors.length; i < length; i++) { IHyperlinkDetector detector= fHyperlinkDetectors[i]; if (detector is null) continue; if ( cast(IHyperlinkDetectorExtension2)detector ) { int stateMask= (cast(IHyperlinkDetectorExtension2)detector).getStateMask(); if (stateMask !is -1 && stateMask !is fActiveHyperlinkStateMask) continue; else if (stateMask is -1 && fActiveHyperlinkStateMask !is fHyperlinkStateMask) continue; } else if (fActiveHyperlinkStateMask !is fHyperlinkStateMask) continue; IHyperlink[] hyperlinks= detector.detectHyperlinks(fTextViewer, region, canShowMultipleHyperlinks); if (hyperlinks is null) continue; Assert.isLegal(hyperlinks.length > 0); if (fDetectionStrategy is FIRST) { if (hyperlinks.length is 1) return hyperlinks; return [hyperlinks[0]]; } allHyperlinks.addAll(Arrays.asList(hyperlinks)); } } if (allHyperlinks.isEmpty()) return null; if (fDetectionStrategy !is ALL) { int maxLength= computeLongestHyperlinkLength(allHyperlinks); Iterator iter= (new ArrayList(allHyperlinks)).iterator(); while (iter.hasNext()) { IHyperlink hyperlink= cast(IHyperlink)iter.next(); if (hyperlink.getHyperlinkRegion().getLength() < maxLength) allHyperlinks.remove(hyperlink); } } if (fDetectionStrategy is LONGEST_REGION_FIRST) return [cast(IHyperlink)allHyperlinks.get(0)]; return arraycast!(IHyperlink)(allHyperlinks.toArray()); } /** * Computes the length of the longest detected * hyperlink. * * @param hyperlinks * @return the length of the longest detected */ protected int computeLongestHyperlinkLength(List hyperlinks) { Assert.isLegal(hyperlinks !is null && !hyperlinks.isEmpty()); Iterator iter= hyperlinks.iterator(); int length= Integer.MIN_VALUE; while (iter.hasNext()) { IRegion region= (cast(IHyperlink)iter.next()).getHyperlinkRegion(); if (region.getLength() < length) continue; length= region.getLength(); } return length; } /** * Returns the current text offset. * * @return the current text offset */ protected int getCurrentTextOffset() { try { StyledText text= fTextViewer.getTextWidget(); if (text is null || text.isDisposed()) return -1; Display display= text.getDisplay(); Point absolutePosition= display.getCursorLocation(); Point relativePosition= text.toControl(absolutePosition); int widgetOffset= text.getOffsetAtLocation(relativePosition); Point p= text.getLocationAtOffset(widgetOffset); if (p.x > relativePosition.x) widgetOffset--; if ( cast(ITextViewerExtension5)fTextViewer ) { ITextViewerExtension5 extension= cast(ITextViewerExtension5)fTextViewer; return extension.widgetOffset2ModelOffset(widgetOffset); } return widgetOffset + fTextViewer.getVisibleRegion().getOffset(); } catch (IllegalArgumentException e) { return -1; } } /* * @see dwt.events.KeyListener#keyPressed(dwt.events.KeyEvent) */ public void keyPressed(KeyEvent event) { if (fActive) { deactivate(); return; } if (!isRegisteredStateMask(event.keyCode)) { deactivate(); return; } fActive= true; fActiveHyperlinkStateMask= event.keyCode; // removed for #25871 (hyperlinks could interact with typing) // // ITextViewer viewer= getSourceViewer(); // if (viewer is null) // return; // // IRegion region= getCurrentTextRegion(viewer); // if (region is null) // return; // // highlightRegion(viewer, region); // activateCursor(viewer); } /* * @see dwt.events.KeyListener#keyReleased(dwt.events.KeyEvent) */ public void keyReleased(KeyEvent event) { } /* * @see dwt.events.MouseListener#mouseDoubleClick(dwt.events.MouseEvent) */ public void mouseDoubleClick(MouseEvent e) { } /* * @see dwt.events.MouseListener#mouseDown(dwt.events.MouseEvent) */ public void mouseDown(MouseEvent event) { if (!fActive) return; if (event.stateMask !is fActiveHyperlinkStateMask) { deactivate(); return; } if (event.button !is 1) { deactivate(); return; } } /* * @see dwt.events.MouseListener#mouseUp(dwt.events.MouseEvent) */ public void mouseUp(MouseEvent e) { if (!fActive) { fActiveHyperlinks= null; return; } if (e.button !is 1) fActiveHyperlinks= null; deactivate(); if (fActiveHyperlinks !is null) fActiveHyperlinks[0].open(); } /* * @see dwt.events.MouseMoveListener#mouseMove(dwt.events.MouseEvent) */ public void mouseMove(MouseEvent event) { if ( cast(IHyperlinkPresenterExtension)fHyperlinkPresenter ) { if (!(cast(IHyperlinkPresenterExtension)fHyperlinkPresenter).canHideHyperlinks()) return; } if (!isRegisteredStateMask(event.stateMask)) { if (fActive) deactivate(); return; } fActive= true; fActiveHyperlinkStateMask= event.stateMask; StyledText text= fTextViewer.getTextWidget(); if (text is null || text.isDisposed()) { deactivate(); return; } if ((event.stateMask & DWT.BUTTON1) !is 0 && text.getSelectionCount() !is 0) { deactivate(); return; } fActiveHyperlinks= findHyperlinks(); if (fActiveHyperlinks is null || fActiveHyperlinks.length is 0) { fHyperlinkPresenter.hideHyperlinks(); return; } fHyperlinkPresenter.showHyperlinks(fActiveHyperlinks); } /** * Checks whether the given state mask is registered. * * @param stateMask * @return <code>true</code> if a detector is registered for the given state mask * @since 3.3 */ private bool isRegisteredStateMask(int stateMask) { if (stateMask is fHyperlinkStateMask) return true; synchronized (fHyperlinkDetectors) { for (int i= 0; i < fHyperlinkDetectors.length; i++) { if (cast(IHyperlinkDetectorExtension2)fHyperlinkDetectors[i] ) { if (stateMask is (cast(IHyperlinkDetectorExtension2)fHyperlinkDetectors[i]).getStateMask()) return true; } } } return false; } /* * @see dwt.events.FocusListener#focusGained(dwt.events.FocusEvent) */ public void focusGained(FocusEvent e) {} /* * @see dwt.events.FocusListener#focusLost(dwt.events.FocusEvent) */ public void focusLost(FocusEvent event) { deactivate(); } /* * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) * @since 3.2 */ public void handleEvent(Event event) { //key up deactivate(); } /* * @see dwtx.jface.text.ITextListener#textChanged(TextEvent) * @since 3.2 */ public void textChanged(TextEvent event) { if (event.getDocumentEvent() !is null) deactivate(); } /** * {@inheritDoc} * * @since 3.4 */ public void mouseExit(MouseEvent e) { if ( cast(IHyperlinkPresenterExtension)fHyperlinkPresenter ) { if (!(cast(IHyperlinkPresenterExtension)fHyperlinkPresenter).canHideHyperlinks()) return; } deactivate(); } /** * {@inheritDoc} * * @since 3.4 */ public void mouseEnter(MouseEvent e) { } /** * {@inheritDoc} * * @since 3.4 */ public void mouseHover(MouseEvent e) { } }