package tirateima.gui.arquivos;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import tirateima.gui.Constantes;
import tirateima.gui.variaveis.Janela;
import tirateima.gui.variaveis.Variavel;
/**
* Modela um arquivo binário de Pascal.
*
* @author Luciano
*/
public class VarFile extends AbstractArquivo{
private static final long serialVersionUID = 1L;
/**
* Modela um estado de VarFile
*
* @author Luciano
*/
private class EstadoVarFile {
/* O arquivo */
public File file = null;
public boolean is_opened = false;
public boolean read_only = true;
/* Indice do registro atual */
public int atual;
/* Registros no arquivo*/
public List<Variavel> registros = new ArrayList<Variavel>();
}
private Variavel tipo = null;
private ArrayList<Variavel> buffer = null;
private int atual = 0;
private JPanel pVisualizacao = null;
private int num_max_reg = 5;
private Color cor_fundo = Constantes.COR_FUNDO_NORMAL;
/** Cor do registro atual. */
public static final Color COR_ATUAL = Color.red;
/**
* Constrói uma nova variável do tipo arquivo binário (file)
* de Pascal, associando-a a um tipo de registro.
*
* @param nome Nome da variável.
* @param tipo Tipo dos registros nesse arquivo (deve derivar de Variavel).
*
* @throws Exception
*/
public VarFile(String nome, Variavel tipo){
super(nome);
assert tipo != null;
this.tipo = tipo.criarCopia();
this.buffer = new ArrayList<Variavel>();
inicializar();
}
public void reset() throws Exception{
open();
read_only = true;
}
public void rewrite() throws Exception {
if(is_opened){
close();
}
buffer = new ArrayList<Variavel>();
is_opened = true;
read_only = false;
}
/**
* Move para o registro informado.
*
* @param registro Registro a ser atingido.
*/
public void seek(int registro){
if(!is_opened){
throw new RuntimeException("Arquivo fechado!");
}
if((registro < 1) || (registro > buffer.size())){
throw new IllegalArgumentException("Registro inexistente: " + registro + "!");
}
atual = registro - 1;
}
public Object read() throws IOException{
if(eof()) throw new IOException("Fim de arquivo atingido.");
Variavel v = buffer.get(atual).criarCopia();
atual++;
return v.getValor();
}
public void write(Variavel v) {
if(read_only) {
throw new RuntimeException("Arquivo aberto em modo de leitura");
}
buffer.add(v.criarCopia());
}
public boolean eof() {
return atual == buffer.size();
}
public void close() throws IOException {
file = null;
buffer = null;
is_opened = false;
}
public int getNumMaxRegistros(){
return num_max_reg;
}
public void setNumMaxRegistros(int num){
if(num > 0){
num_max_reg = num;
}
}
public Dimension getMinimumSize(){
if (buffer != null) {
if (buffer.size() > 0) {
Dimension tj = buffer.get(0).getSize();
return new Dimension(tj.width * buffer.size(), tj.height + 20);
} else {
return new Dimension(0, 0);
}
} else {
return new Dimension(0, 0);
}
}
public Dimension getMaximumSize(){
Dimension d = getMinimumSize();
return new Dimension(d.width * 10, d.height * 10);
}
public Dimension getPreferredSize(){
return getMinimumSize();
}
private void inicializar(){
setLayout(new BorderLayout());
add(getSpPrincipal(), BorderLayout.CENTER);
}
private JScrollPane getSpPrincipal(){
if(spPrincipal == null){
spPrincipal = new JScrollPane(getPVisualizacao(), JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
}
return spPrincipal;
}
private JPanel getPVisualizacao(){
if(pVisualizacao == null){
pVisualizacao = new JPanel();
pVisualizacao.setLayout(new GridBagLayout());
pVisualizacao.setBackground(cor_fundo);
}
return pVisualizacao;
}
/**
* Abre o arquivo e carrega o buffer.
*
* @throws Exception Se não for possível obter um Reader
* para este arquivo.
*/
private void open() throws Exception{
if(file == null){
throw new IOException("Nenhum nome associado ao arquivo!");
}
if(is_opened){
close();
}
//Lê os registros
BufferedReader bf = new BufferedReader(getReader());
Variavel temp = tipo.criarCopia();
buffer = new ArrayList<Variavel>();
while(temp.readData(bf) == 0){
buffer.add(temp);
temp = tipo.criarCopia();
}
bf.close();
is_opened = true;
if(buffer.size() > 0){
seek(1);
}
}
private void atualizarVisualizacao(){
pVisualizacao.removeAll();
if(is_opened){
GridBagConstraints gb = new GridBagConstraints();
gb.insets = new Insets(1, 1, 1, 1);
gb.fill = GridBagConstraints.BOTH;
gb.anchor = GridBagConstraints.NORTHWEST;
gb.weightx = gb.weighty = 1.0;
gb.gridheight = gb.gridwidth = 1;
gb.gridy = gb.gridx = 0;
//Adiciona cada registro
int i = 1;
ListIterator<Variavel> it = buffer.listIterator();
Variavel temp;
Janela jatual = null;
while(it.hasNext()){
temp = it.next();
Janela j = new Janela(temp);
if(atual == i - 1){
j.setCorFundo(COR_ATUAL);
jatual = j;
}
j.setTitulo(String.valueOf(i));
pVisualizacao.add(j, gb);
gb.gridx++;
i++;
}
//Adiciona fim de arquivo
if(read_only) {
Variavel v = new RegistroEOF(tipo);
Janela j = new Janela(v);
pVisualizacao.add(j, gb);
if(jatual == null) jatual = j;
}
//Redimensiona
pVisualizacao.setSize(getMinimumSize());
spPrincipal.setSize(pVisualizacao.getSize());
setSize(getMinimumSize());
revalidate();
repaint();
//Move para registro atual
Rectangle r = new Rectangle(pVisualizacao.getX() + jatual.getX(), jatual.getY(),
jatual.getWidth(), jatual.getHeight());
if(atual <= buffer.size() - num_max_reg / 2){
r.width += jatual.getWidth() * (getNumMaxRegistros()/2);
}
spPrincipal.getViewport().scrollRectToVisible(r);
}
}
public Color getCorTitulo(){
return Color.blue;
}
//IEstado
public Object getEstado(){
EstadoVarFile e = new EstadoVarFile();
e.file = file;
e.is_opened = is_opened;
e.read_only = read_only;
e.registros.addAll(buffer);
e.atual = atual;
return e;
}
public void setEstado(Object estado){
buffer = null;
file = null;
is_opened = false;
atual = 0;
if(estado != null){
EstadoVarFile e = (EstadoVarFile) estado;
file = e.file;
if(is_opened = e.is_opened){
buffer = new ArrayList<Variavel>();
buffer.addAll(e.registros);
atual = e.atual;
}
read_only = e.read_only;
}
atualizarVisualizacao();
}
}