source: other-projects/trunk/realistic-books/packages/AntInstaller/src/org/tp23/antinstaller/runtime/SwingRunner.java@ 19253

Last change on this file since 19253 was 19253, checked in by davidb, 15 years ago

Establishing a source code repository for Veronica's Realistic Book's software

File size: 11.6 KB
Line 
1/*
2 * Copyright 2005 Paul Hinds
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.tp23.antinstaller.runtime;
17
18import java.awt.GraphicsConfiguration;
19import java.io.ByteArrayOutputStream;
20import java.io.InputStream;
21import java.util.ArrayList;
22import java.util.List;
23import java.util.ResourceBundle;
24
25import javax.swing.ImageIcon;
26import javax.swing.JFrame;
27
28import org.tp23.antinstaller.InstallException;
29import org.tp23.antinstaller.Installer;
30import org.tp23.antinstaller.InstallerContext;
31import org.tp23.antinstaller.ValidationException;
32import org.tp23.antinstaller.antmod.FeedbackListener;
33import org.tp23.antinstaller.page.Page;
34import org.tp23.antinstaller.renderer.AntOutputRenderer;
35import org.tp23.antinstaller.renderer.RendererFactory;
36import org.tp23.antinstaller.renderer.swing.PageCompletionListener;
37import org.tp23.antinstaller.renderer.swing.SizeConstants;
38import org.tp23.antinstaller.renderer.swing.SwingInstallerContext;
39import org.tp23.antinstaller.renderer.swing.SwingMessageRenderer;
40import org.tp23.antinstaller.renderer.swing.SwingPageRenderer;
41
42/**
43 * <p>Runs the installer in a JFrame window </p>
44 * <p>This class uses the Installer object tree as its data source and renderers
45 * from the org.tp23.antinstaller.renderer.swing package </p>
46 * Runners must also create a MessageRenderer and make it available in the
47 * InstallerContext
48 * <p>Copyright: Copyright (c) 2004</p>
49 * <p>Company: tp23</p>
50 *
51 * @author Paul Hinds
52 * @version $Id: SwingRunner.java,v 1.11 2007/01/19 00:24:36 teknopaul Exp $
53 */
54public class SwingRunner extends AntRunner implements Runner, PageCompletionListener {
55
56 private static final ResourceBundle res = ResourceBundle.getBundle("org.tp23.antinstaller.renderer.Res");
57
58
59 protected SwingInstallerContext swingCtx = null;
60 private JFrame frame = new JFrame();
61 private List pageRenderers;
62 private volatile boolean doAnt = false;
63 protected Thread initialThread;
64 protected IfPropertyHelper ifHelper;
65 // context local property refs
66 protected InstallerContext ctx;
67 protected Logger logger;
68 protected Installer installer;
69
70 public SwingRunner(InstallerContext ctx) {
71 super(ctx);
72 swingCtx = new SwingInstallerContext(ctx, frame);
73
74 SwingMessageRenderer smr = new SwingMessageRenderer();
75 smr.setOwner(frame);
76 ctx.setMessageRenderer(smr);
77
78 ctx.setBuildListener(new FeedbackListener(swingCtx));
79
80 ifHelper = new IfPropertyHelper(ctx);
81 logger = ctx.getLogger();
82 installer = ctx.getInstaller();
83 this.ctx = ctx;
84 }
85
86 /**
87 * Renders the installer in a Swing GUI, this method blocks until
88 * the UI has finished
89 *
90 * @return boolean false implies user aborted
91 * @throws InstallException
92 */
93 public boolean runInstaller() throws InstallException {
94 try {
95 frame.setTitle(installer.getName());
96 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
97 frame.setSize(SizeConstants.PAGE_WIDTH, SizeConstants.PAGE_HEIGHT);
98 frame.getRootPane().setDoubleBuffered(true);
99 setLocation(frame);
100 setIcon(frame, installer);
101
102 preparePages(installer.getPages(), ctx);
103 showFirstPage();
104 // need to block here until pages are complete
105 initialThread = Thread.currentThread();
106 try {
107 Thread.sleep(Long.MAX_VALUE);
108 }
109 catch (InterruptedException ex1) {
110
111 }
112 return doAnt;
113 }
114 catch (Exception ex) {
115 logger.log("Fatal exception: " + ex.getMessage());
116 if (ctx.getInstaller().isVerbose()) {
117 logger.log(ex);
118 }
119 ctx.getMessageRenderer().printMessage("Fatal exception: " + ex.getMessage());
120 throw new InstallException("", ex);
121 }
122 }
123
124 public void pageBack(Page page) {
125 if (page.isAbort()) {
126 abort();
127 return;
128 }
129 Page[] pages = installer.getPages();
130 for (int i = 0; i < pages.length; i++) {
131 if (pages[i] == page) {
132 // found current page
133 if (i > 0) {
134
135 //skip pages if the ifTarget or ifProperty attributes exist and fail
136 int nextIdx = i - 1;
137 try {
138 while (true) {
139 if (!ifHelper.ifTarget(pages[nextIdx], pages) ||
140 !ifHelper.ifProperty(pages[nextIdx])) {
141 //Continue looping
142 --nextIdx;
143 } else {
144 break;
145 }
146 }
147 }
148 catch (InstallException instExc) {
149 logger.log("InstallException rendering page:" + page.getName());
150 logger.log(installer, instExc);
151 }
152
153 //for(;ifTargetSkip(pages[nextIdx], pages);nextIdx--);
154
155 SwingPageRenderer renderer = (SwingPageRenderer) pageRenderers.get(nextIdx);
156 ctx.setCurrentPage(pages[nextIdx]);
157 try {
158 renderNext(renderer);
159 }
160 catch (InstallException ex) {
161 logger.log("InstallExcepiton rendering page:" + page.getName());
162 logger.log(installer, ex);
163 }
164 catch (ClassNotFoundException ex) {
165 logger.log("ClassNotFoundException rendering page:" + page.getName());
166 logger.log(installer, ex);
167 }
168 return;
169 }
170 }
171 }
172 }
173
174 /**
175 * Called when a page is complete and the next button is pressed.
176 * This method is called by the event thread that looses exceptions so Throwable
177 * is caught
178 *
179 * @param page Page
180 */
181 public void pageComplete(Page page) {
182 try {
183 if (page.isAbort()) {
184 abort();
185 return;
186 }
187 runPost(page);
188 Page[] pages = installer.getPages();
189 SwingPageRenderer currentRenderer;
190 for (int i = 0; i < pages.length; i++) {
191 if (pages[i] == page) { // found current page
192 currentRenderer = (SwingPageRenderer) pageRenderers.get(i);
193 // check validation
194 boolean validationPassed = false;
195 try {
196 currentRenderer.updateInputFields();
197 validationPassed = currentRenderer.validateFields();
198 } catch (ValidationException ve) {
199 logger.log("ValidationException rendering page:" + page.getName());
200 logger.log(installer, ve);
201 return;
202 }
203 if (!validationPassed) {
204 return;
205 }
206
207
208 if (i < pages.length - 1) {
209
210 //more pages left
211
212 // skip the page if the ifTarget or ifProperty dictate it
213 int nextIdx = i + 1;
214 while (true) {
215 if (!ifHelper.ifTarget(pages[nextIdx], pages) ||
216 !ifHelper.ifProperty(pages[nextIdx])) {
217 //Continue looping
218 nextIdx++;
219 } else {
220 break;
221 }
222 }
223
224
225 SwingPageRenderer renderer = (SwingPageRenderer) pageRenderers.get(nextIdx);
226 ctx.setCurrentPage(pages[nextIdx]);
227 try {
228 renderNext(renderer);
229 }
230 catch (InstallException ex) {
231 logger.log("InstallException rendering page:" + page.getName());
232 logger.log(installer, ex);
233 }
234 catch (ClassNotFoundException ex) {
235 logger.log("ClassNotFoundException rendering page:" + page.getName());
236 logger.log(installer, ex);
237 }
238 return;
239 }
240 if (i == pages.length - 1) {
241 // all done
242 currentRenderer.getBackButton().setEnabled(false);
243 currentRenderer.getNextButton().setEnabled(false);
244 currentRenderer.getFinishButton().setEnabled(false);
245 doAnt = true;
246 initialThread.interrupt();
247 return;
248 }
249 }
250 }
251 }
252 catch (Throwable e) {
253 ctx.log("Throwable during page completion:" + e.getMessage());
254 if (ctx.getInstaller().isVerbose()) {
255 ctx.log(e);
256 }
257 }
258 }
259
260 protected void showFirstPage() throws Exception {
261 ctx.setCurrentPage(installer.getPages()[0]);
262 renderNext((SwingPageRenderer) pageRenderers.get(0));
263 }
264
265
266 private void preparePages(Page[] pages, InstallerContext ctx) throws Exception {
267 pageRenderers = new ArrayList();
268 for (int i = 0; i < pages.length; i++) {
269 SwingPageRenderer renderer = RendererFactory.getSwingPageRenderer(pages[i]);
270 if (i == 0) {
271 renderer.getBackButton().setEnabled(false);
272 }
273 renderer.setContext(swingCtx);
274 renderer.setPageCompletionListener(this);
275 renderer.setPage(pages[i]);
276 renderer.instanceInit();
277 pageRenderers.add(renderer);
278 if (renderer instanceof AntOutputRenderer) {
279 ctx.setAntOutputRenderer((AntOutputRenderer) renderer);
280 }
281 }
282 }
283
284 protected void renderNext(SwingPageRenderer renderer) throws ClassNotFoundException, InstallException {
285 renderer.updateDefaultValues();
286 frame.getContentPane().removeAll();
287 frame.getContentPane().add(renderer);
288 frame.getContentPane().repaint();
289 frame.show();
290 if (renderer.getNextButton().isEnabled()) {
291 renderer.getNextButton().requestFocus();
292 } else if (renderer.getFinishButton().isEnabled()) {
293 renderer.getFinishButton().requestFocus();
294 }
295 }
296
297 private void setLocation(JFrame frame) {
298 GraphicsConfiguration config = frame.getGraphicsConfiguration();
299 int x = (int) config.getBounds().getCenterX() - (SizeConstants.PAGE_WIDTH / 2);
300 int y = (int) config.getBounds().getCenterY() - (SizeConstants.PAGE_HEIGHT / 2);
301 frame.setLocation(x, y);
302 frame.setResizable(false);
303 }
304
305 private void setIcon(JFrame frame, Installer installer) {
306 String iconResource = installer.getWindowIcon();
307 try {
308 if (iconResource == null) {
309 return;
310 }
311 InputStream in = this.getClass().getResourceAsStream(iconResource);
312 ByteArrayOutputStream baos = new ByteArrayOutputStream();
313 byte[] buffer = new byte[256];
314 int read = 0; // The number of bytes read from the stream
315 for (read = in.read(buffer); read != -1; read = in.read(buffer)) {
316 baos.write(buffer, 0, read);
317 }
318 ImageIcon icon = new ImageIcon(baos.toByteArray());
319 //Image icon = Toolkit.getDefaultToolkit().createImage(baos.toByteArray());
320 frame.setIconImage(icon.getImage());
321 }
322 catch (Exception ex) {
323 // we can live with out an icon
324 logger.log("Can not load icon resource: " + iconResource);
325 logger.log(installer, ex);
326 }
327 }
328
329 public void antFinished() {
330 SwingPageRenderer renderer = (SwingPageRenderer) pageRenderers.get(pageRenderers.size() - 1);
331 renderer.getBackButton().setEnabled(false);
332 renderer.getNextButton().setEnabled(false);
333 renderer.getCancelButton().setEnabled(false);
334 renderer.getFinishButton().setText(res.getString("exit"));
335 renderer.getFinishButton().setEnabled(true);
336 renderer.getFinishButton().requestFocus();
337 renderer.getTitleLabel().setText(res.getString("complete"));
338 ctx.getAntOutputRenderer().getErr().flush();
339 ctx.getAntOutputRenderer().getOut().flush();
340 ctx.getMessageRenderer().printMessage(res.getString("finished"));
341 }
342
343 public void fatalError() {
344 List renderers = getPageRenderers();
345 if ((renderers != null) && (renderers.size() > 0)) {
346 SwingPageRenderer renderer = (SwingPageRenderer) renderers.get(renderers.size() - 1);
347 renderer.getBackButton().setEnabled(false);
348 renderer.getNextButton().setEnabled(false);
349 renderer.getCancelButton().setEnabled(false);
350 renderer.getFinishButton().setText(res.getString("exit"));
351 renderer.getFinishButton().setEnabled(true);
352 renderer.getFinishButton().requestFocus();
353 renderer.getTitleLabel().setText(res.getString("failed"));
354 }
355 // else - we're done here, or should we call abort()?
356 }
357
358 /**
359 * Returns a string representation of the object.
360 *
361 * @return a string representation of the object.
362 */
363 public String toString() {
364 return "SwingRunner";
365 }
366
367 private void abort() {
368 this.doAnt = false;
369 initialThread.interrupt();
370 }
371
372 /**
373 * @return Returns the frame.
374 */
375 public JFrame getFrame() {
376 return frame;
377 }
378
379 /**
380 * This method is only valid after the PageRenderers have been generated
381 *
382 * @return Returns the pageRenderers.
383 */
384 public List getPageRenderers() {
385 return pageRenderers;
386 }
387}
Note: See TracBrowser for help on using the repository browser.