Give PageDown/Up scrolling a sane behaviour. Does not work with selection yet...

* BufferView:
- new scroll(), scrollDown() and scrollUp() method for pixel scrolling.
- new LFUN_SCREEN_UP/DOWN handling.
 
* TextMetrics: new helper and access methods.




git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20283 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2007-09-15 12:28:41 +00:00
parent 2499fdf7f5
commit 8d52aa5638
6 changed files with 158 additions and 23 deletions

View File

@ -592,6 +592,18 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
break;
}
case LFUN_SCREEN_UP:
case LFUN_SCREEN_DOWN:
flag.enabled(true);
break;
// FIXME: LFUN_SCREEN_DOWN_SELECT should be removed from
// everywhere else before this can enabled:
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_DOWN_SELECT:
flag.enabled(false);
break;
default:
flag.enabled(false);
}
@ -935,6 +947,38 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
break;
}
case LFUN_SCREEN_UP:
case LFUN_SCREEN_DOWN: {
Point const p = bv_funcs::getPos(*this, cur, cur.boundary());
scroll(cmd.action == LFUN_SCREEN_UP? - height_ : height_);
cur.reset(buffer_.inset());
text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
//FIXME: what to do with cur.x_target()?
finishUndo();
// The metrics are already up to date. see scroll()
updateFlags = Update::None;
break;
}
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_DOWN_SELECT: {
cur.selHandle(true);
size_t initial_depth = cur.depth();
Point const p = bv_funcs::getPos(*this, cur, cur.boundary());
scroll(cmd.action == LFUN_SCREEN_UP_SELECT? - height_ : height_);
// FIXME: We need to verify if the cursor stayed within an inset...
//cur.reset(buffer_.inset());
text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
finishUndo();
while (cur.depth() > initial_depth) {
cur.forwardInset();
}
// FIXME: we need to do a redraw again because of the selection
buffer_.changed();
updateFlags = Update::Force | Update::FitCursor;
break;
}
default:
updateFlags = Update::None;
}
@ -1138,20 +1182,60 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
}
void BufferView::scroll(int /*lines*/)
void BufferView::scroll(int y)
{
// Text const * t = buffer_.text();
// int const line_height = defaultRowHeight();
//
// // The new absolute coordinate
// int new_top_y = top_y() + lines * line_height;
//
// // Restrict to a valid value
// new_top_y = std::min(t->height() - 4 * line_height, new_top_y);
// new_top_y = std::max(0, new_top_y);
//
// scrollDocView(new_top_y);
//
if (y > 0)
scrollDown(y);
else if (y < 0)
scrollUp(-y);
}
void BufferView::scrollDown(int offset)
{
Text * text = &buffer_.text();
TextMetrics & tm = text_metrics_[text];
int ymax = height_ + offset;
while (true) {
std::pair<pit_type, ParagraphMetrics> const & last = tm.last();
int bottom_pos = last.second.position() + last.second.descent();
if (last.first == text->paragraphs().size() - 1) {
if (bottom_pos <= height_)
return;
offset = min(offset, bottom_pos - height_);
break;
}
if (bottom_pos > ymax)
break;
tm.newParMetricsDown();
}
offset_ref_ += offset;
updateMetrics(false);
buffer_.changed();
}
void BufferView::scrollUp(int offset)
{
Text * text = &buffer_.text();
TextMetrics & tm = text_metrics_[text];
int ymin = - offset;
while (true) {
std::pair<pit_type, ParagraphMetrics> const & first = tm.first();
int top_pos = first.second.position() - first.second.ascent();
if (first.first == 0) {
if (top_pos >= 0)
return;
offset = min(offset, - top_pos);
break;
}
if (top_pos < ymin)
break;
tm.newParMetricsUp();
}
offset_ref_ -= offset;
updateMetrics(false);
buffer_.changed();
}

View File

@ -128,8 +128,12 @@ public:
/// center the document view around the cursor.
void center();
/// scroll document by the given number of lines of default height.
void scroll(int lines);
/// scroll down document by the given number of pixels.
void scrollDown(int pixels);
/// scroll up document by the given number of pixels.
void scrollUp(int pixels);
/// scroll document by the given number of pixels.
void scroll(int pixels);
/// Scroll the view by a number of pixels.
void scrollDocView(int pixels);
/// Set the cursor position based on the scrollbar one.

View File

@ -440,9 +440,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
needsUpdate |= cursorDownParagraph(cur);
break;
case LFUN_SCREEN_UP:
case LFUN_SCREEN_UP_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_UP_SELECT);
needsUpdate |= cur.selHandle(true);
if (cur.pit() == 0 && cur.textRow().pos() == 0)
cur.undispatched();
else {
@ -450,9 +449,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
}
break;
case LFUN_SCREEN_DOWN:
case LFUN_SCREEN_DOWN_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_DOWN_SELECT);
needsUpdate |= cur.selHandle(true);
if (cur.pit() == cur.lastpit()
&& cur.textRow().endpos() == cur.lastpos())
cur.undispatched();
@ -1853,8 +1851,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
case LFUN_WORD_SELECT:
case LFUN_PARAGRAPH_UP:
case LFUN_PARAGRAPH_DOWN:
case LFUN_SCREEN_UP:
case LFUN_SCREEN_DOWN:
case LFUN_LINE_BEGIN:
case LFUN_LINE_END:
case LFUN_BREAK_LINE:

View File

@ -139,6 +139,21 @@ ParagraphMetrics const & TextMetrics::parMetrics(pit_type pit) const
}
pair<pit_type, ParagraphMetrics> const & TextMetrics::first() const
{
pair<pit_type, ParagraphMetrics> const & pm = *par_metrics_.begin();
return pm;
}
pair<pit_type, ParagraphMetrics> const & TextMetrics::last() const
{
pair<pit_type, ParagraphMetrics> const & pm = *par_metrics_.rbegin();
return pm;
}
ParagraphMetrics & TextMetrics::parMetrics(pit_type pit,
bool redo)
{
@ -1153,6 +1168,33 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const
}
void TextMetrics::newParMetricsDown()
{
pair<pit_type, ParagraphMetrics> const & last = *par_metrics_.rbegin();
pit_type const pit = last.first + 1;
if (pit == text_->paragraphs().size())
return;
// do it and update its position.
redoParagraph(pit);
par_metrics_[pit].setPosition(last.second.position()
+ last.second.descent());
}
void TextMetrics::newParMetricsUp()
{
pair<pit_type, ParagraphMetrics> const & first = *par_metrics_.begin();
if (first.first == 0)
return;
pit_type const pit = first.first - 1;
// do it and update its position.
redoParagraph(pit);
par_metrics_[pit].setPosition(first.second.position()
- first.second.ascent());
}
// y is screen coordinate
pit_type TextMetrics::getPitNearY(int y)
{

View File

@ -48,6 +48,11 @@ public:
bool has(pit_type pit) const;
///
ParagraphMetrics const & parMetrics(pit_type) const;
///
std::pair<pit_type, ParagraphMetrics> const & first() const;
///
std::pair<pit_type, ParagraphMetrics> const & last() const;
///
int parPosition(pit_type pit) const;
@ -57,9 +62,15 @@ public:
Point const & origin() const { return origin_; }
/// compute text metrics.
bool metrics(MetricsInfo & mi, Dimension & dim);
///
void newParMetricsDown();
///
void newParMetricsUp();
/// Gets the fully instantiated font at a given position in a paragraph
/// Basically the same routine as Paragraph::getFont() in Paragraph.cpp.
/// The difference is that this one is used for displaying, and thus we

View File

@ -643,13 +643,11 @@ goto_char_backwards:
break;
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_UP:
cmd = FuncRequest(LFUN_FINISHED_LEFT);
cur.undispatched();
break;
case LFUN_SCREEN_DOWN_SELECT:
case LFUN_SCREEN_DOWN:
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
break;