All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.lanterna.gui.Window Maven / Gradle / Ivy

There is a newer version: 3.2.0-alpha1
Show newest version
/*
 * This file is part of lanterna (http://code.google.com/p/lanterna/).
 * 
 * lanterna 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program.  If not, see .
 * 
 * Copyright (C) 2010-2014 Martin
 */

package com.googlecode.lanterna.gui;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.lanterna.gui.Theme.Category;
import com.googlecode.lanterna.gui.component.EmptySpace;
import com.googlecode.lanterna.gui.component.Panel;
import com.googlecode.lanterna.gui.layout.LayoutParameter;
import com.googlecode.lanterna.gui.listener.ComponentAdapter;
import com.googlecode.lanterna.gui.listener.ContainerListener;
import com.googlecode.lanterna.gui.listener.WindowListener;
import com.googlecode.lanterna.input.KeyStroke;
import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TerminalSize;
import java.io.IOException;

/**
 * The Window class is the basis for Lanternas GUI system. The workflow is to
 * create and show modal windows and promt the user for input. A window, once
 * displayed, will take over control by entering an event loop and won't come 
 * back until the window is closed.
 * @author Martin
 */
@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
@Deprecated
public class Window
{
    private final List windowListeners;
    private final List invalidatorAlerts;
    private GUIScreen owner;
    private final WindowContentPane contentPane;
    private Interactable currentlyInFocus;
    private TerminalSize windowSizeOverride;
    private boolean soloWindow;
    private boolean drawShadow;

    /**
     * Creates a new window
     * @param title Title for the new window
     */
    public Window(String title)
    {
        this.windowListeners = new ArrayList();
        this.invalidatorAlerts = new ArrayList();
        this.owner = null;
        this.contentPane = new WindowContentPane(title);
        this.currentlyInFocus = null;
        this.soloWindow = false;
        this.windowSizeOverride = null;
        this.drawShadow = true;
    }

    public void addWindowListener(WindowListener listener)
    {
        windowListeners.add(listener);
    }

    /**
     * @return The GUIScreen which this window is displayed on
     */
    public GUIScreen getOwner()
    {
        return owner;
    }

    void setOwner(GUIScreen owner)
    {
        this.owner = owner;
    }

    /**
     * @return The border of this window
     */
    public Border getBorder()
    {
        return contentPane.getBorder();
    }

    public void setBorder(Border border)
    {
        if(border != null)
            contentPane.setBorder(border);
    }

    /**
     * Returns the current window size override or {@code null} if none is set
     * @return Override for the window size or {@code null}
     */
    public TerminalSize getWindowSizeOverride() {
        return windowSizeOverride;
    }

    /**
     * Sets the size of the window to a fixed value, rather than using automatic size calculation. 
     * If you call this method with {@code windowSizeOverride} parameter set to {@code null}, the
     * automatic size calculation will be activated again.
     * @param windowSizeOverride Size the window should have, or {@code null} if you want to use
     * automatic size calculation
     */
    public void setWindowSizeOverride(TerminalSize windowSizeOverride) {
        this.windowSizeOverride = windowSizeOverride;
    }

    /**
     * @return How big this window would like to be
     */
    TerminalSize getPreferredSize()
    {
        TerminalSize override = getWindowSizeOverride();
        if(override != null)
            return override;
        else
            return contentPane.getPreferredSize();  //Automatically calculate the size
    }

    void repaint(TextGraphics graphics)
    {
        graphics.applyTheme(graphics.getTheme().getDefinition(Category.DIALOG_AREA));
        graphics.fillRectangle(' ', new TerminalPosition(0, 0), new TerminalSize(graphics.getWidth(), graphics.getHeight()));
        contentPane.repaint(graphics);
    }

    private void invalidate()
    {
        for(WindowListener listener: windowListeners)
            listener.onWindowInvalidated(this);
    }

    /**
     * Don't use the method, call {@code addComponent(new EmptySpace(1, 1))} instead
     * @deprecated
     */
    @Deprecated
    public void addEmptyLine()
    {
        addComponent(new EmptySpace(1, 1));
    }
    
    public void addComponent(Component component, LayoutParameter... layoutParameters)
    {
        if(component == null)
            return;

        contentPane.addComponent(component, layoutParameters);
        ComponentInvalidatorAlert invalidatorAlert = new ComponentInvalidatorAlert(component);
        invalidatorAlerts.add(invalidatorAlert);
        component.addComponentListener(invalidatorAlert);
        checkFocus();
        invalidate();
    }

    /**
     * This method will, if nothing is in focus, scan through all components
     * again and find something to focus on.
     */
    void checkFocus() 
    {
        if(currentlyInFocus == null) {
            setFocus(contentPane.nextFocus(null));
            invalidate();
        }
    }

    public void addContainerListener(ContainerListener cl)
    {
        contentPane.addContainerListener(cl);
    }

    public void removeContainerListener(ContainerListener cl)
    {
        contentPane.removeContainerListener(cl);
    }

    public Component getComponentAt(int index)
    {
        return contentPane.getComponentAt(index);
    }

    /**
     * @return How many top-level components this window has
     */
    public int getComponentCount()
    {
        return contentPane.getComponentCount();
    }

    /**
     * Removes a top-level component from the window
     * @param component Top-level component to remove
     */
    public void removeComponent(Component component)
    {
        if(component instanceof InteractableContainer) {
            InteractableContainer container = (InteractableContainer)component;
            if(container.hasInteractable(currentlyInFocus)) {
                Interactable original = currentlyInFocus;
                Interactable current = contentPane.nextFocus(original);
                while(container.hasInteractable(current) && original != current)
                    current = contentPane.nextFocus(current);
                if(container.hasInteractable(current))
                    setFocus(null);
                else
                    setFocus(current);
            }
        }
        else if(component == currentlyInFocus)
            setFocus(contentPane.nextFocus(currentlyInFocus));
        
        contentPane.removeComponent(component);

        for(ComponentInvalidatorAlert invalidatorAlert: invalidatorAlerts) {
            if(component == invalidatorAlert.component) {
                component.removeComponentListener(invalidatorAlert);
                invalidatorAlerts.remove(invalidatorAlert);
                break;
            }
        }
    }

    /**
     * Removes all components from the window
     */
    public void removeAllComponents()
    {
        while(getComponentCount() > 0)
            removeComponent(getComponentAt(0));
    }

    TerminalPosition getWindowHotspotPosition()
    {
        if(currentlyInFocus == null)
            return null;
        else
            return currentlyInFocus.getHotspot();
    }

    public void onKeyPressed(KeyStroke key) throws IOException
    {
        if(currentlyInFocus != null) {
            Interactable.Result result =  currentlyInFocus.keyboardInteraction(key);
            if(result.isNextInteractable()) {
                Interactable nextItem = contentPane.nextFocus(currentlyInFocus);
                if(nextItem == null)
                    nextItem = contentPane.nextFocus(null);
                setFocus(nextItem, result.asFocusChangeDirection());
            }
            else if(result.isPreviousInteractable()) {
                Interactable prevItem = contentPane.previousFocus(currentlyInFocus);
                if(prevItem == null)
                    prevItem = contentPane.previousFocus(null);
                setFocus(prevItem, result.asFocusChangeDirection());
            }
            else if(result == Interactable.Result.EVENT_NOT_HANDLED) {
                //Try to find a shortcut
                if(currentlyInFocus instanceof Component) {
                    Container parentContainer = ((Component)currentlyInFocus).getParent();
                    while(parentContainer != null) {
                        if(parentContainer instanceof InteractableContainer) {
                            //If we could fire off a shortcut, stop here
                            if(((InteractableContainer)parentContainer).triggerShortcut(key))
                                return;
                        }
                        //Otherwise try one level higher
                        parentContainer = parentContainer.getParent();
                    }
                }
                
                //There was no shortcut
                onUnhandledKeyPress(key);
            }
        }
        else {
            onUnhandledKeyPress(key);
        }
    }
    
    protected void onUnhandledKeyPress(KeyStroke key) {
        for(WindowListener listener: windowListeners)
            listener.onUnhandledKeyboardInteraction(this, key);
    }

    public boolean isSoloWindow()
    {
        return soloWindow;
    }

    /**
     * If set to true, when this window is shown, all previous windows are 
     * hidden. Set to false to show them again.
     */
    public void setSoloWindow(boolean soloWindow)
    {
        this.soloWindow = soloWindow;
    }

    public boolean isDrawShadow() {
        return drawShadow;
    }

    public void setDrawShadow(boolean drawShadow) {
        this.drawShadow = drawShadow;
    }            

    protected boolean maximisesVertically()
    {
        return contentPane.maximisesVertically();
    }

    protected boolean maximisesHorisontally()
    {
        return contentPane.maximisesHorisontally();
    }

    public void setFocus(Interactable newFocus)
    {
        setFocus(newFocus, null);
    }

    protected void setFocus(Interactable newFocus, Interactable.FocusChangeDirection direction)
    {
        if(currentlyInFocus != null)
            currentlyInFocus.onLeaveFocus(direction);
        
        //Fire the focus changed event
        for(WindowListener listener: windowListeners) {
            listener.onFocusChanged(this, currentlyInFocus, newFocus);
        }
        
        currentlyInFocus = newFocus;
        if(currentlyInFocus != null)
            currentlyInFocus.onEnterFocus(direction);
        invalidate();
    }

    protected Interactable getInputFocusedComponent() {
        return currentlyInFocus;
    }

    public void close()
    {
        if(owner != null)
            owner.closeWindow(this);
    }

    protected void onVisible()
    {
        for(WindowListener listener: windowListeners)
            listener.onWindowShown(this);
    }

    protected void onClosed()
    {
        for(WindowListener listener: windowListeners)
            listener.onWindowClosed(this);
    }

    @Override
    public String toString() {
        return contentPane.getTitle();
    }

    private class ComponentInvalidatorAlert extends ComponentAdapter
    {
        private final Component component;

        public ComponentInvalidatorAlert(Component component)
        {
            this.component = component;
        }

        public Component getComponent()
        {
            return component;
        }

        @Override
        public void onComponentInvalidated(Component component)
        {
            invalidate();
        }
    }
    
    /**
     * Private class to get through some method restrictions
     */
    private class WindowContentPane extends Panel {
        public WindowContentPane(String title) {
            super(title);
        }

        @Override
        public Window getWindow() {
            return Window.this;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy