booktabs: support for \cmidrule trimming

This has probably still some rough edges, so please test thoroughly.

Fixes: #3072
This commit is contained in:
Juergen Spitzmueller 2019-04-03 07:59:52 +02:00
parent 2e854cd36c
commit 8085fc21f8
11 changed files with 780 additions and 90 deletions

View File

@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be
-----------------------
2019-04-03 Jürgen Spitzmüller <spitz@lyx.org>
* format incremented to 571: Add \cmidrule trimming support
\cmidrule(lr){n-n}
<cell ... toplineltrim|toplinettrim|bottomlineltrim|bottomlinertrim true ...>
2019-03-29 Jürgen Spitzmüller <spitz@lyx.org>
* format incremented to 570: Add individual bib encodings for biblatex
\begin_inset CommandInset bibtex

View File

@ -1555,6 +1555,26 @@ def revert_bibfileencodings(document):
i = j + 1
def revert_cmidruletrimming(document):
" Remove \\cmidrule trimming "
# FIXME: Revert to TeX code?
i = 0
while True:
# first, let's find out if we need to do anything
i = find_token(document.body, '<cell ', i)
if i == -1:
return
j = document.body[i].find('trim="')
if j == -1:
i += 1
continue
rgx = re.compile(r' (bottom|top)line[lr]trim="true"')
# remove trim option
document.body[i] = rgx.sub('', document.body[i])
i += 1
##
# Conversion hub
@ -1587,10 +1607,12 @@ convert = [
[567, []],
[568, []],
[569, []],
[570, []]
[570, []],
[571, []]
]
revert = [
[570, [revert_cmidruletrimming]],
[569, [revert_bibfileencodings]],
[568, [revert_tablestyle]],
[567, [revert_soul]],

View File

@ -3752,7 +3752,10 @@ void LyXAction::init()
* \li Params: Generally see #LFUN_INSET_INSERT for further details.\n
* <FEATURE>: append-row|append-column|delete-row|delete-column|copy-row|\n
copy-column|move-column-right|move-column-left|move-row-down|move-row-up|\n
set-line-top|set-line-bottom|set-line-left|set-line-right|\n
toggle-line-top|toggle-line-bottom|toggle-line-left|toggle-line-right|\n
set-ltrim-top|set-rtrim-top|set-ltrim-bottom|set-rtrim-bottom\n
toggle-ltrim-top|toggle-rtrim-top|toggle-ltrim-bottom|toggle-rtrim-bottom\n
align-left|align-right|align-center|align-block|align-decimal|set-decimal-point|\n
valign-top|valign-bottom|valign-middle|longtabular-align-left|\n
longtabular-align-center|longtabular-align-right|m-align-left|m-align-right|\n

View File

@ -5,6 +5,7 @@
*
* \author Edwin Leuven
* \author John Levon
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
@ -13,26 +14,29 @@
#include "GuiSetBorder.h"
#include "support/debug.h"
#include <QPainter>
#include <QMouseEvent>
#include <QPaintEvent>
GuiSetBorder::GuiSetBorder(QWidget * parent, Qt::WindowFlags fl)
: QWidget(parent, fl), buffer(75, 75)
: QWidget(parent, fl), buffer(75, 75), bottom_drawn_wide_(false),
top_drawn_wide_(false)
{
/* length of corner line */
l = buffer.width() / 10;
corner_length = buffer.width() / 10;
/* margin */
m = buffer.height() / 10;
margin = buffer.height() / 10;
w = buffer.width();
h = buffer.height();
bwidth = buffer.width();
bheight = buffer.height();
init();
setMinimumSize(w,h);
setMaximumSize(w,h);
setMinimumSize(bwidth, bheight);
setMaximumSize(bwidth, bheight);
}
@ -51,19 +55,26 @@ void GuiSetBorder::init()
paint.setPen(Qt::black);
// FIXME: wow, readable !! :)
// Draw the corner marks
paint.drawLine(margin + corner_length, margin,
margin + corner_length, margin + corner_length);
paint.drawLine(bwidth - (margin + corner_length), margin,
bwidth - (margin + corner_length), margin + corner_length);
paint.drawLine(m + l , m, m + l, m + l);
paint.drawLine(w - (m + l), m, w - (m + l), m + l);
paint.drawLine(margin, margin + corner_length,
margin + corner_length, margin + corner_length);
paint.drawLine(margin, bheight - (margin + corner_length),
margin + corner_length, bheight - (margin + corner_length));
paint.drawLine(m, m + l , m + l, m + l);
paint.drawLine(m, h - (m + l), m + l, h - (m + l));
paint.drawLine(margin + corner_length ,bheight - margin,
margin + corner_length ,bheight - (margin + corner_length));
paint.drawLine(bwidth - (margin + corner_length), bheight - margin,
bwidth - (margin + corner_length), bheight - (margin + corner_length));
paint.drawLine(m + l ,h - m, m + l ,h - (m + l));
paint.drawLine(w - (m + l), h - m, w - (m + l), h - (m + l));
paint.drawLine(h - m, m+l, h - (m + l), m + l);
paint.drawLine(h - m, h - (m + l), h - (m + l),h - (m + l));
paint.drawLine(bheight - margin, margin+corner_length,
bheight - (margin + corner_length), margin + corner_length);
paint.drawLine(bheight - margin, bheight - (margin + corner_length),
bheight - (margin + corner_length),bheight - (margin + corner_length));
}
@ -77,7 +88,15 @@ void GuiSetBorder::mousePressEvent(QMouseEvent * e)
leftSet();
}
} else {
if (bottom_.enabled) {
if (bottom_trim_left_.enabled && e->x() < margin + 4 + 2 * corner_length) {
setBottomLeftTrim(bottom_trim_left_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
bottomLTSet();
} else if (bottom_trim_right_.enabled && e->x() > bwidth - margin - 2 * corner_length - 4) {
setBottomRightTrim(bottom_trim_right_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
bottomRTSet();
} else if (bottom_.enabled) {
setBottom(bottom_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
bottomSet();
@ -85,7 +104,15 @@ void GuiSetBorder::mousePressEvent(QMouseEvent * e)
}
} else {
if (e->y() < height() - e->x()) {
if (top_.enabled) {
if (top_trim_left_.enabled && e->x() < margin + 4 + 2 * corner_length) {
setTopLeftTrim(top_trim_left_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
topLTSet();
} else if (top_trim_right_.enabled && e->x() > bwidth - margin - 2 * corner_length - 4) {
setTopRightTrim(top_trim_right_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
topRTSet();
} else if (top_.enabled) {
setTop(top_.set == LINE_SET ? LINE_UNSET : LINE_SET);
// emit signal
topSet();
@ -132,7 +159,8 @@ void GuiSetBorder::drawLeft(BorderState draw)
}
if (!left_.enabled)
col = QColor(Qt::lightGray);
drawLine(col, m + l, m + l + 2, m + l, h - m - l - 1);
drawLine(col, margin + corner_length, margin + corner_length + 2,
margin + corner_length, bheight - margin - corner_length - 1);
}
@ -153,7 +181,8 @@ void GuiSetBorder::drawRight(BorderState draw)
}
if (!right_.enabled)
col = QColor(Qt::lightGray);
drawLine(col, h - m - l + 1, m + l + 2, h - m - l + 1, h - m - l - 1);
drawLine(col, bheight - margin - corner_length + 1, margin + corner_length + 2,
bheight - margin - corner_length + 1, bheight - margin - corner_length - 1);
}
@ -163,22 +192,40 @@ void GuiSetBorder::drawTop(BorderState draw)
switch (draw) {
case LINE_SET:
col = Qt::black;
top_drawn_wide_ = true;
break;
case LINE_UNSET:
col = Qt::white;
top_drawn_wide_ = false;
break;
case LINE_UNDECIDED:
case LINE_UNDEF:
col = Qt::lightGray;
top_drawn_wide_ = true;
break;
}
if (!top_.enabled)
col = QColor(Qt::lightGray);
drawLine(col, m + l + 2, m + l, w - m - l - 1, m + l);
int const lt = (top_trim_left_.enabled) ? corner_length + 4 : 0;
int const rt = (top_trim_right_.enabled) ? corner_length + 4 : 0;
drawLine(col, margin + corner_length + 2 + lt, margin + corner_length,
bwidth - margin - corner_length - 1 - rt, margin + corner_length);
}
void GuiSetBorder::drawBottom(BorderState draw)
void GuiSetBorder::undrawWideTopLine()
{
if (!top_drawn_wide_)
return;
// Overpaint previous lines white
drawLine(Qt::white, margin + corner_length + 2, margin + corner_length,
bwidth - margin - corner_length - 1, margin + corner_length);
top_drawn_wide_ = false;
}
void GuiSetBorder::drawTopLeftTrim(BorderState draw)
{
QColor col;
switch (draw) {
@ -193,9 +240,123 @@ void GuiSetBorder::drawBottom(BorderState draw)
col = Qt::lightGray;
break;
}
if (!top_trim_left_.enabled)
col = QColor(Qt::white);
int const lt = corner_length;
if (top_trim_left_.enabled)
drawLine(col, margin + corner_length + 2, margin + corner_length,
margin + corner_length + 2 + lt, margin + corner_length);
}
void GuiSetBorder::drawTopRightTrim(BorderState draw)
{
QColor col;
switch (draw) {
case LINE_SET:
col = Qt::black;
break;
case LINE_UNSET:
col = Qt::white;
break;
case LINE_UNDECIDED:
case LINE_UNDEF:
col = Qt::lightGray;
break;
}
if (!top_trim_right_.enabled)
col = QColor(Qt::white);
int const rt = corner_length;
if (top_trim_right_.enabled)
drawLine(col, bwidth - margin - corner_length - 1 - rt, margin + corner_length,
bwidth - margin - corner_length - 1, margin + corner_length);
}
void GuiSetBorder::drawBottom(BorderState draw)
{
QColor col;
switch (draw) {
case LINE_SET:
col = Qt::black;
bottom_drawn_wide_ = true;
break;
case LINE_UNSET:
col = Qt::white;
bottom_drawn_wide_ = false;
break;
case LINE_UNDECIDED:
case LINE_UNDEF:
col = Qt::lightGray;
bottom_drawn_wide_ = true;
break;
}
if (!bottom_.enabled)
col = QColor(Qt::lightGray);
drawLine(col, m + l + 2, w - m - l + 1, w - m - l - 1, w - m - l + 1);
int const lt = (bottom_trim_left_.enabled) ? corner_length + 4 : 0;
int const rt = (bottom_trim_right_.enabled) ? corner_length + 4 : 0;
drawLine(col, margin + corner_length + 2 + lt, bwidth - margin - corner_length + 1,
bwidth - margin - corner_length - 1 - rt, bwidth - margin - corner_length + 1);
}
void GuiSetBorder::undrawWideBottomLine()
{
if (!bottom_drawn_wide_)
return;
//Overpaint previous lines white
drawLine(Qt::white, margin + corner_length + 2, bwidth - margin - corner_length + 1,
bwidth - margin - corner_length - 1, bwidth - margin - corner_length + 1);
bottom_drawn_wide_ = false;
}
void GuiSetBorder::drawBottomLeftTrim(BorderState draw)
{
QColor col;
switch (draw) {
case LINE_SET:
col = Qt::black;
break;
case LINE_UNSET:
col = Qt::white;
break;
case LINE_UNDECIDED:
case LINE_UNDEF:
col = Qt::lightGray;
break;
}
if (!bottom_trim_left_.enabled)
col = QColor(Qt::white);
int const lt = corner_length;
if (bottom_trim_left_.enabled)
drawLine(col, margin + corner_length + 2, bwidth - margin - corner_length + 1,
margin + corner_length + 2 + lt, bwidth - margin - corner_length + 1);
}
void GuiSetBorder::drawBottomRightTrim(BorderState draw)
{
QColor col;
switch (draw) {
case LINE_SET:
col = Qt::black;
break;
case LINE_UNSET:
col = Qt::white;
break;
case LINE_UNDECIDED:
case LINE_UNDEF:
col = Qt::lightGray;
break;
}
if (!bottom_trim_right_.enabled)
col = QColor(Qt::white);
int const rt = corner_length;
if (bottom_trim_right_.enabled)
drawLine(col, bwidth - margin - corner_length - 1 - rt, bwidth - margin - corner_length + 1,
bwidth - margin - corner_length - 1, bwidth - margin - corner_length + 1);
}
@ -227,6 +388,46 @@ void GuiSetBorder::setBottomEnabled(bool enabled)
}
void GuiSetBorder::setTopLeftTrimEnabled(bool enabled)
{
top_trim_left_.enabled = enabled;
undrawWideTopLine();
drawTopLeftTrim(top_trim_left_.set);
drawTop(top_.set);
top_drawn_wide_ = !enabled;
}
void GuiSetBorder::setTopRightTrimEnabled(bool enabled)
{
top_trim_right_.enabled = enabled;
undrawWideTopLine();
drawTopRightTrim(top_trim_right_.set);
drawTop(top_.set);
top_drawn_wide_ = !enabled;;
}
void GuiSetBorder::setBottomLeftTrimEnabled(bool enabled)
{
bottom_trim_left_.enabled = enabled;
undrawWideBottomLine();
drawBottomLeftTrim(bottom_trim_left_.set);
drawBottom(bottom_.set);
bottom_drawn_wide_ = !enabled;;
}
void GuiSetBorder::setBottomRightTrimEnabled(bool enabled)
{
bottom_trim_right_.enabled = enabled;
undrawWideBottomLine();
drawBottomRightTrim(bottom_trim_right_.set);
drawBottom(bottom_.set);
bottom_drawn_wide_ = !enabled;;
}
void GuiSetBorder::setLeft(BorderState border)
{
left_.set = border;
@ -255,12 +456,43 @@ void GuiSetBorder::setBottom(BorderState border)
}
void GuiSetBorder::setTopLeftTrim(BorderState border)
{
top_trim_left_.set = border;
drawTopLeftTrim(border);
}
void GuiSetBorder::setTopRightTrim(BorderState border)
{
top_trim_right_.set = border;
drawTopRightTrim(border);
}
void GuiSetBorder::setBottomLeftTrim(BorderState border)
{
bottom_trim_left_.set = border;
drawBottomLeftTrim(border);
}
void GuiSetBorder::setBottomRightTrim(BorderState border)
{
bottom_trim_right_.set = border;
drawBottomRightTrim(border);
}
void GuiSetBorder::setAll(BorderState border)
{
setLeft(border);
setRight(border);
setTop(border);
setBottom(border);
setTopLeftTrim(border);
setTopRightTrim(border);
setBottomLeftTrim(border);
setBottomRightTrim(border);
}
@ -287,4 +519,28 @@ GuiSetBorder::BorderState GuiSetBorder::getBottom()
return bottom_.set;
}
GuiSetBorder::BorderState GuiSetBorder::getTopLeftTrim()
{
return top_trim_left_.set;
}
GuiSetBorder::BorderState GuiSetBorder::getTopRightTrim()
{
return top_trim_right_.set;
}
GuiSetBorder::BorderState GuiSetBorder::getBottomLeftTrim()
{
return bottom_trim_left_.set;
}
GuiSetBorder::BorderState GuiSetBorder::getBottomRightTrim()
{
return bottom_trim_right_.set;
}
#include "moc_GuiSetBorder.cpp"

View File

@ -6,6 +6,7 @@
*
* \author Edwin Leuven
* \author John Levon
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
@ -26,7 +27,7 @@ class GuiSetBorder : public QWidget
{
Q_OBJECT
public:
GuiSetBorder(QWidget * parent = 0, Qt::WindowFlags fl = 0);
GuiSetBorder(QWidget * parent = nullptr, Qt::WindowFlags fl = nullptr);
// We need tristate for multi-cell selection
enum BorderState {
@ -40,6 +41,10 @@ public:
BorderState getRight();
BorderState getTop();
BorderState getBottom();
BorderState getTopLeftTrim();
BorderState getTopRightTrim();
BorderState getBottomLeftTrim();
BorderState getBottomRightTrim();
bool leftLineSet() { return getLeft() == LINE_SET; }
bool rightLineSet() { return getRight() == LINE_SET; }
@ -51,11 +56,25 @@ public:
bool topLineUnset() { return getTop() == LINE_UNSET; }
bool bottomLineUnset() { return getBottom() == LINE_UNSET; }
bool topLineLTSet() { return getTopLeftTrim() == LINE_SET; }
bool bottomLineLTSet() { return getBottomLeftTrim() == LINE_SET; }
bool topLineRTSet() { return getTopRightTrim() == LINE_SET; }
bool bottomLineRTSet() { return getBottomRightTrim() == LINE_SET; }
bool topLineLTUnset() { return getTopLeftTrim() == LINE_UNSET; }
bool bottomLineLTUnset() { return getBottomLeftTrim() == LINE_UNSET; }
bool topLineRTUnset() { return getTopRightTrim() == LINE_UNSET; }
bool bottomLineRTUnset() { return getBottomRightTrim() == LINE_UNSET; }
Q_SIGNALS:
void rightSet();
void leftSet();
void topSet();
void bottomSet();
void topLTSet();
void bottomLTSet();
void topRTSet();
void bottomRTSet();
void clicked();
public Q_SLOTS:
@ -63,10 +82,18 @@ public Q_SLOTS:
void setRightEnabled(bool);
void setTopEnabled(bool);
void setBottomEnabled(bool);
void setTopLeftTrimEnabled(bool);
void setTopRightTrimEnabled(bool);
void setBottomLeftTrimEnabled(bool);
void setBottomRightTrimEnabled(bool);
void setLeft(BorderState);
void setRight(BorderState);
void setTop(BorderState);
void setBottom(BorderState);
void setTopLeftTrim(BorderState);
void setTopRightTrim(BorderState);
void setBottomLeftTrim(BorderState);
void setBottomRightTrim(BorderState);
void setAll(BorderState);
protected:
@ -81,7 +108,13 @@ private:
void drawLeft(BorderState);
void drawRight(BorderState);
void drawTop(BorderState);
void undrawWideTopLine();
void drawBottom(BorderState);
void undrawWideBottomLine();
void drawTopLeftTrim(BorderState);
void drawTopRightTrim(BorderState);
void drawBottomLeftTrim(BorderState);
void drawBottomRightTrim(BorderState);
class Border {
public:
@ -94,13 +127,21 @@ private:
Border right_;
Border top_;
Border bottom_;
/// trim areas
Border top_trim_left_;
Border top_trim_right_;
Border bottom_trim_left_;
Border bottom_trim_right_;
int m;
int l;
int w;
int h;
int margin;
int corner_length;
int bwidth;
int bheight;
QPixmap buffer;
bool bottom_drawn_wide_;
bool top_drawn_wide_;
};

View File

@ -48,7 +48,7 @@ namespace frontend {
GuiTabular::GuiTabular(QWidget * parent)
: InsetParamsWidget(parent), firstheader_suppressable_(false),
lastfooter_suppressable_(false), orig_leftborder_(GuiSetBorder::LINE_UNDEF),
orig_rightborder_(GuiSetBorder::LINE_UNDEF)
orig_rightborder_(GuiSetBorder::LINE_UNDEF), lastrow_(0)
{
setupUi(this);
@ -147,6 +147,14 @@ GuiTabular::GuiTabular(QWidget * parent)
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(leftSet()),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(topLTSet()),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(topRTSet()),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(bottomLTSet()),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(bottomRTSet()),
this, SLOT(checkEnabled()));
connect(rotateTabularCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
@ -344,6 +352,20 @@ void GuiTabular::enableWidgets() const
// Vertical lines cannot be set in formal tables
borders->setLeftEnabled(!booktabsRB->isChecked());
borders->setRightEnabled(!booktabsRB->isChecked());
// Trimming is only allowed in booktabs and if the line is set
int const row = tabularRowED->text().toInt();
borders->setTopLeftTrimEnabled(booktabsRB->isChecked()
&& borders->topLineSet()
&& row > 1);
borders->setTopRightTrimEnabled(booktabsRB->isChecked()
&& borders->topLineSet()
&& row > 1);
borders->setBottomLeftTrimEnabled(booktabsRB->isChecked()
&& borders->bottomLineSet()
&& row < lastrow_);
borders->setBottomRightTrimEnabled(booktabsRB->isChecked()
&& borders->bottomLineSet()
&& row < lastrow_);
}
@ -360,6 +382,10 @@ void GuiTabular::borderSet_clicked()
borders->setBottom(GuiSetBorder::LINE_SET);
borders->setLeft(GuiSetBorder::LINE_SET);
borders->setRight(GuiSetBorder::LINE_SET);
borders->setTopLeftTrim(GuiSetBorder::LINE_SET);
borders->setBottomLeftTrim(GuiSetBorder::LINE_SET);
borders->setTopRightTrim(GuiSetBorder::LINE_SET);
borders->setBottomRightTrim(GuiSetBorder::LINE_SET);
// repaint the setborder widget
borders->update();
checkEnabled();
@ -372,6 +398,10 @@ void GuiTabular::borderUnset_clicked()
borders->setBottom(GuiSetBorder::LINE_UNSET);
borders->setLeft(GuiSetBorder::LINE_UNSET);
borders->setRight(GuiSetBorder::LINE_UNSET);
borders->setTopLeftTrim(GuiSetBorder::LINE_UNSET);
borders->setBottomLeftTrim(GuiSetBorder::LINE_UNSET);
borders->setTopRightTrim(GuiSetBorder::LINE_UNSET);
borders->setBottomRightTrim(GuiSetBorder::LINE_UNSET);
// repaint the setborder widget
borders->update();
checkEnabled();
@ -603,6 +633,22 @@ docstring GuiTabular::dialogToParams() const
setParam(param_str, Tabular::SET_LINE_BOTTOM,
borders->bottomLineSet() ? "true" : "false");
}
if (borders->topLineLTSet())
setParam(param_str, Tabular::SET_LTRIM_TOP, "false");
else if (borders->topLineLTUnset())
setParam(param_str, Tabular::SET_LTRIM_TOP, "true");
if (borders->topLineRTSet())
setParam(param_str, Tabular::SET_RTRIM_TOP, "false");
else if (borders->topLineRTUnset())
setParam(param_str, Tabular::SET_RTRIM_TOP, "true");
if (borders->bottomLineLTSet())
setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "false");
else if (borders->bottomLineRTUnset())
setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "true");
if (borders->bottomLineRTSet())
setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "false");
else if (borders->bottomLineRTUnset())
setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "true");
// apply the special alignment
string special = fromqstr(specialAlignmentED->text());
@ -784,6 +830,7 @@ void GuiTabular::paramsToDialog(Inset const * inset)
tabularRowED->setText(QString::number(row + 1));
tabularColumnED->setText(QString::number(col + 1));
lastrow_ = int(tabular.nrows());
bool const multicol = tabular.isMultiColumn(cell);
multicolumnCB->setChecked(multicol);
@ -810,12 +857,16 @@ void GuiTabular::paramsToDialog(Inset const * inset)
}
// In what follows, we check the borders of all selected cells,
// and if there are diverging settings, we use the LINE_UNDEF
// and if there are diverging settings, we use the LINE_UNDECIDED
// border status.
GuiSetBorder::BorderState lt = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lb = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState ll = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lr = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState ltop = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lbottom = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lleft = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lright = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState ltop_ltrim = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState ltop_rtrim = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lbottom_ltrim = GuiSetBorder::LINE_UNDEF;
GuiSetBorder::BorderState lbottom_rtrim = GuiSetBorder::LINE_UNDEF;
CursorSlice const & beg = bv->cursor().selBegin();
CursorSlice const & end = bv->cursor().selEnd();
if (beg != end) {
@ -830,27 +881,39 @@ void GuiTabular::paramsToDialog(Inset const * inset)
for (Tabular::row_type r = rs; r <= re; ++r)
for (Tabular::col_type c = cs; c <= ce; ++c) {
idx_type const cc = tabular.cellIndex(r, c);
lt = borderState(lt, tabular.topLine(cc));
lb = borderState(lb, tabular.bottomLine(cc));
ll = borderState(ll, tabular.leftLine(cc));
lr = borderState(lr, tabular.rightLine(cc));
ltop = borderState(ltop, tabular.topLine(cc));
lbottom = borderState(lbottom, tabular.bottomLine(cc));
lleft = borderState(lleft, tabular.leftLine(cc));
lright = borderState(lright, tabular.rightLine(cc));
ltop_ltrim = borderState(ltop_ltrim, !tabular.topLineTrim(cc).first);
ltop_rtrim = borderState(ltop_rtrim, !tabular.topLineTrim(cc).second);
lbottom_ltrim = borderState(lbottom_ltrim, !tabular.bottomLineTrim(cc).first);
lbottom_rtrim = borderState(lbottom_rtrim, !tabular.bottomLineTrim(cc).second);
// store left/right borders for the case of formal/nonformal switch
orig_leftborder_ = borderState(ll, tabular.leftLine(cc, true));
orig_rightborder_ = borderState(lr, tabular.rightLine(cc, true));
orig_leftborder_ = borderState(lleft, tabular.leftLine(cc, true));
orig_rightborder_ = borderState(lright, tabular.rightLine(cc, true));
}
} else {
lt = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
lb = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
ll = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
lr = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
ltop = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
lbottom = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
lleft = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
lright = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
ltop_ltrim = tabular.topLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
ltop_rtrim = tabular.topLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
lbottom_ltrim = tabular.bottomLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
lbottom_rtrim = tabular.bottomLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET;
// store left/right borders for the case of formal/nonformal switch
orig_leftborder_ = tabular.leftLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
orig_rightborder_ = tabular.rightLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
}
borders->setTop(lt);
borders->setBottom(lb);
borders->setLeft(ll);
borders->setRight(lr);
borders->setTop(ltop);
borders->setBottom(lbottom);
borders->setLeft(lleft);
borders->setRight(lright);
borders->setTopLeftTrim(ltop_ltrim);
borders->setTopRightTrim(ltop_rtrim);
borders->setBottomLeftTrim(lbottom_ltrim);
borders->setBottomRightTrim(lbottom_rtrim);
// repaint the setborder widget
borders->update();

View File

@ -74,6 +74,8 @@ private:
GuiSetBorder::BorderState orig_leftborder_;
///
GuiSetBorder::BorderState orig_rightborder_;
///
int lastrow_;
};
} // namespace frontend

View File

@ -127,12 +127,20 @@ TabularFeature tabularFeature[] =
{ Tabular::MOVE_ROW_UP, "move-row-up", false },
{ Tabular::SET_LINE_TOP, "set-line-top", true },
{ Tabular::SET_LINE_BOTTOM, "set-line-bottom", true },
{ Tabular::SET_LTRIM_TOP, "set-ltrim-top", true },
{ Tabular::SET_LTRIM_BOTTOM, "set-ltrim-bottom", true },
{ Tabular::SET_RTRIM_TOP, "set-rtrim-top", true },
{ Tabular::SET_RTRIM_BOTTOM, "set-rtrim-bottom", true },
{ Tabular::SET_LINE_LEFT, "set-line-left", true },
{ Tabular::SET_LINE_RIGHT, "set-line-right", true },
{ Tabular::TOGGLE_LINE_TOP, "toggle-line-top", false },
{ Tabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom", false },
{ Tabular::TOGGLE_LINE_LEFT, "toggle-line-left", false },
{ Tabular::TOGGLE_LINE_RIGHT, "toggle-line-right", false },
{ Tabular::TOGGLE_LTRIM_TOP, "toggle-ltrim-top", true },
{ Tabular::TOGGLE_LTRIM_BOTTOM, "toggle-ltrim-bottom", true },
{ Tabular::TOGGLE_RTRIM_TOP, "toggle-rtrim-top", true },
{ Tabular::TOGGLE_RTRIM_BOTTOM, "toggle-rtrim-bottom", true },
{ Tabular::ALIGN_LEFT, "align-left", false },
{ Tabular::ALIGN_RIGHT, "align-right", false },
{ Tabular::ALIGN_CENTER, "align-center", false },
@ -585,6 +593,10 @@ Tabular::CellData::CellData(Buffer * buf)
bottom_line(false),
left_line(false),
right_line(false),
top_line_rtrimmed(false),
top_line_ltrimmed(false),
bottom_line_rtrimmed(false),
bottom_line_ltrimmed(false),
usebox(BOX_NONE),
rotate(0),
inset(new InsetTableCell(buf))
@ -608,6 +620,10 @@ Tabular::CellData::CellData(CellData const & cs)
bottom_line(cs.bottom_line),
left_line(cs.left_line),
right_line(cs.right_line),
top_line_rtrimmed(cs.top_line_rtrimmed),
top_line_ltrimmed(cs.top_line_ltrimmed),
bottom_line_rtrimmed(cs.bottom_line_rtrimmed),
bottom_line_ltrimmed(cs.bottom_line_ltrimmed),
usebox(cs.usebox),
rotate(cs.rotate),
align_special(cs.align_special),
@ -634,6 +650,10 @@ Tabular::CellData & Tabular::CellData::operator=(CellData const & cs)
bottom_line = cs.bottom_line;
left_line = cs.left_line;
right_line = cs.right_line;
top_line_rtrimmed = cs.top_line_rtrimmed;
top_line_ltrimmed = cs.top_line_ltrimmed;
bottom_line_rtrimmed = cs.bottom_line_rtrimmed;
bottom_line_rtrimmed = cs.bottom_line_rtrimmed;
usebox = cs.usebox;
rotate = cs.rotate;
align_special = cs.align_special;
@ -981,6 +1001,24 @@ bool Tabular::rightLine(idx_type cell, bool const ignore_bt) const
}
pair<bool, bool> Tabular::topLineTrim(idx_type const cell) const
{
if (!use_booktabs)
return make_pair(false, false);
return make_pair(cellInfo(cell).top_line_ltrimmed,
cellInfo(cell).top_line_rtrimmed);
}
pair<bool, bool> Tabular::bottomLineTrim(idx_type const cell) const
{
if (!use_booktabs)
return make_pair(false, false);
return make_pair(cellInfo(cell).bottom_line_ltrimmed,
cellInfo(cell).bottom_line_rtrimmed);
}
int Tabular::interRowSpace(row_type row) const
{
if (!row || row >= nrows())
@ -1321,6 +1359,42 @@ void Tabular::setBottomLine(idx_type i, bool line)
}
void Tabular::setTopLineLTrim(idx_type i, bool val)
{
cellInfo(i).top_line_ltrimmed = val;
}
void Tabular::setTopLineRTrim(idx_type i, bool val)
{
cellInfo(i).top_line_rtrimmed = val;
}
void Tabular::setBottomLineLTrim(idx_type i, bool val)
{
cellInfo(i).bottom_line_ltrimmed = val;
}
void Tabular::setBottomLineRTrim(idx_type i, bool val)
{
cellInfo(i).bottom_line_rtrimmed = val;
}
void Tabular::setTopLineTrim(idx_type i, pair<bool, bool> trim)
{
setTopLineLTrim(i, trim.first);
setTopLineRTrim(i, trim.second);
}
void Tabular::setBottomLineTrim(idx_type i, pair<bool, bool> trim)
{
setBottomLineLTrim(i, trim.first);
setBottomLineRTrim(i, trim.second);
}
void Tabular::setLeftLine(idx_type cell, bool line)
{
cellInfo(cell).left_line = line;
@ -1615,7 +1689,11 @@ void Tabular::write(ostream & os) const
<< write_attribute("alignment", cell_info[r][c].alignment)
<< write_attribute("valignment", cell_info[r][c].valignment)
<< write_attribute("topline", cell_info[r][c].top_line)
<< write_attribute("toplineltrim", cell_info[r][c].top_line_ltrimmed)
<< write_attribute("toplinertrim", cell_info[r][c].top_line_rtrimmed)
<< write_attribute("bottomline", cell_info[r][c].bottom_line)
<< write_attribute("bottomlineltrim", cell_info[r][c].bottom_line_ltrimmed)
<< write_attribute("bottomlinertrim", cell_info[r][c].bottom_line_rtrimmed)
<< write_attribute("leftline", cell_info[r][c].left_line)
<< write_attribute("rightline", cell_info[r][c].right_line)
<< write_attribute("rotate", cell_info[r][c].rotate)
@ -1729,7 +1807,11 @@ void Tabular::read(Lexer & lex)
getTokenValue(line, "alignment", cell_info[i][j].alignment);
getTokenValue(line, "valignment", cell_info[i][j].valignment);
getTokenValue(line, "topline", cell_info[i][j].top_line);
getTokenValue(line, "toplineltrim", cell_info[i][j].top_line_ltrimmed);
getTokenValue(line, "toplinertrim", cell_info[i][j].top_line_rtrimmed);
getTokenValue(line, "bottomline", cell_info[i][j].bottom_line);
getTokenValue(line, "bottomlineltrim", cell_info[i][j].bottom_line_ltrimmed);
getTokenValue(line, "bottomlinertrim", cell_info[i][j].bottom_line_rtrimmed);
getTokenValue(line, "leftline", cell_info[i][j].left_line);
getTokenValue(line, "rightline", cell_info[i][j].right_line);
getTokenValue(line, "rotate", cell_info[i][j].rotate);
@ -2305,18 +2387,27 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, string const & lang,
// is done in Tabular::TeXBottomHLine(...)
// get for each column the topline (if any)
map<col_type, bool> topline;
map<col_type, bool> topline, topltrims, toprtrims;
col_type nset = 0;
bool have_trims = false;
for (auto const & c : columns) {
topline[c] = topLine(cellIndex(row, c));
topltrims[c] = topLineTrim(cellIndex(row, c)).first;
toprtrims[c] = topLineTrim(cellIndex(row, c)).second;
// If cell is part of a multirow and not the first cell of the
// multirow, no line must be drawn.
if (row != 0)
if (isMultiRow(cellIndex(row, c))
&& cell_info[row][c].multirow != CELL_BEGIN_OF_MULTIROW)
&& cell_info[row][c].multirow != CELL_BEGIN_OF_MULTIROW) {
topline[c] = false;
topltrims[c] = false;
toprtrims[c] = false;
}
if (topline.find(c) != topline.end() && topline.find(c)->second)
++nset;
if ((topltrims.find(c) != topltrims.end() && topltrims.find(c)->second)
|| (toprtrims.find(c) != toprtrims.end() && toprtrims.find(c)->second))
have_trims = true;
}
// do nothing if empty first row, or incomplete row line after
@ -2324,36 +2415,57 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, string const & lang,
return;
// only output complete row lines and the 1st row's clines
if (nset == ncols()) {
if (nset == ncols() && !have_trims) {
if (use_booktabs) {
os << (row == 0 ? "\\toprule " : "\\midrule ");
} else {
os << "\\hline ";
}
} else if (row == 0) {
} else if (row == 0 || have_trims) {
string const cline = use_booktabs ? "\\cmidrule" : "\\cline";
for (auto & c : columns) {
if (topline.find(c)->second) {
col_type offset = 0;
for (col_type j = 0 ; j < c; ++j)
if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
++offset;
//babel makes the "-" character an active one, so we have to suppress this here
//see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
if (lang == "slovak" || lang == "czech")
os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline")
<< "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
else
os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
string trim;
if (topltrims.find(c) != topltrims.end()
&& topltrims.find(c)->second)
trim = "l";
string const firstcol = convert<string>(c + 1 + offset);
col_type cstart = c;
for ( ; c < ncols() && topline.find(c)->second; ++c) {}
for ( ; c < ncols() - 1 && topline.find(c)->second ; ++c) {
if (c > cstart && topltrims.find(c) != topltrims.end()
&& topltrims.find(c)->second) {
--c;
break;
} else if (toprtrims.find(c) != toprtrims.end()
&& toprtrims.find(c)->second)
break;
}
for (col_type j = cstart ; j < c ; ++j)
if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
++offset;
col_type const lastcol = c + 1 + offset;
if (toprtrims.find(c) != toprtrims.end()
&& toprtrims.find(c)->second)
trim += "r";
os << c + offset << "} ";
//babel makes the "-" character an active one, so we have to suppress this here
//see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
if (lang == "slovak" || lang == "czech") {
os << "\\expandafter" << cline;
if (!trim.empty())
os << "(" << trim << ")";
os << "\\expandafter{\\expandafter" << firstcol << "\\string-";
} else {
os << cline;
if (!trim.empty())
os << "(" << trim << ")";
os << "{" << firstcol << '-';
}
os << lastcol << "}";
if (c == ncols() - 1)
break;
}
}
}
@ -2369,11 +2481,16 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
// get the bottomlines of row r, and toplines in next row
bool lastrow = row == nrows() - 1;
map<col_type, bool> bottomline, topline;
map<col_type, bool> bottomline, topline, topltrims, toprtrims, bottomltrims, bottomrtrims;
bool nextrowset = true;
for (auto const & c : columns) {
idx_type const idx = cellIndex(row, c);
bottomline[c] = bottomLine(cellIndex(row, c));
bottomltrims[c] = bottomLineTrim(idx).first;
bottomrtrims[c] = bottomLineTrim(idx).second;
topline[c] = !lastrow && topLine(cellIndex(row + 1, c));
topltrims[c] = !lastrow && topLineTrim(cellIndex(row + 1, c)).first;
toprtrims[c] = !lastrow && topLineTrim(cellIndex(row + 1, c)).second;
// If cell is part of a multirow and not the last cell of the
// multirow, no line must be drawn.
if (!lastrow)
@ -2382,29 +2499,42 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
&& cell_info[row + 1][c].multirow != CELL_BEGIN_OF_MULTIROW) {
bottomline[c] = false;
topline[c] = false;
bottomltrims[c] = false;
bottomrtrims[c] = false;
topltrims[c] = false;
toprtrims[c] = false;
}
nextrowset &= topline.find(c) != topline.end() && topline.find(c)->second;
}
// combine this row's bottom lines and next row's toplines if necessary
col_type nset = 0;
bool have_trims = false;
for (auto const & c : columns) {
if (!nextrowset)
bottomline[c] = bottomline.find(c)->second || topline.find(c)->second;
bottomltrims[c] = (bottomltrims.find(c) != bottomltrims.end() && bottomltrims.find(c)->second)
|| (topltrims.find(c) != topltrims.end() && topltrims.find(c)->second);
bottomrtrims[c] =(bottomrtrims.find(c) != bottomrtrims.end() && bottomrtrims.find(c)->second)
|| (toprtrims.find(c) != toprtrims.end() && toprtrims.find(c)->second);
if (bottomline.find(c)->second)
++nset;
if ((bottomltrims.find(c) != bottomltrims.end() && bottomltrims.find(c)->second)
|| (bottomrtrims.find(c) != bottomrtrims.end() && bottomrtrims.find(c)->second))
have_trims = true;
}
// do nothing if empty, OR incomplete row line with a topline in next row
if (nset == 0 || (nextrowset && nset != ncols()))
return;
if (nset == ncols()) {
if (nset == ncols() && !have_trims) {
if (use_booktabs)
os << (lastrow ? "\\bottomrule" : "\\midrule");
else
os << "\\hline ";
} else {
string const cline = use_booktabs ? "\\cmidrule" : "\\cline";
for (auto & c : columns) {
if (bottomline.find(c)->second) {
col_type offset = 0;
@ -2412,22 +2542,46 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const & lang,
if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
++offset;
//babel makes the "-" character an active one, so we have to suppress this here
//see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
if (lang == "slovak" || lang == "czech")
os << "\\expandafter" << (use_booktabs ? "\\cmidrule" : "\\cline")
<< "\\expandafter{\\expandafter" << c + 1 + offset << "\\string-";
else
os << (use_booktabs ? "\\cmidrule{" : "\\cline{") << c + 1 + offset << '-';
string trim;
if (bottomltrims.find(c) != bottomltrims.end()
&& bottomltrims.find(c)->second)
trim = "l";
string const firstcol = convert<string>(c + 1 + offset);
col_type cstart = c;
for ( ; c < ncols() && bottomline.find(c)->second; ++c) {}
for ( ; c < ncols() - 1 && bottomline.find(c)->second ; ++c) {
if (c > cstart && bottomltrims.find(c) != bottomltrims.end()
&& bottomltrims.find(c)->second) {
--c;
break;
} else if (bottomrtrims.find(c) != bottomrtrims.end()
&& bottomrtrims.find(c)->second)
break;
}
for (col_type j = cstart ; j < c ; ++j)
if (column_info[j].alignment == LYX_ALIGN_DECIMAL)
++offset;
col_type const lastcol = c + 1 + offset;
if (bottomrtrims.find(c) != bottomrtrims.end()
&& bottomrtrims.find(c)->second)
trim += "r";
os << c + offset << "} ";
//babel makes the "-" character an active one, so we have to suppress this here
//see http://groups.google.com/group/comp.text.tex/browse_thread/thread/af769424a4a0f289#
if (lang == "slovak" || lang == "czech") {
os << "\\expandafter" << cline;
if (!trim.empty())
os << "(" << trim << ")";
os << "\\expandafter{\\expandafter" << firstcol << "\\string-";
} else {
os << cline;
if (!trim.empty())
os << "(" << trim << ")";
os << "{" << firstcol << '-';
}
os << lastcol << "}";
if (c == ncols() - 1)
break;
}
}
}
@ -4215,13 +4369,21 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
namespace {
void tabline(PainterInfo const & pi, int x1, int y1, int x2, int y2,
void tabline(PainterInfo const & pi, int x1, int y1, int x2, int y2, int lt, int rt,
bool drawline, bool heavy = false)
{
ColorCode const col = drawline ? Color_tabularline : Color_tabularonoffline;
pi.pain.line(x1, y1, x2, y2, pi.textColor(col),
if (drawline && lt > 0)
pi.pain.line(x1, y1, x1 + lt, y2, pi.textColor(Color_tabularonoffline),
Painter::line_onoffdash,
Painter::thin_line);
pi.pain.line(x1 + lt, y1, x2 - rt, y2, pi.textColor(col),
drawline ? Painter::line_solid : Painter::line_onoffdash,
(heavy ? 2 : 1) * Painter::thin_line);
if (drawline && rt > 0)
pi.pain.line(x2 - rt, y1, x2, y2, pi.textColor(Color_tabularonoffline),
Painter::line_onoffdash,
Painter::thin_line);
}
}
@ -4233,6 +4395,8 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
y -= tabular.rowAscent(row);
int const w = tabular.cellWidth(cell);
int const h = tabular.cellHeight(cell);
int lt = 0;
int rt = 0;
col_type const col = tabular.cellColumn(cell);
@ -4240,9 +4404,16 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
bool drawline = tabular.topLine(cell)
|| (row > 0 && tabular.bottomLine(tabular.cellAbove(cell)));
bool heavy = tabular.use_booktabs && row == 0 && tabular.rowTopLine(row);
tabline(pi, x, y, x + w, y, drawline, heavy);
if (tabular.topLineTrim(cell).first
|| (row > 0 && tabular.bottomLineTrim(tabular.cellIndex(row - 1, col)).first))
lt = 10;
if (tabular.topLineTrim(cell).second
|| (row > 0 && tabular.bottomLineTrim(tabular.cellIndex(row - 1, col)).second))
rt = 10;
tabline(pi, x, y, x + w, y, lt, rt, drawline, heavy);
// Bottom
lt = rt = 0;
drawline = tabular.bottomLine(cell);
row_type const lastrow = tabular.nrows() - 1;
// Consider multi-rows
@ -4253,12 +4424,16 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
heavy = tabular.use_booktabs
&& ((row == lastrow && tabular.rowBottomLine(row))
|| (r == lastrow && tabular.rowBottomLine(r)));
tabline(pi, x, y + h, x + w, y + h, drawline, heavy);
if (tabular.bottomLineTrim(cell).first)
lt = 10;
if (tabular.bottomLineTrim(cell).second)
rt = 10;
tabline(pi, x, y + h, x + w, y + h, lt, rt, drawline, heavy);
// Left
drawline = tabular.leftLine(cell)
|| (col > 0 && tabular.rightLine(tabular.cellIndex(row, col - 1)));
tabline(pi, x, y, x, y + h, drawline);
tabline(pi, x, y, x, y + h, 0, 0, drawline);
// Right
x -= tabular.interColumnSpace(cell);
@ -4269,7 +4444,7 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
drawline = tabular.rightLine(cell)
|| (next_cell_col < tabular.ncols()
&& tabular.leftLine(tabular.cellIndex(row, next_cell_col)));
tabline(pi, x + w, y, x + w, y + h, drawline);
tabline(pi, x + w, y, x + w, y + h, 0, 0, drawline);
}
@ -4999,6 +5174,20 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
break;
case Tabular::SET_LTRIM_TOP:
case Tabular::SET_RTRIM_TOP:
status.setEnabled(tabular.use_booktabs
&& tabular.cellRow(cur.idx()) != 0
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
break;
case Tabular::SET_LTRIM_BOTTOM:
case Tabular::SET_RTRIM_BOTTOM:
status.setEnabled(tabular.use_booktabs
&& tabular.cellRow(cur.idx()) != tabular.nrows() - 1
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
break;
case Tabular::TOGGLE_LINE_TOP:
status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
status.setOnOff(tabular.topLine(cur.idx()));
@ -5021,6 +5210,30 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
status.setOnOff(tabular.rightLine(cur.idx()));
break;
case Tabular::TOGGLE_LTRIM_TOP:
status.setEnabled(tabular.use_booktabs
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
status.setOnOff(tabular.topLineTrim(cur.idx()).first);
break;
case Tabular::TOGGLE_RTRIM_TOP:
status.setEnabled(tabular.use_booktabs
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
status.setOnOff(tabular.topLineTrim(cur.idx()).second);
break;
case Tabular::TOGGLE_LTRIM_BOTTOM:
status.setEnabled(tabular.use_booktabs
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
status.setOnOff(tabular.bottomLineTrim(cur.idx()).first);
break;
case Tabular::TOGGLE_RTRIM_BOTTOM:
status.setEnabled(tabular.use_booktabs
&& !tabular.ltCaption(tabular.cellRow(cur.idx())));
status.setOnOff(tabular.bottomLineTrim(cur.idx()).second);
break;
// multirow cells only inherit the alignment of the column if the column has
// no width, otherwise they are left-aligned
// therefore allow always left but right and center only if there is no width
@ -5901,9 +6114,12 @@ void InsetTabular::tabularFeatures(Cursor & cur,
case Tabular::DELETE_ROW:
if (sel_row_end == tabular.nrows() - 1 && sel_row_start != 0) {
for (col_type c = 0; c < tabular.ncols(); c++)
for (col_type c = 0; c < tabular.ncols(); c++) {
tabular.setBottomLine(tabular.cellIndex(sel_row_start - 1, c),
tabular.bottomLine(tabular.cellIndex(sel_row_end, c)));
tabular.setBottomLineTrim(tabular.cellIndex(sel_row_start - 1, c),
tabular.bottomLineTrim(tabular.cellIndex(sel_row_end, c)));
}
}
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
@ -5988,6 +6204,46 @@ void InsetTabular::tabularFeatures(Cursor & cur,
break;
}
case Tabular::SET_LTRIM_TOP:
case Tabular::TOGGLE_LTRIM_TOP: {
bool l = (feature == Tabular::SET_LTRIM_TOP)
? (value == "true") : !tabular.topLineTrim(cur.idx()).first;
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
for (col_type c = sel_col_start; c <= sel_col_end; ++c)
tabular.setTopLineLTrim(tabular.cellIndex(r, c), l);
break;
}
case Tabular::SET_RTRIM_TOP:
case Tabular::TOGGLE_RTRIM_TOP: {
bool l = (feature == Tabular::SET_RTRIM_TOP)
? (value == "true") : !tabular.topLineTrim(cur.idx()).second;
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
for (col_type c = sel_col_start; c <= sel_col_end; ++c)
tabular.setTopLineRTrim(tabular.cellIndex(r, c), l);
break;
}
case Tabular::SET_LTRIM_BOTTOM:
case Tabular::TOGGLE_LTRIM_BOTTOM: {
bool l = (feature == Tabular::SET_LTRIM_BOTTOM)
? (value == "true") : !tabular.bottomLineTrim(cur.idx()).first;
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
for (col_type c = sel_col_start; c <= sel_col_end; ++c)
tabular.setBottomLineLTrim(tabular.cellIndex(r, c), l);
break;
}
case Tabular::SET_RTRIM_BOTTOM:
case Tabular::TOGGLE_RTRIM_BOTTOM: {
bool l = (feature == Tabular::SET_RTRIM_BOTTOM)
? (value == "true") : !tabular.bottomLineTrim(cur.idx()).second;
for (row_type r = sel_row_start; r <= sel_row_end; ++r)
for (col_type c = sel_col_start; c <= sel_col_end; ++c)
tabular.setBottomLineRTrim(tabular.cellIndex(r, c), l);
break;
}
case Tabular::SET_LINE_LEFT:
case Tabular::TOGGLE_LINE_LEFT: {
bool lineSet = (feature == Tabular::SET_LINE_LEFT)

View File

@ -179,6 +179,22 @@ public:
///FIXME: remove
TOGGLE_LINE_RIGHT,
///
SET_LTRIM_TOP,
///
SET_RTRIM_TOP,
///
SET_LTRIM_BOTTOM,
///
SET_RTRIM_BOTTOM,
///
TOGGLE_LTRIM_TOP,
///
TOGGLE_RTRIM_TOP,
///
TOGGLE_LTRIM_BOTTOM,
///
TOGGLE_RTRIM_BOTTOM,
///
ALIGN_LEFT,
///
ALIGN_RIGHT,
@ -420,6 +436,10 @@ public:
/// If \p ignore_bt is true, we return the state as if booktabs was
/// not used
bool rightLine(idx_type cell, bool const ignore_bt = false) const;
/// Returns whether the top line is trimmed left and/or right
std::pair<bool, bool> topLineTrim(idx_type const cell) const;
/// Returns whether the bottom line is trimmed left and/or right
std::pair<bool, bool> bottomLineTrim(idx_type const cell) const;
/// return space occupied by the second horizontal line and
/// interline space above row \p row in pixels
@ -453,6 +473,18 @@ public:
///
void setBottomLine(idx_type cell, bool line);
///
void setTopLineLTrim(idx_type cell, bool val);
///
void setBottomLineLTrim(idx_type cell, bool val);
///
void setTopLineRTrim(idx_type cell, bool val);
///
void setBottomLineRTrim(idx_type cell, bool val);
///
void setTopLineTrim(idx_type cell, std::pair<bool, bool>);
///
void setBottomLineTrim(idx_type cell, std::pair<bool, bool>);
///
void setLeftLine(idx_type cell, bool line);
///
void setRightLine(idx_type cell, bool line);
@ -692,6 +724,14 @@ public:
///
bool right_line;
///
bool top_line_rtrimmed;
///
bool top_line_ltrimmed;
///
bool bottom_line_rtrimmed;
///
bool bottom_line_ltrimmed;
///
BoxType usebox;
///
int rotate;

View File

@ -34,6 +34,8 @@ Format LaTeX feature LyX feature
443 unicode-math.sty InsetMath*
453 automatic stmaryrd loading \use_package stmaryrd
457 automatic stackrel loading \use_package stackrel
571 cmirule trimming (booktabs)
\cmidrule(lr){n-n} <cell ... toplineltrim|toplinettrim|bottomlineltrim|bottomlinertrim true ...>

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 570 // spitz: biblatex bibencodings
#define LYX_FORMAT_TEX2LYX 570
#define LYX_FORMAT_LYX 571 // spitz: cmidrule trimming
#define LYX_FORMAT_TEX2LYX 571
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER