[1097] | 1 | package org.expeditee.gio;
|
---|
| 2 |
|
---|
| 3 | import java.util.Stack;
|
---|
| 4 |
|
---|
| 5 | import org.expeditee.core.Clip;
|
---|
| 6 | import org.expeditee.core.EnforcedClipStack;
|
---|
[1163] | 7 | import org.expeditee.core.EnforcedClipStack.EnforcedClipKey;
|
---|
[1097] | 8 | import org.expeditee.core.Image;
|
---|
| 9 |
|
---|
| 10 | /**
|
---|
| 11 | * Helper-class for the graphics manager to maintain a stack of drawing
|
---|
[1142] | 12 | * surfaces. Should be sub-typed by the platform-specific graphics manager to
|
---|
| 13 | * use the appropriate surface class.
|
---|
[1097] | 14 | */
|
---|
| 15 | public abstract class GraphicsSurfaceStack<T> {
|
---|
| 16 |
|
---|
| 17 | /** The root surface corresponds to drawing directly into the window. */
|
---|
| 18 | private T _rootSurface;
|
---|
| 19 | /** The surface that drawing commands should draw into. */
|
---|
| 20 | private T _currentSurface;
|
---|
| 21 | /** The stack of drawing surfaces. */
|
---|
| 22 | private Stack<T> _surfaceStack;
|
---|
| 23 | /** The image that produced the current drawing surface. */
|
---|
| 24 | private Image _currentImage;
|
---|
| 25 | /** The stack of images that produced the surfaces in the surface stack. */
|
---|
| 26 | private Stack<Image> _imageStack;
|
---|
| 27 | /** The clip-stack for the root surface. */
|
---|
| 28 | private EnforcedClipStack _rootClipStack;
|
---|
| 29 | /** The clip-stack for the current surface. */
|
---|
| 30 | private EnforcedClipStack _currentClipStack;
|
---|
| 31 | /** The clip-stack for each drawing surface. */
|
---|
| 32 | private Stack<EnforcedClipStack> _clipStackStack;
|
---|
[1142] | 33 |
|
---|
[1097] | 34 | /** Constructor specifying no root surface. */
|
---|
[1142] | 35 | public GraphicsSurfaceStack() {
|
---|
[1097] | 36 | this(null);
|
---|
| 37 | }
|
---|
[1142] | 38 |
|
---|
[1097] | 39 | /** Constructor specifying the root surface. */
|
---|
[1142] | 40 | public GraphicsSurfaceStack(T rootSurface) {
|
---|
[1097] | 41 | setRootSurface(rootSurface);
|
---|
| 42 | _currentImage = null;
|
---|
| 43 | _surfaceStack = new Stack<T>();
|
---|
| 44 | _imageStack = new Stack<Image>();
|
---|
| 45 | _rootClipStack = _currentClipStack = new EnforcedClipStack();
|
---|
| 46 | _clipStackStack = new Stack<EnforcedClipStack>();
|
---|
| 47 | }
|
---|
[1142] | 48 |
|
---|
| 49 | /**
|
---|
| 50 | * Should be overridden by sub-types to allow a drawing surface to be extracted
|
---|
| 51 | * from an image.
|
---|
| 52 | */
|
---|
[1097] | 53 | public abstract T getSurfaceFromImage(Image image);
|
---|
[1142] | 54 |
|
---|
| 55 | /**
|
---|
| 56 | * Should be overridden by sub-types to set the actual clip on a given surface.
|
---|
| 57 | */
|
---|
[1097] | 58 | public abstract void setSurfaceClip(T surface, Clip clip);
|
---|
[1142] | 59 |
|
---|
| 60 | /**
|
---|
| 61 | * Pushes a new image onto the stack, and sets it as the current drawing
|
---|
| 62 | * surface.
|
---|
| 63 | */
|
---|
| 64 | public void push(Image image) {
|
---|
[1163] | 65 | if (image == null) {
|
---|
[1142] | 66 | return;
|
---|
[1163] | 67 | }
|
---|
| 68 |
|
---|
[1097] | 69 | _currentSurface = getSurfaceFromImage(image);
|
---|
| 70 | _currentImage = image;
|
---|
| 71 | _currentClipStack = new EnforcedClipStack();
|
---|
| 72 | _surfaceStack.push(_currentSurface);
|
---|
| 73 | _imageStack.push(image);
|
---|
| 74 | _clipStackStack.push(_currentClipStack);
|
---|
[1163] | 75 |
|
---|
[1097] | 76 | }
|
---|
[1142] | 77 |
|
---|
| 78 | /**
|
---|
| 79 | * Removes an image from the stack. The removed image is returned, or null if
|
---|
| 80 | * the root surface was current.
|
---|
| 81 | */
|
---|
| 82 | public Image pop() {
|
---|
[1163] | 83 | if (_surfaceStack.isEmpty()) {
|
---|
[1142] | 84 | return null;
|
---|
[1163] | 85 | }
|
---|
[1142] | 86 |
|
---|
[1097] | 87 | Image oldTop = _imageStack.pop();
|
---|
| 88 | _surfaceStack.pop();
|
---|
| 89 | _clipStackStack.pop();
|
---|
[1142] | 90 |
|
---|
[1097] | 91 | if (!_surfaceStack.isEmpty()) {
|
---|
| 92 | _currentSurface = _surfaceStack.peek();
|
---|
| 93 | _currentImage = _imageStack.peek();
|
---|
| 94 | _currentClipStack = _clipStackStack.peek();
|
---|
| 95 | } else {
|
---|
| 96 | _currentSurface = _rootSurface;
|
---|
| 97 | _currentImage = null;
|
---|
| 98 | _currentClipStack = _rootClipStack;
|
---|
| 99 | }
|
---|
[1142] | 100 |
|
---|
[1097] | 101 | return oldTop;
|
---|
| 102 | }
|
---|
[1142] | 103 |
|
---|
[1097] | 104 | /** Gets a reference to the current drawing surface. */
|
---|
[1142] | 105 | public T getCurrentSurface() {
|
---|
[1097] | 106 | return _currentSurface;
|
---|
| 107 | }
|
---|
[1142] | 108 |
|
---|
[1097] | 109 | /** Gets a reference to the top image on the stack. */
|
---|
[1142] | 110 | public Image getCurrentImage() {
|
---|
[1097] | 111 | return _currentImage;
|
---|
| 112 | }
|
---|
[1142] | 113 |
|
---|
| 114 | /**
|
---|
| 115 | * Pushes a new clip onto the stack, ensuring that it is a sub-area of the top
|
---|
| 116 | * of the stack.
|
---|
| 117 | */
|
---|
| 118 | public EnforcedClipKey pushClip(Clip clip) {
|
---|
[1097] | 119 | EnforcedClipKey key = _currentClipStack.push(clip);
|
---|
[1163] | 120 | if (key != null) {
|
---|
[1142] | 121 | ensureClip();
|
---|
[1163] | 122 | }
|
---|
[1097] | 123 | return key;
|
---|
| 124 | }
|
---|
[1142] | 125 |
|
---|
| 126 | /**
|
---|
| 127 | * Pops the top of the current clip-stack if there given key corresponds to it.
|
---|
| 128 | */
|
---|
| 129 | public Clip popClip(EnforcedClipKey key) {
|
---|
[1097] | 130 | Clip clip = _currentClipStack.pop(key);
|
---|
[1163] | 131 | if (clip != null) {
|
---|
[1142] | 132 | ensureClip();
|
---|
[1163] | 133 | }
|
---|
[1097] | 134 | return clip;
|
---|
| 135 | }
|
---|
[1142] | 136 |
|
---|
[1097] | 137 | /** Returns a copy of the top of the current clip-stack. */
|
---|
[1142] | 138 | public Clip peekClip() {
|
---|
[1097] | 139 | return _currentClipStack.peek();
|
---|
| 140 | }
|
---|
[1142] | 141 |
|
---|
[1097] | 142 | /** Ensures the current clip is applied to the underlying surface. */
|
---|
[1142] | 143 | public void ensureClip() {
|
---|
[1097] | 144 | setSurfaceClip(_currentSurface, _currentClipStack.peek());
|
---|
| 145 | }
|
---|
[1142] | 146 |
|
---|
[1097] | 147 | /** Updates the root surface. Does not affect any stacked image surfaces. */
|
---|
[1142] | 148 | public void setRootSurface(T rootSurface) {
|
---|
[1163] | 149 | if (_currentSurface == _rootSurface) {
|
---|
[1142] | 150 | _currentSurface = rootSurface;
|
---|
[1163] | 151 | }
|
---|
[1097] | 152 | _rootSurface = rootSurface;
|
---|
[1142] | 153 |
|
---|
[1097] | 154 | }
|
---|
| 155 | }
|
---|