/* * 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 <http://www.gnu.org/licenses/>. * * Copyright (C) 2010-2012 Martin */ package com.googlecode.lanterna.gui.component; import com.googlecode.lanterna.gui.Component; import com.googlecode.lanterna.gui.Container; import com.googlecode.lanterna.gui.GUIScreen; import com.googlecode.lanterna.gui.TextGraphics; import com.googlecode.lanterna.gui.Window; import com.googlecode.lanterna.gui.listener.ComponentListener; import com.googlecode.lanterna.terminal.TerminalPosition; import com.googlecode.lanterna.terminal.TerminalSize; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * * @author Martin */ public abstract class AbstractComponent implements Component { private final List<ComponentListener> componentListeners; private Container parent; private TerminalSize preferredSizeOverride; private boolean visible; private Alignment alignment; public AbstractComponent() { componentListeners = new LinkedList<ComponentListener>(); parent = null; visible = true; preferredSizeOverride = null; alignment = Alignment.CENTER; } @Override public Container getParent() { return parent; } protected void setParent(Container parent) { this.parent = parent; } @Override public void addComponentListener(ComponentListener cl) { if(cl != null) componentListeners.add(cl); } @Override public void removeComponentListener(ComponentListener cl) { componentListeners.remove(cl); } @Override public boolean isVisible() { return visible; } @Override public void setVisible(boolean visible) { this.visible = visible; } @Override public boolean isScrollable() { return false; } @Override public void setPreferredSize(TerminalSize preferredSizeOverride) { this.preferredSizeOverride = preferredSizeOverride; invalidate(); } @Override public TerminalSize getPreferredSize() { if(preferredSizeOverride != null) return preferredSizeOverride; else return calculatePreferredSize(); } protected abstract TerminalSize calculatePreferredSize(); @Override public TerminalSize getMinimumSize() { return new TerminalSize(1, 1); } @Override public Alignment getAlignment() { return alignment; } @Override public void setAlignment(Alignment alignment) { if(alignment == null) { throw new IllegalArgumentException("Alignment argument to " + "AbstractComponent.setAlignment(...) cannot be null"); } this.alignment = alignment; } protected void invalidate() { for(ComponentListener cl: componentListeners) cl.onComponentInvalidated(this); if(parent != null && parent instanceof AbstractContainer) { ((AbstractContainer)parent).invalidate(); } } protected List<ComponentListener> getComponentListeners() { //This isn't thread safe either, but at least the list can't be modified return Collections.unmodifiableList(componentListeners); } @Override public Window getWindow() { Container container = getParent(); if(container != null) return container.getWindow(); return null; } protected GUIScreen getGUIScreen() { Window window = getWindow(); if(window == null) return null; return window.getOwner(); } /** * Will create a sub-graphic area according to the alignment, if the assigned size is larger * than the preferred size. */ protected TextGraphics transformAccordingToAlignment(TextGraphics graphics, TerminalSize preferredSize) { if(graphics.getWidth() <= preferredSize.getColumns() && graphics.getHeight() <= preferredSize.getRows()) { //Don't do anything, return the original TextGraphics return graphics; } if(alignment == Alignment.FILL) { //For FILL, we also want to return it like it is return graphics; } int leftPosition = 0; if(alignment == Alignment.TOP_CENTER || alignment == Alignment.CENTER || alignment == Alignment.BOTTON_CENTER) { leftPosition = (graphics.getWidth() - preferredSize.getColumns()) / 2; } else if(alignment == Alignment.TOP_RIGHT || alignment == Alignment.RIGHT_CENTER || alignment == Alignment.BOTTOM_RIGHT) { leftPosition = graphics.getWidth() - preferredSize.getColumns(); } int topPosition = 0; if(alignment == Alignment.LEFT_CENTER || alignment == Alignment.CENTER || alignment == Alignment.RIGHT_CENTER) { topPosition = (graphics.getHeight() - preferredSize.getRows()) / 2; } else if(alignment == Alignment.BOTTOM_LEFT || alignment == Alignment.BOTTON_CENTER || alignment == Alignment.BOTTOM_RIGHT) { topPosition = graphics.getHeight() - preferredSize.getRows(); } return graphics.subAreaGraphics(new TerminalPosition(leftPosition, topPosition), preferredSize); } }