Package charva.awt

Source Code of charva.awt.Window

/* class Window
*
* Copyright (C) 2001-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
*/

package charva.awt;

import java.util.Enumeration;
import java.util.Vector;

import charva.awt.event.AWTEvent;
import charva.awt.event.AdjustmentEvent;
import charva.awt.event.GarbageCollectionEvent;
import charva.awt.event.InvocationEvent;
import charva.awt.event.PaintEvent;
import charva.awt.event.ScrollEvent;
import charva.awt.event.SyncEvent;
import charva.awt.event.WindowEvent;
import charva.awt.event.WindowListener;

/**
* The Window class represents a "toplevel" window with no decorative frame.
* The window is initially invisible; you must use the show() method to make it
* visible.
*/
public class Window extends Container implements Runnable {

    public Window(Window owner_) {
        _owner = owner_;
        init();
    }

    public Window(Frame owner_) {
        _owner = owner_;
        init();
    }

    private void init() {
        _term = Toolkit.getDefaultToolkit();
        super._layoutMgr = new BorderLayout();
        _visible = false;

        // The window inherits the colors of its parent if there is one,
        // otherwise use the default colors as set in charva.awt.Toolkit.
        if (_owner != null) {
            super.setForeground(_owner.getForeground());
            super.setBackground(_owner.getBackground());
        } else {
            super.setForeground(Toolkit.getDefaultForeground());
            super.setBackground(Toolkit.getDefaultBackground());
        }
    }

    /**
     * Return the Window that is the "owner" of this Window.
     */
    public Window getOwner() {
        return _owner;
    }

    /**
     * Register a WindowListener object for this window.
     */
    public void addWindowListener(WindowListener listener_) {
        if (_windowListeners == null) _windowListeners = new Vector<WindowListener>();

        _windowListeners.add(listener_);
    }

    /**
     * Process window events occurring on this window by dispatching them to
     * any registered WindowListener objects.
     */
    protected void processWindowEvent(WindowEvent evt_) {
        if (_windowListeners == null) return;

        Enumeration<WindowListener> e = _windowListeners.elements();
        while (e.hasMoreElements()) {
            WindowListener wl = (WindowListener) e.nextElement();
            switch (evt_.getID()) {

            case AWTEvent.WINDOW_CLOSING:
                wl.windowClosing(evt_);
                break;

            case AWTEvent.WINDOW_OPENED:
                wl.windowOpened(evt_);
                break;
            }
        }
    }

    /**
     * Returns true if this Window is currently displayed.
     */
    public boolean isDisplayed() {
        return _term.isWindowDisplayed(this);
    }

    /**
     * Causes this Window to be sized to fit the preferred sizes and layouts of
     * its contained components.
     */
    public void pack() {
        setSize(minimumSize());
        super.doLayout(); // call method in Container superclass
    }

    /**
     * Lay out the contained components, draw the window and its contained
     * components, and then read input events off the EventQueue and send them
     * to the component that has the input focus.
     */
    public void show() {

        if (_visible) return; // This window is already visible.

        _visible = true;
        _term.addWindow(this);

        /*
         * Start the keyboard-reader thread _after_ the first window has been
         * displayed, otherwise we get a NoSuchElement exception if the user
         * starts typing before the first window is displayed, because the
         * _windowList is empty.
         */
        _term.startKeyboardReader();

        /*
         * call doLayout in Container superclass. This will lay out all of the
         * contained components (i.e. children) and their descendants, and in
         * the process will set the valid flag of all descendants.
         */
        super.doLayout(); // call method in Container superclass

        this.adjustLocation(); // ensure it fits inside the screen

        this.draw(Toolkit.getDefaultToolkit());

        /*
         * Rather than call Toolkit.sync() directly here, we put a SyncEvent
         * onto the SyncQueue. The SyncThread will read it off the SyncQueue
         * and then sleep for 50msec before putting the SyncEvent onto the
         * EventQueue, from which it will be picked up by the active Window
         * (i.e. an instance of this class). The active Window will then call
         * Toolkit.sync() directly. This slight delay speeds up the case where
         * a window opens and then immediately opens a new window (and
         * another...).
         */
        SyncQueue.getInstance().postEvent(new SyncEvent(this));

        if (_dispatchThreadRunning)
            run();
        else {
            _dispatchThreadRunning = true;
            //System.err.println( "Created window dispatch thread." );
            Thread dispatchThread = new Thread(this);
            dispatchThread.setName("Window event dispatcher");
            dispatchThread.start();

            /*
             * If "charva.script.playback" is defined, we start up a thread for
             * playing back the script. Keys from both the script and the
             * keyboard will cause "fireKeystroke()" to be invoked. The
             * playback thread is started _after_ "addWindow()" is called for
             * the first time, to make sure that _windowList is non-empty when
             * the playback thread calls "fireKeystroke()".
             */
            //startPlayback();

        }
    }

    public void run() {
        /*
         * Loop and process input events until the window closes.
         */
        try {
            EventQueue evtQueue = _term.getSystemEventQueue();
            for (_windowClosed = false; _windowClosed != true;) {

                java.util.EventObject evt = evtQueue.getNextEvent();

                /*
                 * The event object should always be an AWTEvent. If not, we
                 * will get a ClassCastException.
                 */
                processEvent((AWTEvent) evt);
            } // end FOR loop
        } catch (Exception e) {
            System.err.println( "Exception in Window.run" );
            e.printStackTrace();
//            System.exit(1);
            System.err.println( "Exiting method (not VM)" );
        }
    }

    /**
     * Process an event off the event queue. This method can be extended by
     * subclasses of Window to deal with application-specific events.
     */
    protected void processEvent(AWTEvent evt_) {
        Object source = evt_.getSource();

        if (evt_ instanceof AdjustmentEvent){
            ((Adjustable) source)
                    .processAdjustmentEvent((AdjustmentEvent) evt_);
        }

        else if (evt_ instanceof ScrollEvent) {
            processScrollEvent((ScrollEvent) evt_);
        }

        else if (evt_ instanceof PaintEvent) {

            processPaintEvent((PaintEvent) evt_);
        }

        else if (evt_ instanceof SyncEvent) {
            _term.sync();
        }

        else if (evt_ instanceof WindowEvent) {
            WindowEvent we = (WindowEvent) evt_;
            we.getWindow().processWindowEvent(we);

            /*
             * Now, having given the WindowListener objects a chance to process
             * the WindowEvent, we must check if it was a WINDOW_CLOSING event
             * sent to this window.
             */
            if (we.getID() == AWTEvent.WINDOW_CLOSING) {

                we.getWindow()._windowClosed = true;

                /*
                 * Remove this window from the list of those displayed, and
                 * blank out the screen area where the window was displayed.
                 */
                _term.removeWindow(we.getWindow());
                _term.blankBox(_origin, _size);

                /*
                 * Now redraw all of the windows, from the bottom to the top.
                 */
                Vector<Window> winlist = _term.getWindowList();
                Window window = null;
                synchronized (winlist) {
                    for (int i = 0; i < winlist.size(); i++) {
                        window = (Window) winlist.elementAt(i);
                        window.draw(Toolkit.getDefaultToolkit());
                    }
                    if (window != null) // (there may be no windows left)
                            window.requestFocus();
                }

                /*
                 * Put a SyncEvent onto the SyncQueue. The SyncThread will
                 * sleep for 50 msec before putting it onto the EventQueue,
                 * from which it will be picked up by the active Window (i.e.
                 * an instance of this class), which will then call
                 * Toolkit.sync() directly. This is done to avoid calling
                 * sync() after the close of a window and again after the
                 * display of a new window which might be displayed immediately
                 * afterwards.
                 */
                if(window != null)
                    SyncQueue.getInstance().postEvent(new SyncEvent(window));
            }
        } // end if WindowEvent

        else if (evt_ instanceof GarbageCollectionEvent) {
            SyncQueue.getInstance().postEvent(evt_);
        }

        else if (evt_ instanceof InvocationEvent) {
            ((InvocationEvent) evt_).dispatch();
        }

        else {
            /*
             * It is a KeyEvent, MouseEvent, ActionEvent, ItemEvent, FocusEvent
             * or a custom type of event.
             */
            //System.err.println(evt_);
            ((Component) source).processEvent(evt_);
        }
    }

    protected void processScrollEvent(ScrollEvent event) {
        Scrollable source = (Scrollable) event.getSource();
        source.processScrollEvent(event);
        requestFocus();
        super.requestSync();
    }

    protected void processPaintEvent(PaintEvent  event) {
        Component source = (Component) event.getSource();
        if (!source.isTotallyObscured()) {
            processPaintEvent2(source);
        }
    }

    private void processPaintEvent2(Component source) {
        /*
         * Unless the affected component is totally obscured by windows
         * that are stacked above it, we must redraw its window and all the
         * windows above it.
         */
        if (!((Component) source).isTotallyObscured()) {

            Vector<Window> windowlist = _term.getWindowList();
            synchronized (windowlist) {

                /*
                 * We have to draw the window rather than just the affected
                 * component, because setVisible(false) may have been set
                 * on the component.
                 */
                Window ancestor = ((Component) source).getAncestorWindow();
                ancestor.draw(Toolkit.getDefaultToolkit());

                /*
                 * Ignore windows that are underneath the window that
                 * contains the component that generated the PaintEvent.
                 */
                Window w = null;
                int i;
                for (i = 0; i < windowlist.size(); i++) {
                    w = (Window) windowlist.elementAt(i);
                    if (w == ancestor) break;
                }

                /*
                 * Redraw all the windows _above_ the one that generated
                 * the PaintEvent.
                 */
                for (; i < windowlist.size(); i++) {
                    w = (Window) windowlist.elementAt(i);
                    w.draw(Toolkit.getDefaultToolkit());
                }
            }

            super.requestSync();
        }
    }

    /**
     * Hide this window and all of its contained components. This is done by
     * putting a WINDOW_CLOSING event onto the queue.
     */
    public void hide() {

        if (!_visible) {
            System.err.println("Trying to hide window " + this
                    + " that is already hidden!");
            return; // This window is already hidden.
        }
        _term.removeWindow( this );
        _visible = false;
        WindowEvent we = new WindowEvent(this, AWTEvent.WINDOW_CLOSING);
        _term.getSystemEventQueue().postEvent(we);
    }

    /**
     * Draw all the components in this window, and request the keyboard focus.
     * @param toolkit
     */
    public void draw(Toolkit toolkit) {
        super.draw(toolkit);
        requestFocus();
    }

    /**
     * Overrides the method in the Component superclass, because a Window has
     * no parent container. Note that we return a COPY of the origin, not a
     * reference to it, so that the caller cannot modify our location via the
     * returned value.
     */
    public Point getLocationOnScreen() {
        return new Point(_origin);
    }

    /**
     * A Window component will not receive input focus during keyboard focus
     * traversal using Tab and Shift-Tab.
     */
    public boolean isFocusTraversable() {
        return false;
    }

    /**
     * Adjust the position of the window so that it fits inside the screen.
     */
    public void adjustLocation() {
        int bottom = _origin.y + getHeight();
        if (bottom > _term.getScreenRows())
                _origin.y -= bottom - _term.getScreenRows();

        if (_origin.y < 0) _origin.y = 0;

        int right = _origin.x + getWidth();
        if (right > _term.getScreenColumns())
                _origin.x -= right - _term.getScreenColumns();

        if (_origin.x < 0) _origin.x = 0;
    }

    public void debug(int level_) {
        System.err.println("Window origin=" + _origin + " size=" + _size);
        super.debug(1);
    }

    @SuppressWarnings("unused")
    private void startPlayback() {
//        System.err.println("Playback disabled (awaiting security exception fix..)");
        return;
//        String scriptfilename = null;
//        BufferedReader scriptReader = null;
//        if ((scriptfilename = System.getProperty("charva.script.playback")) == null)
//                return;
//
//        try {
//            scriptReader = new BufferedReader(new FileReader(scriptfilename));
//        } catch (FileNotFoundException ef) {
//            System.err.println("Cannot open script file \"" + scriptfilename
//                    + "\" for reading");
//            return;
//        }
//
//        PlaybackThread thr = new PlaybackThread(scriptReader);
//        thr.setDaemon(true);
//        thr.setName("playback thread");
//        thr.start();
    }

    //====================================================================
    // INSTANCE VARIABLES

    private Window _owner;

    protected Toolkit _term;

    private boolean _windowClosed = false;

    private Vector<WindowListener> _windowListeners = null;

    private static boolean _dispatchThreadRunning = false;

}
TOP

Related Classes of charva.awt.Window

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.