1 | package org.expeditee.core;
|
---|
2 |
|
---|
3 | import java.util.Stack;
|
---|
4 |
|
---|
5 | public class EnforcedClipStack {
|
---|
6 |
|
---|
7 | /** The stack of sub-area clips. */
|
---|
8 | private Stack<Clip> _clipStack;
|
---|
9 |
|
---|
10 | /** Default constructor. */
|
---|
11 | public EnforcedClipStack()
|
---|
12 | {
|
---|
13 | _clipStack = new Stack<Clip>();
|
---|
14 | }
|
---|
15 |
|
---|
16 | /** Pushes a new clip onto the stack, ensuring that it is a sub-area of the top of the stack. */
|
---|
17 | public EnforcedClipKey push(Clip clip)
|
---|
18 | {
|
---|
19 | // No null clips allowed
|
---|
20 | if (clip == null) return null;
|
---|
21 |
|
---|
22 | // Leave the given clip unchanged (in case the provider wants to keep using it)
|
---|
23 | clip = clip.clone();
|
---|
24 |
|
---|
25 | // Each clip must be a sub-area of the one below it in the stack
|
---|
26 | if (!_clipStack.isEmpty()) {
|
---|
27 | clip.intersectWith(_clipStack.peek());
|
---|
28 | }
|
---|
29 |
|
---|
30 | // Put the new clip on the stack
|
---|
31 | _clipStack.push(clip);
|
---|
32 |
|
---|
33 | // Return the clipped area
|
---|
34 | return EnforcedClipKey.get(clip);
|
---|
35 | }
|
---|
36 |
|
---|
37 | /** Pops the top of the stack if there given key corresponds to it. */
|
---|
38 | public Clip pop(EnforcedClipKey key)
|
---|
39 | {
|
---|
40 | if (!_clipStack.isEmpty() && key != null && key.matches(_clipStack.peek())) return _clipStack.pop();
|
---|
41 |
|
---|
42 | return null;
|
---|
43 | }
|
---|
44 |
|
---|
45 | /** Returns a copy of the current top of the stack. */
|
---|
46 | public Clip peek()
|
---|
47 | {
|
---|
48 | if (!_clipStack.isEmpty()) return _clipStack.peek().clone();
|
---|
49 |
|
---|
50 | return null;
|
---|
51 | }
|
---|
52 |
|
---|
53 | /** Key class to ensure only the owner of a given pushed clip can pop it again. */
|
---|
54 | public static class EnforcedClipKey {
|
---|
55 |
|
---|
56 | /** The clip this key corresponds to. */
|
---|
57 | private Clip _keyedClip;
|
---|
58 |
|
---|
59 | /** Gets a key for the given clip. */
|
---|
60 | public static EnforcedClipKey get(Clip clip)
|
---|
61 | {
|
---|
62 | if (clip == null) return null;
|
---|
63 |
|
---|
64 | return new EnforcedClipKey(clip);
|
---|
65 | }
|
---|
66 |
|
---|
67 | /** Private constructor so clip cannot be null. */
|
---|
68 | private EnforcedClipKey(Clip clip)
|
---|
69 | {
|
---|
70 | _keyedClip = clip;
|
---|
71 | }
|
---|
72 |
|
---|
73 | /** Whether this key corresponds to the given clip. */
|
---|
74 | public boolean matches(Clip clip)
|
---|
75 | {
|
---|
76 | return clip == _keyedClip;
|
---|
77 | }
|
---|
78 |
|
---|
79 | }
|
---|
80 |
|
---|
81 | }
|
---|