From: André Pönitz Date: Wed, 5 Dec 2001 17:50:18 +0000 (+0000) Subject: deep iterators for math insets; X-Git-Tag: 1.6.10~20225 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=ebe6d25126e220495d37140bde23dcc64bf4a8d9;p=features.git deep iterators for math insets; use brute force for to determine "best" position when doing cursor up/down (will be sped up a bit again soonish...) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3153 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/mathed/Makefile.am b/src/mathed/Makefile.am index 4a624d3188..a3963baff5 100644 --- a/src/mathed/Makefile.am +++ b/src/mathed/Makefile.am @@ -68,6 +68,8 @@ libmathed_la_SOURCES = \ math_hullinset.h \ math_inset.C \ math_inset.h \ + math_iterator.C \ + math_iterator.h \ math_kerninset.C \ math_kerninset.h \ math_lefteqninset.C \ diff --git a/src/mathed/README b/src/mathed/README index caf9498e1e..d23b8610d5 100644 --- a/src/mathed/README +++ b/src/mathed/README @@ -26,12 +26,12 @@ Inset hierarchy: / \ - Array "Matrix" + Array Hull (base for eqnarray/align/...) There are only two "real LyXInsets" in here: -Formula - containing a pointer to a MathMatrixInset (a misnomer...) +Formula - containing a pointer to a MathHullInset FormulaMacro - containing a pointer to a MathMacroTemplate diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index 0d70e911ce..6c11fca0bc 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -28,22 +28,23 @@ #include "debug.h" #include "LColor.h" #include "Painter.h" -#include "math_support.h" #include "formulabase.h" -#include "math_cursor.h" -#include "math_casesinset.h" -#include "math_factory.h" #include "math_arrayinset.h" #include "math_braceinset.h" +#include "math_casesinset.h" #include "math_charinset.h" +#include "math_cursor.h" #include "math_deliminset.h" +#include "math_factory.h" #include "math_hullinset.h" +#include "math_iterator.h" +#include "math_mathmlstream.h" +#include "math_parser.h" +#include "math_replace.h" #include "math_scriptinset.h" #include "math_spaceinset.h" #include "math_specialcharinset.h" -#include "math_mathmlstream.h" -#include "math_replace.h" -#include "math_parser.h" +#include "math_support.h" #define FILEDEBUG 0 @@ -67,7 +68,7 @@ struct Selection data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_)); else { std::vector indices = - (*i1.par_)->idxBetween(i1.idx_, i2.idx_); + i1.par_->idxBetween(i1.idx_, i2.idx_); for (MathInset::idx_type i = 0; i < indices.size(); ++i) data_.push_back(i1.cell(indices[i])); } @@ -82,7 +83,7 @@ struct Selection i1.cell().erase(i1.pos_, i2.pos_); else { std::vector indices = - (*i1.par_)->idxBetween(i1.idx_, i2.idx_); + i1.par_->idxBetween(i1.idx_, i2.idx_); for (unsigned i = 0; i < indices.size(); ++i) i1.cell(indices[i]).erase(); } @@ -116,13 +117,6 @@ struct Selection Selection theSelection; -#if FILEDEBUG -std::ostream & operator<<(std::ostream & os, MathCursorPos const & p) -{ - os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")"; - return os; -} -#endif } @@ -136,11 +130,7 @@ MathCursor::MathCursor(InsetFormulaBase * formula, bool left) void MathCursor::push(MathAtom & t) { - MathCursorPos p; - p.par_ = &t; - p.idx_ = 0; - p.pos_ = 0; - Cursor_.push_back(p); + Cursor_.push_back(MathCursorPos(t.nucleus())); } @@ -192,48 +182,19 @@ bool MathCursor::popRight() #if FILEDEBUG -void MathCursor::dump(char const * what) const -{ - lyxerr << "MC: " << what << "\n"; - for (unsigned i = 0; i < Cursor_.size(); ++i) - lyxerr << " i: " << i - << " Cursor: pos: " << Cursor_[i].pos_ - << " idx: " << Cursor_[i].idx_ - << " par: " << Cursor_[i].par_ << "\n"; - - for (unsigned i = 0; i < Anchor_.size(); ++i) - lyxerr << " i: " << i - << " Anchor: pos: " << Anchor_[i].pos_ - << " idx: " << Anchor_[i].idx_ - << " par: " << Anchor_[i].par_ << "\n"; - - lyxerr << " sel: " << selection_ << "\n"; -} - - -void MathCursor::seldump(char const * str) const -{ - //lyxerr << "SEL: " << str << ": '" << theSelection << "'\n"; - //dump(" Pos"); - - lyxerr << "\n\n\n=================vvvvvvvvvvvvv======================= " - << str << "\ntheSelection: " << selection_ - << " '" /*<< theSelection.glue()*/ << "'\nCursor:"; - for (unsigned int i = 0; i < Cursor_.size(); ++i) - lyxerr << Cursor_[i].par_ << "\n'" /*<< Cursor_[i].cell()*/ << "'\n"; - lyxerr << "\nAnchor: "; - for (unsigned int i = 0; i < Anchor_.size(); ++i) - lyxerr << Anchor_[i].par_ << "\n'" /*<< Anchor_[i].cell()*/ << "'\n"; - //lyxerr << "\ncursor.pos_: " << pos(); - //lyxerr << "\nanchor.pos_: " << anchor().pos_; - lyxerr << "\n===================^^^^^^^^^^^^=====================\n\n\n"; -} - + void MathCursor::dump(char const * what) const + { + lyxerr << "MC: " << what << "\n"; + lyxerr << " Cursor: " << Cursor_.size() << "\n"; + for (unsigned i = 0; i < Cursor_.size(); ++i) + lyxerr << " i: " << i << " " << Cursor_[i] << "\n"; + lyxerr << " Anchor: " << Anchor_.size() << "\n"; + for (unsigned i = 0; i < Anchor_.size(); ++i) + lyxerr << " i: " << i << " " << Anchor_[i] << "\n"; + lyxerr << " sel: " << selection_ << "\n"; + } #else - -void MathCursor::seldump(char const *) const {} -void MathCursor::dump(char const *) const {} - + void MathCursor::dump(char const *) const {} #endif @@ -246,7 +207,7 @@ UpdatableInset * MathCursor::asHyperActiveInset() const bool MathCursor::isInside(MathInset const * p) const { for (unsigned i = 0; i < Cursor_.size(); ++i) - if (Cursor_[i].par_->nucleus() == p) + if (Cursor_[i].par_ == p) return true; return false; } @@ -267,7 +228,7 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const // we can't move into anything new during selection if (Cursor_.size() == Anchor_.size()) return false; - if (&t != Anchor_[Cursor_.size()].par_) + if (t.nucleus() != Anchor_[Cursor_.size()].par_) return false; } return true; @@ -280,7 +241,7 @@ bool MathCursor::positionable(MathAtom const & t, int x, int y) const // we can't move into anything new during selection if (Cursor_.size() >= Anchor_.size()) return false; - if (&t != Anchor_[Cursor_.size()].par_) + if (t.nucleus() != Anchor_[Cursor_.size()].par_) return false; } @@ -371,6 +332,7 @@ void MathCursor::last() } +#if 0 void MathCursor::setPos(int x, int y) { //dump("setPos 1"); @@ -407,6 +369,47 @@ void MathCursor::setPos(int x, int y) //dump("setPos 2"); } +#else + +void MathCursor::setPos(int x, int y) +{ + dump("setPos 1"); + cursor_type best_cursor; + double best_dist = 1e10; + + MathIterator it(formula()->par().nucleus()); + MathIterator et; + for ( ; it != et; ++it) { + if (selection_) { + // avoid deeper nested insets when selecting + if (it.cursor().size() > Anchor_.size()) + continue; + // anchor might be deeper! + if (it.cursor().size() == Anchor_.size()) + if (it.par() != Anchor_.back().par_) + continue; + //if (it.par() != Anchor_[it.cursor().size()].par_) + // continue; + } + //lyxerr << it.position() << endl; + int xo = it.position().xpos(); + int yo = it.position().ypos(); + double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); + if (d < best_dist) { + best_dist = d; + best_cursor = it.cursor(); + } + } + if (best_dist < 1e10) + Cursor_ = best_cursor; + //lyxerr << "x: " << x << " y: " << y << " dist: " << best_dist << "\n"; + dump("setPos 2"); +} + +#endif + + + void MathCursor::home(bool sel) { @@ -687,7 +690,7 @@ string MathCursor::macroName() const void MathCursor::selCopy() { - seldump("selCopy"); + dump("selCopy"); if (selection_) { theSelection.grab(*this); selClear(); @@ -697,7 +700,7 @@ void MathCursor::selCopy() void MathCursor::selCut() { - seldump("selCut"); + dump("selCut"); if (selection_) { theSelection.grab(*this); theSelection.erase(*this); @@ -710,7 +713,7 @@ void MathCursor::selCut() void MathCursor::selDel() { - seldump("selDel"); + dump("selDel"); if (selection_) { theSelection.erase(*this); if (pos() > size()) @@ -722,7 +725,7 @@ void MathCursor::selDel() void MathCursor::selPaste() { - seldump("selPaste"); + dump("selPaste"); theSelection.paste(*this); //theSelection.grab(*this); //selClear(); @@ -741,23 +744,25 @@ void MathCursor::selHandle(bool sel) void MathCursor::selStart() { - seldump("selStart"); + dump("selStart 1"); //theSelection.clear(); Anchor_ = Cursor_; selection_ = true; + dump("selStart 2"); } void MathCursor::selClear() { - seldump("selClear"); + dump("selClear 1"); selection_ = false; + dump("selClear 2"); } void MathCursor::selGet(MathArray & ar) { - seldump("selGet"); + dump("selGet"); if (!selection_) return; @@ -786,7 +791,7 @@ void MathCursor::drawSelection(Painter & pain) const pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection); } else { std::vector indices - = (*i1.par_)->idxBetween(i1.idx_, i2.idx_); + = i1.par_->idxBetween(i1.idx_, i2.idx_); for (unsigned i = 0; i < indices.size(); ++i) { MathXArray & c = i1.xcell(indices[i]); int x1 = c.xo(); @@ -850,14 +855,16 @@ void MathCursor::getPos(int & x, int & y) #ifdef WITH_WARNINGS #warning This should probably take cellXOffset and cellYOffset into account #endif + dump("getPos 1"); x = xarray().xo() + xarray().pos2x(pos()); y = xarray().yo(); + dump("getPos 2"); } -MathAtom & MathCursor::par() const +MathInset * MathCursor::par() const { - return *cursor().par_; + return cursor().par_; } @@ -906,7 +913,7 @@ bool MathCursor::selection() const MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const { for (int i = Cursor_.size() - 1; i >= 0; --i) { - MathGridInset * p = (*Cursor_[i].par_)->asGridInset(); + MathGridInset * p = Cursor_[i].par_->asGridInset(); if (p) { idx = Cursor_[i].idx_; return p; @@ -1153,8 +1160,12 @@ MathCursorPos const & MathCursor::cursor() const bool MathCursor::goUp() { // first ask the inset if it knows better then we - if (par()->idxUp(idx(), pos())) + if (par()->idxUp(idx(), pos())) { + int xlow, xhigh, ylow, yhigh; + xarray().boundingBox(xlow, xhigh, ylow, yhigh); + bruteFind(xlow, xhigh, ylow, yhigh); return true; + } // leave subscript to the nearest side MathScriptInset * p = par()->asScriptInset(); @@ -1175,8 +1186,12 @@ bool MathCursor::goUp() bool MathCursor::goDown() { // first ask the inset if it knows better then we - if (par()->idxDown(idx(), pos())) + if (par()->idxDown(idx(), pos())) { + int xlow, xhigh, ylow, yhigh; + xarray().boundingBox(xlow, xhigh, ylow, yhigh); + bruteFind(xlow, xhigh, ylow, yhigh); return true; + } // leave superscript to the nearest side MathScriptInset * p = par()->asScriptInset(); @@ -1200,8 +1215,8 @@ bool MathCursor::bruteUpDown(int ylow, int yhigh) int x0; int y0; getPos(x0, y0); - std::vector save = Cursor_; - std::vector best; + cursor_type save = Cursor_; + cursor_type best; double best_dist = 1e10; // large enough bool found = false; for (int y = ylow; y < yhigh; y += 4) { @@ -1229,6 +1244,35 @@ bool MathCursor::bruteUpDown(int ylow, int yhigh) } +bool MathCursor::bruteFind(int xlow, int xhigh, int ylow, int yhigh) +{ + //lyxerr << "looking at range: " << ylow << " " << yhigh << "\n"; + int x; + int y; + getPos(x, y); + + cursor_type best_cursor; + double best_dist = 1e10; + + MathIterator it(formula()->par().nucleus()); + MathIterator et; + for ( ; it != et; ++it) { + int xo = it.position().xpos(); + int yo = it.position().ypos(); + if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) { + double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); + if (d < best_dist) { + best_dist = d; + best_cursor = it.cursor(); + } + } + } + if (best_dist < 1e10) + Cursor_ = best_cursor; + return true; +} + + bool MathCursor::idxLeft() { return par()->idxLeft(idx(), pos()); @@ -1443,75 +1487,109 @@ bool MathCursor::interpret(char c) -//////////////////////////////////////////////////////////////////////// - - -bool operator==(MathCursorPos const & ti, MathCursorPos const & it) +MathCursorPos MathCursor::normalAnchor() const { - return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_; + // use Anchor on the same level as Cursor + MathCursorPos normal = Anchor_[Cursor_.size() - 1]; + if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) { + // anchor is behind cursor -> move anchor behind the inset + ++normal.pos_; + } + return normal; } -bool operator<(MathCursorPos const & ti, MathCursorPos const & it) +void MathCursor::stripFromLastEqualSign() { - if (ti.par_ != it.par_) { - lyxerr << "can't compare cursor and anchor in different insets\n"; - return true; - } - if (ti.idx_ != it.idx_) - return ti.idx_ < it.idx_; - return ti.pos_ < it.pos_; + // find position of last '=' in the array + MathArray & ar = cursor().cell(); + MathArray::const_iterator et = ar.end(); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) + if ((*it)->getChar() == '=') + et = it; + + // delete everything behind this position + ar.erase(et - ar.begin(), ar.size()); + pos() = ar.size(); } +//////////////////////////////////////////////////////////////////////// + + +MathCursorPos::MathCursorPos() + : par_(0), idx_(0), pos_(0) +{} + + +MathCursorPos::MathCursorPos(MathInset * p) + : par_(p), idx_(0), pos_(0) +{} + + MathArray & MathCursorPos::cell(MathCursor::idx_type idx) const { - return (*par_)->cell(idx); + return par_->cell(idx); } MathArray & MathCursorPos::cell() const { - return (*par_)->cell(idx_); + return par_->cell(idx_); } MathXArray & MathCursorPos::xcell(MathCursor::idx_type idx) const { - return (*par_)->xcell(idx); + return par_->xcell(idx); } MathXArray & MathCursorPos::xcell() const { - return (*par_)->xcell(idx_); + return par_->xcell(idx_); } -MathCursorPos MathCursor::normalAnchor() const +int MathCursorPos::xpos() const { - // use Anchor on the same level as Cursor - MathCursorPos normal = Anchor_[Cursor_.size() - 1]; - if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) { - // anchor is behind cursor -> move anchor behind the inset - ++normal.pos_; - } - return normal; + return xcell().xo() + xcell().pos2x(pos_); } -void MathCursor::stripFromLastEqualSign() +int MathCursorPos::ypos() const { - // find position of last '=' in the array - MathArray & ar = cursor().cell(); - MathArray::const_iterator et = ar.end(); - for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) - if ((*it)->getChar() == '=') - et = it; + return xcell().yo(); +} - // delete everything behind this position - ar.erase(et - ar.begin(), ar.size()); - pos() = ar.size(); +std::ostream & operator<<(std::ostream & os, MathCursorPos const & p) +{ + os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")"; + return os; +} + + +bool operator==(MathCursorPos const & ti, MathCursorPos const & it) +{ + return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_; +} + + +bool operator!=(MathCursorPos const & ti, MathCursorPos const & it) +{ + return ti.par_ != it.par_ || ti.idx_ != it.idx_ || ti.pos_ != it.pos_; +} + + +bool operator<(MathCursorPos const & ti, MathCursorPos const & it) +{ + if (ti.par_ != it.par_) { + lyxerr << "can't compare cursor and anchor in different insets\n"; + return true; + } + if (ti.idx_ != it.idx_) + return ti.idx_ < it.idx_; + return ti.pos_ < it.pos_; } diff --git a/src/mathed/math_cursor.h b/src/mathed/math_cursor.h index f38125aa45..5053356309 100644 --- a/src/mathed/math_cursor.h +++ b/src/mathed/math_cursor.h @@ -42,13 +42,12 @@ this formula's mathHullInset to the current position. /// Description of a position -struct MathCursorPos { - /// pointer to an inset - MathAtom * par_; - /// cell index of a position in this inset - MathInset::idx_type idx_; - /// position in this cell - MathInset::pos_type pos_; +class MathCursorPos { +public: + /// + MathCursorPos(); + /// + explicit MathCursorPos(MathInset * p); /// returns cell corresponding to this position MathArray & cell() const; @@ -58,12 +57,28 @@ struct MathCursorPos { MathXArray & xcell() const; /// returns xcell corresponding to this position MathXArray & xcell(MathInset::idx_type idx) const; + /// + int xpos() const; + /// + int ypos() const; + +public: + /// pointer to an inset + MathInset * par_; + /// cell index of a position in this inset + MathInset::idx_type idx_; + /// position in this cell + MathInset::pos_type pos_; }; /// test for equality bool operator==(MathCursorPos const &, MathCursorPos const &); -/// test for unequality +/// test for inequality +bool operator!=(MathCursorPos const &, MathCursorPos const &); +/// test for order bool operator<(MathCursorPos const &, MathCursorPos const &); +/// output +std::ostream & operator<<(std::ostream &, MathCursorPos const &); /// see above @@ -128,7 +143,7 @@ public: /// in pixels from top of screen void getPos(int & x, int & y); /// - MathAtom & par() const; + MathInset * par() const; /// return the next enclosing grid inset and the cursor's index in it MathGridInset * enclosingGrid(idx_type &) const; /// @@ -275,6 +290,8 @@ private: bool goDown(); /// moves position somehow down bool bruteUpDown(int ylow, int yhigh); + /// moves position into box + bool bruteFind(int xlow, int xhigh, int ylow, int yhigh); /// string macroName() const; diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index 56bfaeae55..ce2d94bee5 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -487,31 +487,27 @@ int MathGridInset::cellYOffset(idx_type idx) const } -bool MathGridInset::idxUp(idx_type & /*idx*/, pos_type & /*pos*/) const +bool MathGridInset::idxUp(idx_type & idx, pos_type & pos) const { - return false; -/* + //return false; if (idx < ncols()) return false; int x = cellXOffset(idx) + xcell(idx).pos2x(pos); idx -= ncols(); pos = xcell(idx).x2pos(x - cellXOffset(idx)); return true; -*/ } -bool MathGridInset::idxDown(idx_type & /*idx*/, pos_type & /*pos*/) const +bool MathGridInset::idxDown(idx_type & idx, pos_type & pos) const { - return false; -/* + //return false; if (idx >= ncols() * (nrows() - 1)) return false; int x = cellXOffset(idx) + xcell(idx).pos2x(pos); idx += ncols(); pos = xcell(idx).x2pos(x - cellXOffset(idx)); return true; -*/ } diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index ca568a3ed8..3acdd53a3b 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -72,6 +72,7 @@ class LaTeXFeatures; class BufferView; class UpdatableInset; class MathMacroTemplate; +class MathPosFinder; class MathInset { diff --git a/src/mathed/math_iterator.C b/src/mathed/math_iterator.C new file mode 100644 index 0000000000..0ea88d5098 --- /dev/null +++ b/src/mathed/math_iterator.C @@ -0,0 +1,137 @@ + +#include + +#include "debug.h" +#include "math_iterator.h" + + +MathIterator::MathIterator() +{} + + +MathIterator::MathIterator(MathInset * p) +{ + push(p); +} + + +MathIterator::MathIterator(MathCursor::cursor_type const & c) + : cursor_(c) +{} + + +MathCursorPos const & MathIterator::position() const +{ + return cursor_.back(); +} + + +MathCursorPos & MathIterator::position() +{ + return cursor_.back(); +} + + +MathCursor::cursor_type const & MathIterator::cursor() const +{ + return cursor_; +} + + +MathInset * MathIterator::par() const +{ + return cursor_.size() ? cursor_.back().par_ : 0; +} + + +MathXArray const & MathIterator::xcell() const +{ + if (!par()) + lyxerr << "MathIterator::xcell: no cell\n"; + return par()->xcell(position().idx_); +} + + +MathInset * MathIterator::nextInset() const +{ + if (position().pos_ == xcell().data_.size()) + return 0; + return (xcell().begin() + position().pos_)->nucleus(); +} + + +void MathIterator::push(MathInset * p) +{ + //lyxerr << "push: " << p << endl; + cursor_.push_back(MathCursorPos(p)); +} + + +void MathIterator::pop() +{ + //lyxerr << "pop: " << endl; + cursor_.pop_back(); +} + + +MathCursorPos const & MathIterator::operator*() const +{ + return position(); +} + + +MathCursorPos const & MathIterator::operator->() const +{ + return position(); +} + + +void MathIterator::operator++() +{ + // move into the current inset if possible + // it is impossible for pos() == size()! + if (nextInset() && nextInset()->isActive()) { + push(nextInset()); + return; + } + + // otherwise move on one cell position if possible + if (position().pos_ < xcell().data_.size()) { + // pos() == size() is valid! + ++position().pos_; + return; + } + + // otherwise move on one cell if possible + if (position().idx_ + 1 < par()->nargs()) { + // idx() == nargs() is _not_ valid! + ++position().idx_; + position().pos_ = 0; + return; + } + + // otherwise leave array, move on one cell + // this might yield pos() == size(), but that's a ok. + pop(); + ++position().pos_; +} + + + +bool operator==(MathIterator const & it, MathIterator const & jt) +{ + //lyxerr << "==: " << it.cursor().size() << " " << jt.cursor().size() << endl; + if (it.cursor().size() != jt.cursor().size()) + return false; + return it.cursor() == jt.cursor(); +} + + +bool operator!=(MathIterator const & it, MathIterator const & jt) +{ + //lyxerr << "!=: " << it.cursor().size() << " " << jt.cursor().size() << endl; + if (it.cursor().size() != jt.cursor().size()) + return true; + return it.cursor() != jt.cursor(); +} + diff --git a/src/mathed/math_iterator.h b/src/mathed/math_iterator.h new file mode 100644 index 0000000000..f56911c4d5 --- /dev/null +++ b/src/mathed/math_iterator.h @@ -0,0 +1,51 @@ +#ifndef MATH_ITERATOR_H +#define MATH_ITERATOR_H + +#include "math_cursor.h" + +// this helper struct is used for traversing math insets + +class MathIterator { +public: + /// default constructor, used for end of range + MathIterator(); + /// start with given formula + explicit MathIterator(MathInset * p); + /// start with given position + explicit MathIterator(MathCursor::cursor_type const & cursor); + /// + MathCursorPos const & operator*() const; + /// + MathCursorPos const & operator->() const; + /// + void operator++(); + /// read access to top most item + MathCursorPos const & position() const; + /// write access to top most item + MathCursorPos & position(); + /// read access to full path + MathCursor::cursor_type const & cursor() const; + /// read access to top most inset + MathInset * par() const; + +private: + /// write access to top most item + MathXArray const & xcell() const; + /// write access to top most item + MathInset * nextInset() const; + /// own level down + void push(MathInset *); + /// own level up + void pop(); + + /// current position + MathCursor::cursor_type cursor_; +}; + +/// +bool operator==(MathIterator const &, MathIterator const &); +/// +bool operator!=(MathIterator const &, MathIterator const &); + + +#endif diff --git a/src/mathed/math_xdata.C b/src/mathed/math_xdata.C index 8663e7f115..37786bbc74 100644 --- a/src/mathed/math_xdata.C +++ b/src/mathed/math_xdata.C @@ -151,3 +151,39 @@ bool MathXArray::covers(int x, int y) const int const y1 = yo_ + descent_; return x >= x0 && x <= x1 && y >= y0 && y <= y1; } + + +void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2) +{ + x1 = xo_; + x2 = xo_ + width_; + y1 = yo_ - ascent_; + y2 = yo_ + descent_; +} + +/* +void MathXArray::findPos(MathPosFinder & f) const +{ + double x = xo_; + double y = yo_; + for (const_iterator it = begin(); it < end(); ++it) { + // check this position in the cell first + f.visit(x, y); + f.nextPos(); + + // check inset + MathInset const * p = it->nucleus(); + p->findPos(f); + + // move on + MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it); + if (q) { + x += q->width(p); + f.nextPos(); + ++it; + } else { + x += p->width(); + } + } +} +*/ diff --git a/src/mathed/math_xdata.h b/src/mathed/math_xdata.h index 0fb7842d66..dd059aaefb 100644 --- a/src/mathed/math_xdata.h +++ b/src/mathed/math_xdata.h @@ -14,66 +14,75 @@ class Painter; + +/** This class extends a MathArray by drawing routines and caches for + * metric information. + */ class MathXArray { public: - /// + /// type for positions and sizes typedef MathArray::size_type size_type; - /// + /// const iterator into the underlying MathArray typedef MathArray::const_iterator const_iterator; - /// + /// constructor MathXArray(); - /// + /// rebuild cached metrics information void metrics(MathMetricsInfo const & st) const; - /// + /// redraw cell using cache metrics information void draw(Painter & pain, int x, int y) const; - /// + /// access to cached x coordinate of last drawing int xo() const { return xo_; } - /// + /// access to cached y coordinate of last drawing int yo() const { return yo_; } - /// + /// returns x coordinate of given position in the array int pos2x(size_type pos) const; - /// + /// returns position of given x coordinate size_type x2pos(int pos) const; /// returns distance of this cell to the point given by x and y // assumes valid position and size cache int dist(int x, int y) const; - /// + /// ascent of this cell above the baseline int ascent() const { return ascent_; } - /// + /// descent of this cell below the baseline int descent() const { return descent_; } - /// + /// height of the cell int height() const { return ascent_ + descent_; } - /// + /// width of this cell int width() const { return width_; } /// do we cover point(x, y)? bool covers(int x, int y) const; + /// bounding box of this cell + void boundingBox(int & xlow, int & xhigh, int & ylow, int & yhigh); + /// find best position to do things + //void findPos(PosFinder &) const; - /// + /// begin iterator of the underlying MathArray const_iterator begin() const { return data_.begin(); } - /// + /// end iterator of the underlying MathArray const_iterator end() const { return data_.end(); } public: - /// + /// the underlying MathArray MathArray data_; - /// + /// cached width of cell mutable int width_; - /// + /// cached ascent of cell mutable int ascent_; - /// + /// cached descent of cell mutable int descent_; - /// + /// cached x coordinate of last drawing mutable int xo_; - /// + /// cached y coordinate of last drawing mutable int yo_; - /// + /// cache size information of last drawing mutable MathMetricsInfo size_; }; +/// output cell on a stream std::ostream & operator<<(std::ostream & os, MathXArray const & ar); #endif