- rework update handling, make cursor movement faster,

fixing lots of navigation problems.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15470 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Asger Ottar Alstrup 2006-10-22 11:46:36 +00:00
parent fa299aa246
commit 37e164c6f9
11 changed files with 90 additions and 88 deletions

View File

@ -18,7 +18,7 @@
#include "coordcache.h" #include "coordcache.h"
#include "cursor.h" #include "cursor.h"
#include "metricsinfo.h" #include "metricsinfo.h"
#include "UpdateFlags.h"
#include "support/types.h" #include "support/types.h"
#include <boost/utility.hpp> #include <boost/utility.hpp>
@ -41,26 +41,6 @@ class LyXText;
class ParIterator; class ParIterator;
class ViewMetricsInfo; class ViewMetricsInfo;
namespace Update {
enum flags {
FitCursor = 1,
Force = 2,
SinglePar = 4,
MultiParSel = 8
};
inline flags operator|(flags const f, flags const g)
{
return static_cast<flags>(int(f) | int(g));
}
inline flags operator&(flags const f, flags const g)
{
return static_cast<flags>(int(f) & int(g));
}
} // namespace
/// Scrollbar Parameters /// Scrollbar Parameters
struct ScrollbarParameters struct ScrollbarParameters
{ {

28
src/UpdateFlags.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef UPDATE_FLAGS_H
#define UPDATE_FLAGS_H
namespace lyx {
namespace Update {
enum flags {
None = 0,
FitCursor = 1,
Force = 2,
SinglePar = 4,
MultiParSel = 8
};
inline flags operator|(flags const f, flags const g)
{
return static_cast<flags>(int(f) | int(g));
}
inline flags operator&(flags const f, flags const g)
{
return static_cast<flags>(int(f) & int(g));
}
} // namespace
} // namespace lyx
#endif

View File

@ -285,7 +285,7 @@ void LCursor::dispatch(FuncRequest const & cmd0)
// The common case is 'LFUN handled, need update', so make the // The common case is 'LFUN handled, need update', so make the
// LFUN handler's life easier by assuming this as default value. // LFUN handler's life easier by assuming this as default value.
// The handler can reset the update and val flags if necessary. // The handler can reset the update and val flags if necessary.
disp_.update(true); disp_.update(Update::FitCursor | Update::Force);
disp_.dispatched(true); disp_.dispatched(true);
inset().dispatch(*this, cmd); inset().dispatch(*this, cmd);
if (disp_.dispatched()) if (disp_.dispatched())
@ -296,7 +296,7 @@ void LCursor::dispatch(FuncRequest const & cmd0)
if (!disp_.dispatched()) { if (!disp_.dispatched()) {
lyxerr[Debug::DEBUG] << "RESTORING OLD CURSOR!" << endl; lyxerr[Debug::DEBUG] << "RESTORING OLD CURSOR!" << endl;
operator=(safe); operator=(safe);
disp_.update(false); disp_.update(Update::None);
disp_.dispatched(false); disp_.dispatched(false);
} }
} }
@ -527,14 +527,15 @@ void LCursor::info(odocstream & os) const
} }
void LCursor::selHandle(bool sel) bool LCursor::selHandle(bool sel)
{ {
//lyxerr << "LCursor::selHandle" << endl; //lyxerr << "LCursor::selHandle" << endl;
if (sel == selection()) if (sel == selection())
return; return false;
resetAnchor(); resetAnchor();
selection() = sel; selection() = sel;
return true;
} }
@ -1212,15 +1213,15 @@ void LCursor::dispatched()
} }
void LCursor::needsUpdate() void LCursor::updateFlags(Update::flags f)
{ {
disp_.update(true); disp_.update(f);
} }
void LCursor::noUpdate() void LCursor::noUpdate()
{ {
disp_.update(false); disp_.update(Update::None);
} }

View File

@ -86,7 +86,7 @@ public:
/// access start of selection /// access start of selection
DocIterator selectionEnd() const; DocIterator selectionEnd() const;
/// ///
void selHandle(bool selecting); bool selHandle(bool selecting);
// //
docstring selectionAsString(bool label) const; docstring selectionAsString(bool label) const;
/// ///
@ -158,8 +158,8 @@ public:
void undispatched(); void undispatched();
/// the event was already dispatched /// the event was already dispatched
void dispatched(); void dispatched();
/// call update() when done /// Set which update should be done
void needsUpdate(); void updateFlags(Update::flags f);
/** /**
* don't call update() when done * don't call update() when done
* *

View File

@ -13,28 +13,30 @@
#ifndef DISPATCH_RESULT_H #ifndef DISPATCH_RESULT_H
#define DISPATCH_RESULT_H #define DISPATCH_RESULT_H
#include "UpdateFlags.h"
namespace lyx { namespace lyx {
/// Maybe this can go entirely /// Maybe this can go entirely
class DispatchResult { class DispatchResult {
public: public:
/// ///
DispatchResult() : dispatched_(false), update_(false) {} DispatchResult() : dispatched_(false), update_(Update::None) {}
/// ///
DispatchResult(bool disp, bool upd) : dispatched_(disp), update_(upd) {} DispatchResult(bool disp, Update::flags f) : dispatched_(disp), update_(f) {}
// //
bool dispatched() const { return dispatched_; } bool dispatched() const { return dispatched_; }
/// ///
void dispatched(bool disp) { dispatched_ = disp; } void dispatched(bool disp) { dispatched_ = disp; }
/// ///
bool update() const { return update_; } Update::flags update() const { return update_; }
/// ///
void update(bool up) { update_ = up; } void update(Update::flags f) { update_ = f; }
private: private:
/// was the event fully dispatched? /// was the event fully dispatched?
bool dispatched_; bool dispatched_;
/// do we need to redraw the screen afterwards? /// do we need to redraw the screen afterwards?
bool update_; Update::flags update_;
}; };

View File

@ -140,6 +140,7 @@ void ControlDocument::dispatchParams()
"assign branch")); "assign branch"));
} }
// update the bufferview // update the bufferview
// If we used an LFUN, we would not need that
kernel().bufferview()->update(); kernel().bufferview()->update();
} }

View File

@ -306,6 +306,7 @@ void ControlSpellchecker::replace(string const & replacement)
BufferView & bufferview = *kernel().bufferview(); BufferView & bufferview = *kernel().bufferview();
cap::replaceSelectionWithString(bufferview.cursor(), replacement, true); cap::replaceSelectionWithString(bufferview.cursor(), replacement, true);
kernel().buffer().markDirty(); kernel().buffer().markDirty();
// If we used an LFUN, we would not need that
bufferview.update(); bufferview.update();
// fix up the count // fix up the count
--count_; --count_;

View File

@ -125,7 +125,7 @@ InsetBase::Code InsetBase::translate(std::string const & name)
void InsetBase::dispatch(LCursor & cur, FuncRequest & cmd) void InsetBase::dispatch(LCursor & cur, FuncRequest & cmd)
{ {
cur.needsUpdate(); cur.updateFlags(Update::Force | Update::FitCursor);
cur.dispatched(); cur.dispatched();
doDispatch(cur, cmd); doDispatch(cur, cmd);
} }

View File

@ -1251,7 +1251,7 @@ void InsetTabular::resetPos(LCursor & cur) const
scx_ = 0; scx_ = 0;
} }
cur.needsUpdate(); cur.updateFlags(Update::Force | Update::FitCursor);
InsetTabularMailer(*this).updateDialog(&bv); InsetTabularMailer(*this).updateDialog(&bv);
} }

View File

@ -729,9 +729,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
// redraw the screen at the end (first of the two drawing steps). // redraw the screen at the end (first of the two drawing steps).
//This is done unless explicitely requested otherwise //This is done unless explicitely requested otherwise
bool update = true; Update::flags updateFlags = Update::FitCursor;
// also do the second redrawing step. Only done if requested.
bool updateforce = false;
FuncStatus const flag = getStatus(cmd); FuncStatus const flag = getStatus(cmd);
if (!flag.enabled()) { if (!flag.enabled()) {
@ -819,12 +817,12 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
lyx_view_->message(str + _(" done.")); lyx_view_->message(str + _(" done."));
} else } else
writeAs(lyx_view_->buffer()); writeAs(lyx_view_->buffer());
update = false; updateFlags = Update::None;
break; break;
case LFUN_BUFFER_WRITE_AS: case LFUN_BUFFER_WRITE_AS:
writeAs(lyx_view_->buffer(), argument); writeAs(lyx_view_->buffer(), argument);
update = false; updateFlags = Update::None;
break; break;
case LFUN_BUFFER_RELOAD: { case LFUN_BUFFER_RELOAD: {
@ -1425,7 +1423,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
} }
// ideally, the update flag should be set by the insets, // ideally, the update flag should be set by the insets,
// but this is not possible currently // but this is not possible currently
updateforce = true; updateFlags = Update::Force | Update::FitCursor;
break; break;
} }
@ -1449,7 +1447,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
it->dispatch(tmpcur, fr); it->dispatch(tmpcur, fr);
} }
} }
updateforce = true; updateFlags = Update::Force | Update::FitCursor;
break; break;
} }
@ -1558,7 +1556,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
buffer->errors("Class Switch"); buffer->errors("Class Switch");
updateLabels(*buffer); updateLabels(*buffer);
updateforce = true; updateFlags = Update::Force | Update::FitCursor;
break; break;
} }
@ -1589,10 +1587,10 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
default: { default: {
view()->cursor().dispatch(cmd); view()->cursor().dispatch(cmd);
update = false; updateFlags = view()->cursor().result().update();
updateforce |= view()->cursor().result().update();
if (!view()->cursor().result().dispatched()) if (!view()->cursor().result().dispatched())
updateforce |= view()->dispatch(cmd); if (view()->dispatch(cmd))
updateFlags = Update::Force | Update::FitCursor;
break; break;
} }
} }
@ -1601,13 +1599,16 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
// Redraw screen unless explicitly told otherwise. // Redraw screen unless explicitly told otherwise.
// This also initializes the position cache for all insets // This also initializes the position cache for all insets
// in (at least partially) visible top-level paragraphs. // in (at least partially) visible top-level paragraphs.
if (updateforce) bool needSecondUpdate = false;
view()->update(Update::FitCursor | Update::Force); if (updateFlags != Update::None)
else if (update) view()->update(updateFlags);
view()->update(Update::FitCursor); else
needSecondUpdate = view()->fitCursor();
if (needSecondUpdate || updateFlags != Update::None) {
view()->buffer()->changed(); view()->buffer()->changed();
lyx_view_->updateStatusBar(); lyx_view_->updateStatusBar();
}
// if we executed a mutating lfun, mark the buffer as dirty // if we executed a mutating lfun, mark the buffer as dirty
if (flag.enabled() if (flag.enabled()

View File

@ -283,14 +283,6 @@ bool doInsertInset(LCursor & cur, LyXText * text,
} }
void update(LCursor & cur)
{
//we don't call update(true, false) directly to save a metrics call
if (cur.bv().fitCursor())
cur.bv().update(Update::Force);
}
} // anon namespace } // anon namespace
@ -404,7 +396,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_BUFFER_BEGIN: case LFUN_BUFFER_BEGIN:
case LFUN_BUFFER_BEGIN_SELECT: case LFUN_BUFFER_BEGIN_SELECT:
cur.selHandle(cmd.action == LFUN_BUFFER_BEGIN_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_BEGIN_SELECT);
if (cur.depth() == 1) { if (cur.depth() == 1) {
needsUpdate |= cursorTop(cur); needsUpdate |= cursorTop(cur);
} else { } else {
@ -414,7 +406,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_BUFFER_END: case LFUN_BUFFER_END:
case LFUN_BUFFER_END_SELECT: case LFUN_BUFFER_END_SELECT:
cur.selHandle(cmd.action == LFUN_BUFFER_END_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_END_SELECT);
if (cur.depth() == 1) { if (cur.depth() == 1) {
needsUpdate |= cursorBottom(cur); needsUpdate |= cursorBottom(cur);
} else { } else {
@ -426,7 +418,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_CHAR_FORWARD_SELECT: case LFUN_CHAR_FORWARD_SELECT:
//lyxerr << BOOST_CURRENT_FUNCTION //lyxerr << BOOST_CURRENT_FUNCTION
// << " LFUN_CHAR_FORWARD[SEL]:\n" << cur << endl; // << " LFUN_CHAR_FORWARD[SEL]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT);
if (isRTL(cur.paragraph())) if (isRTL(cur.paragraph()))
needsUpdate |= cursorLeft(cur); needsUpdate |= cursorLeft(cur);
else else
@ -442,7 +434,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_CHAR_BACKWARD: case LFUN_CHAR_BACKWARD:
case LFUN_CHAR_BACKWARD_SELECT: case LFUN_CHAR_BACKWARD_SELECT:
//lyxerr << "handle LFUN_CHAR_BACKWARD[_SELECT]:\n" << cur << endl; //lyxerr << "handle LFUN_CHAR_BACKWARD[_SELECT]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT);
if (isRTL(cur.paragraph())) if (isRTL(cur.paragraph()))
needsUpdate |= cursorRight(cur); needsUpdate |= cursorRight(cur);
else else
@ -457,11 +449,11 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_UP: case LFUN_UP:
case LFUN_UP_SELECT: case LFUN_UP_SELECT:
update(cur);
//lyxerr << "handle LFUN_UP[SEL]:\n" << cur << endl; //lyxerr << "handle LFUN_UP[SEL]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_UP_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_UP_SELECT);
needsUpdate |= cursorUp(cur); needsUpdate |= cursorUp(cur);
if (!needsUpdate && oldTopSlice == cur.top() if (!needsUpdate && oldTopSlice == cur.top()
&& cur.boundary() == oldBoundary) { && cur.boundary() == oldBoundary) {
cur.undispatched(); cur.undispatched();
@ -471,10 +463,10 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_DOWN: case LFUN_DOWN:
case LFUN_DOWN_SELECT: case LFUN_DOWN_SELECT:
update(cur);
//lyxerr << "handle LFUN_DOWN[SEL]:\n" << cur << endl; //lyxerr << "handle LFUN_DOWN[SEL]:\n" << cur << endl;
cur.selHandle(cmd.action == LFUN_DOWN_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
needsUpdate |= cursorDown(cur); needsUpdate |= cursorDown(cur);
if (!needsUpdate && oldTopSlice == cur.top() && if (!needsUpdate && oldTopSlice == cur.top() &&
cur.boundary() == oldBoundary) cur.boundary() == oldBoundary)
{ {
@ -485,20 +477,19 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_UP:
case LFUN_PARAGRAPH_UP_SELECT: case LFUN_PARAGRAPH_UP_SELECT:
cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT);
needsUpdate |= cursorUpParagraph(cur); needsUpdate |= cursorUpParagraph(cur);
break; break;
case LFUN_PARAGRAPH_DOWN: case LFUN_PARAGRAPH_DOWN:
case LFUN_PARAGRAPH_DOWN_SELECT: case LFUN_PARAGRAPH_DOWN_SELECT:
cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT);
needsUpdate |= cursorDownParagraph(cur); needsUpdate |= cursorDownParagraph(cur);
break; break;
case LFUN_SCREEN_UP: case LFUN_SCREEN_UP:
case LFUN_SCREEN_UP_SELECT: case LFUN_SCREEN_UP_SELECT:
update(cur); needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_UP_SELECT);
cur.selHandle(cmd.action == LFUN_SCREEN_UP_SELECT);
if (cur.pit() == 0 && cur.textRow().pos() == 0) { if (cur.pit() == 0 && cur.textRow().pos() == 0) {
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_UP); cmd = FuncRequest(LFUN_FINISHED_UP);
@ -509,8 +500,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_SCREEN_DOWN: case LFUN_SCREEN_DOWN:
case LFUN_SCREEN_DOWN_SELECT: case LFUN_SCREEN_DOWN_SELECT:
update(cur); needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_DOWN_SELECT);
cur.selHandle(cmd.action == LFUN_SCREEN_DOWN_SELECT);
if (cur.pit() == cur.lastpit() if (cur.pit() == cur.lastpit()
&& cur.textRow().endpos() == cur.lastpos()) { && cur.textRow().endpos() == cur.lastpos()) {
cur.undispatched(); cur.undispatched();
@ -522,21 +512,19 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_LINE_BEGIN: case LFUN_LINE_BEGIN:
case LFUN_LINE_BEGIN_SELECT: case LFUN_LINE_BEGIN_SELECT:
update(cur); needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_BEGIN_SELECT);
cur.selHandle(cmd.action == LFUN_LINE_BEGIN_SELECT);
needsUpdate |= cursorHome(cur); needsUpdate |= cursorHome(cur);
break; break;
case LFUN_LINE_END: case LFUN_LINE_END:
case LFUN_LINE_END_SELECT: case LFUN_LINE_END_SELECT:
update(cur); needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_END_SELECT);
cur.selHandle(cmd.action == LFUN_LINE_END_SELECT);
needsUpdate |= cursorEnd(cur); needsUpdate |= cursorEnd(cur);
break; break;
case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD:
case LFUN_WORD_FORWARD_SELECT: case LFUN_WORD_FORWARD_SELECT:
cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT);
if (isRTL(cur.paragraph())) if (isRTL(cur.paragraph()))
needsUpdate |= cursorLeftOneWord(cur); needsUpdate |= cursorLeftOneWord(cur);
else else
@ -545,7 +533,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_WORD_BACKWARD: case LFUN_WORD_BACKWARD:
case LFUN_WORD_BACKWARD_SELECT: case LFUN_WORD_BACKWARD_SELECT:
cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT);
if (isRTL(cur.paragraph())) if (isRTL(cur.paragraph()))
needsUpdate |= cursorRightOneWord(cur); needsUpdate |= cursorRightOneWord(cur);
else else
@ -1473,15 +1461,15 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
break; break;
} }
needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection();
if (singleParUpdate) if (singleParUpdate)
// Inserting characters does not change par height // Inserting characters does not change par height
if (cur.bottom().paragraph().dim().height() if (cur.bottom().paragraph().dim().height()
== olddim.height()) { == olddim.height()) {
// if so, update _only_ this paragraph // if so, update _only_ this paragraph
cur.bv().update(Update::SinglePar | cur.updateFlags(Update::SinglePar |
Update::FitCursor | Update::FitCursor |
Update::MultiParSel); Update::MultiParSel);
cur.noUpdate();
return; return;
} else } else
needsUpdate = true; needsUpdate = true;
@ -1492,7 +1480,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
&& !cur.selection()) && !cur.selection())
cur.noUpdate(); cur.noUpdate();
else else
cur.needsUpdate(); cur.updateFlags(Update::Force | Update::FitCursor);
} }