Skip to content

Commit f66a204

Browse files
committed
Replace Image creating methods accepting Strings as file-system paths
Use java.nio.file.Path to model file-system paths instead of Strings. Add the new way to create ImageData as static factory instead of a constructor, because a constructor is not really suitable to create a copy of the first element of an array of ImageData.
1 parent 0071da4 commit f66a204

File tree

12 files changed

+724
-177
lines changed

12 files changed

+724
-177
lines changed

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java

Lines changed: 107 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2020 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,6 +15,7 @@
1515

1616

1717
import java.io.*;
18+
import java.nio.file.Path;
1819
import java.util.*;
1920

2021
import org.eclipse.swt.*;
@@ -127,9 +128,9 @@ public final class Image extends Resource implements Drawable {
127128
static final int DEFAULT_SCANLINE_PAD = 4;
128129

129130
/**
130-
* ImageFileNameProvider to provide file names at various Zoom levels
131+
* ImageFileProvider to provide files at various Zoom levels
131132
*/
132-
private ImageFileNameProvider imageFileNameProvider;
133+
private ImageFileProvider imageFileProvider;
133134

134135
/**
135136
* ImageDataProvider to provide ImageData at various Zoom levels
@@ -388,11 +389,11 @@ public Image(Device device, Image srcImage, int flag) {
388389
/* Create the 100% representation for the new image from source image & apply flag */
389390
createRepFromSourceAndApplyFlag(srcImage.getRepresentation (100), srcWidth, srcHeight, flag);
390391

391-
imageFileNameProvider = srcImage.imageFileNameProvider;
392+
imageFileProvider = srcImage.imageFileProvider;
392393
imageDataProvider = srcImage.imageDataProvider;
393394
imageGcDrawer = srcImage.imageGcDrawer;
394395
this.styleFlag = srcImage.styleFlag | flag;
395-
if (imageFileNameProvider != null || imageDataProvider != null ||srcImage.imageGcDrawer != null) {
396+
if (imageFileProvider != null || imageDataProvider != null ||srcImage.imageGcDrawer != null) {
396397
/* If source image has 200% representation then create the 200% representation for the new image & apply flag */
397398
NSBitmapImageRep rep200 = srcImage.getRepresentation (200);
398399
if (rep200 != null) createRepFromSourceAndApplyFlag(rep200, srcWidth * 2, srcHeight * 2, flag);
@@ -713,7 +714,7 @@ public Image(Device device, InputStream stream) {
713714
* </p>
714715
*
715716
* @param device the device on which to create the image
716-
* @param filename the name of the file to load the image from
717+
* @param file the name of the file to load the image from
717718
*
718719
* @exception IllegalArgumentException <ul>
719720
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
@@ -730,15 +731,16 @@ public Image(Device device, InputStream stream) {
730731
* </ul>
731732
*
732733
* @see #dispose()
734+
* @since 3.129
733735
*/
734-
public Image(Device device, String filename) {
736+
public Image(Device device, Path file) {
735737
super(device);
736738
NSAutoreleasePool pool = null;
737739
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
738740
try {
739-
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
740-
initNative(filename);
741-
if (this.handle == null) init(new ImageData(filename));
741+
if (file == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
742+
initNative(file);
743+
if (this.handle == null) init(ImageData.create(file));
742744
init();
743745
} finally {
744746
if (pool != null) pool.release();
@@ -747,16 +749,54 @@ public Image(Device device, String filename) {
747749

748750
/**
749751
* Constructs an instance of this class by loading its representation
750-
* from the file retrieved from the ImageFileNameProvider. Throws an
752+
* from the file with the specified name. Throws an error if an error
753+
* occurs while loading the image, or if the result is an image
754+
* of an unsupported type.
755+
* <p>
756+
* This constructor is provided for convenience when loading
757+
* a single image only. If the specified file contains
758+
* multiple images, only the first one will be used.
759+
* <p>
760+
* You must dispose the image when it is no longer required.
761+
* </p>
762+
*
763+
* @param device the device on which to create the image
764+
* @param filename the name of the file to load the image from
765+
*
766+
* @exception IllegalArgumentException <ul>
767+
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
768+
* <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
769+
* </ul>
770+
* @exception SWTException <ul>
771+
* <li>ERROR_IO - if an IO error occurs while reading from the file</li>
772+
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
773+
* <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
774+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
775+
* </ul>
776+
* @exception SWTError <ul>
777+
* <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
778+
* </ul>
779+
*
780+
* @see #dispose()
781+
* @deprecated Instead use {@link #Image(Device, Path)}
782+
*/
783+
@Deprecated(since = "2025-03")
784+
public Image(Device device, String filename) {
785+
this(device, filename == null ? Path.of(filename) : null);
786+
}
787+
788+
/**
789+
* Constructs an instance of this class by loading its representation
790+
* from the file retrieved from the {@link ImageFileProvider}. Throws an
751791
* error if an error occurs while loading the image, or if the result
752792
* is an image of an unsupported type.
753793
* <p>
754794
* This constructor is provided for convenience for loading image as
755795
* per DPI level.
756796
*
757797
* @param device the device on which to create the image
758-
* @param imageFileNameProvider the ImageFileNameProvider object that is
759-
* to be used to get the file name
798+
* @param imageFileProvider the {@link ImageFileProvider} object that is
799+
* to be used to get the file
760800
*
761801
* @exception IllegalArgumentException <ul>
762802
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
@@ -772,24 +812,24 @@ public Image(Device device, String filename) {
772812
* @exception SWTError <ul>
773813
* <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
774814
* </ul>
775-
* @since 3.104
815+
* @since 3.129
776816
*/
777-
public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
817+
public Image(Device device, ImageFileProvider imageFileProvider) {
778818
super(device);
779-
if (imageFileNameProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
780-
this.imageFileNameProvider = imageFileNameProvider;
781-
String filename = imageFileNameProvider.getImagePath(100);
782-
if (filename == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
819+
if (imageFileProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
820+
this.imageFileProvider = imageFileProvider;
821+
Path file = imageFileProvider.getImagePath(100);
822+
if (file == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
783823
NSAutoreleasePool pool = null;
784824
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
785825
try {
786-
initNative(filename);
787-
if (this.handle == null) init(new ImageData(filename));
826+
initNative(file);
827+
if (this.handle == null) init(ImageData.create(file));
788828
init();
789-
String filename2x = imageFileNameProvider.getImagePath(200);
790-
if (filename2x != null) {
829+
Path file2x = imageFileProvider.getImagePath(200);
830+
if (file2x != null) {
791831
alphaInfo_200 = new AlphaInfo();
792-
id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(filename2x));
832+
id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(file2x.toString()));
793833
NSImageRep rep = new NSImageRep(id);
794834
handle.addRepresentation(rep);
795835
}
@@ -798,6 +838,41 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
798838
}
799839
}
800840

841+
/**
842+
* Constructs an instance of this class by loading its representation
843+
* from the file retrieved from the ImageFileNameProvider. Throws an
844+
* error if an error occurs while loading the image, or if the result
845+
* is an image of an unsupported type.
846+
* <p>
847+
* This constructor is provided for convenience for loading image as
848+
* per DPI level.
849+
*
850+
* @param device the device on which to create the image
851+
* @param imageFileNameProvider the ImageFileNameProvider object that is
852+
* to be used to get the file name
853+
*
854+
* @exception IllegalArgumentException <ul>
855+
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
856+
* <li>ERROR_NULL_ARGUMENT - if the ImageFileNameProvider is null</li>
857+
* <li>ERROR_INVALID_ARGUMENT - if the fileName provided by ImageFileNameProvider is null at 100% zoom</li>
858+
* </ul>
859+
* @exception SWTException <ul>
860+
* <li>ERROR_IO - if an IO error occurs while reading from the file</li>
861+
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
862+
* <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
863+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
864+
* </ul>
865+
* @exception SWTError <ul>
866+
* <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
867+
* </ul>
868+
* @since 3.104
869+
* @deprecated Instead use {@link #Image(Device, ImageFileProvider)}
870+
*/
871+
@Deprecated(since = "2025-03")
872+
public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
873+
this(device, (ImageFileProvider) zoom -> Path.of(imageFileNameProvider.getImagePath(zoom)));
874+
}
875+
801876
/**
802877
* Constructs an instance of this class by loading its representation
803878
* from the ImageData retrieved from the ImageDataProvider. Throws an
@@ -880,7 +955,7 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
880955
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
881956
try {
882957
init (data);
883-
init ();
958+
init ();
884959
} finally {
885960
if (pool != null) pool.release();
886961
}
@@ -902,7 +977,7 @@ private ImageData drawWithImageGcDrawer(ImageGcDrawer imageGcDrawer, int width,
902977

903978
private AlphaInfo _getAlphaInfoAtCurrentZoom (NSBitmapImageRep rep) {
904979
int deviceZoom = DPIUtil.getDeviceZoom();
905-
if (deviceZoom != 100 && (imageFileNameProvider != null || imageDataProvider != null)) {
980+
if (deviceZoom != 100 && (imageFileProvider != null || imageDataProvider != null)) {
906981
if (alphaInfo_100.alphaData != null && alphaInfo_200 != null) {
907982
if (alphaInfo_200.alphaData == null) initAlpha_200(rep);
908983
return alphaInfo_200;
@@ -1176,8 +1251,8 @@ public boolean equals (Object object) {
11761251
if (device != image.device || alphaInfo_100.transparentPixel != image.alphaInfo_100.transparentPixel) return false;
11771252
if (imageDataProvider != null && image.imageDataProvider != null) {
11781253
return styleFlag == image.styleFlag && imageDataProvider.equals (image.imageDataProvider);
1179-
} else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
1180-
return styleFlag == image.styleFlag && imageFileNameProvider.equals (image.imageFileNameProvider);
1254+
} else if (imageFileProvider != null && image.imageFileProvider != null) {
1255+
return styleFlag == image.styleFlag && imageFileProvider.equals (image.imageFileProvider);
11811256
} else if (imageGcDrawer != null && image.imageGcDrawer != null) {
11821257
return styleFlag == image.styleFlag && imageGcDrawer.equals(image.imageGcDrawer) && width == image.width
11831258
&& height == image.height;
@@ -1415,8 +1490,8 @@ NSBitmapImageRep createImageRep(NSSize targetSize) {
14151490
public int hashCode () {
14161491
if (imageDataProvider != null) {
14171492
return imageDataProvider.hashCode();
1418-
} else if (imageFileNameProvider != null) {
1419-
return imageFileNameProvider.hashCode();
1493+
} else if (imageFileProvider != null) {
1494+
return imageFileProvider.hashCode();
14201495
} else if (imageGcDrawer != null) {
14211496
return Objects.hash(imageGcDrawer, height, width);
14221497
} else {
@@ -1507,7 +1582,8 @@ void initAlpha_100(NSBitmapImageRep nativeRep) {
15071582

15081583
}
15091584

1510-
void initNative(String filename) {
1585+
void initNative(Path file) {
1586+
String filename = file.toString();
15111587
NSAutoreleasePool pool = null;
15121588
NSImage nativeImage = null;
15131589

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/ImageLoader.java

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2016 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -13,8 +13,9 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.graphics;
1515

16-
1716
import java.io.*;
17+
import java.nio.file.*;
18+
import java.nio.file.Path;
1819
import java.util.*;
1920

2021
import org.eclipse.swt.*;
@@ -161,7 +162,7 @@ public ImageData[] load(InputStream stream) {
161162
* an error occurs while loading the images, or if the images are
162163
* not of a supported type. Returns the loaded image data array.
163164
*
164-
* @param filename the name of the file to load the images from
165+
* @param file the name of the file to load the images from
165166
* @return an array of <code>ImageData</code> objects loaded from the specified file
166167
*
167168
* @exception IllegalArgumentException <ul>
@@ -172,17 +173,42 @@ public ImageData[] load(InputStream stream) {
172173
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
173174
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
174175
* </ul>
176+
* @since 3.129
175177
*/
176-
public ImageData[] load(String filename) {
177-
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
178-
try (InputStream stream = new FileInputStream(filename)) {
178+
public ImageData[] load(Path file) {
179+
if (file == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
180+
try (InputStream stream = Files.newInputStream(file)) {
179181
return load(stream);
180182
} catch (IOException e) {
181183
SWT.error(SWT.ERROR_IO, e);
182184
}
183185
return null;
184186
}
185187

188+
/**
189+
* Loads an array of <code>ImageData</code> objects from the
190+
* file with the specified name. Throws an error if either
191+
* an error occurs while loading the images, or if the images are
192+
* not of a supported type. Returns the loaded image data array.
193+
*
194+
* @param filename the name of the file to load the images from
195+
* @return an array of <code>ImageData</code> objects loaded from the specified file
196+
*
197+
* @exception IllegalArgumentException <ul>
198+
* <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
199+
* </ul>
200+
* @exception SWTException <ul>
201+
* <li>ERROR_IO - if an IO error occurs while reading the file</li>
202+
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
203+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
204+
* </ul>
205+
* @deprecated Instead use {@link #load(Path)}
206+
*/
207+
@Deprecated(since = "2025-03")
208+
public ImageData[] load(String filename) {
209+
return load(Path.of(filename));
210+
}
211+
186212
/**
187213
* Saves the image data in this ImageLoader to the specified stream.
188214
* The format parameter can have one of the following values:
@@ -240,7 +266,7 @@ public void save(OutputStream stream, int format) {
240266
* <dd>TIFF file format</dd>
241267
* </dl>
242268
*
243-
* @param filename the name of the file to write the images to
269+
* @param file the name of the file to write the images to
244270
* @param format the format to write the images in
245271
*
246272
* @exception IllegalArgumentException <ul>
@@ -251,16 +277,55 @@ public void save(OutputStream stream, int format) {
251277
* <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
252278
* <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
253279
* </ul>
280+
* @since 3.129
254281
*/
255-
public void save(String filename, int format) {
256-
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
257-
try (OutputStream stream = new FileOutputStream(filename)) {
282+
public void save(Path file, int format) {
283+
if (file == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
284+
try (OutputStream stream = Files.newOutputStream(file)) {
258285
save(stream, format);
259286
} catch (IOException e) {
260287
SWT.error(SWT.ERROR_IO, e);
261288
}
262289
}
263290

291+
/**
292+
* Saves the image data in this ImageLoader to a file with the specified name.
293+
* The format parameter can have one of the following values:
294+
* <dl>
295+
* <dt>{@link SWT#IMAGE_BMP}</dt>
296+
* <dd>Windows BMP file format, no compression</dd>
297+
* <dt>{@link SWT#IMAGE_BMP_RLE}</dt>
298+
* <dd>Windows BMP file format, RLE compression if appropriate</dd>
299+
* <dt>{@link SWT#IMAGE_GIF}</dt>
300+
* <dd>GIF file format</dd>
301+
* <dt>{@link SWT#IMAGE_ICO}</dt>
302+
* <dd>Windows ICO file format</dd>
303+
* <dt>{@link SWT#IMAGE_JPEG}</dt>
304+
* <dd>JPEG file format</dd>
305+
* <dt>{@link SWT#IMAGE_PNG}</dt>
306+
* <dd>PNG file format</dd>
307+
* <dt>{@link SWT#IMAGE_TIFF}</dt>
308+
* <dd>TIFF file format</dd>
309+
* </dl>
310+
*
311+
* @param filename the name of the file to write the images to
312+
* @param format the format to write the images in
313+
*
314+
* @exception IllegalArgumentException <ul>
315+
* <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
316+
* </ul>
317+
* @exception SWTException <ul>
318+
* <li>ERROR_IO - if an IO error occurs while writing to the file</li>
319+
* <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
320+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
321+
* </ul>
322+
* @deprecated Instead use {@link #save(Path, int)}
323+
*/
324+
@Deprecated(since = "2025-03")
325+
public void save(String filename, int format) {
326+
save(Path.of(filename), format);
327+
}
328+
264329
/**
265330
* Adds the listener to the collection of listeners who will be
266331
* notified when image data is either partially or completely loaded.

0 commit comments

Comments
 (0)