Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-11-24 11:59:38 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-11-24 12:19:24 +0300
commit3106ca8f63979d23cf6944439b4122973b9deb0d (patch)
tree39f759fa5aa1b49786ade2af209ef23636d56034 /source/blender/editors/space_text/text_ops.c
parent44f18ce0a6e56156c3bd67f7080b06af11e502bf (diff)
Text Editor: smooth scrolling
Add smooth scrolling support for vertical scrolling. This is only active while scrolling so we don't need to support pixel-level offsets for operators, interactions.
Diffstat (limited to 'source/blender/editors/space_text/text_ops.c')
-rw-r--r--source/blender/editors/space_text/text_ops.c115
1 files changed, 91 insertions, 24 deletions
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 71e24090aa1..969e2ae3290 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -270,8 +270,8 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
st->text = text;
st->left = 0;
st->top = 0;
- st->scroll_accum[0] = 0.0f;
- st->scroll_accum[1] = 0.0f;
+ st->scroll_ofs_px[0] = 0;
+ st->scroll_ofs_px[1] = 0;
text_drawcache_tag_update(st, 1);
}
@@ -353,8 +353,8 @@ static int text_open_exec(bContext *C, wmOperator *op)
st->text = text;
st->left = 0;
st->top = 0;
- st->scroll_accum[0] = 0.0f;
- st->scroll_accum[1] = 0.0f;
+ st->scroll_ofs_px[0] = 0;
+ st->scroll_ofs_px[1] = 0;
}
text_drawcache_tag_update(st, 1);
@@ -2526,8 +2526,29 @@ typedef struct TextScroll {
int scrollbar;
int zone;
+
+ /* Store the state of the display, cache some constant vars. */
+ struct {
+ int ofs_init[2];
+ int ofs_max[2];
+ int size_px[2];
+ } state;
+ int ofs_delta[2];
+ int ofs_delta_px[2];
} TextScroll;
+static void text_scroll_state_init(TextScroll *tsc, SpaceText *st, ARegion *ar)
+{
+ tsc->state.ofs_init[0] = st->left;
+ tsc->state.ofs_init[1] = st->top;
+
+ tsc->state.ofs_max[0] = INT_MAX;
+ tsc->state.ofs_max[1] = text_get_total_lines(st, ar) - (st->viewlines / 2);
+
+ tsc->state.size_px[0] = st->cwidth;
+ tsc->state.size_px[1] = TXT_LINE_HEIGHT(st);
+}
+
static bool text_scroll_poll(bContext *C)
{
/* it should be possible to still scroll linked texts to read them,
@@ -2556,10 +2577,8 @@ static int text_scroll_exec(bContext *C, wmOperator *op)
static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
TextScroll *tsc = op->customdata;
int mval[2] = {event->x, event->y};
- int scroll_steps[2] = {0, 0};
text_update_character_width(st);
@@ -2578,34 +2597,65 @@ static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event)
/* accumulate scroll, in float values for events that give less than one
* line offset but taken together should still scroll */
if (!tsc->scrollbar) {
- st->scroll_accum[0] += -tsc->delta[0] / (float)st->cwidth;
- st->scroll_accum[1] += tsc->delta[1] / (float)(TXT_LINE_HEIGHT(st));
+ tsc->ofs_delta_px[0] -= tsc->delta[0];
+ tsc->ofs_delta_px[1] += tsc->delta[1];
}
else {
- st->scroll_accum[1] += -tsc->delta[1] * st->pix_per_line;
+ tsc->ofs_delta_px[1] -= (tsc->delta[1] * st->pix_per_line) * tsc->state.size_px[1];
}
- /* round to number of lines to scroll */
- scroll_steps[0] = (int)st->scroll_accum[0];
- scroll_steps[1] = (int)st->scroll_accum[1];
+ for (int i = 0; i < 2; i += 1) {
+ int lines_from_pixels = tsc->ofs_delta_px[i] / tsc->state.size_px[i];
+ tsc->ofs_delta[i] += lines_from_pixels;
+ tsc->ofs_delta_px[i] -= lines_from_pixels * tsc->state.size_px[i];
+ }
- st->scroll_accum[0] -= scroll_steps[0];
- st->scroll_accum[1] -= scroll_steps[1];
+ /* The final values need to be calculated from the inputs,
+ * so clamping and ensuring an unsigned pixel offset doesn't conflict with
+ * updating the cursor delta. */
+ int scroll_ofs_new[2] = {
+ tsc->state.ofs_init[0] + tsc->ofs_delta[0],
+ tsc->state.ofs_init[1] + tsc->ofs_delta[1],
+ };
+ int scroll_ofs_px_new[2] = {
+ tsc->ofs_delta_px[0],
+ tsc->ofs_delta_px[1],
+ };
- /* perform vertical and/or horizontal scroll */
- if (scroll_steps[0] || scroll_steps[1]) {
- txt_screen_skip(st, ar, scroll_steps[1]);
+ for (int i = 0; i < 2; i += 1) {
+ /* Ensure always unsigned (adjusting line/column accordingly). */
+ while (scroll_ofs_px_new[i] < 0) {
+ scroll_ofs_px_new[i] += tsc->state.size_px[i];
+ scroll_ofs_new[i] -= 1;
+ }
- if (st->wordwrap) {
- st->left = 0;
+ /* Clamp within usable region. */
+ if (scroll_ofs_new[i] < 0) {
+ scroll_ofs_new[i] = 0;
+ scroll_ofs_px_new[i] = 0;
}
- else {
- st->left += scroll_steps[0];
- if (st->left < 0) {
- st->left = 0;
- }
+ else if (scroll_ofs_new[i] >= tsc->state.ofs_max[i]) {
+ scroll_ofs_new[i] = tsc->state.ofs_max[i];
+ scroll_ofs_px_new[i] = 0;
}
+ }
+ /* Override for word-wrap. */
+ if (st->wordwrap) {
+ scroll_ofs_new[0] = 0;
+ scroll_ofs_px_new[0] = 0;
+ }
+
+ /* Apply to the screen. */
+ if (scroll_ofs_new[0] != st->left || scroll_ofs_new[1] != st->top ||
+ /* Horizontal sub-pixel offset currently isn't used. */
+ /* scroll_ofs_px_new[0] != st->scroll_ofs_px[0] || */
+ scroll_ofs_px_new[1] != st->scroll_ofs_px[1]) {
+
+ st->left = scroll_ofs_new[0];
+ st->top = scroll_ofs_new[1];
+ st->scroll_ofs_px[0] = scroll_ofs_px_new[0];
+ st->scroll_ofs_px[1] = scroll_ofs_px_new[1];
ED_area_tag_redraw(CTX_wm_area(C));
}
@@ -2616,8 +2666,18 @@ static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event)
static void scroll_exit(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
+ TextScroll *tsc = op->customdata;
st->flags &= ~ST_SCROLL_SELECT;
+
+ if (st->scroll_ofs_px[1] > tsc->state.size_px[1] / 2) {
+ st->top += 1;
+ }
+
+ st->scroll_ofs_px[0] = 0;
+ st->scroll_ofs_px[1] = 0;
+ ED_area_tag_redraw(CTX_wm_area(C));
+
MEM_freeN(op->customdata);
}
@@ -2659,6 +2719,8 @@ static void text_scroll_cancel(bContext *C, wmOperator *op)
static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
+ ARegion *ar = CTX_wm_region(C);
+
TextScroll *tsc;
if (RNA_struct_property_is_set(op->ptr, "lines")) {
@@ -2668,6 +2730,9 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
tsc = MEM_callocN(sizeof(TextScroll), "TextScroll");
tsc->first = 1;
tsc->zone = SCROLLHANDLE_BAR;
+
+ text_scroll_state_init(tsc, st, ar);
+
op->customdata = tsc;
st->flags |= ST_SCROLL_SELECT;
@@ -2780,6 +2845,8 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *ev
op->customdata = tsc;
st->flags |= ST_SCROLL_SELECT;
+ text_scroll_state_init(tsc, st, ar);
+
/* jump scroll, works in v2d but needs to be added here too :S */
if (event->type == MIDDLEMOUSE) {
tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar);