Mercurial > projects > dwt-addons
diff dwtx/jface/text/PaintManager.d @ 129:eb30df5ca28b
Added JFace Text sources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 19:10:48 +0200 |
parents | |
children | c4fb132a086c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/text/PaintManager.d Sat Aug 23 19:10:48 2008 +0200 @@ -0,0 +1,385 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.jface.text.PaintManager; + +import dwt.dwthelper.utils; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dwt.custom.StyledText; +import dwt.events.KeyEvent; +import dwt.events.KeyListener; +import dwt.events.MouseEvent; +import dwt.events.MouseListener; +import dwt.widgets.Control; +import dwtx.jface.viewers.ISelectionChangedListener; +import dwtx.jface.viewers.ISelectionProvider; +import dwtx.jface.viewers.SelectionChangedEvent; + + +/** + * Manages the {@link dwtx.jface.text.IPainter} object registered with an + * {@link dwtx.jface.text.ITextViewer}. + * <p> + * Clients usually instantiate and configure objects of this type.</p> + * + * @since 2.1 + */ +public final class PaintManager : KeyListener, MouseListener, ISelectionChangedListener, ITextListener, ITextInputListener { + + /** + * Position updater used by the position manager. This position updater differs from the default position + * updater in that it extends a position when an insertion happens at the position's offset and right behind + * the position. + */ + static class PaintPositionUpdater : DefaultPositionUpdater { + + /** + * Creates the position updater for the given category. + * + * @param category the position category + */ + protected PaintPositionUpdater(String category) { + super(category); + } + + /** + * If an insertion happens at a position's offset, the + * position is extended rather than shifted. Also, if something is added + * right behind the end of the position, the position is extended rather + * than kept stable. + */ + protected void adaptToInsert() { + + int myStart= fPosition.offset; + int myEnd= fPosition.offset + fPosition.length; + myEnd= Math.max(myStart, myEnd); + + int yoursStart= fOffset; + int yoursEnd= fOffset + fReplaceLength;// - 1; + yoursEnd= Math.max(yoursStart, yoursEnd); + + if (myEnd < yoursStart) + return; + + if (myStart <= yoursStart) + fPosition.length += fReplaceLength; + else + fPosition.offset += fReplaceLength; + } + } + + /** + * The paint position manager used by this paint manager. The paint position + * manager is installed on a single document and control the creation/disposed + * and updating of a position category that will be used for managing positions. + */ + static class PositionManager : IPaintPositionManager { + +// /** The document this position manager works on */ + private IDocument fDocument; + /** The position updater used for the managing position category */ + private IPositionUpdater fPositionUpdater; + /** The managing position category */ + private String fCategory; + + /** + * Creates a new position manager. Initializes the managing + * position category using its class name and its hash value. + */ + public PositionManager() { + fCategory= getClass().getName() + hashCode(); + fPositionUpdater= new PaintPositionUpdater(fCategory); + } + + /** + * Installs this position manager in the given document. The position manager stays + * active until <code>uninstall</code> or <code>dispose</code> + * is called. + * + * @param document the document to be installed on + */ + public void install(IDocument document) { + fDocument= document; + fDocument.addPositionCategory(fCategory); + fDocument.addPositionUpdater(fPositionUpdater); + } + + /** + * Disposes this position manager. The position manager is automatically + * removed from the document it has previously been installed + * on. + */ + public void dispose() { + uninstall(fDocument); + } + + /** + * Uninstalls this position manager form the given document. If the position + * manager has no been installed on this document, this method is without effect. + * + * @param document the document form which to uninstall + */ + public void uninstall(IDocument document) { + if (document is fDocument && document !is null) { + try { + fDocument.removePositionUpdater(fPositionUpdater); + fDocument.removePositionCategory(fCategory); + } catch (BadPositionCategoryException x) { + // should not happen + } + fDocument= null; + } + } + + /* + * @see IPositionManager#addManagedPosition(Position) + */ + public void managePosition(Position position) { + try { + fDocument.addPosition(fCategory, position); + } catch (BadPositionCategoryException x) { + // should not happen + } catch (BadLocationException x) { + // should not happen + } + } + + /* + * @see IPositionManager#removeManagedPosition(Position) + */ + public void unmanagePosition(Position position) { + try { + fDocument.removePosition(fCategory, position); + } catch (BadPositionCategoryException x) { + // should not happen + } + } + } + + + /** The painters managed by this paint manager. */ + private List fPainters= new ArrayList(2); + /** The position manager used by this paint manager */ + private PositionManager fManager; + /** The associated text viewer */ + private ITextViewer fTextViewer; + + /** + * Creates a new paint manager for the given text viewer. + * + * @param textViewer the text viewer associated to this newly created paint manager + */ + public PaintManager(ITextViewer textViewer) { + fTextViewer= textViewer; + } + + + /** + * Adds the given painter to the list of painters managed by this paint manager. + * If the painter is already registered with this paint manager, this method is + * without effect. + * + * @param painter the painter to be added + */ + public void addPainter(IPainter painter) { + if (!fPainters.contains(painter)) { + fPainters.add(painter); + if (fPainters.size() is 1) + install(); + painter.setPositionManager(fManager); + painter.paint(IPainter.INTERNAL); + } + } + + /** + * Removes the given painter from the list of painters managed by this + * paint manager. If the painter has not previously been added to this + * paint manager, this method is without effect. + * + * @param painter the painter to be removed + */ + public void removePainter(IPainter painter) { + if (fPainters.remove(painter)) { + painter.deactivate(true); + painter.setPositionManager(null); + } + if (fPainters.size() is 0) + dispose(); + } + + /** + * Installs/activates this paint manager. Is called as soon as the + * first painter is to be managed by this paint manager. + */ + private void install() { + + fManager= new PositionManager(); + if (fTextViewer.getDocument() !is null) + fManager.install(fTextViewer.getDocument()); + + fTextViewer.addTextInputListener(this); + + addListeners(); + } + + /** + * Installs our listener set on the text viewer and the text widget, + * respectively. + */ + private void addListeners() { + ISelectionProvider provider= fTextViewer.getSelectionProvider(); + provider.addSelectionChangedListener(this); + + fTextViewer.addTextListener(this); + + StyledText text= fTextViewer.getTextWidget(); + text.addKeyListener(this); + text.addMouseListener(this); + } + + /** + * Disposes this paint manager. The paint manager uninstalls itself + * and clears all registered painters. This method is also called when the + * last painter is removed from the list of managed painters. + */ + public void dispose() { + + if (fManager !is null) { + fManager.dispose(); + fManager= null; + } + + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).dispose(); + fPainters.clear(); + + fTextViewer.removeTextInputListener(this); + + removeListeners(); + } + + /** + * Removes our set of listeners from the text viewer and widget, + * respectively. + */ + private void removeListeners() { + ISelectionProvider provider= fTextViewer.getSelectionProvider(); + if (provider !is null) + provider.removeSelectionChangedListener(this); + + fTextViewer.removeTextListener(this); + + StyledText text= fTextViewer.getTextWidget(); + if (text !is null && !text.isDisposed()) { + text.removeKeyListener(this); + text.removeMouseListener(this); + } + } + + /** + * Triggers all registered painters for the given reason. + * + * @param reason the reason + * @see IPainter + */ + private void paint(int reason) { + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).paint(reason); + } + + /* + * @see KeyListener#keyPressed(KeyEvent) + */ + public void keyPressed(KeyEvent e) { + paint(IPainter.KEY_STROKE); + } + + /* + * @see KeyListener#keyReleased(KeyEvent) + */ + public void keyReleased(KeyEvent e) { + } + + /* + * @see MouseListener#mouseDoubleClick(MouseEvent) + */ + public void mouseDoubleClick(MouseEvent e) { + } + + /* + * @see MouseListener#mouseDown(MouseEvent) + */ + public void mouseDown(MouseEvent e) { + paint(IPainter.MOUSE_BUTTON); + } + + /* + * @see MouseListener#mouseUp(MouseEvent) + */ + public void mouseUp(MouseEvent e) { + } + + /* + * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + paint(IPainter.SELECTION); + } + + /* + * @see ITextListener#textChanged(TextEvent) + */ + public void textChanged(TextEvent event) { + + if (!event.getViewerRedrawState()) + return; + + Control control= fTextViewer.getTextWidget(); + if (control !is null) { + control.getDisplay().asyncExec(new Runnable() { + public void run() { + if (fTextViewer !is null) + paint(IPainter.TEXT_CHANGE); + } + }); + } + } + + /* + * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument, IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput !is null) { + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).deactivate(false); + fManager.uninstall(oldInput); + removeListeners(); + } + } + + /* + * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput !is null) { + fManager.install(newInput); + paint(IPainter.TEXT_CHANGE); + addListeners(); + } + } +} +