Source code: com/arranger/jarl/base/RenderManager.java
1 package com.arranger.jarl.base;
2
3 import com.arranger.jarl.filter.IFilter;
4 import com.arranger.jarl.widget.IWidget;
5 import com.arranger.jarl.util.WidgetUtil;
6
7 import java.awt.*;
8 import java.util.*;
9 import java.util.List;
10
11 /**
12 * RenderManager created on Feb 19, 2003
13 */
14 public class RenderManager implements IRenderManager {
15
16 /**
17 * data structure to hold the current 'rendering' widgets
18 */
19 protected List m_currentWidgets = new LinkedList();
20
21 /**
22 * Currently registered widgets
23 */
24 protected List m_registeredWidgets = new LinkedList();
25
26 /**
27 * data structure to hold the current 'rendering' filters
28 */
29 protected List m_currentFilters = new LinkedList();
30
31 /**
32 * Currently registered filters
33 */
34 protected List m_registeredFilters = new LinkedList();
35
36 /**
37 * Current render listeners
38 */
39 protected Set m_renderListeners = new HashSet();
40
41 /**
42 * Have we prepped yet?
43 */
44 protected boolean m_preparedRendering = false;
45
46 /**
47 * Registers a widget to start recieving calls to
48 * {@link IWidget#paint} when the time reaches the time
49 * passed in.
50 *
51 * When a widget is done rendering it should call: {@link #unregister}
52 *
53 * @param widget the widget to register, will be registered at its start time
54 */
55 public void register(IWidget widget) {
56 m_registeredWidgets.add(widget);
57 }
58
59 /**
60 * Unregister this widget from further rendering
61 * @param widget the widget to unregister
62 */
63 public void unregister(IWidget widget) {
64 m_currentWidgets.remove(widget);
65 m_registeredWidgets.remove(widget);
66 }
67
68 /**
69 * Registers a filter to start recieving calls to
70 * When a filter is done rendering it should call: {@link #unregister}
71 *
72 * @param filter the filter to register, will be registered at its start time
73 */
74 public void register(IFilter filter) {
75 m_registeredFilters.add(filter);
76 }
77
78 /**
79 * Unregister this filter from further rendering
80 * @param filter the filter to unregister
81 */
82 public void unregister(IFilter filter) {
83 m_currentFilters.remove(filter);
84 m_registeredFilters.remove(filter);
85 }
86
87 /**
88 * @return registered widgets
89 */
90 public java.util.List getRegisteredWidgets() {
91 return m_registeredWidgets;
92 }
93
94 /**
95 * @return registered filters
96 */
97 public java.util.List getRegisteredFilters() {
98 return m_registeredFilters;
99 }
100
101 /**
102 * Render an image for this specific time
103 * @param context current context
104 * @return the rendered image
105 */
106 public Image render(IContext context) {
107 context.onStatus("rendering: " + context.getTime().toString());
108 context.getAttributes().clear();
109
110 //prepare the data structure
111 if (!m_preparedRendering) {
112 prepareRendering();
113 }
114
115 //see if we need to add any new IWidgets to the currentWidgets
116 checkTimedObject(context.getTime(), m_registeredWidgets, m_currentWidgets);
117 checkTimedObject(context.getTime(), m_registeredFilters, m_currentFilters);
118
119 //check this
120 WidgetUtil.sortBaseJarlObjectZOrder(m_currentWidgets);
121 WidgetUtil.sortBaseJarlObjectZOrder(m_currentFilters);
122
123 onRenderFrameStart(context);
124
125 //render
126 Image image = context.createImage();
127 Graphics2D graphics = (Graphics2D) image.getGraphics();
128 if (context.getRenderingHints() != null) {
129 graphics.setRenderingHints(context.getRenderingHints());
130 }
131 graphics.setStroke(context.getDefaultStroke());
132
133 for (Iterator it = ((LinkedList) ((LinkedList) m_currentWidgets).clone()).iterator(); it.hasNext();) {
134 IWidget widget = (IWidget) it.next();
135 onRender(widget, context);
136 widget.paint(context, graphics);
137 }
138 graphics.dispose();
139
140 for (Iterator it = ((LinkedList) ((LinkedList) m_currentFilters).clone()).iterator(); it.hasNext();) {
141 IFilter filter = (IFilter) it.next();
142 onRender(filter, context);
143 image = filter.filterImage(context, image);
144 }
145
146 onRenderFrameStop(context, image);
147
148 return image;
149 }
150
151 /**
152 * A special function that will only render one frame. At that point, it isn't valid
153 * @param context current context
154 * @param frame the frame to render
155 * @return the rendered image
156 */
157 public Image renderOneFrame(IContext context, int frame) {
158 Time currentTime = new Time(frame);
159 context.setAbsoluteTime(currentTime);
160
161 //prepare the data structure
162 if (!m_preparedRendering) {
163 prepareRendering();
164 }
165 m_currentWidgets.clear();
166 m_currentFilters.clear();
167
168 //we want to keep all the available widgets registered for later
169 LinkedList cachedRegisteredWidgets = (LinkedList) ((LinkedList) m_registeredWidgets).clone();
170 LinkedList cachedRegisteredFilters = (LinkedList) ((LinkedList) m_registeredFilters).clone();
171
172 Time time = new Time(0);
173 while (time.isLess(currentTime) || time.equals(currentTime)) {
174 checkTimedObject(time, m_registeredWidgets, m_currentWidgets);
175 checkTimedObject(time, m_registeredFilters, m_currentFilters);
176
177 for (Iterator it = ((LinkedList) ((LinkedList) m_currentWidgets).clone()).iterator(); it.hasNext();) {
178 IWidget widget = (IWidget) it.next();
179 if (time.isGreater(widget.getEndTime()) || time.equals(widget.getEndTime())) {
180 unregister(widget);
181 }
182 }
183
184 for (Iterator it = ((LinkedList) ((LinkedList) m_currentFilters).clone()).iterator(); it.hasNext();) {
185 IFilter filter = (IFilter) it.next();
186 if (time.isGreater(filter.getEndTime()) || time.equals(filter.getEndTime())) {
187 unregister(filter);
188 }
189 }
190
191 time.increment();
192 }
193
194 Image image = render(context);
195 m_registeredWidgets = cachedRegisteredWidgets;
196 m_registeredFilters = cachedRegisteredFilters;
197 return image;
198 }
199
200 /**
201 * Adds a render Listener
202 * @param renderListener
203 */
204 public void addRenderListener(IRenderListener renderListener) {
205 m_renderListeners.add(renderListener);
206 }
207
208 /**
209 * Removes a render Listener
210 * @param renderListener
211 */
212 public void removeRenderListener(IRenderListener renderListener) {
213 m_registeredFilters.remove(renderListener);
214 }
215
216 /**
217 * Check to see if we need to add any new widgets to the current Widgets
218 * @param time
219 */
220 protected void checkTimedObject(Time time, List registeredList, List currentList) {
221
222 for (Iterator it = registeredList.iterator(); it.hasNext();) {
223 ITimedJarlObject timedObj = (ITimedJarlObject) it.next();
224 if (time.equals(timedObj.getStartTime())) {
225 currentList.add(timedObj);
226 } else if (timedObj.getStartTime().isGreater(time)) {
227 break;
228 }
229 }
230 }
231
232 /**
233 * mainly just sort the registered widgets and filters
234 */
235 protected void prepareRendering() {
236 //widgets
237 IWidget[] widgets = new IWidget[m_registeredWidgets.size()];
238 widgets = (IWidget[]) m_registeredWidgets.toArray(widgets);
239 Arrays.sort(widgets, new TimedJarlObjectComparator());
240 m_registeredWidgets.clear();
241 for (int index = 0; index < widgets.length; index++) {
242 m_registeredWidgets.add(widgets[index]);
243 }
244
245 //filters
246 IFilter[] filters = new IFilter[m_registeredFilters.size()];
247 filters = (IFilter[]) m_registeredFilters.toArray(filters);
248 Arrays.sort(filters, new TimedJarlObjectComparator());
249 m_registeredFilters.clear();
250 for (int index = 0; index < filters.length; index++) {
251 m_registeredFilters.add(filters[index]);
252 }
253
254 m_preparedRendering = true;
255 }
256
257 public void onRender(IJarlObject jarlObject, IContext context) {
258 if (m_renderListeners.isEmpty()) {
259 return;
260 }
261 for (Iterator it = m_renderListeners.iterator(); it.hasNext();) {
262 ((IRenderListener) it.next()).onRender(jarlObject, context);
263 }
264 }
265
266 /**
267 * Frame start rendering
268 * @param context
269 */
270 public void onRenderFrameStart(IContext context) {
271 if (m_renderListeners.isEmpty()) {
272 return;
273 }
274 for (Iterator it = m_renderListeners.iterator(); it.hasNext();) {
275 ((IRenderListener) it.next()).onRenderFrameStart(context);
276 }
277 }
278
279 /**
280 * Frame stop rendering
281 * @param context
282 */
283 public void onRenderFrameStop(IContext context, Image image) {
284 if (m_renderListeners.isEmpty()) {
285 return;
286 }
287 for (Iterator it = m_renderListeners.iterator(); it.hasNext();) {
288 ((IRenderListener) it.next()).onRenderFrameStop(context, image);
289 }
290 }
291
292 protected static class TimedJarlObjectComparator implements Comparator {
293
294 public int compare(Object o1, Object o2) {
295 ITimedJarlObject timed1 = (ITimedJarlObject) o1;
296 ITimedJarlObject timed2 = (ITimedJarlObject) o2;
297 Time time1 = timed1.getStartTime();
298 Time time2 = timed2.getStartTime();
299
300 if (time1.equals(time2)) {
301 return 0;
302 } else if (time1.isLess(time2)) {
303 return -1;
304 } else {
305 return 1;
306 }
307 }
308 }
309 }