File: EditorState.java

package info (click to toggle)
java-imaging-utilities 0.14.2%2B3-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 2,280 kB
  • ctags: 3,725
  • sloc: java: 31,190; sh: 238; makefile: 53; xml: 30
file content (558 lines) | stat: -rw-r--r-- 13,542 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
/*
 * EditorState
 * 
 * Copyright (c) 2000, 2001, 2002, 2003 Marco Schmidt.
 * All rights reserved.
 */

package net.sourceforge.jiu.apps;

import java.io.IOException;
import java.util.Locale;
import java.util.Vector;
import net.sourceforge.jiu.data.PixelImage;
import net.sourceforge.jiu.ops.Operation;
import net.sourceforge.jiu.ops.ProgressListener;

/**
 * Represents the state of the editor, including image(s), modified flag,
 * current file name and directories and more.
 * This class must not know GUI-specific information like Frame or JFrame objects.
 * These GUI classes (more precisely, the JIU classes that extend them) will have to 
 * know EditorState and update according to the information they retrieve from an 
 * EditorState object associated with them.
 * EditorState is a pure data container.
 * @author Marco Schmidt
 */
public class EditorState implements MenuIndexConstants
{
	/**
	 * The default number of undo steps possible.
	 */
	public static final int DEFAULT_MAX_UNDO_IMAGES = 2;

	/**
	 * The default number of redo steps possible.
	 */
	public static final int DEFAULT_MAX_REDO_IMAGES = DEFAULT_MAX_UNDO_IMAGES;

	/**
	 * All allowed zoom levels, as percentage values in ascending order.
	 */
	public static final int[] ZOOM_LEVELS = {5, 7, 10, 15, 20, 30, 50, 70, 100, 150, 200, 300, 500, 700, 1000, 2000, 3000, 5000};

	/**
	 * The index into the {@link #ZOOM_LEVELS} array that holds the original size zoom level (100 percent).
	 * So, ZOOM_LEVELS[ORIGINAL_SIZE_ZOOM_INDEX] must be equal to 100.
	 */
	public static final int ORIGINAL_SIZE_ZOOM_INDEX = 8;

	/**
	 * Integer constant for <em>nearest neighbor interpolation</em>.
	 * A fast but ugly method.
	 */
	public static final int INTERPOLATION_NEAREST_NEIGHBOR = 0;

	/**
	 * Integer constant for <em>bilinear neighbor interpolation</em>.
	 * A slow but nice method.
	 */
	public static final int INTERPOLATION_BILINEAR = 1;

	/**
	 * Integer constant for <em>bicubic interpolation</em>.
	 * A very slow method, but with the nicest output of the three supported interpolation types.
	 */
	public static final int INTERPOLATION_BICUBIC = 2;

	/**
	 * The default interpolation type, one of the three INTERPOLATION_xyz constants.
	 */
	public static final int DEFAULT_INTERPOLATION = INTERPOLATION_NEAREST_NEIGHBOR;
	private String currentDirectory;
	private String fileName;
	private PixelImage currentImage;
	private int interpolation;
	private Locale locale;
	private int maxRedoImages;
	private int maxUndoImages;
	private boolean modified;
	private Vector progressListeners;
	private Vector redoImages;
	private Vector redoModified;
	private String startupImageName;
	private Strings strings;
	private Vector undoImages;
	private Vector undoModified;
	private int zoomIndex = ORIGINAL_SIZE_ZOOM_INDEX;
	private double zoomFactorX;
	private double zoomFactorY;
	private boolean zoomToFit;

	/**
	 * Create new EditorState object and initialize its private fields
	 * to default values.
	 */
	public EditorState()
	{
		locale = Locale.getDefault();
		setStrings(null);
		progressListeners = new Vector();
		maxRedoImages = DEFAULT_MAX_REDO_IMAGES;
		maxUndoImages = DEFAULT_MAX_UNDO_IMAGES;
		redoImages = new Vector(maxRedoImages);
		redoModified = new Vector(maxRedoImages);
		undoImages = new Vector(maxUndoImages);
		undoModified = new Vector(maxUndoImages);
		zoomFactorX = 1.0;
		zoomFactorY = 1.0;
		zoomToFit = false;
	}

	private void addImageToRedo(PixelImage image, boolean modifiedState)
	{
		if (maxRedoImages < 1)
		{
			return;
		}
		if (redoImages.size() == maxRedoImages)
		{
			redoImages.setElementAt(null, 0);
			redoImages.removeElementAt(0);
			redoModified.removeElementAt(0);
		}
		redoImages.addElement(image);
		redoModified.addElement(new Boolean(modifiedState));
	}

	private void addImageToUndo(PixelImage image, boolean modifiedState)
	{
		if (maxUndoImages < 1)
		{
			return;
		}
		if (undoImages.size() == maxUndoImages)
		{
			undoImages.setElementAt(null, 0);
			undoImages.removeElementAt(0);
			undoModified.removeElementAt(0);
		}
		undoImages.addElement(image);
		undoModified.addElement(new Boolean(modifiedState));
	}

	/**
	 * Adds the argument progress listener to the internal list of progress
	 * listeners to be notified by progress updates.
	 * @param pl object implementing ProgressListener to be added
	 */
	public void addProgressListener(ProgressListener pl)
	{
		progressListeners.addElement(pl);
	}

	/**
	 * Returns if a redo operation is possible right now.
	 */
	public boolean canRedo()
	{
		return (redoImages.size() > 0);
	}

	/**
	 * Returns if an undo operation is possible right now.
	 */
	public boolean canUndo()
	{
		return (undoImages.size() > 0);
	}

	public void clearRedo()
	{
		int index = 0;
		while (index < redoImages.size())
		{
			redoImages.setElementAt(null, index++);
		}
		redoImages.setSize(0);
		redoModified.setSize(0);
	}

	public void clearUndo()
	{
		int index = 0;
		while (index < undoImages.size())
		{
			undoImages.setElementAt(null, index++);
		}
		undoImages.setSize(0);
		undoModified.setSize(0);
	}

	public void ensureStringsAvailable()
	{
		if (getStrings() == null)
		{
			setStrings(Strings.DEFAULT_LANGUAGE_ISO_639_CODE);
		}
	}

	/** 
	 * Returns the current directory.
	 * This directory will be used when file dialogs are opened.
	 */
	public String getCurrentDirectory()
	{
		return currentDirectory;
	}

	/**
	 * Returns the name of the file from which the current image was loaded.
	 */
	public String getFileName()
	{
		return fileName;
	}

	/**
	 * Returns the image object currently loaded.
	 */
	public PixelImage getImage()
	{
		return currentImage;
	}

	/**
	 * Returns the current interpolation type, one of the INTERPOLATION_xyz constants.
	 */
	public int getInterpolation()
	{
		return interpolation;
	}

	/**
	 * Returns the Locale object currently used.
	 */
	public Locale getLocale()
	{
		return locale;
	}

	/**
	 * Returns the current modified state (true if image was modified and not saved 
	 * after modification, false otherwise).
	 */
	public boolean getModified()
	{
		return modified;
	}

	/**
	 * Returns the internal list of progress listeners.
	 */
	public Vector getProgressListeners()
	{
		return progressListeners;
	}

	public String getStartupImageName()
	{
		return startupImageName;
	}

	/**
	 * Returns the Strings object currently in use.
	 */
	public Strings getStrings()
	{
		return strings;
	}

	/** 
	 * Returns the current zoom factor in horizontal direction.
	 * The value 1.0 means that the image is displayed at its 
	 * original size.
	 * Anything smaller means that the image is scaled down,
	 * anything larger means that the image is scaled up.
	 * The value must not be smaller than or equal to 0.0.
	 * @return zoom factor in horizontal direction
	 * @see #getZoomFactorY
	 */
	public double getZoomFactorX()
	{
		return zoomFactorX;
	}

	/** 
	 * Returns the current zoom factor in vertical direction.
	 * The value 1.0 means that the image is displayed at its 
	 * original size.
	 * Anything smaller means that the image is scaled down,
	 * anything larger means that the image is scaled up.
	 * The value must not be smaller than or equal to 0.0.
	 * @return zoom factor in vertical direction
	 * @see #getZoomFactorX
	 */
	public double getZoomFactorY()
	{
		return zoomFactorY;
	}

	/**
	 * Returns if image display is currently set to &quot;zoom to fit&quot;
	 * Zoom to fit means that the image is always zoomed to fit exactly into the window.
	 */
	public boolean getZoomToFit()
	{
		return zoomToFit;
	}

	/**
	 * Returns if this state encapsulates an image object.
	 */
	public boolean hasImage()
	{
		return (currentImage != null);
	}

	/**
	 * Adds all ProgressListener objects from the internal list of listeners to
	 * the argument operation.
	 */
	public void installProgressListeners(Operation op)
	{
		if (op == null)
		{
			return;
		}
		// cannot use Iterator because it's 1.2+
		int index = 0;
		while (index < progressListeners.size())
		{
			ProgressListener pl = (ProgressListener)progressListeners.elementAt(index++);
			op.addProgressListener(pl);
		}
	}

	/**
	 * Returns if the image is displayed at maximum zoom level.
	 */
	public boolean isMaximumZoom()
	{
		return zoomIndex == ZOOM_LEVELS.length - 1;
	}

	/**
	 * Returns if the image is displayed at minimum zoom level.
	 */
	public boolean isMinimumZoom()
	{
		return zoomIndex == 0;
	}

	/**
	 * Returns if the current zoom level is set to original size
	 * (each image pixel is displayed as one pixel).
	 */
	public boolean isZoomOriginalSize()
	{
		return zoomIndex == ORIGINAL_SIZE_ZOOM_INDEX;
	}

	/**
	 * Perform a redo operation, restore the state before the last undo operation.
	 * Before that is done, save the current state for an undo.
	 */
	public void redo()
	{
		if (redoImages.size() < 1)
		{
			return;
		}
		addImageToUndo(currentImage, modified);
		int redoIndex = redoImages.size() - 1;
		currentImage = (PixelImage)redoImages.elementAt(redoIndex);
		redoImages.setElementAt(null, redoIndex);
		redoImages.setSize(redoIndex);
		modified = ((Boolean)redoModified.elementAt(redoIndex)).booleanValue();
		redoModified.setSize(redoIndex);
	}

	public void resetZoomFactors()
	{
		setZoomFactors(1.0, 1.0);
	}

	/**
	 * Sets a new current directory.
	 * @param newCurrentDirectory the directory to be used as current directory from now on
	 */
	public void setCurrentDirectory(String newCurrentDirectory)
	{
		currentDirectory = newCurrentDirectory;
	}

	/**
	 * Sets a new file name.
	 * This is used mostly after a new image was loaded from a file or
	 * if the current image is closed (then a null value would be given to this method).
	 * @param newFileName new name of the current file
	 */
	public void setFileName(String newFileName)
	{
		fileName = newFileName;
	}

	/**
	 * Sets image and modified state to argument values.
	 * @param image new current image
	 * @param newModifiedState new state of modified flag
	 */
	public void setImage(PixelImage image, boolean newModifiedState)
	{
		if (hasImage())
		{
			addImageToUndo(currentImage, modified);
		}
		currentImage = image;
		modified = newModifiedState;
		clearRedo();
	}

	public void setStartupImageName(String name)
	{
		startupImageName = name;
	}

	/**
	 * Sets a new interpolation type to be used for display.
	 * @param newInterpolation an int for the interpolation type, must be one of the INTERPOLATION_xyz constants
	 */
	public void setInterpolation(int newInterpolation)
	{
		if (newInterpolation == INTERPOLATION_NEAREST_NEIGHBOR ||
		    newInterpolation == INTERPOLATION_BILINEAR ||
		    newInterpolation == INTERPOLATION_BICUBIC)
		{
			interpolation = newInterpolation;
		}
	}

	/**
	 * Defines a new Locale to be used.
	 * @param newLocale Locale object used from now on
	 * @see #setStrings
	 */
	public void setLocale(Locale newLocale)
	{
		locale = newLocale;
	}

	/*public void setModified(boolean modifiedState)
	{
		modified = modifiedState;
	}*/

	/**
	 * Set new Strings resource.
	 * @param iso639Code language of the new Strings resource
	 */
	public void setStrings(String iso639Code)
	{
		Strings newStrings = null;
		try
		{
			StringLoader loader;
			if (iso639Code == null)
			{
				loader = new StringLoader();
			}
			else
			{
				loader = new StringLoader(iso639Code);
			}
			newStrings = loader.load();
		}
		catch (IOException ioe)
		{
		}
		if (newStrings != null)
		{
			strings = newStrings;
		}
	}

	/**
	 * Sets the zoom factors to the argument values.
	 */
	public void setZoomFactors(double zoomX, double zoomY)
	{
		zoomFactorX = zoomX;
		zoomFactorY = zoomY;
	}

	/**
	 * Perform an undo step - the previous state will be set, the
	 * current state will be saved for a redo operation
	 * @see #redo
	 */
	public void undo()
	{
		if (undoImages.size() < 1)
		{
			return;
		}
		addImageToRedo(currentImage, modified);
		int undoIndex = undoImages.size() - 1;
		currentImage = (PixelImage)undoImages.elementAt(undoIndex);
		undoImages.setElementAt(null, undoIndex);
		undoImages.setSize(undoIndex);
		modified = ((Boolean)undoModified.elementAt(undoIndex)).booleanValue();
		undoModified.setSize(undoIndex);
	}

	/**
	 * Increase the zoom level by one.
	 * @see #zoomOut
	 * @see #zoomSetOriginalSize
	 */
	public void zoomIn()
	{
		if (zoomIndex + 1 == ZOOM_LEVELS.length)
		{
			return;
		}
		zoomIndex++;
		zoomFactorX = 1.0 * ZOOM_LEVELS[zoomIndex] / 100;
		zoomFactorY = zoomFactorX;
	}

	/**
	 * Decrease the zoom level by one.
	 * @see #zoomIn
	 * @see #zoomSetOriginalSize
	 */
	public void zoomOut()
	{
		if (zoomIndex == 0)
		{
			return;
		}
		zoomIndex--;
		zoomFactorX = 1.0 * ZOOM_LEVELS[zoomIndex] / 100;
		zoomFactorY = zoomFactorX;
	}

	/**
	 * Set the zoom level to 100 percent (1:1).
	 * Each image pixel will be displayed as one pixel
	 * @see #zoomIn
	 * @see #zoomOut
	 */
	public void zoomSetOriginalSize()
	{
		zoomIndex = ORIGINAL_SIZE_ZOOM_INDEX;
		zoomFactorX = 1.0;
		zoomFactorY = 1.0;
	}
}