On Fri, Sep 14, 2007 at 03:36:10PM +0200, Helge Hafting wrote: > Martin Vermeer wrote:
... > >I am not entirely happy with this patch. It works allright, but... > > > I tested this. Mostly fine, but a few small problems: > > Using "unit" gives two math boxes. One for the numer and one > for the unit itself. This typesets very nice as \unit[45]{m} for example. > > "\unitfrac" supports a similiar optional argument for the number, but > that capability is not used in lyx. So we can now write > $35\unitfrac{km}{h}$ > but not > $\unitfrac[35]{km}{h}$ > The latter looks better, with better spacing. One can insert > the missing space explicitly, and get $35\,\unitfrac{km}{h} > which looks the same in the dvi. The attached supports now all these alternatives. As a bonus, we have now the option of varying numbers of cells. Also cursor motion should now be OK. I will commit this if I don't hear an outcry. Suggestions for better toolbar pop-up texts are especially welcome. The current implementation is a bit arbitrary in the sense that now InsetMathFrac combines a large number of fraction-like things, but outside it are still tfrac, dfrac and binomial. > Finally, is the fraction toolbar menu the right place for "unit", or does > this thing fit better in the font menu beside it? Not really... it's not a font thing either. At least the current solution is LaTeX-like, because also the units package is built on top of nicefrac. - Martin
Index: src/mathed/InsetMathFrac.h =================================================================== --- src/mathed/InsetMathFrac.h (revision 20236) +++ src/mathed/InsetMathFrac.h (working copy) @@ -28,12 +28,18 @@ OVER, ATOP, NICEFRAC, - UNITFRAC + UNITFRAC, + UNIT, + UNITFRAC3 }; /// - explicit InsetMathFrac(Kind kind = FRAC); + explicit InsetMathFrac(Kind kind = FRAC, idx_type ncells = 2); /// + bool idxRight(Cursor &) const; + /// + bool idxLeft(Cursor &) const; + /// bool metrics(MetricsInfo & mi, Dimension & dim) const; /// void draw(PainterInfo &, int x, int y) const; Index: src/mathed/MathFactory.cpp =================================================================== --- src/mathed/MathFactory.cpp (revision 20236) +++ src/mathed/MathFactory.cpp (working copy) @@ -260,7 +260,7 @@ MathAtom createInsetMath(docstring const & s) { - //lyxerr << "creating inset with name: '" << s << '\'' << endl; + //lyxerr << "creating inset with name: '" << to_utf8(s) << '\'' << endl; latexkeys const * l = in_word_set(s); if (l) { docstring const & inset = l->inset; @@ -372,6 +372,10 @@ return MathAtom(new InsetMathFrac(InsetMathFrac::NICEFRAC)); if (s == "unitfrac") return MathAtom(new InsetMathFrac(InsetMathFrac::UNITFRAC)); + if (s == "unitfracthree") + return MathAtom(new InsetMathFrac(InsetMathFrac::UNITFRAC3, 3)); + if (s == "unit") + return MathAtom(new InsetMathFrac(InsetMathFrac::UNIT)); //if (s == "infer") // return MathAtom(new MathInferInset); if (s == "atop") Index: src/mathed/InsetMathFracBase.h =================================================================== --- src/mathed/InsetMathFracBase.h (revision 20235) +++ src/mathed/InsetMathFracBase.h (working copy) @@ -21,7 +21,7 @@ class InsetMathFracBase : public InsetMathNest { public: /// - InsetMathFracBase(); + explicit InsetMathFracBase(idx_type ncells = 2); /// bool idxUpDown(Cursor &, bool up) const; /// Index: src/mathed/InsetMathFracBase.cpp =================================================================== --- src/mathed/InsetMathFracBase.cpp (revision 20235) +++ src/mathed/InsetMathFracBase.cpp (working copy) @@ -18,8 +18,8 @@ namespace lyx { -InsetMathFracBase::InsetMathFracBase() - : InsetMathNest(2) +InsetMathFracBase::InsetMathFracBase(idx_type ncells) + : InsetMathNest(ncells) {} Index: src/mathed/InsetMathFrac.cpp =================================================================== --- src/mathed/InsetMathFrac.cpp (revision 20236) +++ src/mathed/InsetMathFrac.cpp (working copy) @@ -17,13 +17,14 @@ #include "TextPainter.h" #include "LaTeXFeatures.h" #include "Color.h" +#include "Cursor.h" #include "frontends/Painter.h" namespace lyx { -InsetMathFrac::InsetMathFrac(Kind kind) - : kind_(kind) +InsetMathFrac::InsetMathFrac(Kind kind, InsetMath::idx_type ncells) + : InsetMathFracBase(ncells), kind_(kind) {} @@ -45,24 +46,76 @@ } +bool InsetMathFrac::idxRight(Cursor & cur) const +{ + InsetMath::idx_type target; + if (kind_ == UNITFRAC3) + target = 0; + else if (kind_ == UNIT) + target = 1; + else + return false; + if (cur.idx() == target) + return false; + cur.idx() = target; + cur.pos() = cell(target).x2pos(cur.x_target()); + return true; +} + + +bool InsetMathFrac::idxLeft(Cursor & cur) const +{ + InsetMath::idx_type target; + if (kind_ == UNITFRAC3) + target = 2; + else if (kind_ == UNIT) + target = 0; + else + return false; + if (cur.idx() == target) + return false; + cur.idx() = target; + cur.pos() = cell(target).x2pos(cur.x_target()); + return true; +} + + bool InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const { - FracChanger dummy(mi.base); - cell(0).metrics(mi); - cell(1).metrics(mi); - if (kind_ == NICEFRAC) { + if (kind_ == UNIT) { + cell(0).metrics(mi); + ShapeChanger dummy2(mi.base.font, Font::UP_SHAPE); + cell(1).metrics(mi); dim.wid = cell(0).width() + cell(1).width() + 5; - dim.asc = cell(0).height() + 5; - dim.des = cell(1).height() - 5; - } else if (kind_ == UNITFRAC) { + dim.asc = std::max(cell(0).ascent(), cell(1).ascent()); + dim.des = std::max(cell(0).descent(), cell(1).descent()); + } else if (kind_ == UNITFRAC3) { + cell(2).metrics(mi); ShapeChanger dummy2(mi.base.font, Font::UP_SHAPE); - dim.wid = cell(0).width() + cell(1).width() + 5; - dim.asc = cell(0).height() + 5; - dim.des = cell(1).height() - 5; + FracChanger dummy(mi.base); + cell(0).metrics(mi); + cell(1).metrics(mi); + dim.wid = cell(0).width() + cell(1).width() + cell(2).width() + 10; + dim.asc = std::max(cell(2).ascent(), cell(0).height() + 5); + dim.des = std::max(cell(2).descent(), cell(1).height() - 5); } else { - dim.wid = std::max(cell(0).width(), cell(1).width()) + 2; - dim.asc = cell(0).height() + 2 + 5; - dim.des = cell(1).height() + 2 - 5; + FracChanger dummy(mi.base); + cell(0).metrics(mi); + cell(1).metrics(mi); + if (kind_ == NICEFRAC) { + dim.wid = cell(0).width() + cell(1).width() + 5; + dim.asc = cell(0).height() + 5; + dim.des = cell(1).height() - 5; + } else if (kind_ == UNITFRAC) { + ShapeChanger dummy2(mi.base.font, Font::UP_SHAPE); + dim.wid = cell(0).width() + cell(1).width() + 5; + dim.asc = cell(0).height() + 5; + dim.des = cell(1).height() - 5; + } else { + dim.wid = std::max(cell(0).width(), cell(1).width()) + 2; + dim.asc = cell(0).height() + 2 + 5; + dim.des = cell(1).height() + 2 - 5; + } } metricsMarkers(dim); if (dim_ == dim) @@ -76,28 +129,48 @@ { setPosCache(pi, x, y); int m = x + dim_.wid / 2; - FracChanger dummy(pi.base); - if (kind_ == NICEFRAC) { - cell(0).draw(pi, x + 2, - y - cell(0).descent() - 5); - cell(1).draw(pi, x + cell(0).width() + 5, - y + cell(1).ascent() / 2); - } else if (kind_ == UNITFRAC) { + if (kind_ == UNIT) { + cell(0).draw(pi, x + 1, y); ShapeChanger dummy2(pi.base.font, Font::UP_SHAPE); - cell(0).draw(pi, x + 2, - y - cell(0).descent() - 5); - cell(1).draw(pi, x + cell(0).width() + 5, - y + cell(1).ascent() / 2); + cell(1).draw(pi, x + cell(0).width() + 5, y); + } else if (kind_ == UNITFRAC3) { + cell(2).draw(pi, x + 1, y); + ShapeChanger dummy2(pi.base.font, Font::UP_SHAPE); + FracChanger dummy(pi.base); + int xx = x + cell(2).width() + 5; + cell(0).draw(pi, xx + 2, + y - cell(0).descent() - 5); + cell(1).draw(pi, xx + cell(0).width() + 5, + y + cell(1).ascent() / 2); } else { - cell(0).draw(pi, m - cell(0).width() / 2, - y - cell(0).descent() - 2 - 5); - cell(1).draw(pi, m - cell(1).width() / 2, - y + cell(1).ascent() + 2 - 5); + FracChanger dummy(pi.base); + if (kind_ == NICEFRAC) { + cell(0).draw(pi, x + 2, + y - cell(0).descent() - 5); + cell(1).draw(pi, x + cell(0).width() + 5, + y + cell(1).ascent() / 2); + } else if (kind_ == UNITFRAC) { + ShapeChanger dummy2(pi.base.font, Font::UP_SHAPE); + cell(0).draw(pi, x + 2, + y - cell(0).descent() - 5); + cell(1).draw(pi, x + cell(0).width() + 5, + y + cell(1).ascent() / 2); + } else { + // Classical fraction + cell(0).draw(pi, m - cell(0).width() / 2, + y - cell(0).descent() - 2 - 5); + cell(1).draw(pi, m - cell(1).width() / 2, + y + cell(1).ascent() + 2 - 5); + } } - if (kind_ == NICEFRAC || kind_ == UNITFRAC) { - pi.pain.line(x + cell(0).width(), + if (kind_ == NICEFRAC || kind_ == UNITFRAC || kind_ == UNITFRAC3) { + // Diag line: + int xx = x; + if (kind_ == UNITFRAC3) + xx += cell(2).width() + 5; + pi.pain.line(xx + cell(0).width(), y + dim_.des - 2, - x + cell(0).width() + 5, + xx + cell(0).width() + 5, y - dim_.asc + 2, Color::math); } if (kind_ == FRAC || kind_ == OVER) @@ -144,6 +217,12 @@ case UNITFRAC: InsetMathNest::write(os); break; + case UNIT: + os << "\\unit[" << cell(0) << "]{" << cell(1) << '}'; + break; + case UNITFRAC3: + os << "\\unitfrac[" << cell(0) << "]{" << cell(1) << "}{" << cell(2) << '}'; + break; } } @@ -159,6 +238,10 @@ return from_ascii("nicefrac"); case UNITFRAC: return from_ascii("unitfrac"); + case UNITFRAC3: + return from_ascii("unitfracthree"); + case UNIT: + return from_ascii("unit"); case ATOP: return from_ascii("atop"); } @@ -199,7 +282,8 @@ void InsetMathFrac::validate(LaTeXFeatures & features) const { - if (kind_ == NICEFRAC || kind_ == UNITFRAC) + if (kind_ == NICEFRAC || kind_ == UNITFRAC + || kind_ == UNIT || kind_ == UNITFRAC3) features.require("units"); InsetMathNest::validate(features); } Index: lib/ui/stdtoolbars.inc =================================================================== --- lib/ui/stdtoolbars.inc (revision 20236) +++ lib/ui/stdtoolbars.inc (working copy) @@ -274,7 +274,9 @@ Item "Standard \\frac" "math-insert \frac" Item "No hor. line \\atop" "math-insert \atop" Item "Nice (3/4) \\nicefrac" "math-insert \nicefrac" + Item "Unit (864 m) \\unit" "math-insert \unit" Item "Units (km/h) \\unitfrac" "math-insert \unitfrac" + Item "Units3 ( 20 km/h) \\unitfrac3" "math-insert \unitfracthree" Item "Text frac (amsmath) \\tfrac" "math-insert \tfrac" Item "Display frac (amsmath) \\dfrac" "math-insert \dfrac" Item "Binomial \\choose" "math-insert \choose"