From 8010b90cb447ff9540823f21b49652ac462f81e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Uwe=20St=C3=B6hr?= Date: Mon, 11 May 2015 21:30:32 +0200 Subject: [PATCH] add ability to change box line thickness and separation fileformat change --- development/FORMAT | 8 + lib/lyx2lyx/LyX.py | 2 +- lib/lyx2lyx/lyx_2_2.py | 63 ++++- src/frontends/qt4/GuiBox.cpp | 139 +++++++++-- src/frontends/qt4/ui/BoxUi.ui | 432 ++++++++++++++++++++-------------- src/insets/InsetBox.cpp | 136 ++++++++++- src/insets/InsetBox.h | 7 + src/tex2lyx/text.cpp | 6 + src/version.h | 4 +- 9 files changed, 590 insertions(+), 207 deletions(-) diff --git a/development/FORMAT b/development/FORMAT index a0bf4fa315..058e382b53 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -11,6 +11,14 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx. ----------------------- +2015-05-xx Uwe Stöhr + * Format incremented to 489: support to set line thickness, box separation + and shadow size in the box dialog + New box parameters: + - thickness + - separation + - shadowsize + 2015-04-21 Jürgen Spitzmüller * Format incremented to 488: Rewrite the Glosse insets (Glosse and Tri-Glosse). These insets now do not any longer use PassThru. Instead, they use an optional diff --git a/lib/lyx2lyx/LyX.py b/lib/lyx2lyx/LyX.py index f5e6e4079b..934f995efa 100644 --- a/lib/lyx2lyx/LyX.py +++ b/lib/lyx2lyx/LyX.py @@ -85,7 +85,7 @@ format_relation = [("0_06", [200], minor_versions("0.6" , 4)), ("1_6", list(range(277,346)), minor_versions("1.6" , 10)), ("2_0", list(range(346,414)), minor_versions("2.0" , 8)), ("2_1", list(range(414,475)), minor_versions("2.1" , 0)), - ("2_2", list(range(475,489)), minor_versions("2.2" , 0)) + ("2_2", list(range(475,490)), minor_versions("2.2" , 0)) ] #################################################################### diff --git a/lib/lyx2lyx/lyx_2_2.py b/lib/lyx2lyx/lyx_2_2.py index 68545dd63b..57324ace59 100644 --- a/lib/lyx2lyx/lyx_2_2.py +++ b/lib/lyx2lyx/lyx_2_2.py @@ -956,6 +956,65 @@ def convert_newgloss(document): i = endPlain + 1 +def convert_BoxFeatures(document): + " adds new box features " + + i = 0 + while True: + i = find_token(document.body, "height_special", i) + if i == -1: + return + document.body.insert(i + 1, 'thickness "0.4pt"\nseparation "3pt"\nshadowsize "4pt"\n') + i = i + 1 + + +def revert_BoxFeatures(document): + " deletes new box features " + + i = 0 + defaultSep = "3pt" + defaultThick = "0.4pt" + defaultShadow = "4pt" + while True: + i = find_token(document.body, "height_special", i) + if i == -1: + return + # read out the values + beg = document.body[i+1].find('"'); + end = document.body[i+1].rfind('"'); + thickness = document.body[i+1][beg+1:end]; + beg = document.body[i+2].find('"'); + end = document.body[i+2].rfind('"'); + separation = document.body[i+2][beg+1:end]; + beg = document.body[i+3].find('"'); + end = document.body[i+3].rfind('"'); + shadowsize = document.body[i+3][beg+1:end]; + # delete the specification + del document.body[i+1:i+4] + # output ERT + # first output the closing braces + if shadowsize != defaultShadow or separation != defaultSep or thickness != defaultThick: + document.body[i + 10 : i + 10] = put_cmd_in_ert("}") + # now output the lengths + if shadowsize != defaultShadow or separation != defaultSep or thickness != defaultThick: + document.body[i - 10 : i - 10] = put_cmd_in_ert("{") + if thickness != defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxrule " + thickness] + if separation != defaultSep and thickness == defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxsep " + separation] + if separation != defaultSep and thickness != defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxrule " + thickness + "\\backslash fboxsep " + separation] + if shadowsize != defaultShadow and separation == defaultSep and thickness == defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash shadowsize " + shadowsize] + if shadowsize != defaultShadow and separation != defaultSep and thickness == defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxsep " + separation + "\\backslash shadowsize " + shadowsize] + if shadowsize != defaultShadow and separation == defaultSep and thickness != defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxrule " + thickness + "\\backslash shadowsize " + shadowsize] + if shadowsize != defaultShadow and separation != defaultSep and thickness != defaultThick: + document.body[i - 5 : i - 4] = ["{\\backslash fboxrule " + thickness + "\\backslash fboxsep " + separation + "\\backslash shadowsize " + shadowsize] + i = i + 11 + + ## # Conversion hub # @@ -978,10 +1037,12 @@ convert = [ [485, []], [486, []], [487, []], - [488, [convert_newgloss]] + [488, [convert_newgloss]], + [489, [convert_BoxFeatures]] ] revert = [ + [488, [revert_BoxFeatures]], [487, [revert_newgloss, revert_glossgroup]], [486, [revert_forest]], [485, [revert_ex_itemargs]], diff --git a/src/frontends/qt4/GuiBox.cpp b/src/frontends/qt4/GuiBox.cpp index 86cdf8ee71..c5244d0116 100644 --- a/src/frontends/qt4/GuiBox.cpp +++ b/src/frontends/qt4/GuiBox.cpp @@ -6,6 +6,7 @@ * \author Jürgen Vigna (Minipage stuff) * \author Martin Vermeer * \author Jürgen Spitzmüller + * \author Uwe Stöhr * * Full author contact details are available in file CREDITS. */ @@ -98,13 +99,28 @@ GuiBox::GuiBox(QWidget * parent) : InsetParamsWidget(parent) this, SIGNAL(changed())); connect(halignCO, SIGNAL(activated(int)), this, SIGNAL(changed())); connect(ialignCO, SIGNAL(activated(int)), this, SIGNAL(changed())); + connect(thicknessED, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(thicknessUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), + this, SIGNAL(changed())); + connect(separationED, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(separationUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), + this, SIGNAL(changed())); + connect(shadowsizeED, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(shadowsizeUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), + this, SIGNAL(changed())); heightED->setValidator(unsignedLengthValidator(heightED)); widthED->setValidator(unsignedLengthValidator(widthED)); + thicknessED->setValidator(unsignedLengthValidator(thicknessED)); + separationED->setValidator(unsignedLengthValidator(separationED)); + shadowsizeED->setValidator(unsignedLengthValidator(shadowsizeED)); // initialize the length validator addCheckedWidget(widthED, widthCB); addCheckedWidget(heightED, heightCB); + addCheckedWidget(thicknessED, thicknessLA); + addCheckedWidget(separationED, separationLA); + addCheckedWidget(shadowsizeED, shadowsizeLA); initDialog(); } @@ -142,11 +158,10 @@ void GuiBox::on_typeCO_activated(int index) heightCB->setChecked(false); setSpecial(ibox); } - if (type != "Boxed") { + if (type != "Boxed") if (type != "Frameless") widthCB->setChecked(itype != "none"); pagebreakCB->setChecked(false); - } changed(); } @@ -160,6 +175,15 @@ void GuiBox::initDialog() widthUnitsLC->setCurrentItem(Length::PCW); heightED->setText("1"); heightUnitsLC->setCurrentItem("totalheight"); + // LaTeX's default for \fboxrule is 0.4 pt + thicknessED->setText("0.4"); + thicknessUnitsLC->setCurrentItem(Length::PT); + // LaTeX's default for \fboxsep is 3 pt + separationED->setText("3"); + separationUnitsLC->setCurrentItem(Length::PT); + // LaTeX's default for \shadowsize is 4 pt + shadowsizeED->setText("4"); + shadowsizeUnitsLC->setCurrentItem(Length::PT); } @@ -226,10 +250,14 @@ void GuiBox::paramsToDialog(Inset const * inset) ialignCO->setEnabled(ibox); setSpecial(ibox); - // halign is only allowed without inner box and if a width is used and if - // pagebreak is not used - halignCO->setEnabled(!pagebreakCB->isChecked() && widthCB->isChecked() - && ((!ibox && type == "Boxed") || params.use_makebox)); + // halign is only allowed if a width is used + halignCO->setEnabled(widthCB->isChecked()); + // add the entry "Stretch" if the box is \makebox or \framebox and if not already there + if ((inner_type == "makebox" || (type == "Boxed" && inner_type == "none")) + && halignCO->count() < 4) + halignCO->addItem(toqstr("Stretch")); + else if (inner_type != "makebox" && (type != "Boxed" && inner_type != "none")) + halignCO->removeItem(3); // pagebreak is only allowed for Boxed without inner box pagebreakCB->setEnabled(!ibox && type == "Boxed"); @@ -271,6 +299,24 @@ void GuiBox::paramsToDialog(Inset const * inset) heightCB->setCheckState(Qt::Checked); heightCB->setEnabled(ibox); + + // enable line thickness only for the rectangular frame types and drop shadow + thicknessED->setEnabled(type == "Boxed" || type == "Doublebox" || type == "Shadowbox"); + thicknessUnitsLC->setEnabled(type == "Boxed" || type == "Doublebox" || type == "Shadowbox"); + lengthToWidgets(thicknessED, thicknessUnitsLC, + (params.thickness).asString(), default_unit); + // enable line separation for the allowed frame types + separationED->setEnabled(type == "Boxed" || type == "ovalbox" || type == "Ovalbox" + || type == "Doublebox" || type == "Shadowbox"); + separationUnitsLC->setEnabled(type == "Boxed" || type == "ovalbox" || type == "Ovalbox" + || type == "Doublebox" || type == "Shadowbox"); + lengthToWidgets(separationED, separationUnitsLC, + (params.separation).asString(), default_unit); + // enable shadow size for drop shadow + shadowsizeED->setEnabled(type == "Shadowbox"); + shadowsizeUnitsLC->setEnabled(type == "Shadowbox"); + lengthToWidgets(shadowsizeED, shadowsizeUnitsLC, + (params.shadowsize).asString(), default_unit); } @@ -338,6 +384,21 @@ docstring GuiBox::dialogToParams() const Length(widgetsToLength(heightED, heightUnitsLC)); } } + + // handle the line thickness, line separation and shadow size + if (thicknessED->isEnabled()) + params.thickness = Length(widgetsToLength(thicknessED, thicknessUnitsLC)); + else + params.thickness = Length(); + if (separationED->isEnabled()) + params.separation = Length(widgetsToLength(separationED, separationUnitsLC)); + else + params.separation = Length(); + if (separationED->isEnabled()) + params.shadowsize = Length(widgetsToLength(shadowsizeED, shadowsizeUnitsLC)); + else + params.shadowsize = Length(); + return from_ascii(InsetBox::params2string(params)); } @@ -358,39 +419,79 @@ bool GuiBox::checkWidgets(bool readonly) const heightED->setEnabled(false); heightUnitsLC->setEnabled(false); heightCB->setEnabled(false); + thicknessED->setEnabled(false); + thicknessUnitsLC->setEnabled(false); + separationED->setEnabled(false); + separationUnitsLC->setEnabled(false); + shadowsizeED->setEnabled(false); + shadowsizeUnitsLC->setEnabled(false); } else { QString const outer = typeCO->itemData(typeCO->currentIndex()).toString(); QString const itype = innerBoxCO->itemData(innerBoxCO->currentIndex()).toString(); bool const ibox = (itype != "none" && itype != "makebox"); - // pagebreak is only allowed for Boxed without inner box - pagebreakCB->setEnabled(!ibox && outer == "Boxed"); - innerBoxCO->setEnabled(!pagebreakCB->isChecked()); valignCO->setEnabled(ibox); ialignCO->setEnabled(ibox); - // halign is only allowed without inner box and if a width is used and if - // pagebreak is not used - halignCO->setEnabled(!pagebreakCB->isChecked() && widthCB->isChecked() - && ((!ibox && outer == "Boxed") || itype == "makebox")); + if (heightCB->isChecked() && !ibox) + heightCB->setChecked(false); + heightCB->setEnabled(ibox); // the width can only be selected for makebox or framebox widthCB->setEnabled(itype == "makebox" - || (outer == "Boxed" - && !ibox && !pagebreakCB->isChecked())); - // except for frameless and boxed, the width cannot be specified if + || (outer == "Boxed" && itype == "none") + && !pagebreakCB->isChecked()); + // except for Frameless and Boxed, the width cannot be specified if // there is no inner box bool const width_enabled = ibox || outer == "Frameless" || outer == "Boxed"; - // enable if width_enabled, except if checkbox is active but unset - widthED->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked())); - widthUnitsLC->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked())); + // enable if width_enabled + widthED->setEnabled(width_enabled); + widthUnitsLC->setEnabled(width_enabled); if (!widthCB->isChecked() && widthCB->isEnabled()) { widthED->setEnabled(false); widthUnitsLC->setEnabled(false); } + // halign is only allowed if a width is used + halignCO->setEnabled(widthCB->isChecked()); + // add the entry "Stretch" if the box is \makebox or \framebox and if not already there + if ((itype == "makebox" || (outer == "Boxed" && itype == "none")) + && halignCO->count() < 4) + halignCO->addItem(toqstr("Stretch")); + else if (itype != "makebox" && (outer != "Boxed" && itype != "none")) + halignCO->removeItem(3); + // pagebreak is only allowed for Boxed without inner box + pagebreakCB->setEnabled(!ibox && outer == "Boxed"); + heightED->setEnabled(itype != "none" && heightCB->isChecked()); heightUnitsLC->setEnabled(itype != "none" && heightCB->isChecked()); heightCB->setEnabled(ibox); + + // enable line thickness for the rectangular frame types and drop shadow + thicknessED->setEnabled(outer == "Boxed" || outer == "Doublebox" || outer == "Shadowbox"); + thicknessUnitsLC->setEnabled(outer == "Boxed" || outer == "Doublebox" || outer == "Shadowbox"); + // set default values if empty + if (thicknessED->text().isEmpty() && thicknessED->isEnabled()) { + thicknessED->setText("0.4"); + thicknessUnitsLC->setCurrentItem(Length::PT); + } + // enable line separation for the allowed frame types + separationED->setEnabled(outer == "Boxed" || outer == "ovalbox" || outer == "Ovalbox" + || outer == "Doublebox" || outer == "Shadowbox"); + separationUnitsLC->setEnabled(outer == "Boxed" || outer == "ovalbox" || outer == "Ovalbox" + || outer == "Doublebox" || outer == "Shadowbox"); + // set default values if empty + if (separationED->text().isEmpty() && separationED->isEnabled()) { + separationED->setText("3"); + separationUnitsLC->setCurrentItem(Length::PT); + } + // enable shadow size for drop shadow + shadowsizeED->setEnabled(outer == "Shadowbox"); + shadowsizeUnitsLC->setEnabled(outer == "Shadowbox"); + // set default values if empty + if (shadowsizeED->text().isEmpty() && shadowsizeED->isEnabled()) { + shadowsizeED->setText("4"); + shadowsizeUnitsLC->setCurrentItem(Length::PT); + } } return InsetParamsWidget::checkWidgets(); diff --git a/src/frontends/qt4/ui/BoxUi.ui b/src/frontends/qt4/ui/BoxUi.ui index 982b0776e9..bd530c23e3 100644 --- a/src/frontends/qt4/ui/BoxUi.ui +++ b/src/frontends/qt4/ui/BoxUi.ui @@ -6,8 +6,8 @@ 0 0 - 261 - 245 + 262 + 411 @@ -16,40 +16,137 @@ true - - - 9 - - - 6 - - - - - Check this if the box should break across pages + + + + + Type and size - - Allow &page breaks + + true + + + + + + + + Inner Bo&x: + + + innerBoxCO + + + + + + + + + + &Width: + + + false + + + false + + + + + + + Width value + + + + + + + + + + + + + &Height: + + + false + + + false + + + + + + + false + + + Height value + + + + + + + false + + + + + + + Check this if the box should break across pages + + + Allow &page breaks + + + + + + + Inner box -- needed for fixed width & line breaks + + + + None + + + + + Parbox + + + + + Minipage + + + + + - - + + Alignment true - - - 9 - - - 6 - + + + true + 0 @@ -74,15 +171,58 @@ Right + + + + + + Vertical alignment of the content inside the box + + + Vertical + + + + + + + Horizontal alignment of the content inside the box + + + Horizontal + + + + + + + true + + + Vertical alignment of the box (with regard to baseline) + - Stretch + Top + + + + + Middle + + + + + Bottom + + true + 0 @@ -114,26 +254,14 @@ - - - - Vertical alignment of the box (with regard to baseline) + + + + Co&ntent: + + + ialignCO - - - Top - - - - - Middle - - - - - Bottom - - @@ -149,153 +277,113 @@ - - + + + + + + + Decoration + + + true + + + + + + + - Co&ntent: + &Decoration: - ialignCO + typeCO - - + + - Vertical alignment of the content inside the box + Supported box types + + + + - Vertical + Line thickness: - - + + + + false + - Horizontal alignment of the content inside the box + Width value + + + + + + false + + + + + - Horizontal + Box separation: + + + + + + + false + + + Width value + + + + + + + false + + + + + + + Shadow size: + + + + + + + false + + + Width value + + + + + + + false - - - - false - - - - - - - - - - &Height: - - - false - - - false - - - - - - - - - - Inner Bo&x: - - - innerBoxCO - - - - - - - - - - - - - &Decoration: - - - typeCO - - - - - - - - - - &Width: - - - false - - - false - - - - - - - false - - - Height value - - - - - - - Width value - - - - - - - Inner box -- needed for fixed width & line breaks - - - - None - - - - - Parbox - - - - - Minipage - - - - - - - - Supported box types - - - @@ -308,11 +396,7 @@ typeCO innerBoxCO - widthED - widthUnitsLC heightCB - heightED - heightUnitsLC ialignCO halignCO valignCO diff --git a/src/insets/InsetBox.cpp b/src/insets/InsetBox.cpp index ddb1dce1dd..011df87327 100644 --- a/src/insets/InsetBox.cpp +++ b/src/insets/InsetBox.cpp @@ -6,6 +6,7 @@ * \author Angus Leeming * \author Martin Vermeer * \author Jürgen Spitzmüller + * \author Uwe Stöhr * * Full author contact details are available in file CREDITS. */ @@ -272,20 +273,36 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const BoxType btype = boxtranslator().find(params_.type); string width_string = params_.width.asLatexString(); + string thickness_string = params_.thickness.asLatexString(); + string defaultThick = "0.4pt"; + string separation_string = params_.separation.asLatexString(); + string defaultSep = "3pt"; + string shadowsize_string = params_.shadowsize.asLatexString(); + string defaultShadow = "4pt"; bool stdwidth = false; - // FIXME: do not test explicitely values of width_string - if (params_.inner_box && - (width_string.find("1.0\\columnwidth") != string::npos - || width_string.find("1.0\\textwidth") != string::npos)) { + // in general the overall width of some decorated boxes is wider thean the inner box + // we could therefore calculate the real width for all sizes so that if the user wants + // e.g. 0.1\columnwidth or 2cm he gets exactly this size + // however this makes problems when importing TeX code + // therefore only recalculate for the most common case that the box should not protrude + // the page margins + if (params_.inner_box + && ((width_string.find("1\\columnwidth") != string::npos + || width_string.find("1\\textwidth") != string::npos) + || width_string.find("1\\paperwidth") != string::npos + || width_string.find("1\\linewidth") != string::npos)) { stdwidth = true; switch (btype) { case Frameless: + break; case Framed: + width_string += " - 2\\FrameSep - 2\\FrameRule"; break; case Boxed: - case Shaded: width_string += " - 2\\fboxsep - 2\\fboxrule"; break; + case Shaded: + break; case ovalbox: width_string += " - 2\\fboxsep - 0.8pt"; break; @@ -293,8 +310,7 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const width_string += " - 2\\fboxsep - 1.6pt"; break; case Shadowbox: - // Shadow falls outside right margin... opinions? - width_string += " - 2\\fboxsep - 2\\fboxrule"/* "-\\shadowsize"*/; + width_string += " - 2\\fboxsep - 2\\fboxrule - \\shadowsize"; break; case Doublebox: width_string += " - 2\\fboxsep - 7.5\\fboxrule - 1pt"; @@ -306,17 +322,34 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const if (runparams.lastid != -1) os.texrow().start(runparams.lastid, runparams.lastpos); - // Adapt to column/text width correctly also if paragraphs indented: - if (stdwidth) + // adapt column/text width correctly also if paragraphs indented + if (stdwidth && !(buffer().params().paragraph_separation)) os << "\\noindent"; switch (btype) { case Frameless: break; case Framed: + if (!(thickness_string.find(defaultThick) != string::npos)) { + os << "{\\FrameRule " << from_ascii(thickness_string); + if (!(separation_string.find(defaultSep) != string::npos)) + os << "\\FrameSep " << from_ascii(separation_string); + } + if (!(separation_string.find(defaultSep) != string::npos) + && (thickness_string.find(defaultThick) != string::npos)) + os << "{\\FrameSep " << from_ascii(separation_string); + os << "\\begin{framed}%\n"; break; case Boxed: + if (!(thickness_string.find(defaultThick) != string::npos)) { + os << "{\\fboxrule " << from_ascii(thickness_string); + if (!(separation_string.find(defaultSep) != string::npos)) + os << "\\fboxsep " << from_ascii(separation_string); + } + if (!(separation_string.find(defaultSep) != string::npos) + && (thickness_string.find(defaultThick) != string::npos)) + os << "{\\fboxsep " << from_ascii(separation_string); if (!width_string.empty()) { if (!params_.inner_box) { os << "\\framebox"; @@ -338,12 +371,37 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const os << "{"; break; case ovalbox: + if (!separation_string.empty() && separation_string.find(defaultSep) == string::npos) + os << "{\\fboxsep " << from_ascii(separation_string); os << "\\ovalbox{"; break; case Ovalbox: + if (!separation_string.empty() && separation_string.find(defaultSep) == string::npos) + os << "{\\fboxsep " << from_ascii(separation_string); os << "\\Ovalbox{"; break; case Shadowbox: + if (!(thickness_string.find(defaultThick) != string::npos)) { + os << "{\\fboxrule " << from_ascii(thickness_string); + if (!(separation_string.find(defaultSep) != string::npos)) { + os << "\\fboxsep " << from_ascii(separation_string); + if (!(shadowsize_string.find(defaultShadow) != string::npos)) + os << "\\shadowsize " << from_ascii(shadowsize_string); + } + if (!(shadowsize_string.find(defaultShadow) != string::npos) + && (separation_string.find(defaultSep) != string::npos)) + os << "\\shadowsize " << from_ascii(shadowsize_string); + } + if (!(separation_string.find(defaultSep) != string::npos) + && (thickness_string.find(defaultThick) != string::npos)) { + os << "{\\fboxsep " << from_ascii(separation_string); + if (!(shadowsize_string.find(defaultShadow) != string::npos)) + os << "\\shadowsize " << from_ascii(shadowsize_string); + } + if (!(shadowsize_string.find(defaultShadow) != string::npos) + && (separation_string.find(defaultSep) != string::npos) + && (thickness_string.find(defaultThick) != string::npos)) + os << "{\\shadowsize " << from_ascii(shadowsize_string); os << "\\shadowbox{"; break; case Shaded: @@ -351,6 +409,14 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const // it is inside a minipage or parbox break; case Doublebox: + if (!(thickness_string.find(defaultThick) != string::npos)) { + os << "{\\fboxrule " << from_ascii(thickness_string); + if (!(separation_string.find(defaultSep) != string::npos)) + os << "\\fboxsep " << from_ascii(separation_string); + } + if (!(separation_string.find(defaultSep) != string::npos) + && (thickness_string.find(defaultThick) != string::npos)) + os << "{\\fboxsep " << from_ascii(separation_string); os << "\\doublebox{"; break; } @@ -414,6 +480,23 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const os << "\\begin{shaded}%\n"; } + // \framebox and \makebox handle hor_pos their own way + // hor_pos is senseless for \mbox and \fbox + if (!(params_.use_makebox) + && !(btype == Boxed && !params_.inner_box)) { + switch (params_.hor_pos) { + case 'l': + // do nothing because this is LaTeX's default + break; + case 'c': + os << "\\centering "; + break; + case 'r': + os << "\\raggedleft "; + break; + } + } + InsetText::latex(os, runparams); if (btype == Shaded) @@ -431,15 +514,38 @@ void InsetBox::latex(otexstream & os, OutputParams const & runparams) const break; case Framed: os << "\\end{framed}"; + if (!(separation_string.find(defaultSep) != string::npos) + || !(thickness_string.find(defaultThick) != string::npos)) + os << "}"; break; case Boxed: os << "}"; + if (!(separation_string.find(defaultSep) != string::npos) + || !(thickness_string.find(defaultThick) != string::npos)) + os << "}"; break; case ovalbox: + os << "}"; + if (!(separation_string.find(defaultSep) != string::npos)) + os << "}"; + break; case Ovalbox: + os << "}"; + if (!(separation_string.find(defaultSep) != string::npos)) + os << "}"; + break; case Doublebox: + os << "}"; + if (!(separation_string.find(defaultSep) != string::npos) + || !(thickness_string.find(defaultThick) != string::npos)) + os << "}"; + break; case Shadowbox: os << "}"; + if (!(separation_string.find(defaultSep) != string::npos) + || !(thickness_string.find(defaultThick) != string::npos) + || !(shadowsize_string.find(defaultShadow) != string::npos)) + os << "}"; break; case Shaded: // already done @@ -548,6 +654,7 @@ void InsetBox::validate(LaTeXFeatures & features) const case Frameless: break; case Framed: + features.require("calc"); features.require("framed"); break; case Boxed: @@ -632,7 +739,10 @@ InsetBoxParams::InsetBoxParams(string const & label) hor_pos('c'), inner_pos('t'), height(Length("1in")), - height_special("totalheight") // default is 1\\totalheight + height_special("totalheight"), // default is 1\\totalheight + thickness(Length("0.4pt")), + separation(Length("3pt")), + shadowsize(Length("4pt")) {} @@ -649,6 +759,9 @@ void InsetBoxParams::write(ostream & os) const os << "special \"" << special << "\"\n"; os << "height \"" << height.asString() << "\"\n"; os << "height_special \"" << height_special << "\"\n"; + os << "thickness \"" << thickness.asString() << "\"\n"; + os << "separation \"" << separation.asString() << "\"\n"; + os << "shadowsize \"" << shadowsize.asString() << "\"\n"; } @@ -668,6 +781,9 @@ void InsetBoxParams::read(Lexer & lex) lex >> "special" >> special; lex >> "height" >> height; lex >> "height_special" >> height_special; + lex >> "thickness" >> thickness; + lex >> "separation" >> separation; + lex >> "shadowsize" >> shadowsize; } diff --git a/src/insets/InsetBox.h b/src/insets/InsetBox.h index 76b11f63df..e8ea613efd 100644 --- a/src/insets/InsetBox.h +++ b/src/insets/InsetBox.h @@ -6,6 +6,7 @@ * * \author Angus Leeming * \author Martin Vermeer + * \author Uwe Stöhr * * Full author contact details are available in file CREDITS. */ @@ -52,6 +53,12 @@ public: Length height; /// std::string height_special; + /// + Length thickness; + /// + Length separation; + /// + Length shadowsize; }; diff --git a/src/tex2lyx/text.cpp b/src/tex2lyx/text.cpp index 33c389ba5f..88ec91db8b 100644 --- a/src/tex2lyx/text.cpp +++ b/src/tex2lyx/text.cpp @@ -847,6 +847,9 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags, string width_unit; string latex_width; string width_special = "none"; + string thickness = "0.4pt"; + string separation = "3pt"; + string shadowsize = "4pt"; if (!inner_type.empty() && p.hasOpt()) { if (inner_type != "makebox") position = p.getArg('[', ']'); @@ -1071,6 +1074,9 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags, os << "special \"" << width_special << "\"\n"; os << "height \"" << height_value << height_unit << "\"\n"; os << "height_special \"" << height_special << "\"\n"; + os << "thickness \"" << thickness << "\"\n"; + os << "separation \"" << separation << "\"\n"; + os << "shadowsize \"" << shadowsize << "\"\n"; os << "status open\n\n"; // Unfortunately we can't use parse_text_in_inset: diff --git a/src/version.h b/src/version.h index e52d96babe..8407528cc9 100644 --- a/src/version.h +++ b/src/version.h @@ -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 488 // spitz: rework the Glosse insets -#define LYX_FORMAT_TEX2LYX 488 +#define LYX_FORMAT_LYX 489 // uwestoehr: new box features +#define LYX_FORMAT_TEX2LYX 489 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #ifndef _MSC_VER -- 2.39.2