/* * The JabaJaba class library * Copyright (C) 1997-2001 ASAMI, Tomoharu (asami@zeomtech.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 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.AsamiOffice.jaba2.text.cui; import java.util.*; import com.AsamiOffice.text.UString; import com.AsamiOffice.util.D2Array; /** * CTable * * @since Oct. 19, 1999 * @version Jan. 25, 2004 * @author ASAMI, Tomoharu (asami@zeomtech.com) */ public class CTable extends CNode { protected List columns_ = new ArrayList(); // List<ColumnInfo> protected D2Array head_ = new D2Array(); // D2Array<CTD> protected D2Array foot_ = new D2Array(); // D2Array<CTD> protected D2Array body_ = new D2Array(); // D2Array<CTD> protected ICKeisen keisen_; protected String keisenStyle_; public CTable(String style) { setKeisenStyle(style); } public void setKeisenStyle(String style) { keisenStyle_ = style; if ("jis".equals(style)) { keisen_ = new CJisKeisen(); } else { keisen_ = new CAsciiKeisen(); } } private ColumnInfo _getColumnInfo(int x) { if (columns_.size() > x) { ColumnInfo info = (ColumnInfo)columns_.get(x); return (info); } else { ColumnInfo info = new ColumnInfo(); for (int i = columns_.size();i <= x;i++) { columns_.add(i, null); } columns_.set(x, info); return (info); } } public void setColumnWidth(int x, int width) { ColumnInfo info = _getColumnInfo(x); info.width = width; } public void setColumnAlign(int x, String align) { ColumnInfo info = _getColumnInfo(x); info.align = align; } public void setHead(int x, int y, String data) { setHead(x, y, new CTD(data)); } public void setHead(int x, int y, CTD cell) { cell.setAlign("center"); head_.put(x, y, cell); } public void setFoot(int x, int y, String data) { setFoot(x, y, new CTD(data)); } public void setFoot(int x, int y, CTD cell) { cell.setAlign("center"); foot_.put(x, y, cell); } public void setBody(int x, int y, String data) { body_.put(x, y, new CTD(data)); } public void setBody(int x, int y, CTD cell) { body_.put(x, y, cell); } public void layout(int width) { draw(new CBoardBase()); // XXX } /* protected void _layoutData(D2Array data, int layoutWidth) { int width = data.getWidth(); int height = data.getHeight(); for (int y = 0;y < height;y++) { for (int x = 0;x < width;x++) { CTD cell = (CTD)data.get(x, y); int columnWidth = layoutWidth; // XXX if (cell != null) { cell.layout(columnWidth); } } } } */ public void draw(ICBoard board) { ColumnInfo[] columns = _makeColumns(); int width = body_.getWidth(); int posx = 0; int posy = 0; // top String topleft = _getTopLeft(); board.put(posx, posy, topleft); posx += UString.getHalfLength(topleft); String top = _getTop(); int topWidth = UString.getHalfLength(top); String topthinjoint = _getTopThinJoint(); int topthinjointWidth = UString.getHalfLength(topthinjoint); if (width > 0) { int columnWidth = columns[0].width; int loop = _calcLoopCount(columnWidth, topWidth); while (loop-- > 0) { board.put(posx, posy, top); posx += topWidth; } for (int x = 1;x < width;x++) { board.put(posx, posy, topthinjoint); posx += topthinjointWidth; columnWidth = columns[x].width; loop = _calcLoopCount(columnWidth, topWidth); while (loop-- > 0) { board.put(posx, posy, top); posx += topWidth; } } } String topright = _getTopRight(); board.put(posx, posy, topright); // posx = 0; posy = 1; if (head_.getHeight() > 0) { posy = _drawData(head_, posx, posy, columns, board); if (body_.getHeight() > 0 || foot_.getHeight() > 0) { String left = _getLeftThickJoint(); String right = _getRightThickJoint(); String joint = _getHThickVThinJoint(); String hline = _getThickHLine(); posy += _drawSeparatorLine( posx, posy, columns, left, right, joint, hline, board ); } } if (body_.getHeight() > 0) { posy = _drawData(body_, posx, posy, columns, board); if (foot_.getHeight() > 0) { String left = _getLeftThickJoint(); String right = _getRightThickJoint(); String joint = _getHThickVThinJoint(); String hline = _getThickHLine(); posy += _drawSeparatorLine( posx, posy, columns, left, right, joint, hline, board ); } } if (foot_.getHeight() > 0) { posy = _drawData(foot_, posx, posy, columns, board); } // bottom posx = 0; String bottomleft = _getBottomLeft(); board.put(posx, posy, bottomleft); posx += UString.getHalfLength(bottomleft); String bottom = _getBottom(); int bottomWidth = UString.getHalfLength(bottom); String bottomthinjoint = _getBottomThinJoint(); int bottomthinjointWidth = UString.getHalfLength(bottomthinjoint); if (width > 0) { int columnWidth = columns[0].width; int loop = _calcLoopCount(columnWidth, bottomWidth); while (loop-- > 0) { board.put(posx, posy, bottom); posx += bottomWidth; } for (int x = 1;x < width;x++) { board.put(posx, posy, bottomthinjoint); posx += bottomthinjointWidth; columnWidth = columns[x].width; loop = _calcLoopCount(columnWidth, bottomWidth); while (loop-- > 0) { board.put(posx, posy, bottom); posx += bottomWidth; } } } String bottomright = _getBottomRight(); board.put(posx, posy, bottomright); setWidth(posx); // XXX setHeight(posy + 1); // XXX } protected int _drawData( D2Array array, int posx, int posy, ColumnInfo[] columns, ICBoard board ) { int posy0 = posy; RowInfo[] rowInfos = _makeRows(array, columns); int width = array.getWidth(); int height = array.getHeight(); posy0 += _drawRow(array, 0, posx, posy0, columns, rowInfos, board); for (int y = 1;y < height;y++) { posy0 += _drawSeparatorLine(array, y - 1, posx, posy0, columns, board); posy0 += _drawRow(array, y, posx, posy0, columns, rowInfos, board); } return (posy0); } private int _drawRow( D2Array array, int y, int posx, int posy, ColumnInfo[] columns, RowInfo[] rows, ICBoard board ) { String left = _getLeft(); int leftWidth = UString.getHalfLength(left); String right = _getRight(); int rightWidth = UString.getHalfLength(right); String thinvline = _getThinVLine(); int thinvlineWidth = UString.getHalfLength(thinvline); String thinhline = _getThinHLine(); int thinhlineWidth = UString.getHalfLength(thinhline); int vLength = rows[y].height; int width = array.getWidth(); // left _drawVLine(posx, posy, vLength, left, board); posx += leftWidth; // body boolean isVline = false; for (int x = 0;x < width;x++) { if (isVline) { _drawVLine(posx, posy, vLength, thinvline, board); posx += thinvlineWidth; } CTD cell = (CTD)array.get(x, y); if (cell != null) { _setWidth(cell, columns, x, thinvlineWidth); cell.layout(columns[x].width); cell.draw(new CBoardView(board, posx, posy)); posx += columns[x].width; //System.out.println(cell.getColSpan()); if (cell.getColSpan() == 1) { isVline = true; } else { isVline = false; } } else { posx += columns[x].width; isVline = _isBoundaryCell(array, x, y); } if (!isVline) { posx += thinvlineWidth; } } // right _drawVLine(posx, posy, vLength, left, board); return (vLength); } private void _setWidth( CTD cell, ColumnInfo[] columns, int x, int lineWidth ) { int colspan = cell.getColSpan(); int sum = columns[x].width; while (--colspan > 0) { sum += lineWidth; sum += columns[++x].width; } cell.setWidth(sum); } private boolean _isBoundaryCell(D2Array array, int x, int y) { for (int x0 = x;x0 >= 0;x0--) { for (int y0 = y;y0 >= 0;y0--) { CTD cell = (CTD)array.get(x0, y0); if (cell != null) { int boundsX = x0 + cell.getColSpan() - 1; int boundsY = y0 + cell.getRowSpan() - 1; // System.out.println("pre;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); if (boundsY >= y) { if (boundsX == x) { // System.out.println("true;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); return (true); } if (boundsX > x) { // System.out.println("false;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); return (false); } } } } } return (false); // throw (new InternalError()); } private int _drawSeparatorLine( int posx, int posy, ColumnInfo[] columns, String left, String right, String joint, String hline, ICBoard board ) { board.put(posx, posy, left); posx += UString.getHalfLength(left); int lineWidth = UString.getHalfLength(hline); int loop = _calcLoopCount(columns[0].width, lineWidth); while (loop-- > 0) { board.put(posx, posy, hline); posx += lineWidth; } for (int i = 1;i < columns.length;i++) { lineWidth = UString.getHalfLength(joint); board.put(posx, posy, joint); posx += lineWidth; lineWidth = UString.getHalfLength(hline); loop = _calcLoopCount(columns[i].width, lineWidth); while (loop-- > 0) { board.put(posx, posy, hline); posx += lineWidth; } } board.put(posx, posy, right); return (1); } private int _drawSeparatorLine( D2Array data, int y, int posx, int posy, ColumnInfo[] columns, ICBoard board ) { String left = _getLeftThinJoint(); int leftWidth = UString.getHalfLength(left); String right = _getRightThinJoint(); int rightWidth = UString.getHalfLength(right); String thinhline = _getThinHLine(); int thinhlineWidth = UString.getHalfLength(thinhline); String joint = _getHThinVThinJoint(); int jointWidth = UString.getHalfLength(joint); int width = data.getWidth(); board.put(posx, posy, left); posx += leftWidth; if (_isVSeparate(data, 0, y)) { int loop = _calcLoopCount(columns[0].width, thinhlineWidth); while (loop-- > 0) { board.put(posx, posy, thinhline); posx += thinhlineWidth; } } else { posx += columns[0].width; } for (int x = 1;x < width;x++) { joint = _getJoint(data, x - 1, y); if (joint != null) { board.put(posx, posy, joint); } posx += jointWidth; if (_isVSeparate(data, x, y)) { int loop = _calcLoopCount(columns[x].width, thinhlineWidth); while (loop-- > 0) { board.put(posx, posy, thinhline); posx += thinhlineWidth; } } else { posx += columns[x].width; } } board.put(posx, posy, right); return (1); } private String _getJoint(D2Array data, int x, int y) { if (_isBoundaryCell(data, x, y) || _isVSeparate(data, x, y)) { return (_getHThinVThinJoint()); } else { return (null); } } private boolean _isVSeparate(D2Array data, int x, int y) { for (int x0 = x;x0 >= 0;x0--) { for (int y0 = y;y0 >= 0;y0--) { CTD cell = (CTD)data.get(x0, y0); if (cell != null) { int boundsX = x0 + cell.getColSpan() - 1; int boundsY = y0 + cell.getRowSpan() - 1; // System.out.println("pre;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); if (boundsX >= x) { if (boundsY == y) { // System.out.println("true;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); return (true); } if (boundsY > y) { // System.out.println("false;x = " + x + " y = " + y + " boundsX = " + boundsX + " boundsY = " + boundsY); return (false); } } } } } return (false); } protected void _drawVLine( int posx, int posy, int length, String bar, ICBoard board ) { while (length-- > 0) { board.put(posx, posy++, bar); } } protected ColumnInfo[] _makeColumns() { int nColumns = 0; if (head_ != null) { nColumns = Math.max(head_.getWidth(), nColumns); } if (foot_ != null) { nColumns = Math.max(foot_.getWidth(), nColumns); } if (body_ != null) { nColumns = Math.max(body_.getWidth(), nColumns); } int[] columns = new int[nColumns]; _makeColumns(head_, columns); _makeColumns(foot_, columns); _makeColumns(body_, columns); ColumnInfo[] infos = new ColumnInfo[nColumns]; for (int i = 0;i < nColumns;i++) { ColumnInfo info = _getColumnInfo(i); if (info.width == 0) { info.width = columns[i]; } infos[i] = info; } return (infos); } protected void _makeColumns(D2Array data, int[] columns) { int width = data.getWidth(); int height = data.getHeight(); for (int x = 0;x < width;x++) { int columnWidth = columns[x]; for (int y = 0;y < height;y++) { CTD cell = (CTD)data.get(x, y); if (cell != null) { String text = cell.getText(); columnWidth = Math.max(columnWidth, UCUI.getWidth(text)); columnWidth = _adjustWidth(columnWidth); } } columns[x] = columnWidth; } } protected RowInfo[] _makeRows(D2Array data, ColumnInfo[] columns) { int width = data.getWidth(); int height = data.getHeight(); RowInfo[] infos = new RowInfo[height]; for (int y = 0;y < height;y++) { RowInfo info = new RowInfo(); for (int x = 0;x < width;x++) { CTD cell = (CTD)data.get(x, y); if (cell != null) { switch (cell.getRowSpan()) { case 1: info.height = Math.max( info.height, _calcNLine( cell.getText(), _calcWidth(cell.getColSpan(), columns, x) ) ); break; default: // XXX } } } infos[y] = info; } return (infos); } protected int _calcNLine(String text, int width) { String[] chunks = UCUI.getLines(text, width); return (chunks.length); } protected int _calcWidth(int colspan, ColumnInfo[] infos, int x) { int width = 0; if (colspan > 0) { width = infos[x].width; while (--colspan > 0) { width += UString.getHalfLength(_getThinVLine()); width += infos[++x].width; } } return (width); } protected String _getTopLeft() { return (keisen_.getTopLeft()); } protected String _getTopRight() { return (keisen_.getTopRight()); } protected String _getBottomLeft() { return (keisen_.getBottomLeft()); } protected String _getBottomRight() { return (keisen_.getBottomRight()); } protected String _getTop() { return (keisen_.getTop()); } protected String _getBottom() { return (keisen_.getBottom()); } protected String _getLeft() { return (keisen_.getLeft()); } protected String _getRight() { return (keisen_.getRight()); } protected String _getLeftThickJoint() { return (keisen_.getLeftThickJoint()); } protected String _getRightThickJoint() { return (keisen_.getRightThickJoint()); } protected String _getLeftThinJoint() { return (keisen_.getLeftThinJoint()); } protected String _getRightThinJoint() { return (keisen_.getRightThinJoint()); } protected String _getThickHLine() { return (keisen_.getThickHLine()); } protected String _getThickVLine() { return (keisen_.getThickVLine()); } protected String _getThinHLine() { return (keisen_.getThinHLine()); } protected String _getThinVLine() { return (keisen_.getThinVLine()); } protected String _getTopThickJoint() { return (keisen_.getTopThickJoint()); } protected String _getBottomThickJoint() { return (keisen_.getBottomThickJoint()); } protected String _getTopThinJoint() { return (keisen_.getTopThinJoint()); } protected String _getBottomThinJoint() { return (keisen_.getBottomThinJoint()); } protected String _getHThickVThickJoint() { return (keisen_.getHThickVThickJoint()); } protected String _getHThickVThinJoint() { return (keisen_.getHThickVThinJoint()); } protected String _getHThinVThickJoint() { return (keisen_.getHThinVThickJoint()); } protected String _getHThinVThinJoint() { return (keisen_.getHThinVThinJoint()); } private int _adjustWidth(int width) { if (!"jis".equals(keisenStyle_)) { return (width); } return (width + (width % 2)); } private int _calcLoopCount(int width, int lineWidth) { return (UCUI.calcHLineLoopCount(width, lineWidth)); } static class ColumnInfo { int width; String align = "left"; public String[] makeData(String data) { List list = new ArrayList(); StringBuffer buffer = new StringBuffer(); String[] lines = UString.makeStringList(data); int curWidth = 0; for (int i = 0;i < lines.length;i++) { String string = lines[i]; int size = string.length(); for (int j = 0;j < size;j++) { char c = string.charAt(j); if (UString.isWideCharacter(c)) { if (curWidth + 1 == width) { buffer.append(" "); list.add(new String(buffer)); buffer = new StringBuffer(); buffer.append(c); curWidth = 2; } else { buffer.append(c); if (curWidth + 2 == width) { list.add(new String(buffer)); buffer = new StringBuffer(); curWidth = 0; } else { curWidth += 2; } } } else { buffer.append(c); if (curWidth + 1 == width) { list.add(new String(buffer)); buffer = new StringBuffer(); curWidth = 0; } else { curWidth++; } } } int curSize = UString.getHalfLength(new String(buffer)); if (curSize > 0) { int count = width - curSize; while (count-- > 0) { buffer.append(" "); } list.add(new String(buffer)); buffer = new StringBuffer(); curWidth = 0; } } String[] result = new String[list.size()]; return ((String[])list.toArray(result)); } }; static class RowInfo { int height = 0; String align = "right"; }; }