Source code: com/port80/swt/apps/ImageViewer.java
1 package com.port80.swt.apps;
2
3 import java.io.InputStream;
4 import java.net.URL;
5 import java.text.MessageFormat;
6
7 import org.eclipse.swt.SWT;
8 import org.eclipse.swt.SWTException;
9 import org.eclipse.swt.custom.StyledText;
10 import org.eclipse.swt.events.ControlAdapter;
11 import org.eclipse.swt.events.ControlEvent;
12 import org.eclipse.swt.events.DisposeEvent;
13 import org.eclipse.swt.events.DisposeListener;
14 import org.eclipse.swt.events.MouseEvent;
15 import org.eclipse.swt.events.MouseMoveListener;
16 import org.eclipse.swt.events.PaintEvent;
17 import org.eclipse.swt.events.PaintListener;
18 import org.eclipse.swt.events.SelectionAdapter;
19 import org.eclipse.swt.events.SelectionEvent;
20 import org.eclipse.swt.events.ShellAdapter;
21 import org.eclipse.swt.events.ShellEvent;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.graphics.Cursor;
24 import org.eclipse.swt.graphics.Font;
25 import org.eclipse.swt.graphics.GC;
26 import org.eclipse.swt.graphics.Image;
27 import org.eclipse.swt.graphics.ImageData;
28 import org.eclipse.swt.graphics.ImageLoader;
29 import org.eclipse.swt.graphics.RGB;
30 import org.eclipse.swt.graphics.Rectangle;
31 import org.eclipse.swt.layout.GridData;
32 import org.eclipse.swt.layout.GridLayout;
33 import org.eclipse.swt.layout.RowLayout;
34 import org.eclipse.swt.widgets.Button;
35 import org.eclipse.swt.widgets.Canvas;
36 import org.eclipse.swt.widgets.Combo;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Dialog;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.FileDialog;
41 import org.eclipse.swt.widgets.Label;
42 import org.eclipse.swt.widgets.Menu;
43 import org.eclipse.swt.widgets.MenuItem;
44 import org.eclipse.swt.widgets.MessageBox;
45 import org.eclipse.swt.widgets.Sash;
46 import org.eclipse.swt.widgets.ScrollBar;
47 import org.eclipse.swt.widgets.Shell;
48 import org.eclipse.swt.widgets.Text;
49
50 import com.port80.eclipse.util.UIUtil;
51 import com.port80.util.Sprint;
52 import com.port80.util.SystemWatch;
53
54 /**
55 * An image viewer using swt.
56 *
57 * <li>A GC can be created on an Image and then use it to draw into the Image.</li>
58 * <li>To display very large image, pixel data is loaded into ImageData and then
59 * tiles of the data are used to create Image's for display.</li>
60 * <li>The current development version, for now, this is same as ImageViewer1.</li>
61 *
62 * @author chrisl
63 */
64 public class ImageViewer {
65
66 ////////////////////////////////////////////////////////////////////////
67
68 private static final String NAME = "ImageViewer";
69
70 private static final String[] IMAGE_SUFFICES =
71 new String[] {
72 "*.bmp; *.gif; *.ico; *.jpg; *.pcx; *.png; *.tif",
73 "*.bmp",
74 "*.gif",
75 "*.ico",
76 "*.jpg",
77 "*.pcx",
78 "*.png",
79 "*.tif" };
80
81 private static final String[] IMAGE_FILTER_NAMES =
82 new String[] {
83 i18n("All_images") + " (bmp, gif, ico, jpg, pcx, png, tif)",
84 "BMP (*.bmp)",
85 "GIF (*.gif)",
86 "ICO (*.ico)",
87 "JPEG (*.jpg)",
88 "PCX (*.pcx)",
89 "PNG (*.png)",
90 "TIFF (*.tif)" };
91
92 ////////////////////////////////////////////////////////////////////////
93
94 private Display fDisplay;
95 private Shell fShell;
96 private Font fFont;
97 private Color fWhiteColor, fBlackColor, fLightColor;
98 private Cursor fCrossCursor;
99 private GC fImageCanvasGC;
100 private Image fImage;
101 private ImageData[] fImageDatas;
102 private ImageData fImageData; // the currently-displayed image data
103 private int fImageDataIndex;
104 private double fScale;
105 private int fX = 0, fY = 0; // Top left corner, used to scroll the image and palette
106 private String fLastPath;
107 private boolean fTransparent, fShowMask;
108 private boolean fIncremental;
109 //
110 private long fLoadTime;
111 private String fFilename;
112 //
113 // Widgets
114 private Combo fScaleCombo;
115 private Canvas fImageCanvas;
116 private Sash fSash;
117 private Label fDataLabel, fStatusLabel;
118 private StyledText fDataText;
119 private Label fInfoLabel;
120 //
121 private boolean isResizing;
122
123 ////////////////////////////////////////////////////////////////////////
124
125 public static void main(String[] args) {
126
127 Display display = new Display();
128 ImageViewer app = new ImageViewer();
129 Shell shell = app.open(display);
130
131 while (!shell.isDisposed())
132 if (!display.readAndDispatch())
133 display.sleep();
134 display.dispose();
135 }
136
137 ////////////////////////////////////////////////////////////////////////
138
139 public Shell open(Display display) {
140
141 // Create a window and set its title.
142 this.fDisplay = display;
143 this.fShell = new Shell(fDisplay);
144
145 // Create colors and fonts.
146 fWhiteColor = new Color(display, 255, 255, 255);
147 fBlackColor = new Color(display, 0, 0, 0);
148 fLightColor = new Color(display, 0xd8, 0xd8, 0xd8);
149 fFont = new Font(display, "verdana", 11, 0);
150 fCrossCursor = new Cursor(display, SWT.CURSOR_CROSS);
151
152 fShell.setText(NAME);
153
154 // Hook resize and dispose listeners.
155 fShell.addControlListener(new ControlAdapter() {
156 public void controlResized(ControlEvent event) {
157 resizeShell(event);
158 }
159 });
160 fShell.addShellListener(new ShellAdapter() {
161 public void shellClosed(ShellEvent e) {
162 e.doit = true;
163 }
164 });
165 fShell.addDisposeListener(new DisposeListener() {
166 public void widgetDisposed(DisposeEvent e) {
167 dispose();
168 }
169 });
170
171 // Add a menu bar and widgets.
172 createMenuBar();
173 createWidgets();
174 fShell.pack();
175
176 // Create a GC for drawing, and hook the listener to dispose it.
177 fImageCanvasGC = new GC(fImageCanvas);
178 fImageCanvas.addDisposeListener(new DisposeListener() {
179 public void widgetDisposed(DisposeEvent e) {
180 disposeImageCanvasGC();
181 }
182 });
183
184 // Open the window
185 fShell.open();
186 return fShell;
187 }
188
189 void dispose() {
190 // Clean up.
191 fWhiteColor.dispose();
192 fBlackColor.dispose();
193 fLightColor.dispose();
194 fFont.dispose();
195 fCrossCursor.dispose();
196 }
197
198 void disposeImageCanvasGC() {
199 fImageCanvasGC.dispose();
200 }
201
202 Shell getShell() {
203 return fShell;
204 }
205
206 Display getDisplay() {
207 return fDisplay;
208 }
209
210 void createWidgets() {
211 // Add the widgets to the shell in a grid layout.
212 GridLayout layout = new GridLayout();
213 layout.marginHeight = 0;
214 layout.numColumns = 2;
215 fShell.setLayout(layout);
216
217 // Add a composite to contain some control widgets across the top.
218 Composite controls = new Composite(fShell, SWT.NULL);
219 RowLayout rowLayout = new RowLayout();
220 rowLayout.marginTop = 2;
221 rowLayout.marginBottom = 2;
222 rowLayout.spacing = 8;
223 controls.setLayout(rowLayout);
224 controls.setLayoutData(UIUtil.fillCell(1, 1, false, false));
225
226 // RowLayout is top aligned. To make label text at middle, need to set label height.
227 fInfoLabel = new Label(fShell, SWT.NULL);
228 fInfoLabel.setToolTipText("Image info");
229 fInfoLabel.setText("Image info");
230 fInfoLabel.setLayoutData(UIUtil.fillCell(1, 1, true, false));
231 // Combo to change the x scale.
232 String[] values =
233 {
234 "5 %",
235 "10 %",
236 "25 %",
237 "33 %",
238 "50 %",
239 "75 %",
240 "100 %",
241 "125 %",
242 "133 %",
243 "150 %",
244 "175 %",
245 "200 %",
246 "300 %",
247 "500 %",
248 "750 %",
249 "1000 %",
250 };
251 fScaleCombo = new Combo(controls, SWT.DROP_DOWN);
252 for (int i = 0; i < values.length; i++) {
253 fScaleCombo.add(values[i]);
254 }
255 fScaleCombo.setToolTipText("Scale");
256 fScaleCombo.select(fScaleCombo.indexOf("100 %"));
257 fScaleCombo.addSelectionListener(new SelectionAdapter() {
258 public void widgetSelected(SelectionEvent event) {
259 scaleImage();
260 }
261 });
262
263 // Canvas to show the image.
264 fImageCanvas = new Canvas(fShell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE);
265 fImageCanvas.setBackground(fWhiteColor);
266 fImageCanvas.setCursor(fCrossCursor);
267 fImageCanvas.setLayoutData(UIUtil.fillCell(15, 2, 1024, 768, true, true));
268 fImageCanvas.addPaintListener(new PaintListener() {
269 public void paintControl(PaintEvent event) {
270 paintImage(event);
271 }
272 });
273 fImageCanvas.addMouseMoveListener(new MouseMoveListener() {
274 public void mouseMove(MouseEvent event) {
275 showColorAt(event.x, event.y);
276 }
277 });
278
279 // Set up the image canvas scroll bars.
280 ScrollBar horizontal = fImageCanvas.getHorizontalBar();
281 horizontal.setVisible(true);
282 horizontal.setMinimum(0);
283 horizontal.setEnabled(false);
284 horizontal.addSelectionListener(new SelectionAdapter() {
285 public void widgetSelected(SelectionEvent event) {
286 scrollHorizontally((ScrollBar) event.widget);
287 }
288 });
289 ScrollBar vertical = fImageCanvas.getVerticalBar();
290 vertical.setVisible(true);
291 vertical.setMinimum(0);
292 vertical.setEnabled(false);
293 vertical.addSelectionListener(new SelectionAdapter() {
294 public void widgetSelected(SelectionEvent event) {
295 scrollVertically((ScrollBar) event.widget);
296 }
297 });
298
299 // Label to show status and cursor location in image.
300 fStatusLabel = new Label(fShell, SWT.NULL);
301 fStatusLabel.setText("");
302 fStatusLabel.setLayoutData(UIUtil.fillCell(1, 2, true, false));
303 }
304
305 Menu createMenuBar() {
306 // Menu bar.
307 Menu menuBar = new Menu(fShell, SWT.BAR);
308 fShell.setMenuBar(menuBar);
309 createFileMenu(menuBar);
310 return menuBar;
311 }
312
313 void createFileMenu(Menu menuBar) {
314 // File menu
315 MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
316 item.setText("File");
317 Menu fileMenu = new Menu(fShell, SWT.DROP_DOWN);
318 item.setMenu(fileMenu);
319
320 item = new MenuItem(fileMenu, SWT.NULL);
321 item.setText("&Open");
322 item.setAccelerator(SWT.CTRL + 'O');
323 item.addSelectionListener(new SelectionAdapter() {
324 public void widgetSelected(SelectionEvent event) {
325 openFile();
326 }
327 });
328
329 item = new MenuItem(fileMenu, SWT.NULL);
330 item.setText("Open &URL");
331 item.setAccelerator(SWT.CTRL + 'U');
332 item.addSelectionListener(new SelectionAdapter() {
333 public void widgetSelected(SelectionEvent event) {
334 openURL();
335 }
336 });
337
338 new MenuItem(fileMenu, SWT.SEPARATOR);
339
340 // File -> Exit
341 item = new MenuItem(fileMenu, SWT.NULL);
342 item.setText("Exit");
343 item.addSelectionListener(new SelectionAdapter() {
344 public void widgetSelected(SelectionEvent event) {
345 getShell().close();
346 }
347 });
348
349 // Test menu
350 item = new MenuItem(menuBar, SWT.CASCADE);
351
352 }
353
354 ////////////////////////////////////////////////////////////////////////
355
356 void openFile() {
357 resetScaleCombo();
358
359 // Get the user to choose an image file.
360 FileDialog fileChooser = new FileDialog(fShell, SWT.OPEN);
361 if (fLastPath != null)
362 fileChooser.setFilterPath(fLastPath);
363 fileChooser.setFilterExtensions(IMAGE_SUFFICES);
364 fileChooser.setFilterNames(IMAGE_FILTER_NAMES);
365 String filename = fileChooser.open();
366 fLastPath = fileChooser.getFilterPath();
367 if (filename == null)
368 return;
369
370 Cursor waitCursor = new Cursor(fDisplay, SWT.CURSOR_WAIT);
371 fShell.setCursor(waitCursor);
372 fImageCanvas.setCursor(waitCursor);
373 try {
374 clear();
375 ImageLoader loader = new ImageLoader();
376 // Read the new image(s) from the chosen file.
377 SystemWatch timer = new SystemWatch().start();
378 long startTime = System.currentTimeMillis();
379 fImageDatas = loader.load(filename);
380 fLoadTime = System.currentTimeMillis() - startTime;
381 System.err.println(NAME + ".open(): load time=" + timer.stop().toString());
382 if (fImageDatas.length > 0) {
383 // Cache the filename.
384 fFilename = filename;
385
386 // Display the first image in the file.
387 fImageDataIndex = 0;
388 displayImage(fImageDatas[fImageDataIndex]);
389 resetScrollBars();
390 }
391 } catch (SWTException e) {
392 showErrorDialog(i18n("Loading_lc"), filename, e);
393 } finally {
394 fShell.setCursor(null);
395 fImageCanvas.setCursor(fCrossCursor);
396 waitCursor.dispose();
397 }
398 }
399
400 void openURL() {
401 resetScaleCombo();
402
403 // Get the user to choose an image URL.
404 TextPrompter textPrompter = new TextPrompter(fShell, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
405 textPrompter.setText(i18n("OpenURLDialog"));
406 textPrompter.setMessage(i18n("EnterURL"));
407 String urlname = textPrompter.open();
408 if (urlname == null)
409 return;
410
411 Cursor waitCursor = new Cursor(fDisplay, SWT.CURSOR_WAIT);
412 fShell.setCursor(waitCursor);
413 fImageCanvas.setCursor(waitCursor);
414 try {
415 clear();
416 URL url = new URL(urlname);
417 InputStream stream = url.openStream();
418 ImageLoader loader = new ImageLoader();
419 // Read the new image(s) from the chosen file.
420 long startTime = System.currentTimeMillis();
421 fImageDatas = loader.load(stream);
422 fLoadTime = System.currentTimeMillis() - startTime;
423 if (fImageDatas.length > 0) {
424 fFilename = null;
425 // Display the first image in the file.
426 fImageDataIndex = 0;
427 displayImage(fImageDatas[fImageDataIndex]);
428 resetScrollBars();
429 }
430 } catch (Exception e) {
431 showErrorDialog(i18n("Loading_lc"), urlname, e);
432 } finally {
433 fShell.setCursor(null);
434 fImageCanvas.setCursor(fCrossCursor);
435 waitCursor.dispose();
436 }
437 }
438
439 void displayImage(ImageData newImageData) {
440 // Dispose of the old image, if there was one.
441 if (fImage != null)
442 fImage.dispose();
443
444 try {
445 // Cache the new image and imageData.
446 fImage = new Image(fDisplay, newImageData);
447 fImageData = newImageData;
448 } catch (SWTException e) {
449 showErrorDialog(i18n("Creating_from") + " ", fFilename, e);
450 fImage = null;
451 return;
452 }
453
454 // Update the widgets with the new image info.
455 String string = createMsg(i18n("Analyzer_on"), fFilename);
456 fShell.setText(string);
457
458 fInfoLabel.setText(
459 fFilename
460 + ": w="
461 + fImageData.width
462 + ", h="
463 + fImageData.height
464 + ", depth="
465 + fImageData.depth
466 + Sprint.f(" (%.2f)", fLoadTime / 1000f));
467 fImageCanvas.redraw();
468 }
469
470 void paintImage(PaintEvent event) {
471 if (true)
472 System.err.println(
473 NAME
474 + ".paintImage(): event="
475 + event.x
476 + ","
477 + event.y
478 + ","
479 + event.width
480 + ","
481 + event.height
482 + ", fX,fY="
483 + fX
484 + ","
485 + fY);
486 if (fImageData == null)
487 return;
488 int w = fImageData.width;
489 int h = fImageData.height;
490 event.gc.drawImage(fImage, 0, 0, w, h, fX + fImageData.x, fY + fImageData.y, w, h);
491 }
492
493 /*
494 * Called when the mouse moves in the image canvas.
495 * Show the color of the image at the point under the mouse.
496 */
497 void showColorAt(int mx, int my) {
498 if (fImage == null)
499 return;
500 int x = mx - fImageData.x - fX;
501 int y = my - fImageData.y - fY;
502 showColorForPixel(x, y);
503 }
504
505 /*
506 * Set the status label to show color information
507 * for the specified pixel in the image.
508 */
509 void showColorForPixel(int x, int y) {
510 if (x >= 0 && x < fImageData.width && y >= 0 && y < fImageData.height) {
511 int pixel = fImageData.getPixel(x, y);
512 RGB rgb = fImageData.palette.getRGB(pixel);
513
514 Object[] args =
515 { new Integer(x), new Integer(y), new Integer(pixel), Integer.toHexString(pixel), rgb };
516 if (pixel == fImageData.transparentPixel) {
517 fStatusLabel.setText(createMsg("Color at transparent pixel: ", args));
518 } else {
519 fStatusLabel.setText(Sprint.f("Color at: %d,%d=%06x").a(x).a(y).a(pixel).end());
520 }
521 } else {
522 fStatusLabel.setText("");
523 }
524 }
525
526 /*
527 * Called when a mouse down or key press is detected
528 * in the data text. Show the color of the pixel at
529 * the caret position in the data text.
530 */
531 void showColorForData() {
532 }
533
534 ////////////////////////////////////////////////////////////////////////
535
536 /*
537 * Called when the image canvas' horizontal scrollbar is selected.
538 */
539 void scrollHorizontally(ScrollBar scrollBar) {
540 if (fImage == null)
541 return;
542 Rectangle canvasBounds = fImageCanvas.getClientArea();
543 int width = (int) Math.round(fImageData.width);
544 int height = (int) Math.round(fImageData.height);
545 if (width > canvasBounds.width) {
546 // Only scroll if the image is bigger than the canvas.
547 int x = -scrollBar.getSelection();
548 if (x + width < canvasBounds.width) {
549 // Don't scroll past the end of the image.
550 x = canvasBounds.width - width;
551 }
552 fImageCanvas.scroll(x, fY, fX, fY, width, height, false);
553 fX = x;
554 }
555 }
556
557 /*
558 * Called when the image canvas' vertical scrollbar is selected.
559 */
560 void scrollVertically(ScrollBar scrollBar) {
561 if (fImage == null)
562 return;
563 Rectangle canvasBounds = fImageCanvas.getClientArea();
564 int width = (int) Math.round(fImageData.width);
565 int height = (int) Math.round(fImageData.height);
566 if (height > canvasBounds.height) {
567 // Only scroll if the image is bigger than the canvas.
568 int y = -scrollBar.getSelection();
569 if (y + height < canvasBounds.height) {
570 // Don't scroll past the end of the image.
571 y = canvasBounds.height - height;
572 }
573 fImageCanvas.scroll(fX, y, fX, fY, width, height, false);
574 fY = y;
575 }
576 }
577
578 /*
579 * Called when the ScaleX combo selection changes.
580 */
581 void scaleImage() {
582 try {
583 String text = fScaleCombo.getText();
584 int index = text.indexOf(' ');
585 fScale = Float.parseFloat(text.substring(0, index)) / 100;
586 } catch (NumberFormatException e) {
587 fScale = 1;
588 fScaleCombo.select(fScaleCombo.indexOf("100 %"));
589 }
590 if (fImage == null)
591 return;
592 // Scale image to a new buffer.
593 fImageData = fImageDatas[fImageDataIndex];
594 if (fScale != 1) {
595 fImageData =
596 fImageData.scaledTo(
597 (int) Math.round(fImageData.width * fScale),
598 (int) Math.round(fImageData.height * fScale));
599 }
600 resizeScrollBars();
601 fX = -fImageCanvas.getHorizontalBar().getSelection();
602 fY = -fImageCanvas.getVerticalBar().getSelection();
603 displayImage(fImageData);
604 }
605
606 // Reset the scale combos to 1.
607 void resetScaleCombo() {
608 fScale = 1;
609 fScaleCombo.select(fScaleCombo.indexOf("100 %"));
610 }
611
612 // Reset the scroll bars to 0.
613 void resetScrollBars() {
614 if (fImage == null)
615 return;
616 fX = 0;
617 fY = 0;
618 resizeScrollBars();
619 fImageCanvas.getHorizontalBar().setSelection(0);
620 fImageCanvas.getVerticalBar().setSelection(0);
621 }
622
623 void resizeScrollBars() {
624 // Set the max and thumb for the image canvas scroll bars.
625 ScrollBar horizontal = fImageCanvas.getHorizontalBar();
626 ScrollBar vertical = fImageCanvas.getVerticalBar();
627 Rectangle canvasBounds = fImageCanvas.getClientArea();
628 int width = (int) Math.round(fImageData.width);
629 if (width > canvasBounds.width) {
630 // The image is wider than the canvas.
631 // Set selection such as to keep top left corner of the image stationary.
632 int x = horizontal.getSelection() * width / horizontal.getMaximum();
633 horizontal.setEnabled(true);
634 horizontal.setMaximum(width);
635 horizontal.setSelection(x);
636 horizontal.setThumb(canvasBounds.width);
637 horizontal.setPageIncrement(canvasBounds.width);
638 } else {
639 // The canvas is wider than the image.
640 horizontal.setEnabled(false);
641 if (fX != 0) {
642 // Make sure the image is completely visible.
643 fX = 0;
644 fImageCanvas.redraw();
645 }
646 }
647 int height = (int) Math.round(fImageData.height);
648 if (height > canvasBounds.height) {
649 // The image is taller than the canvas.
650 // Set selection such as to keep top left corner of the image stationary.
651 vertical.setEnabled(true);
652 vertical.setMaximum(height);
653 vertical.setThumb(canvasBounds.height);
654 vertical.setPageIncrement(canvasBounds.height);
655 } else {
656 // The canvas is taller than the image.
657 vertical.setEnabled(false);
658 if (fY != 0) {
659 // Make sure the image is completely visible.
660 fY = 0;
661 fImageCanvas.redraw();
662 }
663 }
664 }
665
666 void resizeShell(ControlEvent event) {
667 if (isResizing)
668 return;
669 if (fImage == null || fShell.isDisposed())
670 return;
671 isResizing = true;
672 resizeScrollBars();
673 isResizing = false;
674 }
675
676 void clear() {
677 fImageDatas = null;
678 fImageData = null;
679 if (fImage != null)
680 fImage.dispose();
681 fImage = null;
682 }
683
684 ////////////////////////////////////////////////////////////////////////
685
686 /*
687 * Open an error dialog displaying the specified information.
688 */
689 void showErrorDialog(String operation, String filename, Exception e) {
690 MessageBox box = new MessageBox(fShell, SWT.ICON_ERROR);
691 String message = createMsg(i18n("Error"), new String[] { operation, filename });
692 String errorMessage = "";
693 if (e != null) {
694 if (e instanceof SWTException) {
695 SWTException swte = (SWTException) e;
696 errorMessage = swte.getMessage();
697 if (swte.throwable != null) {
698 errorMessage += ":\n" + swte.throwable.toString();
699 }
700 } else {
701 errorMessage = e.toString();
702 }
703 }
704 box.setMessage(message + errorMessage);
705 box.open();
706 }
707
708 /*
709 * Return a String describing the specified image file type.
710 */
711 static String fileTypeString(int filetype) {
712 if (filetype == SWT.IMAGE_BMP)
713 return "BMP";
714 if (filetype == SWT.IMAGE_GIF)
715 return "GIF";
716 if (filetype == SWT.IMAGE_ICO)
717 return "ICO";
718 if (filetype == SWT.IMAGE_JPEG)
719 return "JPEG";
720 if (filetype == SWT.IMAGE_PNG)
721 return "PNG";
722 return i18n("Unknown_ac") + ": " + filetype;
723 }
724
725 static String createMsg(String msg, Object arg) {
726 MessageFormat formatter = new MessageFormat(msg);
727 return formatter.format(new Object[] { arg });
728 }
729
730 static String i18n(String str) {
731 return str;
732 }
733
734 ////////////////////////////////////////////////////////////////////////
735
736 class TextPrompter extends Dialog {
737 String message = "";
738 String result = null;
739 Shell dialog;
740 Text text;
741 public TextPrompter(Shell parent, int style) {
742 super(parent, style);
743 }
744 public TextPrompter(Shell parent) {
745 this(parent, SWT.APPLICATION_MODAL);
746 }
747 public String getMessage() {
748 return message;
749 }
750 public void setMessage(String string) {
751 message = string;
752 }
753 public String open() {
754 dialog = new Shell(getParent(), getStyle());
755 dialog.setText(getText());
756 dialog.setLayout(new GridLayout());
757 Label label = new Label(dialog, SWT.NULL);
758 label.setText(message);
759 label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
760 text = new Text(dialog, SWT.SINGLE | SWT.BORDER);
761 GridData data = new GridData(GridData.FILL_HORIZONTAL);
762 data.widthHint = 300;
763 text.setLayoutData(data);
764 Composite buttons = new Composite(dialog, SWT.NONE);
765 GridLayout grid = new GridLayout();
766 grid.numColumns = 2;
767 buttons.setLayout(grid);
768 buttons.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
769 Button ok = new Button(buttons, SWT.PUSH);
770 ok.setText(i18n("OK"));
771 data = new GridData();
772 data.widthHint = 75;
773 ok.setLayoutData(data);
774 ok.addSelectionListener(new SelectionAdapter() {
775 public void widgetSelected(SelectionEvent e) {
776 result = text.getText();
777 dialog.dispose();
778 }
779 });
780 Button cancel = new Button(buttons, SWT.PUSH);
781 cancel.setText(i18n("Cancel"));
782 data = new GridData();
783 data.widthHint = 75;
784 cancel.setLayoutData(data);
785 cancel.addSelectionListener(new SelectionAdapter() {
786 public void widgetSelected(SelectionEvent e) {
787 dialog.dispose();
788 }
789 });
790 dialog.setDefaultButton(ok);
791 dialog.pack();
792 dialog.open();
793 while (!dialog.isDisposed()) {
794 if (!getDisplay().readAndDispatch())
795 getDisplay().sleep();
796 }
797 return result;
798 }
799 }
800
801 ////////////////////////////////////////////////////////////////////////
802
803 }