/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fib.view.widget;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.openflexo.fib.controller.FIBController;
import org.openflexo.fib.model.FIBImage;
import org.openflexo.fib.view.FIBWidgetView;
import org.openflexo.swing.ImageUtils;
public class FIBImageWidget extends FIBWidgetView<FIBImage, JLabel, Image> implements ImageObserver {
private static final Logger logger = Logger.getLogger(FIBImageWidget.class.getPackage().getName());
private JLabel labelWidget;
public FIBImageWidget(FIBImage model, FIBController controller) {
super(model, controller);
labelWidget = new JLabel();
labelWidget.setFocusable(false); // There is not much point in giving focus to a label since there is no KeyBindings nor KeyListener
// on it.
if (model.getData().isValid()) {
labelWidget.setText(" ");
}
updateFont();
updateAlign();
updateImage();
}
@Override
public synchronized boolean updateWidgetFromModel() {
if (modelUpdating) {
return false;
}
widgetUpdating = true;
updateImage();
widgetUpdating = false;
return false;
}
/**
* Update the model given the actual state of the widget
*/
@Override
public synchronized boolean updateModelFromWidget() {
// Read only component
return false;
}
@Override
public JLabel getJComponent() {
return labelWidget;
}
@Override
public JLabel getDynamicJComponent() {
return labelWidget;
}
protected void updateAlign() {
labelWidget.setHorizontalAlignment(getWidget().getAlign().getAlign());
}
protected void updateImage() {
if (getWidget().getData().isValid()) {
Image image = getValue();
updateImageDefaultSize(image);
labelWidget.setIcon(makeImageIcon(image));
} else if (getWidget().getImageFile() != null) {
if (getWidget().getImageFile().exists()) {
Image image = ImageUtils.loadImageFromFile(getWidget().getImageFile());
updateImageDefaultSize(image);
labelWidget.setIcon(makeImageIcon(image));
}
}
}
private ImageIcon makeImageIcon(Image image) {
if (image == null) {
return null;
}
if (getWidget() == null) {
return null;
}
switch (getWidget().getSizeAdjustment()) {
case OriginalSize:
return new ImageIcon(image);
case FitToAvailableSize:
return new ImageIcon(image.getScaledInstance(getJComponent().getWidth(), getJComponent().getHeight(), Image.SCALE_SMOOTH));
case FitToAvailableSizeRespectRatio:
int imageWidth = image.getWidth(this);
int imageHeight = image.getHeight(this);
if (imageWidth <= 0 || imageHeight <= 0) {
synchronized (this) {
logger.fine("Image is not ready, waiting...");
computeImageLater = true;
return null;
}
}
// This is just looking for troubles because it makes a loop in layout
//
if (getJComponent().getWidth() == 0 || getJComponent().getHeight() == 0) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateImage();
}
});
return new ImageIcon(image);
}
double widthRatio = (double) getJComponent().getWidth() / imageWidth;
double heightRatio = (double) getJComponent().getHeight() / imageHeight;
double ratio = widthRatio < heightRatio ? widthRatio : heightRatio;
int newWidth = (int) (imageWidth * ratio);
int newHeight = (int) (imageHeight * ratio);
return new ImageIcon(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH));
case AdjustDimensions:
return new ImageIcon(image.getScaledInstance(getWidget().getImageWidth(), getWidget().getImageHeight(), Image.SCALE_SMOOTH));
case AdjustWidth:
return new ImageIcon(image.getScaledInstance(getWidget().getImageWidth(), -1, Image.SCALE_SMOOTH));
case AdjustHeight:
return new ImageIcon(image.getScaledInstance(-1, getWidget().getImageHeight(), Image.SCALE_SMOOTH));
default:
return null;
}
}
private boolean computeImageLater = false;
private void updateImageDefaultSize(Image image) {
if (getWidget() == null || image == null) {
return;
}
if (getWidget().getImageWidth() == null) {
getWidget().setImageWidth(image.getWidth(this));
}
if (getWidget().getImageHeight() == null) {
getWidget().setImageHeight(image.getHeight(this));
}
}
@Override
public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
updateImageDefaultSize(img);
if (computeImageLater) {
logger.fine("Image can now be displayed");
computeImageLater = false;
updateImage();
}
return false;
}
}