source: release-kits/shared/ant-installer/src/org/tp23/antinstaller/runtime/SwingRunner.java@ 17516

Last change on this file since 17516 was 17516, checked in by oranfry, 16 years ago

made pages reinitialise just before they are shown and added an option to selectinput to change the locale, the end result of this being that you can change the language of the installer as it runs

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