mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Support varwidth's V tabular column type
This effectively enables linebreaks, multipars and layout changes in non-fixed width (i.e., standard) table columns. Fixes: #6577 TODO: metrics are wrong (too wide) on screen with linebreaks.
This commit is contained in:
parent
620efb3540
commit
9dcb24d578
@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be
|
|||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
2018-07-01 Jürgen Spitzmüller <spitz@lyx.org>
|
||||||
|
* format incremented to 555: Support varwidth's V tabular column type.
|
||||||
|
This effectively enables linebreaks, multipars and layout changes in
|
||||||
|
non-fixed width (i.e., standard) table columns.
|
||||||
|
|
||||||
2018-06-23 Jürgen Spitzmüller <spitz@lyx.org>
|
2018-06-23 Jürgen Spitzmüller <spitz@lyx.org>
|
||||||
* format incremented to 554: Support tabularx and xltabular:
|
* format incremented to 554: Support tabularx and xltabular:
|
||||||
- add column flag "varwidth=true", which will output column type 'X'
|
- add column flag "varwidth=true", which will output column type 'X'
|
||||||
|
@ -5431,6 +5431,35 @@ varioref
|
|||||||
the page of the referred label.
|
the page of the referred label.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Subsubsection
|
||||||
|
varwidth
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Description
|
||||||
|
Found:
|
||||||
|
\begin_inset Info
|
||||||
|
type "package"
|
||||||
|
arg "varwidth"
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Description
|
||||||
|
CTAN:
|
||||||
|
\family typewriter
|
||||||
|
macros/latex/contrib/varwidth/
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Description
|
||||||
|
Notes: The package
|
||||||
|
\family sans
|
||||||
|
varwidth
|
||||||
|
\family default
|
||||||
|
\color none
|
||||||
|
is needed to allow for line and paragraph breaks in standard tabular columns.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Subsection
|
\begin_layout Subsection
|
||||||
xltabular
|
xltabular
|
||||||
\end_layout
|
\end_layout
|
||||||
@ -6750,7 +6779,7 @@ Notes: The package
|
|||||||
varwidth
|
varwidth
|
||||||
\family default
|
\family default
|
||||||
\color none
|
\color none
|
||||||
is used to produce minipages variable (i.
|
is used to produce minipages of variable (i.
|
||||||
\begin_inset space \thinspace{}
|
\begin_inset space \thinspace{}
|
||||||
\end_inset
|
\end_inset
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@ import sys, os
|
|||||||
|
|
||||||
# Uncomment only what you need to import, please.
|
# Uncomment only what you need to import, please.
|
||||||
|
|
||||||
from parser_tools import (find_end_of_inset, find_end_of_layout, find_token,
|
from parser_tools import (count_pars_in_inset, find_end_of_inset, find_end_of_layout,
|
||||||
get_bool_value, get_value, get_quoted_value)
|
find_token, get_bool_value, get_option_value, get_value, get_quoted_value)
|
||||||
# del_token, del_value, del_complete_lines,
|
# del_token, del_value, del_complete_lines,
|
||||||
# find_complete_lines, find_end_of,
|
# find_complete_lines, find_end_of,
|
||||||
# find_re, find_substring, find_token_backwards,
|
# find_re, find_substring, find_token_backwards,
|
||||||
# get_containing_inset, get_containing_layout,
|
# get_containing_inset, get_containing_layout,
|
||||||
# is_in_inset, set_bool_value
|
# is_in_inset, set_bool_value
|
||||||
# find_tokens, find_token_exact, check_token, get_option_value
|
# find_tokens, find_token_exact, check_token
|
||||||
|
|
||||||
from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble)
|
from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble)
|
||||||
# revert_font_attrs, insert_to_preamble, latex_length
|
# revert_font_attrs, insert_to_preamble, latex_length
|
||||||
@ -345,6 +345,100 @@ def revert_stretchcolumn(document):
|
|||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
|
|
||||||
|
def revert_vcolumns(document):
|
||||||
|
" Revert standard columns with line breaks etc. "
|
||||||
|
i = 0
|
||||||
|
needvarwidth = False
|
||||||
|
needarray = False
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
i = find_token(document.body, "\\begin_inset Tabular", i)
|
||||||
|
if i == -1:
|
||||||
|
return
|
||||||
|
j = find_end_of_inset(document.body, i)
|
||||||
|
if j == -1:
|
||||||
|
document.warning("Malformed LyX document: Could not find end of tabular.")
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Collect necessary column information
|
||||||
|
m = i + 1
|
||||||
|
nrows = int(document.body[i+1].split('"')[3])
|
||||||
|
ncols = int(document.body[i+1].split('"')[5])
|
||||||
|
col_info = []
|
||||||
|
for k in range(ncols):
|
||||||
|
m = find_token(document.body, "<column", m)
|
||||||
|
width = get_option_value(document.body[m], 'width')
|
||||||
|
varwidth = get_option_value(document.body[m], 'varwidth')
|
||||||
|
alignment = get_option_value(document.body[m], 'alignment')
|
||||||
|
special = get_option_value(document.body[m], 'special')
|
||||||
|
col_info.append([width, varwidth, alignment, special, m])
|
||||||
|
|
||||||
|
# Now parse cells
|
||||||
|
m = i + 1
|
||||||
|
lines = []
|
||||||
|
for row in range(nrows):
|
||||||
|
for col in range(ncols):
|
||||||
|
m = find_token(document.body, "<cell", m)
|
||||||
|
multicolumn = get_option_value(document.body[m], 'multicolumn')
|
||||||
|
multirow = get_option_value(document.body[m], 'multirow')
|
||||||
|
width = get_option_value(document.body[m], 'width')
|
||||||
|
rotate = get_option_value(document.body[m], 'rotate')
|
||||||
|
# Check for: linebreaks, multipars, non-standard environments
|
||||||
|
begcell = m
|
||||||
|
endcell = find_token(document.body, "</cell>", begcell)
|
||||||
|
vcand = False
|
||||||
|
if find_token(document.body, "\\begin_inset Newline", begcell, endcell) != -1:
|
||||||
|
vcand = True
|
||||||
|
elif count_pars_in_inset(document.body, begcell + 2) > 1:
|
||||||
|
vcand = True
|
||||||
|
elif get_value(document.body, "\\begin_layout", begcell) != "Plain Layout":
|
||||||
|
vcand = True
|
||||||
|
if vcand and rotate == "" and ((multicolumn == "" and multirow == "") or width == ""):
|
||||||
|
if col_info[col][0] == "" and col_info[col][1] == "" and col_info[col][3] == "":
|
||||||
|
needvarwidth = True
|
||||||
|
alignment = col_info[col][2]
|
||||||
|
col_line = col_info[col][4]
|
||||||
|
vval = ""
|
||||||
|
if alignment == "center":
|
||||||
|
vval = ">{\\centering}"
|
||||||
|
elif alignment == "left":
|
||||||
|
vval = ">{\\raggedright}"
|
||||||
|
elif alignment == "right":
|
||||||
|
vval = ">{\\raggedleft}"
|
||||||
|
if vval != "":
|
||||||
|
needarray = True
|
||||||
|
vval += "V{\\linewidth}"
|
||||||
|
|
||||||
|
document.body[col_line] = document.body[col_line][:-1] + " special=\"" + vval + "\">"
|
||||||
|
# ERT newlines and linebreaks (since LyX < 2.4 automatically inserts parboxes
|
||||||
|
# with newlines, and we do not want that)
|
||||||
|
while True:
|
||||||
|
endcell = find_token(document.body, "</cell>", begcell)
|
||||||
|
linebreak = False
|
||||||
|
nl = find_token(document.body, "\\begin_inset Newline newline", begcell, endcell)
|
||||||
|
if nl == -1:
|
||||||
|
nl = find_token(document.body, "\\begin_inset Newline linebreak", begcell, endcell)
|
||||||
|
if nl == -1:
|
||||||
|
break
|
||||||
|
linebreak = True
|
||||||
|
nle = find_end_of_inset(document.body, nl)
|
||||||
|
del(document.body[nle:nle+1])
|
||||||
|
if linebreak:
|
||||||
|
document.body[nl:nl+1] = put_cmd_in_ert("\\linebreak{}")
|
||||||
|
else:
|
||||||
|
document.body[nl:nl+1] = put_cmd_in_ert("\\\\")
|
||||||
|
m += 1
|
||||||
|
|
||||||
|
i = j + 1
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if needarray == True:
|
||||||
|
add_to_preamble(document, ["\\usepackage{array}"])
|
||||||
|
if needvarwidth == True:
|
||||||
|
add_to_preamble(document, ["\\usepackage{varwidth}"])
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Conversion hub
|
# Conversion hub
|
||||||
#
|
#
|
||||||
@ -360,10 +454,12 @@ convert = [
|
|||||||
[551, []],
|
[551, []],
|
||||||
[552, []],
|
[552, []],
|
||||||
[553, []],
|
[553, []],
|
||||||
[554, []]
|
[554, []],
|
||||||
|
[555, []]
|
||||||
]
|
]
|
||||||
|
|
||||||
revert = [
|
revert = [
|
||||||
|
[554, [revert_vcolumns]],
|
||||||
[553, [revert_stretchcolumn]],
|
[553, [revert_stretchcolumn]],
|
||||||
[552, [revert_tuftecite]],
|
[552, [revert_tuftecite]],
|
||||||
[551, [revert_floatpclass, revert_floatalignment]],
|
[551, [revert_floatpclass, revert_floatalignment]],
|
||||||
|
@ -160,7 +160,8 @@ ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, bool redo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width)
|
bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width,
|
||||||
|
bool const expand_on_multipars)
|
||||||
{
|
{
|
||||||
LBUFERR(mi.base.textwidth > 0);
|
LBUFERR(mi.base.textwidth > 0);
|
||||||
max_width_ = mi.base.textwidth;
|
max_width_ = mi.base.textwidth;
|
||||||
@ -170,7 +171,7 @@ bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width)
|
|||||||
dim_ = Dimension();
|
dim_ = Dimension();
|
||||||
dim_.wid = min_width;
|
dim_.wid = min_width;
|
||||||
pit_type const npar = text_->paragraphs().size();
|
pit_type const npar = text_->paragraphs().size();
|
||||||
if (npar > 1)
|
if (npar > 1 && expand_on_multipars)
|
||||||
// If there is more than one row, expand the text to
|
// If there is more than one row, expand the text to
|
||||||
// the full allowable width.
|
// the full allowable width.
|
||||||
dim_.wid = max_width_;
|
dim_.wid = max_width_;
|
||||||
|
@ -55,7 +55,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/// compute text metrics.
|
/// compute text metrics.
|
||||||
bool metrics(MetricsInfo & mi, Dimension & dim, int min_width = 0);
|
bool metrics(MetricsInfo & mi, Dimension & dim, int min_width = 0,
|
||||||
|
bool const expand_on_multipars = true);
|
||||||
|
|
||||||
///
|
///
|
||||||
void newParMetricsDown();
|
void newParMetricsDown();
|
||||||
|
@ -917,8 +917,11 @@ void Tabular::updateIndexes()
|
|||||||
// reset column and row of cells and update their width and alignment
|
// reset column and row of cells and update their width and alignment
|
||||||
for (row_type row = 0; row < nrows(); ++row)
|
for (row_type row = 0; row < nrows(); ++row)
|
||||||
for (col_type column = 0; column < ncols(); ++column) {
|
for (col_type column = 0; column < ncols(); ++column) {
|
||||||
if (isPartOfMultiColumn(row, column))
|
if (isPartOfMultiColumn(row, column)) {
|
||||||
|
cell_info[row][column].inset->toggleMultiCol(true);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
cell_info[row][column].inset->toggleMultiCol(false);
|
||||||
// columnofcell needs to be called before setting width and aligment
|
// columnofcell needs to be called before setting width and aligment
|
||||||
// multirow cells inherit the width from the column width
|
// multirow cells inherit the width from the column width
|
||||||
if (!isPartOfMultiRow(row, column)) {
|
if (!isPartOfMultiRow(row, column)) {
|
||||||
@ -926,8 +929,11 @@ void Tabular::updateIndexes()
|
|||||||
rowofcell[i] = row;
|
rowofcell[i] = row;
|
||||||
}
|
}
|
||||||
setFixedWidth(row, column);
|
setFixedWidth(row, column);
|
||||||
if (isPartOfMultiRow(row, column))
|
if (isPartOfMultiRow(row, column)) {
|
||||||
|
cell_info[row][column].inset->toggleMultiRow(true);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
cell_info[row][column].inset->toggleMultiRow(false);
|
||||||
cell_info[row][column].inset->setContentAlignment(
|
cell_info[row][column].inset->setContentAlignment(
|
||||||
getAlignment(cellIndex(row, column)));
|
getAlignment(cellIndex(row, column)));
|
||||||
++i;
|
++i;
|
||||||
@ -1130,14 +1136,16 @@ void Tabular::setVAlignment(idx_type cell, VAlignment align,
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow line and paragraph breaks for fixed width cells or disallow them,
|
* Allow line and paragraph breaks for fixed width multicol/multirow cells
|
||||||
* merge cell paragraphs and reset layout to standard for variable width
|
* or disallow them, merge cell paragraphs and reset layout to standard
|
||||||
* cells.
|
* for variable width multicol cells.
|
||||||
*/
|
*/
|
||||||
void toggleFixedWidth(Cursor & cur, InsetTableCell * inset, bool fixedWidth)
|
void toggleFixedWidth(Cursor & cur, InsetTableCell * inset,
|
||||||
|
bool const fixedWidth, bool const multicol,
|
||||||
|
bool const multirow)
|
||||||
{
|
{
|
||||||
inset->toggleFixedWidth(fixedWidth);
|
inset->toggleFixedWidth(fixedWidth);
|
||||||
if (fixedWidth)
|
if (!multirow && (fixedWidth || !multicol))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// merge all paragraphs to one
|
// merge all paragraphs to one
|
||||||
@ -1145,6 +1153,19 @@ void toggleFixedWidth(Cursor & cur, InsetTableCell * inset, bool fixedWidth)
|
|||||||
while (inset->paragraphs().size() > 1)
|
while (inset->paragraphs().size() > 1)
|
||||||
mergeParagraph(bp, inset->paragraphs(), 0);
|
mergeParagraph(bp, inset->paragraphs(), 0);
|
||||||
|
|
||||||
|
// This is relevant for multirows
|
||||||
|
if (fixedWidth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove newlines
|
||||||
|
ParagraphList::iterator pit = inset->paragraphs().begin();
|
||||||
|
for (; pit != inset->paragraphs().end(); ++pit) {
|
||||||
|
for (pos_type j = 0; j != pit->size(); ++j) {
|
||||||
|
if (pit->isNewline(j))
|
||||||
|
pit->eraseChar(j, bp.track_changes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reset layout
|
// reset layout
|
||||||
cur.push(*inset);
|
cur.push(*inset);
|
||||||
// undo information has already been recorded
|
// undo information has already been recorded
|
||||||
@ -1171,16 +1192,13 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type cell,
|
|||||||
idx_type const cidx = cellIndex(r, c);
|
idx_type const cidx = cellIndex(r, c);
|
||||||
// because of multicolumns
|
// because of multicolumns
|
||||||
toggleFixedWidth(cur, cellInset(cidx).get(),
|
toggleFixedWidth(cur, cellInset(cidx).get(),
|
||||||
!getPWidth(cidx).zero());
|
!getPWidth(cidx).zero(), isMultiColumn(cidx),
|
||||||
|
isMultiRow(cidx));
|
||||||
if (isMultiRow(cidx))
|
if (isMultiRow(cidx))
|
||||||
setAlignment(cidx, LYX_ALIGN_LEFT, false);
|
setAlignment(cidx, LYX_ALIGN_LEFT, false);
|
||||||
}
|
}
|
||||||
// cur paragraph can become invalid after paragraphs were merged
|
// cur can become invalid after paragraphs were merged
|
||||||
if (cur.pit() > cur.lastpit())
|
cur.fixIfBroken();
|
||||||
cur.pit() = cur.lastpit();
|
|
||||||
// cur position can become invalid after newlines were removed
|
|
||||||
if (cur.pos() > cur.lastpos())
|
|
||||||
cur.pos() = cur.lastpos();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1201,13 +1219,10 @@ bool Tabular::setMColumnPWidth(Cursor & cur, idx_type cell,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
cellInfo(cell).p_width = width;
|
cellInfo(cell).p_width = width;
|
||||||
toggleFixedWidth(cur, cellInset(cell).get(), !width.zero());
|
toggleFixedWidth(cur, cellInset(cell).get(), !width.zero(),
|
||||||
// cur paragraph can become invalid after paragraphs were merged
|
isMultiColumn(cell), isMultiRow(cell));
|
||||||
if (cur.pit() > cur.lastpit())
|
// cur can become invalid after paragraphs were merged
|
||||||
cur.pit() = cur.lastpit();
|
cur.fixIfBroken();
|
||||||
// cur position can become invalid after newlines were removed
|
|
||||||
if (cur.pos() > cur.lastpos())
|
|
||||||
cur.pos() = cur.lastpos();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,6 +1732,16 @@ bool Tabular::hasVarwidthColumn() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Tabular::isVTypeColumn(col_type c) const
|
||||||
|
{
|
||||||
|
for (row_type r = 0; r < nrows(); ++r) {
|
||||||
|
idx_type idx = cellIndex(r, c);
|
||||||
|
if (getRotateCell(idx) == 0 && useBox(idx) == BOX_VARWIDTH)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Tabular::CellData const & Tabular::cellInfo(idx_type cell) const
|
Tabular::CellData const & Tabular::cellInfo(idx_type cell) const
|
||||||
{
|
{
|
||||||
@ -1730,7 +1755,7 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number,
|
Tabular::idx_type Tabular::setMultiColumn(Cursor & cur, idx_type cell, idx_type number,
|
||||||
bool const right_border)
|
bool const right_border)
|
||||||
{
|
{
|
||||||
idx_type const col = cellColumn(cell);
|
idx_type const col = cellColumn(cell);
|
||||||
@ -1745,6 +1770,14 @@ Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number,
|
|||||||
if (column_info[col].alignment != LYX_ALIGN_DECIMAL)
|
if (column_info[col].alignment != LYX_ALIGN_DECIMAL)
|
||||||
cs.alignment = column_info[col].alignment;
|
cs.alignment = column_info[col].alignment;
|
||||||
setRightLine(cell, right_border);
|
setRightLine(cell, right_border);
|
||||||
|
// non-fixed width multicolumns cannot have multiple paragraphs
|
||||||
|
if (getPWidth(cell).zero()) {
|
||||||
|
toggleFixedWidth(cur, cellInset(cell).get(),
|
||||||
|
!getPWidth(cell).zero(), isMultiColumn(cell),
|
||||||
|
isMultiRow(cell));
|
||||||
|
// cur can become invalid after paragraphs were merged
|
||||||
|
cur.fixIfBroken();
|
||||||
|
}
|
||||||
|
|
||||||
idx_type lastcell = cellIndex(row, col + number - 1);
|
idx_type lastcell = cellIndex(row, col + number - 1);
|
||||||
for (idx_type i = 1; i < lastcell - cell + 1; ++i) {
|
for (idx_type i = 1; i < lastcell - cell + 1; ++i) {
|
||||||
@ -1773,7 +1806,7 @@ bool Tabular::hasMultiRow(row_type r) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number,
|
Tabular::idx_type Tabular::setMultiRow(Cursor & cur, idx_type cell, idx_type number,
|
||||||
bool const bottom_border,
|
bool const bottom_border,
|
||||||
LyXAlignment const halign)
|
LyXAlignment const halign)
|
||||||
{
|
{
|
||||||
@ -1796,6 +1829,15 @@ Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number,
|
|||||||
else
|
else
|
||||||
cs.alignment = LYX_ALIGN_LEFT;
|
cs.alignment = LYX_ALIGN_LEFT;
|
||||||
|
|
||||||
|
// Multirows cannot have multiple paragraphs
|
||||||
|
if (getPWidth(cell).zero()) {
|
||||||
|
toggleFixedWidth(cur, cellInset(cell).get(),
|
||||||
|
!getPWidth(cell).zero(),
|
||||||
|
isMultiColumn(cell), isMultiRow(cell));
|
||||||
|
// cur can become invalid after paragraphs were merged
|
||||||
|
cur.fixIfBroken();
|
||||||
|
}
|
||||||
|
|
||||||
// set the bottom line of the last selected cell
|
// set the bottom line of the last selected cell
|
||||||
setBottomLine(cell, bottom_border);
|
setBottomLine(cell, bottom_border);
|
||||||
|
|
||||||
@ -1949,7 +1991,7 @@ Tabular::BoxType Tabular::getUsebox(idx_type cell) const
|
|||||||
return BOX_NONE;
|
return BOX_NONE;
|
||||||
if (cellInfo(cell).usebox > 1)
|
if (cellInfo(cell).usebox > 1)
|
||||||
return cellInfo(cell).usebox;
|
return cellInfo(cell).usebox;
|
||||||
return useParbox(cell);
|
return useBox(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2078,11 +2120,11 @@ bool Tabular::haveLTLastFoot(bool withcaptions) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Tabular::idx_type Tabular::setLTCaption(row_type row, bool what)
|
Tabular::idx_type Tabular::setLTCaption(Cursor & cur, row_type row, bool what)
|
||||||
{
|
{
|
||||||
idx_type i = getFirstCellInRow(row);
|
idx_type i = getFirstCellInRow(row);
|
||||||
if (what) {
|
if (what) {
|
||||||
setMultiColumn(i, numberOfCellsInRow(row), false);
|
setMultiColumn(cur, i, numberOfCellsInRow(row), false);
|
||||||
setTopLine(i, false);
|
setTopLine(i, false);
|
||||||
setBottomLine(i, false);
|
setBottomLine(i, false);
|
||||||
setLeftLine(i, false);
|
setLeftLine(i, false);
|
||||||
@ -2490,7 +2532,7 @@ void Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
|
|||||||
}
|
}
|
||||||
os << "]{" << from_ascii(getPWidth(cell).asLatexString())
|
os << "]{" << from_ascii(getPWidth(cell).asLatexString())
|
||||||
<< "}\n";
|
<< "}\n";
|
||||||
} else if (getUsebox(cell) == BOX_VARWIDTH) {
|
} else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH) {
|
||||||
os << "\\begin{varwidth}[";
|
os << "\\begin{varwidth}[";
|
||||||
switch (valign) {
|
switch (valign) {
|
||||||
case LYX_VALIGN_TOP:
|
case LYX_VALIGN_TOP:
|
||||||
@ -2520,7 +2562,7 @@ void Tabular::TeXCellPostamble(otexstream & os, idx_type cell,
|
|||||||
os << '}';
|
os << '}';
|
||||||
else if (getUsebox(cell) == BOX_MINIPAGE)
|
else if (getUsebox(cell) == BOX_MINIPAGE)
|
||||||
os << breakln << "\\end{minipage}";
|
os << breakln << "\\end{minipage}";
|
||||||
else if (getUsebox(cell) == BOX_VARWIDTH)
|
else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH)
|
||||||
os << breakln << "\\end{varwidth}";
|
os << breakln << "\\end{varwidth}";
|
||||||
if (getRotateCell(cell) != 0)
|
if (getRotateCell(cell) != 0)
|
||||||
os << breakln << "\\end{turn}";
|
os << breakln << "\\end{turn}";
|
||||||
@ -2964,6 +3006,25 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
os << 'X';
|
os << 'X';
|
||||||
|
} else if (isVTypeColumn(c)) {
|
||||||
|
switch (column_info[c].alignment) {
|
||||||
|
case LYX_ALIGN_LEFT:
|
||||||
|
os << ">{\\raggedright}";
|
||||||
|
break;
|
||||||
|
case LYX_ALIGN_RIGHT:
|
||||||
|
os << ">{\\raggedleft}";
|
||||||
|
break;
|
||||||
|
case LYX_ALIGN_CENTER:
|
||||||
|
os << ">{\\centering}";
|
||||||
|
break;
|
||||||
|
case LYX_ALIGN_NONE:
|
||||||
|
case LYX_ALIGN_BLOCK:
|
||||||
|
case LYX_ALIGN_LAYOUT:
|
||||||
|
case LYX_ALIGN_SPECIAL:
|
||||||
|
case LYX_ALIGN_DECIMAL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os << "V{\\linewidth}";
|
||||||
} else {
|
} else {
|
||||||
switch (column_info[c].alignment) {
|
switch (column_info[c].alignment) {
|
||||||
case LYX_ALIGN_LEFT:
|
case LYX_ALIGN_LEFT:
|
||||||
@ -3588,7 +3649,8 @@ void Tabular::validate(LaTeXFeatures & features) const
|
|||||||
if (getUsebox(cell) == BOX_VARWIDTH)
|
if (getUsebox(cell) == BOX_VARWIDTH)
|
||||||
features.require("varwidth");
|
features.require("varwidth");
|
||||||
if (getVAlignment(cell) != LYX_VALIGN_TOP
|
if (getVAlignment(cell) != LYX_VALIGN_TOP
|
||||||
|| !getPWidth(cell).zero())
|
|| !getPWidth(cell).zero()
|
||||||
|
|| isVTypeColumn(cellColumn(cell)))
|
||||||
features.require("array");
|
features.require("array");
|
||||||
// Tell footnote that we need a savenote
|
// Tell footnote that we need a savenote
|
||||||
// environment in non-long tables or
|
// environment in non-long tables or
|
||||||
@ -3604,17 +3666,19 @@ void Tabular::validate(LaTeXFeatures & features) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Tabular::BoxType Tabular::useParbox(idx_type cell) const
|
Tabular::BoxType Tabular::useBox(idx_type cell) const
|
||||||
{
|
{
|
||||||
ParagraphList const & parlist = cellInset(cell)->paragraphs();
|
ParagraphList const & parlist = cellInset(cell)->paragraphs();
|
||||||
|
if (parlist.size() > 1)
|
||||||
|
return BOX_VARWIDTH;
|
||||||
|
|
||||||
ParagraphList::const_iterator cit = parlist.begin();
|
ParagraphList::const_iterator cit = parlist.begin();
|
||||||
ParagraphList::const_iterator end = parlist.end();
|
ParagraphList::const_iterator end = parlist.end();
|
||||||
bool const turned = getRotateCell(cell) != 0;
|
|
||||||
|
|
||||||
for (; cit != end; ++cit)
|
for (; cit != end; ++cit)
|
||||||
for (int i = 0; i < cit->size(); ++i)
|
for (int i = 0; i < cit->size(); ++i)
|
||||||
if (cit->isNewline(i))
|
if (cit->isNewline(i) || cit->layout().isEnvironment())
|
||||||
return turned ? BOX_VARWIDTH : BOX_PARBOX;
|
return BOX_VARWIDTH;
|
||||||
|
|
||||||
return BOX_NONE;
|
return BOX_NONE;
|
||||||
}
|
}
|
||||||
@ -3628,13 +3692,13 @@ Tabular::BoxType Tabular::useParbox(idx_type cell) const
|
|||||||
|
|
||||||
InsetTableCell::InsetTableCell(Buffer * buf)
|
InsetTableCell::InsetTableCell(Buffer * buf)
|
||||||
: InsetText(buf, InsetText::PlainLayout), isFixedWidth(false),
|
: InsetText(buf, InsetText::PlainLayout), isFixedWidth(false),
|
||||||
contentAlign(LYX_ALIGN_CENTER)
|
isMultiColumn(false), isMultiRow(false), contentAlign(LYX_ALIGN_CENTER)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
bool InsetTableCell::forcePlainLayout(idx_type) const
|
bool InsetTableCell::forcePlainLayout(idx_type) const
|
||||||
{
|
{
|
||||||
return !isFixedWidth;
|
return isMultiRow || (isMultiColumn && !isFixedWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3701,6 +3765,34 @@ docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InsetTableCell::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||||
|
{
|
||||||
|
TextMetrics & tm = mi.base.bv->textMetrics(&text());
|
||||||
|
|
||||||
|
// Hand font through to contained lyxtext:
|
||||||
|
tm.font_.fontInfo() = mi.base.font;
|
||||||
|
mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
|
||||||
|
|
||||||
|
// This can happen when a layout has a left and right margin,
|
||||||
|
// and the view is made very narrow. We can't do better than
|
||||||
|
// to draw it partly out of view (bug 5890).
|
||||||
|
if (mi.base.textwidth < 1)
|
||||||
|
mi.base.textwidth = 1;
|
||||||
|
|
||||||
|
// We tell metrics here not to expand on multiple pars
|
||||||
|
// This is the difference to InsetText::Metrics
|
||||||
|
// FIXME: pars with newlines are still too wide!
|
||||||
|
if (hasFixedWidth())
|
||||||
|
tm.metrics(mi, dim, mi.base.textwidth, false);
|
||||||
|
else
|
||||||
|
tm.metrics(mi, dim, 0, false);
|
||||||
|
mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
|
||||||
|
dim.asc += TEXT_TO_INSET_OFFSET;
|
||||||
|
dim.des += TEXT_TO_INSET_OFFSET;
|
||||||
|
dim.wid += 2 * TEXT_TO_INSET_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -3921,8 +4013,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col)
|
bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) const
|
||||||
const
|
|
||||||
{
|
{
|
||||||
if (&cur.inset() == this && cur.selection()) {
|
if (&cur.inset() == this && cur.selection()) {
|
||||||
if (cur.selIsMultiCell()) {
|
if (cur.selIsMultiCell()) {
|
||||||
@ -5190,13 +5281,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case LFUN_NEWLINE_INSERT: {
|
case LFUN_NEWLINE_INSERT:
|
||||||
if (tabular.getPWidth(cur.idx()).zero()) {
|
if ((tabular.isMultiColumn(cur.idx()) || tabular.isMultiRow(cur.idx()))
|
||||||
|
&& tabular.getPWidth(cur.idx()).zero()) {
|
||||||
status.setEnabled(false);
|
status.setEnabled(false);
|
||||||
return true;
|
return true;
|
||||||
} else
|
|
||||||
return cell(cur.idx())->getStatus(cur, cmd, status);
|
|
||||||
}
|
}
|
||||||
|
return cell(cur.idx())->getStatus(cur, cmd, status);
|
||||||
|
|
||||||
case LFUN_NEWPAGE_INSERT:
|
case LFUN_NEWPAGE_INSERT:
|
||||||
status.setEnabled(false);
|
status.setEnabled(false);
|
||||||
@ -5863,7 +5954,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
// just multicol for one single cell
|
// just multicol for one single cell
|
||||||
// check whether we are completely in a multicol
|
// check whether we are completely in a multicol
|
||||||
if (!tabular.isMultiColumn(cur.idx()))
|
if (!tabular.isMultiColumn(cur.idx()))
|
||||||
tabular.setMultiColumn(cur.idx(), 1,
|
tabular.setMultiColumn(cur, cur.idx(), 1,
|
||||||
tabular.rightLine(cur.idx()));
|
tabular.rightLine(cur.idx()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5872,7 +5963,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
idx_type const s_start = cur.selBegin().idx();
|
idx_type const s_start = cur.selBegin().idx();
|
||||||
row_type const col_start = tabular.cellColumn(s_start);
|
row_type const col_start = tabular.cellColumn(s_start);
|
||||||
row_type const col_end = tabular.cellColumn(cur.selEnd().idx());
|
row_type const col_end = tabular.cellColumn(cur.selEnd().idx());
|
||||||
cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start + 1,
|
cur.idx() = tabular.setMultiColumn(cur, s_start, col_end - col_start + 1,
|
||||||
tabular.rightLine(cur.selEnd().idx()));
|
tabular.rightLine(cur.selEnd().idx()));
|
||||||
cur.pit() = 0;
|
cur.pit() = 0;
|
||||||
cur.pos() = 0;
|
cur.pos() = 0;
|
||||||
@ -5918,7 +6009,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
// just multirow for one single cell
|
// just multirow for one single cell
|
||||||
// check whether we are completely in a multirow
|
// check whether we are completely in a multirow
|
||||||
if (!tabular.isMultiRow(cur.idx()))
|
if (!tabular.isMultiRow(cur.idx()))
|
||||||
tabular.setMultiRow(cur.idx(), 1,
|
tabular.setMultiRow(cur, cur.idx(), 1,
|
||||||
tabular.bottomLine(cur.idx()),
|
tabular.bottomLine(cur.idx()),
|
||||||
tabular.getAlignment(cur.idx()));
|
tabular.getAlignment(cur.idx()));
|
||||||
break;
|
break;
|
||||||
@ -5928,7 +6019,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
idx_type const s_start = cur.selBegin().idx();
|
idx_type const s_start = cur.selBegin().idx();
|
||||||
row_type const row_start = tabular.cellRow(s_start);
|
row_type const row_start = tabular.cellRow(s_start);
|
||||||
row_type const row_end = tabular.cellRow(cur.selEnd().idx());
|
row_type const row_end = tabular.cellRow(cur.selEnd().idx());
|
||||||
cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 1,
|
cur.idx() = tabular.setMultiRow(cur, s_start, row_end - row_start + 1,
|
||||||
tabular.bottomLine(cur.selEnd().idx()),
|
tabular.bottomLine(cur.selEnd().idx()),
|
||||||
tabular.getAlignment(cur.selEnd().idx()));
|
tabular.getAlignment(cur.selEnd().idx()));
|
||||||
cur.pit() = 0;
|
cur.pit() = 0;
|
||||||
@ -6141,7 +6232,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
case Tabular::SET_LTCAPTION: {
|
case Tabular::SET_LTCAPTION: {
|
||||||
if (tabular.ltCaption(row))
|
if (tabular.ltCaption(row))
|
||||||
break;
|
break;
|
||||||
cur.idx() = tabular.setLTCaption(row, true);
|
cur.idx() = tabular.setLTCaption(cur, row, true);
|
||||||
cur.pit() = 0;
|
cur.pit() = 0;
|
||||||
cur.pos() = 0;
|
cur.pos() = 0;
|
||||||
cur.selection(false);
|
cur.selection(false);
|
||||||
@ -6157,7 +6248,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
|
|||||||
case Tabular::UNSET_LTCAPTION: {
|
case Tabular::UNSET_LTCAPTION: {
|
||||||
if (!tabular.ltCaption(row))
|
if (!tabular.ltCaption(row))
|
||||||
break;
|
break;
|
||||||
cur.idx() = tabular.setLTCaption(row, false);
|
cur.idx() = tabular.setLTCaption(cur, row, false);
|
||||||
cur.pit() = 0;
|
cur.pit() = 0;
|
||||||
cur.pos() = 0;
|
cur.pos() = 0;
|
||||||
cur.selection(false);
|
cur.selection(false);
|
||||||
@ -6457,7 +6548,7 @@ bool InsetTabular::allowParagraphCustomization(idx_type cell) const
|
|||||||
|
|
||||||
bool InsetTabular::forcePlainLayout(idx_type cell) const
|
bool InsetTabular::forcePlainLayout(idx_type cell) const
|
||||||
{
|
{
|
||||||
return !tabular.getPWidth(cell).zero();
|
return tabular.isMultiColumn(cell) && !tabular.getPWidth(cell).zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +63,10 @@ public:
|
|||||||
///
|
///
|
||||||
void toggleFixedWidth(bool fw) { isFixedWidth = fw; }
|
void toggleFixedWidth(bool fw) { isFixedWidth = fw; }
|
||||||
///
|
///
|
||||||
|
void toggleMultiCol(bool m) { isMultiColumn = m; }
|
||||||
|
///
|
||||||
|
void toggleMultiRow(bool m) { isMultiRow = m; }
|
||||||
|
///
|
||||||
void setContentAlignment(LyXAlignment al) {contentAlign = al; }
|
void setContentAlignment(LyXAlignment al) {contentAlign = al; }
|
||||||
/// writes the contents of the cell as a string, optionally
|
/// writes the contents of the cell as a string, optionally
|
||||||
/// descending into insets
|
/// descending into insets
|
||||||
@ -72,14 +76,17 @@ public:
|
|||||||
///
|
///
|
||||||
void addToToc(DocIterator const & di, bool output_active,
|
void addToToc(DocIterator const & di, bool output_active,
|
||||||
UpdateType utype, TocBackend & backend) const;
|
UpdateType utype, TocBackend & backend) const;
|
||||||
|
///
|
||||||
|
void metrics(MetricsInfo &, Dimension &) const;
|
||||||
private:
|
private:
|
||||||
/// unimplemented
|
/// unimplemented
|
||||||
InsetTableCell();
|
InsetTableCell();
|
||||||
/// unimplemented
|
/// unimplemented
|
||||||
void operator=(InsetTableCell const &);
|
void operator=(InsetTableCell const &);
|
||||||
// FIXME
|
// FIXME
|
||||||
// This boolean is supposed to track whether the cell has had its
|
// These booleans are supposed to track whether the cell has had its
|
||||||
// width explicitly set. We need to know this to determine whether
|
// width explicitly set and whether it is part of a multicolumn, respectively.
|
||||||
|
// We need to know this to determine whether
|
||||||
// layout changes and paragraph customization are allowed---that is,
|
// layout changes and paragraph customization are allowed---that is,
|
||||||
// we need it in forcePlainLayout() and allowParagraphCustomization().
|
// we need it in forcePlainLayout() and allowParagraphCustomization().
|
||||||
// Unfortunately, that information is not readily available in
|
// Unfortunately, that information is not readily available in
|
||||||
@ -102,6 +109,10 @@ private:
|
|||||||
// --rgh
|
// --rgh
|
||||||
///
|
///
|
||||||
bool isFixedWidth;
|
bool isFixedWidth;
|
||||||
|
///
|
||||||
|
bool isMultiColumn;
|
||||||
|
///
|
||||||
|
bool isMultiRow;
|
||||||
// FIXME: Here the thoughts from the comment above also apply.
|
// FIXME: Here the thoughts from the comment above also apply.
|
||||||
///
|
///
|
||||||
LyXAlignment contentAlign;
|
LyXAlignment contentAlign;
|
||||||
@ -120,11 +131,7 @@ private:
|
|||||||
/// Is the width forced to some value?
|
/// Is the width forced to some value?
|
||||||
bool hasFixedWidth() const { return isFixedWidth; }
|
bool hasFixedWidth() const { return isFixedWidth; }
|
||||||
/// Can the cell contain several paragraphs?
|
/// Can the cell contain several paragraphs?
|
||||||
/** FIXME this is wrong for multirows, that are limited to one
|
bool allowMultiPar() const { return !isMultiRow && (!isMultiColumn || isFixedWidth); }
|
||||||
* paragraph. However, we cannot test for this (see the big
|
|
||||||
* comment above).
|
|
||||||
*/
|
|
||||||
bool allowMultiPar() const { return isFixedWidth; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -534,7 +541,9 @@ public:
|
|||||||
///
|
///
|
||||||
bool hasVarwidthColumn() const;
|
bool hasVarwidthColumn() const;
|
||||||
///
|
///
|
||||||
idx_type setMultiColumn(idx_type cell, idx_type number,
|
bool isVTypeColumn(col_type cell) const;
|
||||||
|
///
|
||||||
|
idx_type setMultiColumn(Cursor & cur, idx_type cell, idx_type number,
|
||||||
bool const right_border);
|
bool const right_border);
|
||||||
///
|
///
|
||||||
void unsetMultiColumn(idx_type cell);
|
void unsetMultiColumn(idx_type cell);
|
||||||
@ -547,7 +556,7 @@ public:
|
|||||||
///
|
///
|
||||||
bool hasMultiRow(row_type r) const;
|
bool hasMultiRow(row_type r) const;
|
||||||
///
|
///
|
||||||
idx_type setMultiRow(idx_type cell, idx_type number,
|
idx_type setMultiRow(Cursor & cur, idx_type cell, idx_type number,
|
||||||
bool const bottom_border,
|
bool const bottom_border,
|
||||||
LyXAlignment const halign);
|
LyXAlignment const halign);
|
||||||
///
|
///
|
||||||
@ -595,7 +604,7 @@ public:
|
|||||||
///
|
///
|
||||||
bool getLTNewPage(row_type row) const;
|
bool getLTNewPage(row_type row) const;
|
||||||
///
|
///
|
||||||
idx_type setLTCaption(row_type row, bool what);
|
idx_type setLTCaption(Cursor & cur, row_type row, bool what);
|
||||||
///
|
///
|
||||||
bool ltCaption(row_type row) const;
|
bool ltCaption(row_type row) const;
|
||||||
///
|
///
|
||||||
@ -804,7 +813,7 @@ public:
|
|||||||
///
|
///
|
||||||
idx_type rowSpan(idx_type cell) const;
|
idx_type rowSpan(idx_type cell) const;
|
||||||
///
|
///
|
||||||
BoxType useParbox(idx_type cell) const;
|
BoxType useBox(idx_type cell) const;
|
||||||
///
|
///
|
||||||
// helper function for Latex
|
// helper function for Latex
|
||||||
///
|
///
|
||||||
|
@ -59,6 +59,7 @@ Format LaTeX feature LyX feature
|
|||||||
546 Landscape support
|
546 Landscape support
|
||||||
\begin{landscape}...\end{landscape} \begin_inset Flex Landscape
|
\begin{landscape}...\end{landscape} \begin_inset Flex Landscape
|
||||||
with longtable content: <features rotate ="90"...>
|
with longtable content: <features rotate ="90"...>
|
||||||
|
555 V column type (varwidth package) Automatically detected with newlines, paragraph breaks and environment content in cells of rows
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
|
|||||||
|
|
||||||
// Do not remove the comment below, so we get merge conflict in
|
// Do not remove the comment below, so we get merge conflict in
|
||||||
// independent branches. Instead add your own.
|
// independent branches. Instead add your own.
|
||||||
#define LYX_FORMAT_LYX 554 // spitz: tabularx/xltabular
|
#define LYX_FORMAT_LYX 555 // spitz: varwidth V columns
|
||||||
#define LYX_FORMAT_TEX2LYX 554
|
#define LYX_FORMAT_TEX2LYX 555
|
||||||
|
|
||||||
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
|
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
Loading…
Reference in New Issue
Block a user