I tried recently to get rid og all-insets-toggle in favour of inset-forall. This works, but I noticed at this occasion that the performance of inset-forall is horrible, in particular because the screen is redrawn for each inset. This is definitely wrong.
What seems to be a good solution is to define a new LyXFunc::dispatch(FuncRequest, DispatchResult) that just returns what needs to be done, and add change the normal LyXFunc::dispatch to be a wrapper around it that does the screen updates. This is what I started in the attached patch. I have some questions before I proceed: * is that the right direction? (the next steps to make it useful is of course to pass a DispatchResult object to all dispatch routines) * there are some functions (up, down) that require correct metrics. What shall I do if the screen is not updated? Shall we somehow mark that these functions rely on metrics and have a mechanism to compute them if needed? I would need some help with this, I think. * in inset-forall, how do I build the final DispatchResult as a function of the elementary ones? Some kind of logical or? * should LyXFunc::dispatch(FuncRequest, DispatchResult) modify the existing DispatchResult of reset it to forget old contents? Questions, questions... JMarc
svndiff Index: src/LyXFunc.h =================================================================== --- src/LyXFunc.h (révision 33078) +++ src/LyXFunc.h (copie de travail) @@ -24,6 +24,7 @@ namespace lyx { class Buffer; class BufferView; +class DispatchResult; class DocumentClass; class FuncRequest; class FuncStatus; @@ -46,7 +47,11 @@ public: /// explicit LyXFunc(); - /// LyX dispatcher, executes lyx actions. + /// LyX dispatcher: executes lyx actions and returns result. + void dispatch(FuncRequest const &, DispatchResult &); + + /// LyX dispatcher: executes lyx actions and does necessary + /// screen updates depending on results. void dispatch(FuncRequest const &); /// Index: src/LyXFunc.cpp =================================================================== --- src/LyXFunc.cpp (révision 33078) +++ src/LyXFunc.cpp (copie de travail) @@ -340,6 +340,32 @@ static docstring sendDispatchMessage(doc void LyXFunc::dispatch(FuncRequest const & cmd) { + DispatchResult dr; + // redraw the screen at the end (first of the two drawing steps). + //This is done unless explicitely requested otherwise + dr.update(Update::FitCursor); + dispatch(cmd, dr); + + LyXView * lv = theApp()->currentWindow(); + if (lv && lv->currentBufferView()) { + // BufferView::update() updates the ViewMetricsInfo and + // also initializes the position cache for all insets in + // (at least partially) visible top-level paragraphs. + // We will redraw the screen only if needed. + lv->currentBufferView()->processUpdateFlags(dr.update()); + + // Do we have a selection? + theSelection().haveSelection( + lv->currentBufferView()->cursor().selection()); + + // update gui + lv->restartCursor(); + } +} + + +void LyXFunc::dispatch(FuncRequest const & cmd, DispatchResult & dr) +{ string const argument = to_utf8(cmd.argument()); FuncCode const action = cmd.action; @@ -350,10 +376,6 @@ void LyXFunc::dispatch(FuncRequest const errorstat = false; dispatch_buffer.erase(); - // redraw the screen at the end (first of the two drawing steps). - //This is done unless explicitely requested otherwise - Update::flags updateFlags = Update::FitCursor; - LyXView * lv = theApp()->currentWindow(); FuncStatus const flag = getStatus(cmd); @@ -362,9 +384,12 @@ void LyXFunc::dispatch(FuncRequest const LYXERR(Debug::ACTION, "LyXFunc::dispatch: " << lyxaction.getActionName(action) << " [" << action << "] is disabled at this location"); + //FIXME: pass this using the DispatchResult object setErrorMessage(flag.message()); if (lv) lv->restartCursor(); + dr.dispatched(false); + dr.update(Update::None); } else { switch (action) { @@ -481,7 +506,7 @@ void LyXFunc::dispatch(FuncRequest const case LFUN_BOOKMARK_GOTO: // go to bookmark, open unopened file and switch to buffer if necessary gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true); - updateFlags = Update::FitCursor; + dr.update(Update::FitCursor); break; case LFUN_BOOKMARK_CLEAR: @@ -493,8 +518,6 @@ void LyXFunc::dispatch(FuncRequest const break; default: - DispatchResult dr; - LASSERT(theApp(), /**/); // Let the frontend dispatch its own actions. theApp()->dispatch(cmd, dr); @@ -507,10 +530,11 @@ void LyXFunc::dispatch(FuncRequest const break; // Let the current LyXView dispatch its own actions. + //FIXME: pass dr to LyXView::dispatch if (lv->dispatch(cmd)) { BufferView * bv = lv->currentBufferView(); if (bv) - updateFlags = bv->cursor().result().update(); + dr = bv->cursor().result(); break; } @@ -520,31 +544,24 @@ void LyXFunc::dispatch(FuncRequest const // Let the current BufferView dispatch its own actions. if (bv->dispatch(cmd)) { // The BufferView took care of its own updates if needed. - updateFlags = Update::None; + //FIXME: make it pass actions as a DispatchResult instead + dr.update(Update::None); break; } BufferView * doc_bv = lv->documentBufferView(); // Try with the document BufferView dispatch if any. if (doc_bv && doc_bv->dispatch(cmd)) { - updateFlags = Update::None; + dr.update(Update::None); break; } // OK, so try the current Buffer itself... bv->buffer().dispatch(cmd, dr); - if (dr.dispatched()) { - updateFlags = dr.update(); - break; - } + // and with the document Buffer. - if (doc_bv) { + if (doc_bv) doc_bv->buffer().dispatch(cmd, dr); - if (dr.dispatched()) { - updateFlags = dr.update(); - break; - } - } // Let the current Cursor dispatch its own actions. Cursor old = bv->cursor(); @@ -573,7 +590,7 @@ void LyXFunc::dispatch(FuncRequest const lv->updateCompletion(bv->cursor(), false, false); } - updateFlags = bv->cursor().result().update(); + dr = bv->cursor().result(); } // if we executed a mutating lfun, mark the buffer as dirty @@ -584,21 +601,6 @@ void LyXFunc::dispatch(FuncRequest const && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer) && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly)) lv->currentBufferView()->buffer().markDirty(); - - if (lv && lv->currentBufferView()) { - // BufferView::update() updates the ViewMetricsInfo and - // also initializes the position cache for all insets in - // (at least partially) visible top-level paragraphs. - // We will redraw the screen only if needed. - lv->currentBufferView()->processUpdateFlags(updateFlags); - - // Do we have a selection? - theSelection().haveSelection( - lv->currentBufferView()->cursor().selection()); - - // update gui - lv->restartCursor(); - } } if (lv) { // Some messages may already be translated, so we cannot use _()