440 lines
12 KiB
Vala
440 lines
12 KiB
Vala
namespace LAview {
|
|
|
|
namespace Table {
|
|
|
|
/**
|
|
* Row in the {@link Subtable}.
|
|
*/
|
|
public class Row : ADocList {
|
|
|
|
/**
|
|
* Expands {@link AddSpaces.Style}.
|
|
*/
|
|
public enum Style {
|
|
|
|
/**
|
|
* Default style.
|
|
*/
|
|
DEFAULT = 0,
|
|
|
|
/**
|
|
* Formal style for the first ``Row`` in the {@link Subtable}.
|
|
*/
|
|
FORMAL_FIRST,
|
|
|
|
/**
|
|
* Formal style for the middle ``Row`` in the {@link Subtable}.
|
|
*/
|
|
FORMAL_REST,
|
|
|
|
/**
|
|
* Formal style for the last ``Row`` in the {@link Subtable}.
|
|
*/
|
|
FORMAL_LAST,
|
|
|
|
/**
|
|
* Formal style for a single ``Row`` in the {@link Subtable}.
|
|
*/
|
|
FORMAL_SINGLE
|
|
}
|
|
|
|
/**
|
|
* Style of any operation on {@link ATable}/{@link Subtable} or ``Row``
|
|
* for lines preserving/creation.
|
|
*/
|
|
public enum OpLineStyle {
|
|
|
|
/**
|
|
* Do not anything with lines, "store as is".
|
|
*/
|
|
DEFAULT = 0,
|
|
|
|
/**
|
|
* Preserve vertical border.
|
|
*/
|
|
HBORDER = 1,
|
|
|
|
/**
|
|
* Preserve horizontal border.
|
|
*/
|
|
VBORDER = 2,
|
|
|
|
/**
|
|
* Preserve both vertical and horizontal borders.
|
|
*/
|
|
BORDER = 3,
|
|
|
|
/**
|
|
* Remove horizontal double lines.
|
|
*/
|
|
HDBLLINES = 4,
|
|
|
|
/**
|
|
* Remove vertical double lines.
|
|
*/
|
|
VDBLLINES = 8,
|
|
|
|
/**
|
|
* Remove both horizontal and vertical double lines.
|
|
*/
|
|
DBLLINES = 12,
|
|
|
|
/**
|
|
* Preserve any borders and remove any double lines.
|
|
*/
|
|
BORDER_DBLLINES = 15,
|
|
}
|
|
|
|
/**
|
|
* Any text before the ``Row``.
|
|
*/
|
|
public string before { get; set; default = ""; }
|
|
|
|
/**
|
|
* Style of any operation on {@link ATable}/{@link Subtable} or ``Row``
|
|
* for lines preserving/creation.
|
|
*/
|
|
public Style style { get; set; }
|
|
|
|
/**
|
|
* Top vertical spaces.
|
|
*/
|
|
public AddSpaces top { get; set; default = new AddSpaces (); }
|
|
|
|
/**
|
|
* Bottom vertical spaces.
|
|
*/
|
|
public AddSpace bottom { get; set; default = new AddSpace.with_params (""); }
|
|
|
|
/**
|
|
* Vertical spaces inside the {@link Subtable}
|
|
*/
|
|
public AddSpaces between { get; set; default = new AddSpaces (); }
|
|
|
|
/**
|
|
* Type of horizontal lines for the ``Row``.
|
|
*/
|
|
public enum LinesType {
|
|
|
|
/**
|
|
* ``Row`` has no horizontal lines.
|
|
*/
|
|
NONE = 0,
|
|
|
|
/**
|
|
* ``Row`` has continuous horizontal line on the top.
|
|
*/
|
|
HLINE,
|
|
|
|
/**
|
|
* ``Row`` has noncontinuous horizontal line on the top.
|
|
*/
|
|
CLINES
|
|
}
|
|
|
|
/**
|
|
* Constructs a new empty ``Row``.
|
|
*/
|
|
public Row () {}
|
|
|
|
protected override ADocList create_default_instance () { return new Row (); }
|
|
|
|
/**
|
|
* Gets a copy of the ``Row``.
|
|
*/
|
|
public override IDoc copy () {
|
|
var clone = base.copy () as Row;
|
|
clone.before = before;
|
|
clone.style = style;
|
|
clone.top = top;
|
|
clone.bottom = bottom.copy () as AddSpace;
|
|
clone.between = between.copy () as AddSpaces;
|
|
return clone;
|
|
}
|
|
|
|
enum Where { SEARCH_BEGIN = 0, SEARCH_END = 1 }
|
|
|
|
string row_to_lines (bool overline) {
|
|
var s = new StringBuilder ();
|
|
var lcount_row = copy () as Row;
|
|
LinesType lines_type = LinesType.HLINE;
|
|
|
|
while (lines_type != LinesType.NONE) {
|
|
lines_type = LinesType.NONE;
|
|
|
|
foreach (var cell in lcount_row as Gee.ArrayList<Cell>) {
|
|
if (overline && cell.noverlines != 0
|
|
|| !overline && cell.nunderlines != 0) {
|
|
if (lines_type == LinesType.NONE) {
|
|
if (lcount_row.index_of (cell) == 0)
|
|
lines_type = LinesType.HLINE;
|
|
else
|
|
lines_type = LinesType.CLINES;
|
|
}
|
|
} else {
|
|
if (lines_type == LinesType.HLINE)
|
|
lines_type = LinesType.CLINES;
|
|
}
|
|
}
|
|
|
|
if (lines_type != LinesType.NONE)
|
|
s.append_c ('\n');
|
|
|
|
if (lines_type == LinesType.HLINE) {
|
|
string line_style = "";
|
|
|
|
switch (lcount_row.style) {
|
|
case Style.FORMAL_FIRST:
|
|
line_style = overline ? "\\toprule" : "\\midrule";
|
|
break;
|
|
case Style.FORMAL_LAST:
|
|
line_style = overline ? "\\midrule" : "\\bottomrule";
|
|
break;
|
|
case Style.FORMAL_SINGLE:
|
|
line_style = overline ? "\\toprule" : "\\bottomrule";
|
|
break;
|
|
case Style.FORMAL_REST:
|
|
line_style = "\\midrule";
|
|
break;
|
|
default:
|
|
line_style = "\\hline";
|
|
break;
|
|
}
|
|
|
|
s.append (line_style);
|
|
} else if (lines_type == LinesType.CLINES) {
|
|
var clines_added = false;
|
|
|
|
uint cline_begin = 0, cline_end = 0;
|
|
var where = Where.SEARCH_BEGIN;
|
|
for (var idx = 0, max_idx = lcount_row.size; idx < max_idx; ++idx) {
|
|
var cell = lcount_row[idx] as Cell;
|
|
|
|
switch (where) {
|
|
case Where.SEARCH_BEGIN:
|
|
if (overline && cell.noverlines != 0
|
|
|| !overline && cell.nunderlines != 0) {
|
|
|
|
if (idx + 1 < max_idx
|
|
&& (overline && (lcount_row[idx + 1] as Cell).noverlines != 0
|
|
|| !overline && (lcount_row[idx + 1] as Cell).nunderlines != 0)) {
|
|
cline_end = cline_begin + cell.ncells;
|
|
where = Where.SEARCH_END;
|
|
} else {
|
|
if (clines_added)
|
|
s.append_c (' ');
|
|
s.append_printf (lcount_row.style != Style.DEFAULT ?
|
|
"\\cmidrule{%d-%d}" : "\\cline{%d-%d}",
|
|
cline_begin + 1,
|
|
cline_begin + cell.ncells);
|
|
cline_begin += cell.ncells;
|
|
clines_added = true;
|
|
}
|
|
} else {
|
|
cline_begin += cell.ncells;
|
|
}
|
|
break;
|
|
case Where.SEARCH_END:
|
|
if (idx + 1 >= max_idx
|
|
|| overline && (lcount_row[idx + 1] as Cell).noverlines == 0
|
|
|| !overline && (lcount_row[idx + 1] as Cell).nunderlines == 0) {
|
|
if (clines_added)
|
|
s.append_c (' ');
|
|
s.append_printf (lcount_row.style != Style.DEFAULT ?
|
|
"\\cmidrule{%d-%d}" : "\\cline{%d-%d}",
|
|
cline_begin + 1,
|
|
cline_end + cell.ncells);
|
|
cline_begin = cline_end + cell.ncells;
|
|
clines_added = true;
|
|
where = Where.SEARCH_BEGIN;
|
|
} else {
|
|
cline_end += cell.ncells;
|
|
}
|
|
break;
|
|
default:
|
|
assert (where == Where.SEARCH_BEGIN);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var cell in lcount_row as Gee.ArrayList<Cell>) {
|
|
if (overline && cell.noverlines != 0
|
|
|| !overline && cell.nunderlines != 0) {
|
|
if (overline)
|
|
--cell.noverlines;
|
|
else
|
|
--cell.nunderlines;
|
|
}
|
|
}
|
|
}
|
|
|
|
return s.str;
|
|
}
|
|
|
|
void process_opline_insert (Cell cell,
|
|
int index,
|
|
OpLineStyle line_style) {
|
|
if (size == 0) return;
|
|
|
|
if ((line_style & OpLineStyle.VBORDER) != 0) {
|
|
if (index < 0 || index >= size) {
|
|
var last_cell = get (size - 1) as Cell;
|
|
if (last_cell.multitype == Cell.Multitype.MULTICOL
|
|
|| last_cell.multitype == Cell.Multitype.MULTICOLROW)
|
|
cell.nrlines = last_cell.nrlines;
|
|
} else if (index == 0) {
|
|
if ((get (index) as Cell).multitype == Cell.Multitype.MULTICOL
|
|
|| (get (index) as Cell).multitype == Cell.Multitype.MULTICOLROW)
|
|
cell.nllines = (get (index) as Cell).nllines;
|
|
}
|
|
}
|
|
|
|
if ((line_style & OpLineStyle.VDBLLINES) != 0) {
|
|
var prev_index = index - 1;
|
|
|
|
if (index >= 0 && index < size) { // next == [index]
|
|
var idx_cell = get (index) as Cell;
|
|
if (idx_cell.multitype == Cell.Multitype.MULTICOL
|
|
|| idx_cell.multitype == Cell.Multitype.MULTICOLROW ) {
|
|
idx_cell.nllines = cell.nrlines != 0 || idx_cell.nllines != 0 ? 1 : 0;
|
|
cell.nrlines = 0;
|
|
}
|
|
} else {
|
|
prev_index = size - 1;
|
|
}
|
|
|
|
if (prev_index >= 0 && prev_index < size
|
|
&& (cell.multitype == Cell.Multitype.MULTICOL
|
|
|| cell.multitype == Cell.Multitype.MULTICOLROW)) {
|
|
var idx_cell = get (prev_index) as Cell;
|
|
cell.nllines = idx_cell.nrlines != 0 || cell.nllines != 0 ? 1 : 0;
|
|
idx_cell.nrlines = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a {@link Cell} from the ``Row``.
|
|
*
|
|
* @param cell {@link Cell} to remove.
|
|
* @param line_style {@link Row.OpLineStyle} of the operation.
|
|
*/
|
|
public new bool remove (Cell cell, Row.OpLineStyle line_style = Row.OpLineStyle.BORDER_DBLLINES) {
|
|
var index = index_of (cell);
|
|
if (index < 0 || index >= size) return false;
|
|
remove_at (index);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Removes a {@link Cell} from the ``Row`` at specified position.
|
|
*
|
|
* @param index position of the {@link Cell} to remove.
|
|
* @param line_style {@link Row.OpLineStyle} of the operation.
|
|
*/
|
|
public new Cell remove_at (int index, Row.OpLineStyle line_style = Row.OpLineStyle.BORDER_DBLLINES) {
|
|
var cell = get (index) as Cell;
|
|
if ((line_style & OpLineStyle.VBORDER) != 0
|
|
&& (cell.multitype == Cell.Multitype.MULTICOL
|
|
|| cell.multitype == Cell.Multitype.MULTICOLROW)) {
|
|
if (size > 1) {
|
|
if (index == 0)
|
|
(get (1) as Cell).nllines = cell.nllines;
|
|
else if (index == size - 1)
|
|
(get (size - 2) as Cell).nrlines = cell.nrlines;
|
|
}
|
|
|
|
if ((line_style & OpLineStyle.VDBLLINES) != 0) {
|
|
if (index > 0 && index + 1 < size) {
|
|
var prev = get (index - 1) as Cell,
|
|
next = get (index + 1) as Cell;
|
|
if (next.multitype == Cell.Multitype.MULTICOL
|
|
|| next.multitype == Cell.Multitype.MULTICOLROW) {
|
|
next.nllines = prev.nrlines != 0 || next.nllines != 0 ? 1 : 0;
|
|
prev.nrlines = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return base.remove_at (index) as Cell;
|
|
}
|
|
|
|
/**
|
|
* Inserts a {@link Cell} to the ``Row`` to specified position.
|
|
*
|
|
* @param index position to insert the {@link Cell}.
|
|
* @param cell {@link Cell} to insert.
|
|
* @param line_style {@link Row.OpLineStyle} of the operation.
|
|
*/
|
|
public new void insert (int index, Cell cell, OpLineStyle line_style = OpLineStyle.BORDER_DBLLINES) {
|
|
process_opline_insert (cell, index, line_style);
|
|
base.insert (index, cell);
|
|
}
|
|
|
|
/**
|
|
* Adds a {@link Cell} to the ``Row``.
|
|
*
|
|
* @param cell {@link Cell} to add.
|
|
* @param line_style {@link Row.OpLineStyle} of the operation.
|
|
*/
|
|
public new bool add (Cell cell, OpLineStyle line_style = OpLineStyle.BORDER_DBLLINES) {
|
|
process_opline_insert (cell, -1, line_style);
|
|
return base.add (cell);
|
|
}
|
|
|
|
/**
|
|
* Generates LaTeX string for the ``Row``.
|
|
*/
|
|
public override string generate () {
|
|
var s = new StringBuilder ();
|
|
|
|
/* {c,h}lines */
|
|
string tmps = row_to_lines (true);
|
|
s.append (tmps);
|
|
|
|
/* "top" additional space */
|
|
if (top.size != 0) {
|
|
top.style = style == Style.DEFAULT ? AddSpaces.Style.DEFAULT
|
|
: AddSpaces.Style.FORMAL;
|
|
s.append (top.generate ());
|
|
}
|
|
|
|
/* spaces before self */
|
|
if (before != "")
|
|
s.append (before);
|
|
|
|
/* rows contents */
|
|
foreach (var cell in this) {
|
|
if (this.index_of (cell) != 0) s.append_c ('&');
|
|
s.append (cell.generate ());
|
|
}
|
|
|
|
s.append ("\\tabularnewline");
|
|
|
|
/* "bottom" additional space */
|
|
if ((tmps = bottom.generate ()) != "") {
|
|
if (style == Style.DEFAULT)
|
|
s.append_printf ("[%s]", tmps);
|
|
else
|
|
s.append_printf ("\\addlinespace[%s]", tmps);
|
|
}
|
|
|
|
/* "between" additional space */
|
|
if (between.size != 0) {
|
|
between.style = style == Style.DEFAULT ? AddSpaces.Style.DEFAULT
|
|
: AddSpaces.Style.FORMAL;
|
|
s.append (between.generate ());
|
|
}
|
|
|
|
/* {c,h}lines */
|
|
tmps = row_to_lines (false);
|
|
s.append (tmps);
|
|
|
|
return s.str;
|
|
}
|
|
}
|
|
}
|
|
}
|