8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,602 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.applet;
import java.awt.*;
import java.awt.image.ColorModel;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Hashtable;
import java.util.Locale;
import javax.accessibility.*;
/**
* An applet is a small program that is intended not to be run on
* its own, but rather to be embedded inside another application.
* <p>
* The {@code Applet} class must be the superclass of any
* applet that is to be embedded in a Web page or viewed by the Java
* Applet Viewer. The {@code Applet} class provides a standard
* interface between applets and their environment.
*
* @author Arthur van Hoff
* @author Chris Warth
* @since 1.0
*
* @deprecated The Applet API is deprecated. See the
* <a href="package-summary.html"> java.applet package documentation</a>
* for further information.
*/
@Deprecated(since = "9")
public class Applet extends Panel {
/**
* Constructs a new Applet.
* <p>
* Note: Many methods in {@code java.applet.Applet}
* may be invoked by the applet only after the applet is
* fully constructed; applet should avoid calling methods
* in {@code java.applet.Applet} in the constructor.
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.4
*/
public Applet() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
}
/**
* Applets can be serialized but the following conventions MUST be followed:
*
* Before Serialization:
* An applet must be in STOPPED state.
*
* After Deserialization:
* The applet will be restored in STOPPED state (and most clients will
* likely move it into RUNNING state).
* The stub field will be restored by the reader.
*/
private transient AppletStub stub;
/* version ID for serialized form. */
private static final long serialVersionUID = -5836846270535785031L;
/**
* Read an applet from an object input stream.
* @param s an object input stream.
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless()} returns
* {@code true}
* @serial
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.4
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
s.defaultReadObject();
}
/**
* Sets this applet's stub. This is done automatically by the system.
* <p>If there is a security manager, its {@code checkPermission}
* method is called with the
* {@code AWTPermission("setAppletStub")}
* permission if a stub has already been set.
* @param stub the new stub.
* @exception SecurityException if the caller cannot set the stub
*/
public final void setStub(AppletStub stub) {
if (this.stub != null) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
s.checkPermission(new AWTPermission("setAppletStub"));
}
}
this.stub = stub;
}
/**
* Determines if this applet is active. An applet is marked active
* just before its {@code start} method is called. It becomes
* inactive just before its {@code stop} method is called.
*
* @return {@code true} if the applet is active;
* {@code false} otherwise.
* @see java.applet.Applet#start()
* @see java.applet.Applet#stop()
*/
public boolean isActive() {
if (stub != null) {
return stub.isActive();
} else { // If stub field not filled in, applet never active
return false;
}
}
/**
* Gets the URL of the document in which this applet is embedded.
* For example, suppose an applet is contained
* within the document:
* <blockquote><pre>
* http://www.oracle.com/technetwork/java/index.html
* </pre></blockquote>
* The document base is:
* <blockquote><pre>
* http://www.oracle.com/technetwork/java/index.html
* </pre></blockquote>
*
* @return the {@link java.net.URL} of the document that contains this
* applet.
* @see java.applet.Applet#getCodeBase()
*/
public URL getDocumentBase() {
return stub.getDocumentBase();
}
/**
* Gets the base URL. This is the URL of the directory which contains this applet.
*
* @return the base {@link java.net.URL} of
* the directory which contains this applet.
* @see java.applet.Applet#getDocumentBase()
*/
public URL getCodeBase() {
return stub.getCodeBase();
}
/**
* Returns the value of the named parameter in the HTML tag. For
* example, if this applet is specified as
* <blockquote><pre>
* &lt;applet code="Clock" width=50 height=50&gt;
* &lt;param name=Color value="blue"&gt;
* &lt;/applet&gt;
* </pre></blockquote>
* <p>
* then a call to {@code getParameter("Color")} returns the
* value {@code "blue"}.
* <p>
* The {@code name} argument is case insensitive.
*
* @param name a parameter name.
* @return the value of the named parameter,
* or {@code null} if not set.
*/
public String getParameter(String name) {
return stub.getParameter(name);
}
/**
* Determines this applet's context, which allows the applet to
* query and affect the environment in which it runs.
* <p>
* This environment of an applet represents the document that
* contains the applet.
*
* @return the applet's context.
*/
public AppletContext getAppletContext() {
return stub.getAppletContext();
}
/**
* Requests that this applet be resized.
*
* @param width the new requested width for the applet.
* @param height the new requested height for the applet.
*/
@SuppressWarnings("deprecation")
public void resize(int width, int height) {
Dimension d = size();
if ((d.width != width) || (d.height != height)) {
super.resize(width, height);
if (stub != null) {
stub.appletResize(width, height);
}
}
}
/**
* Requests that this applet be resized.
*
* @param d an object giving the new width and height.
*/
@SuppressWarnings("deprecation")
public void resize(Dimension d) {
resize(d.width, d.height);
}
/**
* Indicates if this container is a validate root.
* <p>
* {@code Applet} objects are the validate roots, and, therefore, they
* override this method to return {@code true}.
*
* @return {@code true}
* @since 1.7
* @see java.awt.Container#isValidateRoot
*/
@Override
public boolean isValidateRoot() {
return true;
}
/**
* Requests that the argument string be displayed in the
* "status window". Many browsers and applet viewers
* provide such a window, where the application can inform users of
* its current state.
*
* @param msg a string to display in the status window.
*/
public void showStatus(String msg) {
getAppletContext().showStatus(msg);
}
/**
* Returns an {@code Image} object that can then be painted on
* the screen. The {@code url} that is passed as an argument
* must specify an absolute URL.
* <p>
* This method always returns immediately, whether or not the image
* exists. When this applet attempts to draw the image on the screen,
* the data will be loaded. The graphics primitives that draw the
* image will incrementally paint on the screen.
*
* @param url an absolute URL giving the location of the image.
* @return the image at the specified URL.
* @see java.awt.Image
*/
public Image getImage(URL url) {
return getAppletContext().getImage(url);
}
/**
* Returns an {@code Image} object that can then be painted on
* the screen. The {@code url} argument must specify an absolute
* URL. The {@code name} argument is a specifier that is
* relative to the {@code url} argument.
* <p>
* This method always returns immediately, whether or not the image
* exists. When this applet attempts to draw the image on the screen,
* the data will be loaded. The graphics primitives that draw the
* image will incrementally paint on the screen.
*
* @param url an absolute URL giving the base location of the image.
* @param name the location of the image, relative to the
* {@code url} argument.
* @return the image at the specified URL.
* @see java.awt.Image
*/
public Image getImage(URL url, String name) {
try {
return getImage(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}
/**
* Get an audio clip from the given URL.
*
* @param url points to the audio clip
* @return the audio clip at the specified URL.
*
* @since 1.2
*/
public static final AudioClip newAudioClip(URL url) {
return new sun.applet.AppletAudioClip(url);
}
/**
* Returns the {@code AudioClip} object specified by the
* {@code URL} argument.
* <p>
* This method always returns immediately, whether or not the audio
* clip exists. When this applet attempts to play the audio clip, the
* data will be loaded.
*
* @param url an absolute URL giving the location of the audio clip.
* @return the audio clip at the specified URL.
* @see java.applet.AudioClip
*/
public AudioClip getAudioClip(URL url) {
return getAppletContext().getAudioClip(url);
}
/**
* Returns the {@code AudioClip} object specified by the
* {@code URL} and {@code name} arguments.
* <p>
* This method always returns immediately, whether or not the audio
* clip exists. When this applet attempts to play the audio clip, the
* data will be loaded.
*
* @param url an absolute URL giving the base location of the
* audio clip.
* @param name the location of the audio clip, relative to the
* {@code url} argument.
* @return the audio clip at the specified URL.
* @see java.applet.AudioClip
*/
public AudioClip getAudioClip(URL url, String name) {
try {
return getAudioClip(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}
/**
* Returns information about this applet. An applet should override
* this method to return a {@code String} containing information
* about the author, version, and copyright of the applet.
* <p>
* The implementation of this method provided by the
* {@code Applet} class returns {@code null}.
*
* @return a string containing information about the author, version, and
* copyright of the applet.
*/
public String getAppletInfo() {
return null;
}
/**
* Gets the locale of the applet. It allows the applet
* to maintain its own locale separated from the locale
* of the browser or appletviewer.
*
* @return the locale of the applet; if no locale has
* been set, the default locale is returned.
* @since 1.1
*/
public Locale getLocale() {
Locale locale = super.getLocale();
if (locale == null) {
return Locale.getDefault();
}
return locale;
}
/**
* Returns information about the parameters that are understood by
* this applet. An applet should override this method to return an
* array of {@code Strings} describing these parameters.
* <p>
* Each element of the array should be a set of three
* {@code Strings} containing the name, the type, and a
* description. For example:
* <blockquote><pre>
* String pinfo[][] = {
* {"fps", "1-10", "frames per second"},
* {"repeat", "boolean", "repeat image loop"},
* {"imgs", "url", "images directory"}
* };
* </pre></blockquote>
* <p>
* The implementation of this method provided by the
* {@code Applet} class returns {@code null}.
*
* @return an array describing the parameters this applet looks for.
*/
public String[][] getParameterInfo() {
return null;
}
/**
* Plays the audio clip at the specified absolute URL. Nothing
* happens if the audio clip cannot be found.
*
* @param url an absolute URL giving the location of the audio clip.
*/
public void play(URL url) {
AudioClip clip = getAudioClip(url);
if (clip != null) {
clip.play();
}
}
/**
* Plays the audio clip given the URL and a specifier that is
* relative to it. Nothing happens if the audio clip cannot be found.
*
* @param url an absolute URL giving the base location of the
* audio clip.
* @param name the location of the audio clip, relative to the
* {@code url} argument.
*/
public void play(URL url, String name) {
AudioClip clip = getAudioClip(url, name);
if (clip != null) {
clip.play();
}
}
/**
* Called by the browser or applet viewer to inform
* this applet that it has been loaded into the system. It is always
* called before the first time that the {@code start} method is
* called.
* <p>
* A subclass of {@code Applet} should override this method if
* it has initialization to perform. For example, an applet with
* threads would use the {@code init} method to create the
* threads and the {@code destroy} method to kill them.
* <p>
* The implementation of this method provided by the
* {@code Applet} class does nothing.
*
* @see java.applet.Applet#destroy()
* @see java.applet.Applet#start()
* @see java.applet.Applet#stop()
*/
public void init() {
}
/**
* Called by the browser or applet viewer to inform
* this applet that it should start its execution. It is called after
* the {@code init} method and each time the applet is revisited
* in a Web page.
* <p>
* A subclass of {@code Applet} should override this method if
* it has any operation that it wants to perform each time the Web
* page containing it is visited. For example, an applet with
* animation might want to use the {@code start} method to
* resume animation, and the {@code stop} method to suspend the
* animation.
* <p>
* Note: some methods, such as {@code getLocationOnScreen}, can only
* provide meaningful results if the applet is showing. Because
* {@code isShowing} returns {@code false} when the applet's
* {@code start} is first called, methods requiring
* {@code isShowing} to return {@code true} should be called from
* a {@code ComponentListener}.
* <p>
* The implementation of this method provided by the
* {@code Applet} class does nothing.
*
* @see java.applet.Applet#destroy()
* @see java.applet.Applet#init()
* @see java.applet.Applet#stop()
* @see java.awt.Component#isShowing()
* @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent)
*/
public void start() {
}
/**
* Called by the browser or applet viewer to inform
* this applet that it should stop its execution. It is called when
* the Web page that contains this applet has been replaced by
* another page, and also just before the applet is to be destroyed.
* <p>
* A subclass of {@code Applet} should override this method if
* it has any operation that it wants to perform each time the Web
* page containing it is no longer visible. For example, an applet
* with animation might want to use the {@code start} method to
* resume animation, and the {@code stop} method to suspend the
* animation.
* <p>
* The implementation of this method provided by the
* {@code Applet} class does nothing.
*
* @see java.applet.Applet#destroy()
* @see java.applet.Applet#init()
*/
public void stop() {
}
/**
* Called by the browser or applet viewer to inform
* this applet that it is being reclaimed and that it should destroy
* any resources that it has allocated. The {@code stop} method
* will always be called before {@code destroy}.
* <p>
* A subclass of {@code Applet} should override this method if
* it has any operation that it wants to perform before it is
* destroyed. For example, an applet with threads would use the
* {@code init} method to create the threads and the
* {@code destroy} method to kill them.
* <p>
* The implementation of this method provided by the
* {@code Applet} class does nothing.
*
* @see java.applet.Applet#init()
* @see java.applet.Applet#start()
* @see java.applet.Applet#stop()
*/
public void destroy() {
}
//
// Accessibility support
//
AccessibleContext accessibleContext = null;
/**
* Gets the AccessibleContext associated with this Applet.
* For applets, the AccessibleContext takes the form of an
* AccessibleApplet.
* A new AccessibleApplet instance is created if necessary.
*
* @return an AccessibleApplet that serves as the
* AccessibleContext of this Applet
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleApplet();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Applet} class. It provides an implementation of the
* Java Accessibility API appropriate to applet user-interface elements.
* @since 1.3
*/
protected class AccessibleApplet extends AccessibleAWTPanel {
private static final long serialVersionUID = 8127374778187708896L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.FRAME;
}
/**
* Get the state of this object.
*
* @return an instance of AccessibleStateSet containing the current
* state set of the object
* @see AccessibleState
*/
public AccessibleStateSet getAccessibleStateSet() {
AccessibleStateSet states = super.getAccessibleStateSet();
states.add(AccessibleState.ACTIVE);
return states;
}
}
}

View file

@ -0,0 +1,206 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.applet;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.image.ColorModel;
import java.net.URL;
import java.util.Enumeration;
import java.io.InputStream;
import java.io.IOException;
import java.util.Iterator;
/**
* This interface corresponds to an applet's environment: the
* document containing the applet and the other applets in the same
* document.
* <p>
* The methods in this interface can be used by an applet to obtain
* information about its environment.
*
* @author Arthur van Hoff
* @since 1.0
*
* @deprecated The Applet API is deprecated. See the
* <a href="package-summary.html"> java.applet package documentation</a>
* for further information.
*/
@Deprecated(since = "9")
public interface AppletContext {
/**
* Creates an audio clip.
*
* @param url an absolute URL giving the location of the audio clip.
* @return the audio clip at the specified URL.
*/
AudioClip getAudioClip(URL url);
/**
* Returns an {@code Image} object that can then be painted on
* the screen. The {@code url} argument that is
* passed as an argument must specify an absolute URL.
* <p>
* This method always returns immediately, whether or not the image
* exists. When the applet attempts to draw the image on the screen,
* the data will be loaded. The graphics primitives that draw the
* image will incrementally paint on the screen.
*
* @param url an absolute URL giving the location of the image.
* @return the image at the specified URL.
* @see java.awt.Image
*/
Image getImage(URL url);
/**
* Finds and returns the applet in the document represented by this
* applet context with the given name. The name can be set in the
* HTML tag by setting the {@code name} attribute.
*
* @param name an applet name.
* @return the applet with the given name, or {@code null} if
* not found.
*/
Applet getApplet(String name);
/**
* Finds all the applets in the document represented by this applet
* context.
*
* @return an enumeration of all applets in the document represented by
* this applet context.
*/
Enumeration<Applet> getApplets();
/**
* Requests that the browser or applet viewer show the Web page
* indicated by the {@code url} argument. The browser or
* applet viewer determines which window or frame to display the
* Web page. This method may be ignored by applet contexts that
* are not browsers.
*
* @param url an absolute URL giving the location of the document.
*/
void showDocument(URL url);
/**
* Requests that the browser or applet viewer show the Web page
* indicated by the {@code url} argument. The
* {@code target} argument indicates in which HTML frame the
* document is to be displayed.
* The target argument is interpreted as follows:
*
* <table class="striped">
* <caption>Target arguments and their descriptions</caption>
* <thead>
* <tr><th>Target Argument</th>
* <th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td>{@code "_self"} <td>Show in the window and frame that
* contain the applet.</tr>
* <tr><td>{@code "_parent"}<td>Show in the applet's parent frame. If
* the applet's frame has no parent frame,
* acts the same as "_self".</tr>
* <tr><td>{@code "_top"} <td>Show in the top-level frame of the applet's
* window. If the applet's frame is the
* top-level frame, acts the same as "_self".</tr>
* <tr><td>{@code "_blank"} <td>Show in a new, unnamed
* top-level window.</tr>
* <tr><td><i>name</i><td>Show in the frame or window named <i>name</i>. If
* a target named <i>name</i> does not already exist, a
* new top-level window with the specified name is created,
* and the document is shown there.</tr>
* </tbody>
* </table>
* <p>
* An applet viewer or browser is free to ignore {@code showDocument}.
*
* @param url an absolute URL giving the location of the document.
* @param target a {@code String} indicating where to display
* the page.
*/
public void showDocument(URL url, String target);
/**
* Requests that the argument string be displayed in the
* "status window". Many browsers and applet viewers
* provide such a window, where the application can inform users of
* its current state.
*
* @param status a string to display in the status window.
*/
void showStatus(String status);
/**
* Associates the specified stream with the specified key in this
* applet context. If the applet context previously contained a mapping
* for this key, the old value is replaced.
* <p>
* For security reasons, mapping of streams and keys exists for each
* codebase. In other words, applet from one codebase cannot access
* the streams created by an applet from a different codebase
*
* @param key key with which the specified value is to be associated.
* @param stream stream to be associated with the specified key. If this
* parameter is {@code null}, the specified key is removed
* in this applet context.
* @throws IOException if the stream size exceeds a certain
* size limit. Size limit is decided by the implementor of this
* interface.
* @since 1.4
*/
public void setStream(String key, InputStream stream)throws IOException;
/**
* Returns the stream to which specified key is associated within this
* applet context. Returns {@code null} if the applet context contains
* no stream for this key.
* <p>
* For security reasons, mapping of streams and keys exists for each
* codebase. In other words, applet from one codebase cannot access
* the streams created by an applet from a different codebase
*
* @return the stream to which this applet context maps the key
* @param key key whose associated stream is to be returned.
* @since 1.4
*/
public InputStream getStream(String key);
/**
* Finds all the keys of the streams in this applet context.
* <p>
* For security reasons, mapping of streams and keys exists for each
* codebase. In other words, applet from one codebase cannot access
* the streams created by an applet from a different codebase
*
* @return an Iterator of all the names of the streams in this applet
* context.
* @since 1.4
*/
public Iterator<String> getStreamKeys();
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.applet;
import java.net.URL;
/**
* When an applet is first created, an applet stub is attached to it
* using the applet's {@code setStub} method. This stub
* serves as the interface between the applet and the browser
* environment or applet viewer environment in which the application
* is running.
*
* @author Arthur van Hoff
* @see java.applet.Applet#setStub(java.applet.AppletStub)
* @since 1.0
*
* @deprecated The Applet API is deprecated. See the
* <a href="package-summary.html"> java.applet package documentation</a>
* for further information.
*/
@Deprecated(since = "9")
public interface AppletStub {
/**
* Determines if the applet is active. An applet is active just
* before its {@code start} method is called. It becomes
* inactive just before its {@code stop} method is called.
*
* @return {@code true} if the applet is active;
* {@code false} otherwise.
*/
boolean isActive();
/**
* Gets the URL of the document in which the applet is embedded.
* For example, suppose an applet is contained
* within the document:
* <blockquote><pre>
* http://www.oracle.com/technetwork/java/index.html
* </pre></blockquote>
* The document base is:
* <blockquote><pre>
* http://www.oracle.com/technetwork/java/index.html
* </pre></blockquote>
*
* @return the {@link java.net.URL} of the document that contains the
* applet.
* @see java.applet.AppletStub#getCodeBase()
*/
URL getDocumentBase();
/**
* Gets the base URL. This is the URL of the directory which contains the applet.
*
* @return the base {@link java.net.URL} of
* the directory which contains the applet.
* @see java.applet.AppletStub#getDocumentBase()
*/
URL getCodeBase();
/**
* Returns the value of the named parameter in the HTML tag. For
* example, if an applet is specified as
* <blockquote><pre>
* &lt;applet code="Clock" width=50 height=50&gt;
* &lt;param name=Color value="blue"&gt;
* &lt;/applet&gt;
* </pre></blockquote>
* <p>
* then a call to {@code getParameter("Color")} returns the
* value {@code "blue"}.
*
* @param name a parameter name.
* @return the value of the named parameter,
* or {@code null} if not set.
*/
String getParameter(String name);
/**
* Returns the applet's context.
*
* @return the applet's context.
*/
AppletContext getAppletContext();
/**
* Called when the applet wants to be resized.
*
* @param width the new requested width for the applet.
* @param height the new requested height for the applet.
*/
void appletResize(int width, int height);
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.applet;
/**
* The {@code AudioClip} interface is a simple abstraction for
* playing a sound clip. Multiple {@code AudioClip} items can be
* playing at the same time, and the resulting sound is mixed
* together to produce a composite.
*
* @author Arthur van Hoff
* @since 1.0
*
* @deprecated The Applet API is deprecated. See the
* <a href="package-summary.html">java.applet package documentation</a>
* for further information.
*/
@Deprecated(since = "9")
public interface AudioClip {
/**
* Starts playing this audio clip. Each time this method is called,
* the clip is restarted from the beginning.
*/
void play();
/**
* Starts playing this audio clip in a loop.
*/
void loop();
/**
* Stops playing this audio clip.
*/
void stop();
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Provides the classes necessary to create an applet and the classes an applet
* uses to communicate with its applet context.
* <p>
* The applet framework involves two entities: the <i>applet</i> and the
* <i>applet context</i>. An applet is an embeddable window (see the Panel
* class) with a few extra methods that the applet context can use to
* initialize, start, and stop the applet.
* <p>
* The applet context is an application that is responsible for loading and
* running applets. For example, the applet context could be a Web browser or an
* applet development environment.
* <p>
* The APIs in this package are all deprecated. Alternative technologies such as
* Java Web Start or installable applications should be used instead.
* See <a href="http://openjdk.java.net/jeps/289">JEP 289</a> and
* the Oracle White Paper
* <a href="http://www.oracle.com/technetwork/java/javase/migratingfromapplets-2872444.pdf">
* "Migrating from Java Applets to plugin-free Java technologies"</a> for more
* information.
*
* @since 1.0
*/
package java.applet;

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Thrown when a serious Abstract Window Toolkit error has occurred.
*
* @author Arthur van Hoff
*/
public class AWTError extends Error {
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -1819846354050686206L;
/**
* Constructs an instance of {@code AWTError} with the specified
* detail message.
* @param msg the detail message.
* @since 1.0
*/
public AWTError(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,588 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.util.EventObject;
import java.awt.event.*;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
import java.lang.reflect.Field;
import sun.awt.AWTAccessor;
import sun.util.logging.PlatformLogger;
import java.security.AccessControlContext;
import java.security.AccessController;
/**
* The root event class for all AWT events.
* This class and its subclasses supersede the original
* java.awt.Event class.
* Subclasses of this root AWTEvent class defined outside of the
* java.awt.event package should define event ID values greater than
* the value defined by RESERVED_ID_MAX.
* <p>
* The event masks defined in this class are needed by Component subclasses
* which are using Component.enableEvents() to select for event types not
* selected by registered listeners. If a listener is registered on a
* component, the appropriate event mask is already set internally by the
* component.
* <p>
* The masks are also used to specify to which types of events an
* AWTEventListener should listen. The masks are bitwise-ORed together
* and passed to Toolkit.addAWTEventListener.
*
* @see Component#enableEvents
* @see Toolkit#addAWTEventListener
*
* @see java.awt.event.ActionEvent
* @see java.awt.event.AdjustmentEvent
* @see java.awt.event.ComponentEvent
* @see java.awt.event.ContainerEvent
* @see java.awt.event.FocusEvent
* @see java.awt.event.InputMethodEvent
* @see java.awt.event.InvocationEvent
* @see java.awt.event.ItemEvent
* @see java.awt.event.HierarchyEvent
* @see java.awt.event.KeyEvent
* @see java.awt.event.MouseEvent
* @see java.awt.event.MouseWheelEvent
* @see java.awt.event.PaintEvent
* @see java.awt.event.TextEvent
* @see java.awt.event.WindowEvent
*
* @author Carl Quinn
* @author Amy Fowler
* @since 1.1
*/
public abstract class AWTEvent extends EventObject {
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.AWTEvent");
private byte bdata[];
/**
* The event's id.
* @serial
* @see #getID()
* @see #AWTEvent
*/
protected int id;
/**
* Controls whether or not the event is sent back down to the peer once the
* source has processed it - false means it's sent to the peer; true means
* it's not. Semantic events always have a 'true' value since they were
* generated by the peer in response to a low-level event.
* @serial
* @see #consume
* @see #isConsumed
*/
protected boolean consumed = false;
/*
* The event's AccessControlContext.
*/
private transient volatile AccessControlContext acc =
AccessController.getContext();
/*
* Returns the acc this event was constructed with.
*/
final AccessControlContext getAccessControlContext() {
if (acc == null) {
throw new SecurityException("AWTEvent is missing AccessControlContext");
}
return acc;
}
transient boolean focusManagerIsDispatching = false;
transient boolean isPosted;
/**
* Indicates whether this AWTEvent was generated by the system as
* opposed to by user code.
*/
private transient boolean isSystemGenerated;
/**
* The event mask for selecting component events.
*/
public static final long COMPONENT_EVENT_MASK = 0x01;
/**
* The event mask for selecting container events.
*/
public static final long CONTAINER_EVENT_MASK = 0x02;
/**
* The event mask for selecting focus events.
*/
public static final long FOCUS_EVENT_MASK = 0x04;
/**
* The event mask for selecting key events.
*/
public static final long KEY_EVENT_MASK = 0x08;
/**
* The event mask for selecting mouse events.
*/
public static final long MOUSE_EVENT_MASK = 0x10;
/**
* The event mask for selecting mouse motion events.
*/
public static final long MOUSE_MOTION_EVENT_MASK = 0x20;
/**
* The event mask for selecting window events.
*/
public static final long WINDOW_EVENT_MASK = 0x40;
/**
* The event mask for selecting action events.
*/
public static final long ACTION_EVENT_MASK = 0x80;
/**
* The event mask for selecting adjustment events.
*/
public static final long ADJUSTMENT_EVENT_MASK = 0x100;
/**
* The event mask for selecting item events.
*/
public static final long ITEM_EVENT_MASK = 0x200;
/**
* The event mask for selecting text events.
*/
public static final long TEXT_EVENT_MASK = 0x400;
/**
* The event mask for selecting input method events.
*/
public static final long INPUT_METHOD_EVENT_MASK = 0x800;
/**
* The pseudo event mask for enabling input methods.
* We're using one bit in the eventMask so we don't need
* a separate field inputMethodsEnabled.
*/
static final long INPUT_METHODS_ENABLED_MASK = 0x1000;
/**
* The event mask for selecting paint events.
*/
public static final long PAINT_EVENT_MASK = 0x2000;
/**
* The event mask for selecting invocation events.
*/
public static final long INVOCATION_EVENT_MASK = 0x4000;
/**
* The event mask for selecting hierarchy events.
*/
public static final long HIERARCHY_EVENT_MASK = 0x8000;
/**
* The event mask for selecting hierarchy bounds events.
*/
public static final long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000;
/**
* The event mask for selecting mouse wheel events.
* @since 1.4
*/
public static final long MOUSE_WHEEL_EVENT_MASK = 0x20000;
/**
* The event mask for selecting window state events.
* @since 1.4
*/
public static final long WINDOW_STATE_EVENT_MASK = 0x40000;
/**
* The event mask for selecting window focus events.
* @since 1.4
*/
public static final long WINDOW_FOCUS_EVENT_MASK = 0x80000;
/**
* WARNING: there are more mask defined privately. See
* SunToolkit.GRAB_EVENT_MASK.
*/
/**
* The maximum value for reserved AWT event IDs. Programs defining
* their own event IDs should use IDs greater than this value.
*/
public static final int RESERVED_ID_MAX = 1999;
// security stuff
private static Field inputEvent_CanAccessSystemClipboard_Field = null;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -1825314779160409405L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setAWTEventAccessor(
new AWTAccessor.AWTEventAccessor() {
public void setPosted(AWTEvent ev) {
ev.isPosted = true;
}
public void setSystemGenerated(AWTEvent ev) {
ev.isSystemGenerated = true;
}
public boolean isSystemGenerated(AWTEvent ev) {
return ev.isSystemGenerated;
}
public AccessControlContext getAccessControlContext(AWTEvent ev) {
return ev.getAccessControlContext();
}
public byte[] getBData(AWTEvent ev) {
return ev.bdata;
}
public void setBData(AWTEvent ev, byte[] bdata) {
ev.bdata = bdata;
}
});
}
/**
* Initialize JNI field and method IDs for fields that may be
* accessed from C.
*/
private static native void initIDs();
/**
* Constructs an AWTEvent object from the parameters of a 1.0-style event.
*
* @param event the old-style event
* @deprecated It is recommended that {@link #AWTEvent(Object, int)} be used
* instead
*/
@Deprecated(since = "9")
public AWTEvent(Event event) {
this(event.target, event.id);
}
/**
* Constructs an AWTEvent object with the specified source object and type.
*
* @param source the object where the event originated
* @param id the event type
*/
public AWTEvent(Object source, int id) {
super(source);
this.id = id;
switch(id) {
case ActionEvent.ACTION_PERFORMED:
case ItemEvent.ITEM_STATE_CHANGED:
case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
case TextEvent.TEXT_VALUE_CHANGED:
consumed = true;
break;
default:
}
}
/**
* Retargets an event to a new source. This method is typically used to
* retarget an event to a lightweight child Component of the original
* heavyweight source.
* <p>
* This method is intended to be used only by event targeting subsystems,
* such as client-defined KeyboardFocusManagers. It is not for general
* client use.
*
* @param newSource the new Object to which the event should be dispatched
* @since 1.4
*/
public void setSource(Object newSource) {
if (source == newSource) {
return;
}
Component comp = null;
if (newSource instanceof Component) {
comp = (Component)newSource;
while (comp != null && comp.peer != null &&
(comp.peer instanceof LightweightPeer)) {
comp = comp.parent;
}
}
synchronized (this) {
source = newSource;
if (comp != null) {
ComponentPeer peer = comp.peer;
if (peer != null) {
nativeSetSource(peer);
}
}
}
}
private native void nativeSetSource(ComponentPeer peer);
/**
* Returns the event type.
*
* @return the event's type id
*/
public int getID() {
return id;
}
/**
* Returns a String representation of this object.
*/
public String toString() {
String srcName = null;
if (source instanceof Component) {
srcName = ((Component)source).getName();
} else if (source instanceof MenuComponent) {
srcName = ((MenuComponent)source).getName();
}
return getClass().getName() + "[" + paramString() + "] on " +
(srcName != null? srcName : source);
}
/**
* Returns a string representing the state of this {@code Event}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return a string representation of this event
*/
public String paramString() {
return "";
}
/**
* Consumes this event, if this event can be consumed. Only low-level,
* system events can be consumed
*/
protected void consume() {
switch(id) {
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
case MouseEvent.MOUSE_WHEEL:
case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
case InputMethodEvent.CARET_POSITION_CHANGED:
consumed = true;
break;
default:
// event type cannot be consumed
}
}
/**
* Returns whether this event has been consumed.
*
* @return {@code true} if this event has been consumed;
* otherwise {@code false}
*/
protected boolean isConsumed() {
return consumed;
}
/**
* Converts a new event to an old one (used for compatibility).
* If the new event cannot be converted (because no old equivalent
* exists) then this returns null.
*
* Note: this method is here instead of in each individual new
* event class in java.awt.event because we don't want to make
* it public and it needs to be called from java.awt.
*/
@SuppressWarnings("deprecation")
Event convertToOld() {
Object src = getSource();
int newid = id;
switch(id) {
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
KeyEvent ke = (KeyEvent)this;
if (ke.isActionKey()) {
newid = (id == KeyEvent.KEY_PRESSED?
Event.KEY_ACTION : Event.KEY_ACTION_RELEASE);
}
int keyCode = ke.getKeyCode();
if (keyCode == KeyEvent.VK_SHIFT ||
keyCode == KeyEvent.VK_CONTROL ||
keyCode == KeyEvent.VK_ALT) {
return null; // suppress modifier keys in old event model.
}
// no mask for button1 existed in old Event - strip it out
return new Event(src, ke.getWhen(), newid, 0, 0,
Event.getOldEventKey(ke),
(ke.getModifiers() & ~InputEvent.BUTTON1_MASK));
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
MouseEvent me = (MouseEvent)this;
// no mask for button1 existed in old Event - strip it out
Event olde = new Event(src, me.getWhen(), newid,
me.getX(), me.getY(), 0,
(me.getModifiers() & ~InputEvent.BUTTON1_MASK));
olde.clickCount = me.getClickCount();
return olde;
case FocusEvent.FOCUS_GAINED:
return new Event(src, Event.GOT_FOCUS, null);
case FocusEvent.FOCUS_LOST:
return new Event(src, Event.LOST_FOCUS, null);
case WindowEvent.WINDOW_CLOSING:
case WindowEvent.WINDOW_ICONIFIED:
case WindowEvent.WINDOW_DEICONIFIED:
return new Event(src, newid, null);
case ComponentEvent.COMPONENT_MOVED:
if (src instanceof Frame || src instanceof Dialog) {
Point p = ((Component)src).getLocation();
return new Event(src, 0, Event.WINDOW_MOVED, p.x, p.y, 0, 0);
}
break;
case ActionEvent.ACTION_PERFORMED:
ActionEvent ae = (ActionEvent)this;
String cmd;
if (src instanceof Button) {
cmd = ((Button)src).getLabel();
} else if (src instanceof MenuItem) {
cmd = ((MenuItem)src).getLabel();
} else {
cmd = ae.getActionCommand();
}
return new Event(src, 0, newid, 0, 0, 0, ae.getModifiers(), cmd);
case ItemEvent.ITEM_STATE_CHANGED:
ItemEvent ie = (ItemEvent)this;
Object arg;
if (src instanceof List) {
newid = (ie.getStateChange() == ItemEvent.SELECTED?
Event.LIST_SELECT : Event.LIST_DESELECT);
arg = ie.getItem();
} else {
newid = Event.ACTION_EVENT;
if (src instanceof Choice) {
arg = ie.getItem();
} else { // Checkbox
arg = Boolean.valueOf(ie.getStateChange() == ItemEvent.SELECTED);
}
}
return new Event(src, newid, arg);
case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
AdjustmentEvent aje = (AdjustmentEvent)this;
switch(aje.getAdjustmentType()) {
case AdjustmentEvent.UNIT_INCREMENT:
newid = Event.SCROLL_LINE_DOWN;
break;
case AdjustmentEvent.UNIT_DECREMENT:
newid = Event.SCROLL_LINE_UP;
break;
case AdjustmentEvent.BLOCK_INCREMENT:
newid = Event.SCROLL_PAGE_DOWN;
break;
case AdjustmentEvent.BLOCK_DECREMENT:
newid = Event.SCROLL_PAGE_UP;
break;
case AdjustmentEvent.TRACK:
if (aje.getValueIsAdjusting()) {
newid = Event.SCROLL_ABSOLUTE;
}
else {
newid = Event.SCROLL_END;
}
break;
default:
return null;
}
return new Event(src, newid, Integer.valueOf(aje.getValue()));
default:
}
return null;
}
/**
* Copies all private data from this event into that.
* Space is allocated for the copied data that will be
* freed when the that is finalized. Upon completion,
* this event is not changed.
*/
void copyPrivateDataInto(AWTEvent that) {
that.bdata = this.bdata;
// Copy canAccessSystemClipboard value from this into that.
if (this instanceof InputEvent && that instanceof InputEvent) {
AWTAccessor.InputEventAccessor accessor
= AWTAccessor.getInputEventAccessor();
boolean b = accessor.canAccessSystemClipboard((InputEvent) this);
accessor.setCanAccessSystemClipboard((InputEvent) that, b);
}
that.isSystemGenerated = this.isSystemGenerated;
}
void dispatched() {
if (this instanceof InputEvent) {
AWTAccessor.getInputEventAccessor().
setCanAccessSystemClipboard((InputEvent) this, false);
}
}
} // class AWTEvent

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Signals that an Abstract Window Toolkit exception has occurred.
*
* @author Arthur van Hoff
*/
public class AWTException extends Exception {
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -1900414231151323879L;
/**
* Constructs an instance of {@code AWTException} with the
* specified detail message. A detail message is an
* instance of {@code String} that describes this particular
* exception.
* @param msg the detail message
* @since 1.0
*/
public AWTException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,798 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import sun.awt.AppContext;
import java.awt.event.InputEvent;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.lang.reflect.Field;
import sun.swing.SwingAccessor;
/**
* An {@code AWTKeyStroke} represents a key action on the
* keyboard, or equivalent input device. {@code AWTKeyStroke}s
* can correspond to only a press or release of a
* particular key, just as {@code KEY_PRESSED} and
* {@code KEY_RELEASED KeyEvent}s do;
* alternately, they can correspond to typing a specific Java character, just
* as {@code KEY_TYPED KeyEvent}s do.
* In all cases, {@code AWTKeyStroke}s can specify modifiers
* (alt, shift, control, meta, altGraph, or a combination thereof) which must be present
* during the action for an exact match.
* <p>
* {@code AWTKeyStrokes} are immutable, and are intended
* to be unique. Client code should never create an
* {@code AWTKeyStroke} on its own, but should instead use
* a variant of {@code getAWTKeyStroke}. Client use of these factory
* methods allows the {@code AWTKeyStroke} implementation
* to cache and share instances efficiently.
*
* @see #getAWTKeyStroke
*
* @author Arnaud Weber
* @author David Mendenhall
* @since 1.4
*/
public class AWTKeyStroke implements Serializable {
static final long serialVersionUID = -6430539691155161871L;
private static Map<String, Integer> modifierKeywords;
/**
* Associates VK_XXX (as a String) with code (as Integer). This is
* done to avoid the overhead of the reflective call to find the
* constant.
*/
private static VKCollection vks;
//A key for the collection of AWTKeyStrokes within AppContext.
private static Object APP_CONTEXT_CACHE_KEY = new Object();
//A key withing the cache
private static AWTKeyStroke APP_CONTEXT_KEYSTROKE_KEY = new AWTKeyStroke();
private char keyChar = KeyEvent.CHAR_UNDEFINED;
private int keyCode = KeyEvent.VK_UNDEFINED;
private int modifiers;
private boolean onKeyRelease;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
}
/**
* Constructs an {@code AWTKeyStroke} with default values.
* The default values used are:
*
* <table class="striped">
* <caption>AWTKeyStroke default values</caption>
* <thead>
* <tr><th>Property</th><th>Default Value</th></tr>
* </thead>
* <tbody>
* <tr>
* <td>Key Char</td>
* <td>{@code KeyEvent.CHAR_UNDEFINED}</td>
* </tr>
* <tr>
* <td>Key Code</td>
* <td>{@code KeyEvent.VK_UNDEFINED}</td>
* </tr>
* <tr>
* <td>Modifiers</td>
* <td>none</td>
* </tr>
* <tr>
* <td>On key release?</td>
* <td>{@code false}</td>
* </tr>
* </tbody>
* </table>
*
* {@code AWTKeyStroke}s should not be constructed
* by client code. Use a variant of {@code getAWTKeyStroke}
* instead.
*
* @see #getAWTKeyStroke
*/
protected AWTKeyStroke() {
}
/**
* Constructs an {@code AWTKeyStroke} with the specified
* values. {@code AWTKeyStroke}s should not be constructed
* by client code. Use a variant of {@code getAWTKeyStroke}
* instead.
*
* @param keyChar the character value for a keyboard key
* @param keyCode the key code for this {@code AWTKeyStroke}
* @param modifiers a bitwise-ored combination of any modifiers
* @param onKeyRelease {@code true} if this
* {@code AWTKeyStroke} corresponds
* to a key release; {@code false} otherwise
* @see #getAWTKeyStroke
*/
protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
boolean onKeyRelease) {
this.keyChar = keyChar;
this.keyCode = keyCode;
this.modifiers = modifiers;
this.onKeyRelease = onKeyRelease;
}
/**
* The method has no effect and is only left present to avoid introducing
* a binary incompatibility.
*
* @param subclass the new Class of which the factory methods should create
* instances
* @deprecated
*/
@Deprecated
protected static void registerSubclass(Class<?> subclass) {
}
private static synchronized AWTKeyStroke getCachedStroke
(char keyChar, int keyCode, int modifiers, boolean onKeyRelease)
{
@SuppressWarnings("unchecked")
Map<AWTKeyStroke, AWTKeyStroke> cache = (Map)AppContext.getAppContext().get(APP_CONTEXT_CACHE_KEY);
AWTKeyStroke cacheKey = (AWTKeyStroke)AppContext.getAppContext().get(APP_CONTEXT_KEYSTROKE_KEY);
if (cache == null) {
cache = new HashMap<>();
AppContext.getAppContext().put(APP_CONTEXT_CACHE_KEY, cache);
}
if (cacheKey == null) {
cacheKey = SwingAccessor.getKeyStrokeAccessor().create();
AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey);
}
cacheKey.keyChar = keyChar;
cacheKey.keyCode = keyCode;
cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
cacheKey.onKeyRelease = onKeyRelease;
AWTKeyStroke stroke = cache.get(cacheKey);
if (stroke == null) {
stroke = cacheKey;
cache.put(stroke, stroke);
AppContext.getAppContext().remove(APP_CONTEXT_KEYSTROKE_KEY);
}
return stroke;
}
/**
* Returns a shared instance of an {@code AWTKeyStroke}
* that represents a {@code KEY_TYPED} event for the
* specified character.
*
* @param keyChar the character value for a keyboard key
* @return an {@code AWTKeyStroke} object for that key
*/
public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
}
/**
* Returns a shared instance of an {@code AWTKeyStroke}
* that represents a {@code KEY_TYPED} event for the
* specified Character object and a set of modifiers. Note
* that the first parameter is of type Character rather than
* char. This is to avoid inadvertent clashes with
* calls to {@code getAWTKeyStroke(int keyCode, int modifiers)}.
*
* The modifiers consist of any combination of following:<ul>
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
* <li>java.awt.event.InputEvent.META_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
* </ul>
* The old modifiers listed below also can be used, but they are
* mapped to _DOWN_ modifiers. <ul>
* <li>java.awt.event.InputEvent.SHIFT_MASK
* <li>java.awt.event.InputEvent.CTRL_MASK
* <li>java.awt.event.InputEvent.META_MASK
* <li>java.awt.event.InputEvent.ALT_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
* </ul>
* also can be used, but they are mapped to _DOWN_ modifiers.
*
* Since these numbers are all different powers of two, any combination of
* them is an integer in which each bit represents a different modifier
* key. Use 0 to specify no modifiers.
*
* @param keyChar the Character object for a keyboard character
* @param modifiers a bitwise-ored combination of any modifiers
* @return an {@code AWTKeyStroke} object for that key
* @throws IllegalArgumentException if {@code keyChar} is
* {@code null}
*
* @see java.awt.event.InputEvent
*/
public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
{
if (keyChar == null) {
throw new IllegalArgumentException("keyChar cannot be null");
}
return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
modifiers, false);
}
/**
* Returns a shared instance of an {@code AWTKeyStroke},
* given a numeric key code and a set of modifiers, specifying
* whether the key is activated when it is pressed or released.
* <p>
* The "virtual key" constants defined in
* {@code java.awt.event.KeyEvent} can be
* used to specify the key code. For example:<ul>
* <li>{@code java.awt.event.KeyEvent.VK_ENTER}
* <li>{@code java.awt.event.KeyEvent.VK_TAB}
* <li>{@code java.awt.event.KeyEvent.VK_SPACE}
* </ul>
* Alternatively, the key code may be obtained by calling
* {@code java.awt.event.KeyEvent.getExtendedKeyCodeForChar}.
*
* The modifiers consist of any combination of:<ul>
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
* <li>java.awt.event.InputEvent.META_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
* </ul>
* The old modifiers <ul>
* <li>java.awt.event.InputEvent.SHIFT_MASK
* <li>java.awt.event.InputEvent.CTRL_MASK
* <li>java.awt.event.InputEvent.META_MASK
* <li>java.awt.event.InputEvent.ALT_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
* </ul>
* also can be used, but they are mapped to _DOWN_ modifiers.
*
* Since these numbers are all different powers of two, any combination of
* them is an integer in which each bit represents a different modifier
* key. Use 0 to specify no modifiers.
*
* @param keyCode an int specifying the numeric code for a keyboard key
* @param modifiers a bitwise-ored combination of any modifiers
* @param onKeyRelease {@code true} if the {@code AWTKeyStroke}
* should represent a key release; {@code false} otherwise
* @return an AWTKeyStroke object for that key
*
* @see java.awt.event.KeyEvent
* @see java.awt.event.InputEvent
*/
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
boolean onKeyRelease) {
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
onKeyRelease);
}
/**
* Returns a shared instance of an {@code AWTKeyStroke},
* given a numeric key code and a set of modifiers. The returned
* {@code AWTKeyStroke} will correspond to a key press.
* <p>
* The "virtual key" constants defined in
* {@code java.awt.event.KeyEvent} can be
* used to specify the key code. For example:<ul>
* <li>{@code java.awt.event.KeyEvent.VK_ENTER}
* <li>{@code java.awt.event.KeyEvent.VK_TAB}
* <li>{@code java.awt.event.KeyEvent.VK_SPACE}
* </ul>
* The modifiers consist of any combination of:<ul>
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
* <li>java.awt.event.InputEvent.META_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
* </ul>
* The old modifiers <ul>
* <li>java.awt.event.InputEvent.SHIFT_MASK
* <li>java.awt.event.InputEvent.CTRL_MASK
* <li>java.awt.event.InputEvent.META_MASK
* <li>java.awt.event.InputEvent.ALT_MASK
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
* </ul>
* also can be used, but they are mapped to _DOWN_ modifiers.
*
* Since these numbers are all different powers of two, any combination of
* them is an integer in which each bit represents a different modifier
* key. Use 0 to specify no modifiers.
*
* @param keyCode an int specifying the numeric code for a keyboard key
* @param modifiers a bitwise-ored combination of any modifiers
* @return an {@code AWTKeyStroke} object for that key
*
* @see java.awt.event.KeyEvent
* @see java.awt.event.InputEvent
*/
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
false);
}
/**
* Returns an {@code AWTKeyStroke} which represents the
* stroke which generated a given {@code KeyEvent}.
* <p>
* This method obtains the keyChar from a {@code KeyTyped}
* event, and the keyCode from a {@code KeyPressed} or
* {@code KeyReleased} event. The {@code KeyEvent} modifiers are
* obtained for all three types of {@code KeyEvent}.
*
* @param anEvent the {@code KeyEvent} from which to
* obtain the {@code AWTKeyStroke}
* @throws NullPointerException if {@code anEvent} is null
* @return the {@code AWTKeyStroke} that precipitated the event
*/
@SuppressWarnings("deprecation")
public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
int id = anEvent.getID();
switch(id) {
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
anEvent.getKeyCode(),
anEvent.getModifiers(),
(id == KeyEvent.KEY_RELEASED));
case KeyEvent.KEY_TYPED:
return getCachedStroke(anEvent.getKeyChar(),
KeyEvent.VK_UNDEFINED,
anEvent.getModifiers(),
false);
default:
// Invalid ID for this KeyEvent
return null;
}
}
/**
* Parses a string and returns an {@code AWTKeyStroke}.
* The string must have the following syntax:
* <pre>
* &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
*
* modifiers := shift | control | ctrl | meta | alt | altGraph
* typedID := typed &lt;typedKey&gt;
* typedKey := string of length 1 giving Unicode character.
* pressedReleasedID := (pressed | released) key
* key := KeyEvent key code name, i.e. the name following "VK_".
* </pre>
* If typed, pressed or released is not specified, pressed is assumed. Here
* are some examples:
* <pre>
* "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
* "control DELETE" =&gt; getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
* "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
* "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
* "typed a" =&gt; getAWTKeyStroke('a');
* </pre>
*
* @param s a String formatted as described above
* @return an {@code AWTKeyStroke} object for that String
* @throws IllegalArgumentException if {@code s} is {@code null},
* or is formatted incorrectly
*/
@SuppressWarnings("deprecation")
public static AWTKeyStroke getAWTKeyStroke(String s) {
if (s == null) {
throw new IllegalArgumentException("String cannot be null");
}
final String errmsg = "String formatted incorrectly";
StringTokenizer st = new StringTokenizer(s, " ");
int mask = 0;
boolean released = false;
boolean typed = false;
boolean pressed = false;
synchronized (AWTKeyStroke.class) {
if (modifierKeywords == null) {
Map<String, Integer> uninitializedMap = new HashMap<>(8, 1.0f);
uninitializedMap.put("shift",
Integer.valueOf(InputEvent.SHIFT_DOWN_MASK
|InputEvent.SHIFT_MASK));
uninitializedMap.put("control",
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
|InputEvent.CTRL_MASK));
uninitializedMap.put("ctrl",
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
|InputEvent.CTRL_MASK));
uninitializedMap.put("meta",
Integer.valueOf(InputEvent.META_DOWN_MASK
|InputEvent.META_MASK));
uninitializedMap.put("alt",
Integer.valueOf(InputEvent.ALT_DOWN_MASK
|InputEvent.ALT_MASK));
uninitializedMap.put("altGraph",
Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK
|InputEvent.ALT_GRAPH_MASK));
uninitializedMap.put("button1",
Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK));
uninitializedMap.put("button2",
Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK));
uninitializedMap.put("button3",
Integer.valueOf(InputEvent.BUTTON3_DOWN_MASK));
modifierKeywords =
Collections.synchronizedMap(uninitializedMap);
}
}
int count = st.countTokens();
for (int i = 1; i <= count; i++) {
String token = st.nextToken();
if (typed) {
if (token.length() != 1 || i != count) {
throw new IllegalArgumentException(errmsg);
}
return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
mask, false);
}
if (pressed || released || i == count) {
if (i != count) {
throw new IllegalArgumentException(errmsg);
}
String keyCodeName = "VK_" + token;
int keyCode = getVKValue(keyCodeName);
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
mask, released);
}
if (token.equals("released")) {
released = true;
continue;
}
if (token.equals("pressed")) {
pressed = true;
continue;
}
if (token.equals("typed")) {
typed = true;
continue;
}
Integer tokenMask = modifierKeywords.get(token);
if (tokenMask != null) {
mask |= tokenMask.intValue();
} else {
throw new IllegalArgumentException(errmsg);
}
}
throw new IllegalArgumentException(errmsg);
}
private static VKCollection getVKCollection() {
if (vks == null) {
vks = new VKCollection();
}
return vks;
}
/**
* Returns the integer constant for the KeyEvent.VK field named
* {@code key}. This will throw an
* {@code IllegalArgumentException} if {@code key} is
* not a valid constant.
*/
private static int getVKValue(String key) {
VKCollection vkCollect = getVKCollection();
Integer value = vkCollect.findCode(key);
if (value == null) {
int keyCode = 0;
final String errmsg = "String formatted incorrectly";
try {
keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class);
} catch (NoSuchFieldException nsfe) {
throw new IllegalArgumentException(errmsg);
} catch (IllegalAccessException iae) {
throw new IllegalArgumentException(errmsg);
}
value = Integer.valueOf(keyCode);
vkCollect.put(key, value);
}
return value.intValue();
}
/**
* Returns the character for this {@code AWTKeyStroke}.
*
* @return a char value
* @see #getAWTKeyStroke(char)
* @see KeyEvent#getKeyChar
*/
public final char getKeyChar() {
return keyChar;
}
/**
* Returns the numeric key code for this {@code AWTKeyStroke}.
*
* @return an int containing the key code value
* @see #getAWTKeyStroke(int,int)
* @see KeyEvent#getKeyCode
*/
public final int getKeyCode() {
return keyCode;
}
/**
* Returns the modifier keys for this {@code AWTKeyStroke}.
*
* @return an int containing the modifiers
* @see #getAWTKeyStroke(int,int)
*/
public final int getModifiers() {
return modifiers;
}
/**
* Returns whether this {@code AWTKeyStroke} represents a key release.
*
* @return {@code true} if this {@code AWTKeyStroke}
* represents a key release; {@code false} otherwise
* @see #getAWTKeyStroke(int,int,boolean)
*/
public final boolean isOnKeyRelease() {
return onKeyRelease;
}
/**
* Returns the type of {@code KeyEvent} which corresponds to
* this {@code AWTKeyStroke}.
*
* @return {@code KeyEvent.KEY_PRESSED},
* {@code KeyEvent.KEY_TYPED},
* or {@code KeyEvent.KEY_RELEASED}
* @see java.awt.event.KeyEvent
*/
public final int getKeyEventType() {
if (keyCode == KeyEvent.VK_UNDEFINED) {
return KeyEvent.KEY_TYPED;
} else {
return (onKeyRelease)
? KeyEvent.KEY_RELEASED
: KeyEvent.KEY_PRESSED;
}
}
/**
* Returns a numeric value for this object that is likely to be unique,
* making it a good choice as the index value in a hash table.
*
* @return an int that represents this object
*/
public int hashCode() {
return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
(onKeyRelease ? 1 : 2);
}
/**
* Returns true if this object is identical to the specified object.
*
* @param anObject the Object to compare this object to
* @return true if the objects are identical
*/
public final boolean equals(Object anObject) {
if (anObject instanceof AWTKeyStroke) {
AWTKeyStroke ks = (AWTKeyStroke)anObject;
return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
ks.onKeyRelease == onKeyRelease &&
ks.modifiers == modifiers);
}
return false;
}
/**
* Returns a string that displays and identifies this object's properties.
* The {@code String} returned by this method can be passed
* as a parameter to {@code getAWTKeyStroke(String)} to produce
* a key stroke equal to this key stroke.
*
* @return a String representation of this object
* @see #getAWTKeyStroke(String)
*/
public String toString() {
if (keyCode == KeyEvent.VK_UNDEFINED) {
return getModifiersText(modifiers) + "typed " + keyChar;
} else {
return getModifiersText(modifiers) +
(onKeyRelease ? "released" : "pressed") + " " +
getVKText(keyCode);
}
}
static String getModifiersText(int modifiers) {
StringBuilder buf = new StringBuilder();
if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
buf.append("shift ");
}
if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
buf.append("ctrl ");
}
if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
buf.append("meta ");
}
if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
buf.append("alt ");
}
if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
buf.append("altGraph ");
}
if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
buf.append("button1 ");
}
if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
buf.append("button2 ");
}
if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
buf.append("button3 ");
}
return buf.toString();
}
static String getVKText(int keyCode) {
VKCollection vkCollect = getVKCollection();
Integer key = Integer.valueOf(keyCode);
String name = vkCollect.findName(key);
if (name != null) {
return name.substring(3);
}
int expected_modifiers =
(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
Field[] fields = KeyEvent.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
if (fields[i].getModifiers() == expected_modifiers
&& fields[i].getType() == Integer.TYPE
&& fields[i].getName().startsWith("VK_")
&& fields[i].getInt(KeyEvent.class) == keyCode)
{
name = fields[i].getName();
vkCollect.put(name, key);
return name.substring(3);
}
} catch (IllegalAccessException e) {
assert(false);
}
}
return "UNKNOWN";
}
/**
* Returns a cached instance of {@code AWTKeyStroke} (or a subclass of
* {@code AWTKeyStroke}) which is equal to this instance.
*
* @return a cached instance which is equal to this instance
* @throws java.io.ObjectStreamException if a serialization problem occurs
*/
protected Object readResolve() throws java.io.ObjectStreamException {
synchronized (AWTKeyStroke.class) {
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
}
}
@SuppressWarnings("deprecation")
private static int mapOldModifiers(int modifiers) {
if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
modifiers |= InputEvent.SHIFT_DOWN_MASK;
}
if ((modifiers & InputEvent.ALT_MASK) != 0) {
modifiers |= InputEvent.ALT_DOWN_MASK;
}
if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
}
if ((modifiers & InputEvent.CTRL_MASK) != 0) {
modifiers |= InputEvent.CTRL_DOWN_MASK;
}
if ((modifiers & InputEvent.META_MASK) != 0) {
modifiers |= InputEvent.META_DOWN_MASK;
}
modifiers &= InputEvent.SHIFT_DOWN_MASK
| InputEvent.ALT_DOWN_MASK
| InputEvent.ALT_GRAPH_DOWN_MASK
| InputEvent.CTRL_DOWN_MASK
| InputEvent.META_DOWN_MASK
| InputEvent.BUTTON1_DOWN_MASK
| InputEvent.BUTTON2_DOWN_MASK
| InputEvent.BUTTON3_DOWN_MASK;
return modifiers;
}
@SuppressWarnings("deprecation")
private static int mapNewModifiers(int modifiers) {
if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
modifiers |= InputEvent.SHIFT_MASK;
}
if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
modifiers |= InputEvent.ALT_MASK;
}
if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
modifiers |= InputEvent.ALT_GRAPH_MASK;
}
if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
modifiers |= InputEvent.CTRL_MASK;
}
if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
modifiers |= InputEvent.META_MASK;
}
return modifiers;
}
}
class VKCollection {
Map<Integer, String> code2name;
Map<String, Integer> name2code;
public VKCollection() {
code2name = new HashMap<>();
name2code = new HashMap<>();
}
public synchronized void put(String name, Integer code) {
assert((name != null) && (code != null));
assert(findName(code) == null);
assert(findCode(name) == null);
code2name.put(code, name);
name2code.put(name, code);
}
public synchronized Integer findCode(String name) {
assert(name != null);
return name2code.get(name);
}
public synchronized String findName(Integer code) {
assert(code != null);
return code2name.get(code);
}
}

View file

@ -0,0 +1,241 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.security.BasicPermission;
/**
* This class is for AWT permissions.
* An {@code AWTPermission} contains a target name but
* no actions list; you either have the named permission
* or you don't.
*
* <P>
* The target name is the name of the AWT permission (see below). The naming
* convention follows the hierarchical property naming convention.
* Also, an asterisk could be used to represent all AWT permissions.
*
* <P>
* The following table lists all the possible {@code AWTPermission}
* target names, and for each provides a description of what the
* permission allows and a discussion of the risks of granting code
* the permission.
*
* <table class="striped">
* <caption>AWTPermission target names, descriptions, and associated risks
* </caption>
* <thead>
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>accessClipboard</td>
* <td>Posting and retrieval of information to and from the AWT clipboard</td>
* <td>This would allow malfeasant code to share
* potentially sensitive or confidential information.</td>
* </tr>
*
* <tr>
* <td>accessEventQueue</td>
* <td>Access to the AWT event queue</td>
* <td>After retrieving the AWT event queue,
* malicious code may peek at and even remove existing events
* from its event queue, as well as post bogus events which may purposefully
* cause the application or applet to misbehave in an insecure manner.</td>
* </tr>
*
* <tr>
* <td>accessSystemTray</td>
* <td>Access to the AWT SystemTray instance</td>
* <td>This would allow malicious code to add tray icons to the system tray.
* First, such an icon may look like the icon of some known application
* (such as a firewall or anti-virus) and order a user to do something unsafe
* (with help of balloon messages). Second, the system tray may be glutted with
* tray icons so that no one could add a tray icon anymore.</td>
* </tr>
*
* <tr>
* <td>createRobot</td>
* <td>Create java.awt.Robot objects</td>
* <td>The java.awt.Robot object allows code to generate native-level
* mouse and keyboard events as well as read the screen. It could allow
* malicious code to control the system, run other programs, read the
* display, and deny mouse and keyboard access to the user.</td>
* </tr>
*
* <tr>
* <td>fullScreenExclusive</td>
* <td>Enter full-screen exclusive mode</td>
* <td>Entering full-screen exclusive mode allows direct access to
* low-level graphics card memory. This could be used to spoof the
* system, since the program is in direct control of rendering. Depending on
* the implementation, the security warning may not be shown for the windows
* used to enter the full-screen exclusive mode (assuming that the {@code
* fullScreenExclusive} permission has been granted to this application). Note
* that this behavior does not mean that the {@code
* showWindowWithoutWarningBanner} permission will be automatically granted to
* the application which has the {@code fullScreenExclusive} permission:
* non-full-screen windows will continue to be shown with the security
* warning.</td>
* </tr>
*
* <tr>
* <td>listenToAllAWTEvents</td>
* <td>Listen to all AWT events, system-wide</td>
* <td>After adding an AWT event listener,
* malicious code may scan all AWT events dispatched in the system,
* allowing it to read all user input (such as passwords). Each
* AWT event listener is called from within the context of that
* event queue's EventDispatchThread, so if the accessEventQueue
* permission is also enabled, malicious code could modify the
* contents of AWT event queues system-wide, causing the application
* or applet to misbehave in an insecure manner.</td>
* </tr>
*
* <tr>
* <td>readDisplayPixels</td>
* <td>Readback of pixels from the display screen</td>
* <td>Interfaces such as the java.awt.Composite interface or the
* java.awt.Robot class allow arbitrary code to examine pixels on the
* display enable malicious code to snoop on the activities of the user.</td>
* </tr>
*
* <tr>
* <td>replaceKeyboardFocusManager</td>
* <td>Sets the {@code KeyboardFocusManager} for
* a particular thread.
* <td>When {@code SecurityManager} is installed, the invoking
* thread must be granted this permission in order to replace
* the current {@code KeyboardFocusManager}. If permission
* is not granted, a {@code SecurityException} will be thrown.
* </tr>
*
* <tr>
* <td>setAppletStub</td>
* <td>Setting the stub which implements Applet container services</td>
* <td>Malicious code could set an applet's stub and result in unexpected
* behavior or denial of service to an applet.</td>
* </tr>
*
* <tr>
* <td>setWindowAlwaysOnTop</td>
* <td>Setting always-on-top property of the window: {@link Window#setAlwaysOnTop}</td>
* <td>The malicious window might make itself look and behave like a real full desktop, so that
* information entered by the unsuspecting user is captured and subsequently misused </td>
* </tr>
*
* <tr>
* <td>showWindowWithoutWarningBanner</td>
* <td>Display of a window without also displaying a banner warning
* that the window was created by an applet</td>
* <td>Without this warning,
* an applet may pop up windows without the user knowing that they
* belong to an applet. Since users may make security-sensitive
* decisions based on whether or not the window belongs to an applet
* (entering a username and password into a dialog box, for example),
* disabling this warning banner may allow applets to trick the user
* into entering such information.</td>
* </tr>
*
* <tr>
* <td>toolkitModality</td>
* <td>Creating {@link Dialog.ModalityType#TOOLKIT_MODAL TOOLKIT_MODAL} dialogs
* and setting the {@link Dialog.ModalExclusionType#TOOLKIT_EXCLUDE
* TOOLKIT_EXCLUDE} window property.</td>
* <td>When a toolkit-modal dialog is shown from an applet, it blocks all other
* applets in the browser. When launching applications from Java Web Start,
* its windows (such as the security dialog) may also be blocked by toolkit-modal
* dialogs, shown from these applications.</td>
* </tr>
*
* <tr>
* <td>watchMousePointer</td>
* <td>Getting the information about the mouse pointer position at any
* time</td>
* <td>Constantly watching the mouse pointer,
* an applet can make guesses about what the user is doing, i.e. moving
* the mouse to the lower left corner of the screen most likely means that
* the user is about to launch an application. If a virtual keypad is used
* so that keyboard is emulated using the mouse, an applet may guess what
* is being typed.</td>
* </tr>
* </tbody>
* </table>
*
* @see java.security.BasicPermission
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
* @see java.lang.SecurityManager
*
*
* @author Marianne Mueller
* @author Roland Schemers
*/
public final class AWTPermission extends BasicPermission {
/** use serialVersionUID from the Java 2 platform for interoperability */
private static final long serialVersionUID = 8890392402588814465L;
/**
* Creates a new {@code AWTPermission} with the specified name.
* The name is the symbolic name of the {@code AWTPermission},
* such as "topLevelWindow", "systemClipboard", etc. An asterisk
* may be used to indicate all AWT permissions.
*
* @param name the name of the AWTPermission
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public AWTPermission(String name)
{
super(name);
}
/**
* Creates a new {@code AWTPermission} object with the specified name.
* The name is the symbolic name of the {@code AWTPermission}, and the
* actions string is currently unused and should be {@code null}.
*
* @param name the name of the {@code AWTPermission}
* @param actions should be {@code null}
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public AWTPermission(String name, String actions)
{
super(name, actions);
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* An interface for events that know how to dispatch themselves.
* By implementing this interface an event can be placed upon the event
* queue and its {@code dispatch()} method will be called when the event
* is dispatched, using the {@code EventDispatchThread}.
* <p>
* This is a very useful mechanism for avoiding deadlocks. If
* a thread is executing in a critical section (i.e., it has entered
* one or more monitors), calling other synchronized code may
* cause deadlocks. To avoid the potential deadlocks, an
* {@code ActiveEvent} can be created to run the second section of
* code at later time. If there is contention on the monitor,
* the second thread will simply block until the first thread
* has finished its work and exited its monitors.
* <p>
* For security reasons, it is often desirable to use an {@code ActiveEvent}
* to avoid calling untrusted code from a critical thread. For
* instance, peer implementations can use this facility to avoid
* making calls into user code from a system thread. Doing so avoids
* potential deadlocks and denial-of-service attacks.
*
* @author Timothy Prinzing
* @since 1.2
*/
public interface ActiveEvent {
/**
* Dispatch the event to its target, listeners of the events source,
* or do whatever it is this event is supposed to do.
*/
public void dispatch();
}

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.*;
import java.lang.annotation.Native;
/**
* The interface for objects which have an adjustable numeric value
* contained within a bounded range of values.
*
* @author Amy Fowler
* @author Tim Prinzing
*/
public interface Adjustable {
/**
* Indicates that the {@code Adjustable} has horizontal orientation.
*/
@Native public static final int HORIZONTAL = 0;
/**
* Indicates that the {@code Adjustable} has vertical orientation.
*/
@Native public static final int VERTICAL = 1;
/**
* Indicates that the {@code Adjustable} has no orientation.
*/
@Native public static final int NO_ORIENTATION = 2;
/**
* Gets the orientation of the adjustable object.
* @return the orientation of the adjustable object;
* either {@code HORIZONTAL}, {@code VERTICAL},
* or {@code NO_ORIENTATION}
*/
int getOrientation();
/**
* Sets the minimum value of the adjustable object.
* @param min the minimum value
*/
void setMinimum(int min);
/**
* Gets the minimum value of the adjustable object.
* @return the minimum value of the adjustable object
*/
int getMinimum();
/**
* Sets the maximum value of the adjustable object.
* @param max the maximum value
*/
void setMaximum(int max);
/**
* Gets the maximum value of the adjustable object.
* @return the maximum value of the adjustable object
*/
int getMaximum();
/**
* Sets the unit value increment for the adjustable object.
* @param u the unit increment
*/
void setUnitIncrement(int u);
/**
* Gets the unit value increment for the adjustable object.
* @return the unit value increment for the adjustable object
*/
int getUnitIncrement();
/**
* Sets the block value increment for the adjustable object.
* @param b the block increment
*/
void setBlockIncrement(int b);
/**
* Gets the block value increment for the adjustable object.
* @return the block value increment for the adjustable object
*/
int getBlockIncrement();
/**
* Sets the length of the proportional indicator of the
* adjustable object.
* @param v the length of the indicator
*/
void setVisibleAmount(int v);
/**
* Gets the length of the proportional indicator.
* @return the length of the proportional indicator
*/
int getVisibleAmount();
/**
* Sets the current value of the adjustable object. If
* the value supplied is less than {@code minimum}
* or greater than {@code maximum} - {@code visibleAmount},
* then one of those values is substituted, as appropriate.
* <p>
* Calling this method does not fire an
* {@code AdjustmentEvent}.
*
* @param v the current value, between {@code minimum}
* and {@code maximum} - {@code visibleAmount}
*/
void setValue(int v);
/**
* Gets the current value of the adjustable object.
* @return the current value of the adjustable object
*/
int getValue();
/**
* Adds a listener to receive adjustment events when the value of
* the adjustable object changes.
* @param l the listener to receive events
* @see AdjustmentEvent
*/
void addAdjustmentListener(AdjustmentListener l);
/**
* Removes an adjustment listener.
* @param l the listener being removed
* @see AdjustmentEvent
*/
void removeAdjustmentListener(AdjustmentListener l);
}

View file

@ -0,0 +1,805 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ColorModel;
import java.lang.annotation.Native;
import sun.java2d.SunCompositeContext;
/**
* The {@code AlphaComposite} class implements basic alpha
* compositing rules for combining source and destination colors
* to achieve blending and transparency effects with graphics and
* images.
* The specific rules implemented by this class are the basic set
* of 12 rules described in
* T. Porter and T. Duff, "Compositing Digital Images", SIGGRAPH 84,
* 253-259.
* The rest of this documentation assumes some familiarity with the
* definitions and concepts outlined in that paper.
*
* <p>
* This class extends the standard equations defined by Porter and
* Duff to include one additional factor.
* An instance of the {@code AlphaComposite} class can contain
* an alpha value that is used to modify the opacity or coverage of
* every source pixel before it is used in the blending equations.
*
* <p>
* It is important to note that the equations defined by the Porter
* and Duff paper are all defined to operate on color components
* that are premultiplied by their corresponding alpha components.
* Since the {@code ColorModel} and {@code Raster} classes
* allow the storage of pixel data in either premultiplied or
* non-premultiplied form, all input data must be normalized into
* premultiplied form before applying the equations and all results
* might need to be adjusted back to the form required by the destination
* before the pixel values are stored.
*
* <p>
* Also note that this class defines only the equations
* for combining color and alpha values in a purely mathematical
* sense. The accurate application of its equations depends
* on the way the data is retrieved from its sources and stored
* in its destinations.
* See <a href="#caveats">Implementation Caveats</a>
* for further information.
*
* <p>
* The following factors are used in the description of the blending
* equation in the Porter and Duff paper:
*
* <blockquote>
* <table class="borderless">
* <caption style="display:none">Factors</caption>
* <tr><th style="text-align:left">Factor&nbsp;&nbsp;<th style="text-align:left">Definition
* <tr><td><em>A<sub>s</sub></em><td>the alpha component of the source pixel
* <tr><td><em>C<sub>s</sub></em><td>a color component of the source pixel in premultiplied form
* <tr><td><em>A<sub>d</sub></em><td>the alpha component of the destination pixel
* <tr><td><em>C<sub>d</sub></em><td>a color component of the destination pixel in premultiplied form
* <tr><td><em>F<sub>s</sub></em><td>the fraction of the source pixel that contributes to the output
* <tr><td><em>F<sub>d</sub></em><td>the fraction of the destination pixel that contributes
* to the output
* <tr><td><em>A<sub>r</sub></em><td>the alpha component of the result
* <tr><td><em>C<sub>r</sub></em><td>a color component of the result in premultiplied form
* </table>
* </blockquote>
*
* <p>
* Using these factors, Porter and Duff define 12 ways of choosing
* the blending factors <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em> to
* produce each of 12 desirable visual effects.
* The equations for determining <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em>
* are given in the descriptions of the 12 static fields
* that specify visual effects.
* For example,
* the description for
* <a href="#SRC_OVER">{@code SRC_OVER}</a>
* specifies that <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>).
* Once a set of equations for determining the blending factors is
* known they can then be applied to each pixel to produce a result
* using the following set of equations:
*
* <pre>
* <em>F<sub>s</sub></em> = <em>f</em>(<em>A<sub>d</sub></em>)
* <em>F<sub>d</sub></em> = <em>f</em>(<em>A<sub>s</sub></em>)
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>F<sub>s</sub></em> + <em>A<sub>d</sub></em>*<em>F<sub>d</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>F<sub>s</sub></em> + <em>C<sub>d</sub></em>*<em>F<sub>d</sub></em></pre>
*
* <p>
* The following factors will be used to discuss our extensions to
* the blending equation in the Porter and Duff paper:
*
* <blockquote>
* <table class="borderless">
* <caption style="display:none">Factors</caption>
* <tr><th style="text-align:left">Factor&nbsp;&nbsp;<th style="text-align:left">Definition
* <tr><td><em>C<sub>sr</sub></em> <td>one of the raw color components of the source pixel
* <tr><td><em>C<sub>dr</sub></em> <td>one of the raw color components of the destination pixel
* <tr><td><em>A<sub>ac</sub></em> <td>the "extra" alpha component from the AlphaComposite instance
* <tr><td><em>A<sub>sr</sub></em> <td>the raw alpha component of the source pixel
* <tr><td><em>A<sub>dr</sub></em><td>the raw alpha component of the destination pixel
* <tr><td><em>A<sub>df</sub></em> <td>the final alpha component stored in the destination
* <tr><td><em>C<sub>df</sub></em> <td>the final raw color component stored in the destination
* </table>
*</blockquote>
*
* <h3>Preparing Inputs</h3>
*
* <p>
* The {@code AlphaComposite} class defines an additional alpha
* value that is applied to the source alpha.
* This value is applied as if an implicit SRC_IN rule were first
* applied to the source pixel against a pixel with the indicated
* alpha by multiplying both the raw source alpha and the raw
* source colors by the alpha in the {@code AlphaComposite}.
* This leads to the following equation for producing the alpha
* used in the Porter and Duff blending equation:
*
* <pre>
* <em>A<sub>s</sub></em> = <em>A<sub>sr</sub></em> * <em>A<sub>ac</sub></em> </pre>
*
* All of the raw source color components need to be multiplied
* by the alpha in the {@code AlphaComposite} instance.
* Additionally, if the source was not in premultiplied form
* then the color components also need to be multiplied by the
* source alpha.
* Thus, the equation for producing the source color components
* for the Porter and Duff equation depends on whether the source
* pixels are premultiplied or not:
*
* <pre>
* <em>C<sub>s</sub></em> = <em>C<sub>sr</sub></em> * <em>A<sub>sr</sub></em> * <em>A<sub>ac</sub></em> (if source is not premultiplied)
* <em>C<sub>s</sub></em> = <em>C<sub>sr</sub></em> * <em>A<sub>ac</sub></em> (if source is premultiplied) </pre>
*
* No adjustment needs to be made to the destination alpha:
*
* <pre>
* <em>A<sub>d</sub></em> = <em>A<sub>dr</sub></em> </pre>
*
* <p>
* The destination color components need to be adjusted only if
* they are not in premultiplied form:
*
* <pre>
* <em>C<sub>d</sub></em> = <em>C<sub>dr</sub></em> * <em>A<sub>d</sub></em> (if destination is not premultiplied)
* <em>C<sub>d</sub></em> = <em>C<sub>dr</sub></em> (if destination is premultiplied) </pre>
*
* <h3>Applying the Blending Equation</h3>
*
* <p>
* The adjusted <em>A<sub>s</sub></em>, <em>A<sub>d</sub></em>,
* <em>C<sub>s</sub></em>, and <em>C<sub>d</sub></em> are used in the standard
* Porter and Duff equations to calculate the blending factors
* <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em> and then the resulting
* premultiplied components <em>A<sub>r</sub></em> and <em>C<sub>r</sub></em>.
*
* <h3>Preparing Results</h3>
*
* <p>
* The results only need to be adjusted if they are to be stored
* back into a destination buffer that holds data that is not
* premultiplied, using the following equations:
*
* <pre>
* <em>A<sub>df</sub></em> = <em>A<sub>r</sub></em>
* <em>C<sub>df</sub></em> = <em>C<sub>r</sub></em> (if dest is premultiplied)
* <em>C<sub>df</sub></em> = <em>C<sub>r</sub></em> / <em>A<sub>r</sub></em> (if dest is not premultiplied) </pre>
*
* Note that since the division is undefined if the resulting alpha
* is zero, the division in that case is omitted to avoid the "divide
* by zero" and the color components are left as
* all zeros.
*
* <h3>Performance Considerations</h3>
*
* <p>
* For performance reasons, it is preferable that
* {@code Raster} objects passed to the {@code compose}
* method of a {@link CompositeContext} object created by the
* {@code AlphaComposite} class have premultiplied data.
* If either the source {@code Raster}
* or the destination {@code Raster}
* is not premultiplied, however,
* appropriate conversions are performed before and after the compositing
* operation.
*
* <h3><a id="caveats">Implementation Caveats</a></h3>
*
* <ul>
* <li>
* Many sources, such as some of the opaque image types listed
* in the {@code BufferedImage} class, do not store alpha values
* for their pixels. Such sources supply an alpha of 1.0 for
* all of their pixels.
*
* <li>
* Many destinations also have no place to store the alpha values
* that result from the blending calculations performed by this class.
* Such destinations thus implicitly discard the resulting
* alpha values that this class produces.
* It is recommended that such destinations should treat their stored
* color values as non-premultiplied and divide the resulting color
* values by the resulting alpha value before storing the color
* values and discarding the alpha value.
*
* <li>
* The accuracy of the results depends on the manner in which pixels
* are stored in the destination.
* An image format that provides at least 8 bits of storage per color
* and alpha component is at least adequate for use as a destination
* for a sequence of a few to a dozen compositing operations.
* An image format with fewer than 8 bits of storage per component
* is of limited use for just one or two compositing operations
* before the rounding errors dominate the results.
* An image format
* that does not separately store
* color components is not a
* good candidate for any type of translucent blending.
* For example, {@code BufferedImage.TYPE_BYTE_INDEXED}
* should not be used as a destination for a blending operation
* because every operation
* can introduce large errors, due to
* the need to choose a pixel from a limited palette to match the
* results of the blending equations.
*
* <li>
* Nearly all formats store pixels as discrete integers rather than
* the floating point values used in the reference equations above.
* The implementation can either scale the integer pixel
* values into floating point values in the range 0.0 to 1.0 or
* use slightly modified versions of the equations
* that operate entirely in the integer domain and yet produce
* analogous results to the reference equations.
*
* <p>
* Typically the integer values are related to the floating point
* values in such a way that the integer 0 is equated
* to the floating point value 0.0 and the integer
* 2^<em>n</em>-1 (where <em>n</em> is the number of bits
* in the representation) is equated to 1.0.
* For 8-bit representations, this means that 0x00
* represents 0.0 and 0xff represents
* 1.0.
*
* <li>
* The internal implementation can approximate some of the equations
* and it can also eliminate some steps to avoid unnecessary operations.
* For example, consider a discrete integer image with non-premultiplied
* alpha values that uses 8 bits per component for storage.
* The stored values for a
* nearly transparent darkened red might be:
*
* <pre>
* (A, R, G, B) = (0x01, 0xb0, 0x00, 0x00)</pre>
*
* <p>
* If integer math were being used and this value were being
* composited in
* <a href="#SRC">{@code SRC}</a>
* mode with no extra alpha, then the math would
* indicate that the results were (in integer format):
*
* <pre>
* (A, R, G, B) = (0x01, 0x01, 0x00, 0x00)</pre>
*
* <p>
* Note that the intermediate values, which are always in premultiplied
* form, would only allow the integer red component to be either 0x00
* or 0x01. When we try to store this result back into a destination
* that is not premultiplied, dividing out the alpha will give us
* very few choices for the non-premultiplied red value.
* In this case an implementation that performs the math in integer
* space without shortcuts is likely to end up with the final pixel
* values of:
*
* <pre>
* (A, R, G, B) = (0x01, 0xff, 0x00, 0x00)</pre>
*
* <p>
* (Note that 0x01 divided by 0x01 gives you 1.0, which is equivalent
* to the value 0xff in an 8-bit storage format.)
*
* <p>
* Alternately, an implementation that uses floating point math
* might produce more accurate results and end up returning to the
* original pixel value with little, if any, round-off error.
* Or, an implementation using integer math might decide that since
* the equations boil down to a virtual NOP on the color values
* if performed in a floating point space, it can transfer the
* pixel untouched to the destination and avoid all the math entirely.
*
* <p>
* These implementations all attempt to honor the
* same equations, but use different tradeoffs of integer and
* floating point math and reduced or full equations.
* To account for such differences, it is probably best to
* expect only that the premultiplied form of the results to
* match between implementations and image formats. In this
* case both answers, expressed in premultiplied form would
* equate to:
*
* <pre>
* (A, R, G, B) = (0x01, 0x01, 0x00, 0x00)</pre>
*
* <p>
* and thus they would all match.
*
* <li>
* Because of the technique of simplifying the equations for
* calculation efficiency, some implementations might perform
* differently when encountering result alpha values of 0.0
* on a non-premultiplied destination.
* Note that the simplification of removing the divide by alpha
* in the case of the SRC rule is technically not valid if the
* denominator (alpha) is 0.
* But, since the results should only be expected to be accurate
* when viewed in premultiplied form, a resulting alpha of 0
* essentially renders the resulting color components irrelevant
* and so exact behavior in this case should not be expected.
* </ul>
* @see Composite
* @see CompositeContext
*/
public final class AlphaComposite implements Composite {
/**
* Both the color and the alpha of the destination are cleared
* (Porter-Duff Clear rule).
* Neither the source nor the destination is used as input.
*<p>
* <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = 0, thus:
*<pre>
* <em>A<sub>r</sub></em> = 0
* <em>C<sub>r</sub></em> = 0
*</pre>
*/
@Native public static final int CLEAR = 1;
/**
* The source is copied to the destination
* (Porter-Duff Source rule).
* The destination is not used as input.
*<p>
* <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = 0, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>
*</pre>
*/
@Native public static final int SRC = 2;
/**
* The destination is left untouched
* (Porter-Duff Destination rule).
*<p>
* <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = 1, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>
*</pre>
* @since 1.4
*/
@Native public static final int DST = 9;
// Note that DST was added in 1.4 so it is numbered out of order...
/**
* The source is composited over the destination
* (Porter-Duff Source Over Destination rule).
*<p>
* <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em> + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em> + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
*</pre>
*/
@Native public static final int SRC_OVER = 3;
/**
* The destination is composited over the source and
* the result replaces the destination
* (Porter-Duff Destination Over Source rule).
*<p>
* <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = 1, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em>
*</pre>
*/
@Native public static final int DST_OVER = 4;
/**
* The part of the source lying inside of the destination replaces
* the destination
* (Porter-Duff Source In Destination rule).
*<p>
* <em>F<sub>s</sub></em> = <em>A<sub>d</sub></em> and <em>F<sub>d</sub></em> = 0, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>A<sub>d</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>A<sub>d</sub></em>
*</pre>
*/
@Native public static final int SRC_IN = 5;
/**
* The part of the destination lying inside of the source
* replaces the destination
* (Porter-Duff Destination In Source rule).
*<p>
* <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = <em>A<sub>s</sub></em>, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>*<em>A<sub>s</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>*<em>A<sub>s</sub></em>
*</pre>
*/
@Native public static final int DST_IN = 6;
/**
* The part of the source lying outside of the destination
* replaces the destination
* (Porter-Duff Source Held Out By Destination rule).
*<p>
* <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = 0, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>)
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>)
*</pre>
*/
@Native public static final int SRC_OUT = 7;
/**
* The part of the destination lying outside of the source
* replaces the destination
* (Porter-Duff Destination Held Out By Source rule).
*<p>
* <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
* <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
*</pre>
*/
@Native public static final int DST_OUT = 8;
// Rule 9 is DST which is defined above where it fits into the
// list logically, rather than numerically
//
// public static final int DST = 9;
/**
* The part of the source lying inside of the destination
* is composited onto the destination
* (Porter-Duff Source Atop Destination rule).
*<p>
* <em>F<sub>s</sub></em> = <em>A<sub>d</sub></em> and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>A<sub>d</sub></em> + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) = <em>A<sub>d</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>A<sub>d</sub></em> + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
*</pre>
* @since 1.4
*/
@Native public static final int SRC_ATOP = 10;
/**
* The part of the destination lying inside of the source
* is composited over the source and replaces the destination
* (Porter-Duff Destination Atop Source rule).
*<p>
* <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = <em>A<sub>s</sub></em>, thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em>*<em>A<sub>s</sub></em> = <em>A<sub>s</sub></em>
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em>*<em>A<sub>s</sub></em>
*</pre>
* @since 1.4
*/
@Native public static final int DST_ATOP = 11;
/**
* The part of the source that lies outside of the destination
* is combined with the part of the destination that lies outside
* of the source
* (Porter-Duff Source Xor Destination rule).
*<p>
* <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus:
*<pre>
* <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
* <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
*</pre>
* @since 1.4
*/
@Native public static final int XOR = 12;
/**
* {@code AlphaComposite} object that implements the opaque CLEAR rule
* with an alpha of 1.0f.
* @see #CLEAR
*/
public static final AlphaComposite Clear = new AlphaComposite(CLEAR);
/**
* {@code AlphaComposite} object that implements the opaque SRC rule
* with an alpha of 1.0f.
* @see #SRC
*/
public static final AlphaComposite Src = new AlphaComposite(SRC);
/**
* {@code AlphaComposite} object that implements the opaque DST rule
* with an alpha of 1.0f.
* @see #DST
* @since 1.4
*/
public static final AlphaComposite Dst = new AlphaComposite(DST);
/**
* {@code AlphaComposite} object that implements the opaque SRC_OVER rule
* with an alpha of 1.0f.
* @see #SRC_OVER
*/
public static final AlphaComposite SrcOver = new AlphaComposite(SRC_OVER);
/**
* {@code AlphaComposite} object that implements the opaque DST_OVER rule
* with an alpha of 1.0f.
* @see #DST_OVER
*/
public static final AlphaComposite DstOver = new AlphaComposite(DST_OVER);
/**
* {@code AlphaComposite} object that implements the opaque SRC_IN rule
* with an alpha of 1.0f.
* @see #SRC_IN
*/
public static final AlphaComposite SrcIn = new AlphaComposite(SRC_IN);
/**
* {@code AlphaComposite} object that implements the opaque DST_IN rule
* with an alpha of 1.0f.
* @see #DST_IN
*/
public static final AlphaComposite DstIn = new AlphaComposite(DST_IN);
/**
* {@code AlphaComposite} object that implements the opaque SRC_OUT rule
* with an alpha of 1.0f.
* @see #SRC_OUT
*/
public static final AlphaComposite SrcOut = new AlphaComposite(SRC_OUT);
/**
* {@code AlphaComposite} object that implements the opaque DST_OUT rule
* with an alpha of 1.0f.
* @see #DST_OUT
*/
public static final AlphaComposite DstOut = new AlphaComposite(DST_OUT);
/**
* {@code AlphaComposite} object that implements the opaque SRC_ATOP rule
* with an alpha of 1.0f.
* @see #SRC_ATOP
* @since 1.4
*/
public static final AlphaComposite SrcAtop = new AlphaComposite(SRC_ATOP);
/**
* {@code AlphaComposite} object that implements the opaque DST_ATOP rule
* with an alpha of 1.0f.
* @see #DST_ATOP
* @since 1.4
*/
public static final AlphaComposite DstAtop = new AlphaComposite(DST_ATOP);
/**
* {@code AlphaComposite} object that implements the opaque XOR rule
* with an alpha of 1.0f.
* @see #XOR
* @since 1.4
*/
public static final AlphaComposite Xor = new AlphaComposite(XOR);
@Native private static final int MIN_RULE = CLEAR;
@Native private static final int MAX_RULE = XOR;
float extraAlpha;
int rule;
private AlphaComposite(int rule) {
this(rule, 1.0f);
}
private AlphaComposite(int rule, float alpha) {
if (rule < MIN_RULE || rule > MAX_RULE) {
throw new IllegalArgumentException("unknown composite rule");
}
if (alpha >= 0.0f && alpha <= 1.0f) {
this.rule = rule;
this.extraAlpha = alpha;
} else {
throw new IllegalArgumentException("alpha value out of range");
}
}
/**
* Creates an {@code AlphaComposite} object with the specified rule.
*
* @param rule the compositing rule
* @return the {@code AlphaComposite} object created
* @throws IllegalArgumentException if {@code rule} is not one of
* the following: {@link #CLEAR}, {@link #SRC}, {@link #DST},
* {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN},
* {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT},
* {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR}
*/
public static AlphaComposite getInstance(int rule) {
switch (rule) {
case CLEAR:
return Clear;
case SRC:
return Src;
case DST:
return Dst;
case SRC_OVER:
return SrcOver;
case DST_OVER:
return DstOver;
case SRC_IN:
return SrcIn;
case DST_IN:
return DstIn;
case SRC_OUT:
return SrcOut;
case DST_OUT:
return DstOut;
case SRC_ATOP:
return SrcAtop;
case DST_ATOP:
return DstAtop;
case XOR:
return Xor;
default:
throw new IllegalArgumentException("unknown composite rule");
}
}
/**
* Creates an {@code AlphaComposite} object with the specified rule and
* the constant alpha to multiply with the alpha of the source.
* The source is multiplied with the specified alpha before being composited
* with the destination.
*
* @param rule the compositing rule
* @param alpha the constant alpha to be multiplied with the alpha of
* the source. {@code alpha} must be a floating point number in the
* inclusive range [0.0,&nbsp;1.0].
* @return the {@code AlphaComposite} object created
* @throws IllegalArgumentException if
* {@code alpha} is less than 0.0 or greater than 1.0, or if
* {@code rule} is not one of
* the following: {@link #CLEAR}, {@link #SRC}, {@link #DST},
* {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN},
* {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT},
* {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR}
*/
public static AlphaComposite getInstance(int rule, float alpha) {
if (alpha == 1.0f) {
return getInstance(rule);
}
return new AlphaComposite(rule, alpha);
}
/**
* Creates a context for the compositing operation.
* The context contains state that is used in performing
* the compositing operation.
* @param srcColorModel the {@link ColorModel} of the source
* @param dstColorModel the {@code ColorModel} of the destination
* @return the {@code CompositeContext} object to be used to perform
* compositing operations.
*/
public CompositeContext createContext(ColorModel srcColorModel,
ColorModel dstColorModel,
RenderingHints hints) {
return new SunCompositeContext(this, srcColorModel, dstColorModel);
}
/**
* Returns the alpha value of this {@code AlphaComposite}. If this
* {@code AlphaComposite} does not have an alpha value, 1.0 is returned.
* @return the alpha value of this {@code AlphaComposite}.
*/
public float getAlpha() {
return extraAlpha;
}
/**
* Returns the compositing rule of this {@code AlphaComposite}.
* @return the compositing rule of this {@code AlphaComposite}.
*/
public int getRule() {
return rule;
}
/**
* Returns a similar {@code AlphaComposite} object that uses
* the specified compositing rule.
* If this object already uses the specified compositing rule,
* this object is returned.
* @return an {@code AlphaComposite} object derived from
* this object that uses the specified compositing rule.
* @param rule the compositing rule
* @throws IllegalArgumentException if
* {@code rule} is not one of
* the following: {@link #CLEAR}, {@link #SRC}, {@link #DST},
* {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN},
* {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT},
* {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR}
* @since 1.6
*/
public AlphaComposite derive(int rule) {
return (this.rule == rule)
? this
: getInstance(rule, this.extraAlpha);
}
/**
* Returns a similar {@code AlphaComposite} object that uses
* the specified alpha value.
* If this object already has the specified alpha value,
* this object is returned.
* @return an {@code AlphaComposite} object derived from
* this object that uses the specified alpha value.
* @param alpha the constant alpha to be multiplied with the alpha of
* the source. {@code alpha} must be a floating point number in the
* inclusive range [0.0,&nbsp;1.0].
* @throws IllegalArgumentException if
* {@code alpha} is less than 0.0 or greater than 1.0
* @since 1.6
*/
public AlphaComposite derive(float alpha) {
return (this.extraAlpha == alpha)
? this
: getInstance(this.rule, alpha);
}
/**
* Returns the hashcode for this composite.
* @return a hash code for this composite.
*/
public int hashCode() {
return (Float.floatToIntBits(extraAlpha) * 31 + rule);
}
/**
* Determines whether the specified object is equal to this
* {@code AlphaComposite}.
* <p>
* The result is {@code true} if and only if
* the argument is not {@code null} and is an
* {@code AlphaComposite} object that has the same
* compositing rule and alpha value as this object.
*
* @param obj the {@code Object} to test for equality
* @return {@code true} if {@code obj} equals this
* {@code AlphaComposite}; {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (!(obj instanceof AlphaComposite)) {
return false;
}
AlphaComposite ac = (AlphaComposite) obj;
if (rule != ac.rule) {
return false;
}
if (extraAlpha != ac.extraAlpha) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import sun.util.logging.PlatformLogger;
abstract class AttributeValue {
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.AttributeValue");
private final int value;
private final String[] names;
protected AttributeValue(int value, String[] names) {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("value = " + value + ", names = " + names);
}
if (log.isLoggable(PlatformLogger.Level.FINER)) {
if ((value < 0) || (names == null) || (value >= names.length)) {
log.finer("Assertion failed");
}
}
this.value = value;
this.names = names;
}
// This hashCode is used by the sun.awt implementation as an array
// index.
public int hashCode() {
return value;
}
public String toString() {
return names[value];
}
}

View file

@ -0,0 +1,447 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.beans.ConstructorProperties;
import java.lang.annotation.Native;
/**
* The {@code BasicStroke} class defines a basic set of rendering
* attributes for the outlines of graphics primitives, which are rendered
* with a {@link Graphics2D} object that has its Stroke attribute set to
* this {@code BasicStroke}.
* The rendering attributes defined by {@code BasicStroke} describe
* the shape of the mark made by a pen drawn along the outline of a
* {@link Shape} and the decorations applied at the ends and joins of
* path segments of the {@code Shape}.
* These rendering attributes include:
* <dl>
* <dt><i>width</i>
* <dd>The pen width, measured perpendicularly to the pen trajectory.
* <dt><i>end caps</i>
* <dd>The decoration applied to the ends of unclosed subpaths and
* dash segments. Subpaths that start and end on the same point are
* still considered unclosed if they do not have a CLOSE segment.
* See {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE}
* for more information on the CLOSE segment.
* The three different decorations are: {@link #CAP_BUTT},
* {@link #CAP_ROUND}, and {@link #CAP_SQUARE}.
* <dt><i>line joins</i>
* <dd>The decoration applied at the intersection of two path segments
* and at the intersection of the endpoints of a subpath that is closed
* using {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE}.
* The three different decorations are: {@link #JOIN_BEVEL},
* {@link #JOIN_MITER}, and {@link #JOIN_ROUND}.
* <dt><i>miter limit</i>
* <dd>The limit to trim a line join that has a JOIN_MITER decoration.
* A line join is trimmed when the ratio of miter length to stroke
* width is greater than the miterlimit value. The miter length is
* the diagonal length of the miter, which is the distance between
* the inside corner and the outside corner of the intersection.
* The smaller the angle formed by two line segments, the longer
* the miter length and the sharper the angle of intersection. The
* default miterlimit value of 10.0f causes all angles less than
* 11 degrees to be trimmed. Trimming miters converts
* the decoration of the line join to bevel.
* <dt><i>dash attributes</i>
* <dd>The definition of how to make a dash pattern by alternating
* between opaque and transparent sections.
* </dl>
* All attributes that specify measurements and distances controlling
* the shape of the returned outline are measured in the same
* coordinate system as the original unstroked {@code Shape}
* argument. When a {@code Graphics2D} object uses a
* {@code Stroke} object to redefine a path during the execution
* of one of its {@code draw} methods, the geometry is supplied
* in its original form before the {@code Graphics2D} transform
* attribute is applied. Therefore, attributes such as the pen width
* are interpreted in the user space coordinate system of the
* {@code Graphics2D} object and are subject to the scaling and
* shearing effects of the user-space-to-device-space transform in that
* particular {@code Graphics2D}.
* For example, the width of a rendered shape's outline is determined
* not only by the width attribute of this {@code BasicStroke},
* but also by the transform attribute of the
* {@code Graphics2D} object. Consider this code:
* <blockquote><pre>{@code
* // sets the Graphics2D object's Transform attribute
* g2d.scale(10, 10);
* // sets the Graphics2D object's Stroke attribute
* g2d.setStroke(new BasicStroke(1.5f));
* }</pre></blockquote>
* Assuming there are no other scaling transforms added to the
* {@code Graphics2D} object, the resulting line
* will be approximately 15 pixels wide.
* As the example code demonstrates, a floating-point line
* offers better precision, especially when large transforms are
* used with a {@code Graphics2D} object.
* When a line is diagonal, the exact width depends on how the
* rendering pipeline chooses which pixels to fill as it traces the
* theoretical widened outline. The choice of which pixels to turn
* on is affected by the antialiasing attribute because the
* antialiasing rendering pipeline can choose to color
* partially-covered pixels.
* <p>
* For more information on the user space coordinate system and the
* rendering process, see the {@code Graphics2D} class comments.
* @see Graphics2D
* @author Jim Graham
*/
public class BasicStroke implements Stroke {
/**
* Joins path segments by extending their outside edges until
* they meet.
*/
@Native public static final int JOIN_MITER = 0;
/**
* Joins path segments by rounding off the corner at a radius
* of half the line width.
*/
@Native public static final int JOIN_ROUND = 1;
/**
* Joins path segments by connecting the outer corners of their
* wide outlines with a straight segment.
*/
@Native public static final int JOIN_BEVEL = 2;
/**
* Ends unclosed subpaths and dash segments with no added
* decoration.
*/
@Native public static final int CAP_BUTT = 0;
/**
* Ends unclosed subpaths and dash segments with a round
* decoration that has a radius equal to half of the width
* of the pen.
*/
@Native public static final int CAP_ROUND = 1;
/**
* Ends unclosed subpaths and dash segments with a square
* projection that extends beyond the end of the segment
* to a distance equal to half of the line width.
*/
@Native public static final int CAP_SQUARE = 2;
float width;
int join;
int cap;
float miterlimit;
float dash[];
float dash_phase;
/**
* Constructs a new {@code BasicStroke} with the specified
* attributes.
* @param width the width of this {@code BasicStroke}. The
* width must be greater than or equal to 0.0f. If width is
* set to 0.0f, the stroke is rendered as the thinnest
* possible line for the target device and the antialias
* hint setting.
* @param cap the decoration of the ends of a {@code BasicStroke}
* @param join the decoration applied where path segments meet
* @param miterlimit the limit to trim the miter join. The miterlimit
* must be greater than or equal to 1.0f.
* @param dash the array representing the dashing pattern
* @param dash_phase the offset to start the dashing pattern
* @throws IllegalArgumentException if {@code width} is negative
* @throws IllegalArgumentException if {@code cap} is not either
* CAP_BUTT, CAP_ROUND or CAP_SQUARE
* @throws IllegalArgumentException if {@code miterlimit} is less
* than 1 and {@code join} is JOIN_MITER
* @throws IllegalArgumentException if {@code join} is not
* either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
* @throws IllegalArgumentException if {@code dash_phase}
* is negative and {@code dash} is not {@code null}
* @throws IllegalArgumentException if the length of
* {@code dash} is zero
* @throws IllegalArgumentException if dash lengths are all zero.
*/
@ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" })
public BasicStroke(float width, int cap, int join, float miterlimit,
float dash[], float dash_phase) {
if (width < 0.0f) {
throw new IllegalArgumentException("negative width");
}
if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
throw new IllegalArgumentException("illegal end cap value");
}
if (join == JOIN_MITER) {
if (miterlimit < 1.0f) {
throw new IllegalArgumentException("miter limit < 1");
}
} else if (join != JOIN_ROUND && join != JOIN_BEVEL) {
throw new IllegalArgumentException("illegal line join value");
}
if (dash != null) {
if (dash_phase < 0.0f) {
throw new IllegalArgumentException("negative dash phase");
}
boolean allzero = true;
for (int i = 0; i < dash.length; i++) {
float d = dash[i];
if (d > 0.0) {
allzero = false;
} else if (d < 0.0) {
throw new IllegalArgumentException("negative dash length");
}
}
if (allzero) {
throw new IllegalArgumentException("dash lengths all zero");
}
}
this.width = width;
this.cap = cap;
this.join = join;
this.miterlimit = miterlimit;
if (dash != null) {
this.dash = dash.clone();
}
this.dash_phase = dash_phase;
}
/**
* Constructs a solid {@code BasicStroke} with the specified
* attributes.
* @param width the width of the {@code BasicStroke}
* @param cap the decoration of the ends of a {@code BasicStroke}
* @param join the decoration applied where path segments meet
* @param miterlimit the limit to trim the miter join
* @throws IllegalArgumentException if {@code width} is negative
* @throws IllegalArgumentException if {@code cap} is not either
* CAP_BUTT, CAP_ROUND or CAP_SQUARE
* @throws IllegalArgumentException if {@code miterlimit} is less
* than 1 and {@code join} is JOIN_MITER
* @throws IllegalArgumentException if {@code join} is not
* either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
*/
public BasicStroke(float width, int cap, int join, float miterlimit) {
this(width, cap, join, miterlimit, null, 0.0f);
}
/**
* Constructs a solid {@code BasicStroke} with the specified
* attributes. The {@code miterlimit} parameter is
* unnecessary in cases where the default is allowable or the
* line joins are not specified as JOIN_MITER.
* @param width the width of the {@code BasicStroke}
* @param cap the decoration of the ends of a {@code BasicStroke}
* @param join the decoration applied where path segments meet
* @throws IllegalArgumentException if {@code width} is negative
* @throws IllegalArgumentException if {@code cap} is not either
* CAP_BUTT, CAP_ROUND or CAP_SQUARE
* @throws IllegalArgumentException if {@code join} is not
* either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
*/
public BasicStroke(float width, int cap, int join) {
this(width, cap, join, 10.0f, null, 0.0f);
}
/**
* Constructs a solid {@code BasicStroke} with the specified
* line width and with default values for the cap and join
* styles.
* @param width the width of the {@code BasicStroke}
* @throws IllegalArgumentException if {@code width} is negative
*/
public BasicStroke(float width) {
this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
}
/**
* Constructs a new {@code BasicStroke} with defaults for all
* attributes.
* The default attributes are a solid line of width 1.0, CAP_SQUARE,
* JOIN_MITER, a miter limit of 10.0.
*/
public BasicStroke() {
this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
}
/**
* Returns a {@code Shape} whose interior defines the
* stroked outline of a specified {@code Shape}.
* @param s the {@code Shape} boundary be stroked
* @return the {@code Shape} of the stroked outline.
*/
public Shape createStrokedShape(Shape s) {
sun.java2d.pipe.RenderingEngine re =
sun.java2d.pipe.RenderingEngine.getInstance();
return re.createStrokedShape(s, width, cap, join, miterlimit,
dash, dash_phase);
}
/**
* Returns the line width. Line width is represented in user space,
* which is the default-coordinate space used by Java 2D. See the
* {@code Graphics2D} class comments for more information on
* the user space coordinate system.
* @return the line width of this {@code BasicStroke}.
* @see Graphics2D
*/
public float getLineWidth() {
return width;
}
/**
* Returns the end cap style.
* @return the end cap style of this {@code BasicStroke} as one
* of the static {@code int} values that define possible end cap
* styles.
*/
public int getEndCap() {
return cap;
}
/**
* Returns the line join style.
* @return the line join style of the {@code BasicStroke} as one
* of the static {@code int} values that define possible line
* join styles.
*/
public int getLineJoin() {
return join;
}
/**
* Returns the limit of miter joins.
* @return the limit of miter joins of the {@code BasicStroke}.
*/
public float getMiterLimit() {
return miterlimit;
}
/**
* Returns the array representing the lengths of the dash segments.
* Alternate entries in the array represent the user space lengths
* of the opaque and transparent segments of the dashes.
* As the pen moves along the outline of the {@code Shape}
* to be stroked, the user space
* distance that the pen travels is accumulated. The distance
* value is used to index into the dash array.
* The pen is opaque when its current cumulative distance maps
* to an even element of the dash array and transparent otherwise.
* @return the dash array.
*/
public float[] getDashArray() {
if (dash == null) {
return null;
}
return dash.clone();
}
/**
* Returns the current dash phase.
* The dash phase is a distance specified in user coordinates that
* represents an offset into the dashing pattern. In other words, the dash
* phase defines the point in the dashing pattern that will correspond to
* the beginning of the stroke.
* @return the dash phase as a {@code float} value.
*/
public float getDashPhase() {
return dash_phase;
}
/**
* Returns the hashcode for this stroke.
* @return a hash code for this stroke.
*/
public int hashCode() {
int hash = Float.floatToIntBits(width);
hash = hash * 31 + join;
hash = hash * 31 + cap;
hash = hash * 31 + Float.floatToIntBits(miterlimit);
if (dash != null) {
hash = hash * 31 + Float.floatToIntBits(dash_phase);
for (int i = 0; i < dash.length; i++) {
hash = hash * 31 + Float.floatToIntBits(dash[i]);
}
}
return hash;
}
/**
* Returns true if this BasicStroke represents the same
* stroking operation as the given argument.
*/
/**
* Tests if a specified object is equal to this {@code BasicStroke}
* by first testing if it is a {@code BasicStroke} and then comparing
* its width, join, cap, miter limit, dash, and dash phase attributes with
* those of this {@code BasicStroke}.
* @param obj the specified object to compare to this
* {@code BasicStroke}
* @return {@code true} if the width, join, cap, miter limit, dash, and
* dash phase are the same for both objects;
* {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (!(obj instanceof BasicStroke)) {
return false;
}
BasicStroke bs = (BasicStroke) obj;
if (width != bs.width) {
return false;
}
if (join != bs.join) {
return false;
}
if (cap != bs.cap) {
return false;
}
if (miterlimit != bs.miterlimit) {
return false;
}
if (dash != null) {
if (dash_phase != bs.dash_phase) {
return false;
}
if (!java.util.Arrays.equals(dash, bs.dash)) {
return false;
}
}
else if (bs.dash != null) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,892 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.util.Hashtable;
/**
* A border layout lays out a container, arranging and resizing
* its components to fit in five regions:
* north, south, east, west, and center.
* Each region may contain no more than one component, and
* is identified by a corresponding constant:
* {@code NORTH}, {@code SOUTH}, {@code EAST},
* {@code WEST}, and {@code CENTER}. When adding a
* component to a container with a border layout, use one of these
* five constants, for example:
* <pre>
* Panel p = new Panel();
* p.setLayout(new BorderLayout());
* p.add(new Button("Okay"), BorderLayout.SOUTH);
* </pre>
* As a convenience, {@code BorderLayout} interprets the
* absence of a string specification the same as the constant
* {@code CENTER}:
* <pre>
* Panel p2 = new Panel();
* p2.setLayout(new BorderLayout());
* p2.add(new TextArea()); // Same as p.add(new TextArea(), BorderLayout.CENTER);
* </pre>
* <p>
* In addition, {@code BorderLayout} supports the relative
* positioning constants, {@code PAGE_START}, {@code PAGE_END},
* {@code LINE_START}, and {@code LINE_END}.
* In a container whose {@code ComponentOrientation} is set to
* {@code ComponentOrientation.LEFT_TO_RIGHT}, these constants map to
* {@code NORTH}, {@code SOUTH}, {@code WEST}, and
* {@code EAST}, respectively.
* <p>
* For compatibility with previous releases, {@code BorderLayout}
* also includes the relative positioning constants {@code BEFORE_FIRST_LINE},
* {@code AFTER_LAST_LINE}, {@code BEFORE_LINE_BEGINS} and
* {@code AFTER_LINE_ENDS}. These are equivalent to
* {@code PAGE_START}, {@code PAGE_END}, {@code LINE_START}
* and {@code LINE_END} respectively. For
* consistency with the relative positioning constants used by other
* components, the latter constants are preferred.
* <p>
* Mixing both absolute and relative positioning constants can lead to
* unpredictable results. If
* you use both types, the relative constants will take precedence.
* For example, if you add components using both the {@code NORTH}
* and {@code PAGE_START} constants in a container whose
* orientation is {@code LEFT_TO_RIGHT}, only the
* {@code PAGE_START} will be laid out.
* <p>
* NOTE: Currently,
* {@code BorderLayout} does not support vertical
* orientations. The {@code isVertical} setting on the container's
* {@code ComponentOrientation} is not respected.
* <p>
* The components are laid out according to their
* preferred sizes and the constraints of the container's size.
* The {@code NORTH} and {@code SOUTH} components may
* be stretched horizontally; the {@code EAST} and
* {@code WEST} components may be stretched vertically;
* the {@code CENTER} component may stretch both horizontally
* and vertically to fill any space left over.
* <p>
* Here is an example of five buttons in an applet laid out using
* the {@code BorderLayout} layout manager:
* <p>
* <img src="doc-files/BorderLayout-1.gif"
* alt="Diagram of an applet demonstrating BorderLayout.
* Each section of the BorderLayout contains a Button corresponding to its position in the layout, one of:
* North, West, Center, East, or South."
* style="float:center; margin: 7px 10px;">
* <p>
* The code for this applet is as follows:
*
* <hr><blockquote><pre>
* import java.awt.*;
* import java.applet.Applet;
*
* public class buttonDir extends Applet {
* public void init() {
* setLayout(new BorderLayout());
* add(new Button("North"), BorderLayout.NORTH);
* add(new Button("South"), BorderLayout.SOUTH);
* add(new Button("East"), BorderLayout.EAST);
* add(new Button("West"), BorderLayout.WEST);
* add(new Button("Center"), BorderLayout.CENTER);
* }
* }
* </pre></blockquote><hr>
*
* @author Arthur van Hoff
* @see java.awt.Container#add(String, Component)
* @see java.awt.ComponentOrientation
* @since 1.0
*/
public class BorderLayout implements LayoutManager2,
java.io.Serializable {
/**
* Constructs a border layout with the horizontal gaps
* between components.
* The horizontal gap is specified by {@code hgap}.
*
* @see #getHgap()
* @see #setHgap(int)
*
* @serial
*/
int hgap;
/**
* Constructs a border layout with the vertical gaps
* between components.
* The vertical gap is specified by {@code vgap}.
*
* @see #getVgap()
* @see #setVgap(int)
* @serial
*/
int vgap;
/**
* Constant to specify components location to be the
* north portion of the border layout.
* @serial
* @see #getChild(String, boolean)
* @see #addLayoutComponent
* @see #getLayoutAlignmentX
* @see #getLayoutAlignmentY
* @see #removeLayoutComponent
*/
Component north;
/**
* Constant to specify components location to be the
* west portion of the border layout.
* @serial
* @see #getChild(String, boolean)
* @see #addLayoutComponent
* @see #getLayoutAlignmentX
* @see #getLayoutAlignmentY
* @see #removeLayoutComponent
*/
Component west;
/**
* Constant to specify components location to be the
* east portion of the border layout.
* @serial
* @see #getChild(String, boolean)
* @see #addLayoutComponent
* @see #getLayoutAlignmentX
* @see #getLayoutAlignmentY
* @see #removeLayoutComponent
*/
Component east;
/**
* Constant to specify components location to be the
* south portion of the border layout.
* @serial
* @see #getChild(String, boolean)
* @see #addLayoutComponent
* @see #getLayoutAlignmentX
* @see #getLayoutAlignmentY
* @see #removeLayoutComponent
*/
Component south;
/**
* Constant to specify components location to be the
* center portion of the border layout.
* @serial
* @see #getChild(String, boolean)
* @see #addLayoutComponent
* @see #getLayoutAlignmentX
* @see #getLayoutAlignmentY
* @see #removeLayoutComponent
*/
Component center;
/**
*
* A relative positioning constant, that can be used instead of
* north, south, east, west or center.
* mixing the two types of constants can lead to unpredictable results. If
* you use both types, the relative constants will take precedence.
* For example, if you add components using both the {@code NORTH}
* and {@code BEFORE_FIRST_LINE} constants in a container whose
* orientation is {@code LEFT_TO_RIGHT}, only the
* {@code BEFORE_FIRST_LINE} will be laid out.
* This will be the same for lastLine, firstItem, lastItem.
* @serial
*/
Component firstLine;
/**
* A relative positioning constant, that can be used instead of
* north, south, east, west or center.
* Please read Description for firstLine.
* @serial
*/
Component lastLine;
/**
* A relative positioning constant, that can be used instead of
* north, south, east, west or center.
* Please read Description for firstLine.
* @serial
*/
Component firstItem;
/**
* A relative positioning constant, that can be used instead of
* north, south, east, west or center.
* Please read Description for firstLine.
* @serial
*/
Component lastItem;
/**
* The north layout constraint (top of container).
*/
public static final String NORTH = "North";
/**
* The south layout constraint (bottom of container).
*/
public static final String SOUTH = "South";
/**
* The east layout constraint (right side of container).
*/
public static final String EAST = "East";
/**
* The west layout constraint (left side of container).
*/
public static final String WEST = "West";
/**
* The center layout constraint (middle of container).
*/
public static final String CENTER = "Center";
/**
* Synonym for PAGE_START. Exists for compatibility with previous
* versions. PAGE_START is preferred.
*
* @see #PAGE_START
* @since 1.2
*/
public static final String BEFORE_FIRST_LINE = "First";
/**
* Synonym for PAGE_END. Exists for compatibility with previous
* versions. PAGE_END is preferred.
*
* @see #PAGE_END
* @since 1.2
*/
public static final String AFTER_LAST_LINE = "Last";
/**
* Synonym for LINE_START. Exists for compatibility with previous
* versions. LINE_START is preferred.
*
* @see #LINE_START
* @since 1.2
*/
public static final String BEFORE_LINE_BEGINS = "Before";
/**
* Synonym for LINE_END. Exists for compatibility with previous
* versions. LINE_END is preferred.
*
* @see #LINE_END
* @since 1.2
*/
public static final String AFTER_LINE_ENDS = "After";
/**
* The component comes before the first line of the layout's content.
* For Western, left-to-right and top-to-bottom orientations, this is
* equivalent to NORTH.
*
* @see java.awt.Component#getComponentOrientation
* @since 1.4
*/
public static final String PAGE_START = BEFORE_FIRST_LINE;
/**
* The component comes after the last line of the layout's content.
* For Western, left-to-right and top-to-bottom orientations, this is
* equivalent to SOUTH.
*
* @see java.awt.Component#getComponentOrientation
* @since 1.4
*/
public static final String PAGE_END = AFTER_LAST_LINE;
/**
* The component goes at the beginning of the line direction for the
* layout. For Western, left-to-right and top-to-bottom orientations,
* this is equivalent to WEST.
*
* @see java.awt.Component#getComponentOrientation
* @since 1.4
*/
public static final String LINE_START = BEFORE_LINE_BEGINS;
/**
* The component goes at the end of the line direction for the
* layout. For Western, left-to-right and top-to-bottom orientations,
* this is equivalent to EAST.
*
* @see java.awt.Component#getComponentOrientation
* @since 1.4
*/
public static final String LINE_END = AFTER_LINE_ENDS;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -8658291919501921765L;
/**
* Constructs a new border layout with
* no gaps between components.
*/
public BorderLayout() {
this(0, 0);
}
/**
* Constructs a border layout with the specified gaps
* between components.
* The horizontal gap is specified by {@code hgap}
* and the vertical gap is specified by {@code vgap}.
* @param hgap the horizontal gap.
* @param vgap the vertical gap.
*/
public BorderLayout(int hgap, int vgap) {
this.hgap = hgap;
this.vgap = vgap;
}
/**
* Returns the horizontal gap between components.
*
* @return the horizontal gap between components
* @since 1.1
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between components.
*
* @param hgap the horizontal gap between components
* @since 1.1
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Returns the vertical gap between components.
*
* @return the vertical gap between components
* @since 1.1
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components.
*
* @param vgap the vertical gap between components
* @since 1.1
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Adds the specified component to the layout, using the specified
* constraint object. For border layouts, the constraint must be
* one of the following constants: {@code NORTH},
* {@code SOUTH}, {@code EAST},
* {@code WEST}, or {@code CENTER}.
* <p>
* Most applications do not call this method directly. This method
* is called when a component is added to a container using the
* {@code Container.add} method with the same argument types.
* @param comp the component to be added.
* @param constraints an object that specifies how and where
* the component is added to the layout.
* @see java.awt.Container#add(java.awt.Component, java.lang.Object)
* @exception IllegalArgumentException if the constraint object is not
* a string, or if it not one of the five specified constants.
* @since 1.1
*/
public void addLayoutComponent(Component comp, Object constraints) {
synchronized (comp.getTreeLock()) {
if ((constraints == null) || (constraints instanceof String)) {
addLayoutComponent((String)constraints, comp);
} else {
throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)");
}
}
}
/**
* @deprecated replaced by {@code addLayoutComponent(Component, Object)}.
*/
@Deprecated
public void addLayoutComponent(String name, Component comp) {
synchronized (comp.getTreeLock()) {
/* Special case: treat null the same as "Center". */
if (name == null) {
name = "Center";
}
/* Assign the component to one of the known regions of the layout.
*/
if ("Center".equals(name)) {
center = comp;
} else if ("North".equals(name)) {
north = comp;
} else if ("South".equals(name)) {
south = comp;
} else if ("East".equals(name)) {
east = comp;
} else if ("West".equals(name)) {
west = comp;
} else if (BEFORE_FIRST_LINE.equals(name)) {
firstLine = comp;
} else if (AFTER_LAST_LINE.equals(name)) {
lastLine = comp;
} else if (BEFORE_LINE_BEGINS.equals(name)) {
firstItem = comp;
} else if (AFTER_LINE_ENDS.equals(name)) {
lastItem = comp;
} else {
throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name);
}
}
}
/**
* Removes the specified component from this border layout. This
* method is called when a container calls its {@code remove} or
* {@code removeAll} methods. Most applications do not call this
* method directly.
* @param comp the component to be removed.
* @see java.awt.Container#remove(java.awt.Component)
* @see java.awt.Container#removeAll()
*/
public void removeLayoutComponent(Component comp) {
synchronized (comp.getTreeLock()) {
if (comp == center) {
center = null;
} else if (comp == north) {
north = null;
} else if (comp == south) {
south = null;
} else if (comp == east) {
east = null;
} else if (comp == west) {
west = null;
}
if (comp == firstLine) {
firstLine = null;
} else if (comp == lastLine) {
lastLine = null;
} else if (comp == firstItem) {
firstItem = null;
} else if (comp == lastItem) {
lastItem = null;
}
}
}
/**
* Gets the component that was added using the given constraint
*
* @param constraints the desired constraint, one of {@code CENTER},
* {@code NORTH}, {@code SOUTH},
* {@code WEST}, {@code EAST},
* {@code PAGE_START}, {@code PAGE_END},
* {@code LINE_START}, {@code LINE_END}
* @return the component at the given location, or {@code null} if
* the location is empty
* @exception IllegalArgumentException if the constraint object is
* not one of the nine specified constants
* @see #addLayoutComponent(java.awt.Component, java.lang.Object)
* @since 1.5
*/
public Component getLayoutComponent(Object constraints) {
if (CENTER.equals(constraints)) {
return center;
} else if (NORTH.equals(constraints)) {
return north;
} else if (SOUTH.equals(constraints)) {
return south;
} else if (WEST.equals(constraints)) {
return west;
} else if (EAST.equals(constraints)) {
return east;
} else if (PAGE_START.equals(constraints)) {
return firstLine;
} else if (PAGE_END.equals(constraints)) {
return lastLine;
} else if (LINE_START.equals(constraints)) {
return firstItem;
} else if (LINE_END.equals(constraints)) {
return lastItem;
} else {
throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints);
}
}
/**
* Returns the component that corresponds to the given constraint location
* based on the target {@code Container}'s component orientation.
* Components added with the relative constraints {@code PAGE_START},
* {@code PAGE_END}, {@code LINE_START}, and {@code LINE_END}
* take precedence over components added with the explicit constraints
* {@code NORTH}, {@code SOUTH}, {@code WEST}, and {@code EAST}.
* The {@code Container}'s component orientation is used to determine the location of components
* added with {@code LINE_START} and {@code LINE_END}.
*
* @param constraints the desired absolute position, one of {@code CENTER},
* {@code NORTH}, {@code SOUTH},
* {@code EAST}, {@code WEST}
* @param target the {@code Container} used to obtain
* the constraint location based on the target
* {@code Container}'s component orientation.
* @return the component at the given location, or {@code null} if
* the location is empty
* @exception IllegalArgumentException if the constraint object is
* not one of the five specified constants
* @exception NullPointerException if the target parameter is null
* @see #addLayoutComponent(java.awt.Component, java.lang.Object)
* @since 1.5
*/
public Component getLayoutComponent(Container target, Object constraints) {
boolean ltr = target.getComponentOrientation().isLeftToRight();
Component result = null;
if (NORTH.equals(constraints)) {
result = (firstLine != null) ? firstLine : north;
} else if (SOUTH.equals(constraints)) {
result = (lastLine != null) ? lastLine : south;
} else if (WEST.equals(constraints)) {
result = ltr ? firstItem : lastItem;
if (result == null) {
result = west;
}
} else if (EAST.equals(constraints)) {
result = ltr ? lastItem : firstItem;
if (result == null) {
result = east;
}
} else if (CENTER.equals(constraints)) {
result = center;
} else {
throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints);
}
return result;
}
/**
* Gets the constraints for the specified component
*
* @param comp the component to be queried
* @return the constraint for the specified component,
* or null if component is null or is not present
* in this layout
* @see #addLayoutComponent(java.awt.Component, java.lang.Object)
* @since 1.5
*/
public Object getConstraints(Component comp) {
//fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null
if (comp == null){
return null;
}
if (comp == center) {
return CENTER;
} else if (comp == north) {
return NORTH;
} else if (comp == south) {
return SOUTH;
} else if (comp == west) {
return WEST;
} else if (comp == east) {
return EAST;
} else if (comp == firstLine) {
return PAGE_START;
} else if (comp == lastLine) {
return PAGE_END;
} else if (comp == firstItem) {
return LINE_START;
} else if (comp == lastItem) {
return LINE_END;
}
return null;
}
/**
* Determines the minimum size of the {@code target} container
* using this layout manager.
* <p>
* This method is called when a container calls its
* {@code getMinimumSize} method. Most applications do not call
* this method directly.
* @param target the container in which to do the layout.
* @return the minimum dimensions needed to lay out the subcomponents
* of the specified container.
* @see java.awt.Container
* @see java.awt.BorderLayout#preferredLayoutSize
* @see java.awt.Container#getMinimumSize()
*/
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
boolean ltr = target.getComponentOrientation().isLeftToRight();
Component c = null;
if ((c=getChild(EAST,ltr)) != null) {
Dimension d = c.getMinimumSize();
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(WEST,ltr)) != null) {
Dimension d = c.getMinimumSize();
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(CENTER,ltr)) != null) {
Dimension d = c.getMinimumSize();
dim.width += d.width;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(NORTH,ltr)) != null) {
Dimension d = c.getMinimumSize();
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
if ((c=getChild(SOUTH,ltr)) != null) {
Dimension d = c.getMinimumSize();
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
/**
* Determines the preferred size of the {@code target}
* container using this layout manager, based on the components
* in the container.
* <p>
* Most applications do not call this method directly. This method
* is called when a container calls its {@code getPreferredSize}
* method.
* @param target the container in which to do the layout.
* @return the preferred dimensions to lay out the subcomponents
* of the specified container.
* @see java.awt.Container
* @see java.awt.BorderLayout#minimumLayoutSize
* @see java.awt.Container#getPreferredSize()
*/
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
boolean ltr = target.getComponentOrientation().isLeftToRight();
Component c = null;
if ((c=getChild(EAST,ltr)) != null) {
Dimension d = c.getPreferredSize();
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(WEST,ltr)) != null) {
Dimension d = c.getPreferredSize();
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(CENTER,ltr)) != null) {
Dimension d = c.getPreferredSize();
dim.width += d.width;
dim.height = Math.max(d.height, dim.height);
}
if ((c=getChild(NORTH,ltr)) != null) {
Dimension d = c.getPreferredSize();
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
if ((c=getChild(SOUTH,ltr)) != null) {
Dimension d = c.getPreferredSize();
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
/**
* Returns the maximum dimensions for this layout given the components
* in the specified target container.
* @param target the component which needs to be laid out
* @see Container
* @see #minimumLayoutSize
* @see #preferredLayoutSize
*/
public Dimension maximumLayoutSize(Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentX(Container parent) {
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentY(Container parent) {
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
/**
* Lays out the container argument using this border layout.
* <p>
* This method actually reshapes the components in the specified
* container in order to satisfy the constraints of this
* {@code BorderLayout} object. The {@code NORTH}
* and {@code SOUTH} components, if any, are placed at
* the top and bottom of the container, respectively. The
* {@code WEST} and {@code EAST} components are
* then placed on the left and right, respectively. Finally,
* the {@code CENTER} object is placed in any remaining
* space in the middle.
* <p>
* Most applications do not call this method directly. This method
* is called when a container calls its {@code doLayout} method.
* @param target the container in which to do the layout.
* @see java.awt.Container
* @see java.awt.Container#doLayout()
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int top = insets.top;
int bottom = target.height - insets.bottom;
int left = insets.left;
int right = target.width - insets.right;
boolean ltr = target.getComponentOrientation().isLeftToRight();
Component c = null;
if ((c=getChild(NORTH,ltr)) != null) {
c.setSize(right - left, c.height);
Dimension d = c.getPreferredSize();
c.setBounds(left, top, right - left, d.height);
top += d.height + vgap;
}
if ((c=getChild(SOUTH,ltr)) != null) {
c.setSize(right - left, c.height);
Dimension d = c.getPreferredSize();
c.setBounds(left, bottom - d.height, right - left, d.height);
bottom -= d.height + vgap;
}
if ((c=getChild(EAST,ltr)) != null) {
c.setSize(c.width, bottom - top);
Dimension d = c.getPreferredSize();
c.setBounds(right - d.width, top, d.width, bottom - top);
right -= d.width + hgap;
}
if ((c=getChild(WEST,ltr)) != null) {
c.setSize(c.width, bottom - top);
Dimension d = c.getPreferredSize();
c.setBounds(left, top, d.width, bottom - top);
left += d.width + hgap;
}
if ((c=getChild(CENTER,ltr)) != null) {
c.setBounds(left, top, right - left, bottom - top);
}
}
}
/**
* Get the component that corresponds to the given constraint location
*
* @param key The desired absolute position,
* either NORTH, SOUTH, EAST, or WEST.
* @param ltr Is the component line direction left-to-right?
*/
private Component getChild(String key, boolean ltr) {
Component result = null;
if (key == NORTH) {
result = (firstLine != null) ? firstLine : north;
}
else if (key == SOUTH) {
result = (lastLine != null) ? lastLine : south;
}
else if (key == WEST) {
result = ltr ? firstItem : lastItem;
if (result == null) {
result = west;
}
}
else if (key == EAST) {
result = ltr ? lastItem : firstItem;
if (result == null) {
result = east;
}
}
else if (key == CENTER) {
result = center;
}
if (result != null && !result.visible) {
result = null;
}
return result;
}
/**
* Returns a string representation of the state of this border layout.
* @return a string representation of this border layout.
*/
public String toString() {
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
}
}

View file

@ -0,0 +1,217 @@
/*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Capabilities and properties of buffers.
*
* @see java.awt.image.BufferStrategy#getCapabilities()
* @see GraphicsConfiguration#getBufferCapabilities
* @author Michael Martak
* @since 1.4
*/
public class BufferCapabilities implements Cloneable {
private ImageCapabilities frontCaps;
private ImageCapabilities backCaps;
private FlipContents flipContents;
/**
* Creates a new object for specifying buffering capabilities
* @param frontCaps the capabilities of the front buffer; cannot be
* {@code null}
* @param backCaps the capabilities of the back and intermediate buffers;
* cannot be {@code null}
* @param flipContents the contents of the back buffer after page-flipping,
* {@code null} if page flipping is not used (implies blitting)
* @exception IllegalArgumentException if frontCaps or backCaps are
* {@code null}
*/
public BufferCapabilities(ImageCapabilities frontCaps,
ImageCapabilities backCaps, FlipContents flipContents) {
if (frontCaps == null || backCaps == null) {
throw new IllegalArgumentException(
"Image capabilities specified cannot be null");
}
this.frontCaps = frontCaps;
this.backCaps = backCaps;
this.flipContents = flipContents;
}
/**
* @return the image capabilities of the front (displayed) buffer
*/
public ImageCapabilities getFrontBufferCapabilities() {
return frontCaps;
}
/**
* @return the image capabilities of all back buffers (intermediate buffers
* are considered back buffers)
*/
public ImageCapabilities getBackBufferCapabilities() {
return backCaps;
}
/**
* @return whether or not the buffer strategy uses page flipping; a set of
* buffers that uses page flipping
* can swap the contents internally between the front buffer and one or
* more back buffers by switching the video pointer (or by copying memory
* internally). A non-flipping set of
* buffers uses blitting to copy the contents from one buffer to
* another; when this is the case, {@code getFlipContents} returns
* {@code null}
*/
public boolean isPageFlipping() {
return (getFlipContents() != null);
}
/**
* @return the resulting contents of the back buffer after page-flipping.
* This value is {@code null} when the {@code isPageFlipping}
* returns {@code false}, implying blitting. It can be one of
* {@code FlipContents.UNDEFINED}
* (the assumed default), {@code FlipContents.BACKGROUND},
* {@code FlipContents.PRIOR}, or
* {@code FlipContents.COPIED}.
* @see #isPageFlipping
* @see FlipContents#UNDEFINED
* @see FlipContents#BACKGROUND
* @see FlipContents#PRIOR
* @see FlipContents#COPIED
*/
public FlipContents getFlipContents() {
return flipContents;
}
/**
* @return whether page flipping is only available in full-screen mode. If this
* is {@code true}, full-screen exclusive mode is required for
* page-flipping.
* @see #isPageFlipping
* @see GraphicsDevice#setFullScreenWindow
*/
public boolean isFullScreenRequired() {
return false;
}
/**
* @return whether or not
* page flipping can be performed using more than two buffers (one or more
* intermediate buffers as well as the front and back buffer).
* @see #isPageFlipping
*/
public boolean isMultiBufferAvailable() {
return false;
}
/**
* @return a copy of this BufferCapabilities object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Since we implement Cloneable, this should never happen
throw new InternalError(e);
}
}
// Inner class FlipContents
/**
* A type-safe enumeration of the possible back buffer contents after
* page-flipping
* @since 1.4
*/
public static final class FlipContents extends AttributeValue {
private static int I_UNDEFINED = 0;
private static int I_BACKGROUND = 1;
private static int I_PRIOR = 2;
private static int I_COPIED = 3;
private static final String NAMES[] =
{ "undefined", "background", "prior", "copied" };
/**
* When flip contents are {@code UNDEFINED}, the
* contents of the back buffer are undefined after flipping.
* @see #isPageFlipping
* @see #getFlipContents
* @see #BACKGROUND
* @see #PRIOR
* @see #COPIED
*/
public static final FlipContents UNDEFINED =
new FlipContents(I_UNDEFINED);
/**
* When flip contents are {@code BACKGROUND}, the
* contents of the back buffer are cleared with the background color after
* flipping.
* @see #isPageFlipping
* @see #getFlipContents
* @see #UNDEFINED
* @see #PRIOR
* @see #COPIED
*/
public static final FlipContents BACKGROUND =
new FlipContents(I_BACKGROUND);
/**
* When flip contents are {@code PRIOR}, the
* contents of the back buffer are the prior contents of the front buffer
* (a true page flip).
* @see #isPageFlipping
* @see #getFlipContents
* @see #UNDEFINED
* @see #BACKGROUND
* @see #COPIED
*/
public static final FlipContents PRIOR =
new FlipContents(I_PRIOR);
/**
* When flip contents are {@code COPIED}, the
* contents of the back buffer are copied to the front buffer when
* flipping.
* @see #isPageFlipping
* @see #getFlipContents
* @see #UNDEFINED
* @see #BACKGROUND
* @see #PRIOR
*/
public static final FlipContents COPIED =
new FlipContents(I_COPIED);
private FlipContents(int type) {
super(type, NAMES);
}
} // Inner class FlipContents
}

View file

@ -0,0 +1,676 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.ButtonPeer;
import java.beans.BeanProperty;
import java.util.EventListener;
import java.awt.event.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
/**
* This class creates a labeled button. The application can cause
* some action to happen when the button is pushed. This image
* depicts three views of a "{@code Quit}" button as it appears
* under the Solaris operating system:
* <p>
* <img src="doc-files/Button-1.gif" alt="The following context describes the graphic"
* style="float:center; margin: 7px 10px;">
* <p>
* The first view shows the button as it appears normally.
* The second view shows the button
* when it has input focus. Its outline is darkened to let the
* user know that it is an active object. The third view shows the
* button when the user clicks the mouse over the button, and thus
* requests that an action be performed.
* <p>
* The gesture of clicking on a button with the mouse
* is associated with one instance of {@code ActionEvent},
* which is sent out when the mouse is both pressed and released
* over the button. If an application is interested in knowing
* when the button has been pressed but not released, as a separate
* gesture, it can specialize {@code processMouseEvent},
* or it can register itself as a listener for mouse events by
* calling {@code addMouseListener}. Both of these methods are
* defined by {@code Component}, the abstract superclass of
* all components.
* <p>
* When a button is pressed and released, AWT sends an instance
* of {@code ActionEvent} to the button, by calling
* {@code processEvent} on the button. The button's
* {@code processEvent} method receives all events
* for the button; it passes an action event along by
* calling its own {@code processActionEvent} method.
* The latter method passes the action event on to any action
* listeners that have registered an interest in action
* events generated by this button.
* <p>
* If an application wants to perform some action based on
* a button being pressed and released, it should implement
* {@code ActionListener} and register the new listener
* to receive events from this button, by calling the button's
* {@code addActionListener} method. The application can
* make use of the button's action command as a messaging protocol.
*
* @author Sami Shaio
* @see java.awt.event.ActionEvent
* @see java.awt.event.ActionListener
* @see java.awt.Component#processMouseEvent
* @see java.awt.Component#addMouseListener
* @since 1.0
*/
public class Button extends Component implements Accessible {
/**
* The button's label. This value may be null.
* @serial
* @see #getLabel()
* @see #setLabel(String)
*/
String label;
/**
* The action to be performed once a button has been
* pressed. This value may be null.
* @serial
* @see #getActionCommand()
* @see #setActionCommand(String)
*/
String actionCommand;
transient ActionListener actionListener;
private static final String base = "button";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -8774683716313001058L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Initialize JNI field and method IDs for fields that may be
* accessed from C.
*/
private static native void initIDs();
/**
* Constructs a button with an empty string for its label.
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Button() throws HeadlessException {
this("");
}
/**
* Constructs a button with the specified label.
*
* @param label a string label for the button, or
* {@code null} for no label
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Button(String label) throws HeadlessException {
GraphicsEnvironment.checkHeadless();
this.label = label;
}
/**
* Construct a name for this component. Called by getName() when the
* name is null.
*/
String constructComponentName() {
synchronized (Button.class) {
return base + nameCounter++;
}
}
/**
* Creates the peer of the button. The button's peer allows the
* application to change the look of the button without changing
* its functionality.
*
* @see java.awt.Component#getToolkit()
*/
public void addNotify() {
synchronized(getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createButton(this);
super.addNotify();
}
}
/**
* Gets the label of this button.
*
* @return the button's label, or {@code null}
* if the button has no label.
* @see java.awt.Button#setLabel
*/
public String getLabel() {
return label;
}
/**
* Sets the button's label to be the specified string.
*
* @param label the new label, or {@code null}
* if the button has no label.
* @see java.awt.Button#getLabel
*/
public void setLabel(String label) {
boolean testvalid = false;
synchronized (this) {
if (label != this.label && (this.label == null ||
!this.label.equals(label))) {
this.label = label;
ButtonPeer peer = (ButtonPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
testvalid = true;
}
}
// This could change the preferred size of the Component.
if (testvalid) {
invalidateIfValid();
}
}
/**
* Sets the command name for the action event fired
* by this button. By default this action command is
* set to match the label of the button.
*
* @param command a string used to set the button's
* action command.
* If the string is {@code null} then the action command
* is set to match the label of the button.
* @see java.awt.event.ActionEvent
* @since 1.1
*/
public void setActionCommand(String command) {
actionCommand = command;
}
/**
* Returns the command name of the action event fired by this button.
* If the command name is {@code null} (default) then this method
* returns the label of the button.
*
* @return the action command name (or label) for this button
*/
public String getActionCommand() {
return (actionCommand == null? label : actionCommand);
}
/**
* Adds the specified action listener to receive action events from
* this button. Action events occur when a user presses or releases
* the mouse over this button.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the action listener
* @see #removeActionListener
* @see #getActionListeners
* @see java.awt.event.ActionListener
* @since 1.1
*/
public synchronized void addActionListener(ActionListener l) {
if (l == null) {
return;
}
actionListener = AWTEventMulticaster.add(actionListener, l);
newEventsOnly = true;
}
/**
* Removes the specified action listener so that it no longer
* receives action events from this button. Action events occur
* when a user presses or releases the mouse over this button.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the action listener
* @see #addActionListener
* @see #getActionListeners
* @see java.awt.event.ActionListener
* @since 1.1
*/
public synchronized void removeActionListener(ActionListener l) {
if (l == null) {
return;
}
actionListener = AWTEventMulticaster.remove(actionListener, l);
}
/**
* Returns an array of all the action listeners
* registered on this button.
*
* @return all of this button's {@code ActionListener}s
* or an empty array if no action
* listeners are currently registered
*
* @see #addActionListener
* @see #removeActionListener
* @see java.awt.event.ActionListener
* @since 1.4
*/
public synchronized ActionListener[] getActionListeners() {
return getListeners(ActionListener.class);
}
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this {@code Button}.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the {@code listenerType} argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* {@code Button b}
* for its action listeners with the following code:
*
* <pre>ActionListener[] als = (ActionListener[])(b.getListeners(ActionListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* {@code java.util.EventListener}
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this button,
* or an empty array if no such
* listeners have been added
* @exception ClassCastException if {@code listenerType}
* doesn't specify a class or interface that implements
* {@code java.util.EventListener}
*
* @see #getActionListeners
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ActionListener.class) {
l = actionListener;
} else {
return super.getListeners(listenerType);
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
if (e.id == ActionEvent.ACTION_PERFORMED) {
if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
actionListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
/**
* Processes events on this button. If an event is
* an instance of {@code ActionEvent}, this method invokes
* the {@code processActionEvent} method. Otherwise,
* it invokes {@code processEvent} on the superclass.
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
* @see java.awt.event.ActionEvent
* @see java.awt.Button#processActionEvent
* @since 1.1
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ActionEvent) {
processActionEvent((ActionEvent)e);
return;
}
super.processEvent(e);
}
/**
* Processes action events occurring on this button
* by dispatching them to any registered
* {@code ActionListener} objects.
* <p>
* This method is not called unless action events are
* enabled for this button. Action events are enabled
* when one of the following occurs:
* <ul>
* <li>An {@code ActionListener} object is registered
* via {@code addActionListener}.
* <li>Action events are enabled via {@code enableEvents}.
* </ul>
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the action event
* @see java.awt.event.ActionListener
* @see java.awt.Button#addActionListener
* @see java.awt.Component#enableEvents
* @since 1.1
*/
protected void processActionEvent(ActionEvent e) {
ActionListener listener = actionListener;
if (listener != null) {
listener.actionPerformed(e);
}
}
/**
* Returns a string representing the state of this {@code Button}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this button
*/
protected String paramString() {
return super.paramString() + ",label=" + label;
}
/* Serialization support.
*/
/*
* Button Serial Data Version.
* @serial
*/
private int buttonSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable {@code ActionListeners}
* as optional data. The non-serializable
* {@code ActionListeners} are detected and
* no attempt is made to serialize them.
*
* @serialData {@code null} terminated sequence of 0 or
* more pairs: the pair consists of a {@code String}
* and an {@code Object}; the {@code String}
* indicates the type of object and is one of the following:
* {@code actionListenerK} indicating an
* {@code ActionListener} object
*
* @param s the {@code ObjectOutputStream} to write
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see java.awt.Component#actionListenerK
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
AWTEventMulticaster.save(s, actionListenerK, actionListener);
s.writeObject(null);
}
/**
* Reads the {@code ObjectInputStream} and if
* it isn't {@code null} adds a listener to
* receive action events fired by the button.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @serial
* @see #removeActionListener(ActionListener)
* @see #addActionListener(ActionListener)
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException
{
GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (actionListenerK == key)
addActionListener((ActionListener)(s.readObject()));
else // skip value for unrecognized key
s.readObject();
}
}
/////////////////
// Accessibility support
////////////////
/**
* Gets the {@code AccessibleContext} associated with
* this {@code Button}. For buttons, the
* {@code AccessibleContext} takes the form of an
* {@code AccessibleAWTButton}.
* A new {@code AccessibleAWTButton} instance is
* created if necessary.
*
* @return an {@code AccessibleAWTButton} that serves as the
* {@code AccessibleContext} of this {@code Button}
* @since 1.3
*/
@BeanProperty(expert = true, description
= "The AccessibleContext associated with this Button.")
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTButton();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Button} class. It provides an implementation of the
* Java Accessibility API appropriate to button user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTButton extends AccessibleAWTComponent
implements AccessibleAction, AccessibleValue
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -5932203980244017102L;
/**
* Get the accessible name of this object.
*
* @return the localized name of the object -- can be null if this
* object does not have a name
*/
public String getAccessibleName() {
if (accessibleName != null) {
return accessibleName;
} else {
if (getLabel() == null) {
return super.getAccessibleName();
} else {
return getLabel();
}
}
}
/**
* Get the AccessibleAction associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleAction interface on behalf of itself.
*
* @return this object
*/
public AccessibleAction getAccessibleAction() {
return this;
}
/**
* Get the AccessibleValue associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleValue interface on behalf of itself.
*
* @return this object
*/
public AccessibleValue getAccessibleValue() {
return this;
}
/**
* Returns the number of Actions available in this object. The
* default behavior of a button is to have one action - toggle
* the button.
*
* @return 1, the number of Actions in this object
*/
public int getAccessibleActionCount() {
return 1;
}
/**
* Return a description of the specified action of the object.
*
* @param i zero-based index of the actions
*/
public String getAccessibleActionDescription(int i) {
if (i == 0) {
// [[[PENDING: WDW -- need to provide a localized string]]]
return "click";
} else {
return null;
}
}
/**
* Perform the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; else false.
*/
public boolean doAccessibleAction(int i) {
if (i == 0) {
// Simulate a button click
Toolkit.getEventQueue().postEvent(
new ActionEvent(Button.this,
ActionEvent.ACTION_PERFORMED,
Button.this.getActionCommand()));
return true;
} else {
return false;
}
}
/**
* Get the value of this object as a Number.
*
* @return An Integer of 0 if this isn't selected or an Integer of 1 if
* this is selected.
* @see javax.swing.AbstractButton#isSelected()
*/
public Number getCurrentAccessibleValue() {
return Integer.valueOf(0);
}
/**
* Set the value of this object as a Number.
*
* @return True if the value was set.
*/
public boolean setCurrentAccessibleValue(Number n) {
return false;
}
/**
* Get the minimum value of this object as a Number.
*
* @return An Integer of 0.
*/
public Number getMinimumAccessibleValue() {
return Integer.valueOf(0);
}
/**
* Get the maximum value of this object as a Number.
*
* @return An Integer of 0.
*/
public Number getMaximumAccessibleValue() {
return Integer.valueOf(0);
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.PUSH_BUTTON;
}
} // inner class AccessibleAWTButton
}

View file

@ -0,0 +1,255 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.BufferStrategy;
import java.awt.peer.CanvasPeer;
import javax.accessibility.*;
/**
* A {@code Canvas} component represents a blank rectangular
* area of the screen onto which the application can draw or from
* which the application can trap input events from the user.
* <p>
* An application must subclass the {@code Canvas} class in
* order to get useful functionality such as creating a custom
* component. The {@code paint} method must be overridden
* in order to perform custom graphics on the canvas.
*
* @author Sami Shaio
* @since 1.0
*/
public class Canvas extends Component implements Accessible {
private static final String base = "canvas";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -2284879212465893870L;
/**
* Constructs a new Canvas.
*/
public Canvas() {
}
/**
* Constructs a new Canvas given a GraphicsConfiguration object. If null is
* passed, then the default GraphicsConfiguration will be used.
*
* @param config a reference to a GraphicsConfiguration object or null
*
* @see GraphicsConfiguration
* @see Component#getGraphicsConfiguration()
*/
public Canvas(GraphicsConfiguration config) {
this();
setGraphicsConfiguration(config);
}
@Override
void setGraphicsConfiguration(GraphicsConfiguration gc) {
synchronized(getTreeLock()) {
CanvasPeer peer = (CanvasPeer) this.peer;
if (peer != null) {
gc = peer.getAppropriateGraphicsConfiguration(gc);
}
super.setGraphicsConfiguration(gc);
}
}
/**
* Construct a name for this component. Called by getName() when the
* name is null.
*/
String constructComponentName() {
synchronized (Canvas.class) {
return base + nameCounter++;
}
}
/**
* Creates the peer of the canvas. This peer allows you to change the
* user interface of the canvas without changing its functionality.
* @see java.awt.Component#getToolkit()
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createCanvas(this);
super.addNotify();
}
}
/**
* Paints this canvas.
* <p>
* Most applications that subclass {@code Canvas} should
* override this method in order to perform some useful operation
* (typically, custom painting of the canvas).
* The default operation is simply to clear the canvas.
* Applications that override this method need not call
* super.paint(g).
*
* @param g the specified Graphics context
* @see #update(Graphics)
* @see Component#paint(Graphics)
*/
public void paint(Graphics g) {
g.clearRect(0, 0, width, height);
}
/**
* Updates this canvas.
* <p>
* This method is called in response to a call to {@code repaint}.
* The canvas is first cleared by filling it with the background
* color, and then completely redrawn by calling this canvas's
* {@code paint} method.
* Note: applications that override this method should either call
* super.update(g) or incorporate the functionality described
* above into their own code.
*
* @param g the specified Graphics context
* @see #paint(Graphics)
* @see Component#update(Graphics)
*/
public void update(Graphics g) {
g.clearRect(0, 0, width, height);
paint(g);
}
boolean postsOldMouseEvents() {
return true;
}
/**
* Creates a new strategy for multi-buffering on this component.
* Multi-buffering is useful for rendering performance. This method
* attempts to create the best strategy available with the number of
* buffers supplied. It will always create a {@code BufferStrategy}
* with that number of buffers.
* A page-flipping strategy is attempted first, then a blitting strategy
* using accelerated buffers. Finally, an unaccelerated blitting
* strategy is used.
* <p>
* Each time this method is called,
* the existing buffer strategy for this component is discarded.
* @param numBuffers number of buffers to create, including the front buffer
* @exception IllegalArgumentException if numBuffers is less than 1.
* @exception IllegalStateException if the component is not displayable
* @see #isDisplayable
* @see #getBufferStrategy
* @since 1.4
*/
public void createBufferStrategy(int numBuffers) {
super.createBufferStrategy(numBuffers);
}
/**
* Creates a new strategy for multi-buffering on this component with the
* required buffer capabilities. This is useful, for example, if only
* accelerated memory or page flipping is desired (as specified by the
* buffer capabilities).
* <p>
* Each time this method
* is called, the existing buffer strategy for this component is discarded.
* @param numBuffers number of buffers to create
* @param caps the required capabilities for creating the buffer strategy;
* cannot be {@code null}
* @exception AWTException if the capabilities supplied could not be
* supported or met; this may happen, for example, if there is not enough
* accelerated memory currently available, or if page flipping is specified
* but not possible.
* @exception IllegalArgumentException if numBuffers is less than 1, or if
* caps is {@code null}
* @see #getBufferStrategy
* @since 1.4
*/
public void createBufferStrategy(int numBuffers,
BufferCapabilities caps) throws AWTException {
super.createBufferStrategy(numBuffers, caps);
}
/**
* Returns the {@code BufferStrategy} used by this component. This
* method will return null if a {@code BufferStrategy} has not yet
* been created or has been disposed.
*
* @return the buffer strategy used by this component
* @see #createBufferStrategy
* @since 1.4
*/
public BufferStrategy getBufferStrategy() {
return super.getBufferStrategy();
}
/*
* --- Accessibility Support ---
*
*/
/**
* Gets the AccessibleContext associated with this Canvas.
* For canvases, the AccessibleContext takes the form of an
* AccessibleAWTCanvas.
* A new AccessibleAWTCanvas instance is created if necessary.
*
* @return an AccessibleAWTCanvas that serves as the
* AccessibleContext of this Canvas
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTCanvas();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Canvas} class. It provides an implementation of the
* Java Accessibility API appropriate to canvas user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTCanvas extends AccessibleAWTComponent
{
private static final long serialVersionUID = -6325592262103146699L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.CANVAS;
}
} // inner class AccessibleAWTCanvas
}

View file

@ -0,0 +1,613 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.IOException;
/**
* A {@code CardLayout} object is a layout manager for a
* container. It treats each component in the container as a card.
* Only one card is visible at a time, and the container acts as
* a stack of cards. The first component added to a
* {@code CardLayout} object is the visible component when the
* container is first displayed.
* <p>
* The ordering of cards is determined by the container's own internal
* ordering of its component objects. {@code CardLayout}
* defines a set of methods that allow an application to flip
* through these cards sequentially, or to show a specified card.
* The {@link CardLayout#addLayoutComponent}
* method can be used to associate a string identifier with a given card
* for fast random access.
*
* @author Arthur van Hoff
* @see java.awt.Container
* @since 1.0
*/
public class CardLayout implements LayoutManager2,
Serializable {
private static final long serialVersionUID = -4328196481005934313L;
/*
* This creates a Vector to store associated
* pairs of components and their names.
* @see java.util.Vector
*/
Vector<Card> vector = new Vector<>();
/*
* A pair of Component and String that represents its name.
*/
class Card implements Serializable {
static final long serialVersionUID = 6640330810709497518L;
public String name;
public Component comp;
public Card(String cardName, Component cardComponent) {
name = cardName;
comp = cardComponent;
}
}
/*
* Index of Component currently displayed by CardLayout.
*/
int currentCard = 0;
/*
* A cards horizontal Layout gap (inset). It specifies
* the space between the left and right edges of a
* container and the current component.
* This should be a non negative Integer.
* @see getHgap()
* @see setHgap()
*/
int hgap;
/*
* A cards vertical Layout gap (inset). It specifies
* the space between the top and bottom edges of a
* container and the current component.
* This should be a non negative Integer.
* @see getVgap()
* @see setVgap()
*/
int vgap;
/**
* @serialField tab Hashtable
* deprecated, for forward compatibility only
* @serialField hgap int
* @serialField vgap int
* @serialField vector Vector
* @serialField currentCard int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("tab", Hashtable.class),
new ObjectStreamField("hgap", Integer.TYPE),
new ObjectStreamField("vgap", Integer.TYPE),
new ObjectStreamField("vector", Vector.class),
new ObjectStreamField("currentCard", Integer.TYPE)
};
/**
* Creates a new card layout with gaps of size zero.
*/
public CardLayout() {
this(0, 0);
}
/**
* Creates a new card layout with the specified horizontal and
* vertical gaps. The horizontal gaps are placed at the left and
* right edges. The vertical gaps are placed at the top and bottom
* edges.
* @param hgap the horizontal gap.
* @param vgap the vertical gap.
*/
public CardLayout(int hgap, int vgap) {
this.hgap = hgap;
this.vgap = vgap;
}
/**
* Gets the horizontal gap between components.
* @return the horizontal gap between components.
* @see java.awt.CardLayout#setHgap(int)
* @see java.awt.CardLayout#getVgap()
* @since 1.1
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between components.
* @param hgap the horizontal gap between components.
* @see java.awt.CardLayout#getHgap()
* @see java.awt.CardLayout#setVgap(int)
* @since 1.1
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Gets the vertical gap between components.
* @return the vertical gap between components.
* @see java.awt.CardLayout#setVgap(int)
* @see java.awt.CardLayout#getHgap()
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components.
* @param vgap the vertical gap between components.
* @see java.awt.CardLayout#getVgap()
* @see java.awt.CardLayout#setHgap(int)
* @since 1.1
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Adds the specified component to this card layout's internal
* table of names. The object specified by {@code constraints}
* must be a string. The card layout stores this string as a key-value
* pair that can be used for random access to a particular card.
* By calling the {@code show} method, an application can
* display the component with the specified name.
* @param comp the component to be added.
* @param constraints a tag that identifies a particular
* card in the layout.
* @see java.awt.CardLayout#show(java.awt.Container, java.lang.String)
* @exception IllegalArgumentException if the constraint is not a string.
*/
public void addLayoutComponent(Component comp, Object constraints) {
synchronized (comp.getTreeLock()) {
if (constraints == null){
constraints = "";
}
if (constraints instanceof String) {
addLayoutComponent((String)constraints, comp);
} else {
throw new IllegalArgumentException("cannot add to layout: constraint must be a string");
}
}
}
/**
* @deprecated replaced by
* {@code addLayoutComponent(Component, Object)}.
*/
@Deprecated
public void addLayoutComponent(String name, Component comp) {
synchronized (comp.getTreeLock()) {
if (!vector.isEmpty()) {
comp.setVisible(false);
}
for (int i=0; i < vector.size(); i++) {
if ((vector.get(i)).name.equals(name)) {
(vector.get(i)).comp = comp;
return;
}
}
vector.add(new Card(name, comp));
}
}
/**
* Removes the specified component from the layout.
* If the card was visible on top, the next card underneath it is shown.
* @param comp the component to be removed.
* @see java.awt.Container#remove(java.awt.Component)
* @see java.awt.Container#removeAll()
*/
public void removeLayoutComponent(Component comp) {
synchronized (comp.getTreeLock()) {
for (int i = 0; i < vector.size(); i++) {
if ((vector.get(i)).comp == comp) {
// if we remove current component we should show next one
if (comp.isVisible() && (comp.getParent() != null)) {
next(comp.getParent());
}
vector.remove(i);
// correct currentCard if this is necessary
if (currentCard > i) {
currentCard--;
}
break;
}
}
}
}
/**
* Determines the preferred size of the container argument using
* this card layout.
* @param parent the parent container in which to do the layout
* @return the preferred dimensions to lay out the subcomponents
* of the specified container
* @see java.awt.Container#getPreferredSize
* @see java.awt.CardLayout#minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int w = 0;
int h = 0;
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
if (d.width > w) {
w = d.width;
}
if (d.height > h) {
h = d.height;
}
}
return new Dimension(insets.left + insets.right + w + hgap*2,
insets.top + insets.bottom + h + vgap*2);
}
}
/**
* Calculates the minimum size for the specified panel.
* @param parent the parent container in which to do the layout
* @return the minimum dimensions required to lay out the
* subcomponents of the specified container
* @see java.awt.Container#doLayout
* @see java.awt.CardLayout#preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int w = 0;
int h = 0;
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
Dimension d = comp.getMinimumSize();
if (d.width > w) {
w = d.width;
}
if (d.height > h) {
h = d.height;
}
}
return new Dimension(insets.left + insets.right + w + hgap*2,
insets.top + insets.bottom + h + vgap*2);
}
}
/**
* Returns the maximum dimensions for this layout given the components
* in the specified target container.
* @param target the component which needs to be laid out
* @see Container
* @see #minimumLayoutSize
* @see #preferredLayoutSize
*/
public Dimension maximumLayoutSize(Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentX(Container parent) {
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentY(Container parent) {
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
/**
* Lays out the specified container using this card layout.
* <p>
* Each component in the {@code parent} container is reshaped
* to be the size of the container, minus space for surrounding
* insets, horizontal gaps, and vertical gaps.
*
* @param parent the parent container in which to do the layout
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
Component comp = null;
boolean currentFound = false;
for (int i = 0 ; i < ncomponents ; i++) {
comp = parent.getComponent(i);
comp.setBounds(hgap + insets.left, vgap + insets.top,
parent.width - (hgap*2 + insets.left + insets.right),
parent.height - (vgap*2 + insets.top + insets.bottom));
if (comp.isVisible()) {
currentFound = true;
}
}
if (!currentFound && ncomponents > 0) {
parent.getComponent(0).setVisible(true);
}
}
}
/**
* Make sure that the Container really has a CardLayout installed.
* Otherwise havoc can ensue!
*/
void checkLayout(Container parent) {
if (parent.getLayout() != this) {
throw new IllegalArgumentException("wrong parent for CardLayout");
}
}
/**
* Flips to the first card of the container.
* @param parent the parent container in which to do the layout
* @see java.awt.CardLayout#last
*/
public void first(Container parent) {
synchronized (parent.getTreeLock()) {
checkLayout(parent);
int ncomponents = parent.getComponentCount();
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
if (comp.isVisible()) {
comp.setVisible(false);
break;
}
}
if (ncomponents > 0) {
currentCard = 0;
parent.getComponent(0).setVisible(true);
parent.validate();
}
}
}
/**
* Flips to the next card of the specified container. If the
* currently visible card is the last one, this method flips to the
* first card in the layout.
* @param parent the parent container in which to do the layout
* @see java.awt.CardLayout#previous
*/
public void next(Container parent) {
synchronized (parent.getTreeLock()) {
checkLayout(parent);
int ncomponents = parent.getComponentCount();
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
if (comp.isVisible()) {
comp.setVisible(false);
currentCard = (i + 1) % ncomponents;
comp = parent.getComponent(currentCard);
comp.setVisible(true);
parent.validate();
return;
}
}
showDefaultComponent(parent);
}
}
/**
* Flips to the previous card of the specified container. If the
* currently visible card is the first one, this method flips to the
* last card in the layout.
* @param parent the parent container in which to do the layout
* @see java.awt.CardLayout#next
*/
public void previous(Container parent) {
synchronized (parent.getTreeLock()) {
checkLayout(parent);
int ncomponents = parent.getComponentCount();
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
if (comp.isVisible()) {
comp.setVisible(false);
currentCard = ((i > 0) ? i-1 : ncomponents-1);
comp = parent.getComponent(currentCard);
comp.setVisible(true);
parent.validate();
return;
}
}
showDefaultComponent(parent);
}
}
void showDefaultComponent(Container parent) {
if (parent.getComponentCount() > 0) {
currentCard = 0;
parent.getComponent(0).setVisible(true);
parent.validate();
}
}
/**
* Flips to the last card of the container.
* @param parent the parent container in which to do the layout
* @see java.awt.CardLayout#first
*/
public void last(Container parent) {
synchronized (parent.getTreeLock()) {
checkLayout(parent);
int ncomponents = parent.getComponentCount();
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
if (comp.isVisible()) {
comp.setVisible(false);
break;
}
}
if (ncomponents > 0) {
currentCard = ncomponents - 1;
parent.getComponent(currentCard).setVisible(true);
parent.validate();
}
}
}
/**
* Flips to the component that was added to this layout with the
* specified {@code name}, using {@code addLayoutComponent}.
* If no such component exists, then nothing happens.
* @param parent the parent container in which to do the layout
* @param name the component name
* @see java.awt.CardLayout#addLayoutComponent(java.awt.Component, java.lang.Object)
*/
public void show(Container parent, String name) {
synchronized (parent.getTreeLock()) {
checkLayout(parent);
Component next = null;
int ncomponents = vector.size();
for (int i = 0; i < ncomponents; i++) {
Card card = vector.get(i);
if (card.name.equals(name)) {
next = card.comp;
currentCard = i;
break;
}
}
if ((next != null) && !next.isVisible()) {
ncomponents = parent.getComponentCount();
for (int i = 0; i < ncomponents; i++) {
Component comp = parent.getComponent(i);
if (comp.isVisible()) {
comp.setVisible(false);
break;
}
}
next.setVisible(true);
parent.validate();
}
}
}
/**
* Returns a string representation of the state of this card layout.
* @return a string representation of this card layout.
*/
public String toString() {
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
}
/**
* Reads serializable fields from stream.
*/
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
ObjectInputStream.GetField f = s.readFields();
hgap = f.get("hgap", 0);
vgap = f.get("vgap", 0);
if (f.defaulted("vector")) {
// pre-1.4 stream
Hashtable<String, Component> tab = (Hashtable)f.get("tab", null);
vector = new Vector<>();
if (tab != null && !tab.isEmpty()) {
for (Enumeration<String> e = tab.keys() ; e.hasMoreElements() ; ) {
String key = e.nextElement();
Component comp = tab.get(key);
vector.add(new Card(key, comp));
if (comp.isVisible()) {
currentCard = vector.size() - 1;
}
}
}
} else {
vector = (Vector)f.get("vector", null);
currentCard = f.get("currentCard", 0);
}
}
/**
* Writes serializable fields to stream.
*/
private void writeObject(ObjectOutputStream s)
throws IOException
{
Hashtable<String, Component> tab = new Hashtable<>();
int ncomponents = vector.size();
for (int i = 0; i < ncomponents; i++) {
Card card = vector.get(i);
tab.put(card.name, card.comp);
}
ObjectOutputStream.PutField f = s.putFields();
f.put("hgap", hgap);
f.put("vgap", vgap);
f.put("vector", vector);
f.put("currentCard", currentCard);
f.put("tab", tab);
s.writeFields();
}
}

View file

@ -0,0 +1,868 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.CheckboxPeer;
import java.awt.event.*;
import java.util.EventListener;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
/**
* A check box is a graphical component that can be in either an
* "on" ({@code true}) or "off" ({@code false}) state.
* Clicking on a check box changes its state from
* "on" to "off," or from "off" to "on."
* <p>
* The following code example creates a set of check boxes in
* a grid layout:
*
* <hr><blockquote><pre>
* setLayout(new GridLayout(3, 1));
* add(new Checkbox("one", null, true));
* add(new Checkbox("two"));
* add(new Checkbox("three"));
* </pre></blockquote><hr>
* <p>
* This image depicts the check boxes and grid layout
* created by this code example:
* <p>
* <img src="doc-files/Checkbox-1.gif" alt="The following context describes the graphic."
* style="float:center; margin: 7px 10px;">
* <p>
* The button labeled {@code one} is in the "on" state, and the
* other two are in the "off" state. In this example, which uses the
* {@code GridLayout} class, the states of the three check
* boxes are set independently.
* <p>
* Alternatively, several check boxes can be grouped together under
* the control of a single object, using the
* {@code CheckboxGroup} class.
* In a check box group, at most one button can be in the "on"
* state at any given time. Clicking on a check box to turn it on
* forces any other check box in the same group that is on
* into the "off" state.
*
* @author Sami Shaio
* @see java.awt.GridLayout
* @see java.awt.CheckboxGroup
* @since 1.0
*/
public class Checkbox extends Component implements ItemSelectable, Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* The label of the Checkbox.
* This field can be null.
* @serial
* @see #getLabel()
* @see #setLabel(String)
*/
String label;
/**
* The state of the {@code Checkbox}.
* @serial
* @see #getState()
* @see #setState(boolean)
*/
boolean state;
/**
* The check box group.
* This field can be null indicating that the checkbox
* is not a group checkbox.
* @serial
* @see #getCheckboxGroup()
* @see #setCheckboxGroup(CheckboxGroup)
*/
CheckboxGroup group;
transient ItemListener itemListener;
private static final String base = "checkbox";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 7270714317450821763L;
/**
* Helper function for setState and CheckboxGroup.setSelectedCheckbox
* Should remain package-private.
*/
void setStateInternal(boolean state) {
this.state = state;
CheckboxPeer peer = (CheckboxPeer)this.peer;
if (peer != null) {
peer.setState(state);
}
}
/**
* Creates a check box with an empty string for its label.
* The state of this check box is set to "off," and it is not
* part of any check box group.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Checkbox() throws HeadlessException {
this("", false, null);
}
/**
* Creates a check box with the specified label. The state
* of this check box is set to "off," and it is not part of
* any check box group.
*
* @param label a string label for this check box,
* or {@code null} for no label.
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Checkbox(String label) throws HeadlessException {
this(label, false, null);
}
/**
* Creates a check box with the specified label
* and sets the specified state.
* This check box is not part of any check box group.
*
* @param label a string label for this check box,
* or {@code null} for no label
* @param state the initial state of this check box
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Checkbox(String label, boolean state) throws HeadlessException {
this(label, state, null);
}
/**
* Constructs a Checkbox with the specified label, set to the
* specified state, and in the specified check box group.
*
* @param label a string label for this check box,
* or {@code null} for no label.
* @param state the initial state of this check box.
* @param group a check box group for this check box,
* or {@code null} for no group.
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public Checkbox(String label, boolean state, CheckboxGroup group)
throws HeadlessException {
GraphicsEnvironment.checkHeadless();
this.label = label;
this.state = state;
this.group = group;
if (state && (group != null)) {
group.setSelectedCheckbox(this);
}
}
/**
* Creates a check box with the specified label, in the specified
* check box group, and set to the specified state.
*
* @param label a string label for this check box,
* or {@code null} for no label.
* @param group a check box group for this check box,
* or {@code null} for no group.
* @param state the initial state of this check box.
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public Checkbox(String label, CheckboxGroup group, boolean state)
throws HeadlessException {
this(label, state, group);
}
/**
* Constructs a name for this component. Called by
* {@code getName} when the name is {@code null}.
*
* @return a name for this component
*/
String constructComponentName() {
synchronized (Checkbox.class) {
return base + nameCounter++;
}
}
/**
* Creates the peer of the Checkbox. The peer allows you to change the
* look of the Checkbox without changing its functionality.
*
* @see java.awt.Component#getToolkit()
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createCheckbox(this);
super.addNotify();
}
}
/**
* Gets the label of this check box.
*
* @return the label of this check box, or {@code null}
* if this check box has no label.
* @see #setLabel(String)
*/
public String getLabel() {
return label;
}
/**
* Sets this check box's label to be the string argument.
*
* @param label a string to set as the new label, or
* {@code null} for no label.
* @see #getLabel
*/
public void setLabel(String label) {
boolean testvalid = false;
synchronized (this) {
if (label != this.label && (this.label == null ||
!this.label.equals(label))) {
this.label = label;
CheckboxPeer peer = (CheckboxPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
testvalid = true;
}
}
// This could change the preferred size of the Component.
if (testvalid) {
invalidateIfValid();
}
}
/**
* Determines whether this check box is in the "on" or "off" state.
* The boolean value {@code true} indicates the "on" state,
* and {@code false} indicates the "off" state.
*
* @return the state of this check box, as a boolean value
* @see #setState
*/
public boolean getState() {
return state;
}
/**
* Sets the state of this check box to the specified state.
* The boolean value {@code true} indicates the "on" state,
* and {@code false} indicates the "off" state.
*
* <p>Note that this method should be primarily used to
* initialize the state of the checkbox. Programmatically
* setting the state of the checkbox will <i>not</i> trigger
* an {@code ItemEvent}. The only way to trigger an
* {@code ItemEvent} is by user interaction.
*
* @param state the boolean state of the check box
* @see #getState
*/
public void setState(boolean state) {
/* Cannot hold check box lock when calling group.setSelectedCheckbox. */
CheckboxGroup group = this.group;
if (group != null) {
if (state) {
group.setSelectedCheckbox(this);
} else if (group.getSelectedCheckbox() == this) {
state = true;
}
}
setStateInternal(state);
}
/**
* Returns an array (length 1) containing the checkbox
* label or null if the checkbox is not selected.
* @see ItemSelectable
*/
public Object[] getSelectedObjects() {
if (state) {
Object[] items = new Object[1];
items[0] = label;
return items;
}
return null;
}
/**
* Determines this check box's group.
* @return this check box's group, or {@code null}
* if the check box is not part of a check box group.
* @see #setCheckboxGroup(CheckboxGroup)
*/
public CheckboxGroup getCheckboxGroup() {
return group;
}
/**
* Sets this check box's group to the specified check box group.
* If this check box is already in a different check box group,
* it is first taken out of that group.
* <p>
* If the state of this check box is {@code true} and the new
* group already has a check box selected, this check box's state
* is changed to {@code false}. If the state of this check
* box is {@code true} and the new group has no check box
* selected, this check box becomes the selected checkbox for
* the new group and its state is {@code true}.
*
* @param g the new check box group, or {@code null}
* to remove this check box from any check box group
* @see #getCheckboxGroup
*/
public void setCheckboxGroup(CheckboxGroup g) {
CheckboxGroup oldGroup;
boolean oldState;
/* Do nothing if this check box has already belonged
* to the check box group g.
*/
if (this.group == g) {
return;
}
synchronized (this) {
oldGroup = this.group;
oldState = getState();
this.group = g;
CheckboxPeer peer = (CheckboxPeer)this.peer;
if (peer != null) {
peer.setCheckboxGroup(g);
}
if (this.group != null && getState()) {
if (this.group.getSelectedCheckbox() != null) {
setState(false);
} else {
this.group.setSelectedCheckbox(this);
}
}
}
/* Locking check box below could cause deadlock with
* CheckboxGroup's setSelectedCheckbox method.
*
* Fix for 4726853 by kdm@sparc.spb.su
* Here we should check if this check box was selected
* in the previous group and set selected check box to
* null for that group if so.
*/
if (oldGroup != null && oldState) {
oldGroup.setSelectedCheckbox(null);
}
}
/**
* Adds the specified item listener to receive item events from
* this check box. Item events are sent to listeners in response
* to user input, but not in response to calls to setState().
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the item listener
* @see #removeItemListener
* @see #getItemListeners
* @see #setState
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void addItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.add(itemListener, l);
newEventsOnly = true;
}
/**
* Removes the specified item listener so that the item listener
* no longer receives item events from this check box.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the item listener
* @see #addItemListener
* @see #getItemListeners
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void removeItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.remove(itemListener, l);
}
/**
* Returns an array of all the item listeners
* registered on this checkbox.
*
* @return all of this checkbox's {@code ItemListener}s
* or an empty array if no item
* listeners are currently registered
*
* @see #addItemListener
* @see #removeItemListener
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.4
*/
public synchronized ItemListener[] getItemListeners() {
return getListeners(ItemListener.class);
}
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this {@code Checkbox}.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the {@code listenerType} argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* {@code Checkbox c}
* for its item listeners with the following code:
*
* <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* {@code java.util.EventListener}
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this checkbox,
* or an empty array if no such
* listeners have been added
* @exception ClassCastException if {@code listenerType}
* doesn't specify a class or interface that implements
* {@code java.util.EventListener}
*
* @see #getItemListeners
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ItemListener.class) {
l = itemListener;
} else {
return super.getListeners(listenerType);
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
itemListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
/**
* Processes events on this check box.
* If the event is an instance of {@code ItemEvent},
* this method invokes the {@code processItemEvent} method.
* Otherwise, it calls its superclass's {@code processEvent} method.
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
* @see java.awt.event.ItemEvent
* @see #processItemEvent
* @since 1.1
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ItemEvent) {
processItemEvent((ItemEvent)e);
return;
}
super.processEvent(e);
}
/**
* Processes item events occurring on this check box by
* dispatching them to any registered
* {@code ItemListener} objects.
* <p>
* This method is not called unless item events are
* enabled for this component. Item events are enabled
* when one of the following occurs:
* <ul>
* <li>An {@code ItemListener} object is registered
* via {@code addItemListener}.
* <li>Item events are enabled via {@code enableEvents}.
* </ul>
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the item event
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @see #addItemListener
* @see java.awt.Component#enableEvents
* @since 1.1
*/
protected void processItemEvent(ItemEvent e) {
ItemListener listener = itemListener;
if (listener != null) {
listener.itemStateChanged(e);
}
}
/**
* Returns a string representing the state of this {@code Checkbox}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this check box
*/
protected String paramString() {
String str = super.paramString();
String label = this.label;
if (label != null) {
str += ",label=" + label;
}
return str + ",state=" + state;
}
/* Serialization support.
*/
/*
* Serialized data version
* @serial
*/
private int checkboxSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable {@code ItemListeners}
* as optional data. The non-serializable
* {@code ItemListeners} are detected and
* no attempt is made to serialize them.
*
* @param s the {@code ObjectOutputStream} to write
* @serialData {@code null} terminated sequence of 0
* or more pairs; the pair consists of a {@code String}
* and an {@code Object}; the {@code String} indicates
* the type of object and is one of the following:
* {@code itemListenerK} indicating an
* {@code ItemListener} object
*
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see java.awt.Component#itemListenerK
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s)
throws java.io.IOException
{
s.defaultWriteObject();
AWTEventMulticaster.save(s, itemListenerK, itemListener);
s.writeObject(null);
}
/**
* Reads the {@code ObjectInputStream} and if it
* isn't {@code null} adds a listener to receive
* item events fired by the {@code Checkbox}.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @serial
* @see #removeItemListener(ItemListener)
* @see #addItemListener(ItemListener)
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException
{
GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (itemListenerK == key)
addItemListener((ItemListener)(s.readObject()));
else // skip value for unrecognized key
s.readObject();
}
}
/**
* Initialize JNI field and method ids
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this Checkbox.
* For checkboxes, the AccessibleContext takes the form of an
* AccessibleAWTCheckbox.
* A new AccessibleAWTCheckbox is created if necessary.
*
* @return an AccessibleAWTCheckbox that serves as the
* AccessibleContext of this Checkbox
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTCheckbox();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Checkbox} class. It provides an implementation of the
* Java Accessibility API appropriate to checkbox user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTCheckbox extends AccessibleAWTComponent
implements ItemListener, AccessibleAction, AccessibleValue
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = 7881579233144754107L;
/**
* Constructor for {@code AccessibleAWTCheckbox}
*/
public AccessibleAWTCheckbox() {
super();
Checkbox.this.addItemListener(this);
}
/**
* Fire accessible property change events when the state of the
* toggle button changes.
*/
public void itemStateChanged(ItemEvent e) {
Checkbox cb = (Checkbox) e.getSource();
if (Checkbox.this.accessibleContext != null) {
if (cb.getState()) {
Checkbox.this.accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
null, AccessibleState.CHECKED);
} else {
Checkbox.this.accessibleContext.firePropertyChange(
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
AccessibleState.CHECKED, null);
}
}
}
/**
* Get the AccessibleAction associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleAction interface on behalf of itself.
*
* @return this object
*/
public AccessibleAction getAccessibleAction() {
return this;
}
/**
* Get the AccessibleValue associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleValue interface on behalf of itself.
*
* @return this object
*/
public AccessibleValue getAccessibleValue() {
return this;
}
/**
* Returns the number of Actions available in this object.
* If there is more than one, the first one is the "default"
* action.
*
* @return the number of Actions in this object
*/
public int getAccessibleActionCount() {
return 0; // To be fully implemented in a future release
}
/**
* Return a description of the specified action of the object.
*
* @param i zero-based index of the actions
*/
public String getAccessibleActionDescription(int i) {
return null; // To be fully implemented in a future release
}
/**
* Perform the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; else false.
*/
public boolean doAccessibleAction(int i) {
return false; // To be fully implemented in a future release
}
/**
* Get the value of this object as a Number. If the value has not been
* set, the return value will be null.
*
* @return value of the object
* @see #setCurrentAccessibleValue
*/
public Number getCurrentAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Set the value of this object as a Number.
*
* @return True if the value was set; else False
* @see #getCurrentAccessibleValue
*/
public boolean setCurrentAccessibleValue(Number n) {
return false; // To be fully implemented in a future release
}
/**
* Get the minimum value of this object as a Number.
*
* @return Minimum value of the object; null if this object does not
* have a minimum value
* @see #getMaximumAccessibleValue
*/
public Number getMinimumAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Get the maximum value of this object as a Number.
*
* @return Maximum value of the object; null if this object does not
* have a maximum value
* @see #getMinimumAccessibleValue
*/
public Number getMaximumAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of
* the object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.CHECK_BOX;
}
/**
* Get the state set of this object.
*
* @return an instance of AccessibleState containing the current state
* of the object
* @see AccessibleState
*/
public AccessibleStateSet getAccessibleStateSet() {
AccessibleStateSet states = super.getAccessibleStateSet();
if (getState()) {
states.add(AccessibleState.CHECKED);
}
return states;
}
} // inner class AccessibleAWTCheckbox
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* The {@code CheckboxGroup} class is used to group together
* a set of {@code Checkbox} buttons.
* <p>
* Exactly one check box button in a {@code CheckboxGroup} can
* be in the "on" state at any given time. Pushing any
* button sets its state to "on" and forces any other button that
* is in the "on" state into the "off" state.
* <p>
* The following code example produces a new check box group,
* with three check boxes:
*
* <hr><blockquote><pre>
* setLayout(new GridLayout(3, 1));
* CheckboxGroup cbg = new CheckboxGroup();
* add(new Checkbox("one", cbg, true));
* add(new Checkbox("two", cbg, false));
* add(new Checkbox("three", cbg, false));
* </pre></blockquote><hr>
* <p>
* This image depicts the check box group created by this example:
* <p>
* <img src="doc-files/CheckboxGroup-1.gif"
* alt="Shows three checkboxes, arranged vertically, labeled one, two, and three. Checkbox one is in the on state."
* style="float:center; margin: 7px 10px;">
*
* @author Sami Shaio
* @see java.awt.Checkbox
* @since 1.0
*/
public class CheckboxGroup implements java.io.Serializable {
/**
* The current choice.
* @serial
* @see #getCurrent()
* @see #setCurrent(Checkbox)
*/
Checkbox selectedCheckbox = null;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 3729780091441768983L;
/**
* Creates a new instance of {@code CheckboxGroup}.
*/
public CheckboxGroup() {
}
/**
* Gets the current choice from this check box group.
* The current choice is the check box in this
* group that is currently in the "on" state,
* or {@code null} if all check boxes in the
* group are off.
* @return the check box that is currently in the
* "on" state, or {@code null}.
* @see java.awt.Checkbox
* @see java.awt.CheckboxGroup#setSelectedCheckbox
* @since 1.1
*/
public Checkbox getSelectedCheckbox() {
return getCurrent();
}
/**
* Returns the current choice from this check box group
* or {@code null} if none of checkboxes are selected.
*
* @return the selected checkbox
* @deprecated As of JDK version 1.1,
* replaced by {@code getSelectedCheckbox()}.
*/
@Deprecated
public Checkbox getCurrent() {
return selectedCheckbox;
}
/**
* Sets the currently selected check box in this group
* to be the specified check box.
* This method sets the state of that check box to "on" and
* sets all other check boxes in the group to be off.
* <p>
* If the check box argument is {@code null}, all check boxes
* in this check box group are deselected. If the check box argument
* belongs to a different check box group, this method does
* nothing.
* @param box the {@code Checkbox} to set as the
* current selection.
* @see java.awt.Checkbox
* @see java.awt.CheckboxGroup#getSelectedCheckbox
* @since 1.1
*/
public void setSelectedCheckbox(Checkbox box) {
setCurrent(box);
}
/**
* Sets the currently selected check box in this group
* to be the specified check box and unsets all others.
*
* @param box the {@code Checkbox} to set as the
* current selection.
* @deprecated As of JDK version 1.1,
* replaced by {@code setSelectedCheckbox(Checkbox)}.
*/
@Deprecated
public synchronized void setCurrent(Checkbox box) {
if (box != null && box.group != this) {
return;
}
Checkbox oldChoice = this.selectedCheckbox;
this.selectedCheckbox = box;
if (oldChoice != null && oldChoice != box && oldChoice.group == this) {
oldChoice.setState(false);
}
if (box != null && oldChoice != box && !box.getState()) {
box.setStateInternal(true);
}
}
/**
* Returns a string representation of this check box group,
* including the value of its current selection.
* @return a string representation of this check box group.
*/
public String toString() {
return getClass().getName() + "[selectedCheckbox=" + selectedCheckbox + "]";
}
}

View file

@ -0,0 +1,648 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.peer.CheckboxMenuItemPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EventListener;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleValue;
import sun.awt.AWTAccessor;
/**
* This class represents a check box that can be included in a menu.
* Selecting the check box in the menu changes its state from
* "on" to "off" or from "off" to "on."
* <p>
* The following picture depicts a menu which contains an instance
* of {@code CheckBoxMenuItem}:
* <p>
* <img src="doc-files/MenuBar-1.gif"
* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More
* Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
* style="float:center; margin: 7px 10px;">
* <p>
* The item labeled {@code Check} shows a check box menu item
* in its "off" state.
* <p>
* When a check box menu item is selected, AWT sends an item event to
* the item. Since the event is an instance of {@code ItemEvent},
* the {@code processEvent} method examines the event and passes
* it along to {@code processItemEvent}. The latter method redirects
* the event to any {@code ItemListener} objects that have
* registered an interest in item events generated by this menu item.
*
* @author Sami Shaio
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.0
*/
public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setCheckboxMenuItemAccessor(
new AWTAccessor.CheckboxMenuItemAccessor() {
public boolean getState(CheckboxMenuItem cmi) {
return cmi.state;
}
});
}
/**
* The state of a checkbox menu item
* @serial
* @see #getState()
* @see #setState(boolean)
*/
private volatile boolean state;
private transient volatile ItemListener itemListener;
private static final String base = "chkmenuitem";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 6190621106981774043L;
/**
* Create a check box menu item with an empty label.
* The item's state is initially set to "off."
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public CheckboxMenuItem() throws HeadlessException {
this("", false);
}
/**
* Create a check box menu item with the specified label.
* The item's state is initially set to "off."
* @param label a string label for the check box menu item,
* or {@code null} for an unlabeled menu item.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public CheckboxMenuItem(String label) throws HeadlessException {
this(label, false);
}
/**
* Create a check box menu item with the specified label and state.
* @param label a string label for the check box menu item,
* or {@code null} for an unlabeled menu item.
* @param state the initial state of the menu item, where
* {@code true} indicates "on" and
* {@code false} indicates "off."
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public CheckboxMenuItem(String label, boolean state)
throws HeadlessException {
super(label);
this.state = state;
}
/**
* Construct a name for this MenuComponent. Called by getName() when
* the name is null.
*/
String constructComponentName() {
synchronized (CheckboxMenuItem.class) {
return base + nameCounter++;
}
}
/**
* Creates the peer of the checkbox item. This peer allows us to
* change the look of the checkbox item without changing its
* functionality.
* Most applications do not call this method directly.
* @see java.awt.Component#getToolkit()
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createCheckboxMenuItem(this);
super.addNotify();
}
}
/**
* Determines whether the state of this check box menu item
* is "on" or "off."
*
* @return the state of this check box menu item, where
* {@code true} indicates "on" and
* {@code false} indicates "off"
* @see #setState
*/
public boolean getState() {
return state;
}
/**
* Sets this check box menu item to the specified state.
* The boolean value {@code true} indicates "on" while
* {@code false} indicates "off."
*
* <p>Note that this method should be primarily used to
* initialize the state of the check box menu item.
* Programmatically setting the state of the check box
* menu item will <i>not</i> trigger
* an {@code ItemEvent}. The only way to trigger an
* {@code ItemEvent} is by user interaction.
*
* @param b {@code true} if the check box
* menu item is on, otherwise {@code false}
* @see #getState
*/
public synchronized void setState(boolean b) {
state = b;
CheckboxMenuItemPeer peer = (CheckboxMenuItemPeer)this.peer;
if (peer != null) {
peer.setState(b);
}
}
/**
* Returns the an array (length 1) containing the checkbox menu item
* label or null if the checkbox is not selected.
* @see ItemSelectable
*/
public synchronized Object[] getSelectedObjects() {
if (state) {
Object[] items = new Object[1];
items[0] = label;
return items;
}
return null;
}
/**
* Adds the specified item listener to receive item events from
* this check box menu item. Item events are sent in response to user
* actions, but not in response to calls to setState().
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the item listener
* @see #removeItemListener
* @see #getItemListeners
* @see #setState
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void addItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.add(itemListener, l);
newEventsOnly = true;
}
/**
* Removes the specified item listener so that it no longer receives
* item events from this check box menu item.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the item listener
* @see #addItemListener
* @see #getItemListeners
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void removeItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.remove(itemListener, l);
}
/**
* Returns an array of all the item listeners
* registered on this checkbox menuitem.
*
* @return all of this checkbox menuitem's {@code ItemListener}s
* or an empty array if no item
* listeners are currently registered
*
* @see #addItemListener
* @see #removeItemListener
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.4
*/
public synchronized ItemListener[] getItemListeners() {
return getListeners(ItemListener.class);
}
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this {@code CheckboxMenuItem}.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the {@code listenerType} argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* {@code CheckboxMenuItem c}
* for its item listeners with the following code:
*
* <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* {@code java.util.EventListener}
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this checkbox menuitem,
* or an empty array if no such
* listeners have been added
* @exception ClassCastException if {@code listenerType}
* doesn't specify a class or interface that implements
* {@code java.util.EventListener}
*
* @see #getItemListeners
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ItemListener.class) {
l = itemListener;
} else {
return super.getListeners(listenerType);
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
itemListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
/**
* Processes events on this check box menu item.
* If the event is an instance of {@code ItemEvent},
* this method invokes the {@code processItemEvent} method.
* If the event is not an item event,
* it invokes {@code processEvent} on the superclass.
* <p>
* Check box menu items currently support only item events.
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
* @see java.awt.event.ItemEvent
* @see #processItemEvent
* @since 1.1
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ItemEvent) {
processItemEvent((ItemEvent)e);
return;
}
super.processEvent(e);
}
/**
* Processes item events occurring on this check box menu item by
* dispatching them to any registered {@code ItemListener} objects.
* <p>
* This method is not called unless item events are
* enabled for this menu item. Item events are enabled
* when one of the following occurs:
* <ul>
* <li>An {@code ItemListener} object is registered
* via {@code addItemListener}.
* <li>Item events are enabled via {@code enableEvents}.
* </ul>
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the item event
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @see #addItemListener
* @see java.awt.MenuItem#enableEvents
* @since 1.1
*/
protected void processItemEvent(ItemEvent e) {
ItemListener listener = itemListener;
if (listener != null) {
listener.itemStateChanged(e);
}
}
/*
* Post an ItemEvent and toggle state.
*/
void doMenuEvent(long when, int modifiers) {
setState(!state);
Toolkit.getEventQueue().postEvent(
new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
getLabel(),
state ? ItemEvent.SELECTED :
ItemEvent.DESELECTED));
}
/**
* Returns a string representing the state of this
* {@code CheckBoxMenuItem}. This
* method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this check box menu item
*/
public String paramString() {
return super.paramString() + ",state=" + state;
}
/* Serialization support.
*/
/*
* Serial Data Version
* @serial
*/
private int checkboxMenuItemSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable {@code ItemListeners}
* as optional data. The non-serializable
* {@code ItemListeners} are detected and
* no attempt is made to serialize them.
*
* @param s the {@code ObjectOutputStream} to write
* @serialData {@code null} terminated sequence of
* 0 or more pairs; the pair consists of a {@code String}
* and an {@code Object}; the {@code String} indicates
* the type of object and is one of the following:
* {@code itemListenerK} indicating an
* {@code ItemListener} object
*
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see java.awt.Component#itemListenerK
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s)
throws java.io.IOException
{
s.defaultWriteObject();
AWTEventMulticaster.save(s, itemListenerK, itemListener);
s.writeObject(null);
}
/*
* Reads the {@code ObjectInputStream} and if it
* isn't {@code null} adds a listener to receive
* item events fired by the {@code Checkbox} menu item.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @serial
* @see removeActionListener()
* @see addActionListener()
* @see #writeObject
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (itemListenerK == key)
addItemListener((ItemListener)(s.readObject()));
else // skip value for unrecognized key
s.readObject();
}
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this CheckboxMenuItem.
* For checkbox menu items, the AccessibleContext takes the
* form of an AccessibleAWTCheckboxMenuItem.
* A new AccessibleAWTCheckboxMenuItem is created if necessary.
*
* @return an AccessibleAWTCheckboxMenuItem that serves as the
* AccessibleContext of this CheckboxMenuItem
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTCheckboxMenuItem();
}
return accessibleContext;
}
/**
* Inner class of CheckboxMenuItem used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by menu component developers.
* <p>
* This class implements accessibility support for the
* {@code CheckboxMenuItem} class. It provides an implementation
* of the Java Accessibility API appropriate to checkbox menu item
* user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem
implements AccessibleAction, AccessibleValue
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -1122642964303476L;
/**
* Get the AccessibleAction associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleAction interface on behalf of itself.
*
* @return this object
*/
public AccessibleAction getAccessibleAction() {
return this;
}
/**
* Get the AccessibleValue associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleValue interface on behalf of itself.
*
* @return this object
*/
public AccessibleValue getAccessibleValue() {
return this;
}
/**
* Returns the number of Actions available in this object.
* If there is more than one, the first one is the "default"
* action.
*
* @return the number of Actions in this object
*/
public int getAccessibleActionCount() {
return 0; // To be fully implemented in a future release
}
/**
* Return a description of the specified action of the object.
*
* @param i zero-based index of the actions
*/
public String getAccessibleActionDescription(int i) {
return null; // To be fully implemented in a future release
}
/**
* Perform the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; otherwise false.
*/
public boolean doAccessibleAction(int i) {
return false; // To be fully implemented in a future release
}
/**
* Get the value of this object as a Number. If the value has not been
* set, the return value will be null.
*
* @return value of the object
* @see #setCurrentAccessibleValue
*/
public Number getCurrentAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Set the value of this object as a Number.
*
* @return true if the value was set; otherwise false
* @see #getCurrentAccessibleValue
*/
public boolean setCurrentAccessibleValue(Number n) {
return false; // To be fully implemented in a future release
}
/**
* Get the minimum value of this object as a Number.
*
* @return Minimum value of the object; null if this object does not
* have a minimum value
* @see #getMaximumAccessibleValue
*/
public Number getMinimumAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Get the maximum value of this object as a Number.
*
* @return Maximum value of the object; null if this object does not
* have a maximum value
* @see #getMinimumAccessibleValue
*/
public Number getMaximumAccessibleValue() {
return null; // To be fully implemented in a future release
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.CHECK_BOX;
}
} // class AccessibleAWTMenuItem
}

View file

@ -0,0 +1,833 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.util.*;
import java.awt.peer.ChoicePeer;
import java.awt.event.*;
import java.util.EventListener;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
/**
* The {@code Choice} class presents a pop-up menu of choices.
* The current choice is displayed as the title of the menu.
* <p>
* The following code example produces a pop-up menu:
*
* <hr><blockquote><pre>
* Choice ColorChooser = new Choice();
* ColorChooser.add("Green");
* ColorChooser.add("Red");
* ColorChooser.add("Blue");
* </pre></blockquote><hr>
* <p>
* After this choice menu has been added to a panel,
* it appears as follows in its normal state:
* <p>
* <img src="doc-files/Choice-1.gif" alt="The following text describes the graphic"
* style="float:center; margin: 7px 10px;">
* <p>
* In the picture, {@code "Green"} is the current choice.
* Pushing the mouse button down on the object causes a menu to
* appear with the current choice highlighted.
* <p>
* Some native platforms do not support arbitrary resizing of
* {@code Choice} components and the behavior of
* {@code setSize()/getSize()} is bound by
* such limitations.
* Native GUI {@code Choice} components' size are often bound by such
* attributes as font size and length of items contained within
* the {@code Choice}.
*
* @author Sami Shaio
* @author Arthur van Hoff
* @since 1.0
*/
public class Choice extends Component implements ItemSelectable, Accessible {
/**
* The items for the {@code Choice}.
* This can be a {@code null} value.
* @serial
* @see #add(String)
* @see #addItem(String)
* @see #getItem(int)
* @see #getItemCount()
* @see #insert(String, int)
* @see #remove(String)
*/
Vector<String> pItems;
/**
* The index of the current choice for this {@code Choice}
* or -1 if nothing is selected.
* @serial
* @see #getSelectedItem()
* @see #select(int)
*/
int selectedIndex = -1;
transient ItemListener itemListener;
private static final String base = "choice";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -4075310674757313071L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
/* initialize JNI field and method ids */
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Creates a new choice menu. The menu initially has no items in it.
* <p>
* By default, the first item added to the choice menu becomes the
* selected item, until a different selection is made by the user
* by calling one of the {@code select} methods.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #select(int)
* @see #select(java.lang.String)
*/
public Choice() throws HeadlessException {
GraphicsEnvironment.checkHeadless();
pItems = new Vector<>();
}
/**
* Constructs a name for this component. Called by
* {@code getName} when the name is {@code null}.
*/
String constructComponentName() {
synchronized (Choice.class) {
return base + nameCounter++;
}
}
/**
* Creates the {@code Choice}'s peer. This peer allows us
* to change the look
* of the {@code Choice} without changing its functionality.
* @see java.awt.Component#getToolkit()
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createChoice(this);
super.addNotify();
}
}
/**
* Returns the number of items in this {@code Choice} menu.
*
* @return the number of items in this {@code Choice} menu
* @see #getItem
* @since 1.1
*/
public int getItemCount() {
return countItems();
}
/**
* Returns the number of items in this {@code Choice} menu.
*
* @return the number of items in this {@code Choice} menu
* @deprecated As of JDK version 1.1,
* replaced by {@code getItemCount()}.
*/
@Deprecated
public int countItems() {
return pItems.size();
}
/**
* Gets the string at the specified index in this
* {@code Choice} menu.
*
* @param index the index at which to begin
* @return the item at the specified index
* @see #getItemCount
*/
public String getItem(int index) {
return getItemImpl(index);
}
/*
* This is called by the native code, so client code can't
* be called on the toolkit thread.
*/
final String getItemImpl(int index) {
return pItems.elementAt(index);
}
/**
* Adds an item to this {@code Choice} menu.
* @param item the item to be added
* @exception NullPointerException if the item's value is
* {@code null}
* @since 1.1
*/
public void add(String item) {
addItem(item);
}
/**
* Obsolete as of Java 2 platform v1.1. Please use the
* {@code add} method instead.
* <p>
* Adds an item to this {@code Choice} menu.
* @param item the item to be added
* @exception NullPointerException if the item's value is equal to
* {@code null}
*/
public void addItem(String item) {
synchronized (this) {
insertNoInvalidate(item, pItems.size());
}
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
* Inserts an item to this {@code Choice},
* but does not invalidate the {@code Choice}.
* Client methods must provide their own synchronization before
* invoking this method.
* @param item the item to be added
* @param index the new item position
* @exception NullPointerException if the item's value is equal to
* {@code null}
*/
private void insertNoInvalidate(String item, int index) {
if (item == null) {
throw new
NullPointerException("cannot add null item to Choice");
}
pItems.insertElementAt(item, index);
ChoicePeer peer = (ChoicePeer)this.peer;
if (peer != null) {
peer.add(item, index);
}
// no selection or selection shifted up
if (selectedIndex < 0 || selectedIndex >= index) {
select(0);
}
}
/**
* Inserts the item into this choice at the specified position.
* Existing items at an index greater than or equal to
* {@code index} are shifted up by one to accommodate
* the new item. If {@code index} is greater than or
* equal to the number of items in this choice,
* {@code item} is added to the end of this choice.
* <p>
* If the item is the first one being added to the choice,
* then the item becomes selected. Otherwise, if the
* selected item was one of the items shifted, the first
* item in the choice becomes the selected item. If the
* selected item was no among those shifted, it remains
* the selected item.
* @param item the non-{@code null} item to be inserted
* @param index the position at which the item should be inserted
* @exception IllegalArgumentException if index is less than 0
*/
public void insert(String item, int index) {
synchronized (this) {
if (index < 0) {
throw new IllegalArgumentException("index less than zero.");
}
/* if the index greater than item count, add item to the end */
index = Math.min(index, pItems.size());
insertNoInvalidate(item, index);
}
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
* Removes the first occurrence of {@code item}
* from the {@code Choice} menu. If the item
* being removed is the currently selected item,
* then the first item in the choice becomes the
* selected item. Otherwise, the currently selected
* item remains selected (and the selected index is
* updated accordingly).
* @param item the item to remove from this {@code Choice} menu
* @exception IllegalArgumentException if the item doesn't
* exist in the choice menu
* @since 1.1
*/
public void remove(String item) {
synchronized (this) {
int index = pItems.indexOf(item);
if (index < 0) {
throw new IllegalArgumentException("item " + item +
" not found in choice");
} else {
removeNoInvalidate(index);
}
}
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
* Removes an item from the choice menu
* at the specified position. If the item
* being removed is the currently selected item,
* then the first item in the choice becomes the
* selected item. Otherwise, the currently selected
* item remains selected (and the selected index is
* updated accordingly).
* @param position the position of the item
* @throws IndexOutOfBoundsException if the specified
* position is out of bounds
* @since 1.1
*/
public void remove(int position) {
synchronized (this) {
removeNoInvalidate(position);
}
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
* Removes an item from the {@code Choice} at the
* specified position, but does not invalidate the {@code Choice}.
* Client methods must provide their
* own synchronization before invoking this method.
* @param position the position of the item
*/
private void removeNoInvalidate(int position) {
pItems.removeElementAt(position);
ChoicePeer peer = (ChoicePeer)this.peer;
if (peer != null) {
peer.remove(position);
}
/* Adjust selectedIndex if selected item was removed. */
if (pItems.size() == 0) {
selectedIndex = -1;
} else if (selectedIndex == position) {
select(0);
} else if (selectedIndex > position) {
select(selectedIndex-1);
}
}
/**
* Removes all items from the choice menu.
* @see #remove
* @since 1.1
*/
public void removeAll() {
synchronized (this) {
if (peer != null) {
((ChoicePeer)peer).removeAll();
}
pItems.removeAllElements();
selectedIndex = -1;
}
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
* Gets a representation of the current choice as a string.
* @return a string representation of the currently
* selected item in this choice menu
* @see #getSelectedIndex
*/
public synchronized String getSelectedItem() {
return (selectedIndex >= 0) ? getItem(selectedIndex) : null;
}
/**
* Returns an array (length 1) containing the currently selected
* item. If this choice has no items, returns {@code null}.
* @see ItemSelectable
*/
public synchronized Object[] getSelectedObjects() {
if (selectedIndex >= 0) {
Object[] items = new Object[1];
items[0] = getItem(selectedIndex);
return items;
}
return null;
}
/**
* Returns the index of the currently selected item.
* If nothing is selected, returns -1.
*
* @return the index of the currently selected item, or -1 if nothing
* is currently selected
* @see #getSelectedItem
*/
public int getSelectedIndex() {
return selectedIndex;
}
/**
* Sets the selected item in this {@code Choice} menu to be the
* item at the specified position.
*
* <p>Note that this method should be primarily used to
* initially select an item in this component.
* Programmatically calling this method will <i>not</i> trigger
* an {@code ItemEvent}. The only way to trigger an
* {@code ItemEvent} is by user interaction.
*
* @param pos the position of the selected item
* @exception IllegalArgumentException if the specified
* position is greater than the
* number of items or less than zero
* @see #getSelectedItem
* @see #getSelectedIndex
*/
public synchronized void select(int pos) {
if ((pos >= pItems.size()) || (pos < 0)) {
throw new IllegalArgumentException("illegal Choice item position: " + pos);
}
if (pItems.size() > 0) {
selectedIndex = pos;
ChoicePeer peer = (ChoicePeer)this.peer;
if (peer != null) {
peer.select(pos);
}
}
}
/**
* Sets the selected item in this {@code Choice} menu
* to be the item whose name is equal to the specified string.
* If more than one item matches (is equal to) the specified string,
* the one with the smallest index is selected.
*
* <p>Note that this method should be primarily used to
* initially select an item in this component.
* Programmatically calling this method will <i>not</i> trigger
* an {@code ItemEvent}. The only way to trigger an
* {@code ItemEvent} is by user interaction.
*
* @param str the specified string
* @see #getSelectedItem
* @see #getSelectedIndex
*/
public synchronized void select(String str) {
int index = pItems.indexOf(str);
if (index >= 0) {
select(index);
}
}
/**
* Adds the specified item listener to receive item events from
* this {@code Choice} menu. Item events are sent in response
* to user input, but not in response to calls to {@code select}.
* If l is {@code null}, no exception is thrown and no action
* is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
* @param l the item listener
* @see #removeItemListener
* @see #getItemListeners
* @see #select
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void addItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.add(itemListener, l);
newEventsOnly = true;
}
/**
* Removes the specified item listener so that it no longer receives
* item events from this {@code Choice} menu.
* If l is {@code null}, no exception is thrown and no
* action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
* @param l the item listener
* @see #addItemListener
* @see #getItemListeners
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.1
*/
public synchronized void removeItemListener(ItemListener l) {
if (l == null) {
return;
}
itemListener = AWTEventMulticaster.remove(itemListener, l);
}
/**
* Returns an array of all the item listeners
* registered on this choice.
*
* @return all of this choice's {@code ItemListener}s
* or an empty array if no item
* listeners are currently registered
*
* @see #addItemListener
* @see #removeItemListener
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since 1.4
*/
public synchronized ItemListener[] getItemListeners() {
return getListeners(ItemListener.class);
}
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this {@code Choice}.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the {@code listenerType} argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* {@code Choice c}
* for its item listeners with the following code:
*
* <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* {@code java.util.EventListener}
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this choice,
* or an empty array if no such
* listeners have been added
* @exception ClassCastException if {@code listenerType}
* doesn't specify a class or interface that implements
* {@code java.util.EventListener}
*
* @see #getItemListeners
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ItemListener.class) {
l = itemListener;
} else {
return super.getListeners(listenerType);
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
if (e.id == ItemEvent.ITEM_STATE_CHANGED) {
if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||
itemListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
/**
* Processes events on this choice. If the event is an
* instance of {@code ItemEvent}, it invokes the
* {@code processItemEvent} method. Otherwise, it calls its
* superclass's {@code processEvent} method.
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
* @see java.awt.event.ItemEvent
* @see #processItemEvent
* @since 1.1
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ItemEvent) {
processItemEvent((ItemEvent)e);
return;
}
super.processEvent(e);
}
/**
* Processes item events occurring on this {@code Choice}
* menu by dispatching them to any registered
* {@code ItemListener} objects.
* <p>
* This method is not called unless item events are
* enabled for this component. Item events are enabled
* when one of the following occurs:
* <ul>
* <li>An {@code ItemListener} object is registered
* via {@code addItemListener}.
* <li>Item events are enabled via {@code enableEvents}.
* </ul>
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the item event
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @see #addItemListener(ItemListener)
* @see java.awt.Component#enableEvents
* @since 1.1
*/
protected void processItemEvent(ItemEvent e) {
ItemListener listener = itemListener;
if (listener != null) {
listener.itemStateChanged(e);
}
}
/**
* Returns a string representing the state of this {@code Choice}
* menu. This method is intended to be used only for debugging purposes,
* and the content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this {@code Choice} menu
*/
protected String paramString() {
return super.paramString() + ",current=" + getSelectedItem();
}
/* Serialization support.
*/
/*
* Choice Serial Data Version.
* @serial
*/
private int choiceSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable {@code ItemListeners}
* as optional data. The non-serializable
* {@code ItemListeners} are detected and
* no attempt is made to serialize them.
*
* @param s the {@code ObjectOutputStream} to write
* @serialData {@code null} terminated sequence of 0
* or more pairs; the pair consists of a {@code String}
* and an {@code Object}; the {@code String} indicates
* the type of object and is one of the following:
* {@code itemListenerK} indicating an
* {@code ItemListener} object
*
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see java.awt.Component#itemListenerK
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s)
throws java.io.IOException
{
s.defaultWriteObject();
AWTEventMulticaster.save(s, itemListenerK, itemListener);
s.writeObject(null);
}
/**
* Reads the {@code ObjectInputStream} and if it
* isn't {@code null} adds a listener to receive
* item events fired by the {@code Choice} item.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @serial
* @see #removeItemListener(ItemListener)
* @see #addItemListener(ItemListener)
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException
{
GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (itemListenerK == key)
addItemListener((ItemListener)(s.readObject()));
else // skip value for unrecognized key
s.readObject();
}
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the {@code AccessibleContext} associated with this
* {@code Choice}. For {@code Choice} components,
* the {@code AccessibleContext} takes the form of an
* {@code AccessibleAWTChoice}. A new {@code AccessibleAWTChoice}
* instance is created if necessary.
*
* @return an {@code AccessibleAWTChoice} that serves as the
* {@code AccessibleContext} of this {@code Choice}
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTChoice();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Choice} class. It provides an implementation of the
* Java Accessibility API appropriate to choice user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTChoice extends AccessibleAWTComponent
implements AccessibleAction
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = 7175603582428509322L;
/**
* Constructor for {@code AccessibleAWTChoice}
*/
public AccessibleAWTChoice() {
super();
}
/**
* Get the AccessibleAction associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleAction interface on behalf of itself.
*
* @return this object
* @see AccessibleAction
*/
public AccessibleAction getAccessibleAction() {
return this;
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.COMBO_BOX;
}
/**
* Returns the number of accessible actions available in this object
* If there are more than one, the first one is considered the "default"
* action of the object.
*
* @return the zero-based number of Actions in this object
*/
public int getAccessibleActionCount() {
return 0; // To be fully implemented in a future release
}
/**
* Returns a description of the specified action of the object.
*
* @param i zero-based index of the actions
* @return a String description of the action
* @see #getAccessibleActionCount
*/
public String getAccessibleActionDescription(int i) {
return null; // To be fully implemented in a future release
}
/**
* Perform the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; otherwise false.
* @see #getAccessibleActionCount
*/
public boolean doAccessibleAction(int i) {
return false; // To be fully implemented in a future release
}
} // inner class AccessibleAWTChoice
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import sun.awt.image.IntegerComponentRaster;
import java.util.Arrays;
class ColorPaintContext implements PaintContext {
int color;
WritableRaster savedTile;
protected ColorPaintContext(int color, ColorModel cm) {
this.color = color;
}
public void dispose() {
}
/*
* Returns the RGB value representing the color in the default sRGB
* {@link ColorModel}.
* (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are
* blue).
* @return the RGB value of the color in the default sRGB
* {@code ColorModel}.
* @see java.awt.image.ColorModel#getRGBdefault
* @see #getRed
* @see #getGreen
* @see #getBlue
*/
int getRGB() {
return color;
}
public ColorModel getColorModel() {
return ColorModel.getRGBdefault();
}
public synchronized Raster getRaster(int x, int y, int w, int h) {
WritableRaster t = savedTile;
if (t == null || w > t.getWidth() || h > t.getHeight()) {
t = getColorModel().createCompatibleWritableRaster(w, h);
IntegerComponentRaster icr = (IntegerComponentRaster) t;
Arrays.fill(icr.getDataStorage(), color);
// Note - markDirty is probably unnecessary since icr is brand new
icr.markDirty();
if (w <= 64 && h <= 64) {
savedTile = t;
}
}
return t;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* (C) Copyright IBM Corp. 1998 - All Rights Reserved
*
* The original version of this source code and documentation is copyrighted
* and owned by IBM, Inc. These materials are provided under terms of a
* License Agreement between IBM and Sun. This technology is protected by
* multiple US and International patents. This notice and attribution to IBM
* may not be removed.
*
*/
package java.awt;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* The ComponentOrientation class encapsulates the language-sensitive
* orientation that is to be used to order the elements of a component
* or of text. It is used to reflect the differences in this ordering
* between Western alphabets, Middle Eastern (such as Hebrew), and Far
* Eastern (such as Japanese).
* <p>
* Fundamentally, this governs items (such as characters) which are laid out
* in lines, with the lines then laid out in a block. This also applies
* to items in a widget: for example, in a check box where the box is
* positioned relative to the text.
* <p>
* There are four different orientations used in modern languages
* as in the following table.<br>
* <pre>
* LT RT TL TR
* A B C C B A A D G G D A
* D E F F E D B E H H E B
* G H I I H G C F I I F C
* </pre><br>
* (In the header, the two-letter abbreviation represents the item direction
* in the first letter, and the line direction in the second. For example,
* LT means "items left-to-right, lines top-to-bottom",
* TL means "items top-to-bottom, lines left-to-right", and so on.)
* <p>
* The orientations are:
* <ul>
* <li>LT - Western Europe (optional for Japanese, Chinese, Korean)
* <li>RT - Middle East (Arabic, Hebrew)
* <li>TR - Japanese, Chinese, Korean
* <li>TL - Mongolian
* </ul>
* Components whose view and controller code depends on orientation
* should use the {@code isLeftToRight()} and
* {@code isHorizontal()} methods to
* determine their behavior. They should not include switch-like
* code that keys off of the constants, such as:
* <pre>
* if (orientation == LEFT_TO_RIGHT) {
* ...
* } else if (orientation == RIGHT_TO_LEFT) {
* ...
* } else {
* // Oops
* }
* </pre>
* This is unsafe, since more constants may be added in the future and
* since it is not guaranteed that orientation objects will be unique.
*/
public final class ComponentOrientation implements java.io.Serializable
{
/*
* serialVersionUID
*/
private static final long serialVersionUID = -4113291392143563828L;
// Internal constants used in the implementation
private static final int UNK_BIT = 1;
private static final int HORIZ_BIT = 2;
private static final int LTR_BIT = 4;
/**
* Items run left to right and lines flow top to bottom
* Examples: English, French.
*/
public static final ComponentOrientation LEFT_TO_RIGHT =
new ComponentOrientation(HORIZ_BIT|LTR_BIT);
/**
* Items run right to left and lines flow top to bottom
* Examples: Arabic, Hebrew.
*/
public static final ComponentOrientation RIGHT_TO_LEFT =
new ComponentOrientation(HORIZ_BIT);
/**
* Indicates that a component's orientation has not been set.
* To preserve the behavior of existing applications,
* isLeftToRight will return true for this value.
*/
public static final ComponentOrientation UNKNOWN =
new ComponentOrientation(HORIZ_BIT|LTR_BIT|UNK_BIT);
/**
* Are lines horizontal?
* This will return true for horizontal, left-to-right writing
* systems such as Roman.
*
* @return {@code true} if this orientation has horizontal lines
*/
public boolean isHorizontal() {
return (orientation & HORIZ_BIT) != 0;
}
/**
* HorizontalLines: Do items run left-to-right?<br>
* Vertical Lines: Do lines run left-to-right?<br>
* This will return true for horizontal, left-to-right writing
* systems such as Roman.
*
* @return {@code true} if this orientation is left-to-right
*/
public boolean isLeftToRight() {
return (orientation & LTR_BIT) != 0;
}
/**
* Returns the orientation that is appropriate for the given locale.
*
* @param locale the specified locale
* @return the orientation for the locale
*/
public static ComponentOrientation getOrientation(Locale locale) {
// A more flexible implementation would consult a ResourceBundle
// to find the appropriate orientation. Until pluggable locales
// are introduced however, the flexibility isn't really needed.
// So we choose efficiency instead.
String lang = locale.getLanguage();
if( "iw".equals(lang) || "ar".equals(lang)
|| "fa".equals(lang) || "ur".equals(lang) )
{
return RIGHT_TO_LEFT;
} else {
return LEFT_TO_RIGHT;
}
}
/**
* Returns the orientation appropriate for the given ResourceBundle's
* localization. Three approaches are tried, in the following order:
* <ol>
* <li>Retrieve a ComponentOrientation object from the ResourceBundle
* using the string "Orientation" as the key.
* <li>Use the ResourceBundle.getLocale to determine the bundle's
* locale, then return the orientation for that locale.
* <li>Return the default locale's orientation.
* </ol>
*
* @param bdl the bundle to use
* @return the orientation
* @deprecated As of J2SE 1.4, use {@link #getOrientation(java.util.Locale)}.
*/
@Deprecated
public static ComponentOrientation getOrientation(ResourceBundle bdl)
{
ComponentOrientation result = null;
try {
result = (ComponentOrientation)bdl.getObject("Orientation");
}
catch (Exception e) {
}
if (result == null) {
result = getOrientation(bdl.getLocale());
}
if (result == null) {
result = getOrientation(Locale.getDefault());
}
return result;
}
private int orientation;
private ComponentOrientation(int value)
{
orientation = value;
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ColorModel;
/**
* The {@code Composite} interface, along with
* {@link CompositeContext}, defines the methods to compose a draw
* primitive with the underlying graphics area.
* After the {@code Composite} is set in the
* {@link Graphics2D} context, it combines a shape, text, or an image
* being rendered with the colors that have already been rendered
* according to pre-defined rules. The classes
* implementing this interface provide the rules and a method to create
* the context for a particular operation.
* {@code CompositeContext} is an environment used by the
* compositing operation, which is created by the {@code Graphics2D}
* prior to the start of the operation. {@code CompositeContext}
* contains private information and resources needed for a compositing
* operation. When the {@code CompositeContext} is no longer needed,
* the {@code Graphics2D} object disposes of it in order to reclaim
* resources allocated for the operation.
* <p>
* Instances of classes implementing {@code Composite} must be
* immutable because the {@code Graphics2D} does not clone
* these objects when they are set as an attribute with the
* {@code setComposite} method or when the {@code Graphics2D}
* object is cloned. This is to avoid undefined rendering behavior of
* {@code Graphics2D}, resulting from the modification of
* the {@code Composite} object after it has been set in the
* {@code Graphics2D} context.
* <p>
* Since this interface must expose the contents of pixels on the
* target device or image to potentially arbitrary code, the use of
* custom objects which implement this interface when rendering directly
* to a screen device is governed by the {@code readDisplayPixels}
* {@link AWTPermission}. The permission check will occur when such
* a custom object is passed to the {@code setComposite} method
* of a {@code Graphics2D} retrieved from a {@link Component}.
* @see AlphaComposite
* @see CompositeContext
* @see Graphics2D#setComposite
*/
public interface Composite {
/**
* Creates a context containing state that is used to perform
* the compositing operation. In a multi-threaded environment,
* several contexts can exist simultaneously for a single
* {@code Composite} object.
* @param srcColorModel the {@link ColorModel} of the source
* @param dstColorModel the {@code ColorModel} of the destination
* @param hints the hint that the context object uses to choose between
* rendering alternatives
* @return the {@code CompositeContext} object used to perform the
* compositing operation.
*/
public CompositeContext createContext(ColorModel srcColorModel,
ColorModel dstColorModel,
RenderingHints hints);
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
/**
* The {@code CompositeContext} interface defines the encapsulated
* and optimized environment for a compositing operation.
* {@code CompositeContext} objects maintain state for
* compositing operations. In a multi-threaded environment, several
* contexts can exist simultaneously for a single {@link Composite}
* object.
* @see Composite
*/
public interface CompositeContext {
/**
* Releases resources allocated for a context.
*/
public void dispose();
/**
* Composes the two source {@link Raster} objects and
* places the result in the destination
* {@link WritableRaster}. Note that the destination
* can be the same object as either the first or second
* source. Note that {@code dstIn} and
* {@code dstOut} must be compatible with the
* {@code dstColorModel} passed to the
* {@link Composite#createContext(java.awt.image.ColorModel, java.awt.image.ColorModel, java.awt.RenderingHints) createContext}
* method of the {@code Composite} interface.
* @param src the first source for the compositing operation
* @param dstIn the second source for the compositing operation
* @param dstOut the {@code WritableRaster} into which the
* result of the operation is stored
* @see Composite
*/
public void compose(Raster src,
Raster dstIn,
WritableRaster dstOut);
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Conditional is used by the EventDispatchThread's message pumps to
* determine if a given pump should continue to run, or should instead exit
* and yield control to the parent pump.
*
* @author David Mendenhall
*/
interface Conditional {
boolean evaluate();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,607 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.util.List;
import java.util.ArrayList;
import sun.util.logging.PlatformLogger;
/**
* A FocusTraversalPolicy that determines traversal order based on the order
* of child Components in a Container. From a particular focus cycle root, the
* policy makes a pre-order traversal of the Component hierarchy, and traverses
* a Container's children according to the ordering of the array returned by
* {@code Container.getComponents()}. Portions of the hierarchy that are
* not visible and displayable will not be searched.
* <p>
* By default, ContainerOrderFocusTraversalPolicy implicitly transfers focus
* down-cycle. That is, during normal forward focus traversal, the Component
* traversed after a focus cycle root will be the focus-cycle-root's default
* Component to focus. This behavior can be disabled using the
* {@code setImplicitDownCycleTraversal} method.
* <p>
* By default, methods of this class will return a Component only if it is
* visible, displayable, enabled, and focusable. Subclasses can modify this
* behavior by overriding the {@code accept} method.
* <p>
* This policy takes into account <a
* href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal
* policy providers</a>. When searching for first/last/next/previous Component,
* if a focus traversal policy provider is encountered, its focus traversal
* policy is used to perform the search operation.
*
* @author David Mendenhall
*
* @see Container#getComponents
* @since 1.4
*/
public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
implements java.io.Serializable
{
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.ContainerOrderFocusTraversalPolicy");
private final int FORWARD_TRAVERSAL = 0;
private final int BACKWARD_TRAVERSAL = 1;
/*
* JDK 1.4 serialVersionUID
*/
private static final long serialVersionUID = 486933713763926351L;
private boolean implicitDownCycleTraversal = true;
/**
* Used by getComponentAfter and getComponentBefore for efficiency. In
* order to maintain compliance with the specification of
* FocusTraversalPolicy, if traversal wraps, we should invoke
* getFirstComponent or getLastComponent. These methods may be overriden in
* subclasses to behave in a non-generic way. However, in the generic case,
* these methods will simply return the first or last Components of the
* sorted list, respectively. Since getComponentAfter and
* getComponentBefore have already built the list before determining
* that they need to invoke getFirstComponent or getLastComponent, the
* list should be reused if possible.
*/
private transient Container cachedRoot;
private transient List<Component> cachedCycle;
/*
* We suppose to use getFocusTraversalCycle & getComponentIndex methods in order
* to divide the policy into two parts:
* 1) Making the focus traversal cycle.
* 2) Traversing the cycle.
* The 1st point assumes producing a list of components representing the focus
* traversal cycle. The two methods mentioned above should implement this logic.
* The 2nd point assumes implementing the common concepts of operating on the
* cycle: traversing back and forth, retrieving the initial/default/first/last
* component. These concepts are described in the AWT Focus Spec and they are
* applied to the FocusTraversalPolicy in general.
* Thus, a descendant of this policy may wish to not reimplement the logic of
* the 2nd point but just override the implementation of the 1st one.
* A striking example of such a descendant is the javax.swing.SortingFocusTraversalPolicy.
*/
/*protected*/ private List<Component> getFocusTraversalCycle(Container aContainer) {
List<Component> cycle = new ArrayList<Component>();
enumerateCycle(aContainer, cycle);
return cycle;
}
/*protected*/ private int getComponentIndex(List<Component> cycle, Component aComponent) {
return cycle.indexOf(aComponent);
}
private void enumerateCycle(Container container, List<Component> cycle) {
if (!(container.isVisible() && container.isDisplayable())) {
return;
}
cycle.add(container);
Component[] components = container.getComponents();
for (int i = 0; i < components.length; i++) {
Component comp = components[i];
if (comp instanceof Container) {
Container cont = (Container)comp;
if (!cont.isFocusCycleRoot() && !cont.isFocusTraversalPolicyProvider()) {
enumerateCycle(cont, cycle);
continue;
}
}
cycle.add(comp);
}
}
private Container getTopmostProvider(Container focusCycleRoot, Component aComponent) {
Container aCont = aComponent.getParent();
Container ftp = null;
while (aCont != focusCycleRoot && aCont != null) {
if (aCont.isFocusTraversalPolicyProvider()) {
ftp = aCont;
}
aCont = aCont.getParent();
}
if (aCont == null) {
return null;
}
return ftp;
}
/*
* Checks if a new focus cycle takes place and returns a Component to traverse focus to.
* @param comp a possible focus cycle root or policy provider
* @param traversalDirection the direction of the traversal
* @return a Component to traverse focus to if {@code comp} is a root or provider
* and implicit down-cycle is set, otherwise {@code null}
*/
private Component getComponentDownCycle(Component comp, int traversalDirection) {
Component retComp = null;
if (comp instanceof Container) {
Container cont = (Container)comp;
if (cont.isFocusCycleRoot()) {
if (getImplicitDownCycleTraversal()) {
retComp = cont.getFocusTraversalPolicy().getDefaultComponent(cont);
if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Transferred focus down-cycle to " + retComp +
" in the focus cycle root " + cont);
}
} else {
return null;
}
} else if (cont.isFocusTraversalPolicyProvider()) {
retComp = (traversalDirection == FORWARD_TRAVERSAL ?
cont.getFocusTraversalPolicy().getDefaultComponent(cont) :
cont.getFocusTraversalPolicy().getLastComponent(cont));
if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Transferred focus to " + retComp + " in the FTP provider " + cont);
}
}
}
return retComp;
}
/**
* Returns the Component that should receive the focus after aComponent.
* aContainer must be a focus cycle root of aComponent or a focus traversal policy provider.
* <p>
* By default, ContainerOrderFocusTraversalPolicy implicitly transfers
* focus down-cycle. That is, during normal forward focus traversal, the
* Component traversed after a focus cycle root will be the focus-cycle-
* root's default Component to focus. This behavior can be disabled using
* the {@code setImplicitDownCycleTraversal} method.
* <p>
* If aContainer is <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus
* traversal policy provider</a>, the focus is always transferred down-cycle.
*
* @param aContainer a focus cycle root of aComponent or a focus traversal policy provider
* @param aComponent a (possibly indirect) child of aContainer, or
* aContainer itself
* @return the Component that should receive the focus after aComponent, or
* null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is not a focus cycle
* root of aComponent or focus traversal policy provider, or if either aContainer or
* aComponent is null
*/
public Component getComponentAfter(Container aContainer, Component aComponent) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Searching in " + aContainer + " for component after " + aComponent);
}
if (aContainer == null || aComponent == null) {
throw new IllegalArgumentException("aContainer and aComponent cannot be null");
}
if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) {
throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider");
} else if (aContainer.isFocusCycleRoot() && !aComponent.isFocusCycleRoot(aContainer)) {
throw new IllegalArgumentException("aContainer is not a focus cycle root of aComponent");
}
synchronized(aContainer.getTreeLock()) {
if (!(aContainer.isVisible() && aContainer.isDisplayable())) {
return null;
}
// Before all the checks below we first see if it's an FTP provider or a focus cycle root.
// If it's the case just go down cycle (if it's set to "implicit").
Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL);
// Check if aComponent is focus-cycle-root's default Component, i.e.
// focus cycle root & focus-cycle-root's default Component is same.
if (comp != null && comp != aComponent) {
return comp;
}
// See if the component is inside of policy provider.
Container provider = getTopmostProvider(aContainer, aComponent);
if (provider != null) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Asking FTP " + provider + " for component after " + aComponent);
}
// FTP knows how to find component after the given. We don't.
FocusTraversalPolicy policy = provider.getFocusTraversalPolicy();
Component afterComp = policy.getComponentAfter(provider, aComponent);
// Null result means that we overstepped the limit of the FTP's cycle.
// In that case we must quit the cycle, otherwise return the component found.
if (afterComp != null) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### FTP returned " + afterComp);
}
return afterComp;
}
aComponent = provider;
}
List<Component> cycle = getFocusTraversalCycle(aContainer);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is " + cycle + ", component is " + aComponent);
}
int index = getComponentIndex(cycle, aComponent);
if (index < 0) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer);
}
return getFirstComponent(aContainer);
}
for (index++; index < cycle.size(); index++) {
comp = cycle.get(index);
if (accept(comp)) {
return comp;
} else if ((comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null) {
return comp;
}
}
if (aContainer.isFocusCycleRoot()) {
this.cachedRoot = aContainer;
this.cachedCycle = cycle;
comp = getFirstComponent(aContainer);
this.cachedRoot = null;
this.cachedCycle = null;
return comp;
}
}
return null;
}
/**
* Returns the Component that should receive the focus before aComponent.
* aContainer must be a focus cycle root of aComponent or a <a
* href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy
* provider</a>.
*
* @param aContainer a focus cycle root of aComponent or focus traversal policy provider
* @param aComponent a (possibly indirect) child of aContainer, or
* aContainer itself
* @return the Component that should receive the focus before aComponent,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is not a focus cycle
* root of aComponent or focus traversal policy provider, or if either aContainer or
* aComponent is null
*/
public Component getComponentBefore(Container aContainer, Component aComponent) {
if (aContainer == null || aComponent == null) {
throw new IllegalArgumentException("aContainer and aComponent cannot be null");
}
if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) {
throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider");
} else if (aContainer.isFocusCycleRoot() && !aComponent.isFocusCycleRoot(aContainer)) {
throw new IllegalArgumentException("aContainer is not a focus cycle root of aComponent");
}
synchronized(aContainer.getTreeLock()) {
if (!(aContainer.isVisible() && aContainer.isDisplayable())) {
return null;
}
// See if the component is inside of policy provider.
Container provider = getTopmostProvider(aContainer, aComponent);
if (provider != null) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Asking FTP " + provider + " for component after " + aComponent);
}
// FTP knows how to find component after the given. We don't.
FocusTraversalPolicy policy = provider.getFocusTraversalPolicy();
Component beforeComp = policy.getComponentBefore(provider, aComponent);
// Null result means that we overstepped the limit of the FTP's cycle.
// In that case we must quit the cycle, otherwise return the component found.
if (beforeComp != null) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### FTP returned " + beforeComp);
}
return beforeComp;
}
aComponent = provider;
// If the provider is traversable it's returned.
if (accept(aComponent)) {
return aComponent;
}
}
List<Component> cycle = getFocusTraversalCycle(aContainer);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is " + cycle + ", component is " + aComponent);
}
int index = getComponentIndex(cycle, aComponent);
if (index < 0) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer);
}
return getLastComponent(aContainer);
}
Component comp = null;
Component tryComp = null;
for (index--; index>=0; index--) {
comp = cycle.get(index);
if (comp != aContainer && (tryComp = getComponentDownCycle(comp, BACKWARD_TRAVERSAL)) != null) {
return tryComp;
} else if (accept(comp)) {
return comp;
}
}
if (aContainer.isFocusCycleRoot()) {
this.cachedRoot = aContainer;
this.cachedCycle = cycle;
comp = getLastComponent(aContainer);
this.cachedRoot = null;
this.cachedCycle = null;
return comp;
}
}
return null;
}
/**
* Returns the first Component in the traversal cycle. This method is used
* to determine the next Component to focus when traversal wraps in the
* forward direction.
*
* @param aContainer the focus cycle root or focus traversal policy provider whose first
* Component is to be returned
* @return the first Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is null
*/
public Component getFirstComponent(Container aContainer) {
List<Component> cycle;
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Getting first component in " + aContainer);
}
if (aContainer == null) {
throw new IllegalArgumentException("aContainer cannot be null");
}
synchronized(aContainer.getTreeLock()) {
if (!(aContainer.isVisible() && aContainer.isDisplayable())) {
return null;
}
if (this.cachedRoot == aContainer) {
cycle = this.cachedCycle;
} else {
cycle = getFocusTraversalCycle(aContainer);
}
if (cycle.size() == 0) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is empty");
}
return null;
}
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is " + cycle);
}
for (Component comp : cycle) {
if (accept(comp)) {
return comp;
} else if (comp != aContainer &&
(comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null)
{
return comp;
}
}
}
return null;
}
/**
* Returns the last Component in the traversal cycle. This method is used
* to determine the next Component to focus when traversal wraps in the
* reverse direction.
*
* @param aContainer the focus cycle root or focus traversal policy provider whose last
* Component is to be returned
* @return the last Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is null
*/
public Component getLastComponent(Container aContainer) {
List<Component> cycle;
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Getting last component in " + aContainer);
}
if (aContainer == null) {
throw new IllegalArgumentException("aContainer cannot be null");
}
synchronized(aContainer.getTreeLock()) {
if (!(aContainer.isVisible() && aContainer.isDisplayable())) {
return null;
}
if (this.cachedRoot == aContainer) {
cycle = this.cachedCycle;
} else {
cycle = getFocusTraversalCycle(aContainer);
}
if (cycle.size() == 0) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is empty");
}
return null;
}
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("### Cycle is " + cycle);
}
for (int i= cycle.size() - 1; i >= 0; i--) {
Component comp = cycle.get(i);
if (accept(comp)) {
return comp;
} else if (comp instanceof Container && comp != aContainer) {
Container cont = (Container)comp;
if (cont.isFocusTraversalPolicyProvider()) {
Component retComp = cont.getFocusTraversalPolicy().getLastComponent(cont);
if (retComp != null) {
return retComp;
}
}
}
}
}
return null;
}
/**
* Returns the default Component to focus. This Component will be the first
* to receive focus when traversing down into a new focus traversal cycle
* rooted at aContainer. The default implementation of this method
* returns the same Component as {@code getFirstComponent}.
*
* @param aContainer the focus cycle root or focus traversal policy provider whose default
* Component is to be returned
* @return the default Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @see #getFirstComponent
* @throws IllegalArgumentException if aContainer is null
*/
public Component getDefaultComponent(Container aContainer) {
return getFirstComponent(aContainer);
}
/**
* Sets whether this ContainerOrderFocusTraversalPolicy transfers focus
* down-cycle implicitly. If {@code true}, during normal forward focus
* traversal, the Component traversed after a focus cycle root will be the
* focus-cycle-root's default Component to focus. If {@code false},
* the next Component in the focus traversal cycle rooted at the specified
* focus cycle root will be traversed instead. The default value for this
* property is {@code true}.
*
* @param implicitDownCycleTraversal whether this
* ContainerOrderFocusTraversalPolicy transfers focus down-cycle
* implicitly
* @see #getImplicitDownCycleTraversal
* @see #getFirstComponent
*/
public void setImplicitDownCycleTraversal(boolean implicitDownCycleTraversal) {
this.implicitDownCycleTraversal = implicitDownCycleTraversal;
}
/**
* Returns whether this ContainerOrderFocusTraversalPolicy transfers focus
* down-cycle implicitly. If {@code true}, during normal forward focus
* traversal, the Component traversed after a focus cycle root will be the
* focus-cycle-root's default Component to focus. If {@code false},
* the next Component in the focus traversal cycle rooted at the specified
* focus cycle root will be traversed instead.
*
* @return whether this ContainerOrderFocusTraversalPolicy transfers focus
* down-cycle implicitly
* @see #setImplicitDownCycleTraversal
* @see #getFirstComponent
*/
public boolean getImplicitDownCycleTraversal() {
return implicitDownCycleTraversal;
}
/**
* Determines whether a Component is an acceptable choice as the new
* focus owner. By default, this method will accept a Component if and
* only if it is visible, displayable, enabled, and focusable.
*
* @param aComponent the Component whose fitness as a focus owner is to
* be tested
* @return {@code true} if aComponent is visible, displayable,
* enabled, and focusable; {@code false} otherwise
*/
protected boolean accept(Component aComponent) {
if (!aComponent.canBeFocusOwner()) {
return false;
}
// Verify that the Component is recursively enabled. Disabling a
// heavyweight Container disables its children, whereas disabling
// a lightweight Container does not.
if (!(aComponent instanceof Window)) {
for (Container enableTest = aComponent.getParent();
enableTest != null;
enableTest = enableTest.getParent())
{
if (!(enableTest.isEnabled() || enableTest.isLightweight())) {
return false;
}
if (enableTest instanceof Window) {
break;
}
}
}
return true;
}
}

View file

@ -0,0 +1,453 @@
/*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.beans.ConstructorProperties;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import sun.awt.AWTAccessor;
import sun.util.logging.PlatformLogger;
/**
* A class to encapsulate the bitmap representation of the mouse cursor.
*
* @see Component#setCursor
* @author Amy Fowler
*/
public class Cursor implements java.io.Serializable {
/**
* The default cursor type (gets set if no cursor is defined).
*/
public static final int DEFAULT_CURSOR = 0;
/**
* The crosshair cursor type.
*/
public static final int CROSSHAIR_CURSOR = 1;
/**
* The text cursor type.
*/
public static final int TEXT_CURSOR = 2;
/**
* The wait cursor type.
*/
public static final int WAIT_CURSOR = 3;
/**
* The south-west-resize cursor type.
*/
public static final int SW_RESIZE_CURSOR = 4;
/**
* The south-east-resize cursor type.
*/
public static final int SE_RESIZE_CURSOR = 5;
/**
* The north-west-resize cursor type.
*/
public static final int NW_RESIZE_CURSOR = 6;
/**
* The north-east-resize cursor type.
*/
public static final int NE_RESIZE_CURSOR = 7;
/**
* The north-resize cursor type.
*/
public static final int N_RESIZE_CURSOR = 8;
/**
* The south-resize cursor type.
*/
public static final int S_RESIZE_CURSOR = 9;
/**
* The west-resize cursor type.
*/
public static final int W_RESIZE_CURSOR = 10;
/**
* The east-resize cursor type.
*/
public static final int E_RESIZE_CURSOR = 11;
/**
* The hand cursor type.
*/
public static final int HAND_CURSOR = 12;
/**
* The move cursor type.
*/
public static final int MOVE_CURSOR = 13;
/**
* @deprecated As of JDK version 1.7, the {@link #getPredefinedCursor(int)}
* method should be used instead.
*/
@Deprecated
protected static Cursor predefined[] = new Cursor[14];
/**
* This field is a private replacement for 'predefined' array.
*/
private static final Cursor[] predefinedPrivate = new Cursor[14];
/* Localization names and default values */
static final String[][] cursorProperties = {
{ "AWT.DefaultCursor", "Default Cursor" },
{ "AWT.CrosshairCursor", "Crosshair Cursor" },
{ "AWT.TextCursor", "Text Cursor" },
{ "AWT.WaitCursor", "Wait Cursor" },
{ "AWT.SWResizeCursor", "Southwest Resize Cursor" },
{ "AWT.SEResizeCursor", "Southeast Resize Cursor" },
{ "AWT.NWResizeCursor", "Northwest Resize Cursor" },
{ "AWT.NEResizeCursor", "Northeast Resize Cursor" },
{ "AWT.NResizeCursor", "North Resize Cursor" },
{ "AWT.SResizeCursor", "South Resize Cursor" },
{ "AWT.WResizeCursor", "West Resize Cursor" },
{ "AWT.EResizeCursor", "East Resize Cursor" },
{ "AWT.HandCursor", "Hand Cursor" },
{ "AWT.MoveCursor", "Move Cursor" },
};
/**
* The chosen cursor type initially set to
* the {@code DEFAULT_CURSOR}.
*
* @serial
* @see #getType()
*/
int type = DEFAULT_CURSOR;
/**
* The type associated with all custom cursors.
*/
public static final int CUSTOM_CURSOR = -1;
/*
* hashtable, resource prefix, filename, and properties for custom cursors
* support
*/
private static final Hashtable<String,Cursor> systemCustomCursors = new Hashtable<>(1);
private static final String RESOURCE_PREFIX = "/sun/awt/resources/cursors/";
private static final String PROPERTIES_FILE = RESOURCE_PREFIX + "cursors.properties";
private static Properties systemCustomCursorProperties = null;
private static final String CURSOR_DOT_PREFIX = "Cursor.";
private static final String DOT_FILE_SUFFIX = ".File";
private static final String DOT_HOTSPOT_SUFFIX = ".HotSpot";
private static final String DOT_NAME_SUFFIX = ".Name";
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 8028237497568985504L;
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Cursor");
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setCursorAccessor(
new AWTAccessor.CursorAccessor() {
public long getPData(Cursor cursor) {
return cursor.pData;
}
public void setPData(Cursor cursor, long pData) {
cursor.pData = pData;
}
public int getType(Cursor cursor) {
return cursor.type;
}
});
}
/**
* Initialize JNI field and method IDs for fields that may be
* accessed from C.
*/
private static native void initIDs();
/**
* Hook into native data.
*/
private transient long pData;
private transient Object anchor = new Object();
static class CursorDisposer implements sun.java2d.DisposerRecord {
volatile long pData;
public CursorDisposer(long pData) {
this.pData = pData;
}
public void dispose() {
if (pData != 0) {
finalizeImpl(pData);
}
}
}
transient CursorDisposer disposer;
private void setPData(long pData) {
this.pData = pData;
if (GraphicsEnvironment.isHeadless()) {
return;
}
if (disposer == null) {
disposer = new CursorDisposer(pData);
// anchor is null after deserialization
if (anchor == null) {
anchor = new Object();
}
sun.java2d.Disposer.addRecord(anchor, disposer);
} else {
disposer.pData = pData;
}
}
/**
* The user-visible name of the cursor.
*
* @serial
* @see #getName()
*/
protected String name;
/**
* Returns a cursor object with the specified predefined type.
*
* @param type the type of predefined cursor
* @return the specified predefined cursor
* @throws IllegalArgumentException if the specified cursor type is
* invalid
*/
public static Cursor getPredefinedCursor(int type) {
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
throw new IllegalArgumentException("illegal cursor type");
}
Cursor c = predefinedPrivate[type];
if (c == null) {
predefinedPrivate[type] = c = new Cursor(type);
}
// fill 'predefined' array for backwards compatibility.
if (predefined[type] == null) {
predefined[type] = c;
}
return c;
}
/**
* Returns a system-specific custom cursor object matching the
* specified name. Cursor names are, for example: "Invalid.16x16"
*
* @param name a string describing the desired system-specific custom cursor
* @return the system specific custom cursor named
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns true
* @exception AWTException in case of erroneous retrieving of the cursor
*/
public static Cursor getSystemCustomCursor(final String name)
throws AWTException, HeadlessException {
GraphicsEnvironment.checkHeadless();
Cursor cursor = systemCustomCursors.get(name);
if (cursor == null) {
synchronized(systemCustomCursors) {
if (systemCustomCursorProperties == null)
loadSystemCustomCursorProperties();
}
String prefix = CURSOR_DOT_PREFIX + name;
String key = prefix + DOT_FILE_SUFFIX;
if (!systemCustomCursorProperties.containsKey(key)) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");
}
return null;
}
final String fileName =
systemCustomCursorProperties.getProperty(key);
final String localized = systemCustomCursorProperties.getProperty(
prefix + DOT_NAME_SUFFIX, name);
String hotspot = systemCustomCursorProperties.getProperty(prefix + DOT_HOTSPOT_SUFFIX);
if (hotspot == null)
throw new AWTException("no hotspot property defined for cursor: " + name);
StringTokenizer st = new StringTokenizer(hotspot, ",");
if (st.countTokens() != 2)
throw new AWTException("failed to parse hotspot property for cursor: " + name);
final Point hotPoint;
try {
hotPoint = new Point(Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()));
} catch (NumberFormatException nfe) {
throw new AWTException("failed to parse hotspot property for cursor: " + name);
}
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final String file = RESOURCE_PREFIX + fileName;
final InputStream in = AccessController.doPrivileged(
(PrivilegedAction<InputStream>) () -> {
return Cursor.class.getResourceAsStream(file);
});
try (in) {
Image image = toolkit.createImage(in.readAllBytes());
cursor = toolkit.createCustomCursor(image, hotPoint, localized);
} catch (Exception e) {
throw new AWTException(
"Exception: " + e.getClass() + " " + e.getMessage() +
" occurred while creating cursor " + name);
}
if (cursor == null) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");
}
} else {
systemCustomCursors.put(name, cursor);
}
}
return cursor;
}
/**
* Return the system default cursor.
*
* @return the default cursor
*/
public static Cursor getDefaultCursor() {
return getPredefinedCursor(Cursor.DEFAULT_CURSOR);
}
/**
* Creates a new cursor object with the specified type.
* @param type the type of cursor
* @throws IllegalArgumentException if the specified cursor type
* is invalid
*/
@ConstructorProperties({"type"})
public Cursor(int type) {
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
throw new IllegalArgumentException("illegal cursor type");
}
this.type = type;
// Lookup localized name.
name = Toolkit.getProperty(cursorProperties[type][0],
cursorProperties[type][1]);
}
/**
* Creates a new custom cursor object with the specified name.<p>
* Note: this constructor should only be used by AWT implementations
* as part of their support for custom cursors. Applications should
* use Toolkit.createCustomCursor().
* @param name the user-visible name of the cursor.
* @see java.awt.Toolkit#createCustomCursor
*/
protected Cursor(String name) {
this.type = Cursor.CUSTOM_CURSOR;
this.name = name;
}
/**
* Returns the type for this cursor.
*
* @return the cursor type
*/
public int getType() {
return type;
}
/**
* Returns the name of this cursor.
* @return a localized description of this cursor.
* @since 1.2
*/
public String getName() {
return name;
}
/**
* Returns a string representation of this cursor.
* @return a string representation of this cursor.
* @since 1.2
*/
public String toString() {
return getClass().getName() + "[" + getName() + "]";
}
/*
* load the cursor.properties file
*/
private static void loadSystemCustomCursorProperties() throws AWTException {
synchronized(systemCustomCursors) {
systemCustomCursorProperties = new Properties();
try {
AccessController.doPrivileged(
(PrivilegedExceptionAction<Object>) () -> {
try (InputStream is = Cursor.class
.getResourceAsStream(PROPERTIES_FILE)) {
systemCustomCursorProperties.load(is);
}
return null;
});
} catch (Exception e) {
systemCustomCursorProperties = null;
throw new AWTException("Exception: " + e.getClass() + " " +
e.getMessage() + " occurred while loading: " +
PROPERTIES_FILE);
}
}
}
private static native void finalizeImpl(long pData);
}

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.ComponentPeer;
/**
* A FocusTraversalPolicy that determines traversal order based on the order
* of child Components in a Container. From a particular focus cycle root, the
* policy makes a pre-order traversal of the Component hierarchy, and traverses
* a Container's children according to the ordering of the array returned by
* {@code Container.getComponents()}. Portions of the hierarchy that are
* not visible and displayable will not be searched.
* <p>
* If client code has explicitly set the focusability of a Component by either
* overriding {@code Component.isFocusTraversable()} or
* {@code Component.isFocusable()}, or by calling
* {@code Component.setFocusable()}, then a DefaultFocusTraversalPolicy
* behaves exactly like a ContainerOrderFocusTraversalPolicy. If, however, the
* Component is relying on default focusability, then a
* DefaultFocusTraversalPolicy will reject all Components with non-focusable
* peers. This is the default FocusTraversalPolicy for all AWT Containers.
* <p>
* The focusability of a peer is implementation-dependent. Sun recommends that
* all implementations for a particular native platform construct peers with
* the same focusability. The recommendations for Windows and Unix are that
* Canvases, Labels, Panels, Scrollbars, ScrollPanes, Windows, and lightweight
* Components have non-focusable peers, and all other Components have focusable
* peers. These recommendations are used in the Sun AWT implementations. Note
* that the focusability of a Component's peer is different from, and does not
* impact, the focusability of the Component itself.
* <p>
* Please see
* <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
* How to Use the Focus Subsystem</a>,
* a section in <em>The Java Tutorial</em>, and the
* <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
* for more information.
*
* @author David Mendenhall
*
* @see Container#getComponents
* @see Component#isFocusable
* @see Component#setFocusable
* @since 1.4
*/
public class DefaultFocusTraversalPolicy
extends ContainerOrderFocusTraversalPolicy
{
/*
* serialVersionUID
*/
private static final long serialVersionUID = 8876966522510157497L;
/**
* Determines whether a Component is an acceptable choice as the new
* focus owner. The Component must be visible, displayable, and enabled
* to be accepted. If client code has explicitly set the focusability
* of the Component by either overriding
* {@code Component.isFocusTraversable()} or
* {@code Component.isFocusable()}, or by calling
* {@code Component.setFocusable()}, then the Component will be
* accepted if and only if it is focusable. If, however, the Component is
* relying on default focusability, then all Canvases, Labels, Panels,
* Scrollbars, ScrollPanes, Windows, and lightweight Components will be
* rejected.
*
* @param aComponent the Component whose fitness as a focus owner is to
* be tested
* @return {@code true} if aComponent meets the above requirements;
* {@code false} otherwise
*/
protected boolean accept(Component aComponent) {
if (!(aComponent.isVisible() && aComponent.isDisplayable() &&
aComponent.isEnabled()))
{
return false;
}
// Verify that the Component is recursively enabled. Disabling a
// heavyweight Container disables its children, whereas disabling
// a lightweight Container does not.
if (!(aComponent instanceof Window)) {
for (Container enableTest = aComponent.getParent();
enableTest != null;
enableTest = enableTest.getParent())
{
if (!(enableTest.isEnabled() || enableTest.isLightweight())) {
return false;
}
if (enableTest instanceof Window) {
break;
}
}
}
boolean focusable = aComponent.isFocusable();
if (aComponent.isFocusTraversableOverridden()) {
return focusable;
}
ComponentPeer peer = aComponent.peer;
return (peer != null && peer.isFocusable());
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,239 @@
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.Dimension2D;
import java.beans.Transient;
/**
* The {@code Dimension} class encapsulates the width and
* height of a component (in integer precision) in a single object.
* The class is
* associated with certain properties of components. Several methods
* defined by the {@code Component} class and the
* {@code LayoutManager} interface return a
* {@code Dimension} object.
* <p>
* Normally the values of {@code width}
* and {@code height} are non-negative integers.
* The constructors that allow you to create a dimension do
* not prevent you from setting a negative value for these properties.
* If the value of {@code width} or {@code height} is
* negative, the behavior of some methods defined by other objects is
* undefined.
*
* @author Sami Shaio
* @author Arthur van Hoff
* @see java.awt.Component
* @see java.awt.LayoutManager
* @since 1.0
*/
public class Dimension extends Dimension2D implements java.io.Serializable {
/**
* The width dimension; negative values can be used.
*
* @serial
* @see #getSize
* @see #setSize
* @since 1.0
*/
public int width;
/**
* The height dimension; negative values can be used.
*
* @serial
* @see #getSize
* @see #setSize
* @since 1.0
*/
public int height;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 4723952579491349524L;
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Creates an instance of {@code Dimension} with a width
* of zero and a height of zero.
*/
public Dimension() {
this(0, 0);
}
/**
* Creates an instance of {@code Dimension} whose width
* and height are the same as for the specified dimension.
*
* @param d the specified dimension for the
* {@code width} and
* {@code height} values
*/
public Dimension(Dimension d) {
this(d.width, d.height);
}
/**
* Constructs a {@code Dimension} and initializes
* it to the specified width and specified height.
*
* @param width the specified width
* @param height the specified height
*/
public Dimension(int width, int height) {
this.width = width;
this.height = height;
}
/**
* {@inheritDoc}
* @since 1.2
*/
public double getWidth() {
return width;
}
/**
* {@inheritDoc}
* @since 1.2
*/
public double getHeight() {
return height;
}
/**
* Sets the size of this {@code Dimension} object to
* the specified width and height in double precision.
* Note that if {@code width} or {@code height}
* are larger than {@code Integer.MAX_VALUE}, they will
* be reset to {@code Integer.MAX_VALUE}.
*
* @param width the new width for the {@code Dimension} object
* @param height the new height for the {@code Dimension} object
* @since 1.2
*/
public void setSize(double width, double height) {
this.width = (int) Math.ceil(width);
this.height = (int) Math.ceil(height);
}
/**
* Gets the size of this {@code Dimension} object.
* This method is included for completeness, to parallel the
* {@code getSize} method defined by {@code Component}.
*
* @return the size of this dimension, a new instance of
* {@code Dimension} with the same width and height
* @see java.awt.Dimension#setSize
* @see java.awt.Component#getSize
* @since 1.1
*/
@Transient
public Dimension getSize() {
return new Dimension(width, height);
}
/**
* Sets the size of this {@code Dimension} object to the specified size.
* This method is included for completeness, to parallel the
* {@code setSize} method defined by {@code Component}.
* @param d the new size for this {@code Dimension} object
* @see java.awt.Dimension#getSize
* @see java.awt.Component#setSize
* @since 1.1
*/
public void setSize(Dimension d) {
setSize(d.width, d.height);
}
/**
* Sets the size of this {@code Dimension} object
* to the specified width and height.
* This method is included for completeness, to parallel the
* {@code setSize} method defined by {@code Component}.
*
* @param width the new width for this {@code Dimension} object
* @param height the new height for this {@code Dimension} object
* @see java.awt.Dimension#getSize
* @see java.awt.Component#setSize
* @since 1.1
*/
public void setSize(int width, int height) {
this.width = width;
this.height = height;
}
/**
* Checks whether two dimension objects have equal values.
*/
public boolean equals(Object obj) {
if (obj instanceof Dimension) {
Dimension d = (Dimension)obj;
return (width == d.width) && (height == d.height);
}
return false;
}
/**
* Returns the hash code for this {@code Dimension}.
*
* @return a hash code for this {@code Dimension}
*/
public int hashCode() {
int sum = width + height;
return sum * (sum + 1)/2 + width;
}
/**
* Returns a string representation of the values of this
* {@code Dimension} object's {@code height} and
* {@code width} fields. This method is intended to be used only
* for debugging purposes, and the content and format of the returned
* string may vary between implementations. The returned string may be
* empty but may not be {@code null}.
*
* @return a string representation of this {@code Dimension}
* object
*/
public String toString() {
return getClass().getName() + "[width=" + width + ",height=" + height + "]";
}
}

View file

@ -0,0 +1,173 @@
/*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.lang.annotation.Native;
/**
* The {@code DisplayMode} class encapsulates the bit depth, height,
* width, and refresh rate of a {@code GraphicsDevice}. The ability to
* change graphics device's display mode is platform- and
* configuration-dependent and may not always be available
* (see {@link GraphicsDevice#isDisplayChangeSupported}).
* <p>
* For more information on full-screen exclusive mode API, see the
* <a href="http://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html">
* Full-Screen Exclusive Mode API Tutorial</a>.
*
* @see GraphicsDevice
* @see GraphicsDevice#isDisplayChangeSupported
* @see GraphicsDevice#getDisplayModes
* @see GraphicsDevice#setDisplayMode
* @author Michael Martak
* @since 1.4
*/
public final class DisplayMode {
private Dimension size;
private int bitDepth;
private int refreshRate;
/**
* Create a new display mode object with the supplied parameters.
* @param width the width of the display, in pixels
* @param height the height of the display, in pixels
* @param bitDepth the bit depth of the display, in bits per
* pixel. This can be {@code BIT_DEPTH_MULTI} if multiple
* bit depths are available.
* @param refreshRate the refresh rate of the display, in hertz.
* This can be {@code REFRESH_RATE_UNKNOWN} if the
* information is not available.
* @see #BIT_DEPTH_MULTI
* @see #REFRESH_RATE_UNKNOWN
*/
public DisplayMode(int width, int height, int bitDepth, int refreshRate) {
this.size = new Dimension(width, height);
this.bitDepth = bitDepth;
this.refreshRate = refreshRate;
}
/**
* Returns the height of the display, in pixels.
* @return the height of the display, in pixels
*/
public int getHeight() {
return size.height;
}
/**
* Returns the width of the display, in pixels.
* @return the width of the display, in pixels
*/
public int getWidth() {
return size.width;
}
/**
* Value of the bit depth if multiple bit depths are supported in this
* display mode.
* @see #getBitDepth
*/
@Native public static final int BIT_DEPTH_MULTI = -1;
/**
* Returns the bit depth of the display, in bits per pixel. This may be
* {@code BIT_DEPTH_MULTI} if multiple bit depths are supported in
* this display mode.
*
* @return the bit depth of the display, in bits per pixel.
* @see #BIT_DEPTH_MULTI
*/
public int getBitDepth() {
return bitDepth;
}
/**
* Value of the refresh rate if not known.
* @see #getRefreshRate
*/
@Native public static final int REFRESH_RATE_UNKNOWN = 0;
/**
* Returns the refresh rate of the display, in hertz. This may be
* {@code REFRESH_RATE_UNKNOWN} if the information is not available.
*
* @return the refresh rate of the display, in hertz.
* @see #REFRESH_RATE_UNKNOWN
*/
public int getRefreshRate() {
return refreshRate;
}
/**
* Returns whether the two display modes are equal.
*
* @param dm the display mode to compare to
* @return whether the two display modes are equal
*/
public boolean equals(DisplayMode dm) {
if (dm == null) {
return false;
}
return (getHeight() == dm.getHeight()
&& getWidth() == dm.getWidth()
&& getBitDepth() == dm.getBitDepth()
&& getRefreshRate() == dm.getRefreshRate());
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object dm) {
if (dm instanceof DisplayMode) {
return equals((DisplayMode)dm);
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return getWidth() + getHeight() + getBitDepth() * 7
+ getRefreshRate() * 13;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getWidth() + "x" + getHeight() + "x" +
(getBitDepth() > 0 ? getBitDepth() + "bpp": "[Multi depth]")
+ "@" + (getRefreshRate() > 0 ? getRefreshRate() + "Hz" :
"[Unknown refresh rate]");
}
}

View file

@ -0,0 +1,881 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* {@code Event} is a platform-independent class that
* encapsulates events from the platform's Graphical User
* Interface in the Java&nbsp;1.0 event model. In Java&nbsp;1.1
* and later versions, the {@code Event} class is maintained
* only for backwards compatibility. The information in this
* class description is provided to assist programmers in
* converting Java&nbsp;1.0 programs to the new event model.
* <p>
* In the Java&nbsp;1.0 event model, an event contains an
* {@link Event#id} field
* that indicates what type of event it is and which other
* {@code Event} variables are relevant for the event.
* <p>
* For keyboard events, {@link Event#key}
* contains a value indicating which key was activated, and
* {@link Event#modifiers} contains the
* modifiers for that event. For the KEY_PRESS and KEY_RELEASE
* event ids, the value of {@code key} is the unicode
* character code for the key. For KEY_ACTION and
* KEY_ACTION_RELEASE, the value of {@code key} is
* one of the defined action-key identifiers in the
* {@code Event} class ({@code PGUP},
* {@code PGDN}, {@code F1}, {@code F2}, etc).
*
* @deprecated It is recommended that {@code AWTEvent} and its subclasses be
* used instead
* @author Sami Shaio
* @since 1.0
*/
@Deprecated(since = "9")
public class Event implements java.io.Serializable {
private transient long data;
/* Modifier constants */
/**
* This flag indicates that the Shift key was down when the event
* occurred.
*/
public static final int SHIFT_MASK = 1 << 0;
/**
* This flag indicates that the Control key was down when the event
* occurred.
*/
public static final int CTRL_MASK = 1 << 1;
/**
* This flag indicates that the Meta key was down when the event
* occurred. For mouse events, this flag indicates that the right
* button was pressed or released.
*/
public static final int META_MASK = 1 << 2;
/**
* This flag indicates that the Alt key was down when
* the event occurred. For mouse events, this flag indicates that the
* middle mouse button was pressed or released.
*/
public static final int ALT_MASK = 1 << 3;
/* Action keys */
/**
* The Home key, a non-ASCII action key.
*/
public static final int HOME = 1000;
/**
* The End key, a non-ASCII action key.
*/
public static final int END = 1001;
/**
* The Page Up key, a non-ASCII action key.
*/
public static final int PGUP = 1002;
/**
* The Page Down key, a non-ASCII action key.
*/
public static final int PGDN = 1003;
/**
* The Up Arrow key, a non-ASCII action key.
*/
public static final int UP = 1004;
/**
* The Down Arrow key, a non-ASCII action key.
*/
public static final int DOWN = 1005;
/**
* The Left Arrow key, a non-ASCII action key.
*/
public static final int LEFT = 1006;
/**
* The Right Arrow key, a non-ASCII action key.
*/
public static final int RIGHT = 1007;
/**
* The F1 function key, a non-ASCII action key.
*/
public static final int F1 = 1008;
/**
* The F2 function key, a non-ASCII action key.
*/
public static final int F2 = 1009;
/**
* The F3 function key, a non-ASCII action key.
*/
public static final int F3 = 1010;
/**
* The F4 function key, a non-ASCII action key.
*/
public static final int F4 = 1011;
/**
* The F5 function key, a non-ASCII action key.
*/
public static final int F5 = 1012;
/**
* The F6 function key, a non-ASCII action key.
*/
public static final int F6 = 1013;
/**
* The F7 function key, a non-ASCII action key.
*/
public static final int F7 = 1014;
/**
* The F8 function key, a non-ASCII action key.
*/
public static final int F8 = 1015;
/**
* The F9 function key, a non-ASCII action key.
*/
public static final int F9 = 1016;
/**
* The F10 function key, a non-ASCII action key.
*/
public static final int F10 = 1017;
/**
* The F11 function key, a non-ASCII action key.
*/
public static final int F11 = 1018;
/**
* The F12 function key, a non-ASCII action key.
*/
public static final int F12 = 1019;
/**
* The Print Screen key, a non-ASCII action key.
*/
public static final int PRINT_SCREEN = 1020;
/**
* The Scroll Lock key, a non-ASCII action key.
*/
public static final int SCROLL_LOCK = 1021;
/**
* The Caps Lock key, a non-ASCII action key.
*/
public static final int CAPS_LOCK = 1022;
/**
* The Num Lock key, a non-ASCII action key.
*/
public static final int NUM_LOCK = 1023;
/**
* The Pause key, a non-ASCII action key.
*/
public static final int PAUSE = 1024;
/**
* The Insert key, a non-ASCII action key.
*/
public static final int INSERT = 1025;
/* Non-action keys */
/**
* The Enter key.
*/
public static final int ENTER = '\n';
/**
* The BackSpace key.
*/
public static final int BACK_SPACE = '\b';
/**
* The Tab key.
*/
public static final int TAB = '\t';
/**
* The Escape key.
*/
public static final int ESCAPE = 27;
/**
* The Delete key.
*/
public static final int DELETE = 127;
/* Base for all window events. */
private static final int WINDOW_EVENT = 200;
/**
* The user has asked the window manager to kill the window.
*/
public static final int WINDOW_DESTROY = 1 + WINDOW_EVENT;
/**
* The user has asked the window manager to expose the window.
*/
public static final int WINDOW_EXPOSE = 2 + WINDOW_EVENT;
/**
* The user has asked the window manager to iconify the window.
*/
public static final int WINDOW_ICONIFY = 3 + WINDOW_EVENT;
/**
* The user has asked the window manager to de-iconify the window.
*/
public static final int WINDOW_DEICONIFY = 4 + WINDOW_EVENT;
/**
* The user has asked the window manager to move the window.
*/
public static final int WINDOW_MOVED = 5 + WINDOW_EVENT;
/* Base for all keyboard events. */
private static final int KEY_EVENT = 400;
/**
* The user has pressed a normal key.
*/
public static final int KEY_PRESS = 1 + KEY_EVENT;
/**
* The user has released a normal key.
*/
public static final int KEY_RELEASE = 2 + KEY_EVENT;
/**
* The user has pressed a non-ASCII <em>action</em> key.
* The {@code key} field contains a value that indicates
* that the event occurred on one of the action keys, which
* comprise the 12 function keys, the arrow (cursor) keys,
* Page Up, Page Down, Home, End, Print Screen, Scroll Lock,
* Caps Lock, Num Lock, Pause, and Insert.
*/
public static final int KEY_ACTION = 3 + KEY_EVENT;
/**
* The user has released a non-ASCII <em>action</em> key.
* The {@code key} field contains a value that indicates
* that the event occurred on one of the action keys, which
* comprise the 12 function keys, the arrow (cursor) keys,
* Page Up, Page Down, Home, End, Print Screen, Scroll Lock,
* Caps Lock, Num Lock, Pause, and Insert.
*/
public static final int KEY_ACTION_RELEASE = 4 + KEY_EVENT;
/* Base for all mouse events. */
private static final int MOUSE_EVENT = 500;
/**
* The user has pressed the mouse button. The {@code ALT_MASK}
* flag indicates that the middle button has been pressed.
* The {@code META_MASK} flag indicates that the
* right button has been pressed.
* @see java.awt.Event#ALT_MASK
* @see java.awt.Event#META_MASK
*/
public static final int MOUSE_DOWN = 1 + MOUSE_EVENT;
/**
* The user has released the mouse button. The {@code ALT_MASK}
* flag indicates that the middle button has been released.
* The {@code META_MASK} flag indicates that the
* right button has been released.
* @see java.awt.Event#ALT_MASK
* @see java.awt.Event#META_MASK
*/
public static final int MOUSE_UP = 2 + MOUSE_EVENT;
/**
* The mouse has moved with no button pressed.
*/
public static final int MOUSE_MOVE = 3 + MOUSE_EVENT;
/**
* The mouse has entered a component.
*/
public static final int MOUSE_ENTER = 4 + MOUSE_EVENT;
/**
* The mouse has exited a component.
*/
public static final int MOUSE_EXIT = 5 + MOUSE_EVENT;
/**
* The user has moved the mouse with a button pressed. The
* {@code ALT_MASK} flag indicates that the middle
* button is being pressed. The {@code META_MASK} flag indicates
* that the right button is being pressed.
* @see java.awt.Event#ALT_MASK
* @see java.awt.Event#META_MASK
*/
public static final int MOUSE_DRAG = 6 + MOUSE_EVENT;
/* Scrolling events */
private static final int SCROLL_EVENT = 600;
/**
* The user has activated the <em>line up</em>
* area of a scroll bar.
*/
public static final int SCROLL_LINE_UP = 1 + SCROLL_EVENT;
/**
* The user has activated the <em>line down</em>
* area of a scroll bar.
*/
public static final int SCROLL_LINE_DOWN = 2 + SCROLL_EVENT;
/**
* The user has activated the <em>page up</em>
* area of a scroll bar.
*/
public static final int SCROLL_PAGE_UP = 3 + SCROLL_EVENT;
/**
* The user has activated the <em>page down</em>
* area of a scroll bar.
*/
public static final int SCROLL_PAGE_DOWN = 4 + SCROLL_EVENT;
/**
* The user has moved the bubble (thumb) in a scroll bar,
* moving to an "absolute" position, rather than to
* an offset from the last position.
*/
public static final int SCROLL_ABSOLUTE = 5 + SCROLL_EVENT;
/**
* The scroll begin event.
*/
public static final int SCROLL_BEGIN = 6 + SCROLL_EVENT;
/**
* The scroll end event.
*/
public static final int SCROLL_END = 7 + SCROLL_EVENT;
/* List Events */
private static final int LIST_EVENT = 700;
/**
* An item in a list has been selected.
*/
public static final int LIST_SELECT = 1 + LIST_EVENT;
/**
* An item in a list has been deselected.
*/
public static final int LIST_DESELECT = 2 + LIST_EVENT;
/* Misc Event */
private static final int MISC_EVENT = 1000;
/**
* This event indicates that the user wants some action to occur.
*/
public static final int ACTION_EVENT = 1 + MISC_EVENT;
/**
* A file loading event.
*/
public static final int LOAD_FILE = 2 + MISC_EVENT;
/**
* A file saving event.
*/
public static final int SAVE_FILE = 3 + MISC_EVENT;
/**
* A component gained the focus.
*/
public static final int GOT_FOCUS = 4 + MISC_EVENT;
/**
* A component lost the focus.
*/
public static final int LOST_FOCUS = 5 + MISC_EVENT;
/**
* The target component. This indicates the component over which the
* event occurred or with which the event is associated.
* This object has been replaced by AWTEvent.getSource()
*
* @serial
* @see java.awt.AWTEvent#getSource()
*/
public Object target;
/**
* The time stamp.
* Replaced by InputEvent.getWhen().
*
* @serial
* @see java.awt.event.InputEvent#getWhen()
*/
public long when;
/**
* Indicates which type of event the event is, and which
* other {@code Event} variables are relevant for the event.
* This has been replaced by AWTEvent.getID()
*
* @serial
* @see java.awt.AWTEvent#getID()
*/
public int id;
/**
* The <i>x</i> coordinate of the event.
* Replaced by MouseEvent.getX()
*
* @serial
* @see java.awt.event.MouseEvent#getX()
*/
public int x;
/**
* The <i>y</i> coordinate of the event.
* Replaced by MouseEvent.getY()
*
* @serial
* @see java.awt.event.MouseEvent#getY()
*/
public int y;
/**
* The key code of the key that was pressed in a keyboard event.
* This has been replaced by KeyEvent.getKeyCode()
*
* @serial
* @see java.awt.event.KeyEvent#getKeyCode()
*/
public int key;
/**
* The key character that was pressed in a keyboard event.
*/
// public char keyChar;
/**
* The state of the modifier keys.
* This is replaced with InputEvent.getModifiers()
* In java 1.1 MouseEvent and KeyEvent are subclasses
* of InputEvent.
*
* @serial
* @see java.awt.event.InputEvent#getModifiers()
*/
public int modifiers;
/**
* For {@code MOUSE_DOWN} events, this field indicates the
* number of consecutive clicks. For other events, its value is
* {@code 0}.
* This field has been replaced by MouseEvent.getClickCount().
*
* @serial
* @see java.awt.event.MouseEvent#getClickCount()
*/
public int clickCount;
/**
* An arbitrary argument of the event. The value of this field
* depends on the type of event.
* {@code arg} has been replaced by event specific property.
*
* @serial
*/
public Object arg;
/**
* The next event. This field is set when putting events into a
* linked list.
* This has been replaced by EventQueue.
*
* @serial
* @see java.awt.EventQueue
*/
public Event evt;
/* table for mapping old Event action keys to KeyEvent virtual keys. */
private static final int actionKeyCodes[][] = {
/* virtual key action key */
{ KeyEvent.VK_HOME, Event.HOME },
{ KeyEvent.VK_END, Event.END },
{ KeyEvent.VK_PAGE_UP, Event.PGUP },
{ KeyEvent.VK_PAGE_DOWN, Event.PGDN },
{ KeyEvent.VK_UP, Event.UP },
{ KeyEvent.VK_DOWN, Event.DOWN },
{ KeyEvent.VK_LEFT, Event.LEFT },
{ KeyEvent.VK_RIGHT, Event.RIGHT },
{ KeyEvent.VK_F1, Event.F1 },
{ KeyEvent.VK_F2, Event.F2 },
{ KeyEvent.VK_F3, Event.F3 },
{ KeyEvent.VK_F4, Event.F4 },
{ KeyEvent.VK_F5, Event.F5 },
{ KeyEvent.VK_F6, Event.F6 },
{ KeyEvent.VK_F7, Event.F7 },
{ KeyEvent.VK_F8, Event.F8 },
{ KeyEvent.VK_F9, Event.F9 },
{ KeyEvent.VK_F10, Event.F10 },
{ KeyEvent.VK_F11, Event.F11 },
{ KeyEvent.VK_F12, Event.F12 },
{ KeyEvent.VK_PRINTSCREEN, Event.PRINT_SCREEN },
{ KeyEvent.VK_SCROLL_LOCK, Event.SCROLL_LOCK },
{ KeyEvent.VK_CAPS_LOCK, Event.CAPS_LOCK },
{ KeyEvent.VK_NUM_LOCK, Event.NUM_LOCK },
{ KeyEvent.VK_PAUSE, Event.PAUSE },
{ KeyEvent.VK_INSERT, Event.INSERT }
};
/**
* This field controls whether or not the event is sent back
* down to the peer once the target has processed it -
* false means it's sent to the peer, true means it's not.
*
* @serial
* @see #isConsumed()
*/
private boolean consumed = false;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 5488922509400504703L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Initialize JNI field and method IDs for fields that may be
accessed from C.
*/
private static native void initIDs();
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Creates an instance of {@code Event} with the specified target
* component, time stamp, event type, <i>x</i> and <i>y</i>
* coordinates, keyboard key, state of the modifier keys, and
* argument.
* @param target the target component.
* @param when the time stamp.
* @param id the event type.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @param key the key pressed in a keyboard event.
* @param modifiers the state of the modifier keys.
* @param arg the specified argument.
*/
public Event(Object target, long when, int id, int x, int y, int key,
int modifiers, Object arg) {
this.target = target;
this.when = when;
this.id = id;
this.x = x;
this.y = y;
this.key = key;
this.modifiers = modifiers;
this.arg = arg;
this.data = 0;
this.clickCount = 0;
switch(id) {
case ACTION_EVENT:
case WINDOW_DESTROY:
case WINDOW_ICONIFY:
case WINDOW_DEICONIFY:
case WINDOW_MOVED:
case SCROLL_LINE_UP:
case SCROLL_LINE_DOWN:
case SCROLL_PAGE_UP:
case SCROLL_PAGE_DOWN:
case SCROLL_ABSOLUTE:
case SCROLL_BEGIN:
case SCROLL_END:
case LIST_SELECT:
case LIST_DESELECT:
consumed = true; // these types are not passed back to peer
break;
default:
}
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Creates an instance of {@code Event}, with the specified target
* component, time stamp, event type, <i>x</i> and <i>y</i>
* coordinates, keyboard key, state of the modifier keys, and an
* argument set to {@code null}.
* @param target the target component.
* @param when the time stamp.
* @param id the event type.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @param key the key pressed in a keyboard event.
* @param modifiers the state of the modifier keys.
*/
public Event(Object target, long when, int id, int x, int y, int key, int modifiers) {
this(target, when, id, x, y, key, modifiers, null);
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Creates an instance of {@code Event} with the specified
* target component, event type, and argument.
* @param target the target component.
* @param id the event type.
* @param arg the specified argument.
*/
public Event(Object target, int id, Object arg) {
this(target, 0, id, 0, 0, 0, 0, arg);
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Translates this event so that its <i>x</i> and <i>y</i>
* coordinates are increased by <i>dx</i> and <i>dy</i>,
* respectively.
* <p>
* This method translates an event relative to the given component.
* This involves, at a minimum, translating the coordinates into the
* local coordinate system of the given component. It may also involve
* translating a region in the case of an expose event.
* @param dx the distance to translate the <i>x</i> coordinate.
* @param dy the distance to translate the <i>y</i> coordinate.
*/
public void translate(int dx, int dy) {
this.x += dx;
this.y += dy;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Checks if the Shift key is down.
* @return {@code true} if the key is down;
* {@code false} otherwise.
* @see java.awt.Event#modifiers
* @see java.awt.Event#controlDown
* @see java.awt.Event#metaDown
*/
public boolean shiftDown() {
return (modifiers & SHIFT_MASK) != 0;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Checks if the Control key is down.
* @return {@code true} if the key is down;
* {@code false} otherwise.
* @see java.awt.Event#modifiers
* @see java.awt.Event#shiftDown
* @see java.awt.Event#metaDown
*/
public boolean controlDown() {
return (modifiers & CTRL_MASK) != 0;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Checks if the Meta key is down.
*
* @return {@code true} if the key is down;
* {@code false} otherwise.
* @see java.awt.Event#modifiers
* @see java.awt.Event#shiftDown
* @see java.awt.Event#controlDown
*/
public boolean metaDown() {
return (modifiers & META_MASK) != 0;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
*/
void consume() {
switch(id) {
case KEY_PRESS:
case KEY_RELEASE:
case KEY_ACTION:
case KEY_ACTION_RELEASE:
consumed = true;
break;
default:
// event type cannot be consumed
}
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
*/
boolean isConsumed() {
return consumed;
}
/*
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Returns the integer key-code associated with the key in this event,
* as described in java.awt.Event.
*/
static int getOldEventKey(KeyEvent e) {
int keyCode = e.getKeyCode();
for (int i = 0; i < actionKeyCodes.length; i++) {
if (actionKeyCodes[i][0] == keyCode) {
return actionKeyCodes[i][1];
}
}
return (int)e.getKeyChar();
}
/*
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Returns a new KeyEvent char which corresponds to the int key
* of this old event.
*/
char getKeyEventChar() {
for (int i = 0; i < actionKeyCodes.length; i++) {
if (actionKeyCodes[i][1] == key) {
return KeyEvent.CHAR_UNDEFINED;
}
}
return (char)key;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Returns a string representing the state of this {@code Event}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this event
*/
protected String paramString() {
String str = "id=" + id + ",x=" + x + ",y=" + y;
if (key != 0) {
str += ",key=" + key;
}
if (shiftDown()) {
str += ",shift";
}
if (controlDown()) {
str += ",control";
}
if (metaDown()) {
str += ",meta";
}
if (target != null) {
str += ",target=" + target;
}
if (arg != null) {
str += ",arg=" + arg;
}
return str;
}
/**
* <b>NOTE:</b> The {@code Event} class is obsolete and is
* available only for backwards compatibility. It has been replaced
* by the {@code AWTEvent} class and its subclasses.
* <p>
* Returns a representation of this event's values as a string.
* @return a string that represents the event and the values
* of its member fields.
* @see java.awt.Event#paramString
* @since 1.1
*/
public String toString() {
return getClass().getName() + "[" + paramString() + "]";
}
}

View file

@ -0,0 +1,291 @@
/*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.MouseEvent;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import sun.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer;
/**
* EventDispatchThread is a package-private AWT class which takes
* events off the EventQueue and dispatches them to the appropriate
* AWT components.
*
* The Thread starts a "permanent" event pump with a call to
* pumpEvents(Conditional) in its run() method. Event handlers can choose to
* block this event pump at any time, but should start a new pump (<b>not</b>
* a new EventDispatchThread) by again calling pumpEvents(Conditional). This
* secondary event pump will exit automatically as soon as the Conditional
* evaluate()s to false and an additional Event is pumped and dispatched.
*
* @author Tom Ball
* @author Amy Fowler
* @author Fred Ecks
* @author David Mendenhall
*
* @since 1.1
*/
class EventDispatchThread extends Thread {
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
private EventQueue theQueue;
private volatile boolean doDispatch = true;
private static final int ANY_EVENT = -1;
private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();
/**
* Must always call 5 args super-class constructor passing false
* to indicate not to inherit locals.
*/
private EventDispatchThread() {
throw new UnsupportedOperationException("Must erase locals");
}
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
super(group, null, name, 0, false);
setEventQueue(queue);
}
/*
* Must be called on EDT only, that's why no synchronization
*/
public void stopDispatching() {
doDispatch = false;
}
public void run() {
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
return true;
}
});
} finally {
getEventQueue().detachDispatchThread(this);
}
}
void pumpEvents(Conditional cond) {
pumpEvents(ANY_EVENT, cond);
}
void pumpEventsForHierarchy(Conditional cond, Component modalComponent) {
pumpEventsForHierarchy(ANY_EVENT, cond, modalComponent);
}
void pumpEvents(int id, Conditional cond) {
pumpEventsForHierarchy(id, cond, null);
}
void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {
pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));
}
void pumpEventsForFilter(Conditional cond, EventFilter filter) {
pumpEventsForFilter(ANY_EVENT, cond, filter);
}
void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
addEventFilter(filter);
doDispatch = true;
while (doDispatch && !isInterrupted() && cond.evaluate()) {
pumpOneEventForFilters(id);
}
removeEventFilter(filter);
}
void addEventFilter(EventFilter filter) {
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
eventLog.finest("adding the event filter: " + filter);
}
synchronized (eventFilters) {
if (!eventFilters.contains(filter)) {
if (filter instanceof ModalEventFilter) {
ModalEventFilter newFilter = (ModalEventFilter)filter;
int k = 0;
for (k = 0; k < eventFilters.size(); k++) {
EventFilter f = eventFilters.get(k);
if (f instanceof ModalEventFilter) {
ModalEventFilter cf = (ModalEventFilter)f;
if (cf.compareTo(newFilter) > 0) {
break;
}
}
}
eventFilters.add(k, filter);
} else {
eventFilters.add(filter);
}
}
}
}
void removeEventFilter(EventFilter filter) {
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
eventLog.finest("removing the event filter: " + filter);
}
synchronized (eventFilters) {
eventFilters.remove(filter);
}
}
boolean filterAndCheckEvent(AWTEvent event) {
boolean eventOK = true;
synchronized (eventFilters) {
for (int i = eventFilters.size() - 1; i >= 0; i--) {
EventFilter f = eventFilters.get(i);
EventFilter.FilterAction accept = f.acceptEvent(event);
if (accept == EventFilter.FilterAction.REJECT) {
eventOK = false;
break;
} else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {
break;
}
}
}
return eventOK && SunDragSourceContextPeer.checkEvent(event);
}
void pumpOneEventForFilters(int id) {
AWTEvent event = null;
boolean eventOK = false;
try {
EventQueue eq = null;
do {
// EventQueue may change during the dispatching
eq = getEventQueue();
event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
eventOK = filterAndCheckEvent(event);
if (!eventOK) {
event.consume();
}
}
while (eventOK == false);
if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
eventLog.finest("Dispatching: " + event);
}
eq.dispatchEvent(event);
}
catch (ThreadDeath death) {
doDispatch = false;
throw death;
}
catch (InterruptedException interruptedException) {
doDispatch = false; // AppContext.dispose() interrupts all
// Threads in the AppContext
}
catch (Throwable e) {
processException(e);
}
}
private void processException(Throwable e) {
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
eventLog.fine("Processing exception: " + e);
}
getUncaughtExceptionHandler().uncaughtException(this, e);
}
public synchronized EventQueue getEventQueue() {
return theQueue;
}
public synchronized void setEventQueue(EventQueue eq) {
theQueue = eq;
}
private static class HierarchyEventFilter implements EventFilter {
private Component modalComponent;
public HierarchyEventFilter(Component modalComponent) {
this.modalComponent = modalComponent;
}
public FilterAction acceptEvent(AWTEvent event) {
if (modalComponent != null) {
int eventID = event.getID();
boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&
(eventID <= MouseEvent.MOUSE_LAST);
boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&
(eventID <= ActionEvent.ACTION_LAST);
boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);
/*
* filter out MouseEvent and ActionEvent that's outside
* the modalComponent hierarchy.
* KeyEvent is handled by using enqueueKeyEvent
* in Dialog.show
*/
if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {
/*
* Modal internal frames are handled separately. If event is
* for some component from another heavyweight than modalComp,
* it is accepted. If heavyweight is the same - we still accept
* event and perform further filtering in LightweightDispatcher
*/
return windowClosingEvent ? FilterAction.REJECT : FilterAction.ACCEPT;
}
if (mouseEvent || actionEvent || windowClosingEvent) {
Object o = event.getSource();
if (o instanceof sun.awt.ModalExclude) {
// Exclude this object from modality and
// continue to pump it's events.
return FilterAction.ACCEPT;
} else if (o instanceof Component) {
Component c = (Component) o;
// 5.0u3 modal exclusion
boolean modalExcluded = false;
if (modalComponent instanceof Container) {
while (c != modalComponent && c != null) {
if ((c instanceof Window) &&
(sun.awt.SunToolkit.isModalExcluded((Window)c))) {
// Exclude this window and all its children from
// modality and continue to pump it's events.
modalExcluded = true;
break;
}
c = c.getParent();
}
}
if (!modalExcluded && (c != modalComponent)) {
return FilterAction.REJECT;
}
}
}
}
return FilterAction.ACCEPT;
}
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
interface EventFilter {
/**
* Enumeration for possible values for {@code acceptEvent(AWTEvent ev)} method.
* @see EventDispatchThread#pumpEventsForFilter
*/
static enum FilterAction {
/**
* ACCEPT means that this filter do not filter the event and allows other
* active filters to proceed it. If all the active filters accept the event, it
* is dispatched by the {@code EventDispatchThread}
* @see EventDispatchThread#pumpEventsForFilter
*/
ACCEPT,
/**
* REJECT means that this filter filter the event. No other filters are queried,
* and the event is not dispatched by the {@code EventDispatchedThread}
* @see EventDispatchThread#pumpEventsForFilter
*/
REJECT,
/**
* ACCEPT_IMMEDIATELY means that this filter do not filter the event, no other
* filters are queried and to proceed it, and it is dispatched by the
* {@code EventDispatchThread}
* It is not recommended to use ACCEPT_IMMEDIATELY as there may be some active
* filters not queried yet that do not accept this event. It is primarily used
* by modal filters.
* @see EventDispatchThread#pumpEventsForFilter
* @see ModalEventFilter
*/
ACCEPT_IMMEDIATELY
};
FilterAction acceptEvent(AWTEvent ev);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,635 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.FileDialogPeer;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.File;
import sun.awt.AWTAccessor;
/**
* The {@code FileDialog} class displays a dialog window
* from which the user can select a file.
* <p>
* Since it is a modal dialog, when the application calls
* its {@code show} method to display the dialog,
* it blocks the rest of the application until the user has
* chosen a file.
*
* @see Window#show
*
* @author Sami Shaio
* @author Arthur van Hoff
* @since 1.0
*/
public class FileDialog extends Dialog {
/**
* This constant value indicates that the purpose of the file
* dialog window is to locate a file from which to read.
*/
public static final int LOAD = 0;
/**
* This constant value indicates that the purpose of the file
* dialog window is to locate a file to which to write.
*/
public static final int SAVE = 1;
/*
* There are two {@code FileDialog} modes: {@code LOAD} and
* {@code SAVE}.
* This integer will represent one or the other.
* If the mode is not specified it will default to {@code LOAD}.
*
* @serial
* @see getMode()
* @see setMode()
* @see java.awt.FileDialog#LOAD
* @see java.awt.FileDialog#SAVE
*/
int mode;
/*
* The string specifying the directory to display
* in the file dialog. This variable may be {@code null}.
*
* @serial
* @see getDirectory()
* @see setDirectory()
*/
String dir;
/*
* The string specifying the initial value of the
* filename text field in the file dialog.
* This variable may be {@code null}.
*
* @serial
* @see getFile()
* @see setFile()
*/
String file;
/**
* Contains the File instances for all the files that the user selects.
*
* @serial
* @see #getFiles
* @since 1.7
*/
private File[] files;
/**
* Represents whether the file dialog allows the multiple file selection.
*
* @serial
* @see #setMultipleMode
* @see #isMultipleMode
* @since 1.7
*/
private boolean multipleMode = false;
/*
* The filter used as the file dialog's filename filter.
* The file dialog will only be displaying files whose
* names are accepted by this filter.
* This variable may be {@code null}.
*
* @serial
* @see #getFilenameFilter()
* @see #setFilenameFilter()
* @see FileNameFilter
*/
FilenameFilter filter;
private static final String base = "filedlg";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 5035145889651310422L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
static {
AWTAccessor.setFileDialogAccessor(
new AWTAccessor.FileDialogAccessor() {
public void setFiles(FileDialog fileDialog, File files[]) {
fileDialog.setFiles(files);
}
public void setFile(FileDialog fileDialog, String file) {
fileDialog.file = ("".equals(file)) ? null : file;
}
public void setDirectory(FileDialog fileDialog, String directory) {
fileDialog.dir = ("".equals(directory)) ? null : directory;
}
public boolean isMultipleMode(FileDialog fileDialog) {
synchronized (fileDialog.getObjectLock()) {
return fileDialog.multipleMode;
}
}
});
}
/**
* Initialize JNI field and method IDs for fields that may be
accessed from C.
*/
private static native void initIDs();
/**
* Creates a file dialog for loading a file. The title of the
* file dialog is initially empty. This is a convenience method for
* {@code FileDialog(parent, "", LOAD)}.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @since 1.1
*/
public FileDialog(Frame parent) {
this(parent, "", LOAD);
}
/**
* Creates a file dialog window with the specified title for loading
* a file. The files shown are those in the current directory.
* This is a convenience method for
* {@code FileDialog(parent, title, LOAD)}.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @param title the title of the dialog
*/
public FileDialog(Frame parent, String title) {
this(parent, title, LOAD);
}
/**
* Creates a file dialog window with the specified title for loading
* or saving a file.
* <p>
* If the value of {@code mode} is {@code LOAD}, then the
* file dialog is finding a file to read, and the files shown are those
* in the current directory. If the value of
* {@code mode} is {@code SAVE}, the file dialog is finding
* a place to write a file.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @param title the title of the dialog
* @param mode the mode of the dialog; either
* {@code FileDialog.LOAD} or {@code FileDialog.SAVE}
* @exception IllegalArgumentException if an illegal file
* dialog mode is supplied
* @see java.awt.FileDialog#LOAD
* @see java.awt.FileDialog#SAVE
*/
public FileDialog(Frame parent, String title, int mode) {
super(parent, title, true);
this.setMode(mode);
setLayout(null);
}
/**
* Creates a file dialog for loading a file. The title of the
* file dialog is initially empty. This is a convenience method for
* {@code FileDialog(parent, "", LOAD)}.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @exception java.lang.IllegalArgumentException if the {@code parent}'s
* {@code GraphicsConfiguration}
* is not from a screen device;
* @exception java.lang.IllegalArgumentException if {@code parent}
* is {@code null}; this exception is always thrown when
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.5
*/
public FileDialog(Dialog parent) {
this(parent, "", LOAD);
}
/**
* Creates a file dialog window with the specified title for loading
* a file. The files shown are those in the current directory.
* This is a convenience method for
* {@code FileDialog(parent, title, LOAD)}.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @param title the title of the dialog; a {@code null} value
* will be accepted without causing a
* {@code NullPointerException} to be thrown
* @exception java.lang.IllegalArgumentException if the {@code parent}'s
* {@code GraphicsConfiguration}
* is not from a screen device;
* @exception java.lang.IllegalArgumentException if {@code parent}
* is {@code null}; this exception is always thrown when
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.5
*/
public FileDialog(Dialog parent, String title) {
this(parent, title, LOAD);
}
/**
* Creates a file dialog window with the specified title for loading
* or saving a file.
* <p>
* If the value of {@code mode} is {@code LOAD}, then the
* file dialog is finding a file to read, and the files shown are those
* in the current directory. If the value of
* {@code mode} is {@code SAVE}, the file dialog is finding
* a place to write a file.
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*
* @param parent the owner of the dialog
* @param title the title of the dialog; a {@code null} value
* will be accepted without causing a
* {@code NullPointerException} to be thrown
* @param mode the mode of the dialog; either
* {@code FileDialog.LOAD} or {@code FileDialog.SAVE}
* @exception java.lang.IllegalArgumentException if an illegal
* file dialog mode is supplied;
* @exception java.lang.IllegalArgumentException if the {@code parent}'s
* {@code GraphicsConfiguration}
* is not from a screen device;
* @exception java.lang.IllegalArgumentException if {@code parent}
* is {@code null}; this exception is always thrown when
* {@code GraphicsEnvironment.isHeadless}
* returns {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @see java.awt.FileDialog#LOAD
* @see java.awt.FileDialog#SAVE
* @since 1.5
*/
public FileDialog(Dialog parent, String title, int mode) {
super(parent, title, true);
this.setMode(mode);
setLayout(null);
}
/**
* {@inheritDoc}
* <p>
* <strong>Note:</strong> Some platforms may not support
* showing the user-specified title in a file dialog.
* In this situation, either no title will be displayed in the file dialog's
* title bar or, on some systems, the file dialog's title bar will not be
* displayed.
*/
@Override
public void setTitle(String title) {
super.setTitle(title);
}
/**
* Constructs a name for this component. Called by {@code getName()}
* when the name is {@code null}.
*/
String constructComponentName() {
synchronized (FileDialog.class) {
return base + nameCounter++;
}
}
/**
* Creates the file dialog's peer. The peer allows us to change the look
* of the file dialog without changing its functionality.
*/
public void addNotify() {
synchronized(getTreeLock()) {
if (parent != null && parent.peer == null) {
parent.addNotify();
}
if (peer == null)
peer = getComponentFactory().createFileDialog(this);
super.addNotify();
}
}
/**
* Indicates whether this file dialog box is for loading from a file
* or for saving to a file.
*
* @return the mode of this file dialog window, either
* {@code FileDialog.LOAD} or
* {@code FileDialog.SAVE}
* @see java.awt.FileDialog#LOAD
* @see java.awt.FileDialog#SAVE
* @see java.awt.FileDialog#setMode
*/
public int getMode() {
return mode;
}
/**
* Sets the mode of the file dialog. If {@code mode} is not
* a legal value, an exception will be thrown and {@code mode}
* will not be set.
*
* @param mode the mode for this file dialog, either
* {@code FileDialog.LOAD} or
* {@code FileDialog.SAVE}
* @see java.awt.FileDialog#LOAD
* @see java.awt.FileDialog#SAVE
* @see java.awt.FileDialog#getMode
* @exception IllegalArgumentException if an illegal file
* dialog mode is supplied
* @since 1.1
*/
public void setMode(int mode) {
switch (mode) {
case LOAD:
case SAVE:
this.mode = mode;
break;
default:
throw new IllegalArgumentException("illegal file dialog mode");
}
}
/**
* Gets the directory of this file dialog.
*
* @return the (potentially {@code null} or invalid)
* directory of this {@code FileDialog}
* @see java.awt.FileDialog#setDirectory
*/
public String getDirectory() {
return dir;
}
/**
* Sets the directory of this file dialog window to be the
* specified directory. Specifying a {@code null} or an
* invalid directory implies an implementation-defined default.
* This default will not be realized, however, until the user
* has selected a file. Until this point, {@code getDirectory()}
* will return the value passed into this method.
* <p>
* Specifying "" as the directory is exactly equivalent to
* specifying {@code null} as the directory.
*
* @param dir the specified directory
* @see java.awt.FileDialog#getDirectory
*/
public void setDirectory(String dir) {
this.dir = (dir != null && dir.equals("")) ? null : dir;
FileDialogPeer peer = (FileDialogPeer)this.peer;
if (peer != null) {
peer.setDirectory(this.dir);
}
}
/**
* Gets the selected file of this file dialog. If the user
* selected {@code CANCEL}, the returned file is {@code null}.
*
* @return the currently selected file of this file dialog window,
* or {@code null} if none is selected
* @see java.awt.FileDialog#setFile
*/
public String getFile() {
return file;
}
/**
* Returns files that the user selects.
* <p>
* If the user cancels the file dialog,
* then the method returns an empty array.
*
* @return files that the user selects or an empty array
* if the user cancels the file dialog.
* @see #setFile(String)
* @see #getFile
* @since 1.7
*/
public File[] getFiles() {
synchronized (getObjectLock()) {
if (files != null) {
return files.clone();
} else {
return new File[0];
}
}
}
/**
* Stores the names of all the files that the user selects.
*
* Note that the method is private and it's intended to be used
* by the peers through the AWTAccessor API.
*
* @param files the array that contains the short names of
* all the files that the user selects.
*
* @see #getFiles
* @since 1.7
*/
private void setFiles(File files[]) {
synchronized (getObjectLock()) {
this.files = files;
}
}
/**
* Sets the selected file for this file dialog window to be the
* specified file. This file becomes the default file if it is set
* before the file dialog window is first shown.
* <p>
* When the dialog is shown, the specified file is selected. The kind of
* selection depends on the file existence, the dialog type, and the native
* platform. E.g., the file could be highlighted in the file list, or a
* file name editbox could be populated with the file name.
* <p>
* This method accepts either a full file path, or a file name with an
* extension if used together with the {@code setDirectory} method.
* <p>
* Specifying "" as the file is exactly equivalent to specifying
* {@code null} as the file.
*
* @param file the file being set
* @see #getFile
* @see #getFiles
*/
public void setFile(String file) {
this.file = (file != null && file.equals("")) ? null : file;
FileDialogPeer peer = (FileDialogPeer)this.peer;
if (peer != null) {
peer.setFile(this.file);
}
}
/**
* Enables or disables multiple file selection for the file dialog.
*
* @param enable if {@code true}, multiple file selection is enabled;
* {@code false} - disabled.
* @see #isMultipleMode
* @since 1.7
*/
public void setMultipleMode(boolean enable) {
synchronized (getObjectLock()) {
this.multipleMode = enable;
}
}
/**
* Returns whether the file dialog allows the multiple file selection.
*
* @return {@code true} if the file dialog allows the multiple
* file selection; {@code false} otherwise.
* @see #setMultipleMode
* @since 1.7
*/
public boolean isMultipleMode() {
synchronized (getObjectLock()) {
return multipleMode;
}
}
/**
* Determines this file dialog's filename filter. A filename filter
* allows the user to specify which files appear in the file dialog
* window. Filename filters do not function in Sun's reference
* implementation for Microsoft Windows.
*
* @return this file dialog's filename filter
* @see java.io.FilenameFilter
* @see java.awt.FileDialog#setFilenameFilter
*/
public FilenameFilter getFilenameFilter() {
return filter;
}
/**
* Sets the filename filter for this file dialog window to the
* specified filter.
* Filename filters do not function in Sun's reference
* implementation for Microsoft Windows.
*
* @param filter the specified filter
* @see java.io.FilenameFilter
* @see java.awt.FileDialog#getFilenameFilter
*/
public synchronized void setFilenameFilter(FilenameFilter filter) {
this.filter = filter;
FileDialogPeer peer = (FileDialogPeer)this.peer;
if (peer != null) {
peer.setFilenameFilter(filter);
}
}
/**
* Reads the {@code ObjectInputStream} and performs
* a backwards compatibility check by converting
* either a {@code dir} or a {@code file}
* equal to an empty string to {@code null}.
*
* @param s the {@code ObjectInputStream} to read
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
// 1.1 Compatibility: "" is not converted to null in 1.1
if (dir != null && dir.equals("")) {
dir = null;
}
if (file != null && file.equals("")) {
file = null;
}
}
/**
* Returns a string representing the state of this {@code FileDialog}
* window. This method is intended to be used only for debugging purposes,
* and the content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this file dialog window
*/
protected String paramString() {
String str = super.paramString();
str += ",dir= " + dir;
str += ",file= " + file;
return str + ((mode == LOAD) ? ",load" : ",save");
}
boolean postsOldMouseEvents() {
return false;
}
}

View file

@ -0,0 +1,696 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.io.ObjectInputStream;
import java.io.IOException;
/**
* A flow layout arranges components in a directional flow, much
* like lines of text in a paragraph. The flow direction is
* determined by the container's {@code componentOrientation}
* property and may be one of two values:
* <ul>
* <li>{@code ComponentOrientation.LEFT_TO_RIGHT}
* <li>{@code ComponentOrientation.RIGHT_TO_LEFT}
* </ul>
* Flow layouts are typically used
* to arrange buttons in a panel. It arranges buttons
* horizontally until no more buttons fit on the same line.
* The line alignment is determined by the {@code align}
* property. The possible values are:
* <ul>
* <li>{@link #LEFT LEFT}
* <li>{@link #RIGHT RIGHT}
* <li>{@link #CENTER CENTER}
* <li>{@link #LEADING LEADING}
* <li>{@link #TRAILING TRAILING}
* </ul>
* <p>
* For example, the following picture shows an applet using the flow
* layout manager (its default layout manager) to position three buttons:
* <p>
* <img src="doc-files/FlowLayout-1.gif"
* ALT="Graphic of Layout for Three Buttons"
* style="float:center; margin: 7px 10px;">
* <p>
* Here is the code for this applet:
*
* <hr><blockquote><pre>
* import java.awt.*;
* import java.applet.Applet;
*
* public class myButtons extends Applet {
* Button button1, button2, button3;
* public void init() {
* button1 = new Button("Ok");
* button2 = new Button("Open");
* button3 = new Button("Close");
* add(button1);
* add(button2);
* add(button3);
* }
* }
* </pre></blockquote><hr>
* <p>
* A flow layout lets each component assume its natural (preferred) size.
*
* @author Arthur van Hoff
* @author Sami Shaio
* @since 1.0
* @see ComponentOrientation
*/
public class FlowLayout implements LayoutManager, java.io.Serializable {
/**
* This value indicates that each row of components
* should be left-justified.
*/
public static final int LEFT = 0;
/**
* This value indicates that each row of components
* should be centered.
*/
public static final int CENTER = 1;
/**
* This value indicates that each row of components
* should be right-justified.
*/
public static final int RIGHT = 2;
/**
* This value indicates that each row of components
* should be justified to the leading edge of the container's
* orientation, for example, to the left in left-to-right orientations.
*
* @see java.awt.Component#getComponentOrientation
* @see java.awt.ComponentOrientation
* @since 1.2
*/
public static final int LEADING = 3;
/**
* This value indicates that each row of components
* should be justified to the trailing edge of the container's
* orientation, for example, to the right in left-to-right orientations.
*
* @see java.awt.Component#getComponentOrientation
* @see java.awt.ComponentOrientation
* @since 1.2
*/
public static final int TRAILING = 4;
/**
* {@code align} is the property that determines
* how each row distributes empty space.
* It can be one of the following values:
* <ul>
* <li>{@code LEFT}
* <li>{@code RIGHT}
* <li>{@code CENTER}
* </ul>
*
* @serial
* @see #getAlignment
* @see #setAlignment
*/
int align; // This is for 1.1 serialization compatibility
/**
* {@code newAlign} is the property that determines
* how each row distributes empty space for the Java 2 platform,
* v1.2 and greater.
* It can be one of the following three values:
* <ul>
* <li>{@code LEFT}
* <li>{@code RIGHT}
* <li>{@code CENTER}
* <li>{@code LEADING}
* <li>{@code TRAILING}
* </ul>
*
* @serial
* @since 1.2
* @see #getAlignment
* @see #setAlignment
*/
int newAlign; // This is the one we actually use
/**
* The flow layout manager allows a separation of
* components with gaps. The horizontal gap will
* specify the space between components and between
* the components and the borders of the
* {@code Container}.
*
* @serial
* @see #getHgap()
* @see #setHgap(int)
*/
int hgap;
/**
* The flow layout manager allows a separation of
* components with gaps. The vertical gap will
* specify the space between rows and between the
* the rows and the borders of the {@code Container}.
*
* @serial
* @see #getHgap()
* @see #setHgap(int)
*/
int vgap;
/**
* If true, components will be aligned on their baseline.
*/
private boolean alignOnBaseline;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -7262534875583282631L;
/**
* Constructs a new {@code FlowLayout} with a centered alignment and a
* default 5-unit horizontal and vertical gap.
*/
public FlowLayout() {
this(CENTER, 5, 5);
}
/**
* Constructs a new {@code FlowLayout} with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* {@code FlowLayout.LEFT}, {@code FlowLayout.RIGHT},
* {@code FlowLayout.CENTER}, {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @param align the alignment value
*/
public FlowLayout(int align) {
this(align, 5, 5);
}
/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* {@code FlowLayout.LEFT}, {@code FlowLayout.RIGHT},
* {@code FlowLayout.CENTER}, {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @param align the alignment value
* @param hgap the horizontal gap between components
* and between the components and the
* borders of the {@code Container}
* @param vgap the vertical gap between components
* and between the components and the
* borders of the {@code Container}
*/
public FlowLayout(int align, int hgap, int vgap) {
this.hgap = hgap;
this.vgap = vgap;
setAlignment(align);
}
/**
* Gets the alignment for this layout.
* Possible values are {@code FlowLayout.LEFT},
* {@code FlowLayout.RIGHT}, {@code FlowLayout.CENTER},
* {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @return the alignment value for this layout
* @see java.awt.FlowLayout#setAlignment
* @since 1.1
*/
public int getAlignment() {
return newAlign;
}
/**
* Sets the alignment for this layout.
* Possible values are
* <ul>
* <li>{@code FlowLayout.LEFT}
* <li>{@code FlowLayout.RIGHT}
* <li>{@code FlowLayout.CENTER}
* <li>{@code FlowLayout.LEADING}
* <li>{@code FlowLayout.TRAILING}
* </ul>
* @param align one of the alignment values shown above
* @see #getAlignment()
* @since 1.1
*/
public void setAlignment(int align) {
this.newAlign = align;
// this.align is used only for serialization compatibility,
// so set it to a value compatible with the 1.1 version
// of the class
switch (align) {
case LEADING:
this.align = LEFT;
break;
case TRAILING:
this.align = RIGHT;
break;
default:
this.align = align;
break;
}
}
/**
* Gets the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
*
* @return the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#setHgap
* @since 1.1
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between components and
* between the components and the borders of the
* {@code Container}.
*
* @param hgap the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#getHgap
* @since 1.1
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Gets the vertical gap between components and
* between the components and the borders of the
* {@code Container}.
*
* @return the vertical gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#setVgap
* @since 1.1
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components and between
* the components and the borders of the {@code Container}.
*
* @param vgap the vertical gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#getVgap
* @since 1.1
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Sets whether or not components should be vertically aligned along their
* baseline. Components that do not have a baseline will be centered.
* The default is false.
*
* @param alignOnBaseline whether or not components should be
* vertically aligned on their baseline
* @since 1.6
*/
public void setAlignOnBaseline(boolean alignOnBaseline) {
this.alignOnBaseline = alignOnBaseline;
}
/**
* Returns true if components are to be vertically aligned along
* their baseline. The default is false.
*
* @return true if components are to be vertically aligned along
* their baseline
* @since 1.6
*/
public boolean getAlignOnBaseline() {
return alignOnBaseline;
}
/**
* Adds the specified component to the layout.
* Not used by this class.
* @param name the name of the component
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
/**
* Removes the specified component from the layout.
* Not used by this class.
* @param comp the component to remove
* @see java.awt.Container#removeAll
*/
public void removeLayoutComponent(Component comp) {
}
/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
*
* @param target the container that needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
* @see Container
* @see #minimumLayoutSize
* @see java.awt.Container#getPreferredSize
*/
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
boolean useBaseline = getAlignOnBaseline();
int maxAscent = 0;
int maxDescent = 0;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent, d.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the container that needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
* @see #preferredLayoutSize
* @see java.awt.Container
* @see java.awt.Container#doLayout
*/
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
boolean useBaseline = getAlignOnBaseline();
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
int maxAscent = 0;
int maxDescent = 0;
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getMinimumSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent,
dim.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
/**
* Centers the elements in the specified row, if there is any slack.
* @param target the component which needs to be moved
* @param x the x coordinate
* @param y the y coordinate
* @param width the width dimensions
* @param height the height dimensions
* @param rowStart the beginning of the row
* @param rowEnd the ending of the row
* @param useBaseline Whether or not to align on baseline.
* @param ascent Ascent for the components. This is only valid if
* useBaseline is true.
* @param descent Ascent for the components. This is only valid if
* useBaseline is true.
* @return actual row height
*/
private int moveComponents(Container target, int x, int y, int width, int height,
int rowStart, int rowEnd, boolean ltr,
boolean useBaseline, int[] ascent,
int[] descent) {
switch (newAlign) {
case LEFT:
x += ltr ? 0 : width;
break;
case CENTER:
x += width / 2;
break;
case RIGHT:
x += ltr ? width : 0;
break;
case LEADING:
break;
case TRAILING:
x += width;
break;
}
int maxAscent = 0;
int nonbaselineHeight = 0;
int baselineOffset = 0;
if (useBaseline) {
int maxDescent = 0;
for (int i = rowStart ; i < rowEnd ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
if (ascent[i] >= 0) {
maxAscent = Math.max(maxAscent, ascent[i]);
maxDescent = Math.max(maxDescent, descent[i]);
}
else {
nonbaselineHeight = Math.max(m.getHeight(),
nonbaselineHeight);
}
}
}
height = Math.max(maxAscent + maxDescent, nonbaselineHeight);
baselineOffset = (height - maxAscent - maxDescent) / 2;
}
for (int i = rowStart ; i < rowEnd ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
int cy;
if (useBaseline && ascent[i] >= 0) {
cy = y + baselineOffset + maxAscent - ascent[i];
}
else {
cy = y + (height - m.height) / 2;
}
if (ltr) {
m.setLocation(x, cy);
} else {
m.setLocation(target.width - x - m.width, cy);
}
x += m.width + hgap;
}
}
return height;
}
/**
* Lays out the container. This method lets each
* <i>visible</i> component take
* its preferred size by reshaping the components in the
* target container in order to satisfy the alignment of
* this {@code FlowLayout} object.
*
* @param target the specified component being laid out
* @see Container
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int maxwidth = target.width - (insets.left + insets.right + hgap*2);
int nmembers = target.getComponentCount();
int x = 0, y = insets.top + vgap;
int rowh = 0, start = 0;
boolean ltr = target.getComponentOrientation().isLeftToRight();
boolean useBaseline = getAlignOnBaseline();
int[] ascent = null;
int[] descent = null;
if (useBaseline) {
ascent = new int[nmembers];
descent = new int[nmembers];
}
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
ascent[i] = baseline;
descent[i] = d.height - baseline;
}
else {
ascent[i] = -1;
}
}
if ((x == 0) || ((x + d.width) <= maxwidth)) {
if (x > 0) {
x += hgap;
}
x += d.width;
rowh = Math.max(rowh, d.height);
} else {
rowh = moveComponents(target, insets.left + hgap, y,
maxwidth - x, rowh, start, i, ltr,
useBaseline, ascent, descent);
x = d.width;
y += vgap + rowh;
rowh = d.height;
start = i;
}
}
}
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh,
start, nmembers, ltr, useBaseline, ascent, descent);
}
}
//
// the internal serial version which says which version was written
// - 0 (default) for versions before the Java 2 platform, v1.2
// - 1 for version >= Java 2 platform v1.2, which includes "newAlign" field
//
private static final int currentSerialVersion = 1;
/**
* This represent the {@code currentSerialVersion}
* which is bein used. It will be one of two values:
* {@code 0} versions before Java 2 platform v1.2,
* {@code 1} versions after Java 2 platform v1.2.
*
* @serial
* @since 1.2
*/
private int serialVersionOnStream = currentSerialVersion;
/**
* Reads this object out of a serialization stream, handling
* objects written by older versions of the class that didn't contain all
* of the fields we use now..
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
if (serialVersionOnStream < 1) {
// "newAlign" field wasn't present, so use the old "align" field.
setAlignment(this.align);
}
serialVersionOnStream = currentSerialVersion;
}
/**
* Returns a string representation of this {@code FlowLayout}
* object and its values.
* @return a string representation of this layout
*/
public String toString() {
String str = "";
switch (align) {
case LEFT: str = ",align=left"; break;
case CENTER: str = ",align=center"; break;
case RIGHT: str = ",align=right"; break;
case LEADING: str = ",align=leading"; break;
case TRAILING: str = ",align=trailing"; break;
}
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
}
}

View file

@ -0,0 +1,175 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* A FocusTraversalPolicy defines the order in which Components with a
* particular focus cycle root are traversed. Instances can apply the policy to
* arbitrary focus cycle roots, allowing themselves to be shared across
* Containers. They do not need to be reinitialized when the focus cycle roots
* of a Component hierarchy change.
* <p>
* The core responsibility of a FocusTraversalPolicy is to provide algorithms
* determining the next and previous Components to focus when traversing
* forward or backward in a UI. Each FocusTraversalPolicy must also provide
* algorithms for determining the first, last, and default Components in a
* traversal cycle. First and last Components are used when normal forward and
* backward traversal, respectively, wraps. The default Component is the first
* to receive focus when traversing down into a new focus traversal cycle.
* A FocusTraversalPolicy can optionally provide an algorithm for determining
* a Window's initial Component. The initial Component is the first to receive
* focus when a Window is first made visible.
* <p>
* FocusTraversalPolicy takes into account <a
* href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal
* policy providers</a>. When searching for first/last/next/previous Component,
* if a focus traversal policy provider is encountered, its focus traversal
* policy is used to perform the search operation.
* <p>
* Please see
* <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
* How to Use the Focus Subsystem</a>,
* a section in <em>The Java Tutorial</em>, and the
* <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
* for more information.
*
* @author David Mendenhall
*
* @see Container#setFocusTraversalPolicy
* @see Container#getFocusTraversalPolicy
* @see Container#setFocusCycleRoot
* @see Container#isFocusCycleRoot
* @see Container#setFocusTraversalPolicyProvider
* @see Container#isFocusTraversalPolicyProvider
* @see KeyboardFocusManager#setDefaultFocusTraversalPolicy
* @see KeyboardFocusManager#getDefaultFocusTraversalPolicy
* @since 1.4
*/
public abstract class FocusTraversalPolicy {
/**
* Returns the Component that should receive the focus after aComponent.
* aContainer must be a focus cycle root of aComponent or a focus traversal
* policy provider.
*
* @param aContainer a focus cycle root of aComponent or focus traversal
* policy provider
* @param aComponent a (possibly indirect) child of aContainer, or
* aContainer itself
* @return the Component that should receive the focus after aComponent, or
* null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is not a focus cycle
* root of aComponent or a focus traversal policy provider, or if
* either aContainer or aComponent is null
*/
public abstract Component getComponentAfter(Container aContainer,
Component aComponent);
/**
* Returns the Component that should receive the focus before aComponent.
* aContainer must be a focus cycle root of aComponent or a focus traversal
* policy provider.
*
* @param aContainer a focus cycle root of aComponent or focus traversal
* policy provider
* @param aComponent a (possibly indirect) child of aContainer, or
* aContainer itself
* @return the Component that should receive the focus before aComponent,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is not a focus cycle
* root of aComponent or a focus traversal policy provider, or if
* either aContainer or aComponent is null
*/
public abstract Component getComponentBefore(Container aContainer,
Component aComponent);
/**
* Returns the first Component in the traversal cycle. This method is used
* to determine the next Component to focus when traversal wraps in the
* forward direction.
*
* @param aContainer the focus cycle root or focus traversal policy provider
* whose first Component is to be returned
* @return the first Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is null
*/
public abstract Component getFirstComponent(Container aContainer);
/**
* Returns the last Component in the traversal cycle. This method is used
* to determine the next Component to focus when traversal wraps in the
* reverse direction.
*
* @param aContainer the focus cycle root or focus traversal policy
* provider whose last Component is to be returned
* @return the last Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is null
*/
public abstract Component getLastComponent(Container aContainer);
/**
* Returns the default Component to focus. This Component will be the first
* to receive focus when traversing down into a new focus traversal cycle
* rooted at aContainer.
*
* @param aContainer the focus cycle root or focus traversal policy
* provider whose default Component is to be returned
* @return the default Component in the traversal cycle of aContainer,
* or null if no suitable Component can be found
* @throws IllegalArgumentException if aContainer is null
*/
public abstract Component getDefaultComponent(Container aContainer);
/**
* Returns the Component that should receive the focus when a Window is
* made visible for the first time. Once the Window has been made visible
* by a call to {@code show()} or {@code setVisible(true)}, the
* initial Component will not be used again. Instead, if the Window loses
* and subsequently regains focus, or is made invisible or undisplayable
* and subsequently made visible and displayable, the Window's most
* recently focused Component will become the focus owner. The default
* implementation of this method returns the default Component.
*
* @param window the Window whose initial Component is to be returned
* @return the Component that should receive the focus when window is made
* visible for the first time, or null if no suitable Component can
* be found
* @see #getDefaultComponent
* @see Window#getMostRecentFocusOwner
* @throws IllegalArgumentException if window is null
*/
public Component getInitialComponent(Window window) {
if ( window == null ){
throw new IllegalArgumentException("window cannot be equal to null.");
}
Component def = getDefaultComponent(window);
if (def == null && window.isFocusableWindow()) {
def = window;
}
return def;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Thrown by method createFont in the {@code Font} class to indicate
* that the specified font is bad.
*
* @author Parry Kejriwal
* @see java.awt.Font
* @since 1.3
*/
public
class FontFormatException extends Exception {
/*
* serialVersionUID
*/
private static final long serialVersionUID = -4481290147811361272L;
/**
* Report a FontFormatException for the reason specified.
* @param reason a {@code String} message indicating why
* the font is not accepted.
*/
public FontFormatException(String reason) {
super (reason);
}
}

View file

@ -0,0 +1,642 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
import java.text.CharacterIterator;
/**
* The {@code FontMetrics} class defines a font metrics object, which
* encapsulates information about the rendering of a particular font on a
* particular screen.
* <p>
* <b>Note to subclassers</b>: Since many of these methods form closed,
* mutually recursive loops, you must take care that you implement
* at least one of the methods in each such loop to prevent
* infinite recursion when your subclass is used.
* In particular, the following is the minimal suggested set of methods
* to override in order to ensure correctness and prevent infinite
* recursion (though other subsets are equally feasible):
* <ul>
* <li>{@link #getAscent()}
* <li>{@link #getLeading()}
* <li>{@link #getMaxAdvance()}
* <li>{@link #charWidth(char)}
* <li>{@link #charsWidth(char[], int, int)}
* </ul>
* <p>
* <img src="doc-files/FontMetrics-1.gif" alt="The letter 'p' showing its 'reference point'"
* style="border:15px; float:right; margin: 7px 10px;">
* Note that the implementations of these methods are
* inefficient, so they are usually overridden with more efficient
* toolkit-specific implementations.
* <p>
* When an application asks to place a character at the position
* (<i>x</i>,&nbsp;<i>y</i>), the character is placed so that its
* reference point (shown as the dot in the accompanying image) is
* put at that position. The reference point specifies a horizontal
* line called the <i>baseline</i> of the character. In normal
* printing, the baselines of characters should align.
* <p>
* In addition, every character in a font has an <i>ascent</i>, a
* <i>descent</i>, and an <i>advance width</i>. The ascent is the
* amount by which the character ascends above the baseline. The
* descent is the amount by which the character descends below the
* baseline. The advance width indicates the position at which AWT
* should place the next character.
* <p>
* An array of characters or a string can also have an ascent, a
* descent, and an advance width. The ascent of the array is the
* maximum ascent of any character in the array. The descent is the
* maximum descent of any character in the array. The advance width
* is the sum of the advance widths of each of the characters in the
* character array. The advance of a {@code String} is the
* distance along the baseline of the {@code String}. This
* distance is the width that should be used for centering or
* right-aligning the {@code String}.
* <p>Note that the advance of a {@code String} is not necessarily
* the sum of the advances of its characters measured in isolation
* because the width of a character can vary depending on its context.
* For example, in Arabic text, the shape of a character can change
* in order to connect to other characters. Also, in some scripts,
* certain character sequences can be represented by a single shape,
* called a <em>ligature</em>. Measuring characters individually does
* not account for these transformations.
* <p>Font metrics are baseline-relative, meaning that they are
* generally independent of the rotation applied to the font (modulo
* possible grid hinting effects). See {@link java.awt.Font Font}.
*
* @author Jim Graham
* @see java.awt.Font
* @since 1.0
*/
public abstract class FontMetrics implements java.io.Serializable {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
private static final FontRenderContext
DEFAULT_FRC = new FontRenderContext(null, false, false);
/**
* The actual {@link Font} from which the font metrics are
* created.
* This cannot be null.
*
* @serial
* @see #getFont()
*/
protected Font font;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 1681126225205050147L;
/**
* Creates a new {@code FontMetrics} object for finding out
* height and width information about the specified {@code Font}
* and specific character glyphs in that {@code Font}.
* @param font the {@code Font}
* @see java.awt.Font
*/
protected FontMetrics(Font font) {
this.font = font;
}
/**
* Gets the {@code Font} described by this
* {@code FontMetrics} object.
* @return the {@code Font} described by this
* {@code FontMetrics} object.
*/
public Font getFont() {
return font;
}
/**
* Gets the {@code FontRenderContext} used by this
* {@code FontMetrics} object to measure text.
* <p>
* Note that methods in this class which take a {@code Graphics}
* parameter measure text using the {@code FontRenderContext}
* of that {@code Graphics} object, and not this
* {@code FontRenderContext}
* @return the {@code FontRenderContext} used by this
* {@code FontMetrics} object.
* @since 1.6
*/
public FontRenderContext getFontRenderContext() {
return DEFAULT_FRC;
}
/**
* Determines the <em>standard leading</em> of the
* {@code Font} described by this {@code FontMetrics}
* object. The standard leading, or
* interline spacing, is the logical amount of space to be reserved
* between the descent of one line of text and the ascent of the next
* line. The height metric is calculated to include this extra space.
* @return the standard leading of the {@code Font}.
* @see #getHeight()
* @see #getAscent()
* @see #getDescent()
*/
public int getLeading() {
return 0;
}
/**
* Determines the <em>font ascent</em> of the {@code Font}
* described by this {@code FontMetrics} object. The font ascent
* is the distance from the font's baseline to the top of most
* alphanumeric characters. Some characters in the {@code Font}
* might extend above the font ascent line.
* @return the font ascent of the {@code Font}.
* @see #getMaxAscent()
*/
public int getAscent() {
return font.getSize();
}
/**
* Determines the <em>font descent</em> of the {@code Font}
* described by this
* {@code FontMetrics} object. The font descent is the distance
* from the font's baseline to the bottom of most alphanumeric
* characters with descenders. Some characters in the
* {@code Font} might extend
* below the font descent line.
* @return the font descent of the {@code Font}.
* @see #getMaxDescent()
*/
public int getDescent() {
return 0;
}
/**
* Gets the standard height of a line of text in this font. This
* is the distance between the baseline of adjacent lines of text.
* It is the sum of the leading + ascent + descent. Due to rounding
* this may not be the same as getAscent() + getDescent() + getLeading().
* There is no guarantee that lines of text spaced at this distance are
* disjoint; such lines may overlap if some characters overshoot
* either the standard ascent or the standard descent metric.
* @return the standard height of the font.
* @see #getLeading()
* @see #getAscent()
* @see #getDescent()
*/
public int getHeight() {
return getLeading() + getAscent() + getDescent();
}
/**
* Determines the maximum ascent of the {@code Font}
* described by this {@code FontMetrics} object. No character
* extends further above the font's baseline than this height.
* @return the maximum ascent of any character in the
* {@code Font}.
* @see #getAscent()
*/
public int getMaxAscent() {
return getAscent();
}
/**
* Determines the maximum descent of the {@code Font}
* described by this {@code FontMetrics} object. No character
* extends further below the font's baseline than this height.
* @return the maximum descent of any character in the
* {@code Font}.
* @see #getDescent()
*/
public int getMaxDescent() {
return getDescent();
}
/**
* For backward compatibility only.
* @return the maximum descent of any character in the
* {@code Font}.
* @see #getMaxDescent()
* @deprecated As of JDK version 1.1.1,
* replaced by {@code getMaxDescent()}.
*/
@Deprecated
public int getMaxDecent() {
return getMaxDescent();
}
/**
* Gets the maximum advance width of any character in this
* {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* string's baseline. The advance of a {@code String} is
* not necessarily the sum of the advances of its characters.
* @return the maximum advance width of any character
* in the {@code Font}, or {@code -1} if the
* maximum advance width is not known.
*/
public int getMaxAdvance() {
return -1;
}
/**
* Returns the advance width of the specified character in this
* {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* character's baseline. Note that the advance of a
* {@code String} is not necessarily the sum of the advances
* of its characters.
*
* <p>This method doesn't validate the specified character to be a
* valid Unicode code point. The caller must validate the
* character value using {@link
* java.lang.Character#isValidCodePoint(int)
* Character.isValidCodePoint} if necessary.
*
* @param codePoint the character (Unicode code point) to be measured
* @return the advance width of the specified character
* in the {@code Font} described by this
* {@code FontMetrics} object.
* @see #charsWidth(char[], int, int)
* @see #stringWidth(String)
*/
public int charWidth(int codePoint) {
if (!Character.isValidCodePoint(codePoint)) {
codePoint = 0xffff; // substitute missing glyph width
}
if (codePoint < 256) {
return getWidths()[codePoint];
} else {
char[] buffer = new char[2];
int len = Character.toChars(codePoint, buffer, 0);
return charsWidth(buffer, 0, len);
}
}
/**
* Returns the advance width of the specified character in this
* {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* character's baseline. Note that the advance of a
* {@code String} is not necessarily the sum of the advances
* of its characters.
*
* <p><b>Note:</b> This method cannot handle <a
* href="../lang/Character.html#supplementary"> supplementary
* characters</a>. To support all Unicode characters, including
* supplementary characters, use the {@link #charWidth(int)} method.
*
* @param ch the character to be measured
* @return the advance width of the specified character
* in the {@code Font} described by this
* {@code FontMetrics} object.
* @see #charsWidth(char[], int, int)
* @see #stringWidth(String)
*/
public int charWidth(char ch) {
if (ch < 256) {
return getWidths()[ch];
}
char data[] = {ch};
return charsWidth(data, 0, 1);
}
/**
* Returns the total advance width for showing the specified
* {@code String} in this {@code Font}. The advance
* is the distance from the leftmost point to the rightmost point
* on the string's baseline.
* <p>
* Note that the advance of a {@code String} is
* not necessarily the sum of the advances of its characters.
* @param str the {@code String} to be measured
* @return the advance width of the specified {@code String}
* in the {@code Font} described by this
* {@code FontMetrics}.
* @throws NullPointerException if str is null.
* @see #bytesWidth(byte[], int, int)
* @see #charsWidth(char[], int, int)
* @see #getStringBounds(String, Graphics)
*/
public int stringWidth(String str) {
int len = str.length();
char data[] = new char[len];
str.getChars(0, len, data, 0);
return charsWidth(data, 0, len);
}
/**
* Returns the total advance width for showing the specified array
* of characters in this {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* string's baseline. The advance of a {@code String}
* is not necessarily the sum of the advances of its characters.
* This is equivalent to measuring a {@code String} of the
* characters in the specified range.
* @param data the array of characters to be measured
* @param off the start offset of the characters in the array
* @param len the number of characters to be measured from the array
* @return the advance width of the subarray of the specified
* {@code char} array in the font described by
* this {@code FontMetrics} object.
* @throws NullPointerException if {@code data} is null.
* @throws IndexOutOfBoundsException if the {@code off}
* and {@code len} arguments index characters outside
* the bounds of the {@code data} array.
* @see #charWidth(int)
* @see #charWidth(char)
* @see #bytesWidth(byte[], int, int)
* @see #stringWidth(String)
*/
public int charsWidth(char data[], int off, int len) {
return stringWidth(new String(data, off, len));
}
/**
* Returns the total advance width for showing the specified array
* of bytes in this {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* string's baseline. The advance of a {@code String}
* is not necessarily the sum of the advances of its characters.
* This is equivalent to measuring a {@code String} of the
* characters in the specified range.
* @param data the array of bytes to be measured
* @param off the start offset of the bytes in the array
* @param len the number of bytes to be measured from the array
* @return the advance width of the subarray of the specified
* {@code byte} array in the {@code Font}
* described by
* this {@code FontMetrics} object.
* @throws NullPointerException if {@code data} is null.
* @throws IndexOutOfBoundsException if the {@code off}
* and {@code len} arguments index bytes outside
* the bounds of the {@code data} array.
* @see #charsWidth(char[], int, int)
* @see #stringWidth(String)
*/
@SuppressWarnings("deprecation")
public int bytesWidth(byte data[], int off, int len) {
return stringWidth(new String(data, 0, off, len));
}
/**
* Gets the advance widths of the first 256 characters in the
* {@code Font}. The advance is the
* distance from the leftmost point to the rightmost point on the
* character's baseline. Note that the advance of a
* {@code String} is not necessarily the sum of the advances
* of its characters.
* @return an array storing the advance widths of the
* characters in the {@code Font}
* described by this {@code FontMetrics} object.
*/
public int[] getWidths() {
int widths[] = new int[256];
for (char ch = 0 ; ch < 256 ; ch++) {
widths[ch] = charWidth(ch);
}
return widths;
}
/**
* Checks to see if the {@code Font} has uniform line metrics. A
* composite font may consist of several different fonts to cover
* various character sets. In such cases, the
* {@code FontLineMetrics} objects are not uniform.
* Different fonts may have a different ascent, descent, metrics and
* so on. This information is sometimes necessary for line
* measuring and line breaking.
* @return {@code true} if the font has uniform line metrics;
* {@code false} otherwise.
* @see java.awt.Font#hasUniformLineMetrics()
*/
public boolean hasUniformLineMetrics() {
return font.hasUniformLineMetrics();
}
/**
* Returns the {@link LineMetrics} object for the specified
* {@code String} in the specified {@link Graphics} context.
* @param str the specified {@code String}
* @param context the specified {@code Graphics} context
* @return a {@code LineMetrics} object created with the
* specified {@code String} and {@code Graphics} context.
* @see java.awt.Font#getLineMetrics(String, FontRenderContext)
*/
public LineMetrics getLineMetrics( String str, Graphics context) {
return font.getLineMetrics(str, myFRC(context));
}
/**
* Returns the {@link LineMetrics} object for the specified
* {@code String} in the specified {@link Graphics} context.
* @param str the specified {@code String}
* @param beginIndex the initial offset of {@code str}
* @param limit the end offset of {@code str}
* @param context the specified {@code Graphics} context
* @return a {@code LineMetrics} object created with the
* specified {@code String} and {@code Graphics} context.
* @see java.awt.Font#getLineMetrics(String, int, int, FontRenderContext)
*/
public LineMetrics getLineMetrics( String str,
int beginIndex, int limit,
Graphics context) {
return font.getLineMetrics(str, beginIndex, limit, myFRC(context));
}
/**
* Returns the {@link LineMetrics} object for the specified
* character array in the specified {@link Graphics} context.
* @param chars the specified character array
* @param beginIndex the initial offset of {@code chars}
* @param limit the end offset of {@code chars}
* @param context the specified {@code Graphics} context
* @return a {@code LineMetrics} object created with the
* specified character array and {@code Graphics} context.
* @see java.awt.Font#getLineMetrics(char[], int, int, FontRenderContext)
*/
public LineMetrics getLineMetrics(char [] chars,
int beginIndex, int limit,
Graphics context) {
return font.getLineMetrics(
chars, beginIndex, limit, myFRC(context));
}
/**
* Returns the {@link LineMetrics} object for the specified
* {@link CharacterIterator} in the specified {@link Graphics}
* context.
* @param ci the specified {@code CharacterIterator}
* @param beginIndex the initial offset in {@code ci}
* @param limit the end index of {@code ci}
* @param context the specified {@code Graphics} context
* @return a {@code LineMetrics} object created with the
* specified arguments.
* @see java.awt.Font#getLineMetrics(CharacterIterator, int, int, FontRenderContext)
*/
public LineMetrics getLineMetrics(CharacterIterator ci,
int beginIndex, int limit,
Graphics context) {
return font.getLineMetrics(ci, beginIndex, limit, myFRC(context));
}
/**
* Returns the bounds of the specified {@code String} in the
* specified {@code Graphics} context. The bounds is used
* to layout the {@code String}.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.FontMetrics class notes}).
* @param str the specified {@code String}
* @param context the specified {@code Graphics} context
* @return a {@link Rectangle2D} that is the bounding box of the
* specified {@code String} in the specified
* {@code Graphics} context.
* @see java.awt.Font#getStringBounds(String, FontRenderContext)
*/
public Rectangle2D getStringBounds( String str, Graphics context) {
return font.getStringBounds(str, myFRC(context));
}
/**
* Returns the bounds of the specified {@code String} in the
* specified {@code Graphics} context. The bounds is used
* to layout the {@code String}.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.FontMetrics class notes}).
* @param str the specified {@code String}
* @param beginIndex the offset of the beginning of {@code str}
* @param limit the end offset of {@code str}
* @param context the specified {@code Graphics} context
* @return a {@code Rectangle2D} that is the bounding box of the
* specified {@code String} in the specified
* {@code Graphics} context.
* @see java.awt.Font#getStringBounds(String, int, int, FontRenderContext)
*/
public Rectangle2D getStringBounds( String str,
int beginIndex, int limit,
Graphics context) {
return font.getStringBounds(str, beginIndex, limit,
myFRC(context));
}
/**
* Returns the bounds of the specified array of characters
* in the specified {@code Graphics} context.
* The bounds is used to layout the {@code String}
* created with the specified array of characters,
* {@code beginIndex} and {@code limit}.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.FontMetrics class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset of the array of
* characters
* @param limit the end offset of the array of characters
* @param context the specified {@code Graphics} context
* @return a {@code Rectangle2D} that is the bounding box of the
* specified character array in the specified
* {@code Graphics} context.
* @see java.awt.Font#getStringBounds(char[], int, int, FontRenderContext)
*/
public Rectangle2D getStringBounds( char [] chars,
int beginIndex, int limit,
Graphics context) {
return font.getStringBounds(chars, beginIndex, limit,
myFRC(context));
}
/**
* Returns the bounds of the characters indexed in the specified
* {@code CharacterIterator} in the
* specified {@code Graphics} context.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.FontMetrics class notes}).
* @param ci the specified {@code CharacterIterator}
* @param beginIndex the initial offset in {@code ci}
* @param limit the end index of {@code ci}
* @param context the specified {@code Graphics} context
* @return a {@code Rectangle2D} that is the bounding box of the
* characters indexed in the specified {@code CharacterIterator}
* in the specified {@code Graphics} context.
* @see java.awt.Font#getStringBounds(CharacterIterator, int, int, FontRenderContext)
*/
public Rectangle2D getStringBounds(CharacterIterator ci,
int beginIndex, int limit,
Graphics context) {
return font.getStringBounds(ci, beginIndex, limit,
myFRC(context));
}
/**
* Returns the bounds for the character with the maximum bounds
* in the specified {@code Graphics} context.
* @param context the specified {@code Graphics} context
* @return a {@code Rectangle2D} that is the
* bounding box for the character with the maximum bounds.
* @see java.awt.Font#getMaxCharBounds(FontRenderContext)
*/
public Rectangle2D getMaxCharBounds(Graphics context) {
return font.getMaxCharBounds(myFRC(context));
}
private FontRenderContext myFRC(Graphics context) {
if (context instanceof Graphics2D) {
return ((Graphics2D)context).getFontRenderContext();
}
return DEFAULT_FRC;
}
/**
* Returns a representation of this {@code FontMetrics}
* object's values as a {@code String}.
* @return a {@code String} representation of this
* {@code FontMetrics} object.
*/
public String toString() {
return getClass().getName() +
"[font=" + getFont() +
"ascent=" + getAscent() +
", descent=" + getDescent() +
", height=" + getHeight() + "]";
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,278 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.beans.ConstructorProperties;
/**
* The {@code GradientPaint} class provides a way to fill
* a {@link Shape} with a linear color gradient pattern.
* If {@link Point} P1 with {@link Color} C1 and {@code Point} P2 with
* {@code Color} C2 are specified in user space, the
* {@code Color} on the P1, P2 connecting line is proportionally
* changed from C1 to C2. Any point P not on the extended P1, P2
* connecting line has the color of the point P' that is the perpendicular
* projection of P on the extended P1, P2 connecting line.
* Points on the extended line outside of the P1, P2 segment can be colored
* in one of two ways.
* <ul>
* <li>
* If the gradient is cyclic then the points on the extended P1, P2
* connecting line cycle back and forth between the colors C1 and C2.
* <li>
* If the gradient is acyclic then points on the P1 side of the segment
* have the constant {@code Color} C1 while points on the P2 side
* have the constant {@code Color} C2.
* </ul>
*
* @see Paint
* @see Graphics2D#setPaint
* @version 10 Feb 1997
*/
public class GradientPaint implements Paint {
Point2D.Float p1;
Point2D.Float p2;
Color color1;
Color color2;
boolean cyclic;
/**
* Constructs a simple acyclic {@code GradientPaint} object.
* @param x1 x coordinate of the first specified
* {@code Point} in user space
* @param y1 y coordinate of the first specified
* {@code Point} in user space
* @param color1 {@code Color} at the first specified
* {@code Point}
* @param x2 x coordinate of the second specified
* {@code Point} in user space
* @param y2 y coordinate of the second specified
* {@code Point} in user space
* @param color2 {@code Color} at the second specified
* {@code Point}
* @throws NullPointerException if either one of colors is null
*/
public GradientPaint(float x1,
float y1,
Color color1,
float x2,
float y2,
Color color2) {
if ((color1 == null) || (color2 == null)) {
throw new NullPointerException("Colors cannot be null");
}
p1 = new Point2D.Float(x1, y1);
p2 = new Point2D.Float(x2, y2);
this.color1 = color1;
this.color2 = color2;
}
/**
* Constructs a simple acyclic {@code GradientPaint} object.
* @param pt1 the first specified {@code Point} in user space
* @param color1 {@code Color} at the first specified
* {@code Point}
* @param pt2 the second specified {@code Point} in user space
* @param color2 {@code Color} at the second specified
* {@code Point}
* @throws NullPointerException if either one of colors or points
* is null
*/
public GradientPaint(Point2D pt1,
Color color1,
Point2D pt2,
Color color2) {
if ((color1 == null) || (color2 == null) ||
(pt1 == null) || (pt2 == null)) {
throw new NullPointerException("Colors and points should be non-null");
}
p1 = new Point2D.Float((float)pt1.getX(), (float)pt1.getY());
p2 = new Point2D.Float((float)pt2.getX(), (float)pt2.getY());
this.color1 = color1;
this.color2 = color2;
}
/**
* Constructs either a cyclic or acyclic {@code GradientPaint}
* object depending on the {@code boolean} parameter.
* @param x1 x coordinate of the first specified
* {@code Point} in user space
* @param y1 y coordinate of the first specified
* {@code Point} in user space
* @param color1 {@code Color} at the first specified
* {@code Point}
* @param x2 x coordinate of the second specified
* {@code Point} in user space
* @param y2 y coordinate of the second specified
* {@code Point} in user space
* @param color2 {@code Color} at the second specified
* {@code Point}
* @param cyclic {@code true} if the gradient pattern should cycle
* repeatedly between the two colors; {@code false} otherwise
*/
public GradientPaint(float x1,
float y1,
Color color1,
float x2,
float y2,
Color color2,
boolean cyclic) {
this (x1, y1, color1, x2, y2, color2);
this.cyclic = cyclic;
}
/**
* Constructs either a cyclic or acyclic {@code GradientPaint}
* object depending on the {@code boolean} parameter.
* @param pt1 the first specified {@code Point}
* in user space
* @param color1 {@code Color} at the first specified
* {@code Point}
* @param pt2 the second specified {@code Point}
* in user space
* @param color2 {@code Color} at the second specified
* {@code Point}
* @param cyclic {@code true} if the gradient pattern should cycle
* repeatedly between the two colors; {@code false} otherwise
* @throws NullPointerException if either one of colors or points
* is null
*/
@ConstructorProperties({ "point1", "color1", "point2", "color2", "cyclic" })
public GradientPaint(Point2D pt1,
Color color1,
Point2D pt2,
Color color2,
boolean cyclic) {
this (pt1, color1, pt2, color2);
this.cyclic = cyclic;
}
/**
* Returns a copy of the point P1 that anchors the first color.
* @return a {@link Point2D} object that is a copy of the point
* that anchors the first color of this
* {@code GradientPaint}.
*/
public Point2D getPoint1() {
return new Point2D.Float(p1.x, p1.y);
}
/**
* Returns the color C1 anchored by the point P1.
* @return a {@code Color} object that is the color
* anchored by P1.
*/
public Color getColor1() {
return color1;
}
/**
* Returns a copy of the point P2 which anchors the second color.
* @return a {@link Point2D} object that is a copy of the point
* that anchors the second color of this
* {@code GradientPaint}.
*/
public Point2D getPoint2() {
return new Point2D.Float(p2.x, p2.y);
}
/**
* Returns the color C2 anchored by the point P2.
* @return a {@code Color} object that is the color
* anchored by P2.
*/
public Color getColor2() {
return color2;
}
/**
* Returns {@code true} if the gradient cycles repeatedly
* between the two colors C1 and C2.
* @return {@code true} if the gradient cycles repeatedly
* between the two colors; {@code false} otherwise.
*/
public boolean isCyclic() {
return cyclic;
}
/**
* Creates and returns a {@link PaintContext} used to
* generate a linear color gradient pattern.
* See the {@link Paint#createContext specification} of the
* method in the {@link Paint} interface for information
* on null parameter handling.
*
* @param cm the preferred {@link ColorModel} which represents the most convenient
* format for the caller to receive the pixel data, or {@code null}
* if there is no preference.
* @param deviceBounds the device space bounding box
* of the graphics primitive being rendered.
* @param userBounds the user space bounding box
* of the graphics primitive being rendered.
* @param xform the {@link AffineTransform} from user
* space into device space.
* @param hints the set of hints that the context object can use to
* choose between rendering alternatives.
* @return the {@code PaintContext} for
* generating color patterns.
* @see Paint
* @see PaintContext
* @see ColorModel
* @see Rectangle
* @see Rectangle2D
* @see AffineTransform
* @see RenderingHints
*/
public PaintContext createContext(ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform xform,
RenderingHints hints) {
return new GradientPaintContext(cm, p1, p2, xform,
color1, color2, cyclic);
}
/**
* Returns the transparency mode for this {@code GradientPaint}.
* @return an integer value representing this {@code GradientPaint}
* object's transparency mode.
* @see Transparency
*/
public int getTransparency() {
int a1 = color1.getAlpha();
int a2 = color2.getAlpha();
return (((a1 & a2) == 0xff) ? OPAQUE : TRANSLUCENT);
}
}

View file

@ -0,0 +1,295 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.Raster;
import sun.awt.image.IntegerComponentRaster;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.geom.Point2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.lang.ref.WeakReference;
class GradientPaintContext implements PaintContext {
static ColorModel xrgbmodel =
new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
static ColorModel xbgrmodel =
new DirectColorModel(24, 0x000000ff, 0x0000ff00, 0x00ff0000);
static ColorModel cachedModel;
static WeakReference<Raster> cached;
static synchronized Raster getCachedRaster(ColorModel cm, int w, int h) {
if (cm == cachedModel) {
if (cached != null) {
Raster ras = cached.get();
if (ras != null &&
ras.getWidth() >= w &&
ras.getHeight() >= h)
{
cached = null;
return ras;
}
}
}
return cm.createCompatibleWritableRaster(w, h);
}
static synchronized void putCachedRaster(ColorModel cm, Raster ras) {
if (cached != null) {
Raster cras = cached.get();
if (cras != null) {
int cw = cras.getWidth();
int ch = cras.getHeight();
int iw = ras.getWidth();
int ih = ras.getHeight();
if (cw >= iw && ch >= ih) {
return;
}
if (cw * ch >= iw * ih) {
return;
}
}
}
cachedModel = cm;
cached = new WeakReference<>(ras);
}
double x1;
double y1;
double dx;
double dy;
boolean cyclic;
int interp[];
Raster saved;
ColorModel model;
public GradientPaintContext(ColorModel cm,
Point2D p1, Point2D p2, AffineTransform xform,
Color c1, Color c2, boolean cyclic) {
// First calculate the distance moved in user space when
// we move a single unit along the X & Y axes in device space.
Point2D xvec = new Point2D.Double(1, 0);
Point2D yvec = new Point2D.Double(0, 1);
try {
AffineTransform inverse = xform.createInverse();
inverse.deltaTransform(xvec, xvec);
inverse.deltaTransform(yvec, yvec);
} catch (NoninvertibleTransformException e) {
xvec.setLocation(0, 0);
yvec.setLocation(0, 0);
}
// Now calculate the (square of the) user space distance
// between the anchor points. This value equals:
// (UserVec . UserVec)
double udx = p2.getX() - p1.getX();
double udy = p2.getY() - p1.getY();
double ulenSq = udx * udx + udy * udy;
if (ulenSq <= Double.MIN_VALUE) {
dx = 0;
dy = 0;
} else {
// Now calculate the proportional distance moved along the
// vector from p1 to p2 when we move a unit along X & Y in
// device space.
//
// The length of the projection of the Device Axis Vector is
// its dot product with the Unit User Vector:
// (DevAxisVec . (UserVec / Len(UserVec))
//
// The "proportional" length is that length divided again
// by the length of the User Vector:
// (DevAxisVec . (UserVec / Len(UserVec))) / Len(UserVec)
// which simplifies to:
// ((DevAxisVec . UserVec) / Len(UserVec)) / Len(UserVec)
// which simplifies to:
// (DevAxisVec . UserVec) / LenSquared(UserVec)
dx = (xvec.getX() * udx + xvec.getY() * udy) / ulenSq;
dy = (yvec.getX() * udx + yvec.getY() * udy) / ulenSq;
if (cyclic) {
dx = dx % 1.0;
dy = dy % 1.0;
} else {
// We are acyclic
if (dx < 0) {
// If we are using the acyclic form below, we need
// dx to be non-negative for simplicity of scanning
// across the scan lines for the transition points.
// To ensure that constraint, we negate the dx/dy
// values and swap the points and colors.
Point2D p = p1; p1 = p2; p2 = p;
Color c = c1; c1 = c2; c2 = c;
dx = -dx;
dy = -dy;
}
}
}
Point2D dp1 = xform.transform(p1, null);
this.x1 = dp1.getX();
this.y1 = dp1.getY();
this.cyclic = cyclic;
int rgb1 = c1.getRGB();
int rgb2 = c2.getRGB();
int a1 = (rgb1 >> 24) & 0xff;
int r1 = (rgb1 >> 16) & 0xff;
int g1 = (rgb1 >> 8) & 0xff;
int b1 = (rgb1 ) & 0xff;
int da = ((rgb2 >> 24) & 0xff) - a1;
int dr = ((rgb2 >> 16) & 0xff) - r1;
int dg = ((rgb2 >> 8) & 0xff) - g1;
int db = ((rgb2 ) & 0xff) - b1;
if (a1 == 0xff && da == 0) {
model = xrgbmodel;
if (cm instanceof DirectColorModel) {
DirectColorModel dcm = (DirectColorModel) cm;
int tmp = dcm.getAlphaMask();
if ((tmp == 0 || tmp == 0xff) &&
dcm.getRedMask() == 0xff &&
dcm.getGreenMask() == 0xff00 &&
dcm.getBlueMask() == 0xff0000)
{
model = xbgrmodel;
tmp = r1; r1 = b1; b1 = tmp;
tmp = dr; dr = db; db = tmp;
}
}
} else {
model = ColorModel.getRGBdefault();
}
interp = new int[cyclic ? 513 : 257];
for (int i = 0; i <= 256; i++) {
float rel = i / 256.0f;
int rgb =
(((int) (a1 + da * rel)) << 24) |
(((int) (r1 + dr * rel)) << 16) |
(((int) (g1 + dg * rel)) << 8) |
(((int) (b1 + db * rel)) );
interp[i] = rgb;
if (cyclic) {
interp[512 - i] = rgb;
}
}
}
/**
* Release the resources allocated for the operation.
*/
public void dispose() {
if (saved != null) {
putCachedRaster(model, saved);
saved = null;
}
}
/**
* Return the ColorModel of the output.
*/
public ColorModel getColorModel() {
return model;
}
/**
* Return a Raster containing the colors generated for the graphics
* operation.
* @param x,y,w,h The area in device space for which colors are
* generated.
*/
public Raster getRaster(int x, int y, int w, int h) {
double rowrel = (x - x1) * dx + (y - y1) * dy;
Raster rast = saved;
if (rast == null || rast.getWidth() < w || rast.getHeight() < h) {
rast = getCachedRaster(model, w, h);
saved = rast;
}
IntegerComponentRaster irast = (IntegerComponentRaster) rast;
int off = irast.getDataOffset(0);
int adjust = irast.getScanlineStride() - w;
int[] pixels = irast.getDataStorage();
if (cyclic) {
cycleFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
} else {
clipFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
}
irast.markDirty();
return rast;
}
void cycleFillRaster(int[] pixels, int off, int adjust, int w, int h,
double rowrel, double dx, double dy) {
rowrel = rowrel % 2.0;
int irowrel = ((int) (rowrel * (1 << 30))) << 1;
int idx = (int) (-dx * (1 << 31));
int idy = (int) (-dy * (1 << 31));
while (--h >= 0) {
int icolrel = irowrel;
for (int j = w; j > 0; j--) {
pixels[off++] = interp[icolrel >>> 23];
icolrel += idx;
}
off += adjust;
irowrel += idy;
}
}
void clipFillRaster(int[] pixels, int off, int adjust, int w, int h,
double rowrel, double dx, double dy) {
while (--h >= 0) {
double colrel = rowrel;
int j = w;
if (colrel <= 0.0) {
int rgb = interp[0];
do {
pixels[off++] = rgb;
colrel += dx;
} while (--j > 0 && colrel <= 0.0);
}
while (colrel < 1.0 && --j >= 0) {
pixels[off++] = interp[(int) (colrel * 256)];
colrel += dx;
}
if (j > 0) {
int rgb = interp[256];
do {
pixels[off++] = rgb;
} while (--j > 0);
}
off += adjust;
rowrel += dy;
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.LightweightPeer;
import sun.awt.SunGraphicsCallback;
abstract class GraphicsCallback extends SunGraphicsCallback {
static final class PaintCallback extends GraphicsCallback {
private static PaintCallback instance = new PaintCallback();
private PaintCallback() {}
public void run(Component comp, Graphics cg) {
comp.paint(cg);
}
static PaintCallback getInstance() {
return instance;
}
}
static final class PrintCallback extends GraphicsCallback {
private static PrintCallback instance = new PrintCallback();
private PrintCallback() {}
public void run(Component comp, Graphics cg) {
comp.print(cg);
}
static PrintCallback getInstance() {
return instance;
}
}
static final class PaintAllCallback extends GraphicsCallback {
private static PaintAllCallback instance = new PaintAllCallback();
private PaintAllCallback() {}
public void run(Component comp, Graphics cg) {
comp.paintAll(cg);
}
static PaintAllCallback getInstance() {
return instance;
}
}
static final class PrintAllCallback extends GraphicsCallback {
private static PrintAllCallback instance = new PrintAllCallback();
private PrintAllCallback() {}
public void run(Component comp, Graphics cg) {
comp.printAll(cg);
}
static PrintAllCallback getInstance() {
return instance;
}
}
static final class PeerPaintCallback extends GraphicsCallback {
private static PeerPaintCallback instance = new PeerPaintCallback();
private PeerPaintCallback() {}
public void run(Component comp, Graphics cg) {
comp.validate();
if (comp.peer instanceof LightweightPeer) {
comp.lightweightPaint(cg);
} else {
comp.peer.paint(cg);
}
}
static PeerPaintCallback getInstance() {
return instance;
}
}
static final class PeerPrintCallback extends GraphicsCallback {
private static PeerPrintCallback instance = new PeerPrintCallback();
private PeerPrintCallback() {}
public void run(Component comp, Graphics cg) {
comp.validate();
if (comp.peer instanceof LightweightPeer) {
comp.lightweightPrint(cg);
} else {
comp.peer.print(cg);
}
}
static PeerPrintCallback getInstance() {
return instance;
}
}
static final class PaintHeavyweightComponentsCallback
extends GraphicsCallback
{
private static PaintHeavyweightComponentsCallback instance =
new PaintHeavyweightComponentsCallback();
private PaintHeavyweightComponentsCallback() {}
public void run(Component comp, Graphics cg) {
if (comp.peer instanceof LightweightPeer) {
comp.paintHeavyweightComponents(cg);
} else {
comp.paintAll(cg);
}
}
static PaintHeavyweightComponentsCallback getInstance() {
return instance;
}
}
static final class PrintHeavyweightComponentsCallback
extends GraphicsCallback
{
private static PrintHeavyweightComponentsCallback instance =
new PrintHeavyweightComponentsCallback();
private PrintHeavyweightComponentsCallback() {}
public void run(Component comp, Graphics cg) {
if (comp.peer instanceof LightweightPeer) {
comp.printHeavyweightComponents(cg);
} else {
comp.printAll(cg);
}
}
static PrintHeavyweightComponentsCallback getInstance() {
return instance;
}
}
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.io.*;
/**
* The {@code GraphicsConfigTemplate} class is used to obtain a valid
* {@link GraphicsConfiguration}. A user instantiates one of these
* objects and then sets all non-default attributes as desired. The
* {@link GraphicsDevice#getBestConfiguration} method found in the
* {@link GraphicsDevice} class is then called with this
* {@code GraphicsConfigTemplate}. A valid
* {@code GraphicsConfiguration} is returned that meets or exceeds
* what was requested in the {@code GraphicsConfigTemplate}.
* @see GraphicsDevice
* @see GraphicsConfiguration
*
* @since 1.2
*/
public abstract class GraphicsConfigTemplate implements Serializable {
/*
* serialVersionUID
*/
private static final long serialVersionUID = -8061369279557787079L;
/**
* This class is an abstract class so only subclasses can be
* instantiated.
*/
public GraphicsConfigTemplate() {
}
/**
* Value used for "Enum" (Integer) type. States that this
* feature is required for the {@code GraphicsConfiguration}
* object. If this feature is not available, do not select the
* {@code GraphicsConfiguration} object.
*/
public static final int REQUIRED = 1;
/**
* Value used for "Enum" (Integer) type. States that this
* feature is desired for the {@code GraphicsConfiguration}
* object. A selection with this feature is preferred over a
* selection that does not include this feature, although both
* selections can be considered valid matches.
*/
public static final int PREFERRED = 2;
/**
* Value used for "Enum" (Integer) type. States that this
* feature is not necessary for the selection of the
* {@code GraphicsConfiguration} object. A selection
* without this feature is preferred over a selection that
* includes this feature since it is not used.
*/
public static final int UNNECESSARY = 3;
/**
* Returns the "best" configuration possible that passes the
* criteria defined in the {@code GraphicsConfigTemplate}.
* @param gc the array of {@code GraphicsConfiguration}
* objects to choose from.
* @return a {@code GraphicsConfiguration} object that is
* the best configuration possible.
* @see GraphicsConfiguration
*/
public abstract GraphicsConfiguration
getBestConfiguration(GraphicsConfiguration[] gc);
/**
* Returns a {@code boolean} indicating whether or
* not the specified {@code GraphicsConfiguration} can be
* used to create a drawing surface that supports the indicated
* features.
* @param gc the {@code GraphicsConfiguration} object to test
* @return {@code true} if this
* {@code GraphicsConfiguration} object can be used to create
* surfaces that support the indicated features;
* {@code false} if the {@code GraphicsConfiguration} can
* not be used to create a drawing surface usable by this Java(tm)
* API.
*/
public abstract boolean
isGraphicsConfigSupported(GraphicsConfiguration gc);
}

View file

@ -0,0 +1,453 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import sun.awt.image.SunVolatileImage;
/**
* The {@code GraphicsConfiguration} class describes the
* characteristics of a graphics destination such as a printer or monitor.
* There can be many {@code GraphicsConfiguration} objects associated
* with a single graphics device, representing different drawing modes or
* capabilities. The corresponding native structure will vary from platform
* to platform. For example, on X11 windowing systems,
* each visual is a different {@code GraphicsConfiguration}.
* On Microsoft Windows, {@code GraphicsConfiguration}s represent
* PixelFormats available in the current resolution and color depth.
* <p>
* In a virtual device multi-screen environment in which the desktop
* area could span multiple physical screen devices, the bounds of the
* {@code GraphicsConfiguration} objects are relative to the
* virtual coordinate system. When setting the location of a
* component, use {@link #getBounds() getBounds} to get the bounds of
* the desired {@code GraphicsConfiguration} and offset the location
* with the coordinates of the {@code GraphicsConfiguration},
* as the following code sample illustrates:
* </p>
*
* <pre>
* Frame f = new Frame(gc); // where gc is a GraphicsConfiguration
* Rectangle bounds = gc.getBounds();
* f.setLocation(10 + bounds.x, 10 + bounds.y); </pre>
*
* <p>
* To determine if your environment is a virtual device
* environment, call {@code getBounds} on all of the
* {@code GraphicsConfiguration} objects in your system. If
* any of the origins of the returned bounds is not (0,&nbsp;0),
* your environment is a virtual device environment.
*
* <p>
* You can also use {@code getBounds} to determine the bounds
* of the virtual device. To do this, first call {@code getBounds} on all
* of the {@code GraphicsConfiguration} objects in your
* system. Then calculate the union of all of the bounds returned
* from the calls to {@code getBounds}. The union is the
* bounds of the virtual device. The following code sample
* calculates the bounds of the virtual device.
*
* <pre>{@code
* Rectangle virtualBounds = new Rectangle();
* GraphicsEnvironment ge = GraphicsEnvironment.
* getLocalGraphicsEnvironment();
* GraphicsDevice[] gs =
* ge.getScreenDevices();
* for (int j = 0; j < gs.length; j++) {
* GraphicsDevice gd = gs[j];
* GraphicsConfiguration[] gc =
* gd.getConfigurations();
* for (int i=0; i < gc.length; i++) {
* virtualBounds =
* virtualBounds.union(gc[i].getBounds());
* }
* } }</pre>
*
* @see Window
* @see Frame
* @see GraphicsEnvironment
* @see GraphicsDevice
*/
/*
* REMIND: What to do about capabilities?
* The
* capabilities of the device can be determined by enumerating the possible
* capabilities and checking if the GraphicsConfiguration
* implements the interface for that capability.
*
*/
public abstract class GraphicsConfiguration {
private static BufferCapabilities defaultBufferCaps;
private static ImageCapabilities defaultImageCaps;
/**
* This is an abstract class that cannot be instantiated directly.
* Instances must be obtained from a suitable factory or query method.
*
* @see GraphicsDevice#getConfigurations
* @see GraphicsDevice#getDefaultConfiguration
* @see GraphicsDevice#getBestConfiguration
* @see Graphics2D#getDeviceConfiguration
*/
protected GraphicsConfiguration() {
}
/**
* Returns the {@link GraphicsDevice} associated with this
* {@code GraphicsConfiguration}.
* @return a {@code GraphicsDevice} object that is
* associated with this {@code GraphicsConfiguration}.
*/
public abstract GraphicsDevice getDevice();
/**
* Returns a {@link BufferedImage} with a data layout and color model
* compatible with this {@code GraphicsConfiguration}. This
* method has nothing to do with memory-mapping
* a device. The returned {@code BufferedImage} has
* a layout and color model that is closest to this native device
* configuration and can therefore be optimally blitted to this
* device.
* @param width the width of the returned {@code BufferedImage}
* @param height the height of the returned {@code BufferedImage}
* @return a {@code BufferedImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}.
*/
public BufferedImage createCompatibleImage(int width, int height) {
ColorModel model = getColorModel();
WritableRaster raster =
model.createCompatibleWritableRaster(width, height);
return new BufferedImage(model, raster,
model.isAlphaPremultiplied(), null);
}
/**
* Returns a {@code BufferedImage} that supports the specified
* transparency and has a data layout and color model
* compatible with this {@code GraphicsConfiguration}. This
* method has nothing to do with memory-mapping
* a device. The returned {@code BufferedImage} has a layout and
* color model that can be optimally blitted to a device
* with this {@code GraphicsConfiguration}.
* @param width the width of the returned {@code BufferedImage}
* @param height the height of the returned {@code BufferedImage}
* @param transparency the specified transparency mode
* @return a {@code BufferedImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}
* and also supports the specified transparency.
* @throws IllegalArgumentException if the transparency is not a valid value
* @see Transparency#OPAQUE
* @see Transparency#BITMASK
* @see Transparency#TRANSLUCENT
*/
public BufferedImage createCompatibleImage(int width, int height,
int transparency)
{
if (getColorModel().getTransparency() == transparency) {
return createCompatibleImage(width, height);
}
ColorModel cm = getColorModel(transparency);
if (cm == null) {
throw new IllegalArgumentException("Unknown transparency: " +
transparency);
}
WritableRaster wr = cm.createCompatibleWritableRaster(width, height);
return new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
}
/**
* Returns a {@link VolatileImage} with a data layout and color model
* compatible with this {@code GraphicsConfiguration}.
* The returned {@code VolatileImage}
* may have data that is stored optimally for the underlying graphics
* device and may therefore benefit from platform-specific rendering
* acceleration.
* @param width the width of the returned {@code VolatileImage}
* @param height the height of the returned {@code VolatileImage}
* @return a {@code VolatileImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}.
* @see Component#createVolatileImage(int, int)
* @since 1.4
*/
public VolatileImage createCompatibleVolatileImage(int width, int height) {
VolatileImage vi = null;
try {
vi = createCompatibleVolatileImage(width, height,
null, Transparency.OPAQUE);
} catch (AWTException e) {
// shouldn't happen: we're passing in null caps
assert false;
}
return vi;
}
/**
* Returns a {@link VolatileImage} with a data layout and color model
* compatible with this {@code GraphicsConfiguration}.
* The returned {@code VolatileImage}
* may have data that is stored optimally for the underlying graphics
* device and may therefore benefit from platform-specific rendering
* acceleration.
* @param width the width of the returned {@code VolatileImage}
* @param height the height of the returned {@code VolatileImage}
* @param transparency the specified transparency mode
* @return a {@code VolatileImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}.
* @throws IllegalArgumentException if the transparency is not a valid value
* @see Transparency#OPAQUE
* @see Transparency#BITMASK
* @see Transparency#TRANSLUCENT
* @see Component#createVolatileImage(int, int)
* @since 1.5
*/
public VolatileImage createCompatibleVolatileImage(int width, int height,
int transparency)
{
VolatileImage vi = null;
try {
vi = createCompatibleVolatileImage(width, height, null, transparency);
} catch (AWTException e) {
// shouldn't happen: we're passing in null caps
assert false;
}
return vi;
}
/**
* Returns a {@link VolatileImage} with a data layout and color model
* compatible with this {@code GraphicsConfiguration}, using
* the specified image capabilities.
* If the {@code caps} parameter is null, it is effectively ignored
* and this method will create a VolatileImage without regard to
* {@code ImageCapabilities} constraints.
*
* The returned {@code VolatileImage} has
* a layout and color model that is closest to this native device
* configuration and can therefore be optimally blitted to this
* device.
* @return a {@code VolatileImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}.
* @param width the width of the returned {@code VolatileImage}
* @param height the height of the returned {@code VolatileImage}
* @param caps the image capabilities
* @exception AWTException if the supplied image capabilities could not
* be met by this graphics configuration
* @since 1.4
*/
public VolatileImage createCompatibleVolatileImage(int width, int height,
ImageCapabilities caps) throws AWTException
{
return createCompatibleVolatileImage(width, height, caps,
Transparency.OPAQUE);
}
/**
* Returns a {@link VolatileImage} with a data layout and color model
* compatible with this {@code GraphicsConfiguration}, using
* the specified image capabilities and transparency value.
* If the {@code caps} parameter is null, it is effectively ignored
* and this method will create a VolatileImage without regard to
* {@code ImageCapabilities} constraints.
*
* The returned {@code VolatileImage} has
* a layout and color model that is closest to this native device
* configuration and can therefore be optimally blitted to this
* device.
* @param width the width of the returned {@code VolatileImage}
* @param height the height of the returned {@code VolatileImage}
* @param caps the image capabilities
* @param transparency the specified transparency mode
* @return a {@code VolatileImage} whose data layout and color
* model is compatible with this {@code GraphicsConfiguration}.
* @see Transparency#OPAQUE
* @see Transparency#BITMASK
* @see Transparency#TRANSLUCENT
* @throws IllegalArgumentException if the transparency is not a valid value
* @exception AWTException if the supplied image capabilities could not
* be met by this graphics configuration
* @see Component#createVolatileImage(int, int)
* @since 1.5
*/
public VolatileImage createCompatibleVolatileImage(int width, int height,
ImageCapabilities caps, int transparency) throws AWTException
{
VolatileImage vi =
new SunVolatileImage(this, width, height, transparency, caps);
if (caps != null && caps.isAccelerated() &&
!vi.getCapabilities().isAccelerated())
{
throw new AWTException("Supplied image capabilities could not " +
"be met by this graphics configuration.");
}
return vi;
}
/**
* Returns the {@link ColorModel} associated with this
* {@code GraphicsConfiguration}.
* @return a {@code ColorModel} object that is associated with
* this {@code GraphicsConfiguration}.
*/
public abstract ColorModel getColorModel();
/**
* Returns the {@code ColorModel} associated with this
* {@code GraphicsConfiguration} that supports the specified
* transparency.
* @param transparency the specified transparency mode
* @return a {@code ColorModel} object that is associated with
* this {@code GraphicsConfiguration} and supports the
* specified transparency or null if the transparency is not a valid
* value.
* @see Transparency#OPAQUE
* @see Transparency#BITMASK
* @see Transparency#TRANSLUCENT
*/
public abstract ColorModel getColorModel(int transparency);
/**
* Returns the default {@link AffineTransform} for this
* {@code GraphicsConfiguration}. This
* {@code AffineTransform} is typically the Identity transform
* for most normal screens. The default {@code AffineTransform}
* maps coordinates onto the device such that 72 user space
* coordinate units measure approximately 1 inch in device
* space. The normalizing transform can be used to make
* this mapping more exact. Coordinates in the coordinate space
* defined by the default {@code AffineTransform} for screen and
* printer devices have the origin in the upper left-hand corner of
* the target region of the device, with X coordinates
* increasing to the right and Y coordinates increasing downwards.
* For image buffers not associated with a device, such as those not
* created by {@code createCompatibleImage},
* this {@code AffineTransform} is the Identity transform.
* @return the default {@code AffineTransform} for this
* {@code GraphicsConfiguration}.
*/
public abstract AffineTransform getDefaultTransform();
/**
* Returns an {@code AffineTransform} that can be concatenated
* with the default {@code AffineTransform}
* of a {@code GraphicsConfiguration} so that 72 units in user
* space equals 1 inch in device space.
* <p>
* For a particular {@link Graphics2D}, g, one
* can reset the transformation to create
* such a mapping by using the following pseudocode:
* <pre>
* GraphicsConfiguration gc = g.getDeviceConfiguration();
*
* g.setTransform(gc.getDefaultTransform());
* g.transform(gc.getNormalizingTransform());
* </pre>
* Note that sometimes this {@code AffineTransform} is identity,
* such as for printers or metafile output, and that this
* {@code AffineTransform} is only as accurate as the information
* supplied by the underlying system. For image buffers not
* associated with a device, such as those not created by
* {@code createCompatibleImage}, this
* {@code AffineTransform} is the Identity transform
* since there is no valid distance measurement.
* @return an {@code AffineTransform} to concatenate to the
* default {@code AffineTransform} so that 72 units in user
* space is mapped to 1 inch in device space.
*/
public abstract AffineTransform getNormalizingTransform();
/**
* Returns the bounds of the {@code GraphicsConfiguration}
* in the device coordinates. In a multi-screen environment
* with a virtual device, the bounds can have negative X
* or Y origins.
* @return the bounds of the area covered by this
* {@code GraphicsConfiguration}.
* @since 1.3
*/
public abstract Rectangle getBounds();
private static class DefaultBufferCapabilities extends BufferCapabilities {
public DefaultBufferCapabilities(ImageCapabilities imageCaps) {
super(imageCaps, imageCaps, null);
}
}
/**
* Returns the buffering capabilities of this
* {@code GraphicsConfiguration}.
* @return the buffering capabilities of this graphics
* configuration object
* @since 1.4
*/
public BufferCapabilities getBufferCapabilities() {
if (defaultBufferCaps == null) {
defaultBufferCaps = new DefaultBufferCapabilities(
getImageCapabilities());
}
return defaultBufferCaps;
}
/**
* Returns the image capabilities of this
* {@code GraphicsConfiguration}.
* @return the image capabilities of this graphics
* configuration object
* @since 1.4
*/
public ImageCapabilities getImageCapabilities() {
if (defaultImageCaps == null) {
defaultImageCaps = new ImageCapabilities(false);
}
return defaultImageCaps;
}
/**
* Returns whether this {@code GraphicsConfiguration} supports
* the {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
* PERPIXEL_TRANSLUCENT} kind of translucency.
*
* @return whether the given GraphicsConfiguration supports
* the translucency effects.
*
* @see Window#setBackground(Color)
*
* @since 1.7
*/
public boolean isTranslucencyCapable() {
// Overridden in subclasses
return false;
}
}

View file

@ -0,0 +1,594 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ColorModel;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
/**
* The {@code GraphicsDevice} class describes the graphics devices
* that might be available in a particular graphics environment. These
* include screen and printer devices. Note that there can be many screens
* and many printers in an instance of {@link GraphicsEnvironment}. Each
* graphics device has one or more {@link GraphicsConfiguration} objects
* associated with it. These objects specify the different configurations
* in which the {@code GraphicsDevice} can be used.
* <p>
* In a multi-screen environment, the {@code GraphicsConfiguration}
* objects can be used to render components on multiple screens. The
* following code sample demonstrates how to create a {@code JFrame}
* object for each {@code GraphicsConfiguration} on each screen
* device in the {@code GraphicsEnvironment}:
* <pre>{@code
* GraphicsEnvironment ge = GraphicsEnvironment.
* getLocalGraphicsEnvironment();
* GraphicsDevice[] gs = ge.getScreenDevices();
* for (int j = 0; j < gs.length; j++) {
* GraphicsDevice gd = gs[j];
* GraphicsConfiguration[] gc =
* gd.getConfigurations();
* for (int i=0; i < gc.length; i++) {
* JFrame f = new
* JFrame(gs[j].getDefaultConfiguration());
* Canvas c = new Canvas(gc[i]);
* Rectangle gcBounds = gc[i].getBounds();
* int xoffs = gcBounds.x;
* int yoffs = gcBounds.y;
* f.getContentPane().add(c);
* f.setLocation((i*50)+xoffs, (i*60)+yoffs);
* f.show();
* }
* }
* }</pre>
* <p>
* For more information on full-screen exclusive mode API, see the
* <a href="http://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html">
* Full-Screen Exclusive Mode API Tutorial</a>.
*
* @see GraphicsEnvironment
* @see GraphicsConfiguration
*/
public abstract class GraphicsDevice {
private Window fullScreenWindow;
private AppContext fullScreenAppContext; // tracks which AppContext
// created the FS window
// this lock is used for making synchronous changes to the AppContext's
// current full screen window
private final Object fsAppContextLock = new Object();
private Rectangle windowedModeBounds;
/**
* This is an abstract class that cannot be instantiated directly.
* Instances must be obtained from a suitable factory or query method.
* @see GraphicsEnvironment#getScreenDevices
* @see GraphicsEnvironment#getDefaultScreenDevice
* @see GraphicsConfiguration#getDevice
*/
protected GraphicsDevice() {
}
/**
* Device is a raster screen.
*/
public static final int TYPE_RASTER_SCREEN = 0;
/**
* Device is a printer.
*/
public static final int TYPE_PRINTER = 1;
/**
* Device is an image buffer. This buffer can reside in device
* or system memory but it is not physically viewable by the user.
*/
public static final int TYPE_IMAGE_BUFFER = 2;
/**
* Kinds of translucency supported by the underlying system.
*
* @see #isWindowTranslucencySupported
*
* @since 1.7
*/
public static enum WindowTranslucency {
/**
* Represents support in the underlying system for windows each pixel
* of which is guaranteed to be either completely opaque, with
* an alpha value of 1.0, or completely transparent, with an alpha
* value of 0.0.
*/
PERPIXEL_TRANSPARENT,
/**
* Represents support in the underlying system for windows all of
* the pixels of which have the same alpha value between or including
* 0.0 and 1.0.
*/
TRANSLUCENT,
/**
* Represents support in the underlying system for windows that
* contain or might contain pixels with arbitrary alpha values
* between and including 0.0 and 1.0.
*/
PERPIXEL_TRANSLUCENT;
}
/**
* Returns the type of this {@code GraphicsDevice}.
* @return the type of this {@code GraphicsDevice}, which can
* either be TYPE_RASTER_SCREEN, TYPE_PRINTER or TYPE_IMAGE_BUFFER.
* @see #TYPE_RASTER_SCREEN
* @see #TYPE_PRINTER
* @see #TYPE_IMAGE_BUFFER
*/
public abstract int getType();
/**
* Returns the identification string associated with this
* {@code GraphicsDevice}.
* <p>
* A particular program might use more than one
* {@code GraphicsDevice} in a {@code GraphicsEnvironment}.
* This method returns a {@code String} identifying a
* particular {@code GraphicsDevice} in the local
* {@code GraphicsEnvironment}. Although there is
* no public method to set this {@code String}, a programmer can
* use the {@code String} for debugging purposes. Vendors of
* the Java&trade; Runtime Environment can
* format the return value of the {@code String}. To determine
* how to interpret the value of the {@code String}, contact the
* vendor of your Java Runtime. To find out who the vendor is, from
* your program, call the
* {@link System#getProperty(String) getProperty} method of the
* System class with "java.vendor".
* @return a {@code String} that is the identification
* of this {@code GraphicsDevice}.
*/
public abstract String getIDstring();
/**
* Returns all of the {@code GraphicsConfiguration}
* objects associated with this {@code GraphicsDevice}.
* @return an array of {@code GraphicsConfiguration}
* objects that are associated with this
* {@code GraphicsDevice}.
*/
public abstract GraphicsConfiguration[] getConfigurations();
/**
* Returns the default {@code GraphicsConfiguration}
* associated with this {@code GraphicsDevice}.
* @return the default {@code GraphicsConfiguration}
* of this {@code GraphicsDevice}.
*/
public abstract GraphicsConfiguration getDefaultConfiguration();
/**
* Returns the "best" configuration possible that passes the
* criteria defined in the {@link GraphicsConfigTemplate}.
* @param gct the {@code GraphicsConfigTemplate} object
* used to obtain a valid {@code GraphicsConfiguration}
* @return a {@code GraphicsConfiguration} that passes
* the criteria defined in the specified
* {@code GraphicsConfigTemplate}.
* @see GraphicsConfigTemplate
*/
public GraphicsConfiguration
getBestConfiguration(GraphicsConfigTemplate gct) {
GraphicsConfiguration[] configs = getConfigurations();
return gct.getBestConfiguration(configs);
}
/**
* Returns {@code true} if this {@code GraphicsDevice}
* supports full-screen exclusive mode.
* If a SecurityManager is installed, its
* {@code checkPermission} method will be called
* with {@code AWTPermission("fullScreenExclusive")}.
* {@code isFullScreenSupported} returns true only if
* that permission is granted.
* @return whether full-screen exclusive mode is available for
* this graphics device
* @see java.awt.AWTPermission
* @since 1.4
*/
public boolean isFullScreenSupported() {
return false;
}
/**
* Enter full-screen mode, or return to windowed mode. The entered
* full-screen mode may be either exclusive or simulated. Exclusive
* mode is only available if {@code isFullScreenSupported}
* returns {@code true}.
* <p>
* Exclusive mode implies:
* <ul>
* <li>Windows cannot overlap the full-screen window. All other application
* windows will always appear beneath the full-screen window in the Z-order.
* <li>There can be only one full-screen window on a device at any time,
* so calling this method while there is an existing full-screen Window
* will cause the existing full-screen window to
* return to windowed mode.
* <li>Input method windows are disabled. It is advisable to call
* {@code Component.enableInputMethods(false)} to make a component
* a non-client of the input method framework.
* </ul>
* <p>
* The simulated full-screen mode places and resizes the window to the maximum
* possible visible area of the screen. However, the native windowing system
* may modify the requested geometry-related data, so that the {@code Window} object
* is placed and sized in a way that corresponds closely to the desktop settings.
* <p>
* When entering full-screen mode, if the window to be used as a
* full-screen window is not visible, this method will make it visible.
* It will remain visible when returning to windowed mode.
* <p>
* When entering full-screen mode, all the translucency effects are reset for
* the window. Its shape is set to {@code null}, the opacity value is set to
* 1.0f, and the background color alpha is set to 255 (completely opaque).
* These values are not restored when returning to windowed mode.
* <p>
* It is unspecified and platform-dependent how decorated windows operate
* in full-screen mode. For this reason, it is recommended to turn off
* the decorations in a {@code Frame} or {@code Dialog} object by using the
* {@code setUndecorated} method.
* <p>
* When returning to windowed mode from an exclusive full-screen window,
* any display changes made by calling {@code setDisplayMode} are
* automatically restored to their original state.
*
* @param w a window to use as the full-screen window; {@code null}
* if returning to windowed mode. Some platforms expect the
* fullscreen window to be a top-level component (i.e., a {@code Frame});
* therefore it is preferable to use a {@code Frame} here rather than a
* {@code Window}.
*
* @see #isFullScreenSupported
* @see #getFullScreenWindow
* @see #setDisplayMode
* @see Component#enableInputMethods
* @see Component#setVisible
* @see Frame#setUndecorated
* @see Dialog#setUndecorated
*
* @since 1.4
*/
public void setFullScreenWindow(Window w) {
if (w != null) {
if (w.getShape() != null) {
w.setShape(null);
}
if (w.getOpacity() < 1.0f) {
w.setOpacity(1.0f);
}
if (!w.isOpaque()) {
Color bgColor = w.getBackground();
bgColor = new Color(bgColor.getRed(), bgColor.getGreen(),
bgColor.getBlue(), 255);
w.setBackground(bgColor);
}
// Check if this window is in fullscreen mode on another device.
final GraphicsConfiguration gc = w.getGraphicsConfiguration();
if (gc != null && gc.getDevice() != this
&& gc.getDevice().getFullScreenWindow() == w) {
gc.getDevice().setFullScreenWindow(null);
}
}
if (fullScreenWindow != null && windowedModeBounds != null) {
// if the window went into fs mode before it was realized it may
// have (0,0) dimensions
if (windowedModeBounds.width == 0) windowedModeBounds.width = 1;
if (windowedModeBounds.height == 0) windowedModeBounds.height = 1;
fullScreenWindow.setBounds(windowedModeBounds);
}
// Set the full screen window
synchronized (fsAppContextLock) {
// Associate fullscreen window with current AppContext
if (w == null) {
fullScreenAppContext = null;
} else {
fullScreenAppContext = AppContext.getAppContext();
}
fullScreenWindow = w;
}
if (fullScreenWindow != null) {
windowedModeBounds = fullScreenWindow.getBounds();
// Note that we use the graphics configuration of the device,
// not the window's, because we're setting the fs window for
// this device.
final GraphicsConfiguration gc = getDefaultConfiguration();
final Rectangle screenBounds = gc.getBounds();
if (SunToolkit.isDispatchThreadForAppContext(fullScreenWindow)) {
// Update graphics configuration here directly and do not wait
// asynchronous notification from the peer. Note that
// setBounds() will reset a GC, if it was set incorrectly.
fullScreenWindow.setGraphicsConfiguration(gc);
}
fullScreenWindow.setBounds(screenBounds.x, screenBounds.y,
screenBounds.width, screenBounds.height);
fullScreenWindow.setVisible(true);
fullScreenWindow.toFront();
}
}
/**
* Returns the {@code Window} object representing the
* full-screen window if the device is in full-screen mode.
*
* @return the full-screen window, or {@code null} if the device is
* not in full-screen mode.
* @see #setFullScreenWindow(Window)
* @since 1.4
*/
public Window getFullScreenWindow() {
Window returnWindow = null;
synchronized (fsAppContextLock) {
// Only return a handle to the current fs window if we are in the
// same AppContext that set the fs window
if (fullScreenAppContext == AppContext.getAppContext()) {
returnWindow = fullScreenWindow;
}
}
return returnWindow;
}
/**
* Returns {@code true} if this {@code GraphicsDevice}
* supports low-level display changes.
* On some platforms low-level display changes may only be allowed in
* full-screen exclusive mode (i.e., if {@link #isFullScreenSupported()}
* returns {@code true} and the application has already entered
* full-screen mode using {@link #setFullScreenWindow}).
* @return whether low-level display changes are supported for this
* graphics device.
* @see #isFullScreenSupported
* @see #setDisplayMode
* @see #setFullScreenWindow
* @since 1.4
*/
public boolean isDisplayChangeSupported() {
return false;
}
/**
* Sets the display mode of this graphics device. This is only allowed
* if {@link #isDisplayChangeSupported()} returns {@code true} and may
* require first entering full-screen exclusive mode using
* {@link #setFullScreenWindow} providing that full-screen exclusive mode is
* supported (i.e., {@link #isFullScreenSupported()} returns
* {@code true}).
* <p>
*
* The display mode must be one of the display modes returned by
* {@link #getDisplayModes()}, with one exception: passing a display mode
* with {@link DisplayMode#REFRESH_RATE_UNKNOWN} refresh rate will result in
* selecting a display mode from the list of available display modes with
* matching width, height and bit depth.
* However, passing a display mode with {@link DisplayMode#BIT_DEPTH_MULTI}
* for bit depth is only allowed if such mode exists in the list returned by
* {@link #getDisplayModes()}.
* <p>
* Example code:
* <pre><code>
* Frame frame;
* DisplayMode newDisplayMode;
* GraphicsDevice gd;
* // create a Frame, select desired DisplayMode from the list of modes
* // returned by gd.getDisplayModes() ...
*
* if (gd.isFullScreenSupported()) {
* gd.setFullScreenWindow(frame);
* } else {
* // proceed in non-full-screen mode
* frame.setSize(...);
* frame.setLocation(...);
* frame.setVisible(true);
* }
*
* if (gd.isDisplayChangeSupported()) {
* gd.setDisplayMode(newDisplayMode);
* }
* </code></pre>
*
* @param dm The new display mode of this graphics device.
* @exception IllegalArgumentException if the {@code DisplayMode}
* supplied is {@code null}, or is not available in the array returned
* by {@code getDisplayModes}
* @exception UnsupportedOperationException if
* {@code isDisplayChangeSupported} returns {@code false}
* @see #getDisplayMode
* @see #getDisplayModes
* @see #isDisplayChangeSupported
* @since 1.4
*/
public void setDisplayMode(DisplayMode dm) {
throw new UnsupportedOperationException("Cannot change display mode");
}
/**
* Returns the current display mode of this
* {@code GraphicsDevice}.
* The returned display mode is allowed to have a refresh rate
* {@link DisplayMode#REFRESH_RATE_UNKNOWN} if it is indeterminate.
* Likewise, the returned display mode is allowed to have a bit depth
* {@link DisplayMode#BIT_DEPTH_MULTI} if it is indeterminate or if multiple
* bit depths are supported.
* @return the current display mode of this graphics device.
* @see #setDisplayMode(DisplayMode)
* @since 1.4
*/
public DisplayMode getDisplayMode() {
GraphicsConfiguration gc = getDefaultConfiguration();
Rectangle r = gc.getBounds();
ColorModel cm = gc.getColorModel();
return new DisplayMode(r.width, r.height, cm.getPixelSize(), 0);
}
/**
* Returns all display modes available for this
* {@code GraphicsDevice}.
* The returned display modes are allowed to have a refresh rate
* {@link DisplayMode#REFRESH_RATE_UNKNOWN} if it is indeterminate.
* Likewise, the returned display modes are allowed to have a bit depth
* {@link DisplayMode#BIT_DEPTH_MULTI} if it is indeterminate or if multiple
* bit depths are supported.
* @return all of the display modes available for this graphics device.
* @since 1.4
*/
public DisplayMode[] getDisplayModes() {
return new DisplayMode[] { getDisplayMode() };
}
/**
* This method returns the number of bytes available in
* accelerated memory on this device.
* Some images are created or cached
* in accelerated memory on a first-come,
* first-served basis. On some operating systems,
* this memory is a finite resource. Calling this method
* and scheduling the creation and flushing of images carefully may
* enable applications to make the most efficient use of
* that finite resource.
* <br>
* Note that the number returned is a snapshot of how much
* memory is available; some images may still have problems
* being allocated into that memory. For example, depending
* on operating system, driver, memory configuration, and
* thread situations, the full extent of the size reported
* may not be available for a given image. There are further
* inquiry methods on the {@link ImageCapabilities} object
* associated with a VolatileImage that can be used to determine
* whether a particular VolatileImage has been created in accelerated
* memory.
* @return number of bytes available in accelerated memory.
* A negative return value indicates that the amount of accelerated memory
* on this GraphicsDevice is indeterminate.
* @see java.awt.image.VolatileImage#flush
* @see ImageCapabilities#isAccelerated
* @since 1.4
*/
public int getAvailableAcceleratedMemory() {
return -1;
}
/**
* Returns whether the given level of translucency is supported by
* this graphics device.
*
* @param translucencyKind a kind of translucency support
* @return whether the given translucency kind is supported
*
* @since 1.7
*/
public boolean isWindowTranslucencySupported(WindowTranslucency translucencyKind) {
switch (translucencyKind) {
case PERPIXEL_TRANSPARENT:
return isWindowShapingSupported();
case TRANSLUCENT:
return isWindowOpacitySupported();
case PERPIXEL_TRANSLUCENT:
return isWindowPerpixelTranslucencySupported();
}
return false;
}
/**
* Returns whether the windowing system supports changing the shape
* of top-level windows.
* Note that this method may sometimes return true, but the native
* windowing system may still not support the concept of
* shaping (due to the bugs in the windowing system).
*/
static boolean isWindowShapingSupported() {
Toolkit curToolkit = Toolkit.getDefaultToolkit();
if (!(curToolkit instanceof SunToolkit)) {
return false;
}
return ((SunToolkit)curToolkit).isWindowShapingSupported();
}
/**
* Returns whether the windowing system supports changing the opacity
* value of top-level windows.
* Note that this method may sometimes return true, but the native
* windowing system may still not support the concept of
* translucency (due to the bugs in the windowing system).
*/
static boolean isWindowOpacitySupported() {
Toolkit curToolkit = Toolkit.getDefaultToolkit();
if (!(curToolkit instanceof SunToolkit)) {
return false;
}
return ((SunToolkit)curToolkit).isWindowOpacitySupported();
}
boolean isWindowPerpixelTranslucencySupported() {
/*
* Per-pixel alpha is supported if all the conditions are TRUE:
* 1. The toolkit is a sort of SunToolkit
* 2. The toolkit supports translucency in general
* (isWindowTranslucencySupported())
* 3. There's at least one translucency-capable
* GraphicsConfiguration
*/
Toolkit curToolkit = Toolkit.getDefaultToolkit();
if (!(curToolkit instanceof SunToolkit)) {
return false;
}
if (!((SunToolkit)curToolkit).isWindowTranslucencySupported()) {
return false;
}
// TODO: cache translucency capable GC
return getTranslucencyCapableGC() != null;
}
GraphicsConfiguration getTranslucencyCapableGC() {
// If the default GC supports translucency return true.
// It is important to optimize the verification this way,
// see CR 6661196 for more details.
GraphicsConfiguration defaultGC = getDefaultConfiguration();
if (defaultGC.isTranslucencyCapable()) {
return defaultGC;
}
// ... otherwise iterate through all the GCs.
GraphicsConfiguration[] configs = getConfigurations();
for (int j = 0; j < configs.length; j++) {
if (configs[j].isTranslucencyCapable()) {
return configs[j];
}
}
return null;
}
}

View file

@ -0,0 +1,465 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.BufferedImage;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
import sun.java2d.HeadlessGraphicsEnvironment;
import sun.java2d.SunGraphicsEnvironment;
import sun.security.action.GetPropertyAction;
/**
*
* The {@code GraphicsEnvironment} class describes the collection
* of {@link GraphicsDevice} objects and {@link java.awt.Font} objects
* available to a Java(tm) application on a particular platform.
* The resources in this {@code GraphicsEnvironment} might be local
* or on a remote machine. {@code GraphicsDevice} objects can be
* screens, printers or image buffers and are the destination of
* {@link Graphics2D} drawing methods. Each {@code GraphicsDevice}
* has a number of {@link GraphicsConfiguration} objects associated with
* it. These objects specify the different configurations in which the
* {@code GraphicsDevice} can be used.
* @see GraphicsDevice
* @see GraphicsConfiguration
*/
public abstract class GraphicsEnvironment {
/**
* The headless state of the Toolkit and GraphicsEnvironment
*/
private static Boolean headless;
/**
* The headless state assumed by default
*/
private static Boolean defaultHeadless;
/**
* This is an abstract class and cannot be instantiated directly.
* Instances must be obtained from a suitable factory or query method.
*/
protected GraphicsEnvironment() {
}
/**
* Lazy initialization of local graphics environment using holder idiom.
*/
private static final class LocalGE {
/**
* The instance of the local {@code GraphicsEnvironment}.
*/
static final GraphicsEnvironment INSTANCE = createGE();
/**
* Creates and returns the GraphicsEnvironment, according to the
* system property 'java.awt.graphicsenv'.
*
* @return the graphics environment
*/
private static GraphicsEnvironment createGE() {
GraphicsEnvironment ge;
String nm = AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null));
try {
// long t0 = System.currentTimeMillis();
Class<?> geCls;
try {
// First we try if the bootstrap class loader finds the
// requested class. This way we can avoid to run in a privileged
// block.
geCls = Class.forName(nm);
} catch (ClassNotFoundException ex) {
// If the bootstrap class loader fails, we try again with the
// application class loader.
ClassLoader cl = ClassLoader.getSystemClassLoader();
geCls = Class.forName(nm, true, cl);
}
ge = (GraphicsEnvironment)geCls.getConstructor().newInstance();
// long t1 = System.currentTimeMillis();
// System.out.println("GE creation took " + (t1-t0)+ "ms.");
if (isHeadless()) {
ge = new HeadlessGraphicsEnvironment(ge);
}
} catch (ClassNotFoundException e) {
throw new Error("Could not find class: "+nm);
} catch (ReflectiveOperationException | IllegalArgumentException e) {
throw new Error("Could not instantiate Graphics Environment: "
+ nm);
}
return ge;
}
}
/**
* Returns the local {@code GraphicsEnvironment}.
* @return the local {@code GraphicsEnvironment}
*/
public static GraphicsEnvironment getLocalGraphicsEnvironment() {
return LocalGE.INSTANCE;
}
/**
* Tests whether or not a display, keyboard, and mouse can be
* supported in this environment. If this method returns true,
* a HeadlessException is thrown from areas of the Toolkit
* and GraphicsEnvironment that are dependent on a display,
* keyboard, or mouse.
* @return {@code true} if this environment cannot support
* a display, keyboard, and mouse; {@code false}
* otherwise
* @see java.awt.HeadlessException
* @since 1.4
*/
public static boolean isHeadless() {
return getHeadlessProperty();
}
/**
* @return warning message if headless state is assumed by default;
* null otherwise
* @since 1.5
*/
static String getHeadlessMessage() {
if (headless == null) {
getHeadlessProperty(); // initialize the values
}
return defaultHeadless != Boolean.TRUE ? null :
"\nNo X11 DISPLAY variable was set, " +
"but this program performed an operation which requires it.";
}
/**
* @return the value of the property "java.awt.headless"
* @since 1.4
*/
private static boolean getHeadlessProperty() {
if (headless == null) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
String nm = System.getProperty("java.awt.headless");
if (nm == null) {
/* No need to ask for DISPLAY when run in a browser */
if (System.getProperty("javaplugin.version") != null) {
headless = defaultHeadless = Boolean.FALSE;
} else {
String osName = System.getProperty("os.name");
if (osName.contains("OS X") && "sun.awt.HToolkit".equals(
System.getProperty("awt.toolkit")))
{
headless = defaultHeadless = Boolean.TRUE;
} else {
final String display = System.getenv("DISPLAY");
headless = defaultHeadless =
("Linux".equals(osName) ||
"SunOS".equals(osName) ||
"FreeBSD".equals(osName) ||
"NetBSD".equals(osName) ||
"OpenBSD".equals(osName) ||
"AIX".equals(osName)) &&
(display == null || display.trim().isEmpty());
}
}
} else {
headless = Boolean.valueOf(nm);
}
return null;
});
}
return headless;
}
/**
* Check for headless state and throw HeadlessException if headless
* @since 1.4
*/
static void checkHeadless() throws HeadlessException {
if (isHeadless()) {
throw new HeadlessException();
}
}
/**
* Returns whether or not a display, keyboard, and mouse can be
* supported in this graphics environment. If this returns true,
* {@code HeadlessException} will be thrown from areas of the
* graphics environment that are dependent on a display, keyboard, or
* mouse.
* @return {@code true} if a display, keyboard, and mouse
* can be supported in this environment; {@code false}
* otherwise
* @see java.awt.HeadlessException
* @see #isHeadless
* @since 1.4
*/
public boolean isHeadlessInstance() {
// By default (local graphics environment), simply check the
// headless property.
return getHeadlessProperty();
}
/**
* Returns an array of all of the screen {@code GraphicsDevice}
* objects.
* @return an array containing all the {@code GraphicsDevice}
* objects that represent screen devices
* @exception HeadlessException if isHeadless() returns true
* @see #isHeadless()
*/
public abstract GraphicsDevice[] getScreenDevices()
throws HeadlessException;
/**
* Returns the default screen {@code GraphicsDevice}.
* @return the {@code GraphicsDevice} that represents the
* default screen device
* @exception HeadlessException if isHeadless() returns true
* @see #isHeadless()
*/
public abstract GraphicsDevice getDefaultScreenDevice()
throws HeadlessException;
/**
* Returns a {@code Graphics2D} object for rendering into the
* specified {@link BufferedImage}.
* @param img the specified {@code BufferedImage}
* @return a {@code Graphics2D} to be used for rendering into
* the specified {@code BufferedImage}
* @throws NullPointerException if {@code img} is null
*/
public abstract Graphics2D createGraphics(BufferedImage img);
/**
* Returns an array containing a one-point size instance of all fonts
* available in this {@code GraphicsEnvironment}. Typical usage
* would be to allow a user to select a particular font. Then, the
* application can size the font and set various font attributes by
* calling the {@code deriveFont} method on the chosen instance.
* <p>
* This method provides for the application the most precise control
* over which {@code Font} instance is used to render text.
* If a font in this {@code GraphicsEnvironment} has multiple
* programmable variations, only one
* instance of that {@code Font} is returned in the array, and
* other variations must be derived by the application.
* <p>
* If a font in this environment has multiple programmable variations,
* such as Multiple-Master fonts, only one instance of that font is
* returned in the {@code Font} array. The other variations
* must be derived by the application.
*
* @return an array of {@code Font} objects
* @see #getAvailableFontFamilyNames
* @see java.awt.Font
* @see java.awt.Font#deriveFont
* @see java.awt.Font#getFontName
* @since 1.2
*/
public abstract Font[] getAllFonts();
/**
* Returns an array containing the names of all font families in this
* {@code GraphicsEnvironment} localized for the default locale,
* as returned by {@code Locale.getDefault()}.
* <p>
* Typical usage would be for presentation to a user for selection of
* a particular family name. An application can then specify this name
* when creating a font, in conjunction with a style, such as bold or
* italic, giving the font system flexibility in choosing its own best
* match among multiple fonts in the same font family.
*
* @return an array of {@code String} containing font family names
* localized for the default locale, or a suitable alternative
* name if no name exists for this locale.
* @see #getAllFonts
* @see java.awt.Font
* @see java.awt.Font#getFamily
* @since 1.2
*/
public abstract String[] getAvailableFontFamilyNames();
/**
* Returns an array containing the names of all font families in this
* {@code GraphicsEnvironment} localized for the specified locale.
* <p>
* Typical usage would be for presentation to a user for selection of
* a particular family name. An application can then specify this name
* when creating a font, in conjunction with a style, such as bold or
* italic, giving the font system flexibility in choosing its own best
* match among multiple fonts in the same font family.
*
* @param l a {@link Locale} object that represents a
* particular geographical, political, or cultural region.
* Specifying {@code null} is equivalent to
* specifying {@code Locale.getDefault()}.
* @return an array of {@code String} containing font family names
* localized for the specified {@code Locale}, or a
* suitable alternative name if no name exists for the specified locale.
* @see #getAllFonts
* @see java.awt.Font
* @see java.awt.Font#getFamily
* @since 1.2
*/
public abstract String[] getAvailableFontFamilyNames(Locale l);
/**
* Registers a <i>created</i> {@code Font} in this
* {@code GraphicsEnvironment}.
* A created font is one that was returned from calling
* {@link Font#createFont}, or derived from a created font by
* calling {@link Font#deriveFont}.
* After calling this method for such a font, it is available to
* be used in constructing new {@code Font}s by name or family name,
* and is enumerated by {@link #getAvailableFontFamilyNames} and
* {@link #getAllFonts} within the execution context of this
* application or applet. This means applets cannot register fonts in
* a way that they are visible to other applets.
* <p>
* Reasons that this method might not register the font and therefore
* return {@code false} are:
* <ul>
* <li>The font is not a <i>created</i> {@code Font}.
* <li>The font conflicts with a non-created {@code Font} already
* in this {@code GraphicsEnvironment}. For example if the name
* is that of a system font, or a logical font as described in the
* documentation of the {@link Font} class. It is implementation dependent
* whether a font may also conflict if it has the same family name
* as a system font.
* <p>Notice that an application can supersede the registration
* of an earlier created font with a new one.
* </ul>
*
* @param font the font to be registered
* @return true if the {@code font} is successfully
* registered in this {@code GraphicsEnvironment}.
* @throws NullPointerException if {@code font} is null
* @since 1.6
*/
public boolean registerFont(Font font) {
if (font == null) {
throw new NullPointerException("font cannot be null.");
}
FontManager fm = FontManagerFactory.getInstance();
return fm.registerFont(font);
}
/**
* Indicates a preference for locale-specific fonts in the mapping of
* logical fonts to physical fonts. Calling this method indicates that font
* rendering should primarily use fonts specific to the primary writing
* system (the one indicated by the default encoding and the initial
* default locale). For example, if the primary writing system is
* Japanese, then characters should be rendered using a Japanese font
* if possible, and other fonts should only be used for characters for
* which the Japanese font doesn't have glyphs.
* <p>
* The actual change in font rendering behavior resulting from a call
* to this method is implementation dependent; it may have no effect at
* all, or the requested behavior may already match the default behavior.
* The behavior may differ between font rendering in lightweight
* and peered components. Since calling this method requests a
* different font, clients should expect different metrics, and may need
* to recalculate window sizes and layout. Therefore this method should
* be called before user interface initialisation.
* @since 1.5
*/
public void preferLocaleFonts() {
FontManager fm = FontManagerFactory.getInstance();
fm.preferLocaleFonts();
}
/**
* Indicates a preference for proportional over non-proportional (e.g.
* dual-spaced CJK fonts) fonts in the mapping of logical fonts to
* physical fonts. If the default mapping contains fonts for which
* proportional and non-proportional variants exist, then calling
* this method indicates the mapping should use a proportional variant.
* <p>
* The actual change in font rendering behavior resulting from a call to
* this method is implementation dependent; it may have no effect at all.
* The behavior may differ between font rendering in lightweight and
* peered components. Since calling this method requests a
* different font, clients should expect different metrics, and may need
* to recalculate window sizes and layout. Therefore this method should
* be called before user interface initialisation.
* @since 1.5
*/
public void preferProportionalFonts() {
FontManager fm = FontManagerFactory.getInstance();
fm.preferProportionalFonts();
}
/**
* Returns the Point where Windows should be centered.
* It is recommended that centered Windows be checked to ensure they fit
* within the available display area using getMaximumWindowBounds().
* @return the point where Windows should be centered
*
* @exception HeadlessException if isHeadless() returns true
* @see #getMaximumWindowBounds
* @since 1.4
*/
public Point getCenterPoint() throws HeadlessException {
// Default implementation: return the center of the usable bounds of the
// default screen device.
Rectangle usableBounds =
SunGraphicsEnvironment.getUsableBounds(getDefaultScreenDevice());
return new Point((usableBounds.width / 2) + usableBounds.x,
(usableBounds.height / 2) + usableBounds.y);
}
/**
* Returns the maximum bounds for centered Windows.
* These bounds account for objects in the native windowing system such as
* task bars and menu bars. The returned bounds will reside on a single
* display with one exception: on multi-screen systems where Windows should
* be centered across all displays, this method returns the bounds of the
* entire display area.
* <p>
* To get the usable bounds of a single display, use
* {@code GraphicsConfiguration.getBounds()} and
* {@code Toolkit.getScreenInsets()}.
* @return the maximum bounds for centered Windows
*
* @exception HeadlessException if isHeadless() returns true
* @see #getCenterPoint
* @see GraphicsConfiguration#getBounds
* @see Toolkit#getScreenInsets
* @since 1.4
*/
public Rectangle getMaximumWindowBounds() throws HeadlessException {
// Default implementation: return the usable bounds of the default screen
// device. This is correct for Microsoft Windows and non-Xinerama X11.
return SunGraphicsEnvironment.getUsableBounds(getDefaultScreenDevice());
}
}

View file

@ -0,0 +1,663 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* The {@code GridBagConstraints} class specifies constraints
* for components that are laid out using the
* {@code GridBagLayout} class.
*
* @author Doug Stein
* @author Bill Spitzak (orignial NeWS &amp; OLIT implementation)
* @see java.awt.GridBagLayout
* @since 1.0
*/
public class GridBagConstraints implements Cloneable, java.io.Serializable {
/**
* Specifies that this component is the next-to-last component in its
* column or row ({@code gridwidth}, {@code gridheight}),
* or that this component be placed next to the previously added
* component ({@code gridx}, {@code gridy}).
* @see java.awt.GridBagConstraints#gridwidth
* @see java.awt.GridBagConstraints#gridheight
* @see java.awt.GridBagConstraints#gridx
* @see java.awt.GridBagConstraints#gridy
*/
public static final int RELATIVE = -1;
/**
* Specifies that this component is the
* last component in its column or row.
*/
public static final int REMAINDER = 0;
/**
* Do not resize the component.
*/
public static final int NONE = 0;
/**
* Resize the component both horizontally and vertically.
*/
public static final int BOTH = 1;
/**
* Resize the component horizontally but not vertically.
*/
public static final int HORIZONTAL = 2;
/**
* Resize the component vertically but not horizontally.
*/
public static final int VERTICAL = 3;
/**
* Put the component in the center of its display area.
*/
public static final int CENTER = 10;
/**
* Put the component at the top of its display area,
* centered horizontally.
*/
public static final int NORTH = 11;
/**
* Put the component at the top-right corner of its display area.
*/
public static final int NORTHEAST = 12;
/**
* Put the component on the right side of its display area,
* centered vertically.
*/
public static final int EAST = 13;
/**
* Put the component at the bottom-right corner of its display area.
*/
public static final int SOUTHEAST = 14;
/**
* Put the component at the bottom of its display area, centered
* horizontally.
*/
public static final int SOUTH = 15;
/**
* Put the component at the bottom-left corner of its display area.
*/
public static final int SOUTHWEST = 16;
/**
* Put the component on the left side of its display area,
* centered vertically.
*/
public static final int WEST = 17;
/**
* Put the component at the top-left corner of its display area.
*/
public static final int NORTHWEST = 18;
/**
* Place the component centered along the edge of its display area
* associated with the start of a page for the current
* {@code ComponentOrientation}. Equal to NORTH for horizontal
* orientations.
*/
public static final int PAGE_START = 19;
/**
* Place the component centered along the edge of its display area
* associated with the end of a page for the current
* {@code ComponentOrientation}. Equal to SOUTH for horizontal
* orientations.
*/
public static final int PAGE_END = 20;
/**
* Place the component centered along the edge of its display area where
* lines of text would normally begin for the current
* {@code ComponentOrientation}. Equal to WEST for horizontal,
* left-to-right orientations and EAST for horizontal, right-to-left
* orientations.
*/
public static final int LINE_START = 21;
/**
* Place the component centered along the edge of its display area where
* lines of text would normally end for the current
* {@code ComponentOrientation}. Equal to EAST for horizontal,
* left-to-right orientations and WEST for horizontal, right-to-left
* orientations.
*/
public static final int LINE_END = 22;
/**
* Place the component in the corner of its display area where
* the first line of text on a page would normally begin for the current
* {@code ComponentOrientation}. Equal to NORTHWEST for horizontal,
* left-to-right orientations and NORTHEAST for horizontal, right-to-left
* orientations.
*/
public static final int FIRST_LINE_START = 23;
/**
* Place the component in the corner of its display area where
* the first line of text on a page would normally end for the current
* {@code ComponentOrientation}. Equal to NORTHEAST for horizontal,
* left-to-right orientations and NORTHWEST for horizontal, right-to-left
* orientations.
*/
public static final int FIRST_LINE_END = 24;
/**
* Place the component in the corner of its display area where
* the last line of text on a page would normally start for the current
* {@code ComponentOrientation}. Equal to SOUTHWEST for horizontal,
* left-to-right orientations and SOUTHEAST for horizontal, right-to-left
* orientations.
*/
public static final int LAST_LINE_START = 25;
/**
* Place the component in the corner of its display area where
* the last line of text on a page would normally end for the current
* {@code ComponentOrientation}. Equal to SOUTHEAST for horizontal,
* left-to-right orientations and SOUTHWEST for horizontal, right-to-left
* orientations.
*/
public static final int LAST_LINE_END = 26;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally centered and
* vertically aligned along the baseline of the prevailing row.
* If the component does not have a baseline it will be vertically
* centered.
*
* @since 1.6
*/
public static final int BASELINE = 0x100;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* leading edge. For components with a left-to-right orientation,
* the leading edge is the left edge. Vertically the component is
* aligned along the baseline of the prevailing row. If the
* component does not have a baseline it will be vertically
* centered.
*
* @since 1.6
*/
public static final int BASELINE_LEADING = 0x200;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* trailing edge. For components with a left-to-right
* orientation, the trailing edge is the right edge. Vertically
* the component is aligned along the baseline of the prevailing
* row. If the component does not have a baseline it will be
* vertically centered.
*
* @since 1.6
*/
public static final int BASELINE_TRAILING = 0x300;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally centered. Vertically
* the component is positioned so that its bottom edge touches
* the baseline of the starting row. If the starting row does not
* have a baseline it will be vertically centered.
*
* @since 1.6
*/
public static final int ABOVE_BASELINE = 0x400;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* leading edge. For components with a left-to-right orientation,
* the leading edge is the left edge. Vertically the component is
* positioned so that its bottom edge touches the baseline of the
* starting row. If the starting row does not have a baseline it
* will be vertically centered.
*
* @since 1.6
*/
public static final int ABOVE_BASELINE_LEADING = 0x500;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* trailing edge. For components with a left-to-right
* orientation, the trailing edge is the right edge. Vertically
* the component is positioned so that its bottom edge touches
* the baseline of the starting row. If the starting row does not
* have a baseline it will be vertically centered.
*
* @since 1.6
*/
public static final int ABOVE_BASELINE_TRAILING = 0x600;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally centered. Vertically
* the component is positioned so that its top edge touches the
* baseline of the starting row. If the starting row does not
* have a baseline it will be vertically centered.
*
* @since 1.6
*/
public static final int BELOW_BASELINE = 0x700;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* leading edge. For components with a left-to-right orientation,
* the leading edge is the left edge. Vertically the component is
* positioned so that its top edge touches the baseline of the
* starting row. If the starting row does not have a baseline it
* will be vertically centered.
*
* @since 1.6
*/
public static final int BELOW_BASELINE_LEADING = 0x800;
/**
* Possible value for the {@code anchor} field. Specifies
* that the component should be horizontally placed along the
* trailing edge. For components with a left-to-right
* orientation, the trailing edge is the right edge. Vertically
* the component is positioned so that its top edge touches the
* baseline of the starting row. If the starting row does not
* have a baseline it will be vertically centered.
*
* @since 1.6
*/
public static final int BELOW_BASELINE_TRAILING = 0x900;
/**
* Specifies the cell containing the leading edge of the component's
* display area, where the first cell in a row has {@code gridx=0}.
* The leading edge of a component's display area is its left edge for
* a horizontal, left-to-right container and its right edge for a
* horizontal, right-to-left container.
* The value
* {@code RELATIVE} specifies that the component be placed
* immediately following the component that was added to the container
* just before this component was added.
* <p>
* The default value is {@code RELATIVE}.
* {@code gridx} should be a non-negative value.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#gridy
* @see java.awt.ComponentOrientation
*/
public int gridx;
/**
* Specifies the cell at the top of the component's display area,
* where the topmost cell has {@code gridy=0}. The value
* {@code RELATIVE} specifies that the component be placed just
* below the component that was added to the container just before
* this component was added.
* <p>
* The default value is {@code RELATIVE}.
* {@code gridy} should be a non-negative value.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#gridx
*/
public int gridy;
/**
* Specifies the number of cells in a row for the component's
* display area.
* <p>
* Use {@code REMAINDER} to specify that the component's
* display area will be from {@code gridx} to the last
* cell in the row.
* Use {@code RELATIVE} to specify that the component's
* display area will be from {@code gridx} to the next
* to the last one in its row.
* <p>
* {@code gridwidth} should be non-negative and the default
* value is 1.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#gridheight
*/
public int gridwidth;
/**
* Specifies the number of cells in a column for the component's
* display area.
* <p>
* Use {@code REMAINDER} to specify that the component's
* display area will be from {@code gridy} to the last
* cell in the column.
* Use {@code RELATIVE} to specify that the component's
* display area will be from {@code gridy} to the next
* to the last one in its column.
* <p>
* {@code gridheight} should be a non-negative value and the
* default value is 1.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#gridwidth
*/
public int gridheight;
/**
* Specifies how to distribute extra horizontal space.
* <p>
* The grid bag layout manager calculates the weight of a column to
* be the maximum {@code weightx} of all the components in a
* column. If the resulting layout is smaller horizontally than the area
* it needs to fill, the extra space is distributed to each column in
* proportion to its weight. A column that has a weight of zero receives
* no extra space.
* <p>
* If all the weights are zero, all the extra space appears between
* the grids of the cell and the left and right edges.
* <p>
* The default value of this field is {@code 0}.
* {@code weightx} should be a non-negative value.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#weighty
*/
public double weightx;
/**
* Specifies how to distribute extra vertical space.
* <p>
* The grid bag layout manager calculates the weight of a row to be
* the maximum {@code weighty} of all the components in a row.
* If the resulting layout is smaller vertically than the area it
* needs to fill, the extra space is distributed to each row in
* proportion to its weight. A row that has a weight of zero receives no
* extra space.
* <p>
* If all the weights are zero, all the extra space appears between
* the grids of the cell and the top and bottom edges.
* <p>
* The default value of this field is {@code 0}.
* {@code weighty} should be a non-negative value.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#weightx
*/
public double weighty;
/**
* This field is used when the component is smaller than its
* display area. It determines where, within the display area, to
* place the component.
* <p> There are three kinds of possible values: orientation
* relative, baseline relative and absolute. Orientation relative
* values are interpreted relative to the container's component
* orientation property, baseline relative values are interpreted
* relative to the baseline and absolute values are not. The
* absolute values are:
* {@code CENTER}, {@code NORTH}, {@code NORTHEAST},
* {@code EAST}, {@code SOUTHEAST}, {@code SOUTH},
* {@code SOUTHWEST}, {@code WEST}, and {@code NORTHWEST}.
* The orientation relative values are: {@code PAGE_START},
* {@code PAGE_END},
* {@code LINE_START}, {@code LINE_END},
* {@code FIRST_LINE_START}, {@code FIRST_LINE_END},
* {@code LAST_LINE_START} and {@code LAST_LINE_END}. The
* baseline relative values are:
* {@code BASELINE}, {@code BASELINE_LEADING},
* {@code BASELINE_TRAILING},
* {@code ABOVE_BASELINE}, {@code ABOVE_BASELINE_LEADING},
* {@code ABOVE_BASELINE_TRAILING},
* {@code BELOW_BASELINE}, {@code BELOW_BASELINE_LEADING},
* and {@code BELOW_BASELINE_TRAILING}.
* The default value is {@code CENTER}.
* @serial
* @see #clone()
* @see java.awt.ComponentOrientation
*/
public int anchor;
/**
* This field is used when the component's display area is larger
* than the component's requested size. It determines whether to
* resize the component, and if so, how.
* <p>
* The following values are valid for {@code fill}:
*
* <ul>
* <li>
* {@code NONE}: Do not resize the component.
* <li>
* {@code HORIZONTAL}: Make the component wide enough to fill
* its display area horizontally, but do not change its height.
* <li>
* {@code VERTICAL}: Make the component tall enough to fill its
* display area vertically, but do not change its width.
* <li>
* {@code BOTH}: Make the component fill its display area
* entirely.
* </ul>
* <p>
* The default value is {@code NONE}.
* @serial
* @see #clone()
*/
public int fill;
/**
* This field specifies the external padding of the component, the
* minimum amount of space between the component and the edges of its
* display area.
* <p>
* The default value is {@code new Insets(0, 0, 0, 0)}.
* @serial
* @see #clone()
*/
public Insets insets;
/**
* This field specifies the internal padding of the component, how much
* space to add to the minimum width of the component. The width of
* the component is at least its minimum width plus
* {@code ipadx} pixels.
* <p>
* The default value is {@code 0}.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#ipady
*/
public int ipadx;
/**
* This field specifies the internal padding, that is, how much
* space to add to the minimum height of the component. The height of
* the component is at least its minimum height plus
* {@code ipady} pixels.
* <p>
* The default value is 0.
* @serial
* @see #clone()
* @see java.awt.GridBagConstraints#ipadx
*/
public int ipady;
/**
* Temporary place holder for the x coordinate.
* @serial
*/
int tempX;
/**
* Temporary place holder for the y coordinate.
* @serial
*/
int tempY;
/**
* Temporary place holder for the Width of the component.
* @serial
*/
int tempWidth;
/**
* Temporary place holder for the Height of the component.
* @serial
*/
int tempHeight;
/**
* The minimum width of the component. It is used to calculate
* {@code ipady}, where the default will be 0.
* @serial
* @see #ipady
*/
int minWidth;
/**
* The minimum height of the component. It is used to calculate
* {@code ipadx}, where the default will be 0.
* @serial
* @see #ipadx
*/
int minHeight;
// The following fields are only used if the anchor is
// one of BASELINE, BASELINE_LEADING or BASELINE_TRAILING.
// ascent and descent include the insets and ipady values.
transient int ascent;
transient int descent;
transient Component.BaselineResizeBehavior baselineResizeBehavior;
// The following two fields are used if the baseline type is
// CENTER_OFFSET.
// centerPadding is either 0 or 1 and indicates if
// the height needs to be padded by one when calculating where the
// baseline lands
transient int centerPadding;
// Where the baseline lands relative to the center of the component.
transient int centerOffset;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -1000070633030801713L;
/**
* Creates a {@code GridBagConstraint} object with
* all of its fields set to their default value.
*/
public GridBagConstraints () {
gridx = RELATIVE;
gridy = RELATIVE;
gridwidth = 1;
gridheight = 1;
weightx = 0;
weighty = 0;
anchor = CENTER;
fill = NONE;
insets = new Insets(0, 0, 0, 0);
ipadx = 0;
ipady = 0;
}
/**
* Creates a {@code GridBagConstraints} object with
* all of its fields set to the passed-in arguments.
*
* Note: Because the use of this constructor hinders readability
* of source code, this constructor should only be used by
* automatic source code generation tools.
*
* @param gridx The initial gridx value.
* @param gridy The initial gridy value.
* @param gridwidth The initial gridwidth value.
* @param gridheight The initial gridheight value.
* @param weightx The initial weightx value.
* @param weighty The initial weighty value.
* @param anchor The initial anchor value.
* @param fill The initial fill value.
* @param insets The initial insets value.
* @param ipadx The initial ipadx value.
* @param ipady The initial ipady value.
*
* @see java.awt.GridBagConstraints#gridx
* @see java.awt.GridBagConstraints#gridy
* @see java.awt.GridBagConstraints#gridwidth
* @see java.awt.GridBagConstraints#gridheight
* @see java.awt.GridBagConstraints#weightx
* @see java.awt.GridBagConstraints#weighty
* @see java.awt.GridBagConstraints#anchor
* @see java.awt.GridBagConstraints#fill
* @see java.awt.GridBagConstraints#insets
* @see java.awt.GridBagConstraints#ipadx
* @see java.awt.GridBagConstraints#ipady
*
* @since 1.2
*/
public GridBagConstraints(int gridx, int gridy,
int gridwidth, int gridheight,
double weightx, double weighty,
int anchor, int fill,
Insets insets, int ipadx, int ipady) {
this.gridx = gridx;
this.gridy = gridy;
this.gridwidth = gridwidth;
this.gridheight = gridheight;
this.fill = fill;
this.ipadx = ipadx;
this.ipady = ipady;
this.insets = insets;
this.anchor = anchor;
this.weightx = weightx;
this.weighty = weighty;
}
/**
* Creates a copy of this grid bag constraint.
* @return a copy of this grid bag constraint
*/
public Object clone () {
try {
GridBagConstraints c = (GridBagConstraints)super.clone();
c.insets = (Insets)insets.clone();
return c;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
boolean isVerticallyResizable() {
return (fill == BOTH || fill == VERTICAL);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* The {@code GridBagLayoutInfo} is an utility class for
* {@code GridBagLayout} layout manager.
* It stores align, size and baseline parameters for every component within a container.
*
* @see java.awt.GridBagLayout
* @see java.awt.GridBagConstraints
* @since 1.6
*/
public class GridBagLayoutInfo implements java.io.Serializable {
/*
* serialVersionUID
*/
private static final long serialVersionUID = -4899416460737170217L;
int width, height; /* number of cells: horizontal and vertical */
int startx, starty; /* starting point for layout */
int minWidth[]; /* largest minWidth in each column */
int minHeight[]; /* largest minHeight in each row */
double weightX[]; /* largest weight in each column */
double weightY[]; /* largest weight in each row */
boolean hasBaseline; /* Whether or not baseline layout has been
* requested and one of the components
* has a valid baseline. */
// These are only valid if hasBaseline is true and are indexed by
// row.
short baselineType[]; /* The type of baseline for a particular
* row. A mix of the BaselineResizeBehavior
* constants (1 << ordinal()) */
int maxAscent[]; /* Max ascent (baseline). */
int maxDescent[]; /* Max descent (height - baseline) */
/**
* Creates an instance of GridBagLayoutInfo representing {@code GridBagLayout}
* grid cells with it's own parameters.
* @param width the columns
* @param height the rows
* @since 1.6
*/
GridBagLayoutInfo(int width, int height) {
this.width = width;
this.height = height;
}
/**
* Returns true if the specified row has any component aligned on the
* baseline with a baseline resize behavior of CONSTANT_DESCENT.
*/
boolean hasConstantDescent(int row) {
return ((baselineType[row] & (1 << Component.BaselineResizeBehavior.
CONSTANT_DESCENT.ordinal())) != 0);
}
/**
* Returns true if there is a baseline for the specified row.
*/
boolean hasBaseline(int row) {
return (hasBaseline && baselineType[row] != 0);
}
}

View file

@ -0,0 +1,482 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* The {@code GridLayout} class is a layout manager that
* lays out a container's components in a rectangular grid.
* The container is divided into equal-sized rectangles,
* and one component is placed in each rectangle.
* For example, the following is an applet that lays out six buttons
* into three rows and two columns:
*
* <hr><blockquote>
* <pre>
* import java.awt.*;
* import java.applet.Applet;
* public class ButtonGrid extends Applet {
* public void init() {
* setLayout(new GridLayout(3,2));
* add(new Button("1"));
* add(new Button("2"));
* add(new Button("3"));
* add(new Button("4"));
* add(new Button("5"));
* add(new Button("6"));
* }
* }
* </pre></blockquote><hr>
* <p>
* If the container's {@code ComponentOrientation} property is horizontal
* and left-to-right, the above example produces the output shown in Figure 1.
* If the container's {@code ComponentOrientation} property is horizontal
* and right-to-left, the example produces the output shown in Figure 2.
*
* <table style="float:center;width:600">
* <caption style="display:none">Figures</caption>
* <tr style="text-align:center">
* <td><img SRC="doc-files/GridLayout-1.gif"
* alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
* Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6.">
* </td>
*
* <td style="text-align:center"><img SRC="doc-files/GridLayout-2.gif"
* alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1.
* Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5.">
* </td>
* </tr>
*
* <tr style="text-align:center">
* <td>Figure 1: Horizontal, Left-to-Right</td>
*
* <td>Figure 2: Horizontal, Right-to-Left</td>
* </tr>
* </table>
* <p>
* When both the number of rows and the number of columns have
* been set to non-zero values, either by a constructor or
* by the {@code setRows} and {@code setColumns} methods, the number of
* columns specified is ignored. Instead, the number of
* columns is determined from the specified number of rows
* and the total number of components in the layout. So, for
* example, if three rows and two columns have been specified
* and nine components are added to the layout, they will
* be displayed as three rows of three columns. Specifying
* the number of columns affects the layout only when the
* number of rows is set to zero.
*
* @author Arthur van Hoff
* @since 1.0
*/
public class GridLayout implements LayoutManager, java.io.Serializable {
/*
* serialVersionUID
*/
private static final long serialVersionUID = -7411804673224730901L;
/**
* This is the horizontal gap (in pixels) which specifies the space
* between columns. They can be changed at any time.
* This should be a non-negative integer.
*
* @serial
* @see #getHgap()
* @see #setHgap(int)
*/
int hgap;
/**
* This is the vertical gap (in pixels) which specifies the space
* between rows. They can be changed at any time.
* This should be a non negative integer.
*
* @serial
* @see #getVgap()
* @see #setVgap(int)
*/
int vgap;
/**
* This is the number of rows specified for the grid. The number
* of rows can be changed at any time.
* This should be a non negative integer, where '0' means
* 'any number' meaning that the number of Rows in that
* dimension depends on the other dimension.
*
* @serial
* @see #getRows()
* @see #setRows(int)
*/
int rows;
/**
* This is the number of columns specified for the grid. The number
* of columns can be changed at any time.
* This should be a non negative integer, where '0' means
* 'any number' meaning that the number of Columns in that
* dimension depends on the other dimension.
*
* @serial
* @see #getColumns()
* @see #setColumns(int)
*/
int cols;
/**
* Creates a grid layout with a default of one column per component,
* in a single row.
* @since 1.1
*/
public GridLayout() {
this(1, 0, 0, 0);
}
/**
* Creates a grid layout with the specified number of rows and
* columns. All components in the layout are given equal size.
* <p>
* One, but not both, of {@code rows} and {@code cols} can
* be zero, which means that any number of objects can be placed in a
* row or in a column.
* @param rows the rows, with the value zero meaning
* any number of rows.
* @param cols the columns, with the value zero meaning
* any number of columns.
*/
public GridLayout(int rows, int cols) {
this(rows, cols, 0, 0);
}
/**
* Creates a grid layout with the specified number of rows and
* columns. All components in the layout are given equal size.
* <p>
* In addition, the horizontal and vertical gaps are set to the
* specified values. Horizontal gaps are placed between each
* of the columns. Vertical gaps are placed between each of
* the rows.
* <p>
* One, but not both, of {@code rows} and {@code cols} can
* be zero, which means that any number of objects can be placed in a
* row or in a column.
* <p>
* All {@code GridLayout} constructors defer to this one.
* @param rows the rows, with the value zero meaning
* any number of rows
* @param cols the columns, with the value zero meaning
* any number of columns
* @param hgap the horizontal gap
* @param vgap the vertical gap
* @exception IllegalArgumentException if the value of both
* {@code rows} and {@code cols} is
* set to zero
*/
public GridLayout(int rows, int cols, int hgap, int vgap) {
if ((rows == 0) && (cols == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.rows = rows;
this.cols = cols;
this.hgap = hgap;
this.vgap = vgap;
}
/**
* Gets the number of rows in this layout.
* @return the number of rows in this layout
* @since 1.1
*/
public int getRows() {
return rows;
}
/**
* Sets the number of rows in this layout to the specified value.
* @param rows the number of rows in this layout
* @exception IllegalArgumentException if the value of both
* {@code rows} and {@code cols} is set to zero
* @since 1.1
*/
public void setRows(int rows) {
if ((rows == 0) && (this.cols == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.rows = rows;
}
/**
* Gets the number of columns in this layout.
* @return the number of columns in this layout
* @since 1.1
*/
public int getColumns() {
return cols;
}
/**
* Sets the number of columns in this layout to the specified value.
* Setting the number of columns has no affect on the layout
* if the number of rows specified by a constructor or by
* the {@code setRows} method is non-zero. In that case, the number
* of columns displayed in the layout is determined by the total
* number of components and the number of rows specified.
* @param cols the number of columns in this layout
* @exception IllegalArgumentException if the value of both
* {@code rows} and {@code cols} is set to zero
* @since 1.1
*/
public void setColumns(int cols) {
if ((cols == 0) && (this.rows == 0)) {
throw new IllegalArgumentException("rows and cols cannot both be zero");
}
this.cols = cols;
}
/**
* Gets the horizontal gap between components.
* @return the horizontal gap between components
* @since 1.1
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between components to the specified value.
* @param hgap the horizontal gap between components
* @since 1.1
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Gets the vertical gap between components.
* @return the vertical gap between components
* @since 1.1
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components to the specified value.
* @param vgap the vertical gap between components
* @since 1.1
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Adds the specified component with the specified name to the layout.
* @param name the name of the component
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
/**
* Removes the specified component from the layout.
* @param comp the component to be removed
*/
public void removeLayoutComponent(Component comp) {
}
/**
* Determines the preferred size of the container argument using
* this grid layout.
* <p>
* The preferred width of a grid layout is the largest preferred
* width of all of the components in the container times the number of
* columns, plus the horizontal padding times the number of columns
* minus one, plus the left and right insets of the target container.
* <p>
* The preferred height of a grid layout is the largest preferred
* height of all of the components in the container times the number of
* rows, plus the vertical padding times the number of rows minus one,
* plus the top and bottom insets of the target container.
*
* @param parent the container in which to do the layout
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
* @see java.awt.GridLayout#minimumLayoutSize
* @see java.awt.Container#getPreferredSize()
*/
public Dimension preferredLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = rows;
int ncols = cols;
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int w = 0;
int h = 0;
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
if (w < d.width) {
w = d.width;
}
if (h < d.height) {
h = d.height;
}
}
return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
}
}
/**
* Determines the minimum size of the container argument using this
* grid layout.
* <p>
* The minimum width of a grid layout is the largest minimum width
* of all of the components in the container times the number of columns,
* plus the horizontal padding times the number of columns minus one,
* plus the left and right insets of the target container.
* <p>
* The minimum height of a grid layout is the largest minimum height
* of all of the components in the container times the number of rows,
* plus the vertical padding times the number of rows minus one, plus
* the top and bottom insets of the target container.
*
* @param parent the container in which to do the layout
* @return the minimum dimensions needed to lay out the
* subcomponents of the specified container
* @see java.awt.GridLayout#preferredLayoutSize
* @see java.awt.Container#doLayout
*/
public Dimension minimumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = rows;
int ncols = cols;
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int w = 0;
int h = 0;
for (int i = 0 ; i < ncomponents ; i++) {
Component comp = parent.getComponent(i);
Dimension d = comp.getMinimumSize();
if (w < d.width) {
w = d.width;
}
if (h < d.height) {
h = d.height;
}
}
return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
}
}
/**
* Lays out the specified container using this layout.
* <p>
* This method reshapes the components in the specified target
* container in order to satisfy the constraints of the
* {@code GridLayout} object.
* <p>
* The grid layout manager determines the size of individual
* components by dividing the free space in the container into
* equal-sized portions according to the number of rows and columns
* in the layout. The container's free space equals the container's
* size minus any insets and any specified horizontal or vertical
* gap. All components in a grid layout are given the same size.
*
* @param parent the container in which to do the layout
* @see java.awt.Container
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = rows;
int ncols = cols;
boolean ltr = parent.getComponentOrientation().isLeftToRight();
if (ncomponents == 0) {
return;
}
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
// 4370316. To position components in the center we should:
// 1. get an amount of extra space within Container
// 2. incorporate half of that value to the left/top position
// Note that we use trancating division for widthOnComponent
// The reminder goes to extraWidthAvailable
int totalGapsWidth = (ncols - 1) * hgap;
int widthWOInsets = parent.width - (insets.left + insets.right);
int widthOnComponent = (widthWOInsets - totalGapsWidth) / ncols;
int extraWidthAvailable = (widthWOInsets - (widthOnComponent * ncols + totalGapsWidth)) / 2;
int totalGapsHeight = (nrows - 1) * vgap;
int heightWOInsets = parent.height - (insets.top + insets.bottom);
int heightOnComponent = (heightWOInsets - totalGapsHeight) / nrows;
int extraHeightAvailable = (heightWOInsets - (heightOnComponent * nrows + totalGapsHeight)) / 2;
if (ltr) {
for (int c = 0, x = insets.left + extraWidthAvailable; c < ncols ; c++, x += widthOnComponent + hgap) {
for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent);
}
}
}
} else {
for (int c = 0, x = (parent.width - insets.right - widthOnComponent) - extraWidthAvailable; c < ncols ; c++, x -= widthOnComponent + hgap) {
for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent);
}
}
}
}
}
}
/**
* Returns the string representation of this grid layout's values.
* @return a string representation of this grid layout
*/
public String toString() {
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
",rows=" + rows + ",cols=" + cols + "]";
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Thrown when code that is dependent on a keyboard, display, or mouse
* is called in an environment that does not support a keyboard, display,
* or mouse. Any code that depends on any of those devices should firstly
* ensure their availability using the {@code GraphicsEnvironment.isHeadless()}
* method and throw {@code HeadlessException} if the latter returns
* {@code true}.
*
* @since 1.4
* @author Michael Martak
* @see GraphicsEnvironment#isHeadless
*/
public class HeadlessException extends UnsupportedOperationException {
/*
* JDK 1.4 serialVersionUID
*/
private static final long serialVersionUID = 167183644944358563L;
/**
* Constructs new {@code HeadlessException} with empty message.
* For such {@code HeadlessException} the default headless error message
* may be auto-generated for some platforms.
* The text of the default headless message may depend on
* whether the GraphicsEnvironment is in fact headless.
* That is, the default headless message is both system and environmentally
* dependent.
*/
public HeadlessException() {}
/**
* Create a new instance with the specified detailed error message.
* For some platforms the default headless error message may be
* added at the end of the specified message.
* The text of the default headless message may depend on
* whether the GraphicsEnvironment is in fact headless.
* That is, the default headless message is both system and environmentally
* dependent.
*
* @param msg the error message
*/
public HeadlessException(String msg) {
super(msg);
}
/**
* Returns the detail message string of this {@code HeadlessException}.
* Depending on the platform the message specified in the constructor may
* be followed by the default headless error message.
* The text of the default headless message may depend on
* whether the GraphicsEnvironment is in fact headless.
* That is, the default headless message is both system and environmentally
* dependent.
*
* @return the detail message string of this {@code HeadlessException}
* instance (which may be {@code null}).
*/
public String getMessage() {
String superMessage = super.getMessage();
String headlessMessage = GraphicsEnvironment.getHeadlessMessage();
if (superMessage == null) {
return headlessMessage;
} else if (headlessMessage == null) {
return superMessage;
} else {
return superMessage + headlessMessage;
}
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Signals that an AWT component is not in an appropriate state for
* the requested operation.
*
* @author Jonni Kanerva
*/
public class IllegalComponentStateException extends IllegalStateException {
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -1889339587208144238L;
/**
* Constructs an IllegalComponentStateException with no detail message.
* A detail message is a String that describes this particular exception.
*/
public IllegalComponentStateException() {
super();
}
/**
* Constructs an IllegalComponentStateException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
* @param s the String that contains a detailed message
*/
public IllegalComponentStateException(String s) {
super(s);
}
}

View file

@ -0,0 +1,354 @@
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ImageProducer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.AreaAveragingScaleFilter;
import java.awt.image.ReplicateScaleFilter;
import sun.awt.image.SurfaceManager;
/**
* The abstract class {@code Image} is the superclass of all
* classes that represent graphical images. The image must be
* obtained in a platform-specific manner.
*
* @author Sami Shaio
* @author Arthur van Hoff
* @since 1.0
*/
public abstract class Image {
/**
* convenience object; we can use this single static object for
* all images that do not create their own image caps; it holds the
* default (unaccelerated) properties.
*/
private static ImageCapabilities defaultImageCaps =
new ImageCapabilities(false);
/**
* Priority for accelerating this image. Subclasses are free to
* set different default priorities and applications are free to
* set the priority for specific images via the
* {@code setAccelerationPriority(float)} method.
* @since 1.5
*/
protected float accelerationPriority = .5f;
/**
* Determines the width of the image. If the width is not yet known,
* this method returns {@code -1} and the specified
* {@code ImageObserver} object is notified later.
* @param observer an object waiting for the image to be loaded.
* @return the width of this image, or {@code -1}
* if the width is not yet known.
* @see java.awt.Image#getHeight
* @see java.awt.image.ImageObserver
*/
public abstract int getWidth(ImageObserver observer);
/**
* Determines the height of the image. If the height is not yet known,
* this method returns {@code -1} and the specified
* {@code ImageObserver} object is notified later.
* @param observer an object waiting for the image to be loaded.
* @return the height of this image, or {@code -1}
* if the height is not yet known.
* @see java.awt.Image#getWidth
* @see java.awt.image.ImageObserver
*/
public abstract int getHeight(ImageObserver observer);
/**
* Gets the object that produces the pixels for the image.
* This method is called by the image filtering classes and by
* methods that perform image conversion and scaling.
* @return the image producer that produces the pixels
* for this image.
* @see java.awt.image.ImageProducer
*/
public abstract ImageProducer getSource();
/**
* Creates a graphics context for drawing to an off-screen image.
* This method can only be called for off-screen images.
* @return a graphics context to draw to the off-screen image.
* @exception UnsupportedOperationException if called for a
* non-off-screen image.
* @see java.awt.Graphics
* @see java.awt.Component#createImage(int, int)
*/
public abstract Graphics getGraphics();
/**
* Gets a property of this image by name.
* <p>
* Individual property names are defined by the various image
* formats. If a property is not defined for a particular image, this
* method returns the {@code UndefinedProperty} object.
* <p>
* If the properties for this image are not yet known, this method
* returns {@code null}, and the {@code ImageObserver}
* object is notified later.
* <p>
* The property name {@code "comment"} should be used to store
* an optional comment which can be presented to the application as a
* description of the image, its source, or its author.
* @param name a property name.
* @param observer an object waiting for this image to be loaded.
* @return the value of the named property.
* @throws NullPointerException if the property name is null.
* @see java.awt.image.ImageObserver
* @see java.awt.Image#UndefinedProperty
*/
public abstract Object getProperty(String name, ImageObserver observer);
/**
* The {@code UndefinedProperty} object should be returned whenever a
* property which was not defined for a particular image is fetched.
*/
public static final Object UndefinedProperty = new Object();
/**
* Creates a scaled version of this image.
* A new {@code Image} object is returned which will render
* the image at the specified {@code width} and
* {@code height} by default. The new {@code Image} object
* may be loaded asynchronously even if the original source image
* has already been loaded completely.
*
* <p>
*
* If either {@code width}
* or {@code height} is a negative number then a value is
* substituted to maintain the aspect ratio of the original image
* dimensions. If both {@code width} and {@code height}
* are negative, then the original image dimensions are used.
*
* @param width the width to which to scale the image.
* @param height the height to which to scale the image.
* @param hints flags to indicate the type of algorithm to use
* for image resampling.
* @return a scaled version of the image.
* @exception IllegalArgumentException if {@code width}
* or {@code height} is zero.
* @see java.awt.Image#SCALE_DEFAULT
* @see java.awt.Image#SCALE_FAST
* @see java.awt.Image#SCALE_SMOOTH
* @see java.awt.Image#SCALE_REPLICATE
* @see java.awt.Image#SCALE_AREA_AVERAGING
* @since 1.1
*/
public Image getScaledInstance(int width, int height, int hints) {
ImageFilter filter;
if ((hints & (SCALE_SMOOTH | SCALE_AREA_AVERAGING)) != 0) {
filter = new AreaAveragingScaleFilter(width, height);
} else {
filter = new ReplicateScaleFilter(width, height);
}
ImageProducer prod;
prod = new FilteredImageSource(getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(prod);
}
/**
* Use the default image-scaling algorithm.
* @since 1.1
*/
public static final int SCALE_DEFAULT = 1;
/**
* Choose an image-scaling algorithm that gives higher priority
* to scaling speed than smoothness of the scaled image.
* @since 1.1
*/
public static final int SCALE_FAST = 2;
/**
* Choose an image-scaling algorithm that gives higher priority
* to image smoothness than scaling speed.
* @since 1.1
*/
public static final int SCALE_SMOOTH = 4;
/**
* Use the image scaling algorithm embodied in the
* {@code ReplicateScaleFilter} class.
* The {@code Image} object is free to substitute a different filter
* that performs the same algorithm yet integrates more efficiently
* into the imaging infrastructure supplied by the toolkit.
* @see java.awt.image.ReplicateScaleFilter
* @since 1.1
*/
public static final int SCALE_REPLICATE = 8;
/**
* Use the Area Averaging image scaling algorithm. The
* image object is free to substitute a different filter that
* performs the same algorithm yet integrates more efficiently
* into the image infrastructure supplied by the toolkit.
* @see java.awt.image.AreaAveragingScaleFilter
* @since 1.1
*/
public static final int SCALE_AREA_AVERAGING = 16;
/**
* Flushes all reconstructable resources being used by this Image object.
* This includes any pixel data that is being cached for rendering to
* the screen as well as any system resources that are being used
* to store data or pixels for the image if they can be recreated.
* The image is reset to a state similar to when it was first created
* so that if it is again rendered, the image data will have to be
* recreated or fetched again from its source.
* <p>
* Examples of how this method affects specific types of Image object:
* <ul>
* <li>
* BufferedImage objects leave the primary Raster which stores their
* pixels untouched, but flush any information cached about those
* pixels such as copies uploaded to the display hardware for
* accelerated blits.
* <li>
* Image objects created by the Component methods which take a
* width and height leave their primary buffer of pixels untouched,
* but have all cached information released much like is done for
* BufferedImage objects.
* <li>
* VolatileImage objects release all of their pixel resources
* including their primary copy which is typically stored on
* the display hardware where resources are scarce.
* These objects can later be restored using their
* {@link java.awt.image.VolatileImage#validate validate}
* method.
* <li>
* Image objects created by the Toolkit and Component classes which are
* loaded from files, URLs or produced by an {@link ImageProducer}
* are unloaded and all local resources are released.
* These objects can later be reloaded from their original source
* as needed when they are rendered, just as when they were first
* created.
* </ul>
*/
public void flush() {
if (surfaceManager != null) {
surfaceManager.flush();
}
}
/**
* Returns an ImageCapabilities object which can be
* inquired as to the capabilities of this
* Image on the specified GraphicsConfiguration.
* This allows programmers to find
* out more runtime information on the specific Image
* object that they have created. For example, the user
* might create a BufferedImage but the system may have
* no video memory left for creating an image of that
* size on the given GraphicsConfiguration, so although the object
* may be acceleratable in general, it
* does not have that capability on this GraphicsConfiguration.
* @param gc a {@code GraphicsConfiguration} object. A value of null
* for this parameter will result in getting the image capabilities
* for the default {@code GraphicsConfiguration}.
* @return an {@code ImageCapabilities} object that contains
* the capabilities of this {@code Image} on the specified
* GraphicsConfiguration.
* @see java.awt.image.VolatileImage#getCapabilities()
* VolatileImage.getCapabilities()
* @since 1.5
*/
public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
if (surfaceManager != null) {
return surfaceManager.getCapabilities(gc);
}
// Note: this is just a default object that gets returned in the
// absence of any more specific information from a surfaceManager.
// Subclasses of Image should either override this method or
// make sure that they always have a non-null SurfaceManager
// to return an ImageCapabilities object that is appropriate
// for their given subclass type.
return defaultImageCaps;
}
/**
* Sets a hint for this image about how important acceleration is.
* This priority hint is used to compare to the priorities of other
* Image objects when determining how to use scarce acceleration
* resources such as video memory. When and if it is possible to
* accelerate this Image, if there are not enough resources available
* to provide that acceleration but enough can be freed up by
* de-accelerating some other image of lower priority, then that other
* Image may be de-accelerated in deference to this one. Images
* that have the same priority take up resources on a first-come,
* first-served basis.
* @param priority a value between 0 and 1, inclusive, where higher
* values indicate more importance for acceleration. A value of 0
* means that this Image should never be accelerated. Other values
* are used simply to determine acceleration priority relative to other
* Images.
* @throws IllegalArgumentException if {@code priority} is less
* than zero or greater than 1.
* @since 1.5
*/
public void setAccelerationPriority(float priority) {
if (priority < 0 || priority > 1) {
throw new IllegalArgumentException("Priority must be a value " +
"between 0 and 1, inclusive");
}
accelerationPriority = priority;
if (surfaceManager != null) {
surfaceManager.setAccelerationPriority(accelerationPriority);
}
}
/**
* Returns the current value of the acceleration priority hint.
* @see #setAccelerationPriority(float priority) setAccelerationPriority
* @return value between 0 and 1, inclusive, which represents the current
* priority value
* @since 1.5
*/
public float getAccelerationPriority() {
return accelerationPriority;
}
SurfaceManager surfaceManager;
static {
SurfaceManager.setImageAccessor(new SurfaceManager.ImageAccessor() {
public SurfaceManager getSurfaceManager(Image img) {
return img.surfaceManager;
}
public void setSurfaceManager(Image img, SurfaceManager mgr) {
img.surfaceManager = mgr;
}
});
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Capabilities and properties of images.
* @author Michael Martak
* @since 1.4
*/
public class ImageCapabilities implements Cloneable {
private boolean accelerated = false;
/**
* Creates a new object for specifying image capabilities.
* @param accelerated whether or not an accelerated image is desired
*/
public ImageCapabilities(boolean accelerated) {
this.accelerated = accelerated;
}
/**
* Returns {@code true} if the object whose capabilities are
* encapsulated in this {@code ImageCapabilities} can be or is
* accelerated.
* @return whether or not an image can be, or is, accelerated. There are
* various platform-specific ways to accelerate an image, including
* pixmaps, VRAM, AGP. This is the general acceleration method (as
* opposed to residing in system memory).
*/
public boolean isAccelerated() {
return accelerated;
}
/**
* Returns {@code true} if the {@code VolatileImage}
* described by this {@code ImageCapabilities} can lose
* its surfaces.
* @return whether or not a volatile image is subject to losing its surfaces
* at the whim of the operating system.
*/
public boolean isTrueVolatile() {
return false;
}
/**
* @return a copy of this ImageCapabilities object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Since we implement Cloneable, this should never happen
throw new InternalError(e);
}
}
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* An {@code Insets} object is a representation of the borders
* of a container. It specifies the space that a container must leave
* at each of its edges. The space can be a border, a blank space, or
* a title.
*
* @author Arthur van Hoff
* @author Sami Shaio
* @see java.awt.LayoutManager
* @see java.awt.Container
* @since 1.0
*/
public class Insets implements Cloneable, java.io.Serializable {
/**
* The inset from the top.
* This value is added to the Top of the rectangle
* to yield a new location for the Top.
*
* @serial
* @see #clone()
*/
public int top;
/**
* The inset from the left.
* This value is added to the Left of the rectangle
* to yield a new location for the Left edge.
*
* @serial
* @see #clone()
*/
public int left;
/**
* The inset from the bottom.
* This value is subtracted from the Bottom of the rectangle
* to yield a new location for the Bottom.
*
* @serial
* @see #clone()
*/
public int bottom;
/**
* The inset from the right.
* This value is subtracted from the Right of the rectangle
* to yield a new location for the Right edge.
*
* @serial
* @see #clone()
*/
public int right;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -2272572637695466749L;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Creates and initializes a new {@code Insets} object with the
* specified top, left, bottom, and right insets.
* @param top the inset from the top.
* @param left the inset from the left.
* @param bottom the inset from the bottom.
* @param right the inset from the right.
*/
public Insets(int top, int left, int bottom, int right) {
this.top = top;
this.left = left;
this.bottom = bottom;
this.right = right;
}
/**
* Set top, left, bottom, and right to the specified values
*
* @param top the inset from the top.
* @param left the inset from the left.
* @param bottom the inset from the bottom.
* @param right the inset from the right.
* @since 1.5
*/
public void set(int top, int left, int bottom, int right) {
this.top = top;
this.left = left;
this.bottom = bottom;
this.right = right;
}
/**
* Checks whether two insets objects are equal. Two instances
* of {@code Insets} are equal if the four integer values
* of the fields {@code top}, {@code left},
* {@code bottom}, and {@code right} are all equal.
* @return {@code true} if the two insets are equal;
* otherwise {@code false}.
* @since 1.1
*/
public boolean equals(Object obj) {
if (obj instanceof Insets) {
Insets insets = (Insets)obj;
return ((top == insets.top) && (left == insets.left) &&
(bottom == insets.bottom) && (right == insets.right));
}
return false;
}
/**
* Returns the hash code for this Insets.
*
* @return a hash code for this Insets.
*/
public int hashCode() {
int sum1 = left + bottom;
int sum2 = right + top;
int val1 = sum1 * (sum1 + 1)/2 + left;
int val2 = sum2 * (sum2 + 1)/2 + top;
int sum3 = val1 + val2;
return sum3 * (sum3 + 1)/2 + val2;
}
/**
* Returns a string representation of this {@code Insets} object.
* This method is intended to be used only for debugging purposes, and
* the content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return a string representation of this {@code Insets} object.
*/
public String toString() {
return getClass().getName() + "[top=" + top + ",left=" + left + ",bottom=" + bottom + ",right=" + right + "]";
}
/**
* Create a copy of this object.
* @return a copy of this {@code Insets} object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.*;
/**
* The interface for objects which contain a set of items for
* which zero or more can be selected.
*
* @author Amy Fowler
*/
public interface ItemSelectable {
/**
* Returns the selected items or {@code null} if no
* items are selected.
*
* @return the list of selected objects, or {@code null}
*/
public Object[] getSelectedObjects();
/**
* Adds a listener to receive item events when the state of an item is
* changed by the user. Item events are not sent when an item's
* state is set programmatically. If {@code l} is
* {@code null}, no exception is thrown and no action is performed.
*
* @param l the listener to receive events
* @see ItemEvent
*/
public void addItemListener(ItemListener l);
/**
* Removes an item listener.
* If {@code l} is {@code null},
* no exception is thrown and no action is performed.
*
* @param l the listener being removed
* @see ItemEvent
*/
public void removeItemListener(ItemListener l);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
/**
* A KeyEventDispatcher cooperates with the current KeyboardFocusManager in the
* targeting and dispatching of all KeyEvents. KeyEventDispatchers registered
* with the current KeyboardFocusManager will receive KeyEvents before they are
* dispatched to their targets, allowing each KeyEventDispatcher to retarget
* the event, consume it, dispatch the event itself, or make other changes.
* <p>
* Note that KeyboardFocusManager itself implements KeyEventDispatcher. By
* default, the current KeyboardFocusManager will be the sink for all KeyEvents
* not dispatched by the registered KeyEventDispatchers. The current
* KeyboardFocusManager cannot be completely deregistered as a
* KeyEventDispatcher. However, if a KeyEventDispatcher reports that it
* dispatched the KeyEvent, regardless of whether it actually did so, the
* KeyboardFocusManager will take no further action with regard to the
* KeyEvent. (While it is possible for client code to register the current
* KeyboardFocusManager as a KeyEventDispatcher one or more times, this is
* usually unnecessary and not recommended.)
*
* @author David Mendenhall
*
* @see KeyboardFocusManager#addKeyEventDispatcher
* @see KeyboardFocusManager#removeKeyEventDispatcher
* @since 1.4
*/
@FunctionalInterface
public interface KeyEventDispatcher {
/**
* This method is called by the current KeyboardFocusManager requesting
* that this KeyEventDispatcher dispatch the specified event on its behalf.
* This KeyEventDispatcher is free to retarget the event, consume it,
* dispatch it itself, or make other changes. This capability is typically
* used to deliver KeyEvents to Components other than the focus owner. This
* can be useful when navigating children of non-focusable Windows in an
* accessible environment, for example. Note that if a KeyEventDispatcher
* dispatches the KeyEvent itself, it must use {@code redispatchEvent}
* to prevent the current KeyboardFocusManager from recursively requesting
* that this KeyEventDispatcher dispatch the event again.
* <p>
* If an implementation of this method returns {@code false}, then
* the KeyEvent is passed to the next KeyEventDispatcher in the chain,
* ending with the current KeyboardFocusManager. If an implementation
* returns {@code true}, the KeyEvent is assumed to have been
* dispatched (although this need not be the case), and the current
* KeyboardFocusManager will take no further action with regard to the
* KeyEvent. In such a case,
* {@code KeyboardFocusManager.dispatchEvent} should return
* {@code true} as well. If an implementation consumes the KeyEvent,
* but returns {@code false}, the consumed event will still be passed
* to the next KeyEventDispatcher in the chain. It is important for
* developers to check whether the KeyEvent has been consumed before
* dispatching it to a target. By default, the current KeyboardFocusManager
* will not dispatch a consumed KeyEvent.
*
* @param e the KeyEvent to dispatch
* @return {@code true} if the KeyboardFocusManager should take no
* further action with regard to the KeyEvent; {@code false}
* otherwise
* @see KeyboardFocusManager#redispatchEvent
*/
boolean dispatchKeyEvent(KeyEvent e);
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
/**
* A KeyEventPostProcessor cooperates with the current KeyboardFocusManager
* in the final resolution of all unconsumed KeyEvents. KeyEventPostProcessors
* registered with the current KeyboardFocusManager will receive KeyEvents
* after the KeyEvents have been dispatched to and handled by their targets.
* KeyEvents that would have been otherwise discarded because no Component in
* the application currently owns the focus will also be forwarded to
* registered KeyEventPostProcessors. This will allow applications to implement
* features that require global KeyEvent post-handling, such as menu shortcuts.
* <p>
* Note that the KeyboardFocusManager itself implements KeyEventPostProcessor.
* By default, the current KeyboardFocusManager will be the final
* KeyEventPostProcessor in the chain. The current KeyboardFocusManager cannot
* be completely deregistered as a KeyEventPostProcessor. However, if a
* KeyEventPostProcessor reports that no further post-processing of the
* KeyEvent should take place, the AWT will consider the event fully handled
* and will take no additional action with regard to the event. (While it is
* possible for client code to register the current KeyboardFocusManager as
* a KeyEventPostProcessor one or more times, this is usually unnecessary and
* not recommended.)
*
* @author David Mendenhall
*
* @see KeyboardFocusManager#addKeyEventPostProcessor
* @see KeyboardFocusManager#removeKeyEventPostProcessor
* @since 1.4
*/
@FunctionalInterface
public interface KeyEventPostProcessor {
/**
* This method is called by the current KeyboardFocusManager, requesting
* that this KeyEventPostProcessor perform any necessary post-processing
* which should be part of the KeyEvent's final resolution. At the time
* this method is invoked, typically the KeyEvent has already been
* dispatched to and handled by its target. However, if no Component in
* the application currently owns the focus, then the KeyEvent has not
* been dispatched to any Component. Typically, KeyEvent post-processing
* will be used to implement features which require global KeyEvent
* post-handling, such as menu shortcuts. Note that if a
* KeyEventPostProcessor wishes to dispatch the KeyEvent, it must use
* {@code redispatchEvent} to prevent the AWT from recursively
* requesting that this KeyEventPostProcessor perform post-processing
* of the event again.
* <p>
* If an implementation of this method returns {@code false}, then the
* KeyEvent is passed to the next KeyEventPostProcessor in the chain,
* ending with the current KeyboardFocusManager. If an implementation
* returns {@code true}, the KeyEvent is assumed to have been fully
* handled (although this need not be the case), and the AWT will take no
* further action with regard to the KeyEvent. If an implementation
* consumes the KeyEvent but returns {@code false}, the consumed
* event will still be passed to the next KeyEventPostProcessor in the
* chain. It is important for developers to check whether the KeyEvent has
* been consumed before performing any post-processing of the KeyEvent. By
* default, the current KeyboardFocusManager will perform no post-
* processing in response to a consumed KeyEvent.
*
* @param e the KeyEvent to post-process
* @return {@code true} if the AWT should take no further action with
* regard to the KeyEvent; {@code false} otherwise
* @see KeyboardFocusManager#redispatchEvent
*/
boolean postProcessKeyEvent(KeyEvent e);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,363 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.LabelPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.accessibility.*;
/**
* A {@code Label} object is a component for placing text in a
* container. A label displays a single line of read-only text.
* The text can be changed by the application, but a user cannot edit it
* directly.
* <p>
* For example, the code&nbsp;.&nbsp;.&nbsp;.
*
* <hr><blockquote><pre>
* setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
* add(new Label("Hi There!"));
* add(new Label("Another Label"));
* </pre></blockquote><hr>
* <p>
* produces the following labels:
* <p>
* <img src="doc-files/Label-1.gif" alt="Two labels: 'Hi There!' and 'Another label'"
* style="float:center; margin: 7px 10px;">
*
* @author Sami Shaio
* @since 1.0
*/
public class Label extends Component implements Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
}
/**
* Indicates that the label should be left justified.
*/
public static final int LEFT = 0;
/**
* Indicates that the label should be centered.
*/
public static final int CENTER = 1;
/**
* Indicates that the label should be right justified.
*/
public static final int RIGHT = 2;
/**
* The text of this label.
* This text can be modified by the program
* but never by the user.
*
* @serial
* @see #getText()
* @see #setText(String)
*/
String text;
/**
* The label's alignment. The default alignment is set
* to be left justified.
*
* @serial
* @see #getAlignment()
* @see #setAlignment(int)
*/
int alignment = LEFT;
private static final String base = "label";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 3094126758329070636L;
/**
* Constructs an empty label.
* The text of the label is the empty string {@code ""}.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Label() throws HeadlessException {
this("", LEFT);
}
/**
* Constructs a new label with the specified string of text,
* left justified.
* @param text the string that the label presents.
* A {@code null} value
* will be accepted without causing a NullPointerException
* to be thrown.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Label(String text) throws HeadlessException {
this(text, LEFT);
}
/**
* Constructs a new label that presents the specified string of
* text with the specified alignment.
* Possible values for {@code alignment} are {@code Label.LEFT},
* {@code Label.RIGHT}, and {@code Label.CENTER}.
* @param text the string that the label presents.
* A {@code null} value
* will be accepted without causing a NullPointerException
* to be thrown.
* @param alignment the alignment value.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Label(String text, int alignment) throws HeadlessException {
GraphicsEnvironment.checkHeadless();
this.text = text;
setAlignment(alignment);
}
/**
* Read a label from an object input stream.
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless()} returns
* {@code true}
* @serial
* @since 1.4
* @see java.awt.GraphicsEnvironment#isHeadless
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException {
GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
}
/**
* Construct a name for this component. Called by getName() when the
* name is {@code null}.
*/
String constructComponentName() {
synchronized (Label.class) {
return base + nameCounter++;
}
}
/**
* Creates the peer for this label. The peer allows us to
* modify the appearance of the label without changing its
* functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createLabel(this);
super.addNotify();
}
}
/**
* Gets the current alignment of this label. Possible values are
* {@code Label.LEFT}, {@code Label.RIGHT}, and
* {@code Label.CENTER}.
* @return the alignment of this label
* @see java.awt.Label#setAlignment
*/
public int getAlignment() {
return alignment;
}
/**
* Sets the alignment for this label to the specified alignment.
* Possible values are {@code Label.LEFT},
* {@code Label.RIGHT}, and {@code Label.CENTER}.
* @param alignment the alignment to be set.
* @exception IllegalArgumentException if an improper value for
* {@code alignment} is given.
* @see java.awt.Label#getAlignment
*/
public synchronized void setAlignment(int alignment) {
switch (alignment) {
case LEFT:
case CENTER:
case RIGHT:
this.alignment = alignment;
LabelPeer peer = (LabelPeer)this.peer;
if (peer != null) {
peer.setAlignment(alignment);
}
return;
}
throw new IllegalArgumentException("improper alignment: " + alignment);
}
/**
* Gets the text of this label.
* @return the text of this label, or {@code null} if
* the text has been set to {@code null}.
* @see java.awt.Label#setText
*/
public String getText() {
return text;
}
/**
* Sets the text for this label to the specified text.
* @param text the text that this label displays. If
* {@code text} is {@code null}, it is
* treated for display purposes like an empty
* string {@code ""}.
* @see java.awt.Label#getText
*/
public void setText(String text) {
boolean testvalid = false;
synchronized (this) {
if (text != this.text && (this.text == null ||
!this.text.equals(text))) {
this.text = text;
LabelPeer peer = (LabelPeer)this.peer;
if (peer != null) {
peer.setText(text);
}
testvalid = true;
}
}
// This could change the preferred size of the Component.
if (testvalid) {
invalidateIfValid();
}
}
/**
* Returns a string representing the state of this {@code Label}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this label
*/
protected String paramString() {
String align = "";
switch (alignment) {
case LEFT: align = "left"; break;
case CENTER: align = "center"; break;
case RIGHT: align = "right"; break;
}
return super.paramString() + ",align=" + align + ",text=" + text;
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this Label.
* For labels, the AccessibleContext takes the form of an
* AccessibleAWTLabel.
* A new AccessibleAWTLabel instance is created if necessary.
*
* @return an AccessibleAWTLabel that serves as the
* AccessibleContext of this Label
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTLabel();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Label} class. It provides an implementation of the
* Java Accessibility API appropriate to label user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTLabel extends AccessibleAWTComponent
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -3568967560160480438L;
/**
* Constructor for the accessible label.
*/
public AccessibleAWTLabel() {
super();
}
/**
* Get the accessible name of this object.
*
* @return the localized name of the object -- can be null if this
* object does not have a name
* @see AccessibleContext#setAccessibleName
*/
public String getAccessibleName() {
if (accessibleName != null) {
return accessibleName;
} else {
if (getText() == null) {
return super.getAccessibleName();
} else {
return getText();
}
}
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.LABEL;
}
} // inner class AccessibleAWTLabel
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Defines the interface for classes that know how to lay out
* {@code Container}s.
* <p>
* Swing's painting architecture assumes the children of a
* {@code JComponent} do not overlap. If a
* {@code JComponent}'s {@code LayoutManager} allows
* children to overlap, the {@code JComponent} must override
* {@code isOptimizedDrawingEnabled} to return false.
*
* @see Container
* @see javax.swing.JComponent#isOptimizedDrawingEnabled
*
* @author Sami Shaio
* @author Arthur van Hoff
*/
public interface LayoutManager {
/**
* If the layout manager uses a per-component string,
* adds the component {@code comp} to the layout,
* associating it
* with the string specified by {@code name}.
*
* @param name the string to be associated with the component
* @param comp the component to be added
*/
void addLayoutComponent(String name, Component comp);
/**
* Removes the specified component from the layout.
* @param comp the component to be removed
*/
void removeLayoutComponent(Component comp);
/**
* Calculates the preferred size dimensions for the specified
* container, given the components it contains.
*
* @param parent the container to be laid out
* @return the preferred dimension for the container
*
* @see #minimumLayoutSize
*/
Dimension preferredLayoutSize(Container parent);
/**
* Calculates the minimum size dimensions for the specified
* container, given the components it contains.
*
* @param parent the component to be laid out
* @return the minimum dimension for the container
*
* @see #preferredLayoutSize
*/
Dimension minimumLayoutSize(Container parent);
/**
* Lays out the specified container.
* @param parent the container to be laid out
*/
void layoutContainer(Container parent);
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* Defines an interface for classes that know how to layout Containers
* based on a layout constraints object.
*
* This interface extends the LayoutManager interface to deal with layouts
* explicitly in terms of constraint objects that specify how and where
* components should be added to the layout.
* <p>
* This minimal extension to LayoutManager is intended for tool
* providers who wish to the creation of constraint-based layouts.
* It does not yet provide full, general support for custom
* constraint-based layout managers.
*
* @see LayoutManager
* @see Container
*
* @author Jonni Kanerva
*/
public interface LayoutManager2 extends LayoutManager {
/**
* Adds the specified component to the layout, using the specified
* constraint object.
* @param comp the component to be added
* @param constraints where/how the component is added to the layout.
*/
void addLayoutComponent(Component comp, Object constraints);
/**
* Calculates the maximum size dimensions for the specified container,
* given the components it contains.
*
* @see java.awt.Component#getMaximumSize
* @see LayoutManager
* @param target the target container
* @return the maximum size of the container
*/
public Dimension maximumLayoutSize(Container target);
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*
* @param target the target container
* @return the x-axis alignment preference
*/
public float getLayoutAlignmentX(Container target);
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*
* @param target the target container
* @return the y-axis alignment preference
*/
public float getLayoutAlignmentY(Container target);
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
* @param target the target container
*/
public void invalidateLayout(Container target);
}

View file

@ -0,0 +1,382 @@
/*
* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.beans.ConstructorProperties;
/**
* The {@code LinearGradientPaint} class provides a way to fill
* a {@link java.awt.Shape} with a linear color gradient pattern. The user
* may specify two or more gradient colors, and this paint will provide an
* interpolation between each color. The user also specifies start and end
* points which define where in user space the color gradient should begin
* and end.
* <p>
* The user must provide an array of floats specifying how to distribute the
* colors along the gradient. These values should range from 0.0 to 1.0 and
* act like keyframes along the gradient (they mark where the gradient should
* be exactly a particular color).
* <p>
* In the event that the user does not set the first keyframe value equal
* to 0 and/or the last keyframe value equal to 1, keyframes will be created
* at these positions and the first and last colors will be replicated there.
* So, if a user specifies the following arrays to construct a gradient:<br>
* <pre>
* {Color.BLUE, Color.RED}, {.3f, .7f}
* </pre>
* this will be converted to a gradient with the following keyframes:<br>
* <pre>
* {Color.BLUE, Color.BLUE, Color.RED, Color.RED}, {0f, .3f, .7f, 1f}
* </pre>
*
* <p>
* The user may also select what action the {@code LinearGradientPaint} object
* takes when it is filling the space outside the start and end points by
* setting {@code CycleMethod} to either {@code REFLECTION} or {@code REPEAT}.
* The distances between any two colors in any of the reflected or repeated
* copies of the gradient are the same as the distance between those same two
* colors between the start and end points.
* Note that some minor variations in distances may occur due to sampling at
* the granularity of a pixel.
* If no cycle method is specified, {@code NO_CYCLE} will be chosen by
* default, which means the endpoint colors will be used to fill the
* remaining area.
* <p>
* The colorSpace parameter allows the user to specify in which colorspace
* the interpolation should be performed, default sRGB or linearized RGB.
*
* <p>
* The following code demonstrates typical usage of
* {@code LinearGradientPaint}:
* <pre>
* Point2D start = new Point2D.Float(0, 0);
* Point2D end = new Point2D.Float(50, 50);
* float[] dist = {0.0f, 0.2f, 1.0f};
* Color[] colors = {Color.RED, Color.WHITE, Color.BLUE};
* LinearGradientPaint p =
* new LinearGradientPaint(start, end, dist, colors);
* </pre>
* <p>
* This code will create a {@code LinearGradientPaint} which interpolates
* between red and white for the first 20% of the gradient and between white
* and blue for the remaining 80%.
*
* <p>
* This image demonstrates the example code above for each
* of the three cycle methods:
* <p style="text-align:center">
* <img src = "doc-files/LinearGradientPaint.png"
* alt="image showing the output of the example code">
*
* @see java.awt.Paint
* @see java.awt.Graphics2D#setPaint
* @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
* @since 1.6
*/
public final class LinearGradientPaint extends MultipleGradientPaint {
/** Gradient start and end points. */
private final Point2D start, end;
/**
* Constructs a {@code LinearGradientPaint} with a default
* {@code NO_CYCLE} repeating method and {@code SRGB} color space.
*
* @param startX the X coordinate of the gradient axis start point
* in user space
* @param startY the Y coordinate of the gradient axis start point
* in user space
* @param endX the X coordinate of the gradient axis end point
* in user space
* @param endY the Y coordinate of the gradient axis end point
* in user space
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
*
* @throws NullPointerException
* if {@code fractions} array is null,
* or {@code colors} array is null,
* @throws IllegalArgumentException
* if start and end points are the same points,
* or {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
public LinearGradientPaint(float startX, float startY,
float endX, float endY,
float[] fractions, Color[] colors)
{
this(new Point2D.Float(startX, startY),
new Point2D.Float(endX, endY),
fractions,
colors,
CycleMethod.NO_CYCLE);
}
/**
* Constructs a {@code LinearGradientPaint} with a default {@code SRGB}
* color space.
*
* @param startX the X coordinate of the gradient axis start point
* in user space
* @param startY the Y coordinate of the gradient axis start point
* in user space
* @param endX the X coordinate of the gradient axis end point
* in user space
* @param endY the Y coordinate of the gradient axis end point
* in user space
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
* @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
* or {@code REPEAT}
*
* @throws NullPointerException
* if {@code fractions} array is null,
* or {@code colors} array is null,
* or {@code cycleMethod} is null
* @throws IllegalArgumentException
* if start and end points are the same points,
* or {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
public LinearGradientPaint(float startX, float startY,
float endX, float endY,
float[] fractions, Color[] colors,
CycleMethod cycleMethod)
{
this(new Point2D.Float(startX, startY),
new Point2D.Float(endX, endY),
fractions,
colors,
cycleMethod);
}
/**
* Constructs a {@code LinearGradientPaint} with a default
* {@code NO_CYCLE} repeating method and {@code SRGB} color space.
*
* @param start the gradient axis start {@code Point2D} in user space
* @param end the gradient axis end {@code Point2D} in user space
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
*
* @throws NullPointerException
* if one of the points is null,
* or {@code fractions} array is null,
* or {@code colors} array is null
* @throws IllegalArgumentException
* if start and end points are the same points,
* or {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
public LinearGradientPaint(Point2D start, Point2D end,
float[] fractions, Color[] colors)
{
this(start, end,
fractions, colors,
CycleMethod.NO_CYCLE);
}
/**
* Constructs a {@code LinearGradientPaint} with a default {@code SRGB}
* color space.
*
* @param start the gradient axis start {@code Point2D} in user space
* @param end the gradient axis end {@code Point2D} in user space
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
* @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
* or {@code REPEAT}
*
* @throws NullPointerException
* if one of the points is null,
* or {@code fractions} array is null,
* or {@code colors} array is null,
* or {@code cycleMethod} is null
* @throws IllegalArgumentException
* if start and end points are the same points,
* or {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
public LinearGradientPaint(Point2D start, Point2D end,
float[] fractions, Color[] colors,
CycleMethod cycleMethod)
{
this(start, end,
fractions, colors,
cycleMethod,
ColorSpaceType.SRGB,
new AffineTransform());
}
/**
* Constructs a {@code LinearGradientPaint}.
*
* @param start the gradient axis start {@code Point2D} in user space
* @param end the gradient axis end {@code Point2D} in user space
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
* @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
* or {@code REPEAT}
* @param colorSpace which color space to use for interpolation,
* either {@code SRGB} or {@code LINEAR_RGB}
* @param gradientTransform transform to apply to the gradient
*
* @throws NullPointerException
* if one of the points is null,
* or {@code fractions} array is null,
* or {@code colors} array is null,
* or {@code cycleMethod} is null,
* or {@code colorSpace} is null,
* or {@code gradientTransform} is null
* @throws IllegalArgumentException
* if start and end points are the same points,
* or {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
@ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
public LinearGradientPaint(Point2D start, Point2D end,
float[] fractions, Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace,
AffineTransform gradientTransform)
{
super(fractions, colors, cycleMethod, colorSpace, gradientTransform);
// check input parameters
if (start == null || end == null) {
throw new NullPointerException("Start and end points must be" +
"non-null");
}
if (start.equals(end)) {
throw new IllegalArgumentException("Start point cannot equal" +
"endpoint");
}
// copy the points...
this.start = new Point2D.Double(start.getX(), start.getY());
this.end = new Point2D.Double(end.getX(), end.getY());
}
/**
* Creates and returns a {@link PaintContext} used to
* generate a linear color gradient pattern.
* See the {@link Paint#createContext specification} of the
* method in the {@link Paint} interface for information
* on null parameter handling.
*
* @param cm the preferred {@link ColorModel} which represents the most convenient
* format for the caller to receive the pixel data, or {@code null}
* if there is no preference.
* @param deviceBounds the device space bounding box
* of the graphics primitive being rendered.
* @param userBounds the user space bounding box
* of the graphics primitive being rendered.
* @param transform the {@link AffineTransform} from user
* space into device space.
* @param hints the set of hints that the context object can use to
* choose between rendering alternatives.
* @return the {@code PaintContext} for
* generating color patterns.
* @see Paint
* @see PaintContext
* @see ColorModel
* @see Rectangle
* @see Rectangle2D
* @see AffineTransform
* @see RenderingHints
*/
public PaintContext createContext(ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform transform,
RenderingHints hints)
{
// avoid modifying the user's transform...
transform = new AffineTransform(transform);
// incorporate the gradient transform
transform.concatenate(gradientTransform);
if ((fractions.length == 2) &&
(cycleMethod != CycleMethod.REPEAT) &&
(colorSpace == ColorSpaceType.SRGB))
{
// faster to use the basic GradientPaintContext for this
// common case
boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE);
return new GradientPaintContext(cm, start, end,
transform,
colors[0], colors[1],
cyclic);
} else {
return new LinearGradientPaintContext(this, cm,
deviceBounds, userBounds,
transform, hints,
start, end,
fractions, colors,
cycleMethod, colorSpace);
}
}
/**
* Returns a copy of the start point of the gradient axis.
*
* @return a {@code Point2D} object that is a copy of the point
* that anchors the first color of this {@code LinearGradientPaint}
*/
public Point2D getStartPoint() {
return new Point2D.Double(start.getX(), start.getY());
}
/**
* Returns a copy of the end point of the gradient axis.
*
* @return a {@code Point2D} object that is a copy of the point
* that anchors the last color of this {@code LinearGradientPaint}
*/
public Point2D getEndPoint() {
return new Point2D.Double(end.getX(), end.getY());
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.MultipleGradientPaint.ColorSpaceType;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
/**
* Provides the actual implementation for the LinearGradientPaint.
* This is where the pixel processing is done.
*
* @see java.awt.LinearGradientPaint
* @see java.awt.PaintContext
* @see java.awt.Paint
* @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
*/
final class LinearGradientPaintContext extends MultipleGradientPaintContext {
/**
* The following invariants are used to process the gradient value from
* a device space coordinate, (X, Y):
* g(X, Y) = dgdX*X + dgdY*Y + gc
*/
private float dgdX, dgdY, gc;
/**
* Constructor for LinearGradientPaintContext.
*
* @param paint the {@code LinearGradientPaint} from which this context
* is created
* @param cm {@code ColorModel} that receives
* the {@code Paint} data. This is used only as a hint.
* @param deviceBounds the device space bounding box of the
* graphics primitive being rendered
* @param userBounds the user space bounding box of the
* graphics primitive being rendered
* @param t the {@code AffineTransform} from user
* space into device space (gradientTransform should be
* concatenated with this)
* @param hints the hints that the context object uses to choose
* between rendering alternatives
* @param start gradient start point, in user space
* @param end gradient end point, in user space
* @param fractions the fractions specifying the gradient distribution
* @param colors the gradient colors
* @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
* @param colorSpace which colorspace to use for interpolation,
* either SRGB or LINEAR_RGB
*/
LinearGradientPaintContext(LinearGradientPaint paint,
ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform t,
RenderingHints hints,
Point2D start,
Point2D end,
float[] fractions,
Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace)
{
super(paint, cm, deviceBounds, userBounds, t, hints, fractions,
colors, cycleMethod, colorSpace);
// A given point in the raster should take on the same color as its
// projection onto the gradient vector.
// Thus, we want the projection of the current position vector
// onto the gradient vector, then normalized with respect to the
// length of the gradient vector, giving a value which can be mapped
// into the range 0-1.
// projection =
// currentVector dot gradientVector / length(gradientVector)
// normalized = projection / length(gradientVector)
float startx = (float)start.getX();
float starty = (float)start.getY();
float endx = (float)end.getX();
float endy = (float)end.getY();
float dx = endx - startx; // change in x from start to end
float dy = endy - starty; // change in y from start to end
float dSq = dx*dx + dy*dy; // total distance squared
// avoid repeated calculations by doing these divides once
float constX = dx/dSq;
float constY = dy/dSq;
// incremental change along gradient for +x
dgdX = a00*constX + a10*constY;
// incremental change along gradient for +y
dgdY = a01*constX + a11*constY;
// constant, incorporates the translation components from the matrix
gc = (a02-startx)*constX + (a12-starty)*constY;
}
/**
* Return a Raster containing the colors generated for the graphics
* operation. This is where the area is filled with colors distributed
* linearly.
*
* @param x,y,w,h the area in device space for which colors are
* generated.
*/
protected void fillRaster(int[] pixels, int off, int adjust,
int x, int y, int w, int h)
{
// current value for row gradients
float g = 0;
// used to end iteration on rows
int rowLimit = off + w;
// constant which can be pulled out of the inner loop
float initConst = (dgdX*x) + gc;
for (int i = 0; i < h; i++) { // for every row
// initialize current value to be start
g = initConst + dgdY*(y+i);
while (off < rowLimit) { // for every pixel in this row
// get the color
pixels[off++] = indexIntoGradientsArrays(g);
// incremental change in g
g += dgdX;
}
// change in off from row to row
off += adjust;
//rowlimit is width + offset
rowLimit = off + w;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,994 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.Component;
import java.awt.Image;
import java.awt.image.ImageObserver;
import sun.awt.image.MultiResolutionToolkitImage;
/**
* The {@code MediaTracker} class is a utility class to track
* the status of a number of media objects. Media objects could
* include audio clips as well as images, though currently only
* images are supported.
* <p>
* To use a media tracker, create an instance of
* {@code MediaTracker} and call its {@code addImage}
* method for each image to be tracked. In addition, each image can
* be assigned a unique identifier. This identifier controls the
* priority order in which the images are fetched. It can also be used
* to identify unique subsets of the images that can be waited on
* independently. Images with a lower ID are loaded in preference to
* those with a higher ID number.
*
* <p>
*
* Tracking an animated image
* might not always be useful
* due to the multi-part nature of animated image
* loading and painting,
* but it is supported.
* {@code MediaTracker} treats an animated image
* as completely loaded
* when the first frame is completely loaded.
* At that point, the {@code MediaTracker}
* signals any waiters
* that the image is completely loaded.
* If no {@code ImageObserver}s are observing the image
* when the first frame has finished loading,
* the image might flush itself
* to conserve resources
* (see {@link Image#flush()}).
*
* <p>
* Here is an example of using {@code MediaTracker}:
*
* <hr><blockquote><pre>{@code
* import java.applet.Applet;
* import java.awt.Color;
* import java.awt.Image;
* import java.awt.Graphics;
* import java.awt.MediaTracker;
*
* public class ImageBlaster extends Applet implements Runnable {
* MediaTracker tracker;
* Image bg;
* Image anim[] = new Image[5];
* int index;
* Thread animator;
*
* // Get the images for the background (id == 0)
* // and the animation frames (id == 1)
* // and add them to the MediaTracker
* public void init() {
* tracker = new MediaTracker(this);
* bg = getImage(getDocumentBase(),
* "images/background.gif");
* tracker.addImage(bg, 0);
* for (int i = 0; i < 5; i++) {
* anim[i] = getImage(getDocumentBase(),
* "images/anim"+i+".gif");
* tracker.addImage(anim[i], 1);
* }
* }
*
* // Start the animation thread.
* public void start() {
* animator = new Thread(this);
* animator.start();
* }
*
* // Stop the animation thread.
* public void stop() {
* animator = null;
* }
*
* // Run the animation thread.
* // First wait for the background image to fully load
* // and paint. Then wait for all of the animation
* // frames to finish loading. Finally, loop and
* // increment the animation frame index.
* public void run() {
* try {
* tracker.waitForID(0);
* tracker.waitForID(1);
* } catch (InterruptedException e) {
* return;
* }
* Thread me = Thread.currentThread();
* while (animator == me) {
* try {
* Thread.sleep(100);
* } catch (InterruptedException e) {
* break;
* }
* synchronized (this) {
* index++;
* if (index >= anim.length) {
* index = 0;
* }
* }
* repaint();
* }
* }
*
* // The background image fills the frame so we
* // don't need to clear the applet on repaints.
* // Just call the paint method.
* public void update(Graphics g) {
* paint(g);
* }
*
* // Paint a large red rectangle if there are any errors
* // loading the images. Otherwise always paint the
* // background so that it appears incrementally as it
* // is loading. Finally, only paint the current animation
* // frame if all of the frames (id == 1) are done loading,
* // so that we don't get partial animations.
* public void paint(Graphics g) {
* if ((tracker.statusAll(false) & MediaTracker.ERRORED) != 0) {
* g.setColor(Color.red);
* g.fillRect(0, 0, size().width, size().height);
* return;
* }
* g.drawImage(bg, 0, 0, this);
* if (tracker.statusID(1, false) == MediaTracker.COMPLETE) {
* g.drawImage(anim[index], 10, 10, this);
* }
* }
* }
* } </pre></blockquote><hr>
*
* @author Jim Graham
* @since 1.0
*/
public class MediaTracker implements java.io.Serializable {
/**
* A given {@code Component} that will be
* tracked by a media tracker where the image will
* eventually be drawn.
*
* @serial
* @see #MediaTracker(Component)
*/
Component target;
/**
* The head of the list of {@code Images} that is being
* tracked by the {@code MediaTracker}.
*
* @serial
* @see #addImage(Image, int)
* @see #removeImage(Image)
*/
MediaEntry head;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -483174189758638095L;
/**
* Creates a media tracker to track images for a given component.
* @param comp the component on which the images
* will eventually be drawn
*/
public MediaTracker(Component comp) {
target = comp;
}
/**
* Adds an image to the list of images being tracked by this media
* tracker. The image will eventually be rendered at its default
* (unscaled) size.
* @param image the image to be tracked
* @param id an identifier used to track this image
*/
public void addImage(Image image, int id) {
addImage(image, id, -1, -1);
}
/**
* Adds a scaled image to the list of images being tracked
* by this media tracker. The image will eventually be
* rendered at the indicated width and height.
*
* @param image the image to be tracked
* @param id an identifier that can be used to track this image
* @param w the width at which the image is rendered
* @param h the height at which the image is rendered
*/
public synchronized void addImage(Image image, int id, int w, int h) {
addImageImpl(image, id, w, h);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
addImageImpl(rvImage, id,
w == -1 ? -1 : 2 * w,
h == -1 ? -1 : 2 * h);
}
}
private void addImageImpl(Image image, int id, int w, int h) {
head = MediaEntry.insert(head,
new ImageMediaEntry(this, image, id, w, h));
}
/**
* Flag indicating that media is currently being loaded.
* @see java.awt.MediaTracker#statusAll
* @see java.awt.MediaTracker#statusID
*/
public static final int LOADING = 1;
/**
* Flag indicating that the downloading of media was aborted.
* @see java.awt.MediaTracker#statusAll
* @see java.awt.MediaTracker#statusID
*/
public static final int ABORTED = 2;
/**
* Flag indicating that the downloading of media encountered
* an error.
* @see java.awt.MediaTracker#statusAll
* @see java.awt.MediaTracker#statusID
*/
public static final int ERRORED = 4;
/**
* Flag indicating that the downloading of media was completed
* successfully.
* @see java.awt.MediaTracker#statusAll
* @see java.awt.MediaTracker#statusID
*/
public static final int COMPLETE = 8;
static final int DONE = (ABORTED | ERRORED | COMPLETE);
/**
* Checks to see if all images being tracked by this media tracker
* have finished loading.
* <p>
* This method does not start loading the images if they are not
* already loading.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code isErrorAny} or {@code isErrorID} methods to
* check for errors.
* @return {@code true} if all images have finished loading,
* have been aborted, or have encountered
* an error; {@code false} otherwise
* @see java.awt.MediaTracker#checkAll(boolean)
* @see java.awt.MediaTracker#checkID
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#isErrorID
*/
public boolean checkAll() {
return checkAll(false, true);
}
/**
* Checks to see if all images being tracked by this media tracker
* have finished loading.
* <p>
* If the value of the {@code load} flag is {@code true},
* then this method starts loading any images that are not yet
* being loaded.
* <p>
* If there is an error while loading or scaling an image, that
* image is considered to have finished loading. Use the
* {@code isErrorAny} and {@code isErrorID} methods to
* check for errors.
* @param load if {@code true}, start loading any
* images that are not yet being loaded
* @return {@code true} if all images have finished loading,
* have been aborted, or have encountered
* an error; {@code false} otherwise
* @see java.awt.MediaTracker#checkID
* @see java.awt.MediaTracker#checkAll()
* @see java.awt.MediaTracker#isErrorAny()
* @see java.awt.MediaTracker#isErrorID(int)
*/
public boolean checkAll(boolean load) {
return checkAll(load, true);
}
private synchronized boolean checkAll(boolean load, boolean verify) {
MediaEntry cur = head;
boolean done = true;
while (cur != null) {
if ((cur.getStatus(load, verify) & DONE) == 0) {
done = false;
}
cur = cur.next;
}
return done;
}
/**
* Checks the error status of all of the images.
* @return {@code true} if any of the images tracked
* by this media tracker had an error during
* loading; {@code false} otherwise
* @see java.awt.MediaTracker#isErrorID
* @see java.awt.MediaTracker#getErrorsAny
*/
public synchronized boolean isErrorAny() {
MediaEntry cur = head;
while (cur != null) {
if ((cur.getStatus(false, true) & ERRORED) != 0) {
return true;
}
cur = cur.next;
}
return false;
}
/**
* Returns a list of all media that have encountered an error.
* @return an array of media objects tracked by this
* media tracker that have encountered
* an error, or {@code null} if
* there are none with errors
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#getErrorsID
*/
public synchronized Object[] getErrorsAny() {
MediaEntry cur = head;
int numerrors = 0;
while (cur != null) {
if ((cur.getStatus(false, true) & ERRORED) != 0) {
numerrors++;
}
cur = cur.next;
}
if (numerrors == 0) {
return null;
}
Object errors[] = new Object[numerrors];
cur = head;
numerrors = 0;
while (cur != null) {
if ((cur.getStatus(false, false) & ERRORED) != 0) {
errors[numerrors++] = cur.getMedia();
}
cur = cur.next;
}
return errors;
}
/**
* Starts loading all images tracked by this media tracker. This
* method waits until all the images being tracked have finished
* loading.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code isErrorAny} or {@code isErrorID} methods to
* check for errors.
* @see java.awt.MediaTracker#waitForID(int)
* @see java.awt.MediaTracker#waitForAll(long)
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#isErrorID
* @exception InterruptedException if any thread has
* interrupted this thread
*/
public void waitForAll() throws InterruptedException {
waitForAll(0);
}
/**
* Starts loading all images tracked by this media tracker. This
* method waits until all the images being tracked have finished
* loading, or until the length of time specified in milliseconds
* by the {@code ms} argument has passed.
* <p>
* If there is an error while loading or scaling an image, then
* that image is considered to have finished loading. Use the
* {@code isErrorAny} or {@code isErrorID} methods to
* check for errors.
* @param ms the number of milliseconds to wait
* for the loading to complete
* @return {@code true} if all images were successfully
* loaded; {@code false} otherwise
* @see java.awt.MediaTracker#waitForID(int)
* @see java.awt.MediaTracker#waitForAll(long)
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#isErrorID
* @exception InterruptedException if any thread has
* interrupted this thread.
*/
public synchronized boolean waitForAll(long ms)
throws InterruptedException
{
long end = System.currentTimeMillis() + ms;
boolean first = true;
while (true) {
int status = statusAll(first, first);
if ((status & LOADING) == 0) {
return (status == COMPLETE);
}
first = false;
long timeout;
if (ms == 0) {
timeout = 0;
} else {
timeout = end - System.currentTimeMillis();
if (timeout <= 0) {
return false;
}
}
wait(timeout);
}
}
/**
* Calculates and returns the bitwise inclusive <b>OR</b> of the
* status of all media that are tracked by this media tracker.
* <p>
* Possible flags defined by the
* {@code MediaTracker} class are {@code LOADING},
* {@code ABORTED}, {@code ERRORED}, and
* {@code COMPLETE}. An image that hasn't started
* loading has zero as its status.
* <p>
* If the value of {@code load} is {@code true}, then
* this method starts loading any images that are not yet being loaded.
*
* @param load if {@code true}, start loading
* any images that are not yet being loaded
* @return the bitwise inclusive <b>OR</b> of the status of
* all of the media being tracked
* @see java.awt.MediaTracker#statusID(int, boolean)
* @see java.awt.MediaTracker#LOADING
* @see java.awt.MediaTracker#ABORTED
* @see java.awt.MediaTracker#ERRORED
* @see java.awt.MediaTracker#COMPLETE
*/
public int statusAll(boolean load) {
return statusAll(load, true);
}
private synchronized int statusAll(boolean load, boolean verify) {
MediaEntry cur = head;
int status = 0;
while (cur != null) {
status = status | cur.getStatus(load, verify);
cur = cur.next;
}
return status;
}
/**
* Checks to see if all images tracked by this media tracker that
* are tagged with the specified identifier have finished loading.
* <p>
* This method does not start loading the images if they are not
* already loading.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code isErrorAny} or {@code isErrorID} methods to
* check for errors.
* @param id the identifier of the images to check
* @return {@code true} if all images have finished loading,
* have been aborted, or have encountered
* an error; {@code false} otherwise
* @see java.awt.MediaTracker#checkID(int, boolean)
* @see java.awt.MediaTracker#checkAll()
* @see java.awt.MediaTracker#isErrorAny()
* @see java.awt.MediaTracker#isErrorID(int)
*/
public boolean checkID(int id) {
return checkID(id, false, true);
}
/**
* Checks to see if all images tracked by this media tracker that
* are tagged with the specified identifier have finished loading.
* <p>
* If the value of the {@code load} flag is {@code true},
* then this method starts loading any images that are not yet
* being loaded.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code isErrorAny} or {@code isErrorID} methods to
* check for errors.
* @param id the identifier of the images to check
* @param load if {@code true}, start loading any
* images that are not yet being loaded
* @return {@code true} if all images have finished loading,
* have been aborted, or have encountered
* an error; {@code false} otherwise
* @see java.awt.MediaTracker#checkID(int, boolean)
* @see java.awt.MediaTracker#checkAll()
* @see java.awt.MediaTracker#isErrorAny()
* @see java.awt.MediaTracker#isErrorID(int)
*/
public boolean checkID(int id, boolean load) {
return checkID(id, load, true);
}
private synchronized boolean checkID(int id, boolean load, boolean verify)
{
MediaEntry cur = head;
boolean done = true;
while (cur != null) {
if (cur.getID() == id
&& (cur.getStatus(load, verify) & DONE) == 0)
{
done = false;
}
cur = cur.next;
}
return done;
}
/**
* Checks the error status of all of the images tracked by this
* media tracker with the specified identifier.
* @param id the identifier of the images to check
* @return {@code true} if any of the images with the
* specified identifier had an error during
* loading; {@code false} otherwise
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#getErrorsID
*/
public synchronized boolean isErrorID(int id) {
MediaEntry cur = head;
while (cur != null) {
if (cur.getID() == id
&& (cur.getStatus(false, true) & ERRORED) != 0)
{
return true;
}
cur = cur.next;
}
return false;
}
/**
* Returns a list of media with the specified ID that
* have encountered an error.
* @param id the identifier of the images to check
* @return an array of media objects tracked by this media
* tracker with the specified identifier
* that have encountered an error, or
* {@code null} if there are none with errors
* @see java.awt.MediaTracker#isErrorID
* @see java.awt.MediaTracker#isErrorAny
* @see java.awt.MediaTracker#getErrorsAny
*/
public synchronized Object[] getErrorsID(int id) {
MediaEntry cur = head;
int numerrors = 0;
while (cur != null) {
if (cur.getID() == id
&& (cur.getStatus(false, true) & ERRORED) != 0)
{
numerrors++;
}
cur = cur.next;
}
if (numerrors == 0) {
return null;
}
Object errors[] = new Object[numerrors];
cur = head;
numerrors = 0;
while (cur != null) {
if (cur.getID() == id
&& (cur.getStatus(false, false) & ERRORED) != 0)
{
errors[numerrors++] = cur.getMedia();
}
cur = cur.next;
}
return errors;
}
/**
* Starts loading all images tracked by this media tracker with the
* specified identifier. This method waits until all the images with
* the specified identifier have finished loading.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code isErrorAny} and {@code isErrorID} methods to
* check for errors.
* @param id the identifier of the images to check
* @see java.awt.MediaTracker#waitForAll
* @see java.awt.MediaTracker#isErrorAny()
* @see java.awt.MediaTracker#isErrorID(int)
* @exception InterruptedException if any thread has
* interrupted this thread.
*/
public void waitForID(int id) throws InterruptedException {
waitForID(id, 0);
}
/**
* Starts loading all images tracked by this media tracker with the
* specified identifier. This method waits until all the images with
* the specified identifier have finished loading, or until the
* length of time specified in milliseconds by the {@code ms}
* argument has passed.
* <p>
* If there is an error while loading or scaling an image, then that
* image is considered to have finished loading. Use the
* {@code statusID}, {@code isErrorID}, and
* {@code isErrorAny} methods to check for errors.
* @param id the identifier of the images to check
* @param ms the length of time, in milliseconds, to wait
* for the loading to complete
* @return {@code true} if the loading completed in time;
* otherwise {@code false}
* @see java.awt.MediaTracker#waitForAll
* @see java.awt.MediaTracker#waitForID(int)
* @see java.awt.MediaTracker#statusID
* @see java.awt.MediaTracker#isErrorAny()
* @see java.awt.MediaTracker#isErrorID(int)
* @exception InterruptedException if any thread has
* interrupted this thread.
*/
public synchronized boolean waitForID(int id, long ms)
throws InterruptedException
{
long end = System.currentTimeMillis() + ms;
boolean first = true;
while (true) {
int status = statusID(id, first, first);
if ((status & LOADING) == 0) {
return (status == COMPLETE);
}
first = false;
long timeout;
if (ms == 0) {
timeout = 0;
} else {
timeout = end - System.currentTimeMillis();
if (timeout <= 0) {
return false;
}
}
wait(timeout);
}
}
/**
* Calculates and returns the bitwise inclusive <b>OR</b> of the
* status of all media with the specified identifier that are
* tracked by this media tracker.
* <p>
* Possible flags defined by the
* {@code MediaTracker} class are {@code LOADING},
* {@code ABORTED}, {@code ERRORED}, and
* {@code COMPLETE}. An image that hasn't started
* loading has zero as its status.
* <p>
* If the value of {@code load} is {@code true}, then
* this method starts loading any images that are not yet being loaded.
* @param id the identifier of the images to check
* @param load if {@code true}, start loading
* any images that are not yet being loaded
* @return the bitwise inclusive <b>OR</b> of the status of
* all of the media with the specified
* identifier that are being tracked
* @see java.awt.MediaTracker#statusAll(boolean)
* @see java.awt.MediaTracker#LOADING
* @see java.awt.MediaTracker#ABORTED
* @see java.awt.MediaTracker#ERRORED
* @see java.awt.MediaTracker#COMPLETE
*/
public int statusID(int id, boolean load) {
return statusID(id, load, true);
}
private synchronized int statusID(int id, boolean load, boolean verify) {
MediaEntry cur = head;
int status = 0;
while (cur != null) {
if (cur.getID() == id) {
status = status | cur.getStatus(load, verify);
}
cur = cur.next;
}
return status;
}
/**
* Removes the specified image from this media tracker.
* All instances of the specified image are removed,
* regardless of scale or ID.
* @param image the image to be removed
* @see java.awt.MediaTracker#removeImage(java.awt.Image, int)
* @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
* @since 1.1
*/
public synchronized void removeImage(Image image) {
removeImageImpl(image);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
MediaEntry next = cur.next;
if (cur.getMedia() == image) {
if (prev == null) {
head = next;
} else {
prev.next = next;
}
cur.cancel();
} else {
prev = cur;
}
cur = next;
}
}
/**
* Removes the specified image from the specified tracking
* ID of this media tracker.
* All instances of {@code Image} being tracked
* under the specified ID are removed regardless of scale.
* @param image the image to be removed
* @param id the tracking ID from which to remove the image
* @see java.awt.MediaTracker#removeImage(java.awt.Image)
* @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
* @since 1.1
*/
public synchronized void removeImage(Image image, int id) {
removeImageImpl(image, id);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage, id);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image, int id) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
MediaEntry next = cur.next;
if (cur.getID() == id && cur.getMedia() == image) {
if (prev == null) {
head = next;
} else {
prev.next = next;
}
cur.cancel();
} else {
prev = cur;
}
cur = next;
}
}
/**
* Removes the specified image with the specified
* width, height, and ID from this media tracker.
* Only the specified instance (with any duplicates) is removed.
* @param image the image to be removed
* @param id the tracking ID from which to remove the image
* @param width the width to remove (-1 for unscaled)
* @param height the height to remove (-1 for unscaled)
* @see java.awt.MediaTracker#removeImage(java.awt.Image)
* @see java.awt.MediaTracker#removeImage(java.awt.Image, int)
* @since 1.1
*/
public synchronized void removeImage(Image image, int id,
int width, int height) {
removeImageImpl(image, id, width, height);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage, id,
width == -1 ? -1 : 2 * width,
height == -1 ? -1 : 2 * height);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image, int id, int width, int height) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
MediaEntry next = cur.next;
if (cur.getID() == id && cur instanceof ImageMediaEntry
&& ((ImageMediaEntry) cur).matches(image, width, height))
{
if (prev == null) {
head = next;
} else {
prev.next = next;
}
cur.cancel();
} else {
prev = cur;
}
cur = next;
}
}
synchronized void setDone() {
notifyAll();
}
private static Image getResolutionVariant(Image image) {
if (image instanceof MultiResolutionToolkitImage) {
return ((MultiResolutionToolkitImage) image).getResolutionVariant();
}
return null;
}
}
abstract class MediaEntry {
MediaTracker tracker;
int ID;
MediaEntry next;
int status;
boolean cancelled;
MediaEntry(MediaTracker mt, int id) {
tracker = mt;
ID = id;
}
abstract Object getMedia();
static MediaEntry insert(MediaEntry head, MediaEntry me) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
if (cur.ID > me.ID) {
break;
}
prev = cur;
cur = cur.next;
}
me.next = cur;
if (prev == null) {
head = me;
} else {
prev.next = me;
}
return head;
}
int getID() {
return ID;
}
abstract void startLoad();
void cancel() {
cancelled = true;
}
static final int LOADING = MediaTracker.LOADING;
static final int ABORTED = MediaTracker.ABORTED;
static final int ERRORED = MediaTracker.ERRORED;
static final int COMPLETE = MediaTracker.COMPLETE;
static final int LOADSTARTED = (LOADING | ERRORED | COMPLETE);
static final int DONE = (ABORTED | ERRORED | COMPLETE);
synchronized int getStatus(boolean doLoad, boolean doVerify) {
if (doLoad && ((status & LOADSTARTED) == 0)) {
status = (status & ~ABORTED) | LOADING;
startLoad();
}
return status;
}
void setStatus(int flag) {
synchronized (this) {
status = flag;
}
tracker.setDone();
}
}
class ImageMediaEntry extends MediaEntry implements ImageObserver,
java.io.Serializable {
Image image;
int width;
int height;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 4739377000350280650L;
ImageMediaEntry(MediaTracker mt, Image img, int c, int w, int h) {
super(mt, c);
image = img;
width = w;
height = h;
}
boolean matches(Image img, int w, int h) {
return (image == img && width == w && height == h);
}
Object getMedia() {
return image;
}
synchronized int getStatus(boolean doLoad, boolean doVerify) {
if (doVerify) {
int flags = tracker.target.checkImage(image, width, height, null);
int s = parseflags(flags);
if (s == 0) {
if ((status & (ERRORED | COMPLETE)) != 0) {
setStatus(ABORTED);
}
} else if (s != status) {
setStatus(s);
}
}
return super.getStatus(doLoad, doVerify);
}
void startLoad() {
if (tracker.target.prepareImage(image, width, height, this)) {
setStatus(COMPLETE);
}
}
int parseflags(int infoflags) {
if ((infoflags & ERROR) != 0) {
return ERRORED;
} else if ((infoflags & ABORT) != 0) {
return ABORTED;
} else if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
return COMPLETE;
}
return 0;
}
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int w, int h) {
if (cancelled) {
return false;
}
int s = parseflags(infoflags);
if (s != 0 && s != status) {
setStatus(s);
}
return ((status & LOADING) != 0);
}
}

View file

@ -0,0 +1,639 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Vector;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
/**
* A {@code Menu} object is a pull-down menu component
* that is deployed from a menu bar.
* <p>
* A menu can optionally be a <i>tear-off</i> menu. A tear-off menu
* can be opened and dragged away from its parent menu bar or menu.
* It remains on the screen after the mouse button has been released.
* The mechanism for tearing off a menu is platform dependent, since
* the look and feel of the tear-off menu is determined by its peer.
* On platforms that do not support tear-off menus, the tear-off
* property is ignored.
* <p>
* Each item in a menu must belong to the {@code MenuItem}
* class. It can be an instance of {@code MenuItem}, a submenu
* (an instance of {@code Menu}), or a check box (an instance of
* {@code CheckboxMenuItem}).
*
* @author Sami Shaio
* @see java.awt.MenuItem
* @see java.awt.CheckboxMenuItem
* @since 1.0
*/
public class Menu extends MenuItem implements MenuContainer, Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setMenuAccessor(
new AWTAccessor.MenuAccessor() {
public Vector<MenuItem> getItems(Menu menu) {
return menu.items;
}
});
}
/**
* A vector of the items that will be part of the Menu.
*
* @serial
* @see #countItems()
*/
private final Vector<MenuItem> items = new Vector<>();
/**
* This field indicates whether the menu has the
* tear of property or not. It will be set to
* {@code true} if the menu has the tear off
* property and it will be set to {@code false}
* if it does not.
* A torn off menu can be deleted by a user when
* it is no longer needed.
*
* @serial
* @see #isTearOff()
*/
private final boolean tearOff;
/**
* This field will be set to {@code true}
* if the Menu in question is actually a help
* menu. Otherwise it will be set to
* {@code false}.
*
* @serial
*/
volatile boolean isHelpMenu;
private static final String base = "menu";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -8809584163345499784L;
/**
* Constructs a new menu with an empty label. This menu is not
* a tear-off menu.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public Menu() throws HeadlessException {
this("", false);
}
/**
* Constructs a new menu with the specified label. This menu is not
* a tear-off menu.
* @param label the menu's label in the menu bar, or in
* another menu of which this menu is a submenu.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Menu(String label) throws HeadlessException {
this(label, false);
}
/**
* Constructs a new menu with the specified label,
* indicating whether the menu can be torn off.
* <p>
* Tear-off functionality may not be supported by all
* implementations of AWT. If a particular implementation doesn't
* support tear-off menus, this value is silently ignored.
* @param label the menu's label in the menu bar, or in
* another menu of which this menu is a submenu.
* @param tearOff if {@code true}, the menu
* is a tear-off menu.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public Menu(String label, boolean tearOff) throws HeadlessException {
super(label);
this.tearOff = tearOff;
}
/**
* Construct a name for this MenuComponent. Called by getName() when
* the name is null.
*/
String constructComponentName() {
synchronized (Menu.class) {
return base + nameCounter++;
}
}
/**
* Creates the menu's peer. The peer allows us to modify the
* appearance of the menu without changing its functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createMenu(this);
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
MenuItem mi = getItem(i);
mi.parent = this;
mi.addNotify();
}
}
}
/**
* Removes the menu's peer. The peer allows us to modify the appearance
* of the menu without changing its functionality.
*/
public void removeNotify() {
synchronized (getTreeLock()) {
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
getItem(i).removeNotify();
}
super.removeNotify();
}
}
/**
* Indicates whether this menu is a tear-off menu.
* <p>
* Tear-off functionality may not be supported by all
* implementations of AWT. If a particular implementation doesn't
* support tear-off menus, this value is silently ignored.
* @return {@code true} if this is a tear-off menu;
* {@code false} otherwise.
*/
public boolean isTearOff() {
return tearOff;
}
/**
* Get the number of items in this menu.
* @return the number of items in this menu
* @since 1.1
*/
public int getItemCount() {
return countItems();
}
/**
* Returns the number of items in this menu.
*
* @return the number of items in this menu
* @deprecated As of JDK version 1.1,
* replaced by {@code getItemCount()}.
*/
@Deprecated
public int countItems() {
return countItemsImpl();
}
/*
* This is called by the native code, so client code can't
* be called on the toolkit thread.
*/
final int countItemsImpl() {
return items.size();
}
/**
* Gets the item located at the specified index of this menu.
* @param index the position of the item to be returned.
* @return the item located at the specified index.
*/
public MenuItem getItem(int index) {
return getItemImpl(index);
}
/*
* This is called by the native code, so client code can't
* be called on the toolkit thread.
*/
final MenuItem getItemImpl(int index) {
return items.elementAt(index);
}
/**
* Adds the specified menu item to this menu. If the
* menu item has been part of another menu, removes it
* from that menu.
*
* @param mi the menu item to be added
* @return the menu item added
* @see java.awt.Menu#insert(java.lang.String, int)
* @see java.awt.Menu#insert(java.awt.MenuItem, int)
*/
public MenuItem add(MenuItem mi) {
synchronized (getTreeLock()) {
if (mi.parent != null) {
mi.parent.remove(mi);
}
items.addElement(mi);
mi.parent = this;
MenuPeer peer = (MenuPeer)this.peer;
if (peer != null) {
mi.addNotify();
peer.addItem(mi);
}
return mi;
}
}
/**
* Adds an item with the specified label to this menu.
*
* @param label the text on the item
* @see java.awt.Menu#insert(java.lang.String, int)
* @see java.awt.Menu#insert(java.awt.MenuItem, int)
*/
public void add(String label) {
add(new MenuItem(label));
}
/**
* Inserts a menu item into this menu
* at the specified position.
*
* @param menuitem the menu item to be inserted.
* @param index the position at which the menu
* item should be inserted.
* @see java.awt.Menu#add(java.lang.String)
* @see java.awt.Menu#add(java.awt.MenuItem)
* @exception IllegalArgumentException if the value of
* {@code index} is less than zero
* @since 1.1
*/
public void insert(MenuItem menuitem, int index) {
synchronized (getTreeLock()) {
if (index < 0) {
throw new IllegalArgumentException("index less than zero.");
}
int nitems = getItemCount();
Vector<MenuItem> tempItems = new Vector<>();
/* Remove the item at index, nitems-index times
storing them in a temporary vector in the
order they appear on the menu.
*/
for (int i = index ; i < nitems; i++) {
tempItems.addElement(getItem(index));
remove(index);
}
add(menuitem);
/* Add the removed items back to the menu, they are
already in the correct order in the temp vector.
*/
for (int i = 0; i < tempItems.size() ; i++) {
add(tempItems.elementAt(i));
}
}
}
/**
* Inserts a menu item with the specified label into this menu
* at the specified position. This is a convenience method for
* {@code insert(menuItem, index)}.
*
* @param label the text on the item
* @param index the position at which the menu item
* should be inserted
* @see java.awt.Menu#add(java.lang.String)
* @see java.awt.Menu#add(java.awt.MenuItem)
* @exception IllegalArgumentException if the value of
* {@code index} is less than zero
* @since 1.1
*/
public void insert(String label, int index) {
insert(new MenuItem(label), index);
}
/**
* Adds a separator line, or a hypen, to the menu at the current position.
* @see java.awt.Menu#insertSeparator(int)
*/
public void addSeparator() {
add("-");
}
/**
* Inserts a separator at the specified position.
* @param index the position at which the
* menu separator should be inserted.
* @exception IllegalArgumentException if the value of
* {@code index} is less than 0.
* @see java.awt.Menu#addSeparator
* @since 1.1
*/
public void insertSeparator(int index) {
synchronized (getTreeLock()) {
if (index < 0) {
throw new IllegalArgumentException("index less than zero.");
}
int nitems = getItemCount();
Vector<MenuItem> tempItems = new Vector<>();
/* Remove the item at index, nitems-index times
storing them in a temporary vector in the
order they appear on the menu.
*/
for (int i = index ; i < nitems; i++) {
tempItems.addElement(getItem(index));
remove(index);
}
addSeparator();
/* Add the removed items back to the menu, they are
already in the correct order in the temp vector.
*/
for (int i = 0; i < tempItems.size() ; i++) {
add(tempItems.elementAt(i));
}
}
}
/**
* Removes the menu item at the specified index from this menu.
* @param index the position of the item to be removed.
*/
public void remove(int index) {
synchronized (getTreeLock()) {
MenuItem mi = getItem(index);
items.removeElementAt(index);
MenuPeer peer = (MenuPeer)this.peer;
if (peer != null) {
peer.delItem(index);
mi.removeNotify();
}
mi.parent = null;
}
}
/**
* Removes the specified menu item from this menu.
* @param item the item to be removed from the menu.
* If {@code item} is {@code null}
* or is not in this menu, this method does
* nothing.
*/
public void remove(MenuComponent item) {
synchronized (getTreeLock()) {
int index = items.indexOf(item);
if (index >= 0) {
remove(index);
}
}
}
/**
* Removes all items from this menu.
* @since 1.1
*/
public void removeAll() {
synchronized (getTreeLock()) {
int nitems = getItemCount();
for (int i = nitems-1 ; i >= 0 ; i--) {
remove(i);
}
}
}
/*
* Post an ActionEvent to the target of the MenuPeer
* associated with the specified keyboard event (on
* keydown). Returns true if there is an associated
* keyboard event.
*/
boolean handleShortcut(KeyEvent e) {
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
MenuItem mi = getItem(i);
if (mi.handleShortcut(e)) {
return true;
}
}
return false;
}
MenuItem getShortcutMenuItem(MenuShortcut s) {
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
MenuItem mi = getItem(i).getShortcutMenuItem(s);
if (mi != null) {
return mi;
}
}
return null;
}
synchronized Enumeration<MenuShortcut> shortcuts() {
Vector<MenuShortcut> shortcuts = new Vector<>();
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
MenuItem mi = getItem(i);
if (mi instanceof Menu) {
Enumeration<MenuShortcut> e = ((Menu)mi).shortcuts();
while (e.hasMoreElements()) {
shortcuts.addElement(e.nextElement());
}
} else {
MenuShortcut ms = mi.getShortcut();
if (ms != null) {
shortcuts.addElement(ms);
}
}
}
return shortcuts.elements();
}
void deleteShortcut(MenuShortcut s) {
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
getItem(i).deleteShortcut(s);
}
}
/* Serialization support. A MenuContainer is responsible for
* restoring the parent fields of its children.
*/
/**
* The menu serialized Data Version.
*
* @serial
*/
private int menuSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream.
*
* @param s the {@code ObjectOutputStream} to write
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see #readObject(ObjectInputStream)
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException
{
s.defaultWriteObject();
}
/**
* Reads the {@code ObjectInputStream}.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException, HeadlessException
{
// HeadlessException will be thrown from MenuComponent's readObject
s.defaultReadObject();
for(int i = 0; i < items.size(); i++) {
MenuItem item = items.elementAt(i);
item.parent = this;
}
}
/**
* Returns a string representing the state of this {@code Menu}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this menu
*/
public String paramString() {
String str = ",tearOff=" + tearOff+",isHelpMenu=" + isHelpMenu;
return super.paramString() + str;
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this Menu.
* For menus, the AccessibleContext takes the form of an
* AccessibleAWTMenu.
* A new AccessibleAWTMenu instance is created if necessary.
*
* @return an AccessibleAWTMenu that serves as the
* AccessibleContext of this Menu
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTMenu();
}
return accessibleContext;
}
/**
* Defined in MenuComponent. Overridden here.
*/
int getAccessibleChildIndex(MenuComponent child) {
return items.indexOf(child);
}
/**
* Inner class of Menu used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by menu component developers.
* <p>
* This class implements accessibility support for the
* {@code Menu} class. It provides an implementation of the
* Java Accessibility API appropriate to menu user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = 5228160894980069094L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.MENU;
}
} // class AccessibleAWTMenu
}

View file

@ -0,0 +1,529 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuBarPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Vector;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
/**
* The {@code MenuBar} class encapsulates the platform's
* concept of a menu bar bound to a frame. In order to associate
* the menu bar with a {@code Frame} object, call the
* frame's {@code setMenuBar} method.
* <p>
* <a id="mbexample"></a><!-- target for cross references -->
* This is what a menu bar might look like:
* <p>
* <img src="doc-files/MenuBar-1.gif"
* alt="Diagram of MenuBar containing 2 menus: Examples and Options.
* Examples menu is expanded showing items: Basic, Simple, Check, and More Examples."
* style="float:center; margin: 7px 10px;">
* <p>
* A menu bar handles keyboard shortcuts for menu items, passing them
* along to its child menus.
* (Keyboard shortcuts, which are optional, provide the user with
* an alternative to the mouse for invoking a menu item and the
* action that is associated with it.)
* Each menu item can maintain an instance of {@code MenuShortcut}.
* The {@code MenuBar} class defines several methods,
* {@link MenuBar#shortcuts} and
* {@link MenuBar#getShortcutMenuItem}
* that retrieve information about the shortcuts a given
* menu bar is managing.
*
* @author Sami Shaio
* @see java.awt.Frame
* @see java.awt.Frame#setMenuBar(java.awt.MenuBar)
* @see java.awt.Menu
* @see java.awt.MenuItem
* @see java.awt.MenuShortcut
* @since 1.0
*/
public class MenuBar extends MenuComponent implements MenuContainer, Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setMenuBarAccessor(
new AWTAccessor.MenuBarAccessor() {
public Menu getHelpMenu(MenuBar menuBar) {
return menuBar.helpMenu;
}
public Vector<Menu> getMenus(MenuBar menuBar) {
return menuBar.menus;
}
});
}
/**
* This field represents a vector of the
* actual menus that will be part of the MenuBar.
*
* @serial
* @see #countMenus()
*/
private final Vector<Menu> menus = new Vector<>();
/**
* This menu is a special menu dedicated to
* help. The one thing to note about this menu
* is that on some platforms it appears at the
* right edge of the menubar.
*
* @serial
* @see #getHelpMenu()
* @see #setHelpMenu(Menu)
*/
private volatile Menu helpMenu;
private static final String base = "menubar";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -4930327919388951260L;
/**
* Creates a new menu bar.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public MenuBar() throws HeadlessException {
}
/**
* Construct a name for this MenuComponent. Called by getName() when
* the name is null.
*/
String constructComponentName() {
synchronized (MenuBar.class) {
return base + nameCounter++;
}
}
/**
* Creates the menu bar's peer. The peer allows us to change the
* appearance of the menu bar without changing any of the menu bar's
* functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createMenuBar(this);
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
getMenu(i).addNotify();
}
}
}
/**
* Removes the menu bar's peer. The peer allows us to change the
* appearance of the menu bar without changing any of the menu bar's
* functionality.
*/
public void removeNotify() {
synchronized (getTreeLock()) {
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
getMenu(i).removeNotify();
}
super.removeNotify();
}
}
/**
* Gets the help menu on the menu bar.
* @return the help menu on this menu bar.
*/
public Menu getHelpMenu() {
return helpMenu;
}
/**
* Sets the specified menu to be this menu bar's help menu.
* If this menu bar has an existing help menu, the old help menu is
* removed from the menu bar, and replaced with the specified menu.
* @param m the menu to be set as the help menu
*/
public void setHelpMenu(final Menu m) {
synchronized (getTreeLock()) {
if (helpMenu == m) {
return;
}
if (helpMenu != null) {
remove(helpMenu);
}
helpMenu = m;
if (m != null) {
if (m.parent != this) {
add(m);
}
m.isHelpMenu = true;
m.parent = this;
MenuBarPeer peer = (MenuBarPeer)this.peer;
if (peer != null) {
if (m.peer == null) {
m.addNotify();
}
peer.addHelpMenu(m);
}
}
}
}
/**
* Adds the specified menu to the menu bar.
* If the menu has been part of another menu bar,
* removes it from that menu bar.
*
* @param m the menu to be added
* @return the menu added
* @see java.awt.MenuBar#remove(int)
* @see java.awt.MenuBar#remove(java.awt.MenuComponent)
*/
public Menu add(Menu m) {
synchronized (getTreeLock()) {
if (m.parent != null) {
m.parent.remove(m);
}
m.parent = this;
MenuBarPeer peer = (MenuBarPeer)this.peer;
if (peer != null) {
if (m.peer == null) {
m.addNotify();
}
menus.addElement(m);
peer.addMenu(m);
} else {
menus.addElement(m);
}
return m;
}
}
/**
* Removes the menu located at the specified
* index from this menu bar.
* @param index the position of the menu to be removed.
* @see java.awt.MenuBar#add(java.awt.Menu)
*/
public void remove(final int index) {
synchronized (getTreeLock()) {
Menu m = getMenu(index);
menus.removeElementAt(index);
MenuBarPeer peer = (MenuBarPeer)this.peer;
if (peer != null) {
peer.delMenu(index);
m.removeNotify();
}
m.parent = null;
if (helpMenu == m) {
helpMenu = null;
m.isHelpMenu = false;
}
}
}
/**
* Removes the specified menu component from this menu bar.
* @param m the menu component to be removed.
* @see java.awt.MenuBar#add(java.awt.Menu)
*/
public void remove(MenuComponent m) {
synchronized (getTreeLock()) {
int index = menus.indexOf(m);
if (index >= 0) {
remove(index);
}
}
}
/**
* Gets the number of menus on the menu bar.
* @return the number of menus on the menu bar.
* @since 1.1
*/
public int getMenuCount() {
return countMenus();
}
/**
* Gets the number of menus on the menu bar.
*
* @return the number of menus on the menu bar.
* @deprecated As of JDK version 1.1,
* replaced by {@code getMenuCount()}.
*/
@Deprecated
public int countMenus() {
return getMenuCountImpl();
}
/*
* This is called by the native code, so client code can't
* be called on the toolkit thread.
*/
final int getMenuCountImpl() {
return menus.size();
}
/**
* Gets the specified menu.
* @param i the index position of the menu to be returned.
* @return the menu at the specified index of this menu bar.
*/
public Menu getMenu(int i) {
return getMenuImpl(i);
}
/*
* This is called by the native code, so client code can't
* be called on the toolkit thread.
*/
final Menu getMenuImpl(int i) {
return menus.elementAt(i);
}
/**
* Gets an enumeration of all menu shortcuts this menu bar
* is managing.
* @return an enumeration of menu shortcuts that this
* menu bar is managing.
* @see java.awt.MenuShortcut
* @since 1.1
*/
public synchronized Enumeration<MenuShortcut> shortcuts() {
Vector<MenuShortcut> shortcuts = new Vector<>();
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
Enumeration<MenuShortcut> e = getMenu(i).shortcuts();
while (e.hasMoreElements()) {
shortcuts.addElement(e.nextElement());
}
}
return shortcuts.elements();
}
/**
* Gets the instance of {@code MenuItem} associated
* with the specified {@code MenuShortcut} object,
* or {@code null} if none of the menu items being managed
* by this menu bar is associated with the specified menu
* shortcut.
* @param s the specified menu shortcut.
* @return the menu item for the specified shortcut.
* @see java.awt.MenuItem
* @see java.awt.MenuShortcut
* @since 1.1
*/
public MenuItem getShortcutMenuItem(MenuShortcut s) {
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
MenuItem mi = getMenu(i).getShortcutMenuItem(s);
if (mi != null) {
return mi;
}
}
return null; // MenuShortcut wasn't found
}
/*
* Post an ACTION_EVENT to the target of the MenuPeer
* associated with the specified keyboard event (on
* keydown). Returns true if there is an associated
* keyboard event.
*/
@SuppressWarnings("deprecation")
boolean handleShortcut(KeyEvent e) {
// Is it a key event?
int id = e.getID();
if (id != KeyEvent.KEY_PRESSED && id != KeyEvent.KEY_RELEASED) {
return false;
}
// Is the accelerator modifier key pressed?
int accelKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
if ((e.getModifiers() & accelKey) == 0) {
return false;
}
// Pass MenuShortcut on to child menus.
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
Menu m = getMenu(i);
if (m.handleShortcut(e)) {
return true;
}
}
return false;
}
/**
* Deletes the specified menu shortcut.
* @param s the menu shortcut to delete.
* @since 1.1
*/
public void deleteShortcut(MenuShortcut s) {
int nmenus = getMenuCount();
for (int i = 0 ; i < nmenus ; i++) {
getMenu(i).deleteShortcut(s);
}
}
/* Serialization support. Restore the (transient) parent
* fields of Menubar menus here.
*/
/**
* The MenuBar's serialized data version.
*
* @serial
*/
private int menuBarSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream.
*
* @param s the {@code ObjectOutputStream} to write
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see #readObject(java.io.ObjectInputStream)
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.lang.ClassNotFoundException,
java.io.IOException
{
s.defaultWriteObject();
}
/**
* Reads the {@code ObjectInputStream}.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @see java.awt.GraphicsEnvironment#isHeadless
* @see #writeObject(java.io.ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException
{
// HeadlessException will be thrown from MenuComponent's readObject
s.defaultReadObject();
for (int i = 0; i < menus.size(); i++) {
Menu m = menus.elementAt(i);
m.parent = this;
}
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this MenuBar.
* For menu bars, the AccessibleContext takes the form of an
* AccessibleAWTMenuBar.
* A new AccessibleAWTMenuBar instance is created if necessary.
*
* @return an AccessibleAWTMenuBar that serves as the
* AccessibleContext of this MenuBar
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTMenuBar();
}
return accessibleContext;
}
/**
* Defined in MenuComponent. Overridden here.
*/
int getAccessibleChildIndex(MenuComponent child) {
return menus.indexOf(child);
}
/**
* Inner class of MenuBar used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by menu component developers.
* <p>
* This class implements accessibility support for the
* {@code MenuBar} class. It provides an implementation of the
* Java Accessibility API appropriate to menu bar user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTMenuBar extends AccessibleAWTMenuComponent
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -8577604491830083815L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @since 1.4
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.MENU_BAR;
}
} // class AccessibleAWTMenuBar
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* The super class of all menu related containers.
*
* @author Arthur van Hoff
*/
public interface MenuContainer {
/**
* Returns the font in use by this container.
*
* @return the menu font
*/
Font getFont();
/**
* Removes the specified menu component from the menu.
*
* @param comp the menu component to remove
*/
void remove(MenuComponent comp);
/**
* Posts an event to the listeners.
*
* @param evt the event to dispatch
* @return the results of posting the event
* @deprecated As of JDK version 1.1
* replaced by dispatchEvent(AWTEvent).
*/
@Deprecated
boolean postEvent(Event evt);
}

View file

@ -0,0 +1,963 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EventListener;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleValue;
import sun.awt.AWTAccessor;
/**
* All items in a menu must belong to the class
* {@code MenuItem}, or one of its subclasses.
* <p>
* The default {@code MenuItem} object embodies
* a simple labeled menu item.
* <p>
* This picture of a menu bar shows five menu items:
* <IMG SRC="doc-files/MenuBar-1.gif" alt="The following text describes this graphic."
* style="float:center; margin: 7px 10px;">
* <br style="clear:left;">
* The first two items are simple menu items, labeled
* {@code "Basic"} and {@code "Simple"}.
* Following these two items is a separator, which is itself
* a menu item, created with the label {@code "-"}.
* Next is an instance of {@code CheckboxMenuItem}
* labeled {@code "Check"}. The final menu item is a
* submenu labeled <code>"More&nbsp;Examples"</code>,
* and this submenu is an instance of {@code Menu}.
* <p>
* When a menu item is selected, AWT sends an action event to
* the menu item. Since the event is an
* instance of {@code ActionEvent}, the {@code processEvent}
* method examines the event and passes it along to
* {@code processActionEvent}. The latter method redirects the
* event to any {@code ActionListener} objects that have
* registered an interest in action events generated by this
* menu item.
* <P>
* Note that the subclass {@code Menu} overrides this behavior and
* does not send any event to the frame until one of its subitems is
* selected.
*
* @author Sami Shaio
*/
public class MenuItem extends MenuComponent implements Accessible {
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setMenuItemAccessor(
new AWTAccessor.MenuItemAccessor() {
public boolean isEnabled(MenuItem item) {
return item.enabled;
}
public String getLabel(MenuItem item) {
return item.label;
}
public MenuShortcut getShortcut(MenuItem item) {
return item.shortcut;
}
public String getActionCommandImpl(MenuItem item) {
return item.getActionCommandImpl();
}
public boolean isItemEnabled(MenuItem item) {
return item.isItemEnabled();
}
});
}
/**
* A value to indicate whether a menu item is enabled
* or not. If it is enabled, {@code enabled} will
* be set to true. Else {@code enabled} will
* be set to false.
*
* @serial
* @see #isEnabled()
* @see #setEnabled(boolean)
*/
private volatile boolean enabled = true;
/**
* {@code label} is the label of a menu item.
* It can be any string.
*
* @serial
* @see #getLabel()
* @see #setLabel(String)
*/
volatile String label;
/**
* This field indicates the command that has been issued
* by a particular menu item.
* By default the {@code actionCommand}
* is the label of the menu item, unless it has been
* set using setActionCommand.
*
* @serial
* @see #setActionCommand(String)
* @see #getActionCommand()
*/
private volatile String actionCommand;
/**
* The eventMask is ONLY set by subclasses via enableEvents.
* The mask should NOT be set when listeners are registered
* so that we can distinguish the difference between when
* listeners request events and subclasses request them.
*
* @serial
*/
volatile long eventMask;
private transient volatile ActionListener actionListener;
/**
* A sequence of key stokes that ia associated with
* a menu item.
* Note :in 1.1.2 you must use setActionCommand()
* on a menu item in order for its shortcut to
* work.
*
* @serial
* @see #getShortcut()
* @see #setShortcut(MenuShortcut)
* @see #deleteShortcut()
*/
private volatile MenuShortcut shortcut;
private static final String base = "menuitem";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -21757335363267194L;
/**
* Constructs a new MenuItem with an empty label and no keyboard
* shortcut.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public MenuItem() throws HeadlessException {
this("", null);
}
/**
* Constructs a new MenuItem with the specified label
* and no keyboard shortcut. Note that use of "-" in
* a label is reserved to indicate a separator between
* menu items. By default, all menu items except for
* separators are enabled.
* @param label the label for this menu item.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.0
*/
public MenuItem(String label) throws HeadlessException {
this(label, null);
}
/**
* Create a menu item with an associated keyboard shortcut.
* Note that use of "-" in a label is reserved to indicate
* a separator between menu items. By default, all menu
* items except for separators are enabled.
* @param label the label for this menu item.
* @param s the instance of {@code MenuShortcut}
* associated with this menu item.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @since 1.1
*/
public MenuItem(String label, MenuShortcut s) throws HeadlessException {
this.label = label;
this.shortcut = s;
}
/**
* Construct a name for this MenuComponent. Called by getName() when
* the name is null.
*/
String constructComponentName() {
synchronized (MenuItem.class) {
return base + nameCounter++;
}
}
/**
* Creates the menu item's peer. The peer allows us to modify the
* appearance of the menu item without changing its functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createMenuItem(this);
}
}
/**
* Gets the label for this menu item.
* @return the label of this menu item, or {@code null}
if this menu item has no label.
* @see java.awt.MenuItem#setLabel
* @since 1.0
*/
public String getLabel() {
return label;
}
/**
* Sets the label for this menu item to the specified label.
* @param label the new label, or {@code null} for no label.
* @see java.awt.MenuItem#getLabel
* @since 1.0
*/
public synchronized void setLabel(String label) {
this.label = label;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
}
/**
* Checks whether this menu item is enabled.
*
* @return {@code true} if the item is enabled;
* otherwise {@code false}
* @see java.awt.MenuItem#setEnabled
* @since 1.0
*/
public boolean isEnabled() {
return enabled;
}
/**
* Sets whether or not this menu item can be chosen.
* @param b if {@code true}, enables this menu item;
* if {@code false}, disables it.
* @see java.awt.MenuItem#isEnabled
* @since 1.1
*/
public synchronized void setEnabled(boolean b) {
enable(b);
}
/**
* @deprecated As of JDK version 1.1,
* replaced by {@code setEnabled(boolean)}.
*/
@Deprecated
public synchronized void enable() {
enabled = true;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setEnabled(true);
}
}
/**
* Sets whether or not this menu item can be chosen.
*
* @param b if {@code true}, enables this menu item;
* otherwise disables
* @deprecated As of JDK version 1.1,
* replaced by {@code setEnabled(boolean)}.
*/
@Deprecated
public void enable(boolean b) {
if (b) {
enable();
} else {
disable();
}
}
/**
* @deprecated As of JDK version 1.1,
* replaced by {@code setEnabled(boolean)}.
*/
@Deprecated
public synchronized void disable() {
enabled = false;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setEnabled(false);
}
}
/**
* Get the {@code MenuShortcut} object associated with this
* menu item,
* @return the menu shortcut associated with this menu item,
* or {@code null} if none has been specified.
* @see java.awt.MenuItem#setShortcut
* @since 1.1
*/
public MenuShortcut getShortcut() {
return shortcut;
}
/**
* Set the {@code MenuShortcut} object associated with this
* menu item. If a menu shortcut is already associated with
* this menu item, it is replaced.
* @param s the menu shortcut to associate
* with this menu item.
* @see java.awt.MenuItem#getShortcut
* @since 1.1
*/
public void setShortcut(MenuShortcut s) {
shortcut = s;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
}
/**
* Delete any {@code MenuShortcut} object associated
* with this menu item.
* @since 1.1
*/
public void deleteShortcut() {
shortcut = null;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
}
/*
* Delete a matching MenuShortcut associated with this MenuItem.
* Used when iterating Menus.
*/
void deleteShortcut(MenuShortcut s) {
if (s.equals(shortcut)) {
shortcut = null;
MenuItemPeer peer = (MenuItemPeer)this.peer;
if (peer != null) {
peer.setLabel(label);
}
}
}
/*
* The main goal of this method is to post an appropriate event
* to the event queue when menu shortcut is pressed. However,
* in subclasses this method may do more than just posting
* an event.
*/
void doMenuEvent(long when, int modifiers) {
Toolkit.getEventQueue().postEvent(
new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
getActionCommand(), when, modifiers));
}
/*
* Returns true if the item and all its ancestors are
* enabled, false otherwise
*/
private final boolean isItemEnabled() {
// Fix For 6185151: Menu shortcuts of all menuitems within a menu
// should be disabled when the menu itself is disabled
if (!isEnabled()) {
return false;
}
MenuContainer container = getParent_NoClientCode();
do {
if (!(container instanceof Menu)) {
return true;
}
Menu menu = (Menu)container;
if (!menu.isEnabled()) {
return false;
}
container = menu.getParent_NoClientCode();
} while (container != null);
return true;
}
/*
* Post an ActionEvent to the target (on
* keydown) and the item is enabled.
* Returns true if there is an associated shortcut.
*/
@SuppressWarnings("deprecation")
boolean handleShortcut(KeyEvent e) {
MenuShortcut s = new MenuShortcut(e.getKeyCode(),
(e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
MenuShortcut sE = new MenuShortcut(e.getExtendedKeyCode(),
(e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
// Fix For 6185151: Menu shortcuts of all menuitems within a menu
// should be disabled when the menu itself is disabled
if ((s.equals(shortcut) || sE.equals(shortcut)) && isItemEnabled()) {
// MenuShortcut match -- issue an event on keydown.
if (e.getID() == KeyEvent.KEY_PRESSED) {
doMenuEvent(e.getWhen(), e.getModifiers());
} else {
// silently eat key release.
}
return true;
}
return false;
}
MenuItem getShortcutMenuItem(MenuShortcut s) {
return (s.equals(shortcut)) ? this : null;
}
/**
* Enables event delivery to this menu item for events
* to be defined by the specified event mask parameter
* <p>
* Since event types are automatically enabled when a listener for
* that type is added to the menu item, this method only needs
* to be invoked by subclasses of {@code MenuItem} which desire to
* have the specified event types delivered to {@code processEvent}
* regardless of whether a listener is registered.
*
* @param eventsToEnable the event mask defining the event types
* @see java.awt.MenuItem#processEvent
* @see java.awt.MenuItem#disableEvents
* @see java.awt.Component#enableEvents
* @since 1.1
*/
protected final void enableEvents(long eventsToEnable) {
eventMask |= eventsToEnable;
newEventsOnly = true;
}
/**
* Disables event delivery to this menu item for events
* defined by the specified event mask parameter.
*
* @param eventsToDisable the event mask defining the event types
* @see java.awt.MenuItem#processEvent
* @see java.awt.MenuItem#enableEvents
* @see java.awt.Component#disableEvents
* @since 1.1
*/
protected final void disableEvents(long eventsToDisable) {
eventMask &= ~eventsToDisable;
}
/**
* Sets the command name of the action event that is fired
* by this menu item.
* <p>
* By default, the action command is set to the label of
* the menu item.
* @param command the action command to be set
* for this menu item.
* @see java.awt.MenuItem#getActionCommand
* @since 1.1
*/
public void setActionCommand(String command) {
actionCommand = command;
}
/**
* Gets the command name of the action event that is fired
* by this menu item.
*
* @return the action command name
* @see java.awt.MenuItem#setActionCommand
* @since 1.1
*/
public String getActionCommand() {
return getActionCommandImpl();
}
// This is final so it can be called on the Toolkit thread.
final String getActionCommandImpl() {
return (actionCommand == null? label : actionCommand);
}
/**
* Adds the specified action listener to receive action events
* from this menu item.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the action listener.
* @see #removeActionListener
* @see #getActionListeners
* @see java.awt.event.ActionEvent
* @see java.awt.event.ActionListener
* @since 1.1
*/
public synchronized void addActionListener(ActionListener l) {
if (l == null) {
return;
}
actionListener = AWTEventMulticaster.add(actionListener, l);
newEventsOnly = true;
}
/**
* Removes the specified action listener so it no longer receives
* action events from this menu item.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the action listener.
* @see #addActionListener
* @see #getActionListeners
* @see java.awt.event.ActionEvent
* @see java.awt.event.ActionListener
* @since 1.1
*/
public synchronized void removeActionListener(ActionListener l) {
if (l == null) {
return;
}
actionListener = AWTEventMulticaster.remove(actionListener, l);
}
/**
* Returns an array of all the action listeners
* registered on this menu item.
*
* @return all of this menu item's {@code ActionListener}s
* or an empty array if no action
* listeners are currently registered
*
* @see #addActionListener
* @see #removeActionListener
* @see java.awt.event.ActionEvent
* @see java.awt.event.ActionListener
* @since 1.4
*/
public synchronized ActionListener[] getActionListeners() {
return getListeners(ActionListener.class);
}
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this {@code MenuItem}.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the {@code listenerType} argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* {@code MenuItem m}
* for its action listeners with the following code:
*
* <pre>ActionListener[] als = (ActionListener[])(m.getListeners(ActionListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param <T> the type of the listeners
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* {@code java.util.EventListener}
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this menu item,
* or an empty array if no such
* listeners have been added
* @exception ClassCastException if {@code listenerType}
* doesn't specify a class or interface that implements
* {@code java.util.EventListener}
*
* @see #getActionListeners
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ActionListener.class) {
l = actionListener;
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
/**
* Processes events on this menu item. If the event is an
* instance of {@code ActionEvent}, it invokes
* {@code processActionEvent}, another method
* defined by {@code MenuItem}.
* <p>
* Currently, menu items only support action events.
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
* @see java.awt.MenuItem#processActionEvent
* @since 1.1
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ActionEvent) {
processActionEvent((ActionEvent)e);
}
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
if (e.id == ActionEvent.ACTION_PERFORMED) {
if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
actionListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
/**
* Processes action events occurring on this menu item,
* by dispatching them to any registered
* {@code ActionListener} objects.
* This method is not called unless action events are
* enabled for this component. Action events are enabled
* when one of the following occurs:
* <ul>
* <li>An {@code ActionListener} object is registered
* via {@code addActionListener}.
* <li>Action events are enabled via {@code enableEvents}.
* </ul>
* <p>Note that if the event parameter is {@code null}
* the behavior is unspecified and may result in an
* exception.
*
* @param e the action event
* @see java.awt.event.ActionEvent
* @see java.awt.event.ActionListener
* @see java.awt.MenuItem#enableEvents
* @since 1.1
*/
protected void processActionEvent(ActionEvent e) {
ActionListener listener = actionListener;
if (listener != null) {
listener.actionPerformed(e);
}
}
/**
* Returns a string representing the state of this {@code MenuItem}.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* {@code null}.
*
* @return the parameter string of this menu item
*/
public String paramString() {
String str = ",label=" + label;
if (shortcut != null) {
str += ",shortcut=" + shortcut;
}
return super.paramString() + str;
}
/* Serialization support.
*/
/**
* Menu item serialized data version.
*
* @serial
*/
private int menuItemSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable {@code ActionListeners}
* as optional data. The non-serializable listeners are
* detected and no attempt is made to serialize them.
*
* @param s the {@code ObjectOutputStream} to write
* @serialData {@code null} terminated sequence of 0
* or more pairs; the pair consists of a {@code String}
* and an {@code Object}; the {@code String}
* indicates the type of object and is one of the following:
* {@code actionListenerK} indicating an
* {@code ActionListener} object
*
* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
AWTEventMulticaster.save(s, actionListenerK, actionListener);
s.writeObject(null);
}
/**
* Reads the {@code ObjectInputStream} and if it
* isn't {@code null} adds a listener to receive
* action events fired by the {@code Menu} Item.
* Unrecognized keys or values will be ignored.
*
* @param s the {@code ObjectInputStream} to read
* @exception HeadlessException if
* {@code GraphicsEnvironment.isHeadless} returns
* {@code true}
* @see #removeActionListener(ActionListener)
* @see #addActionListener(ActionListener)
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException
{
// HeadlessException will be thrown from MenuComponent's readObject
s.defaultReadObject();
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (actionListenerK == key)
addActionListener((ActionListener)(s.readObject()));
else // skip value for unrecognized key
s.readObject();
}
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this MenuItem.
* For menu items, the AccessibleContext takes the form of an
* AccessibleAWTMenuItem.
* A new AccessibleAWTMenuItem instance is created if necessary.
*
* @return an AccessibleAWTMenuItem that serves as the
* AccessibleContext of this MenuItem
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTMenuItem();
}
return accessibleContext;
}
/**
* Inner class of MenuItem used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by menu component developers.
* <p>
* This class implements accessibility support for the
* {@code MenuItem} class. It provides an implementation of the
* Java Accessibility API appropriate to menu item user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTMenuItem extends AccessibleAWTMenuComponent
implements AccessibleAction, AccessibleValue
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -217847831945965825L;
/**
* Get the accessible name of this object.
*
* @return the localized name of the object -- can be null if this
* object does not have a name
*/
public String getAccessibleName() {
if (accessibleName != null) {
return accessibleName;
} else {
if (getLabel() == null) {
return super.getAccessibleName();
} else {
return getLabel();
}
}
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.MENU_ITEM;
}
/**
* Get the AccessibleAction associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleAction interface on behalf of itself.
*
* @return this object
*/
public AccessibleAction getAccessibleAction() {
return this;
}
/**
* Get the AccessibleValue associated with this object. In the
* implementation of the Java Accessibility API for this class,
* return this object, which is responsible for implementing the
* AccessibleValue interface on behalf of itself.
*
* @return this object
*/
public AccessibleValue getAccessibleValue() {
return this;
}
/**
* Returns the number of Actions available in this object. The
* default behavior of a menu item is to have one action.
*
* @return 1, the number of Actions in this object
*/
public int getAccessibleActionCount() {
return 1;
}
/**
* Return a description of the specified action of the object.
*
* @param i zero-based index of the actions
*/
public String getAccessibleActionDescription(int i) {
if (i == 0) {
// [[[PENDING: WDW -- need to provide a localized string]]]
return "click";
} else {
return null;
}
}
/**
* Perform the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; otherwise false.
*/
public boolean doAccessibleAction(int i) {
if (i == 0) {
// Simulate a button click
Toolkit.getEventQueue().postEvent(
new ActionEvent(MenuItem.this,
ActionEvent.ACTION_PERFORMED,
MenuItem.this.getActionCommand(),
EventQueue.getMostRecentEventTime(),
0));
return true;
} else {
return false;
}
}
/**
* Get the value of this object as a Number.
*
* @return An Integer of 0 if this isn't selected or an Integer of 1 if
* this is selected.
* @see javax.swing.AbstractButton#isSelected()
*/
public Number getCurrentAccessibleValue() {
return Integer.valueOf(0);
}
/**
* Set the value of this object as a Number.
*
* @return True if the value was set.
*/
public boolean setCurrentAccessibleValue(Number n) {
return false;
}
/**
* Get the minimum value of this object as a Number.
*
* @return An Integer of 0.
*/
public Number getMinimumAccessibleValue() {
return Integer.valueOf(0);
}
/**
* Get the maximum value of this object as a Number.
*
* @return An Integer of 0.
*/
public Number getMaximumAccessibleValue() {
return Integer.valueOf(0);
}
} // class AccessibleAWTMenuItem
}

View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
/**
* The {@code MenuShortcut} class represents a keyboard accelerator
* for a MenuItem.
* <p>
* Menu shortcuts are created using virtual keycodes, not characters.
* For example, a menu shortcut for Ctrl-a (assuming that Control is
* the accelerator key) would be created with code like the following:
* <p>
* {@code MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false);}
* <p> or alternatively
* <p>
* {@code MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('A'), false);}
* <p>
* Menu shortcuts may also be constructed for a wider set of keycodes
* using the {@code java.awt.event.KeyEvent.getExtendedKeyCodeForChar} call.
* For example, a menu shortcut for "Ctrl+cyrillic ef" is created by
* <p>
* <code>MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('\u0444'), false);</code>
* <p>
* Note that shortcuts created with a keycode or an extended keycode defined as a constant in {@code KeyEvent}
* work regardless of the current keyboard layout. However, a shortcut made of
* an extended keycode not listed in {@code KeyEvent}
* only work if the current keyboard layout produces a corresponding letter.
* <p>
* The accelerator key is platform-dependent and may be obtained
* via {@link Toolkit#getMenuShortcutKeyMask}.
*
* @author Thomas Ball
* @since 1.1
*/
public class MenuShortcut implements java.io.Serializable
{
/**
* The virtual keycode for the menu shortcut.
* This is the keycode with which the menu shortcut will be created.
* Note that it is a virtual keycode, not a character,
* e.g. KeyEvent.VK_A, not 'a'.
* Note: in 1.1.x you must use setActionCommand() on a menu item
* in order for its shortcut to work, otherwise it will fire a null
* action command.
*
* @serial
* @see #getKey()
* @see #usesShiftModifier()
* @see java.awt.event.KeyEvent
* @since 1.1
*/
int key;
/**
* Indicates whether the shift key was pressed.
* If true, the shift key was pressed.
* If false, the shift key was not pressed
*
* @serial
* @see #usesShiftModifier()
* @since 1.1
*/
boolean usesShift;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 143448358473180225L;
/**
* Constructs a new MenuShortcut for the specified virtual keycode.
* @param key the raw keycode for this MenuShortcut, as would be returned
* in the keyCode field of a {@link java.awt.event.KeyEvent KeyEvent} if
* this key were pressed.
* @see java.awt.event.KeyEvent
**/
public MenuShortcut(int key) {
this(key, false);
}
/**
* Constructs a new MenuShortcut for the specified virtual keycode.
* @param key the raw keycode for this MenuShortcut, as would be returned
* in the keyCode field of a {@link java.awt.event.KeyEvent KeyEvent} if
* this key were pressed.
* @param useShiftModifier indicates whether this MenuShortcut is invoked
* with the SHIFT key down.
* @see java.awt.event.KeyEvent
**/
public MenuShortcut(int key, boolean useShiftModifier) {
this.key = key;
this.usesShift = useShiftModifier;
}
/**
* Returns the raw keycode of this MenuShortcut.
* @return the raw keycode of this MenuShortcut.
* @see java.awt.event.KeyEvent
* @since 1.1
*/
public int getKey() {
return key;
}
/**
* Returns whether this MenuShortcut must be invoked using the SHIFT key.
* @return {@code true} if this MenuShortcut must be invoked using the
* SHIFT key, {@code false} otherwise.
* @since 1.1
*/
public boolean usesShiftModifier() {
return usesShift;
}
/**
* Returns whether this MenuShortcut is the same as another:
* equality is defined to mean that both MenuShortcuts use the same key
* and both either use or don't use the SHIFT key.
* @param s the MenuShortcut to compare with this.
* @return {@code true} if this MenuShortcut is the same as another,
* {@code false} otherwise.
* @since 1.1
*/
public boolean equals(MenuShortcut s) {
return (s != null && (s.getKey() == key) &&
(s.usesShiftModifier() == usesShift));
}
/**
* Returns whether this MenuShortcut is the same as another:
* equality is defined to mean that both MenuShortcuts use the same key
* and both either use or don't use the SHIFT key.
* @param obj the Object to compare with this.
* @return {@code true} if this MenuShortcut is the same as another,
* {@code false} otherwise.
* @since 1.2
*/
public boolean equals(Object obj) {
if (obj instanceof MenuShortcut) {
return equals( (MenuShortcut) obj );
}
return false;
}
/**
* Returns the hashcode for this MenuShortcut.
* @return the hashcode for this MenuShortcut.
* @since 1.2
*/
public int hashCode() {
return (usesShift) ? (~key) : key;
}
/**
* Returns an internationalized description of the MenuShortcut.
* @return a string representation of this MenuShortcut.
* @since 1.1
*/
@SuppressWarnings("deprecation")
public String toString() {
int modifiers = 0;
if (!GraphicsEnvironment.isHeadless()) {
modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
}
if (usesShiftModifier()) {
modifiers |= Event.SHIFT_MASK;
}
return KeyEvent.getKeyModifiersText(modifiers) + "+" +
KeyEvent.getKeyText(key);
}
/**
* Returns the parameter string representing the state of this
* MenuShortcut. This string is useful for debugging.
* @return the parameter string of this MenuShortcut.
* @since 1.1
*/
protected String paramString() {
String str = "key=" + key;
if (usesShiftModifier()) {
str += ",usesShiftModifier";
}
return str;
}
}

View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.*;
import sun.awt.AppContext;
abstract class ModalEventFilter implements EventFilter {
protected Dialog modalDialog;
protected boolean disabled;
protected ModalEventFilter(Dialog modalDialog) {
this.modalDialog = modalDialog;
disabled = false;
}
Dialog getModalDialog() {
return modalDialog;
}
public FilterAction acceptEvent(AWTEvent event) {
if (disabled || !modalDialog.isVisible()) {
return FilterAction.ACCEPT;
}
int eventID = event.getID();
if ((eventID >= MouseEvent.MOUSE_FIRST &&
eventID <= MouseEvent.MOUSE_LAST) ||
(eventID >= ActionEvent.ACTION_FIRST &&
eventID <= ActionEvent.ACTION_LAST) ||
eventID == WindowEvent.WINDOW_CLOSING)
{
Object o = event.getSource();
if (o instanceof sun.awt.ModalExclude) {
// Exclude this object from modality and
// continue to pump it's events.
} else if (o instanceof Component) {
Component c = (Component)o;
while ((c != null) && !(c instanceof Window)) {
c = c.getParent_NoClientCode();
}
if (c != null) {
return acceptWindow((Window)c);
}
}
}
return FilterAction.ACCEPT;
}
protected abstract FilterAction acceptWindow(Window w);
// When a modal dialog is hidden its modal filter may not be deleted from
// EventDispatchThread event filters immediately, so we need to mark the filter
// as disabled to prevent it from working. Simple checking for visibility of
// the modalDialog is not enough, as it can be hidden and then shown again
// with a new event pump and a new filter
void disable() {
disabled = true;
}
int compareTo(ModalEventFilter another) {
Dialog anotherDialog = another.getModalDialog();
// check if modalDialog is from anotherDialog's hierarchy
// or vice versa
Component c = modalDialog;
while (c != null) {
if (c == anotherDialog) {
return 1;
}
c = c.getParent_NoClientCode();
}
c = anotherDialog;
while (c != null) {
if (c == modalDialog) {
return -1;
}
c = c.getParent_NoClientCode();
}
// check if one dialog blocks (directly or indirectly) another
Dialog blocker = modalDialog.getModalBlocker();
while (blocker != null) {
if (blocker == anotherDialog) {
return -1;
}
blocker = blocker.getModalBlocker();
}
blocker = anotherDialog.getModalBlocker();
while (blocker != null) {
if (blocker == modalDialog) {
return 1;
}
blocker = blocker.getModalBlocker();
}
// compare modality types
return modalDialog.getModalityType().compareTo(anotherDialog.getModalityType());
}
static ModalEventFilter createFilterForDialog(Dialog modalDialog) {
switch (modalDialog.getModalityType()) {
case DOCUMENT_MODAL: return new DocumentModalEventFilter(modalDialog);
case APPLICATION_MODAL: return new ApplicationModalEventFilter(modalDialog);
case TOOLKIT_MODAL: return new ToolkitModalEventFilter(modalDialog);
}
return null;
}
private static class ToolkitModalEventFilter extends ModalEventFilter {
private AppContext appContext;
ToolkitModalEventFilter(Dialog modalDialog) {
super(modalDialog);
appContext = modalDialog.appContext;
}
protected FilterAction acceptWindow(Window w) {
if (w.isModalExcluded(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE)) {
return FilterAction.ACCEPT;
}
if (w.appContext != appContext) {
return FilterAction.REJECT;
}
while (w != null) {
if (w == modalDialog) {
return FilterAction.ACCEPT_IMMEDIATELY;
}
w = w.getOwner();
}
return FilterAction.REJECT;
}
}
private static class ApplicationModalEventFilter extends ModalEventFilter {
private AppContext appContext;
ApplicationModalEventFilter(Dialog modalDialog) {
super(modalDialog);
appContext = modalDialog.appContext;
}
protected FilterAction acceptWindow(Window w) {
if (w.isModalExcluded(Dialog.ModalExclusionType.APPLICATION_EXCLUDE)) {
return FilterAction.ACCEPT;
}
if (w.appContext == appContext) {
while (w != null) {
if (w == modalDialog) {
return FilterAction.ACCEPT_IMMEDIATELY;
}
w = w.getOwner();
}
return FilterAction.REJECT;
}
return FilterAction.ACCEPT;
}
}
private static class DocumentModalEventFilter extends ModalEventFilter {
private Window documentRoot;
DocumentModalEventFilter(Dialog modalDialog) {
super(modalDialog);
documentRoot = modalDialog.getDocumentRoot();
}
protected FilterAction acceptWindow(Window w) {
// application- and toolkit-excluded windows are blocked by
// document-modal dialogs from their child hierarchy
if (w.isModalExcluded(Dialog.ModalExclusionType.APPLICATION_EXCLUDE)) {
Window w1 = modalDialog.getOwner();
while (w1 != null) {
if (w1 == w) {
return FilterAction.REJECT;
}
w1 = w1.getOwner();
}
return FilterAction.ACCEPT;
}
while (w != null) {
if (w == modalDialog) {
return FilterAction.ACCEPT_IMMEDIATELY;
}
if (w == documentRoot) {
return FilterAction.REJECT;
}
w = w.getOwner();
}
return FilterAction.ACCEPT;
}
}
}

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import sun.awt.AWTPermissions;
import sun.awt.ComponentFactory;
/**
* {@code MouseInfo} provides methods for getting information about the mouse,
* such as mouse pointer location and the number of mouse buttons.
*
* @author Roman Poborchiy
* @since 1.5
*/
public class MouseInfo {
/**
* Private constructor to prevent instantiation.
*/
private MouseInfo() {
}
/**
* Returns a {@code PointerInfo} instance that represents the current
* location of the mouse pointer.
* The {@code GraphicsDevice} stored in this {@code PointerInfo}
* contains the mouse pointer. The coordinate system used for the mouse position
* depends on whether or not the {@code GraphicsDevice} is part of a virtual
* screen device.
* For virtual screen devices, the coordinates are given in the virtual
* coordinate system, otherwise they are returned in the coordinate system
* of the {@code GraphicsDevice}. See {@link GraphicsConfiguration}
* for more information about the virtual screen devices.
* On systems without a mouse, returns {@code null}.
* <p>
* If there is a security manager, its {@code checkPermission} method
* is called with an {@code AWTPermission("watchMousePointer")}
* permission before creating and returning a {@code PointerInfo}
* object. This may result in a {@code SecurityException}.
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
* @exception SecurityException if a security manager exists and its
* {@code checkPermission} method doesn't allow the operation
* @see GraphicsConfiguration
* @see SecurityManager#checkPermission
* @see java.awt.AWTPermission
* @return location of the mouse pointer
* @since 1.5
*/
public static PointerInfo getPointerInfo() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(AWTPermissions.WATCH_MOUSE_PERMISSION);
}
Toolkit toolkit = Toolkit.getDefaultToolkit();
Point point = new Point(0, 0);
int deviceNum = 0;
if (toolkit instanceof ComponentFactory) {
deviceNum = ((ComponentFactory) toolkit).getMouseInfoPeer().fillPointWithCoords(point);
}
GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().
getScreenDevices();
PointerInfo retval = null;
if (areScreenDevicesIndependent(gds)) {
retval = new PointerInfo(gds[deviceNum], point);
} else {
for (int i = 0; i < gds.length; i++) {
GraphicsConfiguration gc = gds[i].getDefaultConfiguration();
Rectangle bounds = gc.getBounds();
if (bounds.contains(point)) {
retval = new PointerInfo(gds[i], point);
}
}
}
return retval;
}
private static boolean areScreenDevicesIndependent(GraphicsDevice[] gds) {
for (int i = 0; i < gds.length; i++) {
Rectangle bounds = gds[i].getDefaultConfiguration().getBounds();
if (bounds.x != 0 || bounds.y != 0) {
return false;
}
}
return true;
}
/**
* Returns the number of buttons on the mouse.
* On systems without a mouse, returns {@code -1}.
* The number of buttons is obtained from the AWT Toolkit
* by requesting the {@code "awt.mouse.numButtons"} desktop property
* which is set by the underlying native platform.
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
* @return number of buttons on the mouse
* @see Toolkit#getDesktopProperty
* @since 1.5
*/
public static int getNumberOfButtons() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
Object prop = Toolkit.getDefaultToolkit().
getDesktopProperty("awt.mouse.numButtons");
if (prop instanceof Integer) {
return ((Integer)prop).intValue();
}
// This should never happen.
assert false : "awt.mouse.numButtons is not an integer property";
return 0;
}
}

View file

@ -0,0 +1,311 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.lang.ref.SoftReference;
import java.util.Arrays;
/**
* This is the superclass for Paints which use a multiple color
* gradient to fill in their raster. It provides storage for variables and
* enumerated values common to
* {@code LinearGradientPaint} and {@code RadialGradientPaint}.
*
* @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
* @since 1.6
*/
public abstract class MultipleGradientPaint implements Paint {
/** The method to use when painting outside the gradient bounds.
* @since 1.6
*/
public static enum CycleMethod {
/**
* Use the terminal colors to fill the remaining area.
*/
NO_CYCLE,
/**
* Cycle the gradient colors start-to-end, end-to-start
* to fill the remaining area.
*/
REFLECT,
/**
* Cycle the gradient colors start-to-end, start-to-end
* to fill the remaining area.
*/
REPEAT
}
/** The color space in which to perform the gradient interpolation.
* @since 1.6
*/
public static enum ColorSpaceType {
/**
* Indicates that the color interpolation should occur in sRGB space.
*/
SRGB,
/**
* Indicates that the color interpolation should occur in linearized
* RGB space.
*/
LINEAR_RGB
}
/** The transparency of this paint object. */
final int transparency;
/** Gradient keyframe values in the range 0 to 1. */
final float[] fractions;
/** Gradient colors. */
final Color[] colors;
/** Transform to apply to gradient. */
final AffineTransform gradientTransform;
/** The method to use when painting outside the gradient bounds. */
final CycleMethod cycleMethod;
/** The color space in which to perform the gradient interpolation. */
final ColorSpaceType colorSpace;
/**
* The following fields are used only by MultipleGradientPaintContext
* to cache certain values that remain constant and do not need to be
* recalculated for each context created from this paint instance.
*/
ColorModel model;
float[] normalizedIntervals;
boolean isSimpleLookup;
SoftReference<int[][]> gradients;
SoftReference<int[]> gradient;
int fastGradientArraySize;
/**
* Package-private constructor.
*
* @param fractions numbers ranging from 0.0 to 1.0 specifying the
* distribution of colors along the gradient
* @param colors array of colors corresponding to each fractional value
* @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
* or {@code REPEAT}
* @param colorSpace which color space to use for interpolation,
* either {@code SRGB} or {@code LINEAR_RGB}
* @param gradientTransform transform to apply to the gradient
*
* @throws NullPointerException
* if {@code fractions} array is null,
* or {@code colors} array is null,
* or {@code gradientTransform} is null,
* or {@code cycleMethod} is null,
* or {@code colorSpace} is null
* @throws IllegalArgumentException
* if {@code fractions.length != colors.length},
* or {@code colors} is less than 2 in size,
* or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order
*/
MultipleGradientPaint(float[] fractions,
Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace,
AffineTransform gradientTransform)
{
if (fractions == null) {
throw new NullPointerException("Fractions array cannot be null");
}
if (colors == null) {
throw new NullPointerException("Colors array cannot be null");
}
if (cycleMethod == null) {
throw new NullPointerException("Cycle method cannot be null");
}
if (colorSpace == null) {
throw new NullPointerException("Color space cannot be null");
}
if (gradientTransform == null) {
throw new NullPointerException("Gradient transform cannot be "+
"null");
}
if (fractions.length != colors.length) {
throw new IllegalArgumentException("Colors and fractions must " +
"have equal size");
}
if (colors.length < 2) {
throw new IllegalArgumentException("User must specify at least " +
"2 colors");
}
// check that values are in the proper range and progress
// in increasing order from 0 to 1
float previousFraction = -1.0f;
for (float currentFraction : fractions) {
if (currentFraction < 0f || currentFraction > 1f) {
throw new IllegalArgumentException("Fraction values must " +
"be in the range 0 to 1: " +
currentFraction);
}
if (currentFraction <= previousFraction) {
throw new IllegalArgumentException("Keyframe fractions " +
"must be increasing: " +
currentFraction);
}
previousFraction = currentFraction;
}
// We have to deal with the cases where the first gradient stop is not
// equal to 0 and/or the last gradient stop is not equal to 1.
// In both cases, create a new point and replicate the previous
// extreme point's color.
boolean fixFirst = false;
boolean fixLast = false;
int len = fractions.length;
int off = 0;
if (fractions[0] != 0f) {
// first stop is not equal to zero, fix this condition
fixFirst = true;
len++;
off++;
}
if (fractions[fractions.length-1] != 1f) {
// last stop is not equal to one, fix this condition
fixLast = true;
len++;
}
this.fractions = new float[len];
System.arraycopy(fractions, 0, this.fractions, off, fractions.length);
this.colors = new Color[len];
System.arraycopy(colors, 0, this.colors, off, colors.length);
if (fixFirst) {
this.fractions[0] = 0f;
this.colors[0] = colors[0];
}
if (fixLast) {
this.fractions[len-1] = 1f;
this.colors[len-1] = colors[colors.length - 1];
}
// copy some flags
this.colorSpace = colorSpace;
this.cycleMethod = cycleMethod;
// copy the gradient transform
this.gradientTransform = new AffineTransform(gradientTransform);
// determine transparency
boolean opaque = true;
for (int i = 0; i < colors.length; i++){
opaque = opaque && (colors[i].getAlpha() == 0xff);
}
this.transparency = opaque ? OPAQUE : TRANSLUCENT;
}
/**
* Returns a copy of the array of floats used by this gradient
* to calculate color distribution.
* The returned array always has 0 as its first value and 1 as its
* last value, with increasing values in between.
*
* @return a copy of the array of floats used by this gradient to
* calculate color distribution
*/
public final float[] getFractions() {
return Arrays.copyOf(fractions, fractions.length);
}
/**
* Returns a copy of the array of colors used by this gradient.
* The first color maps to the first value in the fractions array,
* and the last color maps to the last value in the fractions array.
*
* @return a copy of the array of colors used by this gradient
*/
public final Color[] getColors() {
return Arrays.copyOf(colors, colors.length);
}
/**
* Returns the enumerated type which specifies cycling behavior.
*
* @return the enumerated type which specifies cycling behavior
*/
public final CycleMethod getCycleMethod() {
return cycleMethod;
}
/**
* Returns the enumerated type which specifies color space for
* interpolation.
*
* @return the enumerated type which specifies color space for
* interpolation
*/
public final ColorSpaceType getColorSpace() {
return colorSpace;
}
/**
* Returns a copy of the transform applied to the gradient.
*
* <p>
* Note that if no transform is applied to the gradient
* when it is created, the identity transform is used.
*
* @return a copy of the transform applied to the gradient
*/
public final AffineTransform getTransform() {
return new AffineTransform(gradientTransform);
}
/**
* Returns the transparency mode for this {@code Paint} object.
*
* @return {@code OPAQUE} if all colors used by this
* {@code Paint} object are opaque,
* {@code TRANSLUCENT} if at least one of the
* colors used by this {@code Paint} object is not opaque.
* @see java.awt.Transparency
*/
public final int getTransparency() {
return transparency;
}
}

View file

@ -0,0 +1,724 @@
/*
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.MultipleGradientPaint.ColorSpaceType;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
/**
* This is the superclass for all PaintContexts which use a multiple color
* gradient to fill in their raster. It provides the actual color
* interpolation functionality. Subclasses only have to deal with using
* the gradient to fill pixels in a raster.
*
* @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
*/
abstract class MultipleGradientPaintContext implements PaintContext {
/**
* The PaintContext's ColorModel. This is ARGB if colors are not all
* opaque, otherwise it is RGB.
*/
protected ColorModel model;
/** Color model used if gradient colors are all opaque. */
private static ColorModel xrgbmodel =
new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
/** The cached ColorModel. */
protected static ColorModel cachedModel;
/** The cached raster, which is reusable among instances. */
protected static WeakReference<Raster> cached;
/** Raster is reused whenever possible. */
protected Raster saved;
/** The method to use when painting out of the gradient bounds. */
protected CycleMethod cycleMethod;
/** The ColorSpace in which to perform the interpolation */
protected ColorSpaceType colorSpace;
/** Elements of the inverse transform matrix. */
protected float a00, a01, a10, a11, a02, a12;
/**
* This boolean specifies whether we are in simple lookup mode, where an
* input value between 0 and 1 may be used to directly index into a single
* array of gradient colors. If this boolean value is false, then we have
* to use a 2-step process where we have to determine which gradient array
* we fall into, then determine the index into that array.
*/
protected boolean isSimpleLookup;
/**
* Size of gradients array for scaling the 0-1 index when looking up
* colors the fast way.
*/
protected int fastGradientArraySize;
/**
* Array which contains the interpolated color values for each interval,
* used by calculateSingleArrayGradient(). It is protected for possible
* direct access by subclasses.
*/
protected int[] gradient;
/**
* Array of gradient arrays, one array for each interval. Used by
* calculateMultipleArrayGradient().
*/
private int[][] gradients;
/** Normalized intervals array. */
private float[] normalizedIntervals;
/** Fractions array. */
private float[] fractions;
/** Used to determine if gradient colors are all opaque. */
private int transparencyTest;
/** Color space conversion lookup tables. */
private static final int SRGBtoLinearRGB[] = new int[256];
private static final int LinearRGBtoSRGB[] = new int[256];
static {
// build the tables
for (int k = 0; k < 256; k++) {
SRGBtoLinearRGB[k] = convertSRGBtoLinearRGB(k);
LinearRGBtoSRGB[k] = convertLinearRGBtoSRGB(k);
}
}
/**
* Constant number of max colors between any 2 arbitrary colors.
* Used for creating and indexing gradients arrays.
*/
protected static final int GRADIENT_SIZE = 256;
protected static final int GRADIENT_SIZE_INDEX = GRADIENT_SIZE -1;
/**
* Maximum length of the fast single-array. If the estimated array size
* is greater than this, switch over to the slow lookup method.
* No particular reason for choosing this number, but it seems to provide
* satisfactory performance for the common case (fast lookup).
*/
private static final int MAX_GRADIENT_ARRAY_SIZE = 5000;
/**
* Constructor for MultipleGradientPaintContext superclass.
*/
protected MultipleGradientPaintContext(MultipleGradientPaint mgp,
ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform t,
RenderingHints hints,
float[] fractions,
Color[] colors,
CycleMethod cycleMethod,
ColorSpaceType colorSpace)
{
if (deviceBounds == null) {
throw new NullPointerException("Device bounds cannot be null");
}
if (userBounds == null) {
throw new NullPointerException("User bounds cannot be null");
}
if (t == null) {
throw new NullPointerException("Transform cannot be null");
}
if (hints == null) {
throw new NullPointerException("RenderingHints cannot be null");
}
// The inverse transform is needed to go from device to user space.
// Get all the components of the inverse transform matrix.
AffineTransform tInv;
try {
// the following assumes that the caller has copied the incoming
// transform and is not concerned about it being modified
t.invert();
tInv = t;
} catch (NoninvertibleTransformException e) {
// just use identity transform in this case; better to show
// (incorrect) results than to throw an exception and/or no-op
tInv = new AffineTransform();
}
double m[] = new double[6];
tInv.getMatrix(m);
a00 = (float)m[0];
a10 = (float)m[1];
a01 = (float)m[2];
a11 = (float)m[3];
a02 = (float)m[4];
a12 = (float)m[5];
// copy some flags
this.cycleMethod = cycleMethod;
this.colorSpace = colorSpace;
// we can avoid copying this array since we do not modify its values
this.fractions = fractions;
// note that only one of these values can ever be non-null (we either
// store the fast gradient array or the slow one, but never both
// at the same time)
int[] gradient =
(mgp.gradient != null) ? mgp.gradient.get() : null;
int[][] gradients =
(mgp.gradients != null) ? mgp.gradients.get() : null;
if (gradient == null && gradients == null) {
// we need to (re)create the appropriate values
calculateLookupData(colors);
// now cache the calculated values in the
// MultipleGradientPaint instance for future use
mgp.model = this.model;
mgp.normalizedIntervals = this.normalizedIntervals;
mgp.isSimpleLookup = this.isSimpleLookup;
if (isSimpleLookup) {
// only cache the fast array
mgp.fastGradientArraySize = this.fastGradientArraySize;
mgp.gradient = new SoftReference<int[]>(this.gradient);
} else {
// only cache the slow array
mgp.gradients = new SoftReference<int[][]>(this.gradients);
}
} else {
// use the values cached in the MultipleGradientPaint instance
this.model = mgp.model;
this.normalizedIntervals = mgp.normalizedIntervals;
this.isSimpleLookup = mgp.isSimpleLookup;
this.gradient = gradient;
this.fastGradientArraySize = mgp.fastGradientArraySize;
this.gradients = gradients;
}
}
/**
* This function is the meat of this class. It calculates an array of
* gradient colors based on an array of fractions and color values at
* those fractions.
*/
private void calculateLookupData(Color[] colors) {
Color[] normalizedColors;
if (colorSpace == ColorSpaceType.LINEAR_RGB) {
// create a new colors array
normalizedColors = new Color[colors.length];
// convert the colors using the lookup table
for (int i = 0; i < colors.length; i++) {
int argb = colors[i].getRGB();
int a = argb >>> 24;
int r = SRGBtoLinearRGB[(argb >> 16) & 0xff];
int g = SRGBtoLinearRGB[(argb >> 8) & 0xff];
int b = SRGBtoLinearRGB[(argb ) & 0xff];
normalizedColors[i] = new Color(r, g, b, a);
}
} else {
// we can just use this array by reference since we do not
// modify its values in the case of SRGB
normalizedColors = colors;
}
// this will store the intervals (distances) between gradient stops
normalizedIntervals = new float[fractions.length-1];
// convert from fractions into intervals
for (int i = 0; i < normalizedIntervals.length; i++) {
// interval distance is equal to the difference in positions
normalizedIntervals[i] = this.fractions[i+1] - this.fractions[i];
}
// initialize to be fully opaque for ANDing with colors
transparencyTest = 0xff000000;
// array of interpolation arrays
gradients = new int[normalizedIntervals.length][];
// find smallest interval
float Imin = 1;
for (int i = 0; i < normalizedIntervals.length; i++) {
Imin = (Imin > normalizedIntervals[i]) ?
normalizedIntervals[i] : Imin;
}
// Estimate the size of the entire gradients array.
// This is to prevent a tiny interval from causing the size of array
// to explode. If the estimated size is too large, break to using
// separate arrays for each interval, and using an indexing scheme at
// look-up time.
int estimatedSize = 0;
for (int i = 0; i < normalizedIntervals.length; i++) {
estimatedSize += (normalizedIntervals[i]/Imin) * GRADIENT_SIZE;
}
if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
// slow method
calculateMultipleArrayGradient(normalizedColors);
} else {
// fast method
calculateSingleArrayGradient(normalizedColors, Imin);
}
// use the most "economical" model
if ((transparencyTest >>> 24) == 0xff) {
model = xrgbmodel;
} else {
model = ColorModel.getRGBdefault();
}
}
/**
* FAST LOOKUP METHOD
*
* This method calculates the gradient color values and places them in a
* single int array, gradient[]. It does this by allocating space for
* each interval based on its size relative to the smallest interval in
* the array. The smallest interval is allocated 255 interpolated values
* (the maximum number of unique in-between colors in a 24 bit color
* system), and all other intervals are allocated
* size = (255 * the ratio of their size to the smallest interval).
*
* This scheme expedites a speedy retrieval because the colors are
* distributed along the array according to their user-specified
* distribution. All that is needed is a relative index from 0 to 1.
*
* The only problem with this method is that the possibility exists for
* the array size to balloon in the case where there is a
* disproportionately small gradient interval. In this case the other
* intervals will be allocated huge space, but much of that data is
* redundant. We thus need to use the space conserving scheme below.
*
* @param Imin the size of the smallest interval
*/
private void calculateSingleArrayGradient(Color[] colors, float Imin) {
// set the flag so we know later it is a simple (fast) lookup
isSimpleLookup = true;
// 2 colors to interpolate
int rgb1, rgb2;
//the eventual size of the single array
int gradientsTot = 1;
// for every interval (transition between 2 colors)
for (int i = 0; i < gradients.length; i++) {
// create an array whose size is based on the ratio to the
// smallest interval
int nGradients = (int)((normalizedIntervals[i]/Imin)*255f);
gradientsTot += nGradients;
gradients[i] = new int[nGradients];
// the 2 colors (keyframes) to interpolate between
rgb1 = colors[i].getRGB();
rgb2 = colors[i+1].getRGB();
// fill this array with the colors in between rgb1 and rgb2
interpolate(rgb1, rgb2, gradients[i]);
// if the colors are opaque, transparency should still
// be 0xff000000
transparencyTest &= rgb1;
transparencyTest &= rgb2;
}
// put all gradients in a single array
gradient = new int[gradientsTot];
int curOffset = 0;
for (int i = 0; i < gradients.length; i++){
System.arraycopy(gradients[i], 0, gradient,
curOffset, gradients[i].length);
curOffset += gradients[i].length;
}
gradient[gradient.length-1] = colors[colors.length-1].getRGB();
// if interpolation occurred in Linear RGB space, convert the
// gradients back to sRGB using the lookup table
if (colorSpace == ColorSpaceType.LINEAR_RGB) {
for (int i = 0; i < gradient.length; i++) {
gradient[i] = convertEntireColorLinearRGBtoSRGB(gradient[i]);
}
}
fastGradientArraySize = gradient.length - 1;
}
/**
* SLOW LOOKUP METHOD
*
* This method calculates the gradient color values for each interval and
* places each into its own 255 size array. The arrays are stored in
* gradients[][]. (255 is used because this is the maximum number of
* unique colors between 2 arbitrary colors in a 24 bit color system.)
*
* This method uses the minimum amount of space (only 255 * number of
* intervals), but it aggravates the lookup procedure, because now we
* have to find out which interval to select, then calculate the index
* within that interval. This causes a significant performance hit,
* because it requires this calculation be done for every point in
* the rendering loop.
*
* For those of you who are interested, this is a classic example of the
* time-space tradeoff.
*/
private void calculateMultipleArrayGradient(Color[] colors) {
// set the flag so we know later it is a non-simple lookup
isSimpleLookup = false;
// 2 colors to interpolate
int rgb1, rgb2;
// for every interval (transition between 2 colors)
for (int i = 0; i < gradients.length; i++){
// create an array of the maximum theoretical size for
// each interval
gradients[i] = new int[GRADIENT_SIZE];
// get the 2 colors
rgb1 = colors[i].getRGB();
rgb2 = colors[i+1].getRGB();
// fill this array with the colors in between rgb1 and rgb2
interpolate(rgb1, rgb2, gradients[i]);
// if the colors are opaque, transparency should still
// be 0xff000000
transparencyTest &= rgb1;
transparencyTest &= rgb2;
}
// if interpolation occurred in Linear RGB space, convert the
// gradients back to SRGB using the lookup table
if (colorSpace == ColorSpaceType.LINEAR_RGB) {
for (int j = 0; j < gradients.length; j++) {
for (int i = 0; i < gradients[j].length; i++) {
gradients[j][i] =
convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
}
}
}
}
/**
* Yet another helper function. This one linearly interpolates between
* 2 colors, filling up the output array.
*
* @param rgb1 the start color
* @param rgb2 the end color
* @param output the output array of colors; must not be null
*/
private void interpolate(int rgb1, int rgb2, int[] output) {
// color components
int a1, r1, g1, b1, da, dr, dg, db;
// step between interpolated values
float stepSize = 1.0f / output.length;
// extract color components from packed integer
a1 = (rgb1 >> 24) & 0xff;
r1 = (rgb1 >> 16) & 0xff;
g1 = (rgb1 >> 8) & 0xff;
b1 = (rgb1 ) & 0xff;
// calculate the total change in alpha, red, green, blue
da = ((rgb2 >> 24) & 0xff) - a1;
dr = ((rgb2 >> 16) & 0xff) - r1;
dg = ((rgb2 >> 8) & 0xff) - g1;
db = ((rgb2 ) & 0xff) - b1;
// for each step in the interval calculate the in-between color by
// multiplying the normalized current position by the total color
// change (0.5 is added to prevent truncation round-off error)
for (int i = 0; i < output.length; i++) {
output[i] =
(((int) ((a1 + i * da * stepSize) + 0.5) << 24)) |
(((int) ((r1 + i * dr * stepSize) + 0.5) << 16)) |
(((int) ((g1 + i * dg * stepSize) + 0.5) << 8)) |
(((int) ((b1 + i * db * stepSize) + 0.5) ));
}
}
/**
* Yet another helper function. This one extracts the color components
* of an integer RGB triple, converts them from LinearRGB to SRGB, then
* recompacts them into an int.
*/
private int convertEntireColorLinearRGBtoSRGB(int rgb) {
// color components
int a1, r1, g1, b1;
// extract red, green, blue components
a1 = (rgb >> 24) & 0xff;
r1 = (rgb >> 16) & 0xff;
g1 = (rgb >> 8) & 0xff;
b1 = (rgb ) & 0xff;
// use the lookup table
r1 = LinearRGBtoSRGB[r1];
g1 = LinearRGBtoSRGB[g1];
b1 = LinearRGBtoSRGB[b1];
// re-compact the components
return ((a1 << 24) |
(r1 << 16) |
(g1 << 8) |
(b1 ));
}
/**
* Helper function to index into the gradients array. This is necessary
* because each interval has an array of colors with uniform size 255.
* However, the color intervals are not necessarily of uniform length, so
* a conversion is required.
*
* @param position the unmanipulated position, which will be mapped
* into the range 0 to 1
* @return integer color to display
*/
protected final int indexIntoGradientsArrays(float position) {
// first, manipulate position value depending on the cycle method
if (cycleMethod == CycleMethod.NO_CYCLE) {
if (position > 1) {
// upper bound is 1
position = 1;
} else if (position < 0) {
// lower bound is 0
position = 0;
}
} else if (cycleMethod == CycleMethod.REPEAT) {
// get the fractional part
// (modulo behavior discards integer component)
position = position - (int)position;
//position should now be between -1 and 1
if (position < 0) {
// force it to be in the range 0-1
position = position + 1;
}
} else { // cycleMethod == CycleMethod.REFLECT
if (position < 0) {
// take absolute value
position = -position;
}
// get the integer part
int part = (int)position;
// get the fractional part
position = position - part;
if ((part & 1) == 1) {
// integer part is odd, get reflected color instead
position = 1 - position;
}
}
// now, get the color based on this 0-1 position...
if (isSimpleLookup) {
// easy to compute: just scale index by array size
return gradient[(int)(position * fastGradientArraySize)];
} else {
// more complicated computation, to save space
// for all the gradient interval arrays
for (int i = 0; i < gradients.length; i++) {
if (position < fractions[i+1]) {
// this is the array we want
float delta = position - fractions[i];
// this is the interval we want
int index = (int)((delta / normalizedIntervals[i])
* (GRADIENT_SIZE_INDEX));
return gradients[i][index];
}
}
}
return gradients[gradients.length - 1][GRADIENT_SIZE_INDEX];
}
/**
* Helper function to convert a color component in sRGB space to linear
* RGB space. Used to build a static lookup table.
*/
private static int convertSRGBtoLinearRGB(int color) {
float input, output;
input = color / 255.0f;
if (input <= 0.04045f) {
output = input / 12.92f;
} else {
output = (float)Math.pow((input + 0.055) / 1.055, 2.4);
}
return Math.round(output * 255.0f);
}
/**
* Helper function to convert a color component in linear RGB space to
* SRGB space. Used to build a static lookup table.
*/
private static int convertLinearRGBtoSRGB(int color) {
float input, output;
input = color/255.0f;
if (input <= 0.0031308) {
output = input * 12.92f;
} else {
output = (1.055f *
((float) Math.pow(input, (1.0 / 2.4)))) - 0.055f;
}
return Math.round(output * 255.0f);
}
/**
* {@inheritDoc}
*/
public final Raster getRaster(int x, int y, int w, int h) {
// If working raster is big enough, reuse it. Otherwise,
// build a large enough new one.
Raster raster = saved;
if (raster == null ||
raster.getWidth() < w || raster.getHeight() < h)
{
raster = getCachedRaster(model, w, h);
saved = raster;
}
// Access raster internal int array. Because we use a DirectColorModel,
// we know the DataBuffer is of type DataBufferInt and the SampleModel
// is SinglePixelPackedSampleModel.
// Adjust for initial offset in DataBuffer and also for the scanline
// stride.
// These calls make the DataBuffer non-acceleratable, but the
// Raster is never Stable long enough to accelerate anyway...
DataBufferInt rasterDB = (DataBufferInt)raster.getDataBuffer();
int[] pixels = rasterDB.getData(0);
int off = rasterDB.getOffset();
int scanlineStride = ((SinglePixelPackedSampleModel)
raster.getSampleModel()).getScanlineStride();
int adjust = scanlineStride - w;
fillRaster(pixels, off, adjust, x, y, w, h); // delegate to subclass
return raster;
}
protected abstract void fillRaster(int pixels[], int off, int adjust,
int x, int y, int w, int h);
/**
* Took this cacheRaster code from GradientPaint. It appears to recycle
* rasters for use by any other instance, as long as they are sufficiently
* large.
*/
private static synchronized Raster getCachedRaster(ColorModel cm,
int w, int h)
{
if (cm == cachedModel) {
if (cached != null) {
Raster ras = cached.get();
if (ras != null &&
ras.getWidth() >= w &&
ras.getHeight() >= h)
{
cached = null;
return ras;
}
}
}
return cm.createCompatibleWritableRaster(w, h);
}
/**
* Took this cacheRaster code from GradientPaint. It appears to recycle
* rasters for use by any other instance, as long as they are sufficiently
* large.
*/
private static synchronized void putCachedRaster(ColorModel cm,
Raster ras)
{
if (cached != null) {
Raster cras = cached.get();
if (cras != null) {
int cw = cras.getWidth();
int ch = cras.getHeight();
int iw = ras.getWidth();
int ih = ras.getHeight();
if (cw >= iw && ch >= ih) {
return;
}
if (cw * ch >= iw * ih) {
return;
}
}
}
cachedModel = cm;
cached = new WeakReference<Raster>(ras);
}
/**
* {@inheritDoc}
*/
public final void dispose() {
if (saved != null) {
putCachedRaster(model, saved);
saved = null;
}
}
/**
* {@inheritDoc}
*/
public final ColorModel getColorModel() {
return model;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.image.ColorModel;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
/**
* This {@code Paint} interface defines how color patterns
* can be generated for {@link Graphics2D} operations. A class
* implementing the {@code Paint} interface is added to the
* {@code Graphics2D} context in order to define the color
* pattern used by the {@code draw} and {@code fill} methods.
* <p>
* Instances of classes implementing {@code Paint} must be
* read-only because the {@code Graphics2D} does not clone
* these objects when they are set as an attribute with the
* {@code setPaint} method or when the {@code Graphics2D}
* object is itself cloned.
* @see PaintContext
* @see Color
* @see GradientPaint
* @see TexturePaint
* @see Graphics2D#setPaint
* @version 1.36, 06/05/07
*/
public interface Paint extends Transparency {
/**
* Creates and returns a {@link PaintContext} used to
* generate the color pattern.
* The arguments to this method convey additional information
* about the rendering operation that may be
* used or ignored on various implementations of the {@code Paint} interface.
* A caller must pass non-{@code null} values for all of the arguments
* except for the {@code ColorModel} argument which may be {@code null} to
* indicate that no specific {@code ColorModel} type is preferred.
* Implementations of the {@code Paint} interface are allowed to use or ignore
* any of the arguments as makes sense for their function, and are
* not constrained to use the specified {@code ColorModel} for the returned
* {@code PaintContext}, even if it is not {@code null}.
* Implementations are allowed to throw {@code NullPointerException} for
* any {@code null} argument other than the {@code ColorModel} argument,
* but are not required to do so.
*
* @param cm the preferred {@link ColorModel} which represents the most convenient
* format for the caller to receive the pixel data, or {@code null}
* if there is no preference.
* @param deviceBounds the device space bounding box
* of the graphics primitive being rendered.
* Implementations of the {@code Paint} interface
* are allowed to throw {@code NullPointerException}
* for a {@code null deviceBounds}.
* @param userBounds the user space bounding box
* of the graphics primitive being rendered.
* Implementations of the {@code Paint} interface
* are allowed to throw {@code NullPointerException}
* for a {@code null userBounds}.
* @param xform the {@link AffineTransform} from user
* space into device space.
* Implementations of the {@code Paint} interface
* are allowed to throw {@code NullPointerException}
* for a {@code null xform}.
* @param hints the set of hints that the context object can use to
* choose between rendering alternatives.
* Implementations of the {@code Paint} interface
* are allowed to throw {@code NullPointerException}
* for a {@code null hints}.
* @return the {@code PaintContext} for
* generating color patterns.
* @see PaintContext
* @see ColorModel
* @see Rectangle
* @see Rectangle2D
* @see AffineTransform
* @see RenderingHints
*/
public PaintContext createContext(ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform xform,
RenderingHints hints);
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
/**
* The {@code PaintContext} interface defines the encapsulated
* and optimized environment to generate color patterns in device
* space for fill or stroke operations on a
* {@link Graphics2D}. The {@code PaintContext} provides
* the necessary colors for {@code Graphics2D} operations in the
* form of a {@link Raster} associated with a {@link ColorModel}.
* The {@code PaintContext} maintains state for a particular paint
* operation. In a multi-threaded environment, several
* contexts can exist simultaneously for a single {@link Paint} object.
* @see Paint
*/
public interface PaintContext {
/**
* Releases the resources allocated for the operation.
*/
public void dispose();
/**
* Returns the {@code ColorModel} of the output. Note that
* this {@code ColorModel} might be different from the hint
* specified in the
* {@link Paint#createContext(ColorModel, Rectangle, Rectangle2D,
AffineTransform, RenderingHints) createContext} method of
* {@code Paint}. Not all {@code PaintContext} objects are
* capable of generating color patterns in an arbitrary
* {@code ColorModel}.
* @return the {@code ColorModel} of the output.
*/
ColorModel getColorModel();
/**
* Returns a {@code Raster} containing the colors generated for
* the graphics operation.
* @param x the x coordinate of the area in device space
* for which colors are generated.
* @param y the y coordinate of the area in device space
* for which colors are generated.
* @param w the width of the area in device space
* @param h the height of the area in device space
* @return a {@code Raster} representing the specified
* rectangular area and containing the colors generated for
* the graphics operation.
*/
Raster getRaster(int x,
int y,
int w,
int h);
}

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import javax.accessibility.*;
/**
* {@code Panel} is the simplest container class. A panel
* provides space in which an application can attach any other
* component, including other panels.
* <p>
* The default layout manager for a panel is the
* {@code FlowLayout} layout manager.
*
* @author Sami Shaio
* @see java.awt.FlowLayout
* @since 1.0
*/
public class Panel extends Container implements Accessible {
private static final String base = "panel";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -2728009084054400034L;
/**
* Creates a new panel using the default layout manager.
* The default layout manager for all panels is the
* {@code FlowLayout} class.
*/
public Panel() {
this(new FlowLayout());
}
/**
* Creates a new panel with the specified layout manager.
* @param layout the layout manager for this panel.
* @since 1.1
*/
public Panel(LayoutManager layout) {
setLayout(layout);
}
/**
* Construct a name for this component. Called by getName() when the
* name is null.
*/
String constructComponentName() {
synchronized (Panel.class) {
return base + nameCounter++;
}
}
/**
* Creates the Panel's peer. The peer allows you to modify the
* appearance of the panel without changing its functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getComponentFactory().createPanel(this);
super.addNotify();
}
}
/////////////////
// Accessibility support
////////////////
/**
* Gets the AccessibleContext associated with this Panel.
* For panels, the AccessibleContext takes the form of an
* AccessibleAWTPanel.
* A new AccessibleAWTPanel instance is created if necessary.
*
* @return an AccessibleAWTPanel that serves as the
* AccessibleContext of this Panel
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTPanel();
}
return accessibleContext;
}
/**
* This class implements accessibility support for the
* {@code Panel} class. It provides an implementation of the
* Java Accessibility API appropriate to panel user-interface elements.
* @since 1.3
*/
protected class AccessibleAWTPanel extends AccessibleAWTContainer {
private static final long serialVersionUID = -6409552226660031050L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.PANEL;
}
}
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.Point2D;
import java.beans.Transient;
/**
* A point representing a location in {@code (x,y)} coordinate space,
* specified in integer precision.
*
* @author Sami Shaio
* @since 1.0
*/
public class Point extends Point2D implements java.io.Serializable {
/**
* The X coordinate of this {@code Point}.
* If no X coordinate is set it will default to 0.
*
* @serial
* @see #getLocation()
* @see #move(int, int)
* @since 1.0
*/
public int x;
/**
* The Y coordinate of this {@code Point}.
* If no Y coordinate is set it will default to 0.
*
* @serial
* @see #getLocation()
* @see #move(int, int)
* @since 1.0
*/
public int y;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -5276940640259749850L;
/**
* Constructs and initializes a point at the origin
* (0,&nbsp;0) of the coordinate space.
* @since 1.1
*/
public Point() {
this(0, 0);
}
/**
* Constructs and initializes a point with the same location as
* the specified {@code Point} object.
* @param p a point
* @since 1.1
*/
public Point(Point p) {
this(p.x, p.y);
}
/**
* Constructs and initializes a point at the specified
* {@code (x,y)} location in the coordinate space.
* @param x the X coordinate of the newly constructed {@code Point}
* @param y the Y coordinate of the newly constructed {@code Point}
* @since 1.0
*/
public Point(int x, int y) {
this.x = x;
this.y = y;
}
/**
* {@inheritDoc}
* @since 1.2
*/
public double getX() {
return x;
}
/**
* {@inheritDoc}
* @since 1.2
*/
public double getY() {
return y;
}
/**
* Returns the location of this point.
* This method is included for completeness, to parallel the
* {@code getLocation} method of {@code Component}.
* @return a copy of this point, at the same location
* @see java.awt.Component#getLocation
* @see java.awt.Point#setLocation(java.awt.Point)
* @see java.awt.Point#setLocation(int, int)
* @since 1.1
*/
@Transient
public Point getLocation() {
return new Point(x, y);
}
/**
* Sets the location of the point to the specified location.
* This method is included for completeness, to parallel the
* {@code setLocation} method of {@code Component}.
* @param p a point, the new location for this point
* @see java.awt.Component#setLocation(java.awt.Point)
* @see java.awt.Point#getLocation
* @since 1.1
*/
public void setLocation(Point p) {
setLocation(p.x, p.y);
}
/**
* Changes the point to have the specified location.
* <p>
* This method is included for completeness, to parallel the
* {@code setLocation} method of {@code Component}.
* Its behavior is identical with <code>move(int,&nbsp;int)</code>.
* @param x the X coordinate of the new location
* @param y the Y coordinate of the new location
* @see java.awt.Component#setLocation(int, int)
* @see java.awt.Point#getLocation
* @see java.awt.Point#move(int, int)
* @since 1.1
*/
public void setLocation(int x, int y) {
move(x, y);
}
/**
* Sets the location of this point to the specified double coordinates.
* The double values will be rounded to integer values.
* Any number smaller than {@code Integer.MIN_VALUE}
* will be reset to {@code MIN_VALUE}, and any number
* larger than {@code Integer.MAX_VALUE} will be
* reset to {@code MAX_VALUE}.
*
* @param x the X coordinate of the new location
* @param y the Y coordinate of the new location
* @see #getLocation
*/
public void setLocation(double x, double y) {
this.x = (int) Math.floor(x+0.5);
this.y = (int) Math.floor(y+0.5);
}
/**
* Moves this point to the specified location in the
* {@code (x,y)} coordinate plane. This method
* is identical with <code>setLocation(int,&nbsp;int)</code>.
* @param x the X coordinate of the new location
* @param y the Y coordinate of the new location
* @see java.awt.Component#setLocation(int, int)
*/
public void move(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Translates this point, at location {@code (x,y)},
* by {@code dx} along the {@code x} axis and {@code dy}
* along the {@code y} axis so that it now represents the point
* {@code (x+dx,y+dy)}.
*
* @param dx the distance to move this point
* along the X axis
* @param dy the distance to move this point
* along the Y axis
*/
public void translate(int dx, int dy) {
this.x += dx;
this.y += dy;
}
/**
* Determines whether or not two points are equal. Two instances of
* {@code Point2D} are equal if the values of their
* {@code x} and {@code y} member fields, representing
* their position in the coordinate space, are the same.
* @param obj an object to be compared with this {@code Point2D}
* @return {@code true} if the object to be compared is
* an instance of {@code Point2D} and has
* the same values; {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Point) {
Point pt = (Point)obj;
return (x == pt.x) && (y == pt.y);
}
return super.equals(obj);
}
/**
* Returns a string representation of this point and its location
* in the {@code (x,y)} coordinate space. This method is
* intended to be used only for debugging purposes, and the content
* and format of the returned string may vary between implementations.
* The returned string may be empty but may not be {@code null}.
*
* @return a string representation of this point
*/
public String toString() {
return getClass().getName() + "[x=" + x + ",y=" + y + "]";
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
/**
* A class that describes the pointer position.
* It provides the {@code GraphicsDevice} where the pointer is and
* the {@code Point} that represents the coordinates of the pointer.
* <p>
* Instances of this class should be obtained via
* {@link MouseInfo#getPointerInfo}.
* The {@code PointerInfo} instance is not updated dynamically as the mouse
* moves. To get the updated location, you must call
* {@link MouseInfo#getPointerInfo} again.
*
* @see MouseInfo#getPointerInfo
* @author Roman Poborchiy
* @since 1.5
*/
public class PointerInfo {
private final GraphicsDevice device;
private final Point location;
/**
* Package-private constructor to prevent instantiation.
*/
PointerInfo(final GraphicsDevice device, final Point location) {
this.device = device;
this.location = location;
}
/**
* Returns the {@code GraphicsDevice} where the mouse pointer was at the
* moment this {@code PointerInfo} was created.
*
* @return {@code GraphicsDevice} corresponding to the pointer
* @since 1.5
*/
public GraphicsDevice getDevice() {
return device;
}
/**
* Returns the {@code Point} that represents the coordinates of the pointer
* on the screen. See {@link MouseInfo#getPointerInfo} for more information
* about coordinate calculation for multiscreen systems.
*
* @return coordinates of mouse pointer
* @see MouseInfo
* @see MouseInfo#getPointerInfo
* @since 1.5
*/
public Point getLocation() {
return location;
}
}

View file

@ -0,0 +1,677 @@
/*
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import sun.awt.geom.Crossings;
import java.util.Arrays;
/**
* The {@code Polygon} class encapsulates a description of a
* closed, two-dimensional region within a coordinate space. This
* region is bounded by an arbitrary number of line segments, each of
* which is one side of the polygon. Internally, a polygon
* comprises of a list of {@code (x,y)}
* coordinate pairs, where each pair defines a <i>vertex</i> of the
* polygon, and two successive pairs are the endpoints of a
* line that is a side of the polygon. The first and final
* pairs of {@code (x,y)} points are joined by a line segment
* that closes the polygon. This {@code Polygon} is defined with
* an even-odd winding rule. See
* {@link java.awt.geom.PathIterator#WIND_EVEN_ODD WIND_EVEN_ODD}
* for a definition of the even-odd winding rule.
* This class's hit-testing methods, which include the
* {@code contains}, {@code intersects} and {@code inside}
* methods, use the <i>insideness</i> definition described in the
* {@link Shape} class comments.
*
* @author Sami Shaio
* @see Shape
* @author Herb Jellinek
* @since 1.0
*/
public class Polygon implements Shape, java.io.Serializable {
/**
* The total number of points. The value of {@code npoints}
* represents the number of valid points in this {@code Polygon}
* and might be less than the number of elements in
* {@link #xpoints xpoints} or {@link #ypoints ypoints}.
* This value can be NULL.
*
* @serial
* @see #addPoint(int, int)
* @since 1.0
*/
public int npoints;
/**
* The array of X coordinates. The number of elements in
* this array might be more than the number of X coordinates
* in this {@code Polygon}. The extra elements allow new points
* to be added to this {@code Polygon} without re-creating this
* array. The value of {@link #npoints npoints} is equal to the
* number of valid points in this {@code Polygon}.
*
* @serial
* @see #addPoint(int, int)
* @since 1.0
*/
public int xpoints[];
/**
* The array of Y coordinates. The number of elements in
* this array might be more than the number of Y coordinates
* in this {@code Polygon}. The extra elements allow new points
* to be added to this {@code Polygon} without re-creating this
* array. The value of {@code npoints} is equal to the
* number of valid points in this {@code Polygon}.
*
* @serial
* @see #addPoint(int, int)
* @since 1.0
*/
public int ypoints[];
/**
* The bounds of this {@code Polygon}.
* This value can be null.
*
* @serial
* @see #getBoundingBox()
* @see #getBounds()
* @since 1.0
*/
protected Rectangle bounds;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -6460061437900069969L;
/*
* Default length for xpoints and ypoints.
*/
private static final int MIN_LENGTH = 4;
/**
* Creates an empty polygon.
* @since 1.0
*/
public Polygon() {
xpoints = new int[MIN_LENGTH];
ypoints = new int[MIN_LENGTH];
}
/**
* Constructs and initializes a {@code Polygon} from the specified
* parameters.
* @param xpoints an array of X coordinates
* @param ypoints an array of Y coordinates
* @param npoints the total number of points in the
* {@code Polygon}
* @exception NegativeArraySizeException if the value of
* {@code npoints} is negative.
* @exception IndexOutOfBoundsException if {@code npoints} is
* greater than the length of {@code xpoints}
* or the length of {@code ypoints}.
* @exception NullPointerException if {@code xpoints} or
* {@code ypoints} is {@code null}.
* @since 1.0
*/
public Polygon(int xpoints[], int ypoints[], int npoints) {
// Fix 4489009: should throw IndexOutOfBoundsException instead
// of OutOfMemoryError if npoints is huge and > {x,y}points.length
if (npoints > xpoints.length || npoints > ypoints.length) {
throw new IndexOutOfBoundsException("npoints > xpoints.length || "+
"npoints > ypoints.length");
}
// Fix 6191114: should throw NegativeArraySizeException with
// negative npoints
if (npoints < 0) {
throw new NegativeArraySizeException("npoints < 0");
}
// Fix 6343431: Applet compatibility problems if arrays are not
// exactly npoints in length
this.npoints = npoints;
this.xpoints = Arrays.copyOf(xpoints, npoints);
this.ypoints = Arrays.copyOf(ypoints, npoints);
}
/**
* Resets this {@code Polygon} object to an empty polygon.
* The coordinate arrays and the data in them are left untouched
* but the number of points is reset to zero to mark the old
* vertex data as invalid and to start accumulating new vertex
* data at the beginning.
* All internally-cached data relating to the old vertices
* are discarded.
* Note that since the coordinate arrays from before the reset
* are reused, creating a new empty {@code Polygon} might
* be more memory efficient than resetting the current one if
* the number of vertices in the new polygon data is significantly
* smaller than the number of vertices in the data from before the
* reset.
* @see java.awt.Polygon#invalidate
* @since 1.4
*/
public void reset() {
npoints = 0;
bounds = null;
}
/**
* Invalidates or flushes any internally-cached data that depends
* on the vertex coordinates of this {@code Polygon}.
* This method should be called after any direct manipulation
* of the coordinates in the {@code xpoints} or
* {@code ypoints} arrays to avoid inconsistent results
* from methods such as {@code getBounds} or {@code contains}
* that might cache data from earlier computations relating to
* the vertex coordinates.
* @see java.awt.Polygon#getBounds
* @since 1.4
*/
public void invalidate() {
bounds = null;
}
/**
* Translates the vertices of the {@code Polygon} by
* {@code deltaX} along the x axis and by
* {@code deltaY} along the y axis.
* @param deltaX the amount to translate along the X axis
* @param deltaY the amount to translate along the Y axis
* @since 1.1
*/
public void translate(int deltaX, int deltaY) {
for (int i = 0; i < npoints; i++) {
xpoints[i] += deltaX;
ypoints[i] += deltaY;
}
if (bounds != null) {
bounds.translate(deltaX, deltaY);
}
}
/*
* Calculates the bounding box of the points passed to the constructor.
* Sets {@code bounds} to the result.
* @param xpoints[] array of <i>x</i> coordinates
* @param ypoints[] array of <i>y</i> coordinates
* @param npoints the total number of points
*/
void calculateBounds(int xpoints[], int ypoints[], int npoints) {
int boundsMinX = Integer.MAX_VALUE;
int boundsMinY = Integer.MAX_VALUE;
int boundsMaxX = Integer.MIN_VALUE;
int boundsMaxY = Integer.MIN_VALUE;
for (int i = 0; i < npoints; i++) {
int x = xpoints[i];
boundsMinX = Math.min(boundsMinX, x);
boundsMaxX = Math.max(boundsMaxX, x);
int y = ypoints[i];
boundsMinY = Math.min(boundsMinY, y);
boundsMaxY = Math.max(boundsMaxY, y);
}
bounds = new Rectangle(boundsMinX, boundsMinY,
boundsMaxX - boundsMinX,
boundsMaxY - boundsMinY);
}
/*
* Resizes the bounding box to accommodate the specified coordinates.
* @param x,&nbsp;y the specified coordinates
*/
void updateBounds(int x, int y) {
if (x < bounds.x) {
bounds.width = bounds.width + (bounds.x - x);
bounds.x = x;
}
else {
bounds.width = Math.max(bounds.width, x - bounds.x);
// bounds.x = bounds.x;
}
if (y < bounds.y) {
bounds.height = bounds.height + (bounds.y - y);
bounds.y = y;
}
else {
bounds.height = Math.max(bounds.height, y - bounds.y);
// bounds.y = bounds.y;
}
}
/**
* Appends the specified coordinates to this {@code Polygon}.
* <p>
* If an operation that calculates the bounding box of this
* {@code Polygon} has already been performed, such as
* {@code getBounds} or {@code contains}, then this
* method updates the bounding box.
* @param x the specified X coordinate
* @param y the specified Y coordinate
* @see java.awt.Polygon#getBounds
* @see java.awt.Polygon#contains
* @since 1.0
*/
public void addPoint(int x, int y) {
if (npoints >= xpoints.length || npoints >= ypoints.length) {
int newLength = npoints * 2;
// Make sure that newLength will be greater than MIN_LENGTH and
// aligned to the power of 2
if (newLength < MIN_LENGTH) {
newLength = MIN_LENGTH;
} else if ((newLength & (newLength - 1)) != 0) {
newLength = Integer.highestOneBit(newLength);
}
xpoints = Arrays.copyOf(xpoints, newLength);
ypoints = Arrays.copyOf(ypoints, newLength);
}
xpoints[npoints] = x;
ypoints[npoints] = y;
npoints++;
if (bounds != null) {
updateBounds(x, y);
}
}
/**
* Gets the bounding box of this {@code Polygon}.
* The bounding box is the smallest {@link Rectangle} whose
* sides are parallel to the x and y axes of the
* coordinate space, and can completely contain the {@code Polygon}.
* @return a {@code Rectangle} that defines the bounds of this
* {@code Polygon}.
* @since 1.1
*/
public Rectangle getBounds() {
return getBoundingBox();
}
/**
* Returns the bounds of this {@code Polygon}.
* @return the bounds of this {@code Polygon}.
* @deprecated As of JDK version 1.1,
* replaced by {@code getBounds()}.
* @since 1.0
*/
@Deprecated
public Rectangle getBoundingBox() {
if (npoints == 0) {
return new Rectangle();
}
if (bounds == null) {
calculateBounds(xpoints, ypoints, npoints);
}
return bounds.getBounds();
}
/**
* Determines whether the specified {@link Point} is inside this
* {@code Polygon}.
* @param p the specified {@code Point} to be tested
* @return {@code true} if the {@code Polygon} contains the
* {@code Point}; {@code false} otherwise.
* @see #contains(double, double)
* @since 1.0
*/
public boolean contains(Point p) {
return contains(p.x, p.y);
}
/**
* Determines whether the specified coordinates are inside this
* {@code Polygon}.
*
* @param x the specified X coordinate to be tested
* @param y the specified Y coordinate to be tested
* @return {@code true} if this {@code Polygon} contains
* the specified coordinates {@code (x,y)};
* {@code false} otherwise.
* @see #contains(double, double)
* @since 1.1
*/
public boolean contains(int x, int y) {
return contains((double) x, (double) y);
}
/**
* Determines whether the specified coordinates are contained in this
* {@code Polygon}.
* @param x the specified X coordinate to be tested
* @param y the specified Y coordinate to be tested
* @return {@code true} if this {@code Polygon} contains
* the specified coordinates {@code (x,y)};
* {@code false} otherwise.
* @see #contains(double, double)
* @deprecated As of JDK version 1.1,
* replaced by {@code contains(int, int)}.
* @since 1.0
*/
@Deprecated
public boolean inside(int x, int y) {
return contains((double) x, (double) y);
}
/**
* {@inheritDoc}
* @since 1.2
*/
public Rectangle2D getBounds2D() {
return getBounds();
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean contains(double x, double y) {
if (npoints <= 2 || !getBoundingBox().contains(x, y)) {
return false;
}
int hits = 0;
int lastx = xpoints[npoints - 1];
int lasty = ypoints[npoints - 1];
int curx, cury;
// Walk the edges of the polygon
for (int i = 0; i < npoints; lastx = curx, lasty = cury, i++) {
curx = xpoints[i];
cury = ypoints[i];
if (cury == lasty) {
continue;
}
int leftx;
if (curx < lastx) {
if (x >= lastx) {
continue;
}
leftx = curx;
} else {
if (x >= curx) {
continue;
}
leftx = lastx;
}
double test1, test2;
if (cury < lasty) {
if (y < cury || y >= lasty) {
continue;
}
if (x < leftx) {
hits++;
continue;
}
test1 = x - curx;
test2 = y - cury;
} else {
if (y < lasty || y >= cury) {
continue;
}
if (x < leftx) {
hits++;
continue;
}
test1 = x - lastx;
test2 = y - lasty;
}
if (test1 < (test2 / (lasty - cury) * (lastx - curx))) {
hits++;
}
}
return ((hits & 1) != 0);
}
private Crossings getCrossings(double xlo, double ylo,
double xhi, double yhi)
{
Crossings cross = new Crossings.EvenOdd(xlo, ylo, xhi, yhi);
int lastx = xpoints[npoints - 1];
int lasty = ypoints[npoints - 1];
int curx, cury;
// Walk the edges of the polygon
for (int i = 0; i < npoints; i++) {
curx = xpoints[i];
cury = ypoints[i];
if (cross.accumulateLine(lastx, lasty, curx, cury)) {
return null;
}
lastx = curx;
lasty = cury;
}
return cross;
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean contains(Point2D p) {
return contains(p.getX(), p.getY());
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean intersects(double x, double y, double w, double h) {
if (npoints <= 0 || !getBoundingBox().intersects(x, y, w, h)) {
return false;
}
Crossings cross = getCrossings(x, y, x+w, y+h);
return (cross == null || !cross.isEmpty());
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean intersects(Rectangle2D r) {
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean contains(double x, double y, double w, double h) {
if (npoints <= 0 || !getBoundingBox().intersects(x, y, w, h)) {
return false;
}
Crossings cross = getCrossings(x, y, x+w, y+h);
return (cross != null && cross.covers(y, y+h));
}
/**
* {@inheritDoc}
* @since 1.2
*/
public boolean contains(Rectangle2D r) {
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
/**
* Returns an iterator object that iterates along the boundary of this
* {@code Polygon} and provides access to the geometry
* of the outline of this {@code Polygon}. An optional
* {@link AffineTransform} can be specified so that the coordinates
* returned in the iteration are transformed accordingly.
* @param at an optional {@code AffineTransform} to be applied to the
* coordinates as they are returned in the iteration, or
* {@code null} if untransformed coordinates are desired
* @return a {@link PathIterator} object that provides access to the
* geometry of this {@code Polygon}.
* @since 1.2
*/
public PathIterator getPathIterator(AffineTransform at) {
return new PolygonPathIterator(this, at);
}
/**
* Returns an iterator object that iterates along the boundary of
* the {@code Shape} and provides access to the geometry of the
* outline of the {@code Shape}. Only SEG_MOVETO, SEG_LINETO, and
* SEG_CLOSE point types are returned by the iterator.
* Since polygons are already flat, the {@code flatness} parameter
* is ignored. An optional {@code AffineTransform} can be specified
* in which case the coordinates returned in the iteration are transformed
* accordingly.
* @param at an optional {@code AffineTransform} to be applied to the
* coordinates as they are returned in the iteration, or
* {@code null} if untransformed coordinates are desired
* @param flatness the maximum amount that the control points
* for a given curve can vary from collinear before a subdivided
* curve is replaced by a straight line connecting the
* endpoints. Since polygons are already flat the
* {@code flatness} parameter is ignored.
* @return a {@code PathIterator} object that provides access to the
* {@code Shape} object's geometry.
* @since 1.2
*/
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return getPathIterator(at);
}
class PolygonPathIterator implements PathIterator {
Polygon poly;
AffineTransform transform;
int index;
public PolygonPathIterator(Polygon pg, AffineTransform at) {
poly = pg;
transform = at;
if (pg.npoints == 0) {
// Prevent a spurious SEG_CLOSE segment
index = 1;
}
}
/**
* Returns the winding rule for determining the interior of the
* path.
* @return an integer representing the current winding rule.
* @see PathIterator#WIND_NON_ZERO
*/
public int getWindingRule() {
return WIND_EVEN_ODD;
}
/**
* Tests if there are more points to read.
* @return {@code true} if there are more points to read;
* {@code false} otherwise.
*/
public boolean isDone() {
return index > poly.npoints;
}
/**
* Moves the iterator forwards, along the primary direction of
* traversal, to the next segment of the path when there are
* more points in that direction.
*/
public void next() {
index++;
}
/**
* Returns the coordinates and type of the current path segment in
* the iteration.
* The return value is the path segment type:
* SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.
* A {@code float} array of length 2 must be passed in and
* can be used to store the coordinates of the point(s).
* Each point is stored as a pair of {@code float} x,&nbsp;y
* coordinates. SEG_MOVETO and SEG_LINETO types return one
* point, and SEG_CLOSE does not return any points.
* @param coords a {@code float} array that specifies the
* coordinates of the point(s)
* @return an integer representing the type and coordinates of the
* current path segment.
* @see PathIterator#SEG_MOVETO
* @see PathIterator#SEG_LINETO
* @see PathIterator#SEG_CLOSE
*/
public int currentSegment(float[] coords) {
if (index >= poly.npoints) {
return SEG_CLOSE;
}
coords[0] = poly.xpoints[index];
coords[1] = poly.ypoints[index];
if (transform != null) {
transform.transform(coords, 0, coords, 0, 1);
}
return (index == 0 ? SEG_MOVETO : SEG_LINETO);
}
/**
* Returns the coordinates and type of the current path segment in
* the iteration.
* The return value is the path segment type:
* SEG_MOVETO, SEG_LINETO, or SEG_CLOSE.
* A {@code double} array of length 2 must be passed in and
* can be used to store the coordinates of the point(s).
* Each point is stored as a pair of {@code double} x,&nbsp;y
* coordinates.
* SEG_MOVETO and SEG_LINETO types return one point,
* and SEG_CLOSE does not return any points.
* @param coords a {@code double} array that specifies the
* coordinates of the point(s)
* @return an integer representing the type and coordinates of the
* current path segment.
* @see PathIterator#SEG_MOVETO
* @see PathIterator#SEG_LINETO
* @see PathIterator#SEG_CLOSE
*/
public int currentSegment(double[] coords) {
if (index >= poly.npoints) {
return SEG_CLOSE;
}
coords[0] = poly.xpoints[index];
coords[1] = poly.ypoints[index];
if (transform != null) {
transform.transform(coords, 0, coords, 0, 1);
}
return (index == 0 ? SEG_MOVETO : SEG_LINETO);
}
}
}

View file

@ -0,0 +1,243 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.PopupMenuPeer;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
/**
* A class that implements a menu which can be dynamically popped up
* at a specified position within a component.
* <p>
* As the inheritance hierarchy implies, a {@code PopupMenu}
* can be used anywhere a {@code Menu} can be used.
* However, if you use a {@code PopupMenu} like a {@code Menu}
* (e.g., you add it to a {@code MenuBar}), then you <b>cannot</b>
* call {@code show} on that {@code PopupMenu}.
*
* @author Amy Fowler
*/
public class PopupMenu extends Menu {
private static final String base = "popup";
static int nameCounter = 0;
transient volatile boolean isTrayIconPopup;
static {
AWTAccessor.setPopupMenuAccessor(
new AWTAccessor.PopupMenuAccessor() {
public boolean isTrayIconPopup(PopupMenu popupMenu) {
return popupMenu.isTrayIconPopup;
}
});
}
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -4620452533522760060L;
/**
* Creates a new popup menu with an empty name.
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public PopupMenu() throws HeadlessException {
this("");
}
/**
* Creates a new popup menu with the specified name.
*
* @param label a non-{@code null} string specifying
* the popup menu's label
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public PopupMenu(String label) throws HeadlessException {
super(label);
}
/**
* {@inheritDoc}
*/
public MenuContainer getParent() {
if (isTrayIconPopup) {
return null;
}
return super.getParent();
}
/**
* Constructs a name for this {@code MenuComponent}.
* Called by {@code getName} when the name is {@code null}.
*/
String constructComponentName() {
synchronized (PopupMenu.class) {
return base + nameCounter++;
}
}
/**
* Creates the popup menu's peer.
* The peer allows us to change the appearance of the popup menu without
* changing any of the popup menu's functionality.
*/
public void addNotify() {
synchronized (getTreeLock()) {
// If our parent is not a Component, then this PopupMenu is
// really just a plain, old Menu.
if (parent != null && !(parent instanceof Component)) {
super.addNotify();
}
else {
if (peer == null)
peer = getComponentFactory().createPopupMenu(this);
int nitems = getItemCount();
for (int i = 0 ; i < nitems ; i++) {
MenuItem mi = getItem(i);
mi.parent = this;
mi.addNotify();
}
}
}
}
/**
* Shows the popup menu at the x, y position relative to an origin
* component.
* The origin component must be contained within the component
* hierarchy of the popup menu's parent. Both the origin and the parent
* must be showing on the screen for this method to be valid.
* <p>
* If this {@code PopupMenu} is being used as a {@code Menu}
* (i.e., it has a non-{@code Component} parent),
* then you cannot call this method on the {@code PopupMenu}.
*
* @param origin the component which defines the coordinate space
* @param x the x coordinate position to popup the menu
* @param y the y coordinate position to popup the menu
* @exception NullPointerException if the parent is {@code null}
* @exception IllegalArgumentException if this {@code PopupMenu}
* has a non-{@code Component} parent
* @exception IllegalArgumentException if the origin is not in the
* parent's hierarchy
* @exception RuntimeException if the parent is not showing on screen
*/
@SuppressWarnings("deprecation")
public void show(Component origin, int x, int y) {
// Use localParent for thread safety.
MenuContainer localParent = parent;
if (localParent == null) {
throw new NullPointerException("parent is null");
}
if (!(localParent instanceof Component)) {
throw new IllegalArgumentException(
"PopupMenus with non-Component parents cannot be shown");
}
Component compParent = (Component)localParent;
//Fixed 6278745: Incorrect exception throwing in PopupMenu.show() method
//Exception was not thrown if compParent was not equal to origin and
//was not Container
if (compParent != origin) {
if (compParent instanceof Container) {
if (!((Container)compParent).isAncestorOf(origin)) {
throw new IllegalArgumentException("origin not in parent's hierarchy");
}
} else {
throw new IllegalArgumentException("origin not in parent's hierarchy");
}
}
if (compParent.peer == null || !compParent.isShowing()) {
throw new RuntimeException("parent not showing on screen");
}
if (peer == null) {
addNotify();
}
synchronized (getTreeLock()) {
if (peer != null) {
((PopupMenuPeer)peer).show(
new Event(origin, 0, Event.MOUSE_DOWN, x, y, 0, 0));
}
}
}
/////////////////
// Accessibility support
////////////////
/**
* Gets the {@code AccessibleContext} associated with this
* {@code PopupMenu}.
*
* @return the {@code AccessibleContext} of this
* {@code PopupMenu}
* @since 1.3
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTPopupMenu();
}
return accessibleContext;
}
/**
* Inner class of PopupMenu used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by menu component developers.
* <p>
* The class used to obtain the accessible role for this object.
* @since 1.3
*/
protected class AccessibleAWTPopupMenu extends AccessibleAWTMenu
{
/*
* JDK 1.3 serialVersionUID
*/
private static final long serialVersionUID = -4282044795947239955L;
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.POPUP_MENU;
}
} // class AccessibleAWTPopupMenu
}

Some files were not shown because too many files have changed in this diff Show more