blob: 0a0cc8498722bb205485ed89f2317712fe44715d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* http://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.
*/
/**
* @author Dmitry A. Durnev
* @version $Revision$
*/
package java.awt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.harmony.awt.internal.nls.Messages;
import org.apache.harmony.awt.wtk.NativeCursor;
/**
* The Cursor class represents the bitmap of the mouse cursor.
*
* @since Android 1.0
*/
public class Cursor implements Serializable {
/**
* The Constant serialVersionUID.
*/
private static final long serialVersionUID = 8028237497568985504L;
/**
* The Constant DEFAULT_CURSOR indicates the default cursor type.
*/
public static final int DEFAULT_CURSOR = 0;
/**
* The Constant CROSSHAIR_CURSOR cursor type.
*/
public static final int CROSSHAIR_CURSOR = 1;
/**
* The Constant TEXT_CURSOR cursor type.
*/
public static final int TEXT_CURSOR = 2;
/**
* The Constant WAIT_CURSOR cursor type.
*/
public static final int WAIT_CURSOR = 3;
/**
* The Constant SW_RESIZE_CURSOR cursor type.
*/
public static final int SW_RESIZE_CURSOR = 4;
/**
* The Constant SE_RESIZE_CURSOR cursor type.
*/
public static final int SE_RESIZE_CURSOR = 5;
/**
* The Constant NW_RESIZE_CURSOR cursor type.
*/
public static final int NW_RESIZE_CURSOR = 6;
/**
* The Constant NE_RESIZE_CURSOR cursor type.
*/
public static final int NE_RESIZE_CURSOR = 7;
/**
* The Constant N_RESIZE_CURSOR cursor type.
*/
public static final int N_RESIZE_CURSOR = 8;
/**
* The Constant S_RESIZE_CURSOR cursor type.
*/
public static final int S_RESIZE_CURSOR = 9;
/**
* The Constant W_RESIZE_CURSOR cursor type.
*/
public static final int W_RESIZE_CURSOR = 10;
/**
* The Constant E_RESIZE_CURSOR cursor type.
*/
public static final int E_RESIZE_CURSOR = 11;
/**
* The Constant HAND_CURSOR cursor type.
*/
public static final int HAND_CURSOR = 12;
/**
* The Constant MOVE_CURSOR cursor type.
*/
public static final int MOVE_CURSOR = 13;
/**
* A mapping from names to system custom cursors.
*/
static Map<String, Cursor> systemCustomCursors;
/**
* The cursor props.
*/
static Properties cursorProps;
/**
* The Constant predefinedNames.
*/
static final String[] predefinedNames = {
"Default", "Crosshair", "Text", "Wait", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"Southwest Resize", "Southeast Resize", //$NON-NLS-1$ //$NON-NLS-2$
"Northwest Resize", "Northeast Resize", //$NON-NLS-1$ //$NON-NLS-2$
"North Resize", "South Resize", "West Resize", "East Resize", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"Hand", "Move" //$NON-NLS-1$ //$NON-NLS-2$
};
/**
* The predefined set of cursors.
*/
protected static Cursor[] predefined = {
new Cursor(DEFAULT_CURSOR), null, null, null, null, null, null, null, null, null, null,
null, null, null
};
/**
* The Constant CUSTOM_CURSOR is associated with all custom cursor types.
* (Those which are not predefined)
*/
public static final int CUSTOM_CURSOR = -1;
/**
* The name of the cursor.
*/
protected String name;
/**
* The type of the cursor, chosen from the list of cursor type constants.
*/
private final int type;
/**
* The native cursor.
*/
private transient NativeCursor nativeCursor;
/**
* The exact point on the cursor image that indicates which point the cursor
* is selecting (pointing to). The coordinates are given with respect the
* origin of the Image (its upper left corner).
*/
private Point hotSpot;
/**
* The image to draw on the screen representing the cursor.
*/
private Image image;
/**
* Instantiates a new cursor with the specified name.
*
* @param name
* the name of cursor.
*/
protected Cursor(String name) {
this(name, null, new Point());
}
/**
* Instantiates a new cursor of the specified type.
*
* @param type
* the type of cursor.
*/
public Cursor(int type) {
checkType(type);
this.type = type;
if ((type >= 0) && (type < predefinedNames.length)) {
name = predefinedNames[type] + " Cursor"; //$NON-NLS-1$
}
}
/**
* Instantiates a new cursor.
*
* @param name
* the name.
* @param img
* the img.
* @param hotSpot
* the hot spot.
*/
Cursor(String name, Image img, Point hotSpot) {
this.name = name;
type = CUSTOM_CURSOR;
this.hotSpot = hotSpot;
image = img;
}
/**
* Finalize method overrides the finalize method from Object class.
*
* @throws Throwable
* if the native cursor is not null and throws a Throwable when
* destroyed.
*/
@Override
protected void finalize() throws Throwable {
if (nativeCursor != null) {
nativeCursor.destroyCursor();
}
}
/**
* Gets the name of the cursor.
*
* @return the name of the cursor.
*/
public String getName() {
return name;
}
/**
* Returns the String representation of the cursor.
*
* @return the String representation of the cursor.
*/
@Override
public String toString() {
return getClass().getName() + "[" + name + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Gets the cursor type.
*
* @return the cursor type.
*/
public int getType() {
return type;
}
/**
* Gets the predefined cursor with the specified type.
*
* @param type
* the type of cursor.
* @return the predefined cursor with the specified type.
*/
public static Cursor getPredefinedCursor(int type) {
checkType(type);
Cursor cursor = predefined[type];
if (cursor == null) {
cursor = new Cursor(type);
predefined[type] = cursor;
}
return cursor;
}
/**
* Gets the default cursor.
*
* @return the default cursor.
*/
public static Cursor getDefaultCursor() {
return getPredefinedCursor(DEFAULT_CURSOR);
}
/**
* Gets the specified system custom cursor.
*
* @param name
* the name of the desired system cursor.
* @return the specific system cursor with the specified name.
* @throws AWTException
* if the desired cursor has malformed data such as an
* incorrectly defined hot spot.
* @throws HeadlessException
* if the isHeadless method of the GraphicsEnvironment returns
* true.
*/
public static Cursor getSystemCustomCursor(String name) throws AWTException, HeadlessException {
Toolkit.checkHeadless();
return getSystemCustomCursorFromMap(name);
}
/**
* Gets the specified system custom cursor from the map of system custom
* cursors.
*
* @param name
* the name of the desired cursor.
* @return the desired system custom cursor from the map of system custom
* cursors.
* @throws AWTException
* the AWT exception.
*/
private static Cursor getSystemCustomCursorFromMap(String name) throws AWTException {
loadCursorProps();
if (systemCustomCursors == null) {
systemCustomCursors = new HashMap<String, Cursor>();
}
Cursor cursor = systemCustomCursors.get(name);
if (cursor != null) {
return cursor;
}
// awt.141=failed to parse hotspot property for cursor:
String exMsg = Messages.getString("awt.141") + name; //$NON-NLS-1$
String nm = "Cursor." + name; //$NON-NLS-1$
String nameStr = cursorProps.getProperty(nm + ".Name"); //$NON-NLS-1$
String hotSpotStr = cursorProps.getProperty(nm + ".HotSpot"); //$NON-NLS-1$
String fileStr = cursorProps.getProperty(nm + ".File"); //$NON-NLS-1$
int idx = hotSpotStr.indexOf(',');
if (idx < 0) {
throw new AWTException(exMsg);
}
int x, y;
try {
x = new Integer(hotSpotStr.substring(0, idx)).intValue();
y = new Integer(hotSpotStr.substring(idx + 1, hotSpotStr.length())).intValue();
} catch (NumberFormatException nfe) {
throw new AWTException(exMsg);
}
Image img = Toolkit.getDefaultToolkit().createImage(fileStr);
cursor = new Cursor(nameStr, img, new Point(x, y));
systemCustomCursors.put(name, cursor);
return cursor;
}
/**
* Load cursor props.
*
* @throws AWTException
* the AWT exception.
*/
private static void loadCursorProps() throws AWTException {
if (cursorProps != null) {
return;
}
String sep = File.separator;
String cursorsDir = "lib" + sep + "images" + sep + "cursors"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String cursorsAbsDir = System.getProperty("java.home") + sep + //$NON-NLS-1$
cursorsDir;
String cursorPropsFileName = "cursors.properties"; //$NON-NLS-1$
String cursorPropsFullFileName = (cursorsAbsDir + sep + cursorPropsFileName);
cursorProps = new Properties();
try {
cursorProps.load(new FileInputStream(new File(cursorPropsFullFileName)));
} catch (FileNotFoundException e) {
// awt.142=Exception: class {0} {1} occurred while loading: {2}
throw new AWTException(Messages.getString("awt.142",//$NON-NLS-1$
new Object[] {
e.getClass(), e.getMessage(), cursorPropsFullFileName
}));
} catch (IOException e) {
throw new AWTException(e.getMessage());
}
}
/**
* Check type.
*
* @param type
* the type.
*/
static void checkType(int type) {
// can't use predefined array here because it may not have been
// initialized yet
if ((type < 0) || (type >= predefinedNames.length)) {
// awt.143=illegal cursor type
throw new IllegalArgumentException(Messages.getString("awt.143")); //$NON-NLS-1$
}
}
// "lazily" create native cursors:
/**
* Gets the native cursor.
*
* @return the native cursor.
*/
NativeCursor getNativeCursor() {
if (nativeCursor != null) {
return nativeCursor;
}
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (type != CUSTOM_CURSOR) {
nativeCursor = toolkit.createNativeCursor(type);
} else {
nativeCursor = toolkit.createCustomNativeCursor(image, hotSpot, name);
}
return nativeCursor;
}
/**
* Sets the native cursor.
*
* @param nativeCursor
* the new native cursor.
*/
void setNativeCursor(NativeCursor nativeCursor) {
this.nativeCursor = nativeCursor;
}
}