/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2009, Benedikt Huber (benedikt.huber@gmail.com) 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 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.timing; import java.util.ArrayList; import java.util.List; import java.util.Vector; /** * Class for drawing tables on the console * FIXME: If available, replace by a proper library implementation. */ public class ConsoleTable { /** DEMO App */ public static void main(String argv[]) { System.out.println(demoTable().render()); } /** DEMO Table */ public static ConsoleTable demoTable() { ConsoleTable table = new ConsoleTable(); table.addColumn("Problem",Alignment.ALIGN_LEFT) .addColumn("Cost",Alignment.ALIGN_RIGHT) .addColumn("Gain",Alignment.ALIGN_RIGHT); table.addRow().addCell("Foo") .addCell(3) .addCell(4); table.addRow().addCell("Undef") .addCell("undefined",2,Alignment.ALIGN_LEFT); table.addRow().addCell("Waldemar Bankhofer") .addCell(32324); table.addRow().addCell("This is a long text, width 'span 3'",3,Alignment.ALIGN_LEFT); table.addRow().addCell("Too many columns (4)",3,Alignment.ALIGN_CENTER) .addCell("I'm at col 4"); table.addRow().addCell("Too many columns (5)",2,Alignment.ALIGN_CENTER) .addCell("Spanning to col 5",3,Alignment.ALIGN_RIGHT); return table; } static final String lineSeparator = System.getProperty ( "line.separator" ); public enum Alignment { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT }; /* cells */ private class TableCell { Alignment align; Object data; int pos; int span; TableCell(Object data, int pos, int span, Alignment align) { this.data = data; this.pos = pos; this.span = span; this.align = align; } public StringBuffer getAlignedString(int cwidth) { StringBuffer s = new StringBuffer(); s.append(' '); s.append(data.toString()); s.append(' '); int pad = cwidth - s.length(); int padLeft = 0, padRight = 0; switch(align) { case ALIGN_LEFT: padRight = cwidth - s.length();break; case ALIGN_RIGHT: padLeft = cwidth - s.length();break; case ALIGN_CENTER: padLeft = pad / 2; padRight = (pad+1) / 2; break; } for(int i = 0; i < padLeft; i++) s.insert(0,' '); for(int i = 0; i < padRight; i++) s.append(' '); return s; } } /** rows in the table, managing the corresponding cells */ public class TableRow { private int nextCol = 0; private ArrayList<TableCell> entries = new ArrayList<TableCell>(); public TableRow addCell(Object o) { return addCell(o,1, getColumn(nextCol).align); } public TableRow addCell(Object o, int colspan, Alignment align) { ensureColumn(nextCol + colspan - 1); entries.add(new TableCell(o, nextCol, colspan,align)); nextCol += colspan; return this; } } /* columns (specification, header) */ private class TableColumn { String name; String label; Alignment align; TableColumn(String name,String label, Alignment align) { this.name = name; this.label = label; this.align = align; } } private List<TableColumn> columns; private List<TableRow> rows; private List<String> topLegend = new ArrayList<String>(), bottomLegend = new ArrayList<String>(); private Vector<Integer> width; private int totalWidth; public ConsoleTable() { this.rows = new ArrayList<TableRow>(); this.columns = new ArrayList<TableColumn>(); } public ConsoleTable addColumn(String name, Alignment align) { this.columns.add(new TableColumn(name,name,align)); return this; } private TableColumn getColumn(int index) { ensureColumn(index); return columns.get(index); } private void ensureColumn(int index) { while(columns.size() <= index) { addColumn("Column "+(columns.size()+1),Alignment.ALIGN_LEFT); } } public TableRow addRow() { TableRow r = new TableRow(); rows.add(r); return r; } public void addLegendTop(String str) { this.topLegend.add(str); } public void addLegendBottom(String str) { this.bottomLegend.add(str); } public String render() { StringBuffer sb = new StringBuffer(); render(sb); return sb.toString(); } public void render(StringBuffer sb) { calculateWidth(); renderSep('=',sb); TableRow header = new TableRow(); for(TableColumn col : columns) { header.addCell(col.label,1,Alignment.ALIGN_CENTER); } renderRow(header,sb); renderSep('-',sb); if(this.topLegend.size() > 0) { for(String legend : this.topLegend) { renderRow(new TableRow().addCell(legend,columns.size(),Alignment.ALIGN_LEFT),sb); } renderSep('-',sb); } for(TableRow row : rows) { renderRow(row,sb); } if(this.bottomLegend.size() > 0) { renderSep('-',sb); for(String legend : this.bottomLegend) { renderRow(new TableRow().addCell(legend,columns.size(),Alignment.ALIGN_LEFT),sb); } } renderSep('=',sb); } private void renderRow(TableRow r, StringBuffer sb) { int i = 0; sb.append("|"); for(TableCell c : r.entries) { int cwidth = width.get(i++); for(int j = 0; j < c.span - 1; j++) { cwidth += width.get(i++) + 1; } sb.append(c.getAlignedString(cwidth)); sb.append("|"); } for(; i < columns.size(); i++) { renderChar(' ',width.get(i),sb);sb.append("|"); } sb.append('\n'); } private void renderSep(char sep, StringBuffer sb) { renderChar(sep,totalWidth,sb); sb.append('\n'); } private static void renderChar(char s, int count, StringBuffer sb) { for(int i = 0 ; i < count; i++) sb.append(s); } private void calculateWidth() { this.width = new Vector<Integer>(); for(TableColumn col : columns) { width.add(col.label.length()+2); } for(TableRow row : rows) { int i = 0; for(TableCell cell : row.entries) { int minwidth = cell.data.toString().length() + 2; // heuristic for(int j = 1; j < cell.span; j++) { minwidth -= width.get(i+j) + 1; } width.set(i, Math.max(width.get(i),minwidth)); i+=cell.span; } } this.totalWidth = 0; for(int w : width) { totalWidth += w; } totalWidth += width.size() + 1; } public static String getSepLine(char sep, int l) { StringBuffer sb = new StringBuffer(); renderChar(sep, l, sb); return sb.toString(); } }