Move some Cursor methods to CursorData

Basically, everything that does not depend on a BufferView should move
there. Some methods that do not seem to need a BufferView, like
selHandle or IdxFirst or push actually depend on it and could not be
moved.

This allows to simplify a few uses of recordUndo helpers.

- Move some methods to DocIterator: nextMath, prevMath, getPossibleLabel,
  getEncoding;

- Move some methods to CursorData: setCursor, setCursorSelectionTo,
  (setCursorTo|normal|reset)Anchor, (set|clear)Selection,
  sel(|ection)(Begin|End), selectionAsString, info, currentState,
  (mark|clear|check)NewWordPosition, fixIfBroken, sanitize, all undo
  related methods, reset, isInside, leaveInset, current mode;

- kill some unused methods: macromode, replaceWord, setScreenPos, touch,
  markInsert, markErase;

- Move code around to group things, and add a few comments (a lot remains to be done).

This changes lead to some related changes in other classes: removal,
change of parameter.

No intended change.
This commit is contained in:
Jean-Marc Lasgouttes 2017-07-23 18:13:33 +02:00
parent 785c6d4e05
commit 02028c0b12
16 changed files with 825 additions and 884 deletions

View File

@ -5011,7 +5011,7 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
* non-const. This would however be costly in
* terms of code duplication.
*/
const_cast<Buffer *>(this)->undo().recordUndo(CursorData(parit));
CursorData(parit).recordUndo();
parit->params().depth(maxdepth);
}
maxdepth = parit->getMaxDepthAfter();

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,6 @@ class Row;
// these should go
class InsetMathUnknown;
class Encoding;
/**
* This class describes the position of a cursor within a document,
@ -93,62 +92,9 @@ public:
friend std::ostream & operator<<(std::ostream & os, CursorData const & cur);
friend LyXErr & operator<<(LyXErr & os, CursorData const & cur);
protected:
/// the anchor position
DocIterator anchor_;
/// do we have a selection?
bool selection_;
/// are we on the way to get one?
bool mark_;
/// are we in word-selection mode? This is set when double clicking.
bool word_selection_;
// FIXME: make them protected.
public:
/// the current font settings
Font current_font;
/// the current font
Font real_current_font;
protected:
//
// math specific stuff that could be promoted to "global" later
//
/// do we allow autocorrection
bool autocorrect_;
/// are we entering a macro name?
bool macromode_;
};
/// The cursor class describes the position of a cursor within a document.
class Cursor : public CursorData
{
public:
/// create the cursor of a BufferView
explicit Cursor(BufferView & bv);
/// returns true if we made a decision
bool getStatus(FuncRequest const & cmd, FuncStatus & flag) const;
/// dispatch from innermost inset upwards
void dispatch(FuncRequest const & cmd);
/// get the resut of the last dispatch
DispatchResult const & result() const;
/// add a new cursor slice
void push(Inset & inset);
/// add a new cursor slice, place cursor at front (move backwards)
void pushBackward(Inset & inset);
/// pop one level off the cursor
void pop();
/// pop one slice off the cursor stack and go backwards
bool popBackward();
/// pop one slice off the cursor stack and go forward
bool popForward();
/// make sure we are outside of given inset
void leaveInset(Inset const & inset);
/// set the cursor data
void setCursorData(CursorData const & data);
/// reset cursor bottom to the beginning of the top inset
// (sort of 'chroot' environment...)
void reset();
/// sets cursor part
/// this (intentionally) does neither touch anchor nor selection status
void setCursor(DocIterator const & it);
@ -157,9 +103,6 @@ public:
/// sets the cursor to the normalized selection anchor
void setCursorToAnchor();
///
void setCurrentFont();
//
// selection
//
@ -187,6 +130,16 @@ public:
void setSelection(DocIterator const & where, int n);
///
void clearSelection();
/// access to normalized selection anchor
CursorSlice normalAnchor() const;
/// access to real selection anchor
DocIterator const & realAnchor() const { return anchor_; }
DocIterator & realAnchor() { return anchor_; }
/// sets anchor to cursor position
void resetAnchor();
/// access to owning BufferView
/// access start of selection
CursorSlice selBegin() const;
/// access end of selection
@ -195,15 +148,11 @@ public:
DocIterator selectionBegin() const;
/// access end of selection
DocIterator selectionEnd() const;
/**
* Update the selection status and save permanent
* selection if needed.
* @param selecting the new selection status
* @return whether the selection status has changed
*/
bool selHandle(bool selecting);
///
docstring selectionAsString(bool with_label) const;
/// get some interesting description of top position
void info(odocstream & os, bool devel_mode) const;
///
docstring currentState(bool devel_mode) const;
@ -211,10 +160,137 @@ public:
bool autocorrect() const { return autocorrect_; }
/// auto-correct mode
bool & autocorrect() { return autocorrect_; }
/// are we entering a macro name?
bool macromode() const { return macromode_; }
/// are we entering a macro name?
bool & macromode() { return macromode_; }
/// fix cursor in circumstances that should never happen.
/// \retval true if a fix occurred.
bool fixIfBroken();
/// Repopulate the slices insets from bottom to top. Useful
/// for stable iterators or Undo data.
void sanitize();
///
bool isInside(Inset const *) const;
/// make sure we are outside of given inset
void leaveInset(Inset const & inset);
///
bool textUndo();
///
bool textRedo();
/// makes sure the next operation will be stored
void finishUndo() const;
/// open a new group of undo operations. Groups can be nested.
void beginUndoGroup() const;
/// end the current undo group
void endUndoGroup() const;
/// The general case: prepare undo for an arbitrary range.
void recordUndo(pit_type from, pit_type to) const;
/// Convenience: prepare undo for the range between 'from' and cursor.
void recordUndo(pit_type from) const;
/// Convenience: prepare undo for the single paragraph or cell
/// containing the cursor
void recordUndo(UndoKind kind = ATOMIC_UNDO) const;
/// Convenience: prepare undo for the inset containing the cursor
void recordUndoInset(Inset const * inset = 0) const;
/// Convenience: prepare undo for the whole buffer
void recordUndoFullBuffer() const;
/// Convenience: prepare undo for buffer parameters
void recordUndoBufferParams() const;
/// Convenience: prepare undo for the selected paragraphs or cells
void recordUndoSelection() const;
/// hook for text input to maintain the "new born word"
void markNewWordPosition();
/// The position of the new born word
/// As the user is entering a word without leaving it
/// the result is not empty. When not in text mode
/// and after leaving the word the result is empty.
DocIterator newWord() const { return new_word_; }
/// are we in math mode (2), text mode (1) or unsure (0)?
int currentMode();
/// Return true if the next or previous inset has confirmDeletion depending
/// on the boolean before. If there is a selection, return true if at least
/// one inset in the selection has confirmDeletion.
bool confirmDeletion(bool before = false) const;
protected:
/// validate the "new born word" position
void checkNewWordPosition();
/// clear the "new born word" position
void clearNewWordPosition();
/// the anchor position
DocIterator anchor_;
/// do we have a selection?
bool selection_;
/// are we on the way to get one?
bool mark_;
/// are we in word-selection mode? This is set when double clicking.
bool word_selection_;
// FIXME: make them protected.
public:
/// the current font settings
Font current_font;
/// the current font
Font real_current_font;
protected:
/// the start of the new born word
DocIterator new_word_;
//
// math specific stuff that could be promoted to "global" later
//
/// do we allow autocorrection
bool autocorrect_;
};
/// The cursor class describes the position of a cursor within a document.
class Cursor : public CursorData
{
public:
/// create the cursor of a BufferView
explicit Cursor(BufferView & bv);
/// add a new cursor slice
void push(Inset & inset);
/// add a new cursor slice, place cursor at front (move backwards)
void pushBackward(Inset & inset);
/// pop one level off the cursor
void pop();
/// pop one slice off the cursor stack and go backwards
bool popBackward();
/// pop one slice off the cursor stack and go forward
bool popForward();
/// set the cursor data
void setCursorData(CursorData const & data);
/// returns true if we made a decision
bool getStatus(FuncRequest const & cmd, FuncStatus & flag) const;
/// dispatch from innermost inset upwards
void dispatch(FuncRequest const & cmd);
/// display a message
void message(docstring const & msg) const;
/// display an error message
void errorMessage(docstring const & msg) const;
/// get the resut of the last dispatch
DispatchResult const & result() const;
///
void setCurrentFont();
/**
* Update the selection status and save permanent
* selection if needed.
* @param selecting the new selection status
* @return whether the selection status has changed
*/
bool selHandle(bool selecting);
/// returns x,y position
void getPos(int & x, int & y) const;
@ -265,12 +341,28 @@ public:
/// Should interpretation of the arrow keys be reversed?
bool reverseDirectionNeeded() const;
/// insert an inset
void insert(Inset *);
///
/// Insertion (mathed and texted)
///
/// insert a single char
void insert(char_type c);
/// insert a string
void insert(docstring const & str);
/// insert an inset
void insert(Inset *);
///
/// Insertion (mathed only)
///
/// insert a math atom
void insert(MathAtom const &);
/// insert a string of atoms
void insert(MathData const &);
/// Like insert, but moves the selection inside the inset if possible
void niceInsert(MathAtom const & at);
/// return the number of inserted array items
/// FIXME: document properly
int niceInsert(docstring const & str, Parse::flags f = Parse::NORMAL,
bool enter = true);
/// FIXME: rename to something sensible showing difference to x_target()
/// in pixels from left of screen, set to current position if unset
@ -288,24 +380,11 @@ public:
/// distance between actual and targeted position during last up/down in text
int textTargetOffset() const;
/// access to normalized selection anchor
CursorSlice normalAnchor() const;
/// access to real selection anchor
DocIterator const & realAnchor() const { return anchor_; }
DocIterator & realAnchor() { return anchor_; }
/// sets anchor to cursor position
void resetAnchor();
/// access to owning BufferView
BufferView & bv() const;
/// get some interesting description of top position
void info(odocstream & os, bool devel_mode) const;
/// are we in math mode (2), text mode (1) or unsure (0)?
int currentMode();
/// reset cursor bottom to the beginning of the top inset
// (sort of 'chroot' environment...)
void reset();
/// for spellchecking
void replaceWord(std::string const & replacestring);
/**
* the event was not (yet) dispatched.
*
@ -337,72 +416,23 @@ public:
* Not using noScreenUpdate() should never be wrong.
*/
void noScreenUpdate() const;
/// fix cursor in circumstances that should never happen.
/// \retval true if a fix occurred.
bool fixIfBroken();
/// Repopulate the slices insets from bottom to top. Useful
/// for stable iterators or Undo data.
void sanitize();
///
bool textUndo();
///
bool textRedo();
/// makes sure the next operation will be stored
void finishUndo() const;
/// open a new group of undo operations. Groups can be nested.
void beginUndoGroup() const;
/// end the current undo group
void endUndoGroup() const;
/// The general case: prepare undo for an arbitrary range.
void recordUndo(pit_type from, pit_type to) const;
/// Convenience: prepare undo for the range between 'from' and cursor.
void recordUndo(pit_type from) const;
/// Convenience: prepare undo for the single paragraph or cell
/// containing the cursor
void recordUndo(UndoKind kind = ATOMIC_UNDO) const;
/// Convenience: prepare undo for the inset containing the cursor
void recordUndoInset(Inset const * inset = 0) const;
/// Convenience: prepare undo for the whole buffer
void recordUndoFullBuffer() const;
/// Convenience: prepare undo for buffer parameters
void recordUndoBufferParams() const;
/// Convenience: prepare undo for the selected paragraphs or cells
void recordUndoSelection() const;
///
void checkBufferStructure();
/// hook for text input to maintain the "new born word"
void markNewWordPosition();
/// The position of the new born word
/// As the user is entering a word without leaving it
/// the result is not empty. When not in text mode
/// and after leaving the word the result is empty.
DocIterator newWord() const { return new_word_; }
/// Return true if the next or previous inset has confirmDeletion depending
/// on the boolean before. If there is a selection, return true if at least
/// one inset in the selection has confirmDeletion.
bool confirmDeletion(bool before = false) const;
/// Determine if x falls to the left or to the side of the middle of the
/// inset, and advance the cursor to match this position. If edit is true,
/// keep the cursor in front of the inset if it matter for dialogs.
/// Note: it does not handle RTL text yet, and is only used in math for now.
void moveToClosestEdge(int x, bool edit = false);
/// whether the cursor is either at the first or last row
bool atFirstOrLastRow(bool up);
public:
//private:
@ -411,12 +441,6 @@ public:
///
void saveBeforeDispatchPosXY();
private:
/// validate the "new born word" position
void checkNewWordPosition();
/// clear the "new born word" position
void clearNewWordPosition();
private:
///
BufferView * bv_;
@ -437,8 +461,6 @@ private:
int x_target_;
/// if a x_target cannot be hit exactly in a text, put the difference here
int textTargetOffset_;
/// the start of the new born word
DocIterator new_word_;
/// position before dispatch started
DocIterator beforeDispatchCursor_;
/// cursor screen coordinates before dispatch started
@ -454,10 +476,6 @@ private:
///////////////////////////////////////////////////////////////////
public:
///
void insert(MathAtom const &);
///
void insert(MathData const &);
/// return false for empty math insets
/// Use force to skip the confirmDeletion check.
bool erase(bool force = false);
@ -469,8 +487,6 @@ public:
/// move the cursor up by sending an internal LFUN_DOWN,
/// return true if fullscreen update is needed
bool down();
/// whether the cursor is either at the first or last row
bool atFirstOrLastRow(bool up);
/// move up/down in a text inset, called for LFUN_UP/DOWN,
/// return true if successful, updateNeeded set to true if fullscreen
/// update is needed, otherwise it's not touched
@ -478,10 +494,6 @@ public:
/// move up/down in math or any non text inset, call for LFUN_UP/DOWN
/// return true if successful
bool upDownInMath(bool up);
///
InsetMath & nextMath();
///
InsetMath & prevMath();
/// move forward in math. word: whether to skip a whole "word" (insets with
/// the same mathclass)
bool mathForward(bool word);
@ -491,18 +503,9 @@ public:
void plainErase();
///
void plainInsert(MathAtom const & at);
///
void niceInsert(MathAtom const & at);
/// return the number of inserted array items
int niceInsert(docstring const & str, Parse::flags f = Parse::NORMAL,
bool enter = true);
/// in pixels from top of screen
void setScreenPos(int x, int y);
/// current offset in the top cell
/// interpret name a name of a macro. Returns true if
/// something got inserted.
/// interpret name of a macro. Returns true if something got
/// inserted.
bool macroModeClose();
/// are we currently typing the name of a macro?
bool inMacroMode() const;
@ -510,42 +513,25 @@ public:
InsetMathUnknown * activeMacro();
/// get access to the macro we are currently typing
InsetMathUnknown const * activeMacro() const;
/// the name of the macro we are currently inputting
docstring macroName();
/// replace selected stuff with at, placing the former
// selection in given cell of atom
void handleNest(MathAtom const & at, int cell = 0);
///
bool isInside(Inset const *) const;
/// make sure cursor position is valid
/// FIXME: It does a subset of fixIfBroken. Maybe merge them?
void normalize();
/// mark current cursor trace for redraw
void touch();
/// hack for reveal codes
void markInsert();
void markErase();
/// injects content of a cell into parent
void pullArg();
/// split font inset etc
void handleFont(std::string const & font);
/// display a message
void message(docstring const & msg) const;
/// display an error message
void errorMessage(docstring const & msg) const;
///
docstring getPossibleLabel() const;
/// the name of the macro we are currently inputting
docstring macroName();
/// where in the curent cell does the macro name start?
int macroNamePos();
/// can we enter the inset?
bool openable(MathAtom const &) const;
///
Encoding const * getEncoding() const;
/// font at cursor position
Font getFont() const;
};

View File

@ -690,7 +690,7 @@ docstring grabAndEraseSelection(Cursor & cur)
}
bool reduceSelectionToOneCell(Cursor & cur)
bool reduceSelectionToOneCell(CursorData & cur)
{
if (!cur.selection() || !cur.inMathed())
return false;
@ -712,7 +712,7 @@ bool reduceSelectionToOneCell(Cursor & cur)
}
bool multipleCellsSelected(Cursor const & cur)
bool multipleCellsSelected(CursorData const & cur)
{
if (!cur.selection() || !cur.inMathed())
return false;
@ -969,7 +969,7 @@ void copyInset(Cursor const & cur, Inset * inset, docstring const & plaintext)
namespace {
void copySelectionToStack(Cursor const & cur, CutStack & cutstack)
void copySelectionToStack(CursorData const & cur, CutStack & cutstack)
{
// this doesn't make sense, if there is no selection
if (!cur.selection())
@ -1369,7 +1369,7 @@ void selClearOrDel(Cursor & cur)
}
docstring grabSelection(Cursor const & cur)
docstring grabSelection(CursorData const & cur)
{
if (!cur.selection())
return docstring();

View File

@ -127,7 +127,7 @@ void switchBetweenClasses(DocumentClassConstPtr c1,
/// Get the current selection as a string. Does not change the selection.
/// Does only work if the whole selection is in mathed.
docstring grabSelection(Cursor const & cur);
docstring grabSelection(CursorData const & cur);
/// Erase the current selection.
/// Does not handle undo. Does only work if the whole selection is in mathed.
/// Calls saveSelection.
@ -136,9 +136,9 @@ void eraseSelection(Cursor & cur);
/// cells, the cursor is moved the end of the current cell and the anchor to the
/// start. If the selection is inside only one cell, nothing is done. Return
/// true if the selection now does not span multiple cells anymore.
bool reduceSelectionToOneCell(Cursor & cur);
bool reduceSelectionToOneCell(CursorData & cur);
/// Returns true if multiple cells are selected in mathed.
bool multipleCellsSelected(Cursor const & cur);
bool multipleCellsSelected(CursorData const & cur);
/// Erase the selection and return it as a string.
/// Does not handle undo. Does only work if the whole selection is in mathed.
docstring grabAndEraseSelection(Cursor & cur);

View File

@ -15,9 +15,12 @@
#include "DocIterator.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "Encoding.h"
#include "Font.h"
#include "InsetList.h"
#include "Language.h"
#include "Paragraph.h"
#include "LyXRC.h"
#include "Text.h"
#include "mathed/MathData.h"
@ -156,6 +159,18 @@ Inset * DocIterator::realInset() const
}
InsetMath & DocIterator::nextMath()
{
return *nextAtom().nucleus();
}
InsetMath & DocIterator::prevMath()
{
return *prevAtom().nucleus();
}
MathAtom & DocIterator::prevAtom() const
{
LASSERT(!empty(), /**/);
@ -688,6 +703,28 @@ void DocIterator::append(DocIterator::idx_type idx, pos_type pos)
}
docstring DocIterator::getPossibleLabel() const
{
return inMathed() ? from_ascii("eq:") : text()->getPossibleLabel(*this);
}
Encoding const * DocIterator::getEncoding() const
{
if (empty())
return 0;
BufferParams const & bp = buffer()->params();
if (bp.useNonTeXFonts)
return encodings.fromLyXName("utf8-plain");
CursorSlice const & sl = innerTextSlice();
Text const & text = *sl.text();
Font font = text.getPar(sl.pit()).getFont(bp, sl.pos(),
text.outerFont(sl.pit()));
return font.language()->encoding();
}
ostream & operator<<(ostream & os, DocIterator const & dit)
{
for (size_t i = 0, n = dit.depth(); i != n; ++i)

View File

@ -20,12 +20,13 @@
namespace lyx {
class DocIterator;
class Encoding;
class FontSpan;
class InsetIterator;
class LyXErr;
class MathAtom;
class Paragraph;
class Text;
class InsetIterator;
class FontSpan;
DocIterator doc_iterator_begin(Buffer const * buf, Inset const * inset = 0);
DocIterator doc_iterator_end(Buffer const * buf, Inset const * inset = 0);
@ -149,6 +150,10 @@ public:
//
/// return the mathed cell this cursor is in
MathData & cell() const;
///
InsetMath & nextMath();
///
InsetMath & prevMath();
/// the mathatom left of the cursor
MathAtom & prevAtom() const;
/// the mathatom right of the cursor
@ -257,6 +262,11 @@ public:
/// push one CursorSlice on top and set its index and position
void append(idx_type idx, pos_type pos);
///
docstring getPossibleLabel() const;
///
Encoding const * getEncoding() const;
private:
friend class InsetIterator;
friend DocIterator doc_iterator_begin(Buffer const * buf, Inset const * inset);

View File

@ -1896,7 +1896,7 @@ bool Text::read(Lexer & lex,
// Returns the current font and depth as a message.
docstring Text::currentState(Cursor const & cur, bool devel_mode) const
docstring Text::currentState(CursorData const & cur, bool devel_mode) const
{
LBUFERR(this == cur.text());
Buffer & buf = *cur.buffer();
@ -1973,7 +1973,7 @@ docstring Text::currentState(Cursor const & cur, bool devel_mode) const
}
docstring Text::getPossibleLabel(Cursor const & cur) const
docstring Text::getPossibleLabel(DocIterator const & cur) const
{
pit_type pit = cur.pit();

View File

@ -24,6 +24,7 @@ class BufferParams;
class BufferView;
class CompletionList;
class Cursor;
class CursorData;
class CursorSlice;
class DocIterator;
class ErrorList;
@ -158,7 +159,7 @@ public:
Paragraph & getPar(pit_type pit) { return pars_[pit]; }
// Returns the current font and depth as a message.
// When \param devel_mode is true, add more precise information
docstring currentState(Cursor const & cur, bool devel_mode) const;
docstring currentState(CursorData const & cur, bool devel_mode) const;
/** Find the word under \c from in the relative location
* defined by \c word_location.
@ -280,7 +281,7 @@ public:
double spacing(Paragraph const & par) const;
/// make a suggestion for a label
/// FIXME: replace Cursor with DocIterator.
docstring getPossibleLabel(Cursor const & cur) const;
docstring getPossibleLabel(DocIterator const & cur) const;
/// is this paragraph right-to-left?
bool isRTL(Paragraph const & par) const;

View File

@ -1159,7 +1159,7 @@ void unifyGraphicsGroups(Buffer & b, string const & argument)
InsetGraphics & ins = static_cast<InsetGraphics &>(*it);
InsetGraphicsParams inspar = ins.getParams();
if (params.groupId == inspar.groupId) {
b.undo().recordUndo(CursorData(it));
CursorData(it).recordUndo();
params.filename = inspar.filename;
ins.setParams(params);
}

View File

@ -115,7 +115,7 @@ void InsetLabel::updateReferences(docstring const & old_label,
Buffer::References::const_iterator end = refs.end();
for (; it != end; ++it) {
ugh.resetBuffer(it->second.buffer());
it->second.buffer()->undo().recordUndo(CursorData(it->second));
CursorData(it->second).recordUndo();
if (it->first->lyxCode() == MATH_REF_CODE) {
InsetMathRef * mi = it->first->asInsetMath()->asRefInset();
mi->changeTarget(new_label);

View File

@ -2243,42 +2243,6 @@ void InsetMathHull::edit(Cursor & cur, bool front, EntryDirection entry_from)
}
void InsetMathHull::revealCodes(Cursor & cur) const
{
if (!cur.inMathed())
return;
odocstringstream os;
cur.info(os, false);
cur.message(os.str());
/*
// write something to the minibuffer
// translate to latex
cur.markInsert(bv);
ostringstream os;
write(os);
string str = os.str();
cur.markErase(bv);
string::size_type pos = 0;
string res;
for (string::iterator it = str.begin(); it != str.end(); ++it) {
if (*it == '\n')
res += ' ';
else if (*it == '\0') {
res += " -X- ";
pos = it - str.begin();
}
else
res += *it;
}
if (pos > 30)
res = res.substr(pos - 30);
if (res.size() > 60)
res = res.substr(0, 60);
cur.message(res);
*/
}
/////////////////////////////////////////////////////////////////////

View File

@ -284,8 +284,6 @@ public:
///
virtual void mutateToText();
///
virtual void revealCodes(Cursor & cur) const;
///
bool editable() const { return true; }
///
void edit(Cursor & cur, bool front,

View File

@ -896,7 +896,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
int y = 0;
istringstream is(to_utf8(cmd.argument()));
is >> x >> y;
cur.setScreenPos(x, y);
cur.setTargetX(x);
break;
}

View File

@ -212,11 +212,6 @@ bool MathData::contains(MathData const & ar) const
}
void MathData::touch() const
{
}
bool MathData::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
{
bool has_contents = false;

View File

@ -137,8 +137,6 @@ public:
void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
/// redraw cell using cache metrics information
void drawT(TextPainter & pi, int x, int y) const;
/// mark cell for re-drawing
void touch() const;
/// approximate the math class of the data
MathClass mathClass() const;