diff options
author | Starla Insigna <hatkirby@fourisland.com> | 2009-03-05 20:54:17 -0500 |
---|---|---|
committer | Starla Insigna <hatkirby@fourisland.com> | 2009-03-05 20:54:17 -0500 |
commit | a0f6cd976b8661eb608794ae169185b45b1b0a88 (patch) | |
tree | c737e11d81e4ad719ff6a7c17c38eb360add50e3 | |
parent | 82e91f3b85917f456214c121daa97ba65c7cce2a (diff) | |
download | fourpuzzle-a0f6cd976b8661eb608794ae169185b45b1b0a88.tar.gz fourpuzzle-a0f6cd976b8661eb608794ae169185b45b1b0a88.tar.bz2 fourpuzzle-a0f6cd976b8661eb608794ae169185b45b1b0a88.zip |
Engine: Created Message Escapes
Rewrote MessageWindow to render text through another class called TextRenderer, which takes settings and parses the text with its message escapes. The text-color-setting escape works perfectly but the pause escape doesn't. It works pretty well, except for some reason, if the escape is directly next to some text on the left, it won't be parsed. Also, the pause escape was implemented as \P rather than \| because | is a special character .in regular expressions. The variable-displaying escape was not added for two reasons: First of all, a dynamically introduced variable would mess up the generated layout and the text would not wrap correctly. Secondly, a much easier/better way of including a variable in a message than message escapes exists: Using string concatenation when writing the DisplayMessage() call. As FourPuzzle is a programming library, it is much more powerful than RM2K and clients need not resort to strange hacks such as message escapes to include variables in messages. Clients can include whatever dynamic data they wish in messages, rather than some predefined stuff RM2K provides. A small bug was discovered in PauseTimer that made it wait for it's underlying Interval to elapse before it could elapse, even if it had zero ticks remaining. This has been fixed. Closes #16
6 files changed, 420 insertions, 103 deletions
diff --git a/src/com/fourisland/fourpuzzle/util/PauseTimer.java b/src/com/fourisland/fourpuzzle/util/PauseTimer.java index 7d66d1a..f26f105 100644 --- a/src/com/fourisland/fourpuzzle/util/PauseTimer.java +++ b/src/com/fourisland/fourpuzzle/util/PauseTimer.java | |||
@@ -29,12 +29,12 @@ public class PauseTimer { | |||
29 | 29 | ||
30 | if (in.isElapsed()) | 30 | if (in.isElapsed()) |
31 | { | 31 | { |
32 | if (ticks == 0) | 32 | ticks--; |
33 | { | 33 | } |
34 | return true; | 34 | |
35 | } else { | 35 | if (ticks <= 0) |
36 | ticks--; | 36 | { |
37 | } | 37 | return true; |
38 | } | 38 | } |
39 | 39 | ||
40 | return false; | 40 | return false; |
diff --git a/src/com/fourisland/fourpuzzle/window/ChoiceWindow.java b/src/com/fourisland/fourpuzzle/window/ChoiceWindow.java index 4926a6d..90f2d96 100755 --- a/src/com/fourisland/fourpuzzle/window/ChoiceWindow.java +++ b/src/com/fourisland/fourpuzzle/window/ChoiceWindow.java | |||
@@ -79,7 +79,7 @@ public class ChoiceWindow implements Renderable { | |||
79 | g2.drawImage(Window.Selector.getImage(fw-Window.Selector.getLeftX(), fh-Window.Selector.getTopY()), tx-SPACER, ty-fh-SPACER, null); | 79 | g2.drawImage(Window.Selector.getImage(fw-Window.Selector.getLeftX(), fh-Window.Selector.getTopY()), tx-SPACER, ty-fh-SPACER, null); |
80 | } | 80 | } |
81 | 81 | ||
82 | g2.setPaint(new TexturePaint(SystemGraphic.getTextColor(), new Rectangle(tx, ty, fw, fh))); | 82 | g2.setPaint(new TexturePaint(SystemGraphic.getTextColor(0), new Rectangle(tx, ty, fw, fh))); |
83 | g2.drawString(choice, tx, ty); | 83 | g2.drawString(choice, tx, ty); |
84 | 84 | ||
85 | ty+=(SPACER+fh); | 85 | ty+=(SPACER+fh); |
diff --git a/src/com/fourisland/fourpuzzle/window/MessageEscape.java b/src/com/fourisland/fourpuzzle/window/MessageEscape.java new file mode 100644 index 0000000..2ae55b2 --- /dev/null +++ b/src/com/fourisland/fourpuzzle/window/MessageEscape.java | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * To change this template, choose Tools | Templates | ||
3 | * and open the template in the editor. | ||
4 | */ | ||
5 | |||
6 | package com.fourisland.fourpuzzle.window; | ||
7 | |||
8 | import java.util.regex.MatchResult; | ||
9 | import java.util.regex.Matcher; | ||
10 | import java.util.regex.Pattern; | ||
11 | |||
12 | |||
13 | /** | ||
14 | * | ||
15 | * @author hatkirby | ||
16 | */ | ||
17 | public enum MessageEscape | ||
18 | { | ||
19 | Color("\\\\C\\[(\\d+)\\]"), | ||
20 | Pause("\\\\P"); | ||
21 | |||
22 | private Pattern pattern; | ||
23 | private MessageEscape(String pattern) | ||
24 | { | ||
25 | this.pattern = Pattern.compile(pattern); | ||
26 | } | ||
27 | |||
28 | public static String removeEscapes(String message) | ||
29 | { | ||
30 | for (MessageEscape escape : values()) | ||
31 | { | ||
32 | message = escape.pattern.matcher(message).replaceAll(""); | ||
33 | } | ||
34 | |||
35 | return message; | ||
36 | } | ||
37 | |||
38 | public boolean match(String substring) | ||
39 | { | ||
40 | Matcher m = pattern.matcher(substring); | ||
41 | |||
42 | return (m.lookingAt() && (m.start() == 0)); | ||
43 | } | ||
44 | |||
45 | public String removeEscape(String message) | ||
46 | { | ||
47 | return pattern.matcher(message).replaceFirst(""); | ||
48 | } | ||
49 | |||
50 | MessageEscapePair getMatch(String substring) | ||
51 | { | ||
52 | Matcher m = pattern.matcher(substring); | ||
53 | m.lookingAt(); | ||
54 | |||
55 | return new MessageEscapePair(this, m.toMatchResult()); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | class MessageEscapePair | ||
60 | { | ||
61 | MessageEscape escape; | ||
62 | MatchResult match; | ||
63 | |||
64 | public MessageEscapePair(MessageEscape escape, MatchResult match) | ||
65 | { | ||
66 | this.escape = escape; | ||
67 | this.match = match; | ||
68 | } | ||
69 | |||
70 | public MessageEscape getMessageEscape() | ||
71 | { | ||
72 | return escape; | ||
73 | } | ||
74 | |||
75 | public MatchResult getMatchResult() | ||
76 | { | ||
77 | return match; | ||
78 | } | ||
79 | } \ No newline at end of file | ||
diff --git a/src/com/fourisland/fourpuzzle/window/MessageWindow.java b/src/com/fourisland/fourpuzzle/window/MessageWindow.java index dab67d1..709704a 100644 --- a/src/com/fourisland/fourpuzzle/window/MessageWindow.java +++ b/src/com/fourisland/fourpuzzle/window/MessageWindow.java | |||
@@ -14,11 +14,7 @@ import com.fourisland.fourpuzzle.util.Inputable; | |||
14 | import com.fourisland.fourpuzzle.util.Interval; | 14 | import com.fourisland.fourpuzzle.util.Interval; |
15 | import com.fourisland.fourpuzzle.util.Renderable; | 15 | import com.fourisland.fourpuzzle.util.Renderable; |
16 | import java.awt.Graphics2D; | 16 | import java.awt.Graphics2D; |
17 | import java.awt.Rectangle; | ||
18 | import java.awt.TexturePaint; | ||
19 | import java.awt.image.BufferedImage; | 17 | import java.awt.image.BufferedImage; |
20 | import java.util.ArrayList; | ||
21 | import java.util.List; | ||
22 | import java.util.concurrent.CountDownLatch; | 18 | import java.util.concurrent.CountDownLatch; |
23 | 19 | ||
24 | /** | 20 | /** |
@@ -30,10 +26,9 @@ public class MessageWindow implements Renderable { | |||
30 | private static final int SPACER = 4; | 26 | private static final int SPACER = 4; |
31 | private static final int HEIGHT = (4*(Display.getFontMetrics().getHeight()+SPACER)); | 27 | private static final int HEIGHT = (4*(Display.getFontMetrics().getHeight()+SPACER)); |
32 | 28 | ||
33 | private volatile List<String> messages; | 29 | TextRenderer tr; |
34 | int width; | 30 | int width; |
35 | BufferedImage cacheBase; | 31 | BufferedImage cacheBase; |
36 | int num = 0; | ||
37 | int upTo = 0; | 32 | int upTo = 0; |
38 | boolean bounceArrow = false; | 33 | boolean bounceArrow = false; |
39 | Interval in = Interval.createTickInterval(4); | 34 | Interval in = Interval.createTickInterval(4); |
@@ -42,7 +37,9 @@ public class MessageWindow implements Renderable { | |||
42 | width = Game.WIDTH - Window.Default.getFullWidth(0); | 37 | width = Game.WIDTH - Window.Default.getFullWidth(0); |
43 | cacheBase = Window.Default.getImage(width, HEIGHT); | 38 | cacheBase = Window.Default.getImage(width, HEIGHT); |
44 | 39 | ||
45 | initalizeMessages(message); | 40 | tr = new TextRenderer(width); |
41 | tr.setEscapes(true); | ||
42 | tr.initalizeText(message); | ||
46 | } | 43 | } |
47 | 44 | ||
48 | boolean hasFace = false; | 45 | boolean hasFace = false; |
@@ -55,7 +52,10 @@ public class MessageWindow implements Renderable { | |||
55 | this.face = FaceSet.getFaceSet(faceSet).getImage(face); | 52 | this.face = FaceSet.getFaceSet(faceSet).getImage(face); |
56 | hasFace = true; | 53 | hasFace = true; |
57 | 54 | ||
58 | initalizeMessages(message); | 55 | tr = new TextRenderer(width); |
56 | tr.setEscapes(true); | ||
57 | tr.setIndent(48 + (SPACER*2)); | ||
58 | tr.initalizeText(message); | ||
59 | } | 59 | } |
60 | 60 | ||
61 | private static void displayMessage(final MessageWindow mw) throws InterruptedException | 61 | private static void displayMessage(final MessageWindow mw) throws InterruptedException |
@@ -101,96 +101,24 @@ public class MessageWindow implements Renderable { | |||
101 | displayMessage(new MessageWindow(message, faceSet, face)); | 101 | displayMessage(new MessageWindow(message, faceSet, face)); |
102 | } | 102 | } |
103 | 103 | ||
104 | private void initalizeMessages(String message) | ||
105 | { | ||
106 | messages = new ArrayList<String>(); | ||
107 | |||
108 | int length = width - SPACER; | ||
109 | if (hasFace) | ||
110 | { | ||
111 | length -= (48 + (SPACER*3)); | ||
112 | } | ||
113 | |||
114 | String temp = message; | ||
115 | int len = 0; | ||
116 | while (!temp.isEmpty()) | ||
117 | { | ||
118 | while ((Display.getFontMetrics().stringWidth(temp.substring(0, len)) < length) && (len < temp.length())) | ||
119 | { | ||
120 | len++; | ||
121 | } | ||
122 | |||
123 | if (len != temp.length()) | ||
124 | { | ||
125 | while ((!temp.substring(len, len+1).equals(" ")) && (len > 0)) | ||
126 | { | ||
127 | len--; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | messages.add(temp.substring(0, len)); | ||
132 | |||
133 | if (len != temp.length()) | ||
134 | { | ||
135 | temp = temp.substring(len+1); | ||
136 | } else { | ||
137 | temp = ""; | ||
138 | } | ||
139 | |||
140 | len = 0; | ||
141 | } | ||
142 | |||
143 | setLength(); | ||
144 | } | ||
145 | |||
146 | private void setLength() | ||
147 | { | ||
148 | num = 0; | ||
149 | |||
150 | for (int i=0;i<Math.min(messages.size(),4);i++) | ||
151 | { | ||
152 | num += messages.get(i).length(); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | public void render(Graphics2D g2) | 104 | public void render(Graphics2D g2) |
157 | { | 105 | { |
158 | int y = MessageWindowLocation.Bottom.getY(); | 106 | int y = MessageWindowLocation.Bottom.getY(); |
159 | |||
160 | Display.setFont(g2); | ||
161 | 107 | ||
162 | g2.drawImage(cacheBase, 0, y, null); | 108 | g2.drawImage(cacheBase, 0, y, null); |
163 | 109 | ||
164 | int fh = g2.getFontMetrics().getHeight(); | 110 | int fh = g2.getFontMetrics().getHeight(); |
165 | int tx = Window.Default.getLeftX(); | ||
166 | int ty = Window.Default.getTopY()+fh-(SPACER/2)+y; | 111 | int ty = Window.Default.getTopY()+fh-(SPACER/2)+y; |
167 | int msgs = Math.min(messages.size(), 4); | ||
168 | int toPrint = upTo; | ||
169 | 112 | ||
170 | if (hasFace) | 113 | if (hasFace) |
171 | { | 114 | { |
172 | g2.drawImage(face, tx+SPACER, ty-fh+SPACER, null); | 115 | g2.drawImage(face, Window.Default.getLeftX()+SPACER, ty-fh+SPACER, null); |
173 | |||
174 | tx += 48 + (SPACER*2); | ||
175 | } | 116 | } |
176 | 117 | ||
177 | for (int i=0;i<msgs;i++) | 118 | g2.drawImage(tr.render(upTo), Window.Default.getLeftX(), Window.Default.getTopY()+y, null); |
178 | { | ||
179 | String message = messages.get(i); | ||
180 | int fw = g2.getFontMetrics().stringWidth(message); | ||
181 | |||
182 | g2.setPaint(new TexturePaint(SystemGraphic.getTextColor(), new Rectangle(tx, ty, fw, fh))); | ||
183 | g2.drawString(message.substring(0, Math.min(toPrint, message.length())), tx, ty); | ||
184 | |||
185 | ty+=(SPACER+fh); | ||
186 | |||
187 | toPrint -= Math.min(toPrint, message.length()); | ||
188 | } | ||
189 | 119 | ||
190 | if (upTo < num) | 120 | if (tr.isCascadingDone()) |
191 | { | 121 | { |
192 | upTo+=3; | ||
193 | } else { | ||
194 | g2.drawImage(SystemGraphic.getDownArrow(), (Window.Default.getFullWidth(width)/2)-5, y+HEIGHT+SPACER+(bounceArrow ? 1 : 0), null); | 122 | g2.drawImage(SystemGraphic.getDownArrow(), (Window.Default.getFullWidth(width)/2)-5, y+HEIGHT+SPACER+(bounceArrow ? 1 : 0), null); |
195 | 123 | ||
196 | if (in.isElapsed()) | 124 | if (in.isElapsed()) |
@@ -202,20 +130,19 @@ public class MessageWindow implements Renderable { | |||
202 | 130 | ||
203 | private synchronized boolean pushEnter() | 131 | private synchronized boolean pushEnter() |
204 | { | 132 | { |
205 | if (upTo >= num) | 133 | if (tr.isCascadingDone()) |
206 | { | 134 | { |
207 | int msgs = messages.size(); | 135 | int msgs = tr.numLines(); |
208 | for (int i=0;i<Math.min(4, msgs);i++) | 136 | if (upTo >= (msgs-4)) |
209 | { | 137 | { |
210 | messages.remove(0); | ||
211 | } | ||
212 | |||
213 | if (messages.size() > 0) | ||
214 | { | ||
215 | upTo = 0; | ||
216 | setLength(); | ||
217 | } else { | ||
218 | return true; | 138 | return true; |
139 | } else { | ||
140 | upTo += 4; | ||
141 | |||
142 | if (upTo > msgs) | ||
143 | { | ||
144 | upTo = msgs; | ||
145 | } | ||
219 | } | 146 | } |
220 | } | 147 | } |
221 | 148 | ||
diff --git a/src/com/fourisland/fourpuzzle/window/SystemGraphic.java b/src/com/fourisland/fourpuzzle/window/SystemGraphic.java index 75e2b45..aa0b593 100755 --- a/src/com/fourisland/fourpuzzle/window/SystemGraphic.java +++ b/src/com/fourisland/fourpuzzle/window/SystemGraphic.java | |||
@@ -64,14 +64,19 @@ public class SystemGraphic { | |||
64 | return systemGraphic.getSubimage(sca.x, sca.y, sca.width, sca.height); | 64 | return systemGraphic.getSubimage(sca.x, sca.y, sca.width, sca.height); |
65 | } | 65 | } |
66 | 66 | ||
67 | public static BufferedImage getTextColor() | 67 | public static BufferedImage getTextColor(int color) |
68 | { | 68 | { |
69 | if (systemGraphic == null) | 69 | if (systemGraphic == null) |
70 | { | 70 | { |
71 | initalize(); | 71 | initalize(); |
72 | } | 72 | } |
73 | 73 | ||
74 | return systemGraphic.getSubimage(0, 48, 16, 16); | 74 | if (color < 10) |
75 | { | ||
76 | return systemGraphic.getSubimage(color*16, 48, 16, 16); | ||
77 | } else { | ||
78 | return systemGraphic.getSubimage(color*16, 64, 16, 16); | ||
79 | } | ||
75 | } | 80 | } |
76 | 81 | ||
77 | public static BufferedImage getUpArrow() | 82 | public static BufferedImage getUpArrow() |
diff --git a/src/com/fourisland/fourpuzzle/window/TextRenderer.java b/src/com/fourisland/fourpuzzle/window/TextRenderer.java new file mode 100644 index 0000000..f114c4d --- /dev/null +++ b/src/com/fourisland/fourpuzzle/window/TextRenderer.java | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * To change this template, choose Tools | Templates | ||
3 | * and open the template in the editor. | ||
4 | */ | ||
5 | |||
6 | package com.fourisland.fourpuzzle.window; | ||
7 | |||
8 | import com.fourisland.fourpuzzle.Display; | ||
9 | import com.fourisland.fourpuzzle.Game; | ||
10 | import com.fourisland.fourpuzzle.util.PauseTimer; | ||
11 | import java.awt.Graphics2D; | ||
12 | import java.awt.Rectangle; | ||
13 | import java.awt.TexturePaint; | ||
14 | import java.awt.image.BufferedImage; | ||
15 | import java.util.ArrayList; | ||
16 | import java.util.HashMap; | ||
17 | import java.util.List; | ||
18 | import java.util.Map; | ||
19 | import java.util.Vector; | ||
20 | |||
21 | /** | ||
22 | * | ||
23 | * @author hatkirby | ||
24 | */ | ||
25 | public class TextRenderer { | ||
26 | |||
27 | private static final int SPACER = 4; | ||
28 | |||
29 | private boolean initalized = false; | ||
30 | private int width; | ||
31 | private List<LineOfText> messages = new ArrayList<LineOfText>(); | ||
32 | |||
33 | public TextRenderer(int width) | ||
34 | { | ||
35 | this.width = width; | ||
36 | } | ||
37 | |||
38 | private boolean useEscapes = false; | ||
39 | public void setEscapes(boolean use) | ||
40 | { | ||
41 | if (initalized == true) | ||
42 | { | ||
43 | throw new IllegalStateException("Already initalized"); | ||
44 | } | ||
45 | |||
46 | useEscapes = use; | ||
47 | } | ||
48 | |||
49 | private int indent = 0; | ||
50 | public void setIndent(int indent) | ||
51 | { | ||
52 | if (initalized == true) | ||
53 | { | ||
54 | throw new IllegalStateException("Already initalized"); | ||
55 | } | ||
56 | |||
57 | this.indent = indent; | ||
58 | } | ||
59 | |||
60 | public void initalizeText(String message) | ||
61 | { | ||
62 | if (initalized == true) | ||
63 | { | ||
64 | throw new IllegalStateException("Already initalized"); | ||
65 | } | ||
66 | |||
67 | int length = width - SPACER - indent; | ||
68 | int len = 0; | ||
69 | LineOfText temp = new LineOfText(message); | ||
70 | |||
71 | if (useEscapes) | ||
72 | { | ||
73 | for (int i=0; i<temp.length(); i++) | ||
74 | { | ||
75 | if (temp.toString().substring(i, i+1).equals("\\")) | ||
76 | { | ||
77 | for (MessageEscape escape : MessageEscape.values()) | ||
78 | { | ||
79 | if (escape.match(temp.toString().substring(i))) | ||
80 | { | ||
81 | temp.addEscape(i, escape.getMatch(temp.toString().substring(i))); | ||
82 | temp = new LineOfText(escape.removeEscape(temp.toString()), temp.escapes); | ||
83 | |||
84 | break; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | temp = new LineOfText(MessageEscape.removeEscapes(temp.toString()), temp.escapes); | ||
91 | } | ||
92 | |||
93 | while (!temp.toString().isEmpty()) | ||
94 | { | ||
95 | while ((Display.getFontMetrics().stringWidth(temp.toString().substring(0, len)) < length) && (len < temp.length())) | ||
96 | { | ||
97 | len++; | ||
98 | } | ||
99 | |||
100 | if (len != temp.toString().length()) | ||
101 | { | ||
102 | while ((!temp.toString().substring(len, len+1).equals(" ")) && (len > 0)) | ||
103 | { | ||
104 | len--; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | messages.add(temp.part(0, len)); | ||
109 | |||
110 | if (len != temp.length()) | ||
111 | { | ||
112 | temp = temp.part(len+1, temp.length()); | ||
113 | } else { | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | len = 0; | ||
118 | } | ||
119 | |||
120 | initalized = true; | ||
121 | } | ||
122 | |||
123 | int upTo = Integer.MIN_VALUE; | ||
124 | int num = 0; | ||
125 | int lastStart = Integer.MIN_VALUE+1; | ||
126 | PauseTimer pt = new PauseTimer(0); | ||
127 | public BufferedImage render(int start) | ||
128 | { | ||
129 | if (initalized == false) | ||
130 | { | ||
131 | throw new IllegalStateException("TextRenderer must be initalized prior to rendering"); | ||
132 | } | ||
133 | |||
134 | if (lastStart != start) | ||
135 | { | ||
136 | num = 0; | ||
137 | for (int i=start;i<Math.min(messages.size(),start+4);i++) | ||
138 | { | ||
139 | num += messages.get(i).length(); | ||
140 | } | ||
141 | |||
142 | lastStart = start; | ||
143 | upTo = 0; | ||
144 | } | ||
145 | |||
146 | BufferedImage temp = Display.createCanvas(width, Game.HEIGHT); | ||
147 | Graphics2D g = temp.createGraphics(); | ||
148 | Display.setFont(g); | ||
149 | |||
150 | int currentColor = 0; | ||
151 | |||
152 | int fh = g.getFontMetrics().getHeight(); | ||
153 | int ty = fh-(SPACER/2); | ||
154 | int toPrint = upTo; | ||
155 | int end = Math.min(messages.size(), start+4); | ||
156 | |||
157 | for (int i=start;i<end;i++) | ||
158 | { | ||
159 | LineOfText message = messages.get(i); | ||
160 | int tx = indent; | ||
161 | g.setPaint(new TexturePaint(SystemGraphic.getTextColor(currentColor), new Rectangle(0, ty, width, fh))); | ||
162 | |||
163 | for (int j=0;j<Math.min(toPrint, message.length());j++) | ||
164 | { | ||
165 | boolean breakout = false; | ||
166 | for (MessageEscapePair escape : message.getEscapes(j)) | ||
167 | { | ||
168 | switch (escape.getMessageEscape()) | ||
169 | { | ||
170 | case Color: currentColor = Integer.decode(escape.getMatchResult().group(1)); | ||
171 | g.setPaint(new TexturePaint(SystemGraphic.getTextColor(currentColor), new Rectangle(0, ty, width, fh))); | ||
172 | |||
173 | break; | ||
174 | |||
175 | case Pause: pt.setTimer(10); | ||
176 | message.getEscapes(j).remove(escape); | ||
177 | |||
178 | breakout = true; | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | if (breakout) | ||
183 | { | ||
184 | break; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | g.drawString(message.toString().substring(j, j+1), tx, ty); | ||
189 | |||
190 | tx+=(g.getFontMetrics().stringWidth(message.toString().substring(j, j+1))); | ||
191 | } | ||
192 | |||
193 | ty+=(SPACER+fh); | ||
194 | |||
195 | toPrint -= Math.min(toPrint, message.length()); | ||
196 | } | ||
197 | |||
198 | if (pt.isElapsed() && (upTo < num)) | ||
199 | { | ||
200 | upTo+=3; | ||
201 | } | ||
202 | |||
203 | return temp; | ||
204 | } | ||
205 | |||
206 | public int numLines() | ||
207 | { | ||
208 | return messages.size(); | ||
209 | } | ||
210 | |||
211 | public boolean isCascadingDone() | ||
212 | { | ||
213 | return (upTo >= num); | ||
214 | } | ||
215 | |||
216 | } | ||
217 | |||
218 | class LineOfText implements CharSequence | ||
219 | { | ||
220 | String line; | ||
221 | Map<Integer, Vector<MessageEscapePair>> escapes = new HashMap<Integer, Vector<MessageEscapePair>>(); | ||
222 | public LineOfText(String line) | ||
223 | { | ||
224 | this.line = line; | ||
225 | } | ||
226 | |||
227 | public LineOfText(String line, Map<Integer, Vector<MessageEscapePair>> escapes) | ||
228 | { | ||
229 | this.line = line; | ||
230 | |||
231 | for (int i=0; i<line.length(); i++) | ||
232 | { | ||
233 | if (escapes.containsKey(i)) | ||
234 | { | ||
235 | for (MessageEscapePair escape : escapes.get(i)) | ||
236 | { | ||
237 | addEscape(i, escape); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | public void addEscape(int index, MessageEscapePair escape) | ||
244 | { | ||
245 | if (!escapes.containsKey(index)) | ||
246 | { | ||
247 | escapes.put(index, new Vector<MessageEscapePair>()); | ||
248 | } | ||
249 | |||
250 | escapes.get(index).add(escape); | ||
251 | } | ||
252 | |||
253 | public Vector<MessageEscapePair> getEscapes(int index) | ||
254 | { | ||
255 | if (!escapes.containsKey(index)) | ||
256 | { | ||
257 | return new Vector<MessageEscapePair>(); | ||
258 | } else { | ||
259 | return escapes.get(index); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | public LineOfText part(int start, int end) | ||
264 | { | ||
265 | LineOfText temp = new LineOfText(line.substring(start, end)); | ||
266 | |||
267 | for (int i=start; i<end; i++) | ||
268 | { | ||
269 | if (escapes.containsKey(i)) | ||
270 | { | ||
271 | for (MessageEscapePair escape : escapes.get(i)) | ||
272 | { | ||
273 | temp.addEscape(i, escape); | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | return temp; | ||
279 | } | ||
280 | |||
281 | @Override | ||
282 | public String toString() | ||
283 | { | ||
284 | return line; | ||
285 | } | ||
286 | |||
287 | public void setString(String message) | ||
288 | { | ||
289 | this.line = message; | ||
290 | } | ||
291 | |||
292 | public int length() | ||
293 | { | ||
294 | return line.length(); | ||
295 | } | ||
296 | |||
297 | public char charAt(int index) | ||
298 | { | ||
299 | return line.charAt(index); | ||
300 | } | ||
301 | |||
302 | public CharSequence subSequence(int start, int end) | ||
303 | { | ||
304 | return line.subSequence(start, end); | ||
305 | } | ||
306 | } \ No newline at end of file | ||