abstracttoolkit.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 949 行 · 第 1/3 页

JAVA
949
字号
/* class Toolkit
 *
 * Copyright (C) 2001, 2002, 2003  R M Pitman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * Modified Jul 14, 2003 by Tadpole Computer, Inc.
 * Modifications Copyright 2003 by Tadpole Computer, Inc.
 *
 * Modifications are hereby licensed to all parties at no charge under
 * the same terms as the original.
 *
 * Modifications include minor bug fixes, and moving the handling of
 * endwin() into an atexit(3) function call.
 */

package charva.awt;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Vector;

import charva.awt.event.AWTEvent;
import charva.awt.event.KeyEvent;
import charva.awt.event.MouseEvent;

/**
 * The Toolkit class provides the interface to the "ncurses" library
 * functions. Exceptions and error messages are reported to the
 * logfile $HOME/charva.log.<p>
 *
 * The default colors are white foreground and black background, but
 * these defaults can be modified by changing the static variables
 * _defaultForeground and _defaultBackground.
 * @author
 * @author Levente S醤tha
 */
public abstract class AbstractToolkit
        implements Runnable {

    private boolean keyboardReaderRunning = false;
    private Thread keyboardReader;

    public EventQueue getSystemEventQueue() {
        return _evtQueue;
    }

    /**
     * Get the top window of the window stack.
     */
    public Window getTopWindow() {
        return (Window) _windowList.lastElement();
    }

    /**
     * Returns true if the specified window is currently displayed.
     */
    public boolean isWindowDisplayed(Window window_) {
        boolean answer = false;
        synchronized (_windowList) {
            for (int i = 0; i < _windowList.size(); i++) {
                Window w = (Window) _windowList.elementAt(i);
                if (w == window_) {
                    answer = true;
                    break;
                }
            }
        }
        return answer;
    }

    /**
     * Processes a keystroke that was pressed in the currently displayed
     * window.
     * @param key_ the keystroke that was pressed. If it is less than
     * 256, it is a ASCII or ISO8859-1 code; otherwise it is a function
     * key as defined in the "VK_*" values.
     */
    public void fireKeystroke(int key_) {
        Component currentFocus;

        synchronized (_windowList) {

            Window sourcewin = getTopWindow();

            /* Get the (non-Container) component within the source window
             * that generated the keystroke.
             */
            currentFocus = sourcewin.getCurrentFocus();
            while (currentFocus instanceof Container) {
                currentFocus = ((Container) currentFocus).getCurrentFocus();
            }
        }

        fireKeystroke(key_, currentFocus);
    }

    /**
     * Process a keystroke as if it was pressed while the focus was in the
     * specified component.
     * @param key_ the keystroke that was pressed. If it is less than
     * 256, it is an ASCII or ISO8859-1 code; otherwise it is a function
     * key as defined in the "VK_*" values.
     */
    public void fireKeystroke(int key_, Component source_) {
        int id;
        if (key_ > 255 || key_ < ' ')
            id = AWTEvent.KEY_PRESSED;
        else
            id = AWTEvent.KEY_TYPED;

        _evtQueue.postEvent(new KeyEvent(key_, id, source_));
    }

    /**
     * Processes the mouse-click specified by mouse_info.
     * Note that we disable mouse-click resolution in the ncurses library
     * by setting "mouse_interval" to 0, because it doesn't work properly.
     * Instead we do it in this method.
     */
    public void fireMouseEvent(MouseEventInfo mouse_info) {
        Window top_window = getTopWindow();
        Point origin = top_window.getLocation();
        int x = mouse_info.x;
        int y = mouse_info.y;
        int button = 0;
        int modifiers = 0;
        switch (mouse_info.button) {
            case BUTTON1_PRESSED:
                button = MouseEvent.BUTTON1;
                modifiers = MouseEvent.MOUSE_PRESSED;
                break;
            case BUTTON1_RELEASED:
                button = MouseEvent.BUTTON1;
                modifiers = MouseEvent.MOUSE_RELEASED;
                break;
            case BUTTON2_PRESSED:
                button = MouseEvent.BUTTON2;
                modifiers = MouseEvent.MOUSE_PRESSED;
                break;
            case BUTTON2_RELEASED:
                button = MouseEvent.BUTTON2;
                modifiers = MouseEvent.MOUSE_RELEASED;
                break;
            case BUTTON3_PRESSED:
                button = MouseEvent.BUTTON3;
                modifiers = MouseEvent.MOUSE_PRESSED;
                break;
            case BUTTON3_RELEASED:
                button = MouseEvent.BUTTON3;
                modifiers = MouseEvent.MOUSE_RELEASED;
                break;
        }

        // If the mouse has been pressed outside the top-level window
        if (!top_window.contains(x, y)) {
            if (modifiers == MouseEvent.MOUSE_PRESSED)
                beep();
            return;
        }

        if (modifiers == MouseEvent.MOUSE_PRESSED)
            _lastMousePressTime = System.currentTimeMillis();

        Component component =
                top_window.getComponentAt(x - origin.x, y - origin.y);

        if (component != null) {
            _evtQueue.postEvent(
                    new MouseEvent(component, modifiers, x, y, 0, button));

            // If this is a button-release within 400 msec of the corresponding
            // button-press.
            long current_time = System.currentTimeMillis();
            if (modifiers == MouseEvent.MOUSE_RELEASED &&
                    current_time - _lastMousePressTime < 400L) {

                _evtQueue.postEvent(new MouseEvent(
                        component, MouseEvent.MOUSE_CLICKED, x, y, 1, button));

                // Check for a double-click.
                if (current_time - _lastMouseClickTime < 500L) {
                    _evtQueue.postEvent(new MouseEvent(
                            component, MouseEvent.MOUSE_CLICKED, x, y, 2, button));
                }
                _lastMouseClickTime = current_time;
            }
        }
    }

    /** Start a thread that reads characters from the keyboard and
     * writes them to the event-queue.  Make it a daemon thread
     * so that the program will exit when the main thread ends.
     */
    public void startKeyboardReader() {
        if (keyboardReader == null) {
            keyboardReader = new Thread(this);
            keyboardReader.setDaemon(true);
            keyboardReader.setName("keyboard reader");
            keyboardReader.start();
        }
    }

    public synchronized boolean isKeyboardReaderRunning() {
        return keyboardReaderRunning;
    }

    public void setKeyboardReaderRunning(boolean keyboardReaderRunning) {
        this.keyboardReaderRunning = keyboardReaderRunning;
    }

    /**
     * The keyboard-reading thread just reads keystrokes, converts
     * them to KeyEvent objects, and posts the events onto the EventQueue.
     */
    public void run() {
        keyboardReaderRunning = true;
        StringBuffer scriptbuf = new StringBuffer();

        try {
            while (isKeyboardReaderRunning()) {
                int key = readKey();

                if(key == -1) break;

                MouseEventInfo mouse_info = null;

                /* The possibility of an error return from readKey() was
                 * pointed out by Uwe Buettner.
                 */
                if (key == -1) {
                    System.err.println("end of file on keyboard input");
                    System.exit(-1);
                }

                /* Note that if the "kent" key is defined, ncurses returns
                 * VK_ENTER when the ENTER key is pressed; but some terminfo
                 * files don't define the "kent" capability.
                 */
                else if (key == '\n' || key == '\r')
                    key = KeyEvent.VK_ENTER;

                /* Likewise, some versions of curses don't map '\b' to
                 * VK_BACK_SPACE (Solaris at least); this works around
                 * that.  (I can't imagine anyone wanting \b to be mapped
                 * to anything else.  If they do, then they should set it
                 * up that way in the terminfo database.)
                 */
                else if (key == '\b')
                    key = KeyEvent.VK_BACK_SPACE;

                if (key == KEY_MOUSE) {
                    mouse_info = getMouseEventInfo();
                    fireMouseEvent(mouse_info);
                } else {
                    fireKeystroke(key);
                }

                /* If script recording is on.
                 */
                if (_scriptPrintStream != null) {
                    scriptbuf.setLength(0);

                    /* Compute the elapsed time since the last keystroke.
                    */
                    long current = System.currentTimeMillis();
                    long elapsed = 1000;    // initial delay of 1 sec
                    if (_prevTimeMillis != 0)
                        elapsed = current - _prevTimeMillis;
                    _prevTimeMillis = current;
                    scriptbuf.append(elapsed).append(" ");

                    if (key == KEY_MOUSE) {
                        scriptbuf.append("MOUSE ").
                                append(mouse_info.x).
                                append(" ").
                                append(mouse_info.y);
                    } else {
                        scriptbuf.append("KEY ");
                        scriptbuf.append(Integer.toHexString(key));
                        scriptbuf.append(" ");
                        scriptbuf.append(key2ASCII(key));
                    }

                    _scriptPrintStream.println(scriptbuf.toString());
                }   // if (_scriptPrintStream != null)
            }	    // for (;;)
        } catch (Exception e) {
            e.printStackTrace();
        }
        Object obj = Toolkit.getDefaultToolkit();
        synchronized(obj){
            obj.notifyAll();
        }
        keyboardReader = null;
    }

    /**
     * Convert the integer representation of a keystroke to an ASCII string.
     */
    public static String key2ASCII(int key_) {
        StringBuffer buf = new StringBuffer();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?