/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.awt;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.MouseDragGestureRecognizer;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.peer.ButtonPeer;
import java.awt.peer.CanvasPeer;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.peer.CheckboxPeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ChoicePeer;
import java.awt.peer.DialogPeer;
import java.awt.peer.FileDialogPeer;
import java.awt.peer.FontPeer;
import java.awt.peer.FramePeer;
import java.awt.peer.LabelPeer;
import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.ScrollPanePeer;
import java.awt.peer.ScrollbarPeer;
import java.awt.peer.TextAreaPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.WindowPeer;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
public abstract class Toolkit {
private static final String RESOURCE_PATH = "mika.awt.resources.AWTProperties"; //$NON-NLS-1$
private static final ResourceBundle properties = loadResources(RESOURCE_PATH);
// [CG 20120817] Harmony delegates this to a ContextStorage object
// TODO: tell synchronizer about our dispatch thread so that it can give it priority.
// protected static final Synchronizer synchronizer = new Synchronizer();
private boolean bDynamicLayoutSet = true;
KeyboardFocusManager currentKeyboardFocusManager;
private class AWTTreeLock {
}
final Object awtTreeLock = new AWTTreeLock();
/**
* The set of desktop properties that user set directly.
*/
private final HashSet userPropSet = new HashSet();
protected final Map desktopProperties;
protected final PropertyChangeSupport desktopPropsSupport;
// [CG 20120819] Perhaps a BitSet would be better?
private HashMap keyLockingState = new HashMap();
/*
* A lot of methods must throw HeadlessException
* if <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
*/
static void checkHeadless() throws HeadlessException {
if (GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance())
throw new HeadlessException();
}
final void lockAWT() {
Synchronizer.staticLockAWT();
}
final void unlockAWT() {
Synchronizer.staticUnlockAWT();
}
/**
* InvokeAndWait under AWT lock. W/o this method system can hang up.
* Added to support modality (Dialog.show() & PopupMenu.show()) from
* not event dispatch thread. Use in other cases is not recommended.
*
* Still can be called only for whole API methods that
* cannot be called from other classes API methods.
* Examples:
* show() for modal dialogs - correct, only user can call it,
* directly or through setVisible(true)
* setBounds() for components - incorrect, setBounds()
* can be called from layoutContainer()
* for layout managers
final void unsafeInvokeAndWait(Runnable runnable) throws InterruptedException,
InvocationTargetException {
synchronizer.storeStateAndFree();
try {
EventQueue.invokeAndWait(runnable);
} finally {
synchronizer.lockAndRestoreState();
}
}
final Synchronizer getSynchronizer() {
return synchronizer;
}
*/
public static String getProperty(String propName, String defVal) {
if (propName == null) {
throw new NullPointerException("Property name is null");
}
Synchronizer.staticLockAWT();
try {
String retVal = null;
if (properties != null) {
try {
retVal = properties.getString(propName);
} catch (MissingResourceException e) {
} catch (ClassCastException e) {
}
}
return (retVal == null) ? defVal : retVal;
} finally {
Synchronizer.staticUnlockAWT();
}
}
public static Toolkit getDefaultToolkit() {
String className = GetSystemProperty.TOOLKIT;
if (className != null) {
// class to be loaded needs to be on bootstrap class path!
try {
Class toolkitClass = Class.forName(className);
}
catch (Throwable t) {
throw new AWTError("Unable to load default toolkit " + className + " on bootclasspath - got " + t);
}
}
Toolkit toolkit = com.acunia.wonka.rudolph.Toolkit.getInstance();
return (java.awt.Toolkit) toolkit;
}
private static ResourceBundle loadResources(String path) {
try {
return ResourceBundle.getBundle(path);
} catch (MissingResourceException e) {
return null;
}
}
public Toolkit() {
desktopProperties = new HashMap();
desktopPropsSupport = new PropertyChangeSupport(this);
init();
}
void init() {
lockAWT();
try {
new EventQueue(this); // create the system EventQueue
} finally {
unlockAWT();
}
}
public abstract void sync();
protected abstract TextAreaPeer createTextArea(TextArea textArea) throws HeadlessException;
public abstract int checkImage(Image image, int w, int h, ImageObserver observer);
protected abstract DialogPeer createDialog(Dialog dialog) throws HeadlessException;
public abstract Image createImage(ImageProducer producer);
public abstract Image createImage(String filename);
public abstract Image createImage(byte[] imageData, int offset, int count);
public abstract Image createImage(URL url);
public abstract ColorModel getColorModel() throws HeadlessException;
/**
* @deprecated
*/
public abstract FontMetrics getFontMetrics(Font font);
public abstract boolean prepareImage(Image image, int w, int h, ImageObserver observer);
public abstract void beep();
protected abstract ButtonPeer createButton(Button button) throws HeadlessException;
protected abstract CanvasPeer createCanvas(Canvas canvas);
protected abstract CheckboxPeer createCheckbox(Checkbox checkbox);
protected abstract CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem checkBoxMenuItem) throws HeadlessException;
protected abstract ChoicePeer createChoice(Choice choice) throws HeadlessException;
public abstract DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException;
protected abstract FileDialogPeer createFileDialog(FileDialog fileDialog) throws HeadlessException;
protected abstract FramePeer createFrame(Frame frame) throws HeadlessException;
protected abstract LabelPeer createLabel(Label label) throws HeadlessException;
protected abstract ListPeer createList(List list) throws HeadlessException;
protected abstract MenuPeer createMenu(Menu menu) throws HeadlessException;
protected abstract MenuBarPeer createMenuBar(MenuBar menuBar) throws HeadlessException;
protected abstract MenuItemPeer createMenuItem(MenuItem menuItem) throws HeadlessException;
protected abstract PanelPeer createPanel(Panel panel);
protected abstract PopupMenuPeer createPopupMenu(PopupMenu popupMenu) throws HeadlessException;
protected abstract ScrollPanePeer createScrollPane(ScrollPane scrollPane) throws HeadlessException;
protected abstract ScrollbarPeer createScrollbar(Scrollbar scrollbar) throws HeadlessException;
protected abstract TextFieldPeer createTextField(TextField textField) throws HeadlessException;
protected abstract WindowPeer createWindow(Window window) throws HeadlessException;
/**
* @deprecated
*/
public abstract String[] getFontList();
/**
* @deprecated
*/
protected abstract FontPeer getFontPeer(String a0, int a1);
public abstract Image getImage(String filename);
public abstract Image getImage(URL url);
public abstract PrintJob getPrintJob(Frame frame, String title, Properties properties);
public abstract int getScreenResolution();
public abstract Dimension getScreenSize() throws HeadlessException;
public abstract Clipboard getSystemClipboard() throws HeadlessException;
protected abstract EventQueue getSystemEventQueueImpl();
public void addPropertyChangeListener(String propName, PropertyChangeListener l) {
lockAWT();
try {
if (desktopProperties.isEmpty()) {
initializeDesktopProperties();
}
} finally {
unlockAWT();
}
if (l != null) { // there is no guarantee that null listener will not be added
desktopPropsSupport.addPropertyChangeListener(propName, l);
}
}
// FIXME The return type here is wrong - should be LightweightPeer.
// However this is not compatible with the way the method is [ab]used by Rudolph.
protected ComponentPeer createComponent(Component comp) {
throw new RuntimeException("not implemented");
}
public Image createImage(byte[] imagedata) {
return createImage(imagedata, 0, imagedata.length);
}
protected static Container getNativeContainer(Component c) {
Synchronizer.staticLockAWT();
try {
//TODO: implement
throw new RuntimeException("not implemented");
} finally {
Synchronizer.staticUnlockAWT();
}
}
public PropertyChangeListener[] getPropertyChangeListeners() {
return desktopPropsSupport.getPropertyChangeListeners();
}
public PropertyChangeListener[] getPropertyChangeListeners(String propName) {
return desktopPropsSupport.getPropertyChangeListeners(propName);
}
public void removePropertyChangeListener(String propName, PropertyChangeListener l) {
desktopPropsSupport.removePropertyChangeListener(propName, l);
}
public Cursor createCustomCursor(Image img, Point hotSpot, String name)
throws IndexOutOfBoundsException, HeadlessException {
lockAWT();
try {
int w = img.getWidth(null);
int h = img.getHeight(null);
if (w < 0 || h < 0) {
// Fix for HARMONY-4491
hotSpot.x = 0;
hotSpot.y = 0;
} else if (hotSpot.x < 0 || hotSpot.x >= w
|| hotSpot.y < 0 || hotSpot.y >= h) {
throw new IndexOutOfBoundsException("invalid hotSpot");
}
// return new Cursor(name, img, hotSpot);
return new com.acunia.wonka.rudolph.CustomCursor(img, hotSpot, name);
} finally {
unlockAWT();
}
}
// public DragGestureRecognizer createDragGestureRecognizer(Class abstractRecognizerClass, DragSource ds,
// Component c, int srcActions, DragGestureListener dgl){
// if(java.awt.dnd.MouseDragGestureRecognizer.class.isAssignableFrom(abstractRecognizerClass)){
// com.acunia.wonka.rudolph.MouseDragGestureRecognizer mgr = new com.acunia.wonka.rudolph.MouseDragGestureRecognizer(ds,c,srcActions, dgl);
// return ((java.awt.dnd.MouseDragGestureRecognizer) mgr);
// }
// com.acunia.wonka.rudolph.DragGestureRecognizer dgr = new com.acunia.wonka.rudolph.DragGestureRecognizer(ds,c,srcActions, dgl);
// return ((java.awt.dnd.DragGestureRecognizer) dgr);
// }
public DragGestureRecognizer createDragGestureRecognizer(
Class recognizerAbstractClass, DragSource ds, Component c, int srcActions,
DragGestureListener dgl) {
if (recognizerAbstractClass == null) {
return null;
}
if (recognizerAbstractClass.isAssignableFrom(MouseDragGestureRecognizer.class)) {
return (DragGestureRecognizer) new DefaultMouseDragGestureRecognizer(ds, c, srcActions, dgl);
}
return null;
}
public Dimension getBestCursorSize(int prefWidth, int prefHeight) throws HeadlessException {
// custom cursors not supported
return new Dimension(0, 0);
}
public final Object getDesktopProperty(String propName) {
lockAWT();
try {
if (desktopProperties.isEmpty()) {
initializeDesktopProperties();
}
if (propName.equals("awt.dynamicLayoutSupported")) { //$NON-NLS-1$
// dynamicLayoutSupported is special case
return Boolean.valueOf(isDynamicLayoutActive());
}
Object val = desktopProperties.get(propName);
if (val == null) {
// try to lazily load prop value
// just for compatibility, our lazilyLoad is empty
val = lazilyLoadDesktopProperty(propName);
}
return val;
} finally {
unlockAWT();
}
}
public boolean getLockingKeyState(int keyCode) throws UnsupportedOperationException {
if (keyCode != KeyEvent.VK_CAPS_LOCK &&
keyCode != KeyEvent.VK_NUM_LOCK &&
keyCode != KeyEvent.VK_SCROLL_LOCK &&
keyCode != KeyEvent.VK_KANA_LOCK) {
throw new IllegalArgumentException();
}
return ((Boolean) keyLockingState.get(new Integer(keyCode))).booleanValue();
}
public int getMaximumCursorColors() throws HeadlessException {
// custom cursors not supported
return 0;
}
public int getMenuShortcutKeyMask() throws HeadlessException {
return InputEvent.CTRL_MASK;
}
// public PrintJob getPrintJob(Frame a0, String a1, JobAttributes a2, PageAttributes a3) throws NotImplementedException {
// throw RuntimeException("not implemented");
// }
public Insets getScreenInsets(GraphicsConfiguration gc) throws HeadlessException {
if (gc == null) {
throw new NullPointerException();
}
lockAWT();
try {
return new Insets(0, 0, 0, 0); //TODO: get real screen insets
} finally {
unlockAWT();
}
}
public final EventQueue getSystemEventQueue() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkAwtEventQueueAccess();
}
return getSystemEventQueueImpl();
}
public Clipboard getSystemSelection() throws HeadlessException {
// TODO
return null;
/*
lockAWT();
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSystemClipboardAccess();
}
if (systemSelection == null) {
systemSelection = dtk.getNativeSelection();
}
return systemSelection;
} finally {
unlockAWT();
}
*/
}
protected void initializeDesktopProperties() {
lockAWT();
try {
//wtk.getSystemProperties().init(desktopProperties);
} finally {
unlockAWT();
}
}
public boolean isDynamicLayoutActive() throws HeadlessException {
lockAWT();
try {
// always return true
return true;
} finally {
unlockAWT();
}
}
protected boolean isDynamicLayoutSet() throws HeadlessException {
lockAWT();
try {
return bDynamicLayoutSet;
} finally {
unlockAWT();
}
}
public boolean isFrameStateSupported(int state) throws HeadlessException {
// not supported by rudolph
return false;
}
protected Object lazilyLoadDesktopProperty(String propName) {
return null;
}
protected void loadSystemColors(int[] colors) throws HeadlessException {
// not supported by rudolph
}
protected final void setDesktopProperty(String propName, Object value) {
Object oldVal;
lockAWT();
try {
oldVal = getDesktopProperty(propName);
userPropSet.add(propName);
desktopProperties.put(propName, value);
} finally {
unlockAWT();
}
desktopPropsSupport.firePropertyChange(propName, oldVal, value);
}
public void setDynamicLayout(boolean dynamic) throws HeadlessException {
lockAWT();
try {
bDynamicLayoutSet = dynamic;
} finally {
unlockAWT();
}
}
public void setLockingKeyState(int keyCode, boolean on) throws UnsupportedOperationException {
if (keyCode != KeyEvent.VK_CAPS_LOCK &&
keyCode != KeyEvent.VK_NUM_LOCK &&
keyCode != KeyEvent.VK_SCROLL_LOCK &&
keyCode != KeyEvent.VK_KANA_LOCK) {
throw new IllegalArgumentException();
}
keyLockingState.put(new Integer(keyCode), Boolean.valueOf(on));
}
public void addAWTEventListener(AWTEventListener listener, long eventMask) {
// TODO
throw new RuntimeException("not implemented");
/*
lockAWT();
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(awtEventsManager.permission);
}
awtEventsManager.addAWTEventListener(listener, eventMask);
} finally {
unlockAWT();
}
*/
}
public void removeAWTEventListener(AWTEventListener listener) {
// TODO
throw new RuntimeException("not implemented");
/*
lockAWT();
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(awtEventsManager.permission);
}
awtEventsManager.removeAWTEventListener(listener);
} finally {
unlockAWT();
}
*/
}
public AWTEventListener[] getAWTEventListeners() {
// TODO
throw new RuntimeException("not implemented");
/*
lockAWT();
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(awtEventsManager.permission);
}
return awtEventsManager.getAWTEventListeners();
} finally {
unlockAWT();
}
*/
}
public AWTEventListener[] getAWTEventListeners(long eventMask) {
// TODO
throw new RuntimeException("not implemented");
/*
lockAWT();
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(awtEventsManager.permission);
}
return awtEventsManager.getAWTEventListeners(eventMask);
} finally {
unlockAWT();
}
*/
}
void dispatchAWTEvent(AWTEvent event) {
// TODO
throw new RuntimeException("not implemented");
/*
awtEventsManager.dispatchAWTEvent(event);
*/
}
}