📄 myimageview.java
字号:
package wotlas.utils;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.ImageObserver;
import java.io.*;
import java.net.*;
import java.util.Dictionary;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.event.*;
/**
* Enhanced Image View for HTML documents. Thanks to JavaWorld for the tip.
*/
public class MyImageView extends View implements ImageObserver, MouseListener,
MouseMotionListener
{
// --- Attribute Values ------------------------------------------
public static final String
TOP = "top",
TEXTTOP = "texttop",
MIDDLE = "middle",
ABSMIDDLE = "absmiddle",
CENTER = "center",
BOTTOM = "bottom";
// --- Construction ----------------------------------------------
/**
* Creates a new view that represents an IMG element.
*
* @param elem the element to create a view for
*/
public MyImageView(Element elem) {
super(elem);
initialize(elem);
StyleSheet sheet = getStyleSheet();
attr = sheet.getViewAttributes(this);
}
private void initialize( Element elem ) {
synchronized(this) {
loading = true;
fWidth = fHeight = 0;
}
int width = 0;
int height = 0;
boolean customWidth = false;
boolean customHeight = false;
try {
fElement = elem;
// Request image from document's cache:
AttributeSet attr = elem.getAttributes();
if (isURL()) {
URL src = getSourceURL();
if( src != null ) {
Dictionary cache = (Dictionary) getDocument().getProperty(IMAGE_CACHE_PROPERTY);
if( cache != null )
fImage = (Image) cache.get(src);
else
fImage = Toolkit.getDefaultToolkit().getImage(src);
}
}
else {
/******** Code to load from relative path *************/
String src =
(String) fElement.getAttributes().getAttribute
(HTML.Attribute.SRC);
//System.out.println("before src: " + src);
src = processSrcPath(src);
fImage = Toolkit.getDefaultToolkit().getImage(src);
if(fImage==null) {
URL imUrl = getClass().getResource(src);
fImage = Toolkit.getDefaultToolkit().getImage(imUrl);
}
if(fImage!=null)
try { waitForImage(); }
catch (InterruptedException e) { fImage = null; }
/******************************************************/
}
// Get height/width from params or image or defaults:
height = getIntAttr(HTML.Attribute.HEIGHT,-1);
customHeight = (height>0);
if( !customHeight && fImage != null )
height = fImage.getHeight(this);
if( height <= 0 )
height = DEFAULT_HEIGHT;
width = getIntAttr(HTML.Attribute.WIDTH,-1);
customWidth = (width>0);
if( !customWidth && fImage != null )
width = fImage.getWidth(this);
if( width <= 0 )
width = DEFAULT_WIDTH;
// Make sure the image starts loading:
if( fImage != null )
if( customWidth && customHeight )
Toolkit.getDefaultToolkit().prepareImage(fImage,height,
width,this);
else
Toolkit.getDefaultToolkit().prepareImage(fImage,-1,-1,
this);
/********************************************************
// Rob took this out. Changed scope of src.
if( DEBUG ) {
if( fImage != null )
System.out.println("ImageInfo: new on "+src+
" ("+fWidth+"x"+fHeight+")");
else
System.out.println("ImageInfo: couldn't get image at "+
src);
if(isLink())
System.out.println(" It's a link! Border = "+
getBorder());
//((AbstractDocument.AbstractElement)elem).dump(System.out,4);
}
********************************************************/
} finally {
synchronized(this) {
loading = false;
if (customWidth || fWidth == 0) {
fWidth = width;
}
if (customHeight || fHeight == 0) {
fHeight = height;
}
}
}
}
/** Determines if path is in the form of a URL */
private boolean isURL() {
return true;
/* THIS CODE IS TOO RESTRICTIVE :
String src =
(String) fElement.getAttributes().getAttribute(HTML.Attribute.SRC);
return src.toLowerCase().startsWith("file") ||
src.toLowerCase().startsWith("http"); */
}
/** Checks to see if the absolute path is availabe thru an application
global static variable or thru a system variable. If so, appends
the relative path to the absolute path and returns the String. */
private String processSrcPath(String src) {
String val = src;
File imageFile = new File(src);
if (imageFile.isAbsolute()) return src;
//try to get application images path...
/*if (PicTest.ApplicationImagePath != null) {
String imagePath = PicTest.ApplicationImagePath;
val = (new File(imagePath, imageFile.getPath())).toString();
}*/
//try to get system images path...
else {
String imagePath = System.getProperty("system.image.path.key");
if (imagePath != null) {
val = (new File(imagePath, imageFile.getPath())).toString();
}
}
//System.out.println("src before: " + src + ", src after: " + val);
return val;
}
/** Added this guy to make sure an image is loaded - ie no broken
images. So far its used only for images loaded off the disk (non-URL).
It seems to work marvelously. By the way, it does the same thing as
MediaTracker, but you dont need to know the component its being
rendered on. Rob */
private void waitForImage() throws InterruptedException {
int w = fImage.getWidth(this);
int h = fImage.getHeight(this);
while (true) {
int flags = Toolkit.getDefaultToolkit().checkImage(fImage, w, h, this);
if ( ((flags & ERROR) != 0) || ((flags & ABORT) != 0 ) )
throw new InterruptedException();
else if ((flags & (ALLBITS | FRAMEBITS)) != 0)
return;
Thread.sleep(10);
//System.out.println("rise and shine...");
}
}
/**
* Fetches the attributes to use when rendering. This is
* implemented to multiplex the attributes specified in the
* model with a StyleSheet.
*/
public AttributeSet getAttributes() {
return attr;
}
/** Is this image within a link? */
boolean isLink( ) {
//! It would be nice to cache this but in an editor it can change
// See if I have an HREF attribute courtesy of the enclosing A tag:
AttributeSet anchorAttr = (AttributeSet)
fElement.getAttributes().getAttribute(HTML.Tag.A);
if (anchorAttr != null) {
return anchorAttr.isDefined(HTML.Attribute.HREF);
}
return false;
}
/** Returns the size of the border to use. */
int getBorder( ) {
return getIntAttr(HTML.Attribute.BORDER, isLink() ?DEFAULT_BORDER :0);
}
/** Returns the amount of extra space to add along an axis. */
int getSpace( int axis ) {
return getIntAttr( axis==X_AXIS ?HTML.Attribute.HSPACE :HTML.Attribute.VSPACE,
0 );
}
/** Returns the border's color, or null if this is not a link. */
Color getBorderColor( ) {
StyledDocument doc = (StyledDocument) getDocument();
return doc.getForeground(getAttributes());
}
/** Returns the image's vertical alignment.
*/
float getVerticalAlignment() {
String align = (String) fElement.getAttributes().getAttribute(HTML.Attribute.ALIGN);
if ( align != null ) {
align = align.toLowerCase();
if ( align.equals(TOP) || align.equals(TEXTTOP) )
return 0.0f;
else if ( align.equals(this.CENTER) || align.equals(MIDDLE) || align.equals(ABSMIDDLE) )
return 0.5f;
}
return 1.0f; // default alignment is bottom
}
/**
*/
boolean hasPixels( ImageObserver obs ) {
return fImage != null && fImage.getHeight(obs)>0 && fImage.getWidth(obs)>0;
}
/** Return a URL for the image source,
* or null if it could not be determined.
*/
private URL getSourceURL( ) {
String src = (String) fElement.getAttributes().getAttribute(HTML.Attribute.SRC);
if ( src==null ) return null;
URL reference = ((HTMLDocument)getDocument()).getBase();
try {
URL u = new URL(reference,src);
return u;
} catch (MalformedURLException e) {
return null;
}
}
/** Look up an integer-valued attribute. <b>Not</b> recursive.
*/
private int getIntAttr(HTML.Attribute name, int deflt ) {
AttributeSet attr = fElement.getAttributes();
if ( attr.isDefined(name) ) { // does not check parents!
int i;
String val = (String) attr.getAttribute(name);
if ( val == null )
i = deflt;
else
try {
i = Math.max(0, Integer.parseInt(val));
} catch( NumberFormatException x ) {
i = deflt;
}
return i;
} else
return deflt;
}
/** Establishes the parent view for this view.
* Seize this moment to cache the AWT Container I'm in.
*/
public void setParent(View parent) {
super.setParent(parent);
fContainer = parent!=null ?getContainer() :null;
if ( parent==null && fComponent!=null ) {
fComponent.getParent().remove(fComponent);
fComponent = null;
}
}
/** My attributes may have changed.
*/
public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
if (DEBUG)
System.out.println("ImageView: changedUpdate begin...");
super.changedUpdate(e,a,f);
float align = getVerticalAlignment();
int height = fHeight;
int width = fWidth;
initialize(getElement());
boolean hChanged = fHeight!=height;
boolean wChanged = fWidth!=width;
if( hChanged || wChanged || getVerticalAlignment()!=align ) {
if (DEBUG)
System.out.println("ImageView: calling preferenceChanged");
getParent().preferenceChanged(this,hChanged,wChanged);
}
if (DEBUG)
System.out.println("ImageView: changedUpdate end; valign="+getVerticalAlignment());
}
// --- Painting --------------------------------------------------------
/** Paints the image.
*
* @param g the rendering surface to use
* @param a the allocated region to render into
* @see View#paint
*/
public void paint(Graphics g, Shape a) {
Color oldColor = g.getColor();
fBounds = a.getBounds();
int border = getBorder();
int x = fBounds.x + border + getSpace(X_AXIS);
int y = fBounds.y + border + getSpace(Y_AXIS);
int width = fWidth;
int height = fHeight;
int sel = getSelectionState();
// Make sure my Component is in the right place:
/*
if ( fComponent == null ) {
fComponent = new Component() { };
fComponent.addMouseListener(this);
fComponent.addMouseMotionListener(this);
fComponent.setCursor(Cursor.getDefaultCursor()); // use arrow cursor
fContainer.add(fComponent);
}
fComponent.setBounds(x,y,width,height);
*/
// If no pixels yet, draw gray outline and icon:
if ( ! hasPixels(this) ) {
g.setColor(Color.lightGray);
g.drawRect(x,y,width-1,height-1);
g.setColor(oldColor);
loadIcons();
Icon icon = fImage==null ?sMissingImageIcon :sPendingImageIcon;
if ( icon != null )
icon.paintIcon(getContainer(), g, x, y);
}
// Draw image:
if ( fImage != null ) {
g.drawImage(fImage,x, y,width,height,this);
// Use the following instead of g.drawImage when
// BufferedImageGraphics2D.setXORMode is fixed (4158822).
// Use Xor mode when selected/highlighted.
//! Could darken image instead, but it would be more expensive.
/*
if( sel > 0 )
g.setXORMode(Color.white);
g.drawImage(fImage,x,y,width,height,this);
if( sel > 0 )
g.setPaintMode();
*/
}
// If selected exactly, we need a black border & grow-box:
Color bc = getBorderColor();
if ( sel == 2 ) {
// Make sure there's room for a border:
int delta = 2-border;
if ( delta > 0 ) {
x += delta;
y += delta;
width -= delta<<1;
height -= delta<<1;
border = 2;
}
bc = null;
g.setColor(Color.black);
// Draw grow box:
g.fillRect(x+width-5,y+height-5,5,5);
}
// Draw border:
if ( border > 0 ) {
if ( bc != null )
g.setColor(bc);
// Draw a thick rectangle:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -