]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/screen.C
slimmer row painter interface
[lyx.git] / src / frontends / screen.C
index 2e98ad9cba26e2c045f3d2971273855f61cc71af..301c41f207d20cb806a53b90477a6e1740f6d757 100644 (file)
@@ -25,6 +25,9 @@
 #include "language.h"
 #include "debug.h"
 #include "rowpainter.h"
+#include "insets/updatableinset.h"
+#include "mathed/formulabase.h"
+#include "lyx_gui.h"
 
 // Splash screen-specific stuff
 #include "lyxfont.h"
 #include <boost/bind.hpp>
 #include <boost/signals/trackable.hpp>
 
+using namespace lyx::support;
+
 using std::min;
 using std::max;
 using std::endl;
 
+namespace grfx = lyx::graphics;
+
 namespace {
 
 class SplashScreen : boost::noncopyable, boost::signals::trackable {
@@ -126,33 +133,92 @@ LyXScreen::~LyXScreen()
 {
 }
 
-// FIXME: GUII these cursor methods need to decide
-// whether the workarea is focused or not
 
-void LyXScreen::showCursor(LyXText const * text, BufferView const * bv)
+void LyXScreen::showCursor(BufferView & bv)
 {
+       // this is needed to make sure we copy back the right
+       // pixmap on the hide for the Qt frontend
+       lyx_gui::sync_events();
+
        if (cursor_visible_)
                return;
 
-       workarea().getPainter().start();
+       if (!bv.available())
+               return;
 
        Cursor_Shape shape = BAR_SHAPE;
-       BufferParams const & bp(bv->buffer()->params);
-       LyXFont const & realfont(text->real_current_font);
-
-       if (realfont.language() != bp.language
-               || realfont.isVisibleRightToLeft()
-               != bp.language->RightToLeft()) {
-               shape = (realfont.isVisibleRightToLeft())
-                       ? REVERSED_L_SHAPE : L_SHAPE;
+
+       LyXText const & text = *bv.getLyXText();
+       LyXFont const & realfont(text.real_current_font);
+       BufferParams const & bp(bv.buffer()->params);
+       bool const samelang = realfont.language() == bp.language;
+       bool const isrtl = realfont.isVisibleRightToLeft();
+
+       if (!samelang || isrtl != bp.language->RightToLeft()) {
+               shape = L_SHAPE;
+               if (isrtl)
+                       shape = REVERSED_L_SHAPE;
        }
 
-       showManualCursor(text, text->cursor.x(), text->cursor.y(),
-               font_metrics::maxAscent(realfont),
-               font_metrics::maxDescent(realfont),
-               shape);
+       int ascent = font_metrics::maxAscent(realfont);
+       int descent = font_metrics::maxDescent(realfont);
+       int h = ascent + descent;
+       int x = 0;
+       int y = 0;
+       int const top_y = bv.text->top_y();
+
+       if (bv.theLockingInset()) {
+               // Would be nice to clean this up to make some understandable sense...
+               UpdatableInset * inset = bv.theLockingInset();
+               inset->getCursor(bv, x, y);
+
+               // Non-obvious. The reason we have to have these
+               // extra checks is that the ->getCursor() calls rely
+               // on the inset's own knowledge of its screen position.
+               // If we scroll up or down in a big enough increment, the
+               // inset->draw() is not called: this doesn't update
+               // inset.top_baseline, so getCursor() returns an old value.
+               // Ugly as you like.
+               int bx, by;
+               inset->getCursorPos(&bv, bx, by);
+               by += inset->insetInInsetY() + bv.text->cursor.iy();
+               if (by < top_y)
+                       return;
+               if (by > top_y + workarea().workHeight())
+                       return;
+       } else {
+               x = bv.text->cursor.x();
+               y = bv.text->cursor.y();
+               y -= top_y;
+       }
 
-       workarea().getPainter().end();
+       y -= ascent;
+
+       // if it doesn't fit entirely on the screen, don't try to show it
+       if (y < 0 || y + h > workarea().workHeight())
+               return;
+
+       cursor_visible_ = true;
+       showCursor(x, y, h, shape);
+}
+
+
+void LyXScreen::hideCursor()
+{
+       if (!cursor_visible_)
+               return;
+
+       cursor_visible_ = false;
+       removeCursor();
+}
+
+
+void LyXScreen::toggleCursor(BufferView & bv)
+{
+       if (cursor_visible_)
+               hideCursor();
+       else
+               showCursor(bv);
 }
 
 
@@ -181,21 +247,14 @@ bool LyXScreen::fitManualCursor(BufferView * bv, LyXText * text,
 }
 
 
-void LyXScreen::cursorToggle(BufferView * bv) const
+unsigned int LyXScreen::topCursorVisible(LyXText * text)
 {
-       if (cursor_visible_)
-               bv->hideCursor();
-       else
-               bv->showCursor();
-}
-
-
-unsigned int LyXScreen::topCursorVisible(LyXCursor const & cursor, int top_y)
-{
-       int const vheight = workarea().workHeight();
+       LyXCursor const & cursor = text->cursor;
+       int top_y = text->top_y();
        int newtop = top_y;
+       int const vheight = workarea().workHeight();
 
-       RowList::iterator row = cursor.row();
+       RowList::iterator row = text->cursorRow();
 
 #warning SUPER HACK DISABLED (Lgb)
 #if 0
@@ -210,9 +269,8 @@ unsigned int LyXScreen::topCursorVisible(LyXCursor const & cursor, int top_y)
                                + row->height()
                                - row->baseline() - vheight;
                } else {
-                       // scroll down
-                       newtop = cursor.y()
-                               - vheight / 2;   /* the scroll region must be so big!! */
+                       // scroll down, the scroll region must be so big!!
+                       newtop = cursor.y() - vheight / 2;
                }
 
        } else if (static_cast<int>((cursor.y()) - row->baseline()) <
@@ -236,7 +294,7 @@ unsigned int LyXScreen::topCursorVisible(LyXCursor const & cursor, int top_y)
 bool LyXScreen::fitCursor(LyXText * text, BufferView * bv)
 {
        // Is a change necessary?
-       int const newtop = topCursorVisible(text->cursor, text->top_y());
+       int const newtop = topCursorVisible(text);
        bool const result = (newtop != text->top_y());
        if (result) {
                draw(text, bv, newtop);
@@ -295,13 +353,13 @@ void LyXScreen::toggleSelection(LyXText * text, BufferView * bv,
 
        int const bottom = min(
                max(static_cast<int>(text->selection.end.y()
-                                    - text->selection.end.row()->baseline()
-                                    + text->selection.end.row()->height()),
+                                    - text->getRow(text->selection.end)->baseline()
+                                    + text->getRow(text->selection.end)->height()),
                    text->top_y()),
                static_cast<int>(text->top_y() + workarea().workHeight()));
        int const top = min(
                max(static_cast<int>(text->selection.start.y() -
-                                    text->selection.start.row()->baseline()),
+                                    text->getRow(text->selection.start)->baseline()),
                    text->top_y()),
                static_cast<int>(text->top_y() + workarea().workHeight()));
 
@@ -328,10 +386,10 @@ void LyXScreen::toggleToggle(LyXText * text, BufferView * bv,
                return;
 
        int const top_tmp = text->toggle_cursor.y()
-               - text->toggle_cursor.row()->baseline();
+               - text->getRow(text->toggle_cursor)->baseline();
        int const bottom_tmp = text->toggle_end_cursor.y()
-               - text->toggle_end_cursor.row()->baseline()
-               + text->toggle_end_cursor.row()->height();
+               - text->getRow(text->toggle_end_cursor)->baseline()
+               + text->getRow(text->toggle_end_cursor)->height();
 
        int const offset = yo < 0 ? yo : 0;
        int const bottom = min(max(bottom_tmp, text->top_y()),
@@ -365,11 +423,6 @@ void LyXScreen::redraw(LyXText * text, BufferView * bv)
        expose(0, 0, workarea().workWidth(), workarea().workHeight());
 
        workarea().getPainter().end();
-
-       if (cursor_visible_) {
-               cursor_visible_ = false;
-               bv->showCursor();
-       }
 }
 
 
@@ -421,10 +474,11 @@ void LyXScreen::drawFromTo(LyXText * text, BufferView * bv,
        int y = y_text - topy;
        // y1 is now the real beginning of row on the screen
 
+       hideCursor();
+
        RowList::iterator const rend = text->rows().end();
        while (rit != rend && y < y2) {
-               RowPainter rp(*bv, *text, rit);
-               rp.paint(y + yo, xo, y + topy);
+               paintRows(*bv, *text, rit, y + yo, xo, y + topy);
                y += rit->height();
                ++rit;
        }
@@ -450,6 +504,7 @@ void LyXScreen::drawOneRow(LyXText * text, BufferView * bv,
        if (y - row->height() > workarea().workHeight())
                return;
 
-       RowPainter rp(*bv, *text, row);
-       rp.paint(y, xo, y + text->top_y());
+       hideCursor();
+
+       paintRows(*bv, *text, row, y, xo, y + text->top_y());
 }