/* Copyright (C) 2007 Felipe A. Lessa
* Copyright (C) 2007 Renan Leandro Ferreira
* Copyright (C) 2007 Luciano Henrique dos Santos
* Copyright (C) 2009 Andrew Biller
*
* 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;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.Reader;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import tirateima.controlador.Controlador;
import tirateima.gui.alerta.Alerta;
import tirateima.gui.arquivos.ArquivoVisivelEventListener;
import tirateima.gui.arquivos.GerenciadorArquivos;
import tirateima.gui.console.Console;
import tirateima.gui.editortexto.EditorTexto;
import tirateima.gui.editortexto.Linguagem;
import tirateima.gui.variaveis.Mostrador;
import tirateima.gui.variaveis.Mostrador.zoom;
import tirateima.ui.Ajuda;
/**
*
* Classe principal do AlgoStep. Cria e controla todas as outras classes.
* Deve ser incluída num applet ou numa janela para ser útil.
*
* @see tirateima.main.Applet
* @see tirateima.main.Programa
*
*/
@SuppressWarnings("serial")
public class Principal extends JPanel {
private EditorTexto editor = null;
private Mostrador mostrador = null;
private JButton btnReiniciar = null;
private JButton btnProximo = null;
private JButton btnAnterior = null;
private Console console = null;
private Alerta alerta = null;
public Boolean jump = Boolean.FALSE;
public String jumpTo = null;
private GerenciadorArquivos ga = null;
@SuppressWarnings("unused")
private Controlador control = null;
private JSplitPane spl_principal = null;
private JSplitPane spl_painel_direita = null;
private JSplitPane spl_desenho = null;
private JPanel spl_painel_abaixo = null;
private JPanel spl_barra_topo = null;
private JScrollPane comentarioPainel = null;
/**
* Cria e inicializa todos os componentes.
*/
public Principal() {
inicializar();
btnAnterior.setEnabled(false);
btnProximo.setEnabled(false);
btnReiniciar.setEnabled(false);
}
/**
* Cria e inicializa a interface.
*
* @param arq_fonte Streamer com o texto do arquivo fonte.
* @param arq_texto Streamer com o texto do arquivo de instruções.
*
* @throws Exception
*/
public Principal(Reader arq_fonte, Reader arq_texto, Linguagem linguagem) throws Exception{
inicializar();
editor.getCaixaTexto().setText(arq_fonte,linguagem);
control = new Controlador(
arq_texto,
mostrador,
ga,
editor,
console,
alerta,
btnAnterior,
btnProximo,
btnReiniciar);
//Inicializa o número de linhas
editor.setNumeracao(editor.getCaixaTexto().getTotalLinhas());
// Evita que o comentário apareça logo na inicialização
comentarioPainel.setVisible(false);
}
/**
* Retorna o componente mostrador.
*/
public Mostrador getMostrador() {
if(mostrador == null){
mostrador = new Mostrador();
mostrador.setPreferredSize(new Dimension(400,400));
}
return mostrador;
}
/**
* Retorna o componente editor.
*/
public EditorTexto getEditor() {
if(editor == null){
editor = new EditorTexto();
}
return editor;
}
/**
* Retorna botão p/ estado anterior.
*/
public JButton getBtnAnterior(){
if(btnAnterior == null){
final ImageIcon iconeAnterior = new ImageIcon(getClass().getResource("/resources/anterior.png"));
btnAnterior = new JButton("Anterior", iconeAnterior);
}
return btnAnterior;
}
/**
* Retorna botão p/ próximo estado.
*/
public JButton getBtnProximo(){
if(btnProximo == null){
btnProximo = new JButton("Próximo");
}
return btnProximo;
}
/**
* Vai para a primeira linha do editor
*/
public JButton getBtnReinicia(){
if(btnReiniciar == null){
final ImageIcon iconeReiniciar = new ImageIcon(getClass().getResource("/resources/reiniciar.png"));
btnReiniciar = new JButton("Reiniciar", iconeReiniciar);
}
return btnReiniciar;
}
/**
* Para que seja possível tratar eventos de teclado
* no componente.
*/
public boolean isFocusable(){
return true;
}
/**
* Define o layout da janela pricipal e suas dimensões proporcionais a janela
* Define o controle do tira-teima pelas setas direcionais
* Define as posições de cada módulo do SplitPane
*/
private void inicializar(){
setLayout(new BorderLayout());
spl_principal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
criarPainelDeTexto(), criarPainelDireita());
spl_principal.setResizeWeight(0.3);
add(getBarraTopo(), BorderLayout.PAGE_START);
add(spl_principal, BorderLayout.CENTER);
/* Controle via setas direcionais. */
this.addKeyListener(new KeyListener(){
public void keyPressed(KeyEvent e){};
public void keyReleased(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_DOWN:
case KeyEvent.VK_RIGHT:
btnProximo.doClick();
break;
case KeyEvent.VK_UP:
case KeyEvent.VK_LEFT:
btnAnterior.doClick();
break;
}
}
public void keyTyped(KeyEvent e){}
});
this.addAncestorListener(new AncestorListener(){
public void ancestorAdded(AncestorEvent arg0) {
spl_principal.setDividerLocation(0.3);
spl_painel_direita.setDividerLocation(0.75);
spl_desenho.setDividerLocation(0.7);
}
public void ancestorMoved(AncestorEvent arg0) {}
public void ancestorRemoved(AncestorEvent arg0) {}
});
}
/**
* Cria a barra de navegação do tira-teima
* Define controles de navegação e de zoom (botões de navegação, áudio e ajuda)
*
* @return JPanel Object: spl_barra_topo (barra de navegação)
*/
private Component getBarraTopo() {
if(spl_barra_topo == null){
spl_barra_topo = new JPanel(new BorderLayout());
// controles de navegação
JPanel controleNavegacao = new JPanel();
controleNavegacao.add(new JLabel("Navegação: "));
controleNavegacao.add(getBtnReinicia());
controleNavegacao.add(getBtnAnterior());
controleNavegacao.add(getBtnProximo());
// controles de zoom
final ImageIcon iconeZoomMenos = new ImageIcon(getClass().getResource("/resources/zoom_out.png"));
final JButton bMenos = new JButton(iconeZoomMenos);
bMenos.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
double valor = mostrador.getProporcao();
if(valor > 0.2){
mostrador.acaoZoom = zoom.DIMINUI;
mostrador.setProporcao(mostrador.getProporcao() - 0.2);
}
}
});
bMenos.setSize(bMenos.getWidth(), 5);
bMenos.setFont(new Font("sansserif", Font.BOLD, 11));
final ImageIcon iconeZoomReiniciar = new ImageIcon(getClass().getResource("/resources/zoom_reiniciar.png"));
final JButton bZero = new JButton(iconeZoomReiniciar);
bZero.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
mostrador.acaoZoom = zoom.REINICIA;
//tenta redefinir o tamanho da barra de rolagem
mostrador.setProporcao(1.2);
mostrador.setProporcao(0.8);
//reinicia o zoom
mostrador.setProporcao(1);
}
});
bZero.setSize(bMenos.getWidth(), 15);
final ImageIcon iconeZoomMais = new ImageIcon(getClass().getResource("/resources/zoom_in.png"));
final JButton bMais = new JButton(iconeZoomMais);
bMais.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
double valor = mostrador.getProporcao();
if(valor > 0){
mostrador.acaoZoom = zoom.AUMENTA;
mostrador.setProporcao(mostrador.getProporcao() + 0.2);
}
}
});
bMais.setSize(bMenos.getWidth(), 10);
bMais.setFont(new Font("sansserif", Font.BOLD, 11));
JPanel controleZoom = new JPanel();
controleZoom.add(new JLabel("Zoom: "));
controleZoom.add(bMenos);
controleZoom.add(bZero);
controleZoom.add(bMais);
// controles diversos
JPanel controleOutros = new JPanel();
final ImageIcon iconeSomAtivo = new ImageIcon(getClass().getResource("/resources/som_ativo.png"));
final ImageIcon iconeSomMudo = new ImageIcon(getClass().getResource("/resources/som_mudo.png"));
JButton btnSom = new JButton("Som", iconeSomAtivo);
btnSom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
JButton btn = (JButton) evt.getSource();
if("Som".equals(btn.getText())){
btn.setText("Mudo");
btn.setIcon(iconeSomMudo);
}else{
btn.setText("Som");
btn.setIcon(iconeSomAtivo);
}
alerta.setSomAtivado(!alerta.isSomAtivado());
}
});
controleOutros.add(btnSom);
final ImageIcon iconeAjuda = new ImageIcon(getClass().getResource("/resources/ajuda.png"));
JButton btnAjuda = new JButton("Ajuda", iconeAjuda);
btnAjuda.addActionListener(new Ajuda());
controleOutros.add(btnAjuda);
spl_barra_topo.add(controleNavegacao, BorderLayout.LINE_START);
spl_barra_topo.add(controleZoom, BorderLayout.CENTER);
spl_barra_topo.add(controleOutros, BorderLayout.LINE_END);
}
return spl_barra_topo;
}
/**
* Instancia os componentes do lado direito do tira-teima e redimensiona-os
* na janela
*
* @return JSplitPane Object: spl_painel_direita (console, alerta, mostrador, comentário)
*/
private JComponent criarPainelDireita(){
final JScrollPane consolePanel = new JScrollPane(getConsole(),
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
comentarioPainel = new JScrollPane(getAlerta(),
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
spl_painel_abaixo = new JPanel(new BorderLayout());
spl_painel_abaixo.add(consolePanel, BorderLayout.CENTER);
spl_painel_abaixo.add(comentarioPainel, BorderLayout.PAGE_END);
comentarioPainel.setPreferredSize(new Dimension(300, 50));
// Controla quando um alerta deve aparecer (som ou comentário)
CaretListener mostrarAlertaListener = new CaretListener() {
public void caretUpdate(CaretEvent arg0) {
Alerta alerta = (Alerta) arg0.getSource();
//Mostra comentário se existir
if ("".equals(alerta.getText())) {
comentarioPainel.setVisible(false);
consolePanel.setSize(consolePanel.getWidth(), consolePanel.getHeight() + comentarioPainel.getHeight());
}else{
comentarioPainel.setVisible(true);
}
// Força o repaint (afetado: alerta)
spl_painel_abaixo.setVisible(false);
spl_painel_abaixo.setVisible(true);
}
};
getAlerta().addCaretListener(mostrarAlertaListener);
spl_painel_direita = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true,
criarAreaDeDesenho(), spl_painel_abaixo
);
spl_painel_direita.setResizeWeight(0.75);
spl_painel_direita.resetToPreferredSizes();
console.setFont(new Font("Courier New", Font.BOLD, 14));
return spl_painel_direita;
}
/**
* Instancia e dimensiona o editor de texto
*
* @return JPanel Object: p (painel com editor de texto)
*/
private JPanel criarPainelDeTexto(){
JPanel p = new JPanel(new GridBagLayout());
GridBagConstraints gb = new GridBagConstraints();
//Cria o editor de texto
gb.anchor = GridBagConstraints.NORTHWEST;
gb.fill = GridBagConstraints.HORIZONTAL;
gb.gridx = 0;
gb.gridy = 0;
gb.gridwidth = 3;
gb.gridheight = 1;
gb.weightx = 1.0;
gb.weighty = 1.0;
gb.fill = GridBagConstraints.BOTH;
p.add(getEditor(), gb);
return p;
}
/**
* Instancia o painel mostrador e define a organização do painel dentro do mostrador
* Instancia o painel como um todo. Este engloba todo o conteúdo interno do painel descrito
* acima com toda sua organização
*
* @return JPanel Object: mostradorCompleto (painel com o mostrador gráfico)
*/
private JPanel criarPainelMostrador(){
JPanel modulo2 = new JPanel();
modulo2.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
modulo2.add(getMostrador(), c);
JPanel mostradorCompleto = new JPanel();
mostradorCompleto.setLayout(new BoxLayout(mostradorCompleto, BoxLayout.PAGE_AXIS));
mostradorCompleto.add(modulo2);
mostradorCompleto.add(Box.createVerticalStrut(5));
return mostradorCompleto;
}
/**
* Instancia a área de desenho
*
* @return JSplitPane Object: spl_desenho (área de desenho)
*/
private JComponent criarAreaDeDesenho() {
spl_desenho = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true,
criarPainelMostrador(), getGA());
spl_desenho.setResizeWeight(0.7);
spl_desenho.resetToPreferredSizes();
return spl_desenho;
}
private GerenciadorArquivos getGA(){
if(ga == null){
ga = new GerenciadorArquivos();
ga.setPreferredSize(new Dimension(400, 50));
ga.addArquivoVisivelListener(new ArquivoVisivelEventListener() {
public void ficouInvisivel() {
spl_desenho.resetToPreferredSizes();
}
public void ficouVisivel() {
spl_desenho.resetToPreferredSizes();
}
});
}
return ga;
}
/**
* Instancia o console
*
* @return Console Object: console
*/
private Console getConsole(){
if(console == null){
console = new Console();
}
return console;
}
/**
* Instancia o alerta
*
* @return Alerta Object: alerta
*/
private Alerta getAlerta(){
if(alerta == null){
alerta = new Alerta();
}
return alerta;
}
}