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"

Reply via email to