]> git.lyx.org Git - features.git/commitdiff
Linearize macros in box edit mode too.
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Wed, 8 Feb 2017 15:42:14 +0000 (16:42 +0100)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 23 Mar 2017 09:17:07 +0000 (10:17 +0100)
The special mode used by macros where the macro name is displayed as
grey text in a box is now one of the possible marker types for any
inset. The new code puts the macro name below the text, which means
that only the text below the current line will be moved. This makes
edition much more comfortable. The grey border around the contents has
been removed too.

The marker_type enum has been moved from Inset to InsetMath. A
markerMargin() function returns the horizontal margin required on each
side for the marker. Only the corner-type markers MARKER and MARKER2
need some.

A new BOX_MARKER enum value has been added and is taken care of in
afterMetricsMarkers (renamed from metricsMarkerVertical) and
drawMarkers.

The InsetMath::marker() macro now takes a BufferView pointer as
argument, so that the marker type can depend on editing state.

MathRow::metrics now makes changes to the MathRow object when needed.

The specific metrics/draw code in MathMacro has been removed and
replaced by assertions. Code in addToMathRow and marker is adapted to
reflect the cases where linearization is possible.

12 files changed:
src/insets/Inset.h
src/mathed/CommandInset.h
src/mathed/InsetMath.cpp
src/mathed/InsetMath.h
src/mathed/InsetMathBox.h
src/mathed/InsetMathDelim.h
src/mathed/InsetMathFrac.h
src/mathed/MathData.cpp
src/mathed/MathMacro.cpp
src/mathed/MathMacro.h
src/mathed/MathRow.cpp
src/mathed/MathRow.h

index b8fd6377d73f836f15994ebab7a91d58c45e775e..5d7f27f89ff4655732856731197f85874fa61f16 100644 (file)
@@ -201,8 +201,6 @@ public:
        ///
        virtual bool showInsetDialog(BufferView *) const;
 
-       // The possible marker types for insets
-       enum marker_type { NO_MARKER, MARKER2, MARKER };
        /// draw two angular markers
        void drawMarkers(PainterInfo & pi, int x, int y) const;
        /// draw four angular markers
index 68d0d13c5331612ba6daa644d5563c70a43aac00..b820d726021a221c53ae0f58cd3a64a98067254e 100644 (file)
@@ -28,7 +28,7 @@ public:
        explicit CommandInset(Buffer * buf, docstring const & name,
                bool needs_math_mode = true);
        ///
-       marker_type marker() const { return NO_MARKER; }
+       marker_type marker(BufferView const *) const { return NO_MARKER; }
        ///
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
index e3b46b9e5caa484c9613e27ff992af3d85d8d036..441cc7cfd556aac438f725529d73cabe2c8c12a4 100644 (file)
@@ -58,7 +58,7 @@ MathClass InsetMath::mathClass() const
 }
 
 
-InsetMath::marker_type InsetMath::marker() const
+InsetMath::marker_type InsetMath::marker(BufferView const *) const
 {
        return nargs() > 0 ? MARKER : NO_MARKER;
 }
@@ -68,7 +68,7 @@ bool InsetMath::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
 {
        MathRow::Element e(mi, MathRow::INSET, mathClass());
        e.inset = this;
-       e.marker = mi.base.macro_nesting ? NO_MARKER : marker();
+       e.marker = mi.base.macro_nesting ? NO_MARKER : marker(mi.base.bv);
        mrow.push_back(e);
        return true;
 }
index 2fc4c1ddf6b1a3129b92119d711f7d584fd9f06d..81cad09b486fd692b2643064b77273760de46d45 100644 (file)
@@ -114,8 +114,10 @@ public:
        /// this is overridden by specific insets
        virtual mode_type currentMode() const { return MATH_MODE; }
 
+       // The possible marker types for math insets
+       enum marker_type { NO_MARKER, MARKER2, MARKER, BOX_MARKER };
        /// this is overridden by insets with specific edit marker type
-       virtual marker_type marker() const;
+       virtual marker_type marker(BufferView const *) const;
 
        /// the ascent of the inset above the baseline
        /// compute the size of the object for text based drawing
index e898a35920165125b3820795c23a05e19ae85e20..af166c19c71b5cf75df874a2d8cb8be522393e05 100644 (file)
@@ -58,7 +58,7 @@ public:
        ///
        mode_type currentMode() const { return TEXT_MODE; }
        ///
-       marker_type marker() const { return NO_MARKER; }
+       marker_type marker(BufferView const *) const { return NO_MARKER; }
        ///
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
@@ -118,7 +118,7 @@ public:
        ///
        InsetMathBoxed(Buffer * buf);
        ///
-       marker_type marker() const { return NO_MARKER; }
+       marker_type marker(BufferView const *) const { return NO_MARKER; }
        ///
        void validate(LaTeXFeatures & features) const;
        ///
index bc49ce3c592c4ba7575d60e7ace6f89b0231cba1..69242d50a7e66b1d8aa5c48b6c2fc5123a22a6b5 100644 (file)
@@ -33,7 +33,7 @@ public:
        ///
        MathClass mathClass() const { return MC_INNER; }
        ///
-       marker_type marker() const { return NO_MARKER; }
+       marker_type marker(BufferView const *) const { return NO_MARKER; }
        /// is it (...)?
        bool isParenthesis() const;
        /// is it [...]?
index b43180c41639405bae1732f944301da37db0b240..f82f3b43cd09ea7ff47bb0d1f2263975b1d3f4b9 100644 (file)
@@ -125,7 +125,7 @@ public:
        /// Generalized fractions are of inner class (see The TeXbook, p.292)
        MathClass mathClass() const { return MC_INNER; }
        ///
-       marker_type marker() const { return MARKER2; }
+       marker_type marker(BufferView const *) const { return MARKER2; }
        ///
        void metrics(MetricsInfo & mi, Dimension & dim) const;
        ///
index 60ef524b0eb4b886f8c35e16bdc32bb069c892d2..d6522ab3a35ae38a6974ae0f554c24fdfb3f51fc 100644 (file)
@@ -277,8 +277,8 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim) const
        sshift_ = xascent / 4;
 
        MathRow mrow(mi, this);
-       mrow_cache_[mi.base.bv] = mrow;
        mrow.metrics(mi, dim);
+       mrow_cache_[mi.base.bv] = mrow;
        kerning_ = mrow.kerning(mi.base.bv);
 
        // Cache the dimension.
index e71b2881d0f88c0c8dfd49493a6ed579fe5c81ab..8f16e2b696a986f8a286e70c1ea2cff061da6f57 100644 (file)
@@ -67,7 +67,7 @@ public:
        ///
        MathMacro const * owner() { return mathMacro_; }
        ///
-       marker_type marker() const { return NO_MARKER; }
+       marker_type marker(BufferView const *) const { return NO_MARKER; }
        ///
        InsetCode lyxCode() const { return ARGUMENT_PROXY_CODE; }
        /// The math data to use for display
@@ -331,7 +331,7 @@ bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
        // - editing with parameter list
        // - editing with box around macro
        if (displayMode() != MathMacro::DISPLAY_NORMAL
-               || (d->editing_[mi.base.bv] && lyxrc.macro_edit_style != LyXRC::MACRO_EDIT_INLINE))
+               || (d->editing_[mi.base.bv] && lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_LIST))
                return InsetMath::addToMathRow(mrow, mi);
 
        /// The macro nesting can change display of insets. Change it locally.
@@ -339,7 +339,7 @@ bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
 
        MathRow::Element e_beg(mi, MathRow::BEGIN);
        e_beg.inset = this;
-       e_beg.marker = (d->nesting_ == 1 && nargs()) ? marker() : NO_MARKER;
+       e_beg.marker = (d->nesting_ == 1) ? marker(mi.base.bv) : NO_MARKER;
        mrow.push_back(e_beg);
 
        d->macro_->lock();
@@ -358,6 +358,7 @@ bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
 
        MathRow::Element e_end(mi, MathRow::END);
        e_end.inset = this;
+       e_end.marker = (d->nesting_ == 1) ? marker(mi.base.bv) : NO_MARKER;
        mrow.push_back(e_end);
 
        return has_contents;
@@ -485,24 +486,29 @@ bool MathMacro::editMetrics(BufferView const * bv) const
 }
 
 
-Inset::marker_type MathMacro::marker() const
+InsetMath::marker_type MathMacro::marker(BufferView const * bv) const
 {
+       if (nargs() == 0)
+               return NO_MARKER;
+
        switch (d->displayMode_) {
        case DISPLAY_INIT:
        case DISPLAY_INTERACTIVE_INIT:
                return NO_MARKER;
        case DISPLAY_UNFOLDED:
                return MARKER;
-       default:
+       case DISPLAY_NORMAL:
                switch (lyxrc.macro_edit_style) {
+               case LyXRC::MACRO_EDIT_INLINE:
+                       return MARKER;
+               case LyXRC::MACRO_EDIT_INLINE_BOX:
+                       return d->editing_[bv] ? BOX_MARKER : NO_MARKER;
                case LyXRC::MACRO_EDIT_LIST:
                        return MARKER2;
-               case LyXRC::MACRO_EDIT_INLINE_BOX:
-                       return NO_MARKER;
-               default:
-                       return MARKER;
                }
        }
+       // please gcc 4.6
+       return NO_MARKER;
 }
 
 
@@ -566,38 +572,8 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
                dim.des += 1;
                dim.wid += 2;
        } else {
-               LBUFERR(d->macro_);
-
-               // calculate metrics, hoping that all cells are seen
-               d->macro_->lock();
-               d->expanded_.metrics(mi, dim);
-
-               // otherwise do a manual metrics call
-               CoordCache & coords = mi.base.bv->coordCache();
-               for (idx_type i = 0; i < nargs(); ++i) {
-                       if (!coords.getArrays().hasDim(&cell(i))) {
-                               Dimension tdim;
-                               cell(i).metrics(mi, tdim);
-                       }
-               }
-               d->macro_->unlock();
-
-               // calculate dimension with label while editing
-               if (lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX
-                   && d->editing_[mi.base.bv]) {
-                       FontInfo font;
-                       font.setSize(FONT_SIZE_TINY);
-                       Dimension namedim;
-                       mathed_string_dim(font, name(), namedim);
-#if 0
-                       dim.wid += 2 + namedim.wid + 2 + 2;
-                       dim.asc = max(dim.asc, namedim.asc) + 2;
-                       dim.des = max(dim.des, namedim.des) + 2;
-#endif
-                       dim.wid = max(1 + namedim.wid + 1, 2 + dim.wid + 2);
-                       dim.asc += 1 + namedim.height() + 1;
-                       dim.des += 2;
-               }
+               // We should not be here, since the macro is linearized in this case.
+               LBUFERR(false);
        }
 }
 
@@ -767,33 +743,8 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
                pi.pain.rectangle(expx, expy - dim.asc + 1, dim.wid - 1,
                                  dim.height() - 2, Color_mathmacroframe);
        } else {
-               bool drawBox = lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX
-                       && d->editing_[pi.base.bv];
-
-               // warm up cells
-               for (size_t i = 0; i < nargs(); ++i)
-                       cell(i).setXY(*pi.base.bv, x, y);
-
-               if (drawBox) {
-                       // draw header and rectangle around
-                       FontInfo font;
-                       font.setSize(FONT_SIZE_TINY);
-                       font.setColor(Color_mathmacrolabel);
-                       Dimension namedim;
-                       mathed_string_dim(font, name(), namedim);
-
-                       pi.pain.fillRectangle(x, y - dim.asc, dim.wid, 1 + namedim.height() + 1, Color_mathmacrobg);
-                       pi.pain.text(x + 1, y - dim.asc + namedim.asc + 2, name(), font);
-                       expx += (dim.wid - d->expanded_.dimension(*pi.base.bv).width()) / 2;
-               }
-
-               beforeDraw(pi);
-               d->expanded_.draw(pi, expx, expy);
-               afterDraw(pi);
-
-               if (drawBox)
-                       pi.pain.rectangle(x, y - dim.asc, dim.wid,
-                                         dim.height(), Color_mathmacroframe);
+               // We should not be here, since the macro is linearized in this case.
+               LBUFERR(false);
        }
 
        // edit mode changed?
index 5392754969c7a71d13a9ae8cd6a4c862356bb1d2..0d4ba34bf533968a7024bd549b300e0fbe2ac3da 100644 (file)
@@ -37,7 +37,7 @@ public:
        ///
        virtual MathMacro const * asMacro() const { return this; }
        ///
-       marker_type marker() const;
+       marker_type marker(BufferView const *) const;
        /// If the macro is in normal edit mode, dissolve its contents in
        /// the row. Otherwise, just insert the inset.
        bool addToMathRow(MathRow &, MetricsInfo & mi) const;
index c3c9a1c9341936f95d04fa9afee7e35e97319721..783e85ab54ab2b6452adcd0bf907f45a4370e1de 100644 (file)
@@ -43,6 +43,95 @@ MathRow::Element::Element(MetricsInfo const & mi, Type t, MathClass mc)
 {}
 
 
+namespace {
+
+// Helper functions for markers
+
+int markerMargin(MathRow::Element const & e)
+{
+       return e.marker == InsetMath::MARKER
+               || e.marker == InsetMath::MARKER2;
+}
+
+
+void afterMetricsMarkers(MetricsInfo const & , MathRow::Element & e,
+                            Dimension & dim)
+{
+       // handle vertical space for markers
+       switch(e.marker) {
+       case InsetMath::NO_MARKER:
+               break;
+       case InsetMath::MARKER:
+               ++dim.des;
+               break;
+       case InsetMath::MARKER2:
+               ++dim.asc;
+               ++dim.des;
+               break;
+       case InsetMath::BOX_MARKER:
+               FontInfo font;
+               font.setSize(FONT_SIZE_TINY);
+               Dimension namedim;
+               mathed_string_dim(font, e.inset->name(), namedim);
+               int const namewid = 1 + namedim.wid + 1;
+
+               if (namewid > dim.wid)
+                       e.after += namewid - dim.wid;
+               dim.des += 3 + namedim.height();
+       }
+}
+
+
+void drawMarkers(PainterInfo const & pi, MathRow::Element const & e,
+                 int const x, int const y)
+{
+       if (e.marker == InsetMath::NO_MARKER)
+               return;
+
+       CoordCache const & coords = pi.base.bv->coordCache();
+       Dimension const dim = coords.getInsets().dim(e.inset);
+
+       // the marker is before/after the inset. Necessary space has been reserved already.
+       int const l = x + e.before - markerMargin(e);
+       int const r = x + dim.width() - e.after;
+
+       if (e.marker == InsetMath::BOX_MARKER) {
+               // draw header and rectangle around
+               FontInfo font;
+               font.setSize(FONT_SIZE_TINY);
+               font.setColor(Color_mathmacrolabel);
+               Dimension namedim;
+               mathed_string_dim(font, e.inset->name(), namedim);
+               pi.pain.fillRectangle(l, y + dim.des - namedim.height() - 2,
+                                     dim.wid, namedim.height() + 2, Color_mathmacrobg);
+               pi.pain.text(l, y + dim.des - namedim.des - 1, e.inset->name(), font);
+               return;
+       }
+
+       // Now markers with corners
+       bool const highlight = e.inset->mouseHovered(pi.base.bv)
+                              || e.inset->editing(pi.base.bv);
+       ColorCode const pen_color = highlight ? Color_mathframe : Color_mathcorners;
+
+       int const d = y + dim.descent();
+       pi.pain.line(l, d - 3, l, d, pen_color);
+       pi.pain.line(r, d - 3, r, d, pen_color);
+       pi.pain.line(l, d, l + 3, d, pen_color);
+       pi.pain.line(r - 3, d, r, d, pen_color);
+
+       if (e.marker == InsetMath::MARKER)
+               return;
+
+       int const a = y - dim.ascent();
+       pi.pain.line(l, a + 3, l, a, pen_color);
+       pi.pain.line(r, a + 3, r, a, pen_color);
+       pi.pain.line(l, a, l + 3, a, pen_color);
+       pi.pain.line(r - 3, a, r, a, pen_color);
+}
+
+}
+
+
 MathRow::MathRow(MetricsInfo & mi, MathData const * ar)
 {
        // First there is a dummy element of type "open"
@@ -90,16 +179,15 @@ MathRow::MathRow(MetricsInfo & mi, MathData const * ar)
                }
 
                // finally reserve space for markers
-               if (bef.marker != Inset::NO_MARKER)
-                       bef.after = max(bef.after, 1);
-               if (e.mclass != MC_UNKNOWN && e.marker != Inset::NO_MARKER)
-                       e.before = max(e.before, 1);
+               bef.after = max(bef.after, markerMargin(bef));
+               if (e.mclass != MC_UNKNOWN)
+                       e.before = max(e.before, markerMargin(e));
                // for linearized insets (macros...) too
-               if (e.type == BEGIN && e.marker != Inset::NO_MARKER)
-                       bef.after = max(bef.after, 1);
-               if (e.type == END && e.marker != Inset::NO_MARKER) {
+               if (e.type == BEGIN)
+                       bef.after = max(bef.after, markerMargin(e));
+               if (e.type == END && e.marker != InsetMath::NO_MARKER) {
                        Element & aft = elements_[after(i)];
-                       aft.before = max(aft.before, 1);
+                       aft.before = max(aft.before, markerMargin(e));
                }
        }
 
@@ -131,28 +219,7 @@ int MathRow::after(int i) const
 }
 
 
-namespace {
-
-void metricsMarkersVertical(MetricsInfo const & , MathRow::Element const & e,
-                            Dimension & dim)
-{
-       // handle vertical space for markers
-       switch(e.marker) {
-       case InsetMath::NO_MARKER:
-               break;
-       case InsetMath::MARKER:
-               ++dim.des;
-               break;
-       case InsetMath::MARKER2:
-               ++dim.asc;
-               ++dim.des;
-       }
-}
-
-}
-
-
-void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
+void MathRow::metrics(MetricsInfo & mi, Dimension & dim)
 {
        dim.asc = 0;
        dim.wid = 0;
@@ -161,7 +228,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
        vector<pair<InsetMath const *, Dimension>> dim_insets;
        vector<pair<MathData const *, Dimension>> dim_arrays;
        CoordCache & coords = mi.base.bv->coordCache();
-       for (Element const & e : elements_) {
+       for (Element & e : elements_) {
                mi.base.macro_nesting = e.macro_nesting;
                Dimension d;
                switch (e.type) {
@@ -176,6 +243,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
                        if (e.inset) {
                                dim_insets.push_back(make_pair(e.inset, Dimension()));
                                dim_insets.back().second.wid += e.before + e.after;
+                               d.wid = e.before + e.after;
                                e.inset->beforeMetrics();
                        }
                        if (e.ar)
@@ -185,11 +253,14 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
                        if (e.inset) {
                                e.inset->afterMetrics();
                                LATTEST(dim_insets.back().first == e.inset);
-                               Dimension & idim = dim_insets.back().second;
-                               metricsMarkersVertical(mi, e, idim);
-                               idim.wid += e.before + e.after;
-                               coords.insets().add(e.inset, idim);
+                               d = dim_insets.back().second;
+                               afterMetricsMarkers(mi, e, d);
+                               d.wid += e.before + e.after;
+                               coords.insets().add(e.inset, d);
                                dim_insets.pop_back();
+                               // We do not want to count the width again, but the
+                               // padding and the vertical dimension are meaningful.
+                               d.wid = e.before + e.after;
                        }
                        if (e.ar) {
                                LATTEST(dim_arrays.back().first == e.ar);
@@ -203,7 +274,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
                                // allow for one pixel before/after the box.
                                d.wid += e.before + e.after + 2;
                        } else {
-                               // hide the box, but give it some height
+                               // hide the box, but keep its height
                                d.wid = 0;
                        }
                        break;
@@ -228,43 +299,6 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
 }
 
 
-namespace {
-
-void drawMarkers(PainterInfo const & pi, MathRow::Element const & e, int const x, int const y)
-{
-       if (e.marker == InsetMath::NO_MARKER)
-               return;
-
-       CoordCache const & coords = pi.base.bv->coordCache();
-       Dimension const dim = coords.getInsets().dim(e.inset);
-
-       // the marker is before/after the inset. Normally some space has been reserved already.
-       int const l = x + e.before - 1;
-       int const r = x + dim.width() - e.after;
-
-       // Duplicated from Inset.cpp and adapted. It is believed that the
-       // Inset version should die eventually
-       ColorCode pen_color = e.inset->mouseHovered(pi.base.bv) || e.inset->editing(pi.base.bv)?
-               Color_mathframe : Color_mathcorners;
-
-       int const d = y + dim.descent();
-       pi.pain.line(l, d - 3, l, d, pen_color);
-       pi.pain.line(r, d - 3, r, d, pen_color);
-       pi.pain.line(l, d, l + 3, d, pen_color);
-       pi.pain.line(r - 3, d, r, d, pen_color);
-
-       if (e.marker == InsetMath::MARKER)
-               return;
-
-       int const a = y - dim.ascent();
-       pi.pain.line(l, a + 3, l, a, pen_color);
-       pi.pain.line(r, a + 3, r, a, pen_color);
-       pi.pain.line(l, a, l + 3, a, pen_color);
-       pi.pain.line(r - 3, a, r, a, pen_color);
-}
-
-}
-
 void MathRow::draw(PainterInfo & pi, int x, int const y) const
 {
        CoordCache & coords = pi.base.bv->coordCache();
index 797248c3a5512901cf284baf7011c8c42d63c3e1..de63ec965ff7a4442191cd044e28be11a07edce4 100644 (file)
@@ -111,7 +111,7 @@ public:
        MathRow(MetricsInfo & mi, MathData const * ar);
 
        //
-       void metrics(MetricsInfo & mi, Dimension & dim) const;
+       void metrics(MetricsInfo & mi, Dimension & dim);
        //
        void draw(PainterInfo & pi, int const x, int const y) const;