You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
10 KiB
295 lines
10 KiB
/* |
|
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. |
|
*/ |
|
package com.fr.design.style.background.image; |
|
|
|
import com.fr.base.BaseUtils; |
|
import com.fr.base.GraphHelper; |
|
import com.fr.base.Style; |
|
import com.fr.design.gui.iscrollbar.UIScrollBar; |
|
import com.fr.general.ImageWithSuffix; |
|
|
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.stable.CoreGraphHelper; |
|
|
|
import javax.swing.JComponent; |
|
import javax.swing.JViewport; |
|
import javax.swing.Scrollable; |
|
import javax.swing.SwingConstants; |
|
import javax.swing.event.ChangeEvent; |
|
import javax.swing.event.ChangeListener; |
|
import java.awt.Dimension; |
|
import java.awt.Graphics; |
|
import java.awt.Image; |
|
import java.awt.Rectangle; |
|
import java.util.ArrayList; |
|
import java.util.List; |
|
|
|
/** |
|
* The pane use to preview image |
|
*/ |
|
public class ImagePreviewPane extends JComponent implements Scrollable, ImagePreviewer { |
|
private ImageWithSuffix image = null; |
|
// carl:image style |
|
private Style imageStyle = null; |
|
private int imageWidth = 0; |
|
private int imageHeight = 0; |
|
private boolean isLoading = false; |
|
|
|
private List<ChangeListener> changeListenerList = new ArrayList<ChangeListener>(); |
|
|
|
public ImagePreviewPane() { |
|
this.setToolTipText("View Image"); |
|
} |
|
|
|
/** |
|
* Return image |
|
*/ |
|
public Image getImage() { |
|
return image == null ? null : image.getImage(); |
|
} |
|
/** |
|
* Return image |
|
*/ |
|
public ImageWithSuffix getImageWithSuffix() { |
|
return this.image; |
|
} |
|
|
|
public void showLoading() { |
|
isLoading = true; |
|
setImage(null); |
|
repaint(); |
|
} |
|
|
|
@Override |
|
public void setImage(Image image) { |
|
|
|
setImageWithSuffix(ImageWithSuffix.build(image)); |
|
|
|
} |
|
|
|
/** |
|
* Set image. |
|
* |
|
* @param image the new image. |
|
*/ |
|
@Override |
|
public void setImageWithSuffix(ImageWithSuffix image) { |
|
this.image = image; |
|
//need to reset the size of JViewPort. |
|
if (this.image == null) { |
|
if (this.getParent() instanceof JViewport) { |
|
UIScrollBar tmpJScrollBar = new UIScrollBar(UIScrollBar.HORIZONTAL); |
|
Dimension newDimension = new Dimension( |
|
this.getSize().width - tmpJScrollBar.getPreferredSize().height, |
|
this.getSize().height - tmpJScrollBar.getPreferredSize().height); |
|
((JViewport) this.getParent()).setPreferredSize(newDimension); |
|
(this.getParent()).setSize(newDimension); |
|
((JViewport) this.getParent()).setMinimumSize(newDimension); |
|
((JViewport) this.getParent()).setMaximumSize(newDimension); |
|
} |
|
} else { |
|
//wait for the size of image. |
|
isLoading = false; |
|
CoreGraphHelper.waitForImage(image); |
|
|
|
if (image.getFineImage() != null && image.getImage() != null) { |
|
try { |
|
imageWidth = image.getWidth(null); |
|
imageHeight = image.getHeight(null); |
|
} catch (Exception e) { |
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
} |
|
} |
|
this.setToolTipText("Image Size: " + imageWidth + "x" + imageHeight + "px"); |
|
} |
|
fireChangeListener(); |
|
this.revalidate(); |
|
} |
|
|
|
/** |
|
* Paint component. |
|
*/ |
|
@Override |
|
public void paintComponent(Graphics g) { |
|
super.paintComponent(g); |
|
if (isLoading) { |
|
g.drawString(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Loading"), getWidth() / 2 - 25, getHeight() / 2); |
|
return; |
|
} |
|
if (this.getImage() != null) { //draw image. |
|
// carl:让imagePreviewPane能预览样式 |
|
if (this.getImageStyle() == null) { |
|
g.drawImage(this.getImage(), 0, 0, this); |
|
} else { |
|
GraphHelper.paintImage( |
|
g, this.getWidth(), this.getHeight(), this.getImage(), |
|
this.getImageStyle().getImageLayout(), |
|
BaseUtils.getAlignment4Horizontal(this.getImageStyle()), |
|
this.getImageStyle().getVerticalAlignment(), -1, -1 |
|
); |
|
} |
|
} |
|
} |
|
|
|
@Override |
|
public Dimension getPreferredSize() { |
|
if (this.image == null) { |
|
return super.getPreferredSize(); |
|
} |
|
|
|
return new Dimension(imageWidth, imageHeight); |
|
} |
|
|
|
/** |
|
* Add change listener. |
|
*/ |
|
public void addChangeListener(ChangeListener changeListener) { |
|
changeListenerList.add(changeListener); |
|
} |
|
|
|
/** |
|
* fire change listener when image changed. |
|
*/ |
|
private void fireChangeListener() { |
|
if (this.changeListenerList.size() > 0) { |
|
ChangeEvent evt = new ChangeEvent(this); |
|
|
|
for (int i = 0; i < changeListenerList.size(); i++) { |
|
changeListenerList.get(i).stateChanged(evt); |
|
} |
|
} |
|
} |
|
|
|
// --- Scrollable methods --------------------------------------------- |
|
|
|
/** |
|
* Returns the preferred size of the viewport for a view component. |
|
* This is implemented to do the default behavior of returning |
|
* the preferred size of the component. |
|
* |
|
* @return the <code>preferredSize</code> of a <code>JViewport</code> |
|
* whose view is this <code>Scrollable</code> |
|
*/ |
|
@Override |
|
public Dimension getPreferredScrollableViewportSize() { |
|
return getPreferredSize(); |
|
} |
|
|
|
/** |
|
* Components that display logical rows or columns should compute |
|
* the scroll increment that will completely expose one new row |
|
* or column, depending on the value of orientation. Ideally, |
|
* components should handle a partially exposed row or column by |
|
* returning the distance required to completely expose the item. |
|
* <p/> |
|
* The default implementation of this is to simply return 10% of |
|
* the visible area. Subclasses are likely to be able to provide |
|
* a much more reasonable value. |
|
* |
|
* @param visibleRect the view area visible within the viewport |
|
* @param orientation either <code>SwingConstants.VERTICAL</code> or |
|
* <code>SwingConstants.HORIZONTAL</code> |
|
* @param direction less than zero to scroll up/left, greater than |
|
* zero for down/right |
|
* @return the "unit" increment for scrolling in the specified direction |
|
* @throws IllegalArgumentException for an invalid orientation |
|
* @see javax.swing.JScrollBar#setUnitIncrement |
|
*/ |
|
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { |
|
switch (orientation) { |
|
case SwingConstants.VERTICAL: |
|
return visibleRect.height / 10; |
|
case SwingConstants.HORIZONTAL: |
|
return visibleRect.width / 10; |
|
default: |
|
throw new IllegalArgumentException("Invalid orientation: " + orientation); |
|
} |
|
} |
|
|
|
|
|
/** |
|
* Components that display logical rows or columns should compute |
|
* the scroll increment that will completely expose one block |
|
* of rows or columns, depending on the value of orientation. |
|
* <p/> |
|
* The default implementation of this is to simply return the visible |
|
* area. Subclasses will likely be able to provide a much more |
|
* reasonable value. |
|
* |
|
* @param visibleRect the view area visible within the viewport |
|
* @param orientation either <code>SwingConstants.VERTICAL</code> or |
|
* <code>SwingConstants.HORIZONTAL</code> |
|
* @param direction less than zero to scroll up/left, greater than zero |
|
* for down/right |
|
* @return the "block" increment for scrolling in the specified direction |
|
* @throws IllegalArgumentException for an invalid orientation |
|
* @see javax.swing.JScrollBar#setBlockIncrement |
|
*/ |
|
@Override |
|
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { |
|
switch (orientation) { |
|
case SwingConstants.VERTICAL: |
|
return visibleRect.height; |
|
case SwingConstants.HORIZONTAL: |
|
return visibleRect.width; |
|
default: |
|
throw new IllegalArgumentException("Invalid orientation: " + orientation); |
|
} |
|
} |
|
|
|
|
|
/** |
|
* Returns true if a viewport should always force the width of this |
|
* <code>Scrollable</code> to match the width of the viewport. |
|
* For example a normal text view that supported line wrapping |
|
* would return true here, since it would be undesirable for |
|
* wrapped lines to disappear beyond the right |
|
* edge of the viewport. Note that returning true for a |
|
* <code>Scrollable</code> whose ancestor is a <code>JScrollPane</code> |
|
* effectively disables horizontal scrolling. |
|
* <p/> |
|
* Scrolling containers, like <code>JViewport</code>, |
|
* will use this method each time they are validated. |
|
* |
|
* @return true if a viewport should force the <code>Scrollable</code>s |
|
* width to match its own |
|
*/ |
|
@Override |
|
public boolean getScrollableTracksViewportWidth() { |
|
if (getParent() instanceof JViewport) { |
|
return (getParent().getWidth() > getPreferredSize().width); |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* Returns true if a viewport should always force the height of this |
|
* <code>Scrollable</code> to match the height of the viewport. |
|
* For example a columnar text view that flowed text in left to |
|
* right columns could effectively disable vertical scrolling by |
|
* returning true here. |
|
* <p/> |
|
* Scrolling containers, like <code>JViewport</code>, |
|
* will use this method each time they are validated. |
|
* |
|
* @return true if a viewport should force the Scrollables height |
|
* to match its own |
|
*/ |
|
@Override |
|
public boolean getScrollableTracksViewportHeight() { |
|
if (getParent() instanceof JViewport) { |
|
return (getParent().getHeight() > getPreferredSize().height); |
|
} |
|
return false; |
|
} |
|
|
|
@Override |
|
public void setImageStyle(Style imageStyle) { |
|
this.imageStyle = imageStyle; |
|
} |
|
|
|
public Style getImageStyle() { |
|
return imageStyle; |
|
} |
|
} |