]> git.lyx.org Git - lyx.git/commitdiff
Optimize drawing.
authorAbdelrazak Younes <younes@lyx.org>
Fri, 17 Nov 2006 17:42:52 +0000 (17:42 +0000)
committerAbdelrazak Younes <younes@lyx.org>
Fri, 17 Nov 2006 17:42:52 +0000 (17:42 +0000)
* 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

src/BufferView.C
src/BufferView.h
src/frontends/WorkArea.C
src/insets/insetcollapsable.C
src/lyxfunc.C
src/lyxtext.h
src/text.C
src/text3.C

index a5f7956928ef3ff0e2cad8b09813d6db2885ad1d..d1d768ac36b652dc994091710f066efa08d17265 100644 (file)
@@ -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();
index 7042440fdb6f3f2bcae67b98c469542853f4015d..0e5f9102b090019644ec6480639742da0d55f9b1 100644 (file)
@@ -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;
index 3deac37bd88c773889c7a29d5584b7702b0d8ade..c2b8faf25c2638ed82d55d4da4f1fa7d6c958af2 100644 (file)
@@ -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);
 }
 
 
index 6c1f127dfc61f400bcf362c487265322c69275fd..3d4434aa79e138ec868fac88b959d75115e279f8 100644 (file)
@@ -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;
+               if (status() == Inlined) {
+                       // The mouse click has to be within the inset!
+                       InsetText::doDispatch(cur, cmd);
                        break;
+               }
 
-               case Open: {
-                       if (hitButton(cmd)) {
-                               //lyxerr << "InsetCollapsable::lfunMouseRelease 2" << endl;
+               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;
-                       } else {
-                               //lyxerr << "InsetCollapsable::lfunMouseRelease 3" << endl;
-                               InsetText::doDispatch(cur, cmd);
                        }
+                       cur.bv().cursor() = cur;
                        break;
                }
 
-               case Inlined:
-                       //lyxerr << "InsetCollapsable::lfunMouseRelease 4" << endl;
-                       InsetText::doDispatch(cur, cmd);
-                       break;
-               }
+               // The mouse click is within the opened inset.
+               InsetText::doDispatch(cur, cmd);
                break;
 
        case LFUN_INSET_TOGGLE:
index 85dfc6cf5520e711bea97fd365147f4d9937c10a..7de71684d5d8267f2de39d929e5b4b88325e2ce3 100644 (file)
@@ -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
index fab70b78cf49d79416657bcfb6b720923f732bdf..5bf93d8278def4cd6aa4c2fee3d53d6eeb340f40 100644 (file)
@@ -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
index 40349eacb9b0ccafae7e1ac0fa72f92bfff6cf26..7ca49fe69e88754bee75bb0fcdb28d7305d990fd 100644 (file)
@@ -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";
index 00bb118d73685d72dbbc7fa151be8799fb01d05e..9fb01eda4f153259b3307df1a09148b06d5424b3 100644 (file)
@@ -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