]> git.lyx.org Git - features.git/blobdiff - src/BufferView.cpp
- Transfer rowpainter.cpp:paintPar() to TextMetrics::drawParagraph()
[features.git] / src / BufferView.cpp
index 5d41d1b1624e58fbd7363754a000bd9532abd5bc..c5a1375a72a96ec3c3b2ff7ba6b90670f48e5578 100644 (file)
@@ -21,6 +21,7 @@
 #include "BufferList.h"
 #include "BufferParams.h"
 #include "bufferview_funcs.h"
+#include "callback.h" // added for Dispatch functions
 #include "CoordCache.h"
 #include "CutAndPaste.h"
 #include "debug.h"
 #include "InsetIterator.h"
 #include "Language.h"
 #include "LaTeXFeatures.h"
-#include "callback.h" // added for Dispatch functions
 #include "LyX.h"
 #include "lyxfind.h"
 #include "LyXFunc.h"
 #include "Layout.h"
-#include "Text.h"
-#include "TextClass.h"
 #include "LyXRC.h"
-#include "Session.h"
+#include "MetricsInfo.h"
 #include "Paragraph.h"
 #include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
 #include "ParIterator.h"
+#include "rowpainter.h"
+#include "Session.h"
 #include "TexRow.h"
+#include "Text.h"
+#include "TextClass.h"
 #include "toc.h"
 #include "Undo.h"
 #include "VSpace.h"
 #include "WordLangTuple.h"
-#include "MetricsInfo.h"
 
 #include "insets/InsetBibtex.h"
 #include "insets/InsetCommand.h" // ChangeRefs
@@ -63,6 +64,7 @@
 #include "frontends/alert.h"
 #include "frontends/FileDialog.h"
 #include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
 #include "frontends/Selection.h"
 
 #include "graphics/Previews.h"
@@ -126,7 +128,7 @@ BufferView::BufferView(Buffer & buf)
        : width_(0), height_(0), buffer_(buf), wh_(0),
          cursor_(*this),
          multiparsel_cache_(false), anchor_ref_(0), offset_ref_(0),
-         intl_(new Intl), last_inset_(0)
+         need_centering_(false), intl_(new Intl), last_inset_(0)
 {
        xsel_cache_.set = false;
        intl_->initKeyMapper(lyxrc.use_kbmap);
@@ -408,9 +410,12 @@ void BufferView::saveBookmark(unsigned int idx)
 }
 
 
-boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom_pit, pos_type bottom_pos,
+bool BufferView::moveToPosition(pit_type bottom_pit, pos_type bottom_pos,
        int top_id, pos_type top_pos)
 {
+       bool success = false;
+       DocIterator doc_it;
+
        cursor_.clearSelection();
 
        // if a valid par_id is given, try it first
@@ -419,24 +424,23 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
        if (top_id > 0) {
                ParIterator par = buffer_.getParFromID(top_id);
                if (par != buffer_.par_iterator_end()) {
-                       DocIterator dit = makeDocIterator(par, min(par->size(), top_pos));
+                       doc_it = makeDocIterator(par, min(par->size(), top_pos));
                        // Some slices of the iterator may not be
                        // reachable (e.g. closed collapsable inset)
                        // so the dociterator may need to be
                        // shortened. Otherwise, setCursor may crash
                        // lyx when the cursor can not be set to these
                        // insets.
-                       size_t const n = dit.depth();
+                       size_t const n = doc_it.depth();
                        for (size_t i = 0; i < n; ++i)
-                               if (dit[i].inset().editable() != Inset::HIGHLY_EDITABLE) {
-                                       dit.resize(i);
+                               if (doc_it[i].inset().editable() != Inset::HIGHLY_EDITABLE) {
+                                       doc_it.resize(i);
                                        break;
                                }
-                       setCursor(dit);
-                       // Note: return bottom (document) level pit.
-                       return boost::make_tuple(cursor_.bottom().pit(), cursor_.bottom().pos(), top_id);
+                       success = true;
                }
        }
+
        // if top_id == 0, or searching through top_id failed
        // This is the case for a 'restored' bookmark when only bottom
        // (document level) pit was saved. Because of this, bookmark
@@ -444,15 +448,22 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
        // it will be restored to the left of the outmost inset that contains
        // the bookmark.
        if (static_cast<size_t>(bottom_pit) < buffer_.paragraphs().size()) {
-               DocIterator it = doc_iterator_begin(buffer_.inset());
-               it.pit() = bottom_pit;
-               it.pos() = min(bottom_pos, it.paragraph().size());
-               setCursor(it);
-               return boost::make_tuple(it.pit(), it.pos(),
-                                        it.paragraph().id());
+               doc_it = doc_iterator_begin(buffer_.inset());
+               doc_it.pit() = bottom_pit;
+               doc_it.pos() = min(bottom_pos, doc_it.paragraph().size());
+               success = true;
+       }
+
+       if (success) {
+               // Note: only bottom (document) level pit is set.
+               setCursor(doc_it);
+               // set the current font.
+               buffer_.text().setCurrentFont(cursor_);
+               // center the screen on this new position.
+               center();
        }
-       // both methods fail
-       return boost::make_tuple(pit_type(0), pos_type(0), 0);
+
+       return success;
 }
 
 
@@ -478,16 +489,31 @@ int BufferView::workWidth() const
 }
 
 
-void BufferView::center()
+void BufferView::updateOffsetRef()
 {
+       // No need to update offset_ref_ in this case.
+       if (!need_centering_)
+               return;
+
+       // We are not properly started yet, delay until resizing is
+       // done.
+       if (height_ == 0)
+               return;
+
        CursorSlice & bot = cursor_.bottom();
        TextMetrics & tm = text_metrics_[bot.text()];
-       pit_type const pit = bot.pit();
-       tm.redoParagraph(pit);
-       ParagraphMetrics const & pm = tm.parMetrics(pit);
-       anchor_ref_ = pit;
-       offset_ref_ = bv_funcs::coordOffset(*this, cursor_, cursor_.boundary()).y_
-               + pm.ascent() - height_ / 2;
+       ParagraphMetrics const & pm = tm.parMetrics(bot.pit());
+       Point p = bv_funcs::coordOffset(*this, cursor_, cursor_.boundary());
+       offset_ref_ = p.y_ + pm.ascent() - height_ / 2;
+
+       need_centering_ = false;
+}
+
+
+void BufferView::center()
+{
+       anchor_ref_ = cursor_.bottom().pit();
+       need_centering_ = true;
 }
 
 
@@ -950,7 +976,7 @@ void BufferView::clearSelection()
 }
 
 
-void BufferView::workAreaResize(int width, int height)
+void BufferView::resize(int width, int height)
 {
        // Update from work area
        width_ = width;
@@ -1061,7 +1087,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
                        //metrics_info_.y1 = ymin of button;
                        //metrics_info_.y2 = ymax of button;
                        //
-                       // Unfortunately, rowpainter.cpp:paintText() does not distinguish
+                       // Unfortunately, BufferView::draw() does not distinguish
                        // between background updates and text updates. So we use the hammer
                        // solution for now. We could also avoid the updateMetrics() below
                        // by using the first and last pit of the CoordCache. Have a look
@@ -1350,6 +1376,8 @@ void BufferView::updateMetrics(bool singlepar)
        if (!singlepar)
                tm.redoParagraph(pit);
 
+       updateOffsetRef();
+
        int y0 = tm.parMetrics(pit).ascent() - offset_ref_;
 
        // Redo paragraphs above anchor if necessary.
@@ -1490,7 +1518,7 @@ void BufferView::menuInsertLyXFile(string const & filenm)
                el = buf.errorList("Parse");
                recordUndo(cursor_);
                cap::pasteParagraphList(cursor_, buf.paragraphs(),
-                                            buf.params().textclass, el);
+                                            buf.params().getTextClass_ptr(), el);
                res = _("Document %1$s inserted.");
        } else
                res = _("Could not insert document %1$s");
@@ -1501,4 +1529,51 @@ void BufferView::menuInsertLyXFile(string const & filenm)
        updateMetrics(false);
 }
 
+
+void BufferView::draw(frontend::Painter & pain)
+{
+       Text & text = buffer_.text();
+       bool const select = cursor_.selection();
+
+       PainterInfo pi(this, pain);
+       // Should the whole screen, including insets, be refreshed?
+       // FIXME: We should also distinguish DecorationUpdate to avoid text
+       // drawing if possible. This is not possible to do easily right now
+       // because of the single backing pixmap.
+       bool repaintAll = select 
+               || metrics_info_.update_strategy != SingleParUpdate;
+
+       if (repaintAll)
+               // Clear background (if not delegated to rows)
+               pain.fillRectangle(0, metrics_info_.y1, width_,
+                       metrics_info_.y2 - metrics_info_.y1, text.backgroundColor());
+
+       TextMetrics const & tm = text_metrics_[&text];
+
+       if (select)
+               text.drawSelection(pi, 0, 0);
+
+       int yy = metrics_info_.y1;
+       // draw contents
+       for (pit_type pit = metrics_info_.p1; pit <= metrics_info_.p2; ++pit) {
+               ParagraphMetrics const & pm = tm.parMetrics(pit);
+               yy += pm.ascent();
+               tm.drawParagraph(pi, pit, 0, yy, repaintAll);
+               yy += pm.descent();
+       }
+
+       // and grey out above (should not happen later)
+//     lyxerr << "par ascent: " << text.getPar(metrics_info_.p1).ascent() << endl;
+       if (metrics_info_.y1 > 0 
+               && metrics_info_.update_strategy == FullScreenUpdate)
+               pain.fillRectangle(0, 0, width_, metrics_info_.y1, Color::bottomarea);
+
+       // and possibly grey out below
+//     lyxerr << "par descent: " << text.getPar(metrics_info_.p1).ascent() << endl;
+       if (metrics_info_.y2 < height_ 
+               && metrics_info_.update_strategy == FullScreenUpdate)
+               pain.fillRectangle(0, metrics_info_.y2, width_,
+                       height_ - metrics_info_.y2, Color::bottomarea);
+}
+
 } // namespace lyx