Relatórios com MEReport

06 novembro 2009 2 comentários

A maioria dos sistemas comerciais, seja móvel ou não, necessita de relatórios para mostrar de forma resumida a entrada e processamento dos dados. Através do blog Mobilidade é tudo descobrimos o MEReport, responsável por realizar essa tarefa de forma bastante simples.
A API ainda está sendo construída e precisando de desenvolvedores para contribuir no andamento do projeto. Quem quiser ajudar é só entrar em contato.

Segue uam prévia da classe Relatorio.java, que através da CustomItem, cria um layout de relatório com componentes personalizáveis.
import java.util.Vector;
import javax.microedition.lcdui.*;

class Relatorio extends CustomItem{
    private int minContentWidth;
    private int minContentHeight;
    
    private int prefContentHeight;
    private int prefContentWidth;
    
    private String title = "";
    private boolean titleBorder;
    private boolean titleFillColor;
    private int[] titleColorText;
    private int[] titleColorBack;
    private int[] titleColorBorder;
    private Font titleFont;
    private Font titleHeader;
    private short titleAlignment;
    
    public static final short LEFT = 0;
    public static final short CENTER = 1;
    public static final short RIGHT = 2;
    
    public String[] columnsText;
    
    public int[] columnsPercents;
    
    private boolean columnsBorder;
    private boolean columnsFillColor;
    private int[] columnsColorText;
    private int[] columnsColorBack;
    private int[] columnsColorBorder;
    private Font columnsFont;
    private short columnsAlignment;
    
    private Font textFont;
    private int[] textColor;
    private boolean textGridH;
    private boolean textGridV;
    private int[] textLinesColor;
    private Vector[] textData;
    private short textAlignment;
    
    private int[] posYInicial;
    private int[] posYFinal;
    
    private int indice;
    
    private Image imgBrasao;
    
    private int[] tamColunas;
    private int sobra;
    
    public Relatorio(int width, int height)
    {
        super("");
        
        titleFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE);
        titleColorText = new int[]{230, 230, 230};
        columnsColorText = new int[]{40, 40, 40};
        columnsFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        textFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        textColor = new int[]{0, 0, 0};
        
        titleAlignment = CENTER;
        titleBorder = true;
        titleColorBorder = new int[]{0, 0, 0};
        
        titleFillColor = true;
        titleColorBack = new int[]{50, 50, 50};
        
        prefContentHeight = height;
        prefContentWidth = width;
        
        minContentHeight = height;
        minContentWidth = width;
    }
    
    public void setImgBrasao(Image imgBrasao)
    {
        this.imgBrasao = imgBrasao;
    }
    
    //métodos referentes a barra superior, que contém o título
    //começo
    public void setTitle(String title)
    {
        this.title = title;
    }
    
    public void setTitleAlignment(short alignment)
    {
        this.titleAlignment = alignment;
    }
    
    public void setTitleFont(Font titleFont)
    {
        this.titleFont = titleFont;
    }
    
    public void setTitleFontHeader(Font titleFont)
    {
        this.titleHeader = titleFont;
    }
    
    public void setTitleBorder(boolean titleBorder)
    {
        this.titleBorder = titleBorder;
    }
    
    public void setTitleFillColor(boolean titleFillColor)
    {
        this.titleFillColor = titleFillColor;
    }
    
    public void setTitleColorText(int[] color)
    {
        this.titleColorText = color;
    }
    
    public void setTitleColorBack(int[] color)
    {
        this.titleColorBack = color;
    }
    
    public void setTitleColorBorder(int[] color)
    {
        this.titleColorBorder = color;
    }
    //fim
    
    //métodos referentes as colunas
    //começa
    
    public void setColumns(String[] columns)
    {
        this.columnsText = columns;
    }
    
    public void setColumnsPercents(int[] percents)
    {
        this.columnsPercents = percents;
        tamColunas = new int[columnsPercents.length];
        
        int total = 0;
        for (int i = percents.length-1; i >= 0; i--)
        {
            tamColunas[i] = ((prefContentWidth) / 100) * percents[i];
            total += tamColunas[i];
        }
        
        int sobra = ((prefContentWidth) - total) / 3;
        
        for (int i = percents.length-1; i >= 0; i--)
        {
            tamColunas[i] += sobra;
        }
    }
    
    public void setColumnsBorder(boolean columnsBorder)
    {
        this.columnsBorder = columnsBorder;
    }
    
    public void setColumnsFillColor(boolean fillColor)
    {
        this.columnsFillColor = fillColor;
    }
    
    public void setColumnsColorText(int[] color)
    {
        this.columnsColorText = color;
    }
    
    public void setColumnsColorBack(int[] color)
    {
        this.columnsColorBack = color;
    }
    
    public void setColumnsColorBorder(int[] color)
    {
        this.columnsColorBorder = color;
    }
    
    public void setColumnsFont(Font fontColumns)
    {
        this.columnsFont = fontColumns;
    }
    
    public void setColumnsAlignment(short alignment)
    {
        this.columnsAlignment = alignment;
    }
    
    //termina
    
    //métodos do texto
    //começa
    public void setTextFont(Font font)
    {
        this.textFont = font;
    }
    
    public void setTextData(Vector[] data)
    {
        this.textData = data;
    }
    
    public void setTextAlignment(short alignment)
    {
        this.textAlignment = alignment;
    }

    public void setTextColor(int[] color)
    {
        this.textColor = color;
    }
    
    public void setTextLineColor(int[] color)
    {
        this.textLinesColor = color;
    }
    
    public void setTextGridH(boolean grid)
    {
        this.textGridH = grid;
    }
    
    public void setTextGridV(boolean grid)
    {
        this.textGridV = grid;
    }
    //termina
    
    protected int getMinContentWidth() {
        return minContentWidth;
    }

    protected int getMinContentHeight() {
        return minContentHeight;
    }

    protected int getPrefContentWidth(int arg0) {
        return prefContentWidth;
    }

    protected int getPrefContentHeight(int arg0) {
        return prefContentHeight;
    }

    protected void paint(Graphics g, int largura, int altura) {
        int aux = 0;
        
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, largura, altura);
        
        int tamTitulo = Math.max( (titleFont.getHeight() + 2), 
                (imgBrasao == null?0:imgBrasao.getHeight()));
        
        //espaço do título
        //se a variável titleFillColor for true significa que o usuário quer que o 
        //espaço do título seja preenchida com a cor definida no vetor 
        //titleColorBack
        if (titleFillColor) // se sim, o título tem cor de fundo
        {
            g.setColor(titleColorBack[0], titleColorBack[1], titleColorBack[2]);
            
            g.fillRect(0, 0, largura, tamTitulo);
            
            if (imgBrasao != null)
            {
                g.drawImage(imgBrasao, 0, 0, Graphics.LEFT|Graphics.TOP);
            }
        }
        
        //configura a cor que vai ser usada no título, para isso usa a variável 
        //titleColorText
        //em seguida é verificado o alinhamento escolhido para o título
        //na variável 
        //titleAlignment
        //o título está armazenado na variável 
        //title
        g.setColor(titleColorText[0], titleColorText[1], titleColorText[2]);
        g.setFont(titleFont);
        if (titleAlignment == LEFT)
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/2, Graphics.LEFT|Graphics.TOP);
        else if (titleAlignment == CENTER)
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/2, Graphics.HCENTER|Graphics.TOP);
        else
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/26, Graphics.RIGHT|Graphics.TOP);
        
        //verifica se o usuário quer que o título seja contornado por uma borda
        //a variável titleBorder especifica isso
        //o vetor titleColorBorder Ccontém a cor da borda
        if (titleBorder) //verifica se o título tem borda
        {
            g.setColor(titleColorBorder[0], titleColorBorder[1], titleColorBorder[2]);
            g.drawRect(0, 0, largura, tamTitulo);
        }
        
        
        //desenha as colunas do título dos dados
        //ou seja, o cabeçalho
        aux = tamTitulo + 4;
        
        if (columnsFillColor)//se sim, as colunas tem background, senão, é transparente
        {
            int auxW = 0;
            g.setColor(columnsColorBack[0], columnsColorBack[1], columnsColorBack[2]);
            
            for (int i = 0; i < columnsText.length; i++)
            {
                g.fillRect(auxW - 1, aux, tamColunas[i]-1, 
                        titleHeader.getHeight() + 2);
                auxW += tamColunas[i];
            }
        }

        int auxW = 0;
        if (columnsBorder)
        {
            g.setColor(columnsColorBorder[0], columnsColorBorder[1], columnsColorBorder[2]);
            
            for (int i = 0; i < columnsText.length; i++)
            {
                g.drawRect(auxW - 1, aux, tamColunas[i]-1, 
                        titleHeader.getHeight() + 2);
                auxW += tamColunas[i];
            }
        }
        
        
        //escreve os títulos que representam os headers dos dados
        g.setColor(columnsColorText[0], columnsColorText[1], columnsColorText[2]);
        g.setFont(titleHeader);
        auxW = 0;
        for (int i = 0; i < columnsText.length; i++)
        {
            if (columnsAlignment == LEFT)
                g.drawString(columnsText[i], auxW, aux, Graphics.LEFT|Graphics.TOP);
            else if (columnsAlignment == RIGHT)
                g.drawString(columnsText[i], auxW + tamColunas[i] - 1, aux, 
                        Graphics.RIGHT|Graphics.TOP);
            else 
                g.drawString(columnsText[i], (auxW + tamColunas[i]/2), 
                        aux, Graphics.HCENTER|Graphics.TOP);
            auxW += tamColunas[i];
        }
        
        
        //Desenha as linhas verticais da tabela de dados
        aux += columnsFont.getHeight() + 8;
        g.setColor(0, 0, 0);
        g.drawLine(0, aux, largura, aux);
        
        if (textGridV)
        {
            g.setColor(textLinesColor[0], textLinesColor[1], textLinesColor[2]);
            
            auxW = 0;
            for (int i = 0; i < tamColunas.length-1; i++)
            {
                auxW += tamColunas[i];
                g.drawLine(auxW, aux, auxW, 
                    aux + (textFont.getHeight() * textData.length));
            }
        }
        
        //Desenha as linhas verticais da tabela de dados
        if (textGridH)
        {
            g.setColor(textLinesColor[0], textLinesColor[1], textLinesColor[2]);
            int aux2 = aux;
            for (int i = 0; i < textData.length; i++)
            {
                aux2 += textFont.getHeight();
                g.drawLine(0, aux2, largura, aux2);
            }
        }
        
        //preenche os valores da tabela
        posYInicial = new int[textData.length];
        posYFinal = new int[textData.length];
        
        g.setFont(textFont);
        for (int i = 0; i < textData.length; i++)
        {
            Vector dados = textData[i];
            auxW = 0;
            posYInicial[i] = aux;
            
            if (indice == i)
            {
                g.setColor(230, 230, 230);
                g.fillRect(0, aux+1, largura, textFont.getHeight()-1);
            }
            
            aux += textFont.getHeight();
            posYFinal[i] = aux;
            
            for (int j = 0; j < tamColunas.length; j++)
            {
                g.setColor(textColor[0], textColor[1], textColor[2]);
                if (textAlignment == LEFT)
                    g.drawString(dados.elementAt(j).toString(), auxW + 2, aux, 
                            Graphics.LEFT|Graphics.BOTTOM);
                auxW += tamColunas[j];
            }
        }
    }
    
    protected void pointerPressed(int x, int y)
    {
        for (int i = 0; i < posYFinal.length; i++)
        {
            if (y >= posYInicial[i] && y <= posYFinal[i])
            {
                indice = i;
                repaint();
                return;
            }
        }
    }
    
    protected void pointerDragged(int x, int y)
    {
    }
    
    protected void pointerReleased(int x, int y)
    {
    }
    
    protected boolean traverse(int dir, int viewportWidth, int viewportHeight, 
            int[] visRect_inout)
    {
        if (dir == 6)//pra baixo
        {
            if (indice < textData.length)
            {
                indice++;
                repaint();
                return true;
            }
            else 
            {
                return false;
            }
        }
        else if (dir == 1)//para cima
        {
            if (indice > 0)
            {
                indice--;
                repaint();
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return true;
        }
    }
    
    protected void traverseOut()
    {
        indice  = 0;
        repaint();
    }
}

A a classe MEReportMidlet.java mostra como podemos trabalhar com o MEReport.
import java.util.Vector;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MEReportMidlet extends MIDlet {
private Display display;

private Relatorio relatorio;

private StringItem titulo;
private Form fmMain;

private Font fonte;
private Font fonte2;
private Font fonte4;

private Image imgBrasao;

public void startApp() {
display = Display.getDisplay(this);

fmMain = new Form("Relatório de Cidades");
titulo = new StringItem("Estado: ", "Rio Grande do Sul");

fmMain.append(titulo);

try{
imgBrasao = Image.createImage("/brasao.PNG");
}
catch (Exception e){
System.out.println("Erro na imagem: " + e.getMessage());
}

relatorio = new Relatorio(fmMain.getWidth(), 200);
fonte = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE);
fonte2 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
fonte4 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
relatorio.setTitle("Cidades - RS");
relatorio.setImgBrasao(imgBrasao);
relatorio.setTitleBorder(true);
relatorio.setTitleFillColor(true);
relatorio.setTitleFont(fonte);
relatorio.setTitleFontHeader(fonte2);
relatorio.setTitleColorBack(new int[]{22, 50, 117});
relatorio.setTitleColorText(new int[]{255, 255, 255});
relatorio.setTitleColorBorder(new int[]{0, 0, 0});
relatorio.setTitleAlignment(Relatorio.CENTER);
relatorio.setColumns(new String[]{"Cód.", "Cidade", "Pop."});
relatorio.setColumnsAlignment(Relatorio.LEFT);
relatorio.setColumnsBorder(true);
relatorio.setColumnsColorBorder(new int[]{0, 0, 0});
relatorio.setColumnsColorBack(new int[]{200, 200, 255});
relatorio.setColumnsColorText(new int[]{0, 0, 0});
relatorio.setColumnsFillColor(true);
relatorio.setColumnsFont(fonte);
relatorio.setTextColor(new int[]{0, 0, 0});
relatorio.setTextLineColor(new int[]{22, 50, 117});
relatorio.setTextFont(fonte2);
relatorio.setTextGridH(true);
relatorio.setTextGridV(true);

Vector[] dados = new Vector[5];
Vector passoFundo = new Vector();
passoFundo.addElement("0");
passoFundo.addElement("Passo Fundo");
passoFundo.addElement("212.700");
Vector portoAlegre = new Vector();
portoAlegre.addElement("2");
portoAlegre.addElement("Porto Alegre");
portoAlegre.addElement("1.400.500");
Vector davidCanabarro = new Vector();
davidCanabarro.addElement("3");
davidCanabarro.addElement("David Canabarro");
davidCanabarro.addElement("960.300");
Vector gramado = new Vector();
gramado.addElement("5");
gramado.addElement("Gramado");
gramado.addElement("87.000");
Vector uruguaiana = new Vector();
uruguaiana.addElement("6");
uruguaiana.addElement("Uruguaiana");
uruguaiana.addElement("134.820");
dados[0] = passoFundo;
dados[1] = portoAlegre;
dados[2] = davidCanabarro;
dados[3] = gramado;
dados[4] = uruguaiana;
relatorio.setTextData(dados);

relatorio.setColumnsPercents(new int[]{10, 58, 32});

fmMain.append(relatorio);

display.setCurrent(fmMain);
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}
}

Referência: Mobilidade é tudo