All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diffplug.common.swt.jface.ImageDescriptors Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 DiffPlug
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.diffplug.common.swt.jface;


import com.diffplug.common.base.Box;
import com.diffplug.common.base.Errors;
import com.diffplug.common.base.Unhandled;
import com.diffplug.common.swt.OnePerWidget;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Widget;

/** Utilities for using {@link ImageDescriptor}s correctly. */
public class ImageDescriptors {
	/** Creates an image from the given data, and disposes it when the lifecycle widget is disposed. */
	public static Image createManagedImage(ImageData data, Widget lifecycle) {
		Image image = new Image(lifecycle.getDisplay(), data);
		lifecycle.addListener(SWT.Dispose, e -> {
			image.dispose();
		});
		return image;
	}

	/**
	 * {@link ImageDescriptor} allows an {@link Image} to be shared in a pool using reference counting. In order to not screw-up the reference
	 * counting, you need to be pretty careful with how you use them.
	 * 

* This creates a {@link com.diffplug.common.base.Box.Nullable Box.Nullable<ImageDescriptor>} which sets and gets images in a way that will keep the reference counting happy. *

* NO ONE MUST SET THE IMAGE EXCEPT THIS SETTER. * * @param lifecycle Any outstanding images will be destroyed with the lifecycle of this Widget. * @param imageGetter Function which returns the image currently on the Widget (used to ensure that nobody messed with it). * @param imageSetter Function which sets the image on the Widget. * @return A `Box.Nullable` for setting the {@link Image} using an {@link ImageDescriptor}. */ public static Box.Nullable createSetter(Widget lifecycle, Supplier imageGetter, Consumer imageSetter) { return new Box.Nullable() { private ImageDescriptor lastDesc; private Image lastImg; { // when the control is disposed, we'll clear the image lifecycle.addListener(SWT.Dispose, e -> { if (lastDesc != null) { lastDesc.destroyResource(lastImg); } }); } @Override public ImageDescriptor get() { return lastDesc; } @Override public void set(ImageDescriptor newDesc) { // make sure nobody else messed with the image if (!Objects.equals(imageGetter.get(), lastImg)) { // if someone else did mess with it, we can probably survive, so best to just // log the failure and continue with setting the image Errors.log().accept(new IllegalStateException("Setter must have exclusive control over the image field.")); } // set the new image Image newImg; if (newDesc != null) { newImg = (Image) newDesc.createResource(lifecycle.getDisplay()); } else { newImg = null; } imageSetter.accept(newImg); // if an image was already set, destroy it if (lastDesc != null) { lastDesc.destroyResource(lastImg); } // save the fields for the next go-round lastDesc = newDesc; lastImg = newImg; } }; } /** Global cache of widget -> image descriptor setters. */ private static final OnePerWidget> globalSetter = OnePerWidget.from((Widget widget) -> { if (widget instanceof Item) { Item cast = (Item) widget; return createSetter(cast, cast::getImage, cast::setImage); } else if (widget instanceof Button) { Button cast = (Button) widget; return createSetter(cast, cast::getImage, cast::setImage); } else if (widget instanceof Label) { Label cast = (Label) widget; return createSetter(cast, cast::getImage, cast::setImage); } else { throw Unhandled.classException(widget); } }); /** Sets the given {@link Item} to have the image described by the given descriptor, maintaining proper reference counting. */ public static void set(Item widget, ImageDescriptor image) { globalSetter.forWidget(widget).set(image); } /** Sets the given {@link Button} to have the image described by the given descriptor, maintaining proper reference counting. */ public static void set(Button widget, ImageDescriptor image) { globalSetter.forWidget(widget).set(image); } /** Sets the given {@link Label} to have the image described by the given descriptor, maintaining proper reference counting. */ public static void set(Label widget, ImageDescriptor image) { globalSetter.forWidget(widget).set(image); } private static final OnePerWidget> globalPool = OnePerWidget.from(widget -> { Map map = new HashMap<>(); widget.addListener(SWT.Dispose, e -> map.values().forEach(Image::dispose)); return map; }); /** Returns an image which will be bound to the lifecycle of the owner widget. */ public static Image getFromPool(Widget owner, ImageDescriptor descriptor) { Map map = globalPool.forWidget(owner); Image image = map.get(descriptor); if (image == null) { image = descriptor.createImage(true, owner.getDisplay()); map.put(descriptor, image); } return image; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy