mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-23 13:31:49 +00:00
Optimize drawing.
* BufferView: - update(): returns a pair of bools in order to inform for singlePar cases. - workAreaDispatch(): ditto and simplify the logic by using cursor update flags. * text.C - breakParagraph(): change the cursor update flag as needed. - insertChar(): ditto. - erase(): ditto - redoParagraph(): now returns true if there is a height change. * text3.C: dispatch(): - initialize the cursor flag at the beginning - LFUN_MOUSE_PRESS: no need to update. - LFUN_MOUSE_RELEASE: ditto. - add some FIXMEs and comments. * LyXFunc::dispatch(): simplify the BufferView update. * insets/insetcollapsable.C: clarify and simplify the logic in doDispatch(). * WorkArea::dispatch(): redraw only if needed. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15958 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
3bc4d28449
commit
c66d2f1ee5
@ -339,7 +339,7 @@ bool BufferView::multiParSel()
|
||||
}
|
||||
|
||||
|
||||
bool BufferView::update(Update::flags flags)
|
||||
std::pair<bool, bool> BufferView::update(Update::flags flags)
|
||||
{
|
||||
// This is close to a hot-path.
|
||||
if (lyxerr.debugging(Debug::DEBUG)) {
|
||||
@ -353,7 +353,7 @@ bool BufferView::update(Update::flags flags)
|
||||
|
||||
// Check needed to survive LyX startup
|
||||
if (!buffer_)
|
||||
return false;
|
||||
return make_pair(false, false);
|
||||
|
||||
if (lyxerr.debugging(Debug::WORKAREA)) {
|
||||
lyxerr[Debug::WORKAREA] << "BufferView::update" << std::endl;
|
||||
@ -362,15 +362,31 @@ bool BufferView::update(Update::flags flags)
|
||||
// Update macro store
|
||||
buffer_->buildMacros();
|
||||
|
||||
// First drawing step
|
||||
updateMetrics(flags & Update::SinglePar);
|
||||
|
||||
// Now do the first drawing step if needed. This consists on updating
|
||||
// the CoordCache in updateMetrics().
|
||||
// The second drawing step is done in WorkArea::redraw() if needed.
|
||||
bool const need_second_step =
|
||||
(flags & (Update::SinglePar | Update::Force | Update::FitCursor | Update::MultiParSel))
|
||||
&& (fitCursor() || multiParSel());
|
||||
|
||||
return need_second_step;
|
||||
// Case when no explicit update is requested.
|
||||
if (!(flags & (Update::SinglePar | Update::Force))) {
|
||||
if (fitCursor() || multiParSel()) {
|
||||
// a CoordCache update is needed
|
||||
updateMetrics(false);
|
||||
// tell the frontend to update the screen.
|
||||
return make_pair(true, false);
|
||||
}
|
||||
// no need to do anything.
|
||||
return make_pair(false, false);
|
||||
}
|
||||
|
||||
// We are now in the case (Update::SinglePar | Update::Force)
|
||||
bool single_par = flags & Update::SinglePar;
|
||||
updateMetrics(single_par);
|
||||
|
||||
// Don't forget to do check for fitCursor() and multiParSel().
|
||||
fitCursor();
|
||||
multiParSel();
|
||||
|
||||
return make_pair(true, single_par);
|
||||
}
|
||||
|
||||
|
||||
@ -1006,7 +1022,7 @@ void BufferView::workAreaResize(int width, int height)
|
||||
}
|
||||
|
||||
|
||||
bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
std::pair<bool, bool> BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
{
|
||||
//lyxerr << BOOST_CURRENT_FUNCTION << "[ cmd0 " << cmd0 << "]" << endl;
|
||||
|
||||
@ -1016,14 +1032,11 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
|
||||
// E.g. Qt mouse press when no buffer
|
||||
if (!buffer_)
|
||||
return false;
|
||||
|
||||
bool needRedraw = false;
|
||||
return make_pair(false, false);
|
||||
|
||||
LCursor cur(*this);
|
||||
cur.push(buffer_->inset());
|
||||
cur.selection() = cursor_.selection();
|
||||
needRedraw |= cur.selection();
|
||||
|
||||
// Either the inset under the cursor or the
|
||||
// surrounding LyXText will handle this event.
|
||||
@ -1046,7 +1059,6 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
// cur.bv().cursor() = cur; (or similar)
|
||||
if (inset) {
|
||||
inset->dispatch(cur, cmd);
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
// Now dispatch to the temporary cursor. If the real cursor should
|
||||
@ -1054,17 +1066,12 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
if (!cur.result().dispatched())
|
||||
cur.dispatch(cmd);
|
||||
|
||||
if (cur.result().dispatched()) {
|
||||
// Redraw if requested or necessary.
|
||||
if (cur.result().update())
|
||||
needRedraw |= update(Update::FitCursor | Update::Force);
|
||||
else
|
||||
needRedraw |= update(Update::FitCursor | Update::MultiParSel);
|
||||
}
|
||||
// Redraw if requested and necessary.
|
||||
if (cur.result().dispatched() && cur.result().update())
|
||||
return update(cur.result().update());
|
||||
|
||||
// When the above and the inner function are fixed, we can do this:
|
||||
//return needRedraw;
|
||||
return true;
|
||||
return make_pair(false, false);
|
||||
}
|
||||
|
||||
|
||||
@ -1217,7 +1224,7 @@ ViewMetricsInfo const & BufferView::viewMetricsInfo()
|
||||
void BufferView::updateMetrics(bool singlepar)
|
||||
{
|
||||
// Clear out the position cache in case of full screen redraw.
|
||||
//if (!singlepar)
|
||||
if (!singlepar)
|
||||
coord_cache_.clear();
|
||||
|
||||
LyXText & buftext = buffer_->text();
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/signal.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -97,9 +98,11 @@ public:
|
||||
* to do a fitcursor, and to force an update if screen
|
||||
* position changes. \c forceupdate means to force an update
|
||||
* in any case.
|
||||
* \return true if a full updateMetrics() is needed.
|
||||
* \retval (false, xxx) if no redraw is required
|
||||
* \retval (true, true) if a single paragraph redraw is needed
|
||||
* \retval (true, false) if a full redraw is needed
|
||||
*/
|
||||
bool update(Update::flags flags = Update::FitCursor | Update::Force);
|
||||
std::pair<bool, bool> update(Update::flags flags = Update::FitCursor | Update::Force);
|
||||
|
||||
/// move the screen to fit the cursor.
|
||||
/// Only to be called with good y coordinates (after a bv::metrics)
|
||||
@ -167,8 +170,10 @@ public:
|
||||
|
||||
/// dispatch method helper for \c WorkArea
|
||||
/// \sa WorkArea
|
||||
/// \return true if a full redraw is needed
|
||||
bool workAreaDispatch(FuncRequest const & ev);
|
||||
/// \retval (false, xxx) if no redraw is required
|
||||
/// \retval (true, true) if a single paragraph redraw is needed
|
||||
/// \retval (true, false) if a full redraw is needed
|
||||
std::pair<bool, bool> workAreaDispatch(FuncRequest const & ev);
|
||||
|
||||
/// access to anchor.
|
||||
pit_type anchor_ref() const;
|
||||
|
@ -191,7 +191,7 @@ void WorkArea::dispatch(FuncRequest const & cmd0)
|
||||
|
||||
theLyXFunc().setLyXView(&lyx_view_);
|
||||
|
||||
bool needRedraw = buffer_view_->workAreaDispatch(cmd0);
|
||||
std::pair<bool, bool> needRedraw = buffer_view_->workAreaDispatch(cmd0);
|
||||
|
||||
// Skip these when selecting
|
||||
if (cmd0.action != LFUN_MOUSE_MOTION) {
|
||||
@ -209,8 +209,8 @@ void WorkArea::dispatch(FuncRequest const & cmd0)
|
||||
hideCursor();
|
||||
toggleCursor();
|
||||
|
||||
if (needRedraw)
|
||||
redraw();
|
||||
if (needRedraw.first)
|
||||
redraw(needRedraw.second);
|
||||
}
|
||||
|
||||
|
||||
|
@ -293,6 +293,11 @@ void InsetCollapsable::doDispatch(LCursor & cur, FuncRequest & cmd)
|
||||
|
||||
switch (cmd.action) {
|
||||
case LFUN_MOUSE_PRESS:
|
||||
if (cmd.button() == mouse_button::button1 && hitButton(cmd)) {
|
||||
cur.dispatched();
|
||||
cur.noUpdate();
|
||||
break;
|
||||
}
|
||||
if (status() == Inlined)
|
||||
InsetText::doDispatch(cur, cmd);
|
||||
else if (status() == Open && !hitButton(cmd))
|
||||
@ -314,36 +319,35 @@ void InsetCollapsable::doDispatch(LCursor & cur, FuncRequest & cmd)
|
||||
|
||||
case LFUN_MOUSE_RELEASE:
|
||||
if (cmd.button() == mouse_button::button3) {
|
||||
// Open the Inset configuration dialog
|
||||
showInsetDialog(&cur.bv());
|
||||
break;
|
||||
}
|
||||
|
||||
switch (status()) {
|
||||
|
||||
case Collapsed:
|
||||
//lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
|
||||
setStatus(cur, Open);
|
||||
edit(cur, true);
|
||||
cur.bv().cursor() = cur;
|
||||
break;
|
||||
|
||||
case Open: {
|
||||
if (hitButton(cmd)) {
|
||||
//lyxerr << "InsetCollapsable::lfunMouseRelease 2" << endl;
|
||||
setStatus(cur, Collapsed);
|
||||
cur.bv().cursor() = cur;
|
||||
} else {
|
||||
//lyxerr << "InsetCollapsable::lfunMouseRelease 3" << endl;
|
||||
InsetText::doDispatch(cur, cmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Inlined:
|
||||
//lyxerr << "InsetCollapsable::lfunMouseRelease 4" << endl;
|
||||
if (status() == Inlined) {
|
||||
// The mouse click has to be within the inset!
|
||||
InsetText::doDispatch(cur, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd.button() == mouse_button::button1 && hitButton(cmd)) {
|
||||
// Left button is clicked, the user asks to toggle the inset
|
||||
// visual state.
|
||||
cur.dispatched();
|
||||
cur.updateFlags(Update::Force | Update::FitCursor);
|
||||
if (status() == Collapsed) {
|
||||
setStatus(cur, Open);
|
||||
edit(cur, true);
|
||||
}
|
||||
else {
|
||||
setStatus(cur, Collapsed);
|
||||
}
|
||||
cur.bv().cursor() = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
// The mouse click is within the opened inset.
|
||||
InsetText::doDispatch(cur, cmd);
|
||||
break;
|
||||
|
||||
case LFUN_INSET_TOGGLE:
|
||||
|
@ -1715,15 +1715,11 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
// Redraw screen unless explicitly told otherwise.
|
||||
// This also initializes the position cache for all insets
|
||||
// in (at least partially) visible top-level paragraphs.
|
||||
bool needSecondUpdate = false;
|
||||
if (updateFlags != Update::None)
|
||||
needSecondUpdate = view()->update(updateFlags);
|
||||
else
|
||||
needSecondUpdate = view()->fitCursor();
|
||||
std::pair<bool, bool> needSecondUpdate = view()->update(updateFlags);
|
||||
|
||||
if (needSecondUpdate.first)
|
||||
view()->buffer()->changed(needSecondUpdate.second);
|
||||
|
||||
if (needSecondUpdate || updateFlags != Update::None) {
|
||||
view()->buffer()->changed(updateFlags & Update::SinglePar);
|
||||
}
|
||||
lyx_view_->updateStatusBar();
|
||||
|
||||
// if we executed a mutating lfun, mark the buffer as dirty
|
||||
|
@ -96,7 +96,9 @@ public:
|
||||
/// Set font over selection paragraphs and rebreak.
|
||||
void setFont(LCursor & cur, LyXFont const &, bool toggleall = false);
|
||||
|
||||
/// rebreaks the given par
|
||||
/// Rebreaks the given paragraph.
|
||||
/// \retval true if a full screen redraw is needed.
|
||||
/// \retval false if a single paragraph redraw is enough.
|
||||
bool redoParagraph(BufferView &, pit_type pit);
|
||||
|
||||
/// returns pos in given par at given x coord
|
||||
|
25
src/text.C
25
src/text.C
@ -1153,8 +1153,12 @@ void LyXText::breakParagraph(LCursor & cur, bool keep_layout)
|
||||
// Because of the mix between the model (the paragraph contents) and the
|
||||
// view (the paragraph breaking in rows, we have to do this here before
|
||||
// the setCursor() call below.
|
||||
redoParagraph(cur.bv(), cpit);
|
||||
redoParagraph(cur.bv(), cpit + 1);
|
||||
bool changed_height = redoParagraph(cur.bv(), cpit);
|
||||
changed_height |= redoParagraph(cur.bv(), cpit + 1);
|
||||
if (changed_height)
|
||||
// A singlePar update is not enough in this case.
|
||||
cur.updateFlags(Update::Force);
|
||||
|
||||
|
||||
// This check is necessary. Otherwise the new empty paragraph will
|
||||
// be deleted automatically. And it is more friendly for the user!
|
||||
@ -1253,7 +1257,9 @@ void LyXText::insertChar(LCursor & cur, char_type c)
|
||||
// FIXME: Inserting a character has nothing to do with setting a cursor.
|
||||
// Because of the mix between the model (the paragraph contents) and the
|
||||
// view (the paragraph breaking in rows, we have to do this here.
|
||||
redoParagraph(cur.bv(), cur.pit());
|
||||
if (redoParagraph(cur.bv(), cur.pit()))
|
||||
// A singlePar update is not enough in this case.
|
||||
cur.updateFlags(Update::Force);
|
||||
setCursor(cur, cur.pit(), cur.pos() + 1, false, cur.boundary());
|
||||
charInserted();
|
||||
}
|
||||
@ -1671,13 +1677,16 @@ bool LyXText::erase(LCursor & cur)
|
||||
} else
|
||||
needsUpdate = dissolveInset(cur);
|
||||
|
||||
// Make sure the cursor is correct. Is this really needed?
|
||||
// FIXME: Inserting characters has nothing to do with setting a cursor.
|
||||
// Because of the mix between the model (the paragraph contents)
|
||||
// and the view (the paragraph breaking in rows, we have to do this
|
||||
// here before the setCursorIntern() call.
|
||||
if (needsUpdate) {
|
||||
redoParagraph(cur.bv(), cur.pit());
|
||||
if (redoParagraph(cur.bv(), cur.pit()))
|
||||
// A singlePar update is not enough in this case.
|
||||
cur.updateFlags(Update::Force);
|
||||
// Make sure the cursor is correct. Is this really needed?
|
||||
// No, not really... at least not here!
|
||||
setCursorIntern(cur, cur.pit(), cur.pos());
|
||||
}
|
||||
|
||||
@ -1786,7 +1795,9 @@ bool LyXText::backspace(LCursor & cur)
|
||||
// Because of the mix between the model (the paragraph contents)
|
||||
// and the view (the paragraph breaking in rows, we have to do this
|
||||
// here before the setCursor() call.
|
||||
redoParagraph(cur.bv(), cur.pit());
|
||||
if (redoParagraph(cur.bv(), cur.pit()))
|
||||
// A singlePar update is not enough in this case.
|
||||
cur.updateFlags(Update::Force);
|
||||
setCursor(cur, cur.pit(), cur.pos(), false, cur.boundary());
|
||||
|
||||
return needsUpdate;
|
||||
@ -1929,7 +1940,7 @@ bool LyXText::redoParagraph(BufferView & bv, pit_type const pit)
|
||||
dim.asc += par.rows()[0].ascent();
|
||||
dim.des -= par.rows()[0].ascent();
|
||||
|
||||
bool const same = dim == par.dim();
|
||||
bool const same = dim.height() == par.dim().height();
|
||||
|
||||
par.dim() = dim;
|
||||
//lyxerr << "redoParagraph: " << par.rows().size() << " rows\n";
|
||||
|
34
src/text3.C
34
src/text3.C
@ -305,6 +305,11 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
|
||||
{
|
||||
lyxerr[Debug::ACTION] << "LyXText::dispatch: cmd: " << cmd << endl;
|
||||
|
||||
// FIXME: We use the update flag to indicates wether a singlePar or a
|
||||
// full screen update is needed. We reset it here but shall we restore it
|
||||
// at the end?
|
||||
cur.noUpdate();
|
||||
|
||||
BOOST_ASSERT(cur.text() == this);
|
||||
BufferView * bv = &cur.bv();
|
||||
CursorSlice oldTopSlice = cur.top();
|
||||
@ -988,6 +993,11 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
|
||||
lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"));
|
||||
}
|
||||
|
||||
if (cmd.button() == mouse_button::button1) {
|
||||
needsUpdate = false;
|
||||
cur.noUpdate();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1037,8 +1047,12 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
|
||||
break;
|
||||
|
||||
// finish selection
|
||||
if (cmd.button() == mouse_button::button1)
|
||||
theSelection().haveSelection(cur.selection());
|
||||
if (cmd.button() == mouse_button::button1) {
|
||||
if (cur.selection())
|
||||
theSelection().haveSelection(cur.selection());
|
||||
needsUpdate = false;
|
||||
cur.noUpdate();
|
||||
}
|
||||
|
||||
bv->switchKeyMap();
|
||||
break;
|
||||
@ -1474,6 +1488,19 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
|
||||
}
|
||||
|
||||
needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection();
|
||||
|
||||
// FIXME: The cursor flag is reset two lines below
|
||||
// so we need to check here if some of the LFUN did touch that.
|
||||
// for now only LyXText::erase() and LyXText::backspace() do that.
|
||||
// The plan is to verify all the LFUNs and then to remove this
|
||||
// singleParUpdate boolean altogether.
|
||||
if (cur.result().update() & Update::Force) {
|
||||
singleParUpdate = false;
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// FIXME: the following code should go in favor of fine grained
|
||||
// update flag treatment.
|
||||
if (singleParUpdate)
|
||||
// Inserting characters does not change par height
|
||||
if (cur.bottom().paragraph().dim().height()
|
||||
@ -1485,10 +1512,11 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
|
||||
return;
|
||||
} else
|
||||
needsUpdate = true;
|
||||
|
||||
if (!needsUpdate
|
||||
&& &oldTopSlice.inset() == &cur.inset()
|
||||
&& oldTopSlice.idx() == cur.idx()
|
||||
&& !sel
|
||||
&& !sel // sel is a backup of cur.selection() at the biginning of the function.
|
||||
&& !cur.selection())
|
||||
cur.noUpdate();
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user