Skip to content

Commit f629853

Browse files
committed
Ensure that scrollbar is only rerendered when the position is changed
1 parent a229d93 commit f629853

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

lib/reline/line_editor.rb

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ def call
559559

560560
class Dialog
561561
attr_reader :name, :contents, :width
562-
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup, :trap_key
562+
attr_accessor :scroll_top, :scrollbar_pos, :column, :vertical_offset, :lines_backup, :trap_key
563563

564564
def initialize(name, config, proc_scope)
565565
@name = name
@@ -663,6 +663,15 @@ def add_dialog_proc(name, p, context = nil)
663663
end
664664
dialog.contents = dialog.contents[dialog.scroll_top, height]
665665
end
666+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
667+
bar_max_height = height * 2
668+
moving_distance = (dialog_render_info.contents.size - height) * 2
669+
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
670+
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
671+
dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
672+
else
673+
dialog.scrollbar_pos = nil
674+
end
666675
upper_space = @first_line_started_from - @started_from
667676
lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
668677
dialog.column = dialog_render_info.pos.x
@@ -682,17 +691,11 @@ def add_dialog_proc(name, p, context = nil)
682691
dialog.vertical_offset = dialog_render_info.pos.y + 1
683692
end
684693
Reline::IOGate.hide_cursor
694+
block_elem_size = calculate_width('█')
695+
dialog.width += block_elem_size if dialog.scrollbar_pos
685696
reset_dialog(dialog, old_dialog)
686697
move_cursor_down(dialog.vertical_offset)
687698
Reline::IOGate.move_cursor_column(dialog.column)
688-
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
689-
bar_max_height = height * 2
690-
moving_distance = (dialog_render_info.contents.size - height) * 2
691-
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
692-
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
693-
position = ((bar_max_height - bar_height) * position_ratio).floor.to_i
694-
end
695-
block_elem_size = calculate_width('█')
696699
dialog.contents.each_with_index do |item, i|
697700
if i == pointer
698701
bg_color = '45'
@@ -703,16 +706,16 @@ def add_dialog_proc(name, p, context = nil)
703706
bg_color = '46'
704707
end
705708
end
706-
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width)
709+
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width - block_elem_size), dialog.width - block_elem_size)
707710
@output.write "\e[#{bg_color}m#{str}"
708-
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
711+
if dialog.scrollbar_pos and dialog.scrollbar_pos != old_dialog.scrollbar_pos
709712
@output.write "\e[37m"
710-
if position <= (i * 2) and (i * 2 + block_elem_size) < (position + bar_height)
713+
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + block_elem_size) < (dialog.scrollbar_pos + bar_height)
711714
@output.write '█'
712-
elsif position <= (i * 2) and (i * 2) < (position + bar_height)
715+
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
713716
@output.write '▀'
714717
str += ''
715-
elsif position <= (i * 2 + block_elem_size) and (i * 2) < (position + bar_height)
718+
elsif dialog.scrollbar_pos <= (i * 2 + block_elem_size) and (i * 2) < (dialog.scrollbar_pos + bar_height)
716719
@output.write '▄'
717720
else
718721
@output.write ' ' * block_elem_size
@@ -723,7 +726,6 @@ def add_dialog_proc(name, p, context = nil)
723726
Reline::IOGate.move_cursor_column(dialog.column)
724727
move_cursor_down(1) if i < (dialog.contents.size - 1)
725728
end
726-
dialog.width += block_elem_size if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
727729
Reline::IOGate.move_cursor_column(cursor_column)
728730
move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
729731
Reline::IOGate.show_cursor
@@ -808,7 +810,10 @@ def add_dialog_proc(name, p, context = nil)
808810
end
809811
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
810812
end
811-
if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
813+
old_dialog_scrollbar = old_dialog.scrollbar_pos.nil? ? 0 : calculate_width('█')
814+
dialog_scrollbar = dialog.scrollbar_pos.nil? ? 0 : calculate_width('█')
815+
if (old_dialog.column + old_dialog.width - old_dialog_scrollbar) > (dialog.column + dialog.width - dialog_scrollbar)
816+
$stderr.puts "RIGHT #{old_dialog.column} #{old_dialog.width} #{old_dialog_scrollbar} #{dialog.column} #{dialog.width} #{dialog_scrollbar}"
812817
# rerender right
813818
move_cursor_down(old_dialog.vertical_offset + y_diff)
814819
width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)

0 commit comments

Comments
 (0)