#include "LyXFunc.h"
#include "Layout.h"
#include "LyXRC.h"
+#include "MenuBackend.h"
#include "MetricsInfo.h"
#include "Paragraph.h"
#include "paragraph_funcs.h"
#include "insets/InsetText.h"
#include "frontends/alert.h"
+#include "frontends/Application.h"
#include "frontends/Delegates.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
tmpcur.clearSelection();
bv->setCursor(tmpcur);
+ bv->showCursor();
}
<< ", singlepar = " << (flags & Update::SinglePar)
<< "] buffer: " << &buffer_);
- // Update macro store
- if (!(cursor().inMathed() && cursor().inMacroMode()))
- buffer_.updateMacros();
+ buffer_.updateMacros();
// Now do the first drawing step if needed. This consists on updating
// the CoordCache in updateMetrics().
|| flags == (Update::Decoration | Update::FitCursor)) {
// tell the frontend to update the screen if needed.
if (fitCursor()) {
- center();
+ showCursor();
return;
}
if (flags & Update::Decoration) {
return;
}
- bool const full_metrics = flags & Update::Force;
+ bool const full_metrics = flags & Update::Force || !singleParUpdate();
- if (full_metrics || !singleParUpdate()) {
- if (flags & Update::FitCursor && fitCursor()) {
- center();
- return;
- }
+ if (full_metrics)
// We have to update the full screen metrics.
updateMetrics();
- }
if (!(flags & Update::FitCursor)) {
+ // Nothing to do anymore. Trigger a redraw and return
buffer_.changed();
return;
}
- //FIXME: updateMetrics() does not update paragraph position
+ // updateMetrics() does not update paragraph position
// This is done at draw() time. So we need a redraw!
-
buffer_.changed();
- if (!fitCursor())
- // The screen has already been updated thanks to the
- // 'buffer_.changed()' call three line above. So no need
- // to redraw again.
- return;
- // The screen needs to be recentered around the cursor position so
- // refresh it:
- center();
+ if (fitCursor()) {
+ // The cursor is off screen so ensure it is visible.
+ // refresh it:
+ showCursor();
+ }
}
<< " curr par: " << d->cursor_.bottom().pit()
<< " default height " << defaultRowHeight());
- int const parsize = int(t.paragraphs().size() - 1);
+ int const parsize = int(t.paragraphs().size());
if (d->par_height_.size() != parsize) {
d->par_height_.clear();
- // FIXME: We assume a default paragraph height of 4 rows. This
+ // FIXME: We assume a default paragraph height of 2 rows. This
// should probably be pondered with the screen width.
- d->par_height_.resize(parsize, defaultRowHeight() * 4);
+ d->par_height_.resize(parsize, defaultRowHeight() * 2);
}
// It would be better to fix the scrollbar to understand
for (pit_type pit = first.first; pit <= last.first; ++pit) {
ParagraphMetrics const & pm = tm.parMetrics(pit);
d->par_height_[pit] = pm.height();
- if (first_visible_pit < 0 && pm.position() + pm.descent() > 0)
- first_visible_pit = pit;
+ if (first_visible_pit >= 0 || pm.position() + pm.descent() <= 0)
+ continue;
+ first_visible_pit = pit;
+ LYXERR(Debug::SCROLLING, "first visible pit " << first_visible_pit);
+ // FIXME: we should look for the first visible row within
+ // the deepest inset!
+ int row_pos = pm.position();
+ size_t const nrows = pm.rows().size();
+ for (size_t i = 0; i != nrows; ++i) {
+ Row const & row = pm.rows()[i];
+ if (row_pos >= 0) {
+ LYXERR(Debug::SCROLLING, "first visible row " << i
+ << "(row pos = " << row_pos << ");");
+ break;
+ }
+ row_pos += row.height();
+ }
+ d->scrollbarParameters_.position = row_pos;
}
- LYXERR(Debug::SCROLLING, "first_visible_pit " << first_visible_pit);
-
d->scrollbarParameters_.height = 0;
for (size_t i = 0; i != d->par_height_.size(); ++i) {
+ if (i == first_visible_pit)
+ d->scrollbarParameters_.position += d->scrollbarParameters_.height;
d->scrollbarParameters_.height += d->par_height_[i];
- if (i != first_visible_pit)
- continue;
- // FIXME: we should look for the first visible row within
- // the deepest inset!
- d->scrollbarParameters_.position = d->scrollbarParameters_.height;
}
- d->scrollbarParameters_.lineScrollHeight =
- tm.parMetrics(first_visible_pit).rows()[0].height();
+ // We prefer fixed size line scrolling.
+ d->scrollbarParameters_.lineScrollHeight = defaultRowHeight();
}
}
+docstring BufferView::toolTip(int x, int y) const
+{
+ // Get inset under mouse, if there is one.
+ Inset const * covering_inset = getCoveringInset(buffer_.text(), x, y);
+ if (!covering_inset)
+ // No inset, no tooltip...
+ return docstring();
+ return covering_inset->toolTip(*this, x, y);
+}
+
+
+docstring BufferView::contextMenu(int x, int y) const
+{
+ // Get inset under mouse, if there is one.
+ Inset const * covering_inset = getCoveringInset(buffer_.text(), x, y);
+ if (covering_inset)
+ return covering_inset->contextMenu(*this, x, y);
+
+ // FIXME: Do something more elaborate here.
+ return from_ascii("edit");
+}
+
+
void BufferView::scrollDocView(int value)
{
int const offset = value - d->scrollbarParameters_.position;
- //TextMetrics & tm = d->text_metrics_[&buffer_.text()];
- if (abs(offset) <= 3*height_) {
+ // If the offset is less than 2 screen height, prefer to scroll instead.
+ if (abs(offset) <= 2 * height_) {
scroll(offset);
return;
}
// So we need a redraw!
buffer_.changed();
if (fitCursor())
- center();
+ showCursor();
}
return success;
}
-void BufferView::center()
+void BufferView::showCursor()
{
// We are not properly started yet, delay until resizing is
// done.
CursorSlice & bot = d->cursor_.bottom();
TextMetrics & tm = d->text_metrics_[bot.text()];
- int const bot_pit = d->cursor_.bottom().pit();
+ pos_type const max_pit = pos_type(bot.text()->paragraphs().size() - 1);
+ int bot_pit = d->cursor_.bottom().pit();
+ if (bot_pit > max_pit) {
+ // FIXME: Why does this happen?
+ LYXERR0("bottom pit is greater that max pit: "
+ << bot_pit << " > " << max_pit);
+ bot_pit = max_pit;
+ }
+
if (bot_pit == tm.first().first - 1)
tm.newParMetricsUp();
else if (bot_pit == tm.last().first + 1)
int ypos = pm.position() + offset;
Dimension const & row_dim = d->cursor_.textRow().dimension();
if (ypos - row_dim.ascent() < 0)
- scrollUp(- ypos + d->cursor_.textRow().ascent());
+ scrollUp(- ypos + row_dim.ascent());
else if (ypos + row_dim.descent() > height_)
- scrollDown(ypos - height_ + d->cursor_.textRow().descent());
+ scrollDown(ypos - height_ + row_dim.descent());
// else, nothing to do, the cursor is already visible so we just return.
return;
}
int offset = coordOffset(d->cursor_, d->cursor_.boundary()).y_;
d->anchor_pit_ = bot_pit;
+ Dimension const & row_dim = d->cursor_.textRow().dimension();
if (d->anchor_pit_ == 0)
d->anchor_ypos_ = offset + pm.ascent();
- else if (d->anchor_pit_ >= pos_type(bot.text()->paragraphs().size() - 1)) {
- d->anchor_pit_ = bot.text()->paragraphs().size() - 1;
- d->anchor_ypos_ = offset + pm.height() - height_;
- } else {
+ else if (d->anchor_pit_ == max_pit)
+ d->anchor_ypos_ = height_ - offset - row_dim.descent();
+ else
d->anchor_ypos_ = offset + pm.ascent() - height_ / 2;
- }
updateMetrics();
buffer_.changed();
}
-Update::flags BufferView::dispatch(FuncRequest const & cmd)
+bool BufferView::dispatch(FuncRequest const & cmd)
{
//lyxerr << [ cmd = " << cmd << "]" << endl;
<< " button[" << cmd.button() << ']');
Cursor & cur = d->cursor_;
- // Default Update flags.
- Update::flags updateFlags = Update::Force | Update::FitCursor;
switch (cmd.action) {
case LFUN_UNDO:
cur.message(_("Undo"));
cur.clearSelection();
- if (!cur.textUndo()) {
+ if (!cur.textUndo())
cur.message(_("No further undo information"));
- updateFlags = Update::None;
- }
break;
case LFUN_REDO:
cur.message(_("Redo"));
cur.clearSelection();
- if (!cur.textRedo()) {
+ if (!cur.textRedo())
cur.message(_("No further redo information"));
- updateFlags = Update::None;
- }
break;
case LFUN_FONT_STATE:
if (b == &buffer_) {
// Set the cursor
setCursor(makeDocIterator(par, 0));
+ showCursor();
} else {
// Switch to other buffer view and resend cmd
theLyXFunc().dispatch(FuncRequest(
LFUN_BUFFER_SWITCH, b->absFileName()));
theLyXFunc().dispatch(cmd);
- updateFlags = Update::None;
}
break;
}
break;
case LFUN_SCREEN_RECENTER:
- center();
+ showCursor();
break;
case LFUN_BIBTEX_DATABASE_ADD: {
Point p = getPos(cur, cur.boundary());
if (p.y_ < 0 || p.y_ > height_) {
// The cursor is off-screen so recenter before proceeding.
- center();
+ showCursor();
p = getPos(cur, cur.boundary());
}
scroll(cmd.action == LFUN_SCREEN_UP? - height_ : height_);
d->text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
//FIXME: what to do with cur.x_target()?
cur.finishUndo();
- // The metrics are already up to date. see scroll()
- updateFlags = Update::None;
break;
}
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_DOWN_SELECT: {
+ // Those two are not ready yet for consumption.
+ return false;
+
cur.selHandle(true);
size_t initial_depth = cur.depth();
Point const p = getPos(cur, cur.boundary());
// But no screen update is needed.
d->update_strategy_ = NoScreenUpdate;
buffer_.changed();
- updateFlags = Update::Force | Update::FitCursor;
break;
}
default:
- updateFlags = Update::None;
+ return false;
}
- return updateFlags;
+ return true;
}
}
-Inset const * BufferView::getCoveringInset(Text const & text, int x, int y)
+Inset const * BufferView::getCoveringInset(Text const & text,
+ int x, int y) const
{
TextMetrics & tm = d->text_metrics_[&text];
Inset * inset = tm.checkInsetHit(x, y);
it->getLabelList(buffer_, labels);
if (find(labels.begin(), labels.end(), label) != labels.end()) {
setCursor(it);
- processUpdateFlags(Update::FitCursor);
+ showCursor();
return;
}
}
int y1 = d->anchor_ypos_ - anchor_pm.ascent();
// We are now just above the anchor paragraph.
pit_type pit1 = d->anchor_pit_ - 1;
- for (; pit1 >= 0 && y1 > 0; --pit1) {
+ for (; pit1 >= 0 && y1 >= 0; --pit1) {
tm.redoParagraph(pit1);
ParagraphMetrics & pm = tm.par_metrics_[pit1];
y1 -= pm.descent();
int y2 = d->anchor_ypos_ + anchor_pm.descent();
// We are now just below the anchor paragraph.
pit_type pit2 = d->anchor_pit_ + 1;
- for (; pit2 < npit && y2 < height_; ++pit2) {
+ for (; pit2 < npit && y2 <= height_; ++pit2) {
tm.redoParagraph(pit2);
ParagraphMetrics & pm = tm.par_metrics_[pit2];
y2 += pm.ascent();