001 /* 002 * JiuAwtFrame 003 * 004 * Copyright (c) 2001, 2002, 2003 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.gui.awt; 009 010 import java.awt.BorderLayout; 011 import java.awt.Cursor; 012 import java.awt.Dimension; 013 import java.awt.Frame; 014 import java.awt.Image; 015 import java.awt.Label; 016 import java.awt.ScrollPane; 017 import java.awt.Toolkit; 018 import java.awt.event.ActionEvent; 019 import java.awt.event.ActionListener; 020 import java.awt.event.ComponentListener; 021 import java.awt.event.ComponentEvent; 022 import java.awt.event.WindowAdapter; 023 import java.awt.event.WindowEvent; 024 import net.sourceforge.jiu.apps.EditorState; 025 import net.sourceforge.jiu.apps.ImageDescriptionCreator; 026 import net.sourceforge.jiu.apps.JiuInfo; 027 import net.sourceforge.jiu.apps.StringIndexConstants; 028 import net.sourceforge.jiu.apps.Strings; 029 import net.sourceforge.jiu.data.PixelImage; 030 import net.sourceforge.jiu.gui.awt.AwtMenuWrapper; 031 import net.sourceforge.jiu.gui.awt.ImageCanvas; 032 import net.sourceforge.jiu.gui.awt.dialogs.InfoDialog; 033 import net.sourceforge.jiu.ops.ProgressListener; 034 035 /** 036 * The frame class for the AWT demo program {@link net.sourceforge.jiu.apps.jiuawt}. 037 * @author Marco Schmidt 038 * @since 0.8.0 039 */ 040 public class JiuAwtFrame extends Frame implements ActionListener, ComponentListener, JiuInfo, ProgressListener 041 { 042 /** 043 * The name of this application, jiuawt, plus the version number taken 044 * from {@link JiuInfo}. 045 * Example: <code>jiuawt 0.8.0</code>. 046 * Will be displayed in the title bar of this frame. 047 */ 048 public static final String APP_NAME = "jiuawt " + JiuInfo.JIU_VERSION; 049 private EditorState editor; 050 private AwtMenuWrapper menuWrapper; 051 private AwtOperationProcessor processor; 052 private Label statusBar; 053 private ScrollPane scrollPane; 054 private ImageCanvas canvas; 055 056 /** 057 * Create an object of this class, using the argument editor 058 * state. 059 * String resources to initialize the menu etc. will be taken 060 * from the EditorState object's Strings variable 061 * @param editorState EditorState object used by this frame 062 */ 063 public JiuAwtFrame(EditorState editorState) 064 { 065 super(APP_NAME); 066 processor = new AwtOperationProcessor(editorState, this); 067 editor = editorState; 068 editor.addProgressListener(this); 069 addComponentListener(this); 070 addWindowListener(new WindowAdapter() 071 { 072 public void windowClosing(WindowEvent e) 073 { 074 processor.fileExit(); 075 } 076 }); 077 // MENU 078 menuWrapper = new AwtMenuWrapper(editor.getStrings(), this); 079 setMenuBar(menuWrapper.getMenuBar()); 080 menuWrapper.updateEnabled(processor); 081 // IMAGE CANVAS 082 // STATUS BAR 083 statusBar = new Label(""); 084 add(statusBar, BorderLayout.SOUTH); 085 maximize(); 086 //pack(); 087 repaint(); 088 setVisible(true); 089 if (editor.getStartupImageName() != null) 090 { 091 processor.fileOpen(); 092 } 093 } 094 095 /** 096 * Processes event objects that get created when menu items are 097 * picked. 098 * Determines the {@link net.sourceforge.jiu.apps.MenuIndexConstants} value for a given 099 * event object and calls the internal {@link AwtOperationProcessor} 100 * object's process method with the menu value. 101 * The operation will then be performed. 102 * @param e the ActionEvent object 103 */ 104 public void actionPerformed(ActionEvent e) 105 { 106 Object source = e.getSource(); 107 int index = menuWrapper.findIndex(source); 108 if (index != -1) 109 { 110 processor.process(index); 111 } 112 } 113 114 public void componentHidden(ComponentEvent e) 115 { 116 } 117 118 public void componentMoved(ComponentEvent e) 119 { 120 } 121 122 public void componentResized(ComponentEvent e) 123 { 124 if (scrollPane != null) 125 { 126 canvas.computeZoomToFitSize(); 127 scrollPane.doLayout(); 128 } 129 } 130 131 public void componentShown(ComponentEvent e) 132 { 133 } 134 135 /** 136 * Maximize the frame on the desktop. 137 * There is no such function in the 1.1 AWT (was added in 1.4), so 138 * this class determines the screen size and sets the frame to be 139 * a little smaller than that (to make up for task bars etc.). 140 * So this is just a heuristical approach. 141 */ 142 public void maximize() 143 { 144 /* 145 The following line: 146 setExtendedState(getExtendedState() | MAXIMIZED_BOTH); 147 does a nice maximization, but works only with Java 1.4+ 148 */ 149 Toolkit toolkit = Toolkit.getDefaultToolkit(); 150 if (toolkit == null) 151 { 152 return; 153 } 154 Dimension screenSize = toolkit.getScreenSize(); 155 if (screenSize == null) 156 { 157 return; 158 } 159 int w = screenSize.width; 160 int h = screenSize.height; 161 int x = 20; 162 int y = 80; 163 setLocation(x / 2, y / 2); 164 setSize(w - x, h - y); 165 } 166 167 /** 168 * Displays the argument text in a message box with 169 * error in the title bar. 170 * @param text the error message to be displayed 171 */ 172 public void showError(String text) 173 { 174 Strings strings = editor.getStrings(); 175 showInfo(strings.get(StringIndexConstants.ERROR_MESSAGE), text); 176 } 177 178 /** 179 * Sets the current cursor to be {@link java.awt.Cursor#DEFAULT_CURSOR}. 180 */ 181 public void setDefaultCursor() 182 { 183 Cursor cursor = new Cursor(Cursor.DEFAULT_CURSOR); 184 setCursor(cursor); 185 } 186 187 /** 188 * If an image is currently loaded, 189 */ 190 public void setOriginalSize() 191 { 192 if (canvas != null && !editor.isZoomOriginalSize()) 193 { 194 editor.zoomSetOriginalSize(); 195 canvas.setZoomFactors(editor.getZoomFactorX(), editor.getZoomFactorY()); 196 updateTitle(); 197 menuWrapper.updateEnabled(processor); 198 } 199 } 200 201 public void setProgress(int zeroBasedIndex, int totalItems) 202 { 203 if (totalItems < 1) 204 { 205 throw new IllegalArgumentException("Total number of items (second parameter) must be larger than zero."); 206 } 207 if (zeroBasedIndex < 0) 208 { 209 throw new IllegalArgumentException("Zero-based index must be at least zero."); 210 } 211 if (zeroBasedIndex >= totalItems) 212 { 213 throw new IllegalArgumentException("Zero-based index must be smaller than total " + 214 "number of items; zeroBasedIndex=" + zeroBasedIndex + ", totalItems=" + 215 totalItems); 216 } 217 setProgress((float)(zeroBasedIndex + 1) / (float)totalItems); 218 } 219 220 /** 221 * Set a new progress status. 222 * @param progress float from 0.0f to 1.0f, indicating the progress between 0 and 100 percent 223 */ 224 public void setProgress(float progress) 225 { 226 if (progress >= 0.0f && progress <= 1.0f) 227 { 228 setStatusBar(" " + Math.round(progress * 100.0f) + "%"); 229 } 230 } 231 232 public void setStatusBar(String text) 233 { 234 statusBar.setText(text); 235 } 236 237 public void setWaitCursor() 238 { 239 Cursor cursor = new Cursor(Cursor.WAIT_CURSOR); 240 setCursor(cursor); 241 } 242 243 /** 244 * Shows a modal dialog with given title bar and message text. 245 * @param title will be displayed in the dialog's title bar 246 * @param text will be displayed in the dialog's center part 247 */ 248 public void showInfo(String title, String text) 249 { 250 InfoDialog d = new InfoDialog(this, title, text); 251 d.show(); 252 } 253 254 /** 255 * If there is an image loaded, forces a canvas redraw by 256 * calling repaint. 257 */ 258 public void updateCanvas() 259 { 260 if (canvas != null) 261 { 262 canvas.setInterpolation(editor.getInterpolation()); 263 //canvas.revalidate(); 264 canvas.repaint(); 265 } 266 } 267 268 /** 269 * Removes the current canvas from the frame (if there 270 * is an image loaded) and creates a new canvas for the 271 * current image. 272 */ 273 public void updateImage() 274 { 275 PixelImage image = editor.getImage(); 276 if (scrollPane != null) 277 { 278 remove(scrollPane); 279 } 280 if (image != null) 281 { 282 //editor.zoomSetOriginalSize(); 283 Image awtImage = ImageCreator.convertToAwtImage(image, RGBA.DEFAULT_ALPHA); 284 scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); 285 canvas = new ImageCanvas(scrollPane); 286 canvas.setInterpolation(editor.getInterpolation()); 287 canvas.setZoomToFit(editor.getZoomToFit()); 288 canvas.setImage(awtImage); 289 canvas.setZoomFactors(editor.getZoomFactorX(), editor.getZoomFactorY()); 290 //canvas.computeZoomToFitSize(); 291 scrollPane.add(canvas); 292 add(scrollPane); 293 } 294 updateStatusBar(); 295 updateTitle(); 296 validate(); 297 menuWrapper.updateEnabled(processor); 298 } 299 300 /** 301 * Creates a description string for the current image and sets the 302 * status bar to that text. 303 */ 304 public void updateStatusBar() 305 { 306 PixelImage image = editor.getImage(); 307 String statusBarText; 308 if (image == null) 309 { 310 statusBarText = ""; 311 } 312 else 313 { 314 statusBarText = ImageDescriptionCreator.getDescription(image, editor.getLocale(), editor.getStrings()); 315 } 316 setStatusBar(statusBarText); 317 } 318 319 /** 320 * Sets the frame's title bar to the application name, plus the file name of 321 * the currently loaded image file, plus the current zoom factor, plus an 322 * optional asterisk in case the image was modified but not yet saved. 323 */ 324 public void updateTitle() 325 { 326 StringBuffer sb = new StringBuffer(APP_NAME); 327 String fileName = editor.getFileName(); 328 if (fileName != null && fileName.length() > 0) 329 { 330 sb.append(" ["); 331 sb.append(fileName); 332 if (editor.getModified()) 333 { 334 sb.append('*'); 335 } 336 sb.append(']'); 337 } 338 if (editor.getImage() != null) 339 { 340 double zoom = editor.getZoomFactorX(); 341 int percent = (int)(zoom * 100.0); 342 sb.append(' '); 343 sb.append(Integer.toString(percent)); 344 sb.append('%'); 345 } 346 setTitle(sb.toString()); 347 } 348 349 /** 350 * If an image is currently displayed, zoom in one level. 351 */ 352 public void zoomIn() 353 { 354 if (canvas != null && !editor.isMaximumZoom()) 355 { 356 editor.zoomIn(); 357 canvas.setZoomFactors(editor.getZoomFactorX(), editor.getZoomFactorY()); 358 updateTitle(); 359 menuWrapper.updateEnabled(processor); 360 } 361 } 362 363 /** 364 * If an image is currently displayed, zoom out one level. 365 */ 366 public void zoomOut() 367 { 368 if (canvas != null && !editor.isMinimumZoom()) 369 { 370 editor.zoomOut(); 371 canvas.setZoomFactors(editor.getZoomFactorX(), editor.getZoomFactorY()); 372 updateTitle(); 373 menuWrapper.updateEnabled(processor); 374 } 375 } 376 }