/* Copyright (C) 2007 Felipe A. Lessa
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package tirateima.gui.variaveis;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import javax.swing.JComponent;
import javax.swing.Scrollable;
import tirateima.gui.Constantes;
/**
* Um componente que implementa uma borda arredondada com um título.
*
* @author felipe.lessa
*
*/
@SuppressWarnings("serial")
public abstract class Borda extends JComponent implements Scrollable {
protected String titulo = "";
protected Font fonte = Constantes.FONTE_TITULO;
protected Color corFundo = Color.BLACK;
protected Color corFonte = Constantes.COR_FONTE;
protected double proporcao = -1.0;
private Dimension tamPadrao;
private int alturaTexto;
private Insets insets;
private JComponent interno;
private Font fonte_atual;
/**
* Cria uma nova borda com o componente especificado.
* @param c o componente a ser exibido.
*/
protected Borda(JComponent c) {
this.interno = c;
setLayout(new BorderLayout());
this.add(c, BorderLayout.CENTER);
}
/**
* Faz a analise da dimensao da janela e retorna o tamanho da mesma
*
* @return tamPadrao (variavel do tipo Dimension)
*/
protected Dimension getTamanhoPadrao() {
if (tamPadrao == null) {
proporcao = 1.0;
tamPadrao = getTamanhoParaProporcao();
}
return tamPadrao;
}
/**
* A proporção que será utilizada quando o desenho da janela for feito.
* @return a proporção (onde 1.0 é equivalente a 100%).
* @see #setProporcao(double)
*/
public double getProporcao() {
return proporcao;
}
/**
* Retorna o tamanho desta janela para a proporção atual. Além disso,
* altera as variáveis utilizadas na hora da pintura.
* @return o tamanho da janela.
*/
protected Dimension getTamanhoParaProporcao() {
Dimension tamInterno = interno.getSize();
float fonte_tam = (float) (fonte.getSize2D());
fonte_atual = fonte.deriveFont(fonte_tam);
Graphics g = getGraphics();
FontMetrics metrics = g != null ?
g.getFontMetrics(Constantes.FONTE_VARIAVEL) :
getFontMetrics(Constantes.FONTE_VARIAVEL);
int larguraTexto = metrics.stringWidth(titulo);
int larguraMaior = Math.max(larguraTexto, tamInterno.width);
alturaTexto = metrics.getHeight() - metrics.getDescent();
double borda, altura, largura;
borda = Constantes.LARGURA_BORDA * proporcao;
altura = borda + metrics.getHeight() + borda + tamInterno.height + borda;
largura = borda + larguraMaior + borda;
int itopo = (int) Math.round(borda + metrics.getHeight() + borda);
int iborda = (int) Math.round(borda);
insets = new Insets(itopo, iborda, iborda, iborda);
return new Dimension((int) Math.round(largura),
(int) Math.round(altura));
}
/**
* Define a proporção que será utilizada. Deve ser um número positivo.
* @param prop a nova proporção (onde 1.0 é equivalente a 100%).
* @see #getProporcao()
*/
public void setProporcao(double prop) {
if (prop <= 0)
throw new AssertionError("Proporção negativa ou nula.");
proporcao = prop;
this.setSize(getTamanhoParaProporcao());
this.validate();
}
/**
* Desenha a nossa borda, com o título e tudo mais.
* @see #paint(Graphics)
* @see #paintChildren(Graphics)
*/
@Override
public void paintBorder(Graphics g) {
// Não precisamos nos preocupar com o desenho do componente
// porque ele será feito por nós em paintChildren.
Graphics2D g2d = (Graphics2D) g;
int arc = (int) (5 * proporcao);
Dimension tamanho = getSize();
g2d.setColor(corFundo);
g2d.fillRoundRect(0, 0, tamanho.width, tamanho.height, arc, arc);
g2d.setColor(new Color(0.0f, 0.0f, 0.0f, 0.2f));
Stroke s = g2d.getStroke();
g2d.setStroke(new BasicStroke(Math.min((float) proporcao, 1.5f)));
g2d.drawRoundRect(0, 0, tamanho.width, tamanho.height, arc, arc);
g2d.setStroke(s);
g2d.setColor(corFonte);
g2d.setFont(fonte_atual);
float offset = (float) (Constantes.LARGURA_BORDA * proporcao);
g2d.drawString(titulo, offset, offset + alturaTexto);
}
@Override
public void paint(Graphics g) {
// Liga o antialiasing antes de pintar tudo
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g2d);
}
@Override
public Insets getInsets() {
if (insets == null) {
/**
* Força os cálculos que dependem de um Graphics a
* serem feitos.
*/
getTamanhoPadrao();
setProporcao(1.0);
}
return insets;
}
@Override
public void setSize(Dimension d) {
super.setSize(d);
super.setMinimumSize(d);
super.setPreferredSize(d);
super.setMaximumSize(d);
}
public void setCorFundo(Color c){
if(c != null){
this.corFundo = c;
repaint();
}
}
public void setTitulo(String titulo){
this.titulo = titulo != null ? titulo : "";
repaint();
}
public String getTitulo(){
return titulo;
}
// Interface Scrollable
public Dimension getPreferredScrollableViewportSize() {
getInsets(); // Força o cálculo do tamanho certo
return getSize();
}
public int getScrollableBlockIncrement(Rectangle arg0, int arg1, int arg2) {
return (int) Math.ceil(proporcao);
}
public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2) {
return (int) Math.ceil(proporcao);
}
public boolean getScrollableTracksViewportHeight() {
return false;
}
public boolean getScrollableTracksViewportWidth() {
return false;
}
}