Add support for tabularx/xltabular

I.e., variable width columns in single and multiple page tables

Files format change.

Fixes: #4154, #4155
This commit is contained in:
Juergen Spitzmueller 2018-06-24 10:05:15 +02:00
parent 25ff03d120
commit f38816bf16
15 changed files with 1029 additions and 770 deletions

View File

@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be
-----------------------
2018-06-23 Jürgen Spitzmüller <spitz@lyx.org>
* format incremented to 554: Support tabularx and xltabular:
- add column flag "varwidth=true", which will output column type 'X'
with either tabularx or xltabular (for multi-page tables) environment.
2018-05-21 Jürgen Spitzmüller <spitz@lyx.org>
* format incremented to 553: Support \cite command in tufte classes.
This builds on an extension of the natbib CiteEngine by tufte.

View File

@ -377,6 +377,7 @@
\TestPackage{subscript}
\TestPackage{Sweave}
\TestPackage{tablefootnote}
\TestPackage{tabularx}
\TestPackage{tcolorbox}
\TestPackage{textcomp}
\TestPackage{thswitch}
@ -394,6 +395,7 @@
\TestPackage{xcolor}
\TestPackage[xetex.def]{xetex-def}
\TestPackage{xkeyval}
\TestPackage{xltabular}
% Packages used by LyX's documentation files
\TestPackage{arydshln}

View File

@ -5309,7 +5309,7 @@ Notes: The package
longtable
\family default
is needed by \SpecialChar LyX
to be able to output correctly multipage tables.
to output multi-page tables.
\end_layout
\begin_layout Subsection
@ -5341,6 +5341,35 @@ tablefootnote
to be able to output footnotes in floating tables.
\end_layout
\begin_layout Subsection
tabularx
\end_layout
\begin_layout Description
Found:
\begin_inset Info
type "package"
arg "tabularx"
\end_inset
\end_layout
\begin_layout Description
CTAN:
\family typewriter
macros/latex/required/tools/
\end_layout
\begin_layout Description
Notes: The package
\family sans
tabularx
\family default
is needed by \SpecialChar LyX
to output variable width columns for single-page tables.
\end_layout
\begin_layout Subsection
textcomp
\end_layout
@ -5402,6 +5431,35 @@ varioref
the page of the referred label.
\end_layout
\begin_layout Subsection
xltabular
\end_layout
\begin_layout Description
Found:
\begin_inset Info
type "package"
arg "xltabular"
\end_inset
\end_layout
\begin_layout Description
CTAN:
\family typewriter
macros/latex/contrib/xltabular/
\end_layout
\begin_layout Description
Notes: The package
\family sans
xltabular
\family default
is needed by \SpecialChar LyX
to output variable width columns for multi-page tables.
\end_layout
\begin_layout Section
Paper layout packages
\end_layout

View File

@ -327,6 +327,24 @@ def revert_tuftecite(document):
i = j + 1
def revert_stretchcolumn(document):
" We remove the column varwidth flags or everything else will become a mess. "
i = 0
while True:
i = find_token(document.body, "\\begin_inset Tabular", i)
if i == -1:
return
j = find_end_of_inset(document.body, i + 1)
if j == -1:
document.warning("Malformed LyX document: Could not find end of tabular.")
continue
for k in range(i, j):
if re.search('^<column.*varwidth="[^"]+".*>$', document.body[k]):
document.warning("Converting 'tabularx'/'xltabular' table to normal table.")
document.body[k] = document.body[k].replace(' varwidth="true"', '')
i = i + 1
##
# Conversion hub
#
@ -341,10 +359,12 @@ convert = [
[550, [convert_fontenc]],
[551, []],
[552, []],
[553, []]
[553, []],
[554, []]
]
revert = [
[553, [revert_stretchcolumn]],
[552, [revert_tuftecite]],
[551, [revert_floatpclass, revert_floatalignment]],
[550, [revert_nospellcheck]],

View File

@ -984,6 +984,8 @@ char const * simplefeatures[] = {
"footnote",
"tablefootnote",
"afterpage",
"tabularx",
"xltabular"
};
char const * bibliofeatures[] = {

View File

@ -3744,7 +3744,8 @@ void LyXAction::init()
set-special-column|set-special-multicolumn|set-special-multirow|\n
toggle-booktabs|set-booktabs|unset-booktabs|set-top-space|set-bottom-space|\n
set-interline-space|set-border-lines|tabular-valign-top|\n
tabular-valign-middle|tabular-valign-bottom|set-tabular-width\n
tabular-valign-middle|tabular-valign-bottom|set-tabular-width|\n
toggle-varwidth-column
Various math-environment features are handled as well, e.g. add-vline-left/right for\n
the Grid/Array environment.\n
<ARG>: additional argument for some commands, use debug mode to explore its values.

View File

@ -131,6 +131,8 @@ GuiTabular::GuiTabular(QWidget * parent)
this, SLOT(checkEnabled()));
connect(specialAlignmentED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(columnTypeCO, SIGNAL(activated(int)),
this, SLOT(checkEnabled()));
connect(columnWidthED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
@ -205,15 +207,17 @@ void GuiTabular::enableWidgets() const
{
// if there is a LaTeX argument, the width and alignment will be overwritten
// therefore disable them in this case
columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
columnWidthUnitLC->setEnabled(specialAlignmentED->text().isEmpty());
bool const fixed = specialAlignmentED->text().isEmpty()
&& columnTypeCO->currentIndex() == 2;
columnWidthED->setEnabled(fixed);
columnWidthUnitLC->setEnabled(fixed);
// if the column has a width, multirows are always left-aligned
// therefore disable hAlignCB in this case
hAlignCO->setEnabled(!(multirowCB->isChecked()
&& !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
&& specialAlignmentED->text().isEmpty());
// decimal alignment is only possible for non-multicol and non-multirow cells
if ((multicolumnCB->isChecked() || multirowCB->isChecked())
if ((multicolumnCB->isChecked() || multirowCB->isChecked() || columnTypeCO->currentIndex() == 1)
&& hAlignCO->findData(toqstr("decimal")))
hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal")));
else if (!multicolumnCB->isChecked() && !multirowCB->isChecked()
@ -224,8 +228,7 @@ void GuiTabular::enableWidgets() const
decimalPointED->setEnabled(dalign);
decimalLA->setEnabled(dalign);
bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
&& !longTabularCB->isChecked();
bool const setwidth = TableAlignCO->currentText() == qt_("Middle");
tabularWidthLA->setEnabled(setwidth);
tabularWidthED->setEnabled(setwidth);
tabularWidthUnitLC->setEnabled(setwidth);
@ -465,13 +468,20 @@ docstring GuiTabular::dialogToParams() const
// this must be done before applying the column alignment
// because its value influences the alignment of multirow cells
string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
if (width.empty())
if (width.empty() || columnTypeCO->currentIndex() != 2)
width = "0pt";
if (multicolumnCB->isChecked())
setParam(param_str, Tabular::SET_MPWIDTH, width);
else
setParam(param_str, Tabular::SET_PWIDTH, width);
bool const varwidth = specialAlignmentED->text().isEmpty()
&& columnTypeCO->currentIndex() == 1;
if (varwidth)
setParam(param_str, Tabular::TOGGLE_VARWIDTH_COLUMN, "on");
else
setParam(param_str, Tabular::TOGGLE_VARWIDTH_COLUMN, "off");
// apply the column alignment
// multirows inherit the alignment from the column; if a column width
// is set, multirows are always left-aligned so that in this case
@ -782,14 +792,20 @@ void GuiTabular::paramsToDialog(Inset const * inset)
Tabular::SET_SPECIAL_COLUMN);
pwidth = getColumnPWidth(tabular, cell);
}
bool const varwidth = tabular.column_info[tabular.cellColumn(cell)].varwidth;
if (varwidth)
columnTypeCO->setCurrentIndex(1);
string colwidth;
if (pwidth.zero()
&& !(columnWidthED->hasFocus() && columnWidthED->text() == "0"))
&& !(columnWidthED->hasFocus() && columnWidthED->text() == "0")) {
columnWidthED->clear();
else {
if (!varwidth)
columnTypeCO->setCurrentIndex(0);
} else {
colwidth = pwidth.asString();
lengthToWidgets(columnWidthED, columnWidthUnitLC,
colwidth, default_unit);
columnTypeCO->setCurrentIndex(2);
}
Length mroffset;
if (multirow)
@ -1054,6 +1070,7 @@ bool GuiTabular::checkWidgets(bool readonly) const
borders->setEnabled(false);
tabularWidthUnitLC->setEnabled(false);
columnWidthUnitLC->setEnabled(false);
columnTypeCO->setEnabled(false);
multirowOffsetUnitLC->setEnabled(false);
setBordersGB->setEnabled(false);
allBordersGB->setEnabled(false);

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TabularUi</class>
<widget class="QWidget" name="TabularUi">
@ -5,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>497</width>
<height>427</height>
<width>726</width>
<height>585</height>
</rect>
</property>
<property name="windowTitle">
@ -15,81 +16,7 @@
<property name="sizeGripEnabled" stdset="0">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_9" >
<property name="margin" >
<number>0</number>
</property>
<item row="1" column="0" >
<layout class="QHBoxLayout" name="_3" >
<item>
<widget class="QLabel" name="TextLabel1" >
<property name="text" >
<string>Current cell:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tabularRowED" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>40</width>
<height>32767</height>
</size>
</property>
<property name="focusPolicy" >
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip" >
<string>Current row position</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tabularColumnED" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>40</width>
<height>32767</height>
</size>
</property>
<property name="focusPolicy" >
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip" >
<string>Current column position</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<layout class="QGridLayout" name="gridLayout_11">
<item row="0" column="0">
<widget class="QTabWidget" name="TabWidget">
<property name="toolTip">
@ -204,7 +131,7 @@
<item>
<widget class="QLabel" name="rotateCellLA">
<property name="text">
<string>degrees</string>
<string>de&amp;grees</string>
</property>
<property name="buddy">
<cstring>rotateCellAngleSB</cstring>
@ -365,15 +292,29 @@
<property name="title">
<string>Column settings</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QLabel" name="hAlignLA" >
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QComboBox" name="columnTypeCO">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Column width type:&lt;/p&gt;&lt;p&gt;* Text Length: Stretch to text width&lt;/p&gt;&lt;p&gt;* Variable: Adjust to match table width&lt;/p&gt;&lt;p&gt;* Custom: Fixed custom width&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<item>
<property name="text">
<string>&amp;Horizontal alignment:</string>
<string>Text length</string>
</property>
<property name="buddy" >
<cstring>hAlignCO</cstring>
</item>
<item>
<property name="text">
<string>Variable[[Width]]</string>
</property>
</item>
<item>
<property name="text">
<string>Custom[[Width]]</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
@ -408,98 +349,17 @@
</item>
</widget>
</item>
<item row="0" column="2" >
<spacer name="horizontalSpacer" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>4</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3" colspan="2" >
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QLabel" name="decimalLA" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>&amp;Decimal separator:</string>
</property>
<property name="buddy" >
<cstring>decimalPointED</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="decimalPointED" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>20</width>
<height>16777215</height>
</size>
</property>
<property name="inputMask" >
<string/>
</property>
<property name="text" >
<string/>
</property>
<property name="maxLength" >
<number>32767</number>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="columnWidthLA">
<property name="text">
<string>&amp;Width:</string>
</property>
<property name="buddy">
<cstring>columnWidthED</cstring>
<cstring>columnTypeCO</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3" >
<layout class="QHBoxLayout" name="horizontalLayout_2" >
<item>
<widget class="QLineEdit" name="columnWidthED" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="toolTip" >
<string>Fixed width of the column</string>
</property>
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="lyx::frontend::LengthCombo" name="columnWidthUnitLC" />
</item>
</layout>
</item>
<item row="1" column="4" >
<item row="2" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -512,13 +372,13 @@
</property>
</spacer>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="vAlignLA" >
<item row="0" column="0">
<widget class="QLabel" name="hAlignLA">
<property name="text">
<string>&amp;Vertical alignment in row:</string>
<string>Hori&amp;zontal alignment:</string>
</property>
<property name="buddy">
<cstring>vAlignCO</cstring>
<cstring>hAlignCO</cstring>
</property>
</widget>
</item>
@ -544,7 +404,113 @@
</item>
</widget>
</item>
<item row="3" column="0" >
<item row="2" column="0">
<widget class="QLabel" name="vAlignLA">
<property name="text">
<string>&amp;Vertical alignment in row:</string>
</property>
<property name="buddy">
<cstring>vAlignCO</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="columnWidthED">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Custom width of the column</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="lyx::frontend::LengthCombo" name="columnWidthUnitLC"/>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="decimalLA">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Decimal separator:</string>
</property>
<property name="buddy">
<cstring>decimalPointED</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="decimalPointED">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>16777215</height>
</size>
</property>
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="maxLength">
<number>32767</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>78</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>31</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="multicolumnCB">
<property name="toolTip">
<string>Merge cells of different columns</string>
@ -554,7 +520,9 @@
</property>
</widget>
</item>
<item row="4" column="0" >
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="specialAlignmentLA">
<property name="text">
<string>LaTe&amp;X argument:</string>
@ -564,7 +532,7 @@
</property>
</widget>
</item>
<item row="4" column="1" >
<item>
<widget class="QLineEdit" name="specialAlignmentED">
<property name="toolTip">
<string>Custom column format (LaTeX)</string>
@ -575,6 +543,8 @@
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
@ -593,7 +563,7 @@
<item row="0" column="0">
<widget class="QFrame" name="bordersF">
<property name="sizePolicy">
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1075,9 +1045,9 @@
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="GuiSetBorder" native="1" name="borders" >
<widget class="GuiSetBorder" name="borders" native="true">
<property name="sizePolicy">
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1301,7 +1271,7 @@
</widget>
<widget class="QWidget" name="Longtables">
<attribute name="title">
<string>&amp;Multi-page table</string>
<string>&amp;Multi-Page Table</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
@ -1553,7 +1523,7 @@
<item row="0" column="1">
<widget class="QRadioButton" name="centerRB">
<property name="text">
<string>Center</string>
<string>&amp;Center</string>
</property>
<property name="checked">
<bool>true</bool>
@ -1587,6 +1557,77 @@
</widget>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="_3">
<item>
<widget class="QLabel" name="TextLabel1">
<property name="text">
<string>Current cell:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tabularRowED">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>32767</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Current row position</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tabularColumnED">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>32767</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Current column position</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>

View File

@ -161,6 +161,7 @@ TabularFeature tabularFeature[] =
{ Tabular::UNSET_LONGTABULAR, "unset-longtabular", false },
{ Tabular::SET_PWIDTH, "set-pwidth", true },
{ Tabular::SET_MPWIDTH, "set-mpwidth", true },
{ Tabular::TOGGLE_VARWIDTH_COLUMN, "toggle-varwidth-column", true },
{ Tabular::SET_ROTATE_TABULAR, "set-rotate-tabular", true },
{ Tabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular", true },
{ Tabular::TOGGLE_ROTATE_TABULAR, "toggle-rotate-tabular", true },
@ -653,7 +654,8 @@ Tabular::RowData::RowData()
Tabular::ColumnData::ColumnData()
: alignment(LYX_ALIGN_CENTER),
valignment(LYX_VALIGN_TOP),
width(0)
width(0),
varwidth(false)
{
}
@ -1206,6 +1208,13 @@ bool Tabular::setMColumnPWidth(Cursor & cur, idx_type cell,
}
bool Tabular::toggleVarwidth(idx_type cell, bool const varwidth)
{
column_info[cellColumn(cell)].varwidth = varwidth;
return true;
}
bool Tabular::setMROffset(Cursor &, idx_type cell, Length const & mroffset)
{
cellInfo(cell).mroffset = mroffset;
@ -1496,6 +1505,7 @@ void Tabular::write(ostream & os) const
os << write_attribute("decimal_point", column_info[c].decimal_point);
os << write_attribute("valignment", column_info[c].valignment)
<< write_attribute("width", column_info[c].p_width.asString())
<< write_attribute("varwidth", column_info[c].varwidth)
<< write_attribute("special", column_info[c].align_special)
<< ">\n";
}
@ -1608,6 +1618,7 @@ void Tabular::read(Lexer & lex)
getTokenValue(line, "valignment", column_info[c].valignment);
getTokenValue(line, "width", column_info[c].p_width);
getTokenValue(line, "special", column_info[c].align_special);
getTokenValue(line, "varwidth", column_info[c].varwidth);
}
for (row_type i = 0; i < nrows(); ++i) {
@ -1693,6 +1704,17 @@ bool Tabular::hasMultiColumn(col_type c) const
}
bool Tabular::hasVarwidthColumn() const
{
for (col_type c = 0; c < ncols(); ++c) {
if (column_info[c].varwidth)
return true;
}
return false;
}
Tabular::CellData const & Tabular::cellInfo(idx_type cell) const
{
return cell_info[cellRow(cell)][cellColumn(cell)];
@ -2752,7 +2774,7 @@ void Tabular::TeXRow(otexstream & os, row_type row,
void Tabular::latex(otexstream & os, OutputParams const & runparams) const
{
bool const is_tabular_star = !tabular_width.zero();
bool const is_tabular_star = !tabular_width.zero() && !hasVarwidthColumn();
TexRow::RowEntry pos = TexRow::textEntry(runparams.lastid, runparams.lastpos);
//+---------------------------------------------------------------------
@ -2771,6 +2793,9 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
}
if (is_long_tabular) {
if (hasVarwidthColumn())
os << "\\begin{xltabular}";
else
os << "\\begin{longtable}";
switch (longtabular_alignment) {
case LYX_LONGTABULAR_ALIGN_LEFT:
@ -2783,10 +2808,22 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
os << "[r]";
break;
}
if (hasVarwidthColumn()) {
if (tabular_width.zero())
os << "{" << from_ascii("\\columnwidth") << "}";
else
os << "{" << from_ascii(tabular_width.asLatexString()) << "}";
}
} else {
if (is_tabular_star)
os << "\\begin{tabular*}{" << from_ascii(tabular_width.asLatexString()) << "}";
else if (hasVarwidthColumn()) {
os << "\\begin{tabularx}{";
if (tabular_width.zero())
os << from_ascii("\\columnwidth") << "}";
else
os << from_ascii(tabular_width.asLatexString()) << "}";
} else
os << "\\begin{tabular}";
switch (tabular_valignment) {
case LYX_VALIGN_TOP:
@ -2887,6 +2924,25 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
os << '{'
<< from_ascii(column_info[c].p_width.asLatexString())
<< '}';
} else if (column_info[c].varwidth) {
switch (column_info[c].alignment) {
case LYX_ALIGN_LEFT:
os << ">{\\raggedright\\arraybackslash}";
break;
case LYX_ALIGN_RIGHT:
os << ">{\\raggedleft\\arraybackslash}";
break;
case LYX_ALIGN_CENTER:
os << ">{\\centering\\arraybackslash}";
break;
case LYX_ALIGN_NONE:
case LYX_ALIGN_BLOCK:
case LYX_ALIGN_LAYOUT:
case LYX_ALIGN_SPECIAL:
case LYX_ALIGN_DECIMAL:
break;
}
os << 'X';
} else {
switch (column_info[c].alignment) {
case LYX_ALIGN_LEFT:
@ -2927,11 +2983,16 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
//+ the closing of the tabular +
//+---------------------------------------------------------------------
if (is_long_tabular)
if (is_long_tabular) {
if (hasVarwidthColumn())
os << "\\end{xltabular}";
else
os << "\\end{longtable}";
else {
} else {
if (is_tabular_star)
os << "\\end{tabular*}";
else if (hasVarwidthColumn())
os << "\\end{tabularx}";
else
os << "\\end{tabular}";
}
@ -3484,12 +3545,18 @@ void Tabular::validate(LaTeXFeatures & features) const
features.require("NeedTabularnewline");
if (use_booktabs)
features.require("booktabs");
if (is_long_tabular)
if (is_long_tabular && !hasVarwidthColumn())
features.require("longtable");
if (rotate && is_long_tabular)
features.require("lscape");
if (needRotating())
features.require("rotating");
if (hasVarwidthColumn()) {
if (is_long_tabular)
features.require("xltabular");
else
features.require("tabularx");
}
for (idx_type cell = 0; cell < numberofcells; ++cell) {
if (isMultiRow(cell))
features.require("multirow");
@ -4619,6 +4686,7 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
switch (action) {
case Tabular::SET_PWIDTH:
case Tabular::SET_MPWIDTH:
case Tabular::TOGGLE_VARWIDTH_COLUMN:
case Tabular::SET_SPECIAL_COLUMN:
case Tabular::SET_SPECIAL_MULTICOLUMN:
case Tabular::APPEND_ROW:
@ -4634,7 +4702,7 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
return true;
case Tabular::SET_TABULAR_WIDTH:
status.setEnabled(!tabular.rotate && !tabular.is_long_tabular
status.setEnabled(!tabular.rotate
&& tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE);
break;
@ -5597,6 +5665,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
tabular.setMColumnPWidth(cur, cur.idx(), Length(value));
break;
case Tabular::TOGGLE_VARWIDTH_COLUMN: {
bool const varwidth = value == "on";
tabular.toggleVarwidth(cur.idx(), varwidth);
break;
}
case Tabular::SET_MROFFSET:
tabular.setMROffset(cur, cur.idx(), Length(value));
break;

View File

@ -228,6 +228,8 @@ public:
///
SET_MPWIDTH,
///
TOGGLE_VARWIDTH_COLUMN,
///
SET_ROTATE_TABULAR,
///
UNSET_ROTATE_TABULAR,
@ -460,6 +462,8 @@ public:
///
bool setMColumnPWidth(Cursor &, idx_type, Length const &);
///
bool toggleVarwidth(idx_type, bool const);
///
bool setMROffset(Cursor &, idx_type, Length const &);
///
void setAlignSpecial(idx_type cell, docstring const & special,
@ -526,6 +530,8 @@ public:
///
bool hasMultiColumn(col_type cell) const;
///
bool hasVarwidthColumn() const;
///
idx_type setMultiColumn(idx_type cell, idx_type number,
bool const right_border);
///
@ -741,6 +747,8 @@ public:
docstring align_special;
///
docstring decimal_point;
///
bool varwidth;
};
///
typedef std::vector<ColumnData> column_vector;

View File

@ -206,8 +206,8 @@ const char * const known_lyx_packages[] = {"amsbsy", "amsmath", "amssymb",
"amstext", "amsthm", "array", "babel", "booktabs", "calc", "CJK", "color",
"float", "fontspec", "framed", "graphicx", "hhline", "ifthen", "longtable",
"makeidx", "minted", "nomencl", "pdfpages", "prettyref", "refstyle",
"rotating", "rotfloat", "splitidx", "setspace", "subscript", "textcomp", "tipa",
"tipx", "tone", "ulem", "url", "varioref", "verbatim", "wrapfig", "xcolor",
"rotating", "rotfloat", "splitidx", "setspace", "subscript", "tabularx","textcomp", "tipa",
"tipx", "tone", "ulem", "url", "varioref", "verbatim", "wrapfig", "xcolor", "xltabular",
"xunicode", 0};
// codes used to remove packages that are loaded automatically by LyX.

View File

@ -37,7 +37,7 @@ namespace {
class ColInfo {
public:
ColInfo() : align('n'), valign('n'), rightlines(0), leftlines(0) {}
ColInfo() : align('n'), valign('n'), rightlines(0), leftlines(0), varwidth(false) {}
/// column alignment
char align;
/// vertical alignment
@ -50,6 +50,8 @@ public:
int rightlines;
/// number of lines on the left
int leftlines;
/// varwidth column
bool varwidth;
};
@ -257,18 +259,23 @@ void ci2special(ColInfo & ci)
return;
if (!ci.width.empty()) {
string arraybackslash;
if (ci.varwidth)
arraybackslash = "\\arraybackslash";
switch (ci.align) {
case 'l':
ci.special += ">{\\raggedright}";
ci.special += ">{\\raggedright" + arraybackslash + "}";
break;
case 'r':
ci.special += ">{\\raggedleft}";
ci.special += ">{\\raggedleft" + arraybackslash + "}";
break;
case 'c':
ci.special += ">{\\centering}";
ci.special += ">{\\centering" + arraybackslash + "}";
break;
}
if (ci.valign == 'n')
if (ci.varwidth)
ci.special += 'X';
else if (ci.valign == 'n')
ci.special += 'p';
else
ci.special += ci.valign;
@ -335,6 +342,14 @@ void handle_colalign(Parser & p, vector<ColInfo> & colinfo,
colinfo.push_back(next);
next = ColInfo();
break;
case 'X':
// varwidth column
next.varwidth = true;
if (!next.special.empty())
ci2special(next);
colinfo.push_back(next);
next = ColInfo();
break;
case 'p':
case 'b':
case 'm':
@ -368,11 +383,11 @@ void handle_colalign(Parser & p, vector<ColInfo> & colinfo,
// Maybe this can be converted to a
// horizontal alignment setting for
// fixed width columns
if (s == "\\raggedleft")
if (s == "\\raggedleft" || s == "\\raggedleft\\arraybackslash")
next.align = 'r';
else if (s == "\\raggedright")
else if (s == "\\raggedright" || s == "\\raggedright\\arraybackslash")
next.align = 'l';
else if (s == "\\centering")
else if (s == "\\centering" || s == "\\centering\\arraybackslash")
next.align = 'c';
else
next.special = ">{" + s + '}';
@ -837,18 +852,15 @@ void handle_hline_below(RowInfo & ri, vector<CellInfo> & ci)
void handle_tabular(Parser & p, ostream & os, string const & name,
string const & tabularwidth, Context & context)
string const & tabularwidth, string const & halign,
Context & context)
{
bool const is_long_tabular(name == "longtable");
bool const is_long_tabular(name == "longtable" || name == "xltabular");
bool booktabs = false;
string tabularvalignment("middle");
string posopts = p.getOpt();
if (!posopts.empty()) {
// FIXME: Convert this to ERT
if (is_long_tabular)
cerr << "horizontal longtable positioning '"
<< posopts << "' ignored\n";
else if (posopts == "[t]")
if (posopts == "[t]")
tabularvalignment = "top";
else if (posopts == "[b]")
tabularvalignment = "bottom";
@ -1314,8 +1326,12 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
if (booktabs)
preamble.registerAutomaticallyLoadedPackage("booktabs");
if (is_long_tabular)
if (name == "longtable")
preamble.registerAutomaticallyLoadedPackage("longtable");
else if (name == "xltabular")
preamble.registerAutomaticallyLoadedPackage("xltabular");
else if (name == "tabularx")
preamble.registerAutomaticallyLoadedPackage("tabularx");
//cerr << "// output what we have\n";
// output what we have
@ -1337,6 +1353,8 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
<< write_attribute("lastFootTopDL", endlastfoot.topDL)
<< write_attribute("lastFootBottomDL", endlastfoot.bottomDL)
<< write_attribute("lastFootEmpty", endlastfoot.empty);
if (!halign.empty())
os << write_attribute("longtabularalignment", halign);
} else
os << write_attribute("tabularvalignment", tabularvalignment)
<< write_attribute("tabularwidth", tabularwidth);
@ -1350,6 +1368,7 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
<< verbose_valign(colinfo[col].valign) << "\""
<< write_attribute("width", translate_len(colinfo[col].width))
<< write_attribute("special", colinfo[col].special)
<< write_attribute("varwidth", colinfo[col].varwidth)
<< ">\n";
}
//cerr << "// after cols\n";

View File

@ -81,7 +81,8 @@ void parse_math(Parser & p, std::ostream & os, unsigned flags, mode_type mode);
/// in table.cpp
void handle_tabular(Parser & p, std::ostream & os, std::string const & name,
std::string const & width, Context & context);
std::string const & width, std::string const & halign,
Context & context);
/// in tex2lyx.cpp

View File

@ -1614,16 +1614,27 @@ void parse_environment(Parser & p, ostream & os, bool outer,
p.skip_spaces();
}
else if (unstarred_name == "tabular" || name == "longtable") {
else if (unstarred_name == "tabular" || name == "longtable"
|| name == "tabularx" || name == "xltabular") {
eat_whitespace(p, os, parent_context, false);
string width = "0pt";
if (name == "tabular*") {
string halign;
if ((name == "longtable" || name == "xltabular") && p.hasOpt()) {
string const opt = p.getArg('[', ']');
if (opt == "c")
halign = "center";
else if (opt == "l")
halign = "left";
else if (opt == "r")
halign = "right";
}
if (name == "tabular*" || name == "tabularx" || name == "xltabular") {
width = lyx::translate_len(p.getArg('{', '}'));
eat_whitespace(p, os, parent_context, false);
}
parent_context.check_layout(os);
begin_inset(os, "Tabular ");
handle_tabular(p, os, name, width, parent_context);
handle_tabular(p, os, name, width, halign, parent_context);
end_inset(os);
p.skip_spaces();
}

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 553 // spitz: tufte \cite
#define LYX_FORMAT_TEX2LYX 553
#define LYX_FORMAT_LYX 554 // spitz: tabularx/xltabular
#define LYX_FORMAT_TEX2LYX 554
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER