具体的なプロトタイプ設計に入る前に、別のアイデアを忘れてしまわないようにメモ書きしておきます。今回、当初の目標はHTMLのtableと同程度の表現能力を考えています。さて、表現能力の獲得はがんばればよいとして、その3で紹介したようにセルが結合されているような表をAPIで指定していくのは面倒くさそうです。たとえば、こんな感じになるんでしょうか。
Hogan h = new Hogan(); // (3, 2)の位置のセルでセル幅を2にして結合 h.setColumnSpan(3, 2, 2); // (4, 6)の位置のセルでセル高を2にして結合 h.setRowSpan(4, 6, 2);
これはこれで必要なAPIですが、これだけで表を作り上げていくのはかなり面倒くさそうです。ですので、下記のようなイメージで、流行の流れるインタフェースというのを使ってはどうかと考えています。
// Builderを通してほぼHTMLの感覚でかける。
Hogan h = HoganBuilder.table()
.thead().tr()
.th("銘柄", Style.rowSpan(2))
.th("始値")
.th("高値")
.th("前日比")
.th("出来高", Style.rowSpan(2))
.th("売気配")
.tr()
.th("終値")
.th("安値")
.th("前日比%")
.th("買気配)
.tbody().tr()
.td("ABC", Style.rowSpan(2))
.td(6460, Style.decimalFormat("#,##0"))
.td(7360, Style.decimalFormat("#,##0"))
.td(2000, Style.decimalFormat("+#,##0;-#,##0"))
.td(1275, Style.decimalFormat("#,##0").rowSpan(2))
.td("---", Style.decimalFormat("#,##0"))
.tr()
.td(7360, Style.decimalFormat("#,##0"))
.td(6020, Style.decimalFormat("#,##0"))
.td(0.373, Style.decimalFormat("+##0.0%;-##0.0%"))
.td(7360, Style.decimalFormat("#,##0"));
// 行の追加
h.addRow(HoganBuilder.tr()
.td("DEF", Style.rowSpan(2))
.td(55000, Style.decimalFormat("#,##0"))
.td(56000, Style.decimalFormat("#,##0"))
.td(-1800, Style.decimalFormat("+#,##0;-#,##0"))
.td(61899, Style.decimalFormat("#,##0").rowSpan(2))
.td(52800, Style.decimalFormat("#,##0"))
.tr()
.td(52700, Style.decimalFormat("#,##0"))
.td(52200, Style.decimalFormat("#,##0"))
.td(-0.033, Style.decimalFormat("+##0.0%;-##0.0%"))
.td(52700, Style.decimalFormat("#,##0")));
// 行の追加
h.addRow(HoganBuilder.tr()
.td("GEF", Style.rowSpan(2))
.td(32350, Style.decimalFormat("#,##0"))
.td(32400, Style.decimalFormat("#,##0"))
.td(300, Style.decimalFormat("+#,##0;-#,##0"))
.td(144616, Style.decimalFormat("#,##0").rowSpan(2))
.td("---", Style.decimalFormat("#,##0"))
.tr()
.td(30650, Style.decimalFormat("#,##0"))
.td(30100, Style.decimalFormat("#,##0"))
.td(0.009, Style.decimalFormat("+##0.0%;-##0.0%"))
.td("---", Style.decimalFormat("#,##0")));

このようにかければ、わりと拡張の融通も利きそうですし、HTMLで表を作ったことがある人ならば、違和感なく使えると思います。スタイルの指定をどうするかはもう少しアイデアを練り込む必要がありそうです。なお、上記の例では毎回、それぞれの行で書式を指定していますが、このあたりは冗長に見えるので、テンプレート機能のようなものを用意しても良いだろうと思っています。
// 株価クラス
public class StockPrice {
private String symbol;
private int startPrice;
private int endPrice;
private int highPrice;
private int lowPrice;
private long volume;
private int diff;
private float diffPercent;
private int ask;
private int bid;
public void setSymbol(String symbol) { this.symbol = symbol; }
public String getSymbol() { return this.symbol; }
... // 以下 setter/getterやコンストラクタなど
}
// 株価情報
StockPrice s = new StockPrice("DEF", 55000, 52700
, 56000, 52200
, -1800, -0.033f
, 61899
, 52800, 52700);
Hogan h = ... /// ... ベースとなる表の作成
RowTemplate tmpl = RowTemplateBuilder.tr()
.td("symbol", Style.rowSpan(2))
.td("startPrice", Style.decimalFormat("#,##0"))
.td("highPrice", Style.decimalFormat("#,##0"))
.td("diff", Style.decimalFormat("+#,##0;-#,##0"))
.td("volume", Style.decimalFormat("#,##0").rowSpan(2))
.td("bid", Style.decimalFormat("#,##0"))
.tr()
.td("endPrice", Style.decimalFormat("#,##0"))
.td("lowPrice", Style.decimalFormat("#,##0"))
.td("diffPercent", Style.decimalFormat("+##0.0%;-##0.0%"))
.td("ask", Style.decimalFormat("#,##0")));
// 株価情報JavaBeanからテンプレートに沿って行に展開
h.addRow(tmpl.newRow(s));
このようにたとえばRowTemplate・RowTemplateBuilderのようなクラスを作っておき、実際に付け加えるデータはStockPriceインスタンスのように管理しやすいままの形で複雑な形式の行を追加します。この例でのRowTemplateBuilderのtd(“symbol”, … のような第一引数はプロパティ名です(拡張してELに対応するか、BeansBindingに対応してもおもしろいですね)。ここではJavaBeanに対するアクセスを考えていますが当然、HashMap等にも応用できます。
この例は表示スタイルについてのみ定義していますが、ほかの発展イメージとしてはバリデーションルールの追加や、エディタやレンダラの指定なども考えられます。
