diff options
Diffstat (limited to 'visualizer/org.eclipse.cdt.visualizer.ui/src/org/eclipse/cdt/visualizer/ui/canvas/BufferedCanvas.java')
-rwxr-xr-x | visualizer/org.eclipse.cdt.visualizer.ui/src/org/eclipse/cdt/visualizer/ui/canvas/BufferedCanvas.java | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/visualizer/org.eclipse.cdt.visualizer.ui/src/org/eclipse/cdt/visualizer/ui/canvas/BufferedCanvas.java b/visualizer/org.eclipse.cdt.visualizer.ui/src/org/eclipse/cdt/visualizer/ui/canvas/BufferedCanvas.java new file mode 100755 index 00000000000..b4f2778cef4 --- /dev/null +++ b/visualizer/org.eclipse.cdt.visualizer.ui/src/org/eclipse/cdt/visualizer/ui/canvas/BufferedCanvas.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2012 Tilera 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: + * William R. Swanson (Tilera Corporation) + *******************************************************************************/ + +package org.eclipse.cdt.visualizer.ui.canvas; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + + +// --------------------------------------------------------------------------- +// BufferedCanvas +// --------------------------------------------------------------------------- + +/** Canvas control with double-buffering support. */ +public class BufferedCanvas extends Canvas + implements PaintListener, ControlListener +{ + // --- members --- + + /** double-buffering image */ + protected Image m_doubleBuffer = null; + + /** buffer GC */ + protected GC m_doubleBufferGC = null; + + + // --- constructors/destructors --- + + /** Constructor. */ + public BufferedCanvas(Composite parent) { + super(parent, + SWT.NO_BACKGROUND | // don't automatically clear background on paint event + SWT.NO_REDRAW_RESIZE // don't automatically repaint on resize event + ); + initBufferedCanvas(); + } + + /** Dispose method. */ + public void dispose() { + super.dispose(); + cleanupBufferedCanvas(); + } + + // --- init methods --- + + /** Initializes control. */ + protected void initBufferedCanvas() { + addControlListener(this); + addPaintListener(this); + } + + /** Cleans up control. */ + protected void cleanupBufferedCanvas() { + removePaintListener(this); + removeControlListener(this); + if (m_doubleBuffer != null) { + m_doubleBuffer.dispose(); + m_doubleBuffer = null; + } + } + + + // --- event handlers --- + + /** Invoked when control is moved/resized */ + public void controlMoved(ControlEvent e) { + // do nothing, we don't care + } + + /** Invoked when control is resized */ + public void controlResized(ControlEvent e) { + resized(getBounds()); + } + + + // --- resize methods --- + + /** Invoked when control is resized. + * Default implementation does nothing, + * intended to be overridden by derived types. + */ + public void resized(Rectangle bounds) { + + } + + + // --- GC management --- + + /** Gets/creates GC for current background buffer. + * NOTE: The GC is disposed whenever the canvas size changes, + * so caller should not retain a reference to this GC. + */ + protected synchronized GC getBufferedGC() { + if (m_doubleBufferGC == null) { + + m_doubleBufferGC = new GC(m_doubleBuffer); + } + return m_doubleBufferGC; + } + + /** Disposes of current background buffer GC. */ + protected synchronized void disposeBufferedGC() { + if (m_doubleBufferGC != null) { + m_doubleBufferGC.dispose(); + m_doubleBufferGC = null; + } + } + + + // --- paint methods --- + + /** Invoked when control needs to be repainted */ + public void paintControl(PaintEvent e) { + // Handle last paint event of a cluster. + if (e.count<=1) { + Display display = e.display; + GC gc = e.gc; + paintDoubleBuffered(display, gc); + } + } + + /** Internal -- handles double-buffering support, calls paintCanvas() */ + // NOTE: need display to create image buffer, not for painting code + protected void paintDoubleBuffered(Display display, GC gc) { + // get/create background image buffer + Rectangle clientArea = getClientArea(); + int width = clientArea.width; + int height = clientArea.height; + if (m_doubleBuffer == null + || m_doubleBuffer.getBounds().width < width + || m_doubleBuffer.getBounds().height < height) + { + m_doubleBuffer = new Image(display, width, height); + disposeBufferedGC(); + } + + // create graphics context for buffer + GC bgc = getBufferedGC(); + + // copy current GC properties into it as defaults + bgc.setBackground(gc.getBackground()); + bgc.setForeground(gc.getForeground()); + bgc.setFont(gc.getFont()); + bgc.setAlpha(255); + + // invoke paintCanvas() method to paint into the buffer + try {
+ paintCanvas(bgc);
+ }
+ catch (Throwable t) {
+ // Throwing an exception in painting code can hang Eclipse,
+ // so catch any exceptions here.
+ System.err.println("BufferedCanvas: Exception thrown in painting code: \n" + t);
+ } +
+ // then copy image buffer to actual canvas (reduces repaint flickering) + gc.drawImage(m_doubleBuffer, 0,0); + } + + /** Invoked when canvas repaint event is raised. + * Default implementation clears canvas to background color. + */ + public void paintCanvas(GC gc) { + clearCanvas(gc); + } + + /** Clears canvas to background color. */ + public void clearCanvas(GC gc) { + Rectangle bounds = getClientArea(); + gc.fillRectangle(bounds); + } + + + // --- update methods --- + + /** Redraws control */ + public void update() { + // guard against update events that happen + // after app has shut down + if (! isDisposed()) { + redraw(); + } + } +} |