diff kitten: Fix images losing position when scrolling using mouse wheel/touchpad
This commit is contained in:
parent
e2339697b9
commit
eddd45bbc3
@ -88,6 +88,12 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
|||||||
|
|
||||||
- Wayland: Fix a crash when drag and dropping into kitty (:iss:`2432`)
|
- Wayland: Fix a crash when drag and dropping into kitty (:iss:`2432`)
|
||||||
|
|
||||||
|
- diff kitten: Fix images lingering as blank rectangles after the kitten quits
|
||||||
|
(:iss:`2449`)
|
||||||
|
|
||||||
|
- diff kitten: Fix images losing position when scrolling using mouse
|
||||||
|
wheel/touchpad
|
||||||
|
|
||||||
|
|
||||||
0.16.0 [2020-01-28]
|
0.16.0 [2020-01-28]
|
||||||
--------------------
|
--------------------
|
||||||
|
|||||||
@ -36,7 +36,7 @@ from .render import (
|
|||||||
)
|
)
|
||||||
from .search import BadRegex, Search
|
from .search import BadRegex, Search
|
||||||
from ..tui.handler import Handler
|
from ..tui.handler import Handler
|
||||||
from ..tui.images import ImageManager
|
from ..tui.images import ImageManager, Placement
|
||||||
from ..tui.line_edit import LineEdit
|
from ..tui.line_edit import LineEdit
|
||||||
from ..tui.loop import Loop
|
from ..tui.loop import Loop
|
||||||
from ..tui.operations import styled
|
from ..tui.operations import styled
|
||||||
@ -322,7 +322,43 @@ class DiffHandler(Handler):
|
|||||||
if image_involved:
|
if image_involved:
|
||||||
self.place_images()
|
self.place_images()
|
||||||
|
|
||||||
|
def update_image_placement_for_resend(self, image_id: int, pl: Placement) -> bool:
|
||||||
|
offset = self.scroll_pos
|
||||||
|
limit = len(self.diff_lines)
|
||||||
|
in_image = False
|
||||||
|
|
||||||
|
def adjust(row: int, candidate: ImagePlacement, is_left: bool) -> bool:
|
||||||
|
if candidate.image.image_id == image_id:
|
||||||
|
q = self.xpos_for_image(row, candidate, is_left)
|
||||||
|
if q is not None:
|
||||||
|
pl['x'] = q[0]
|
||||||
|
pl['y'] = row
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for row in range(self.num_lines):
|
||||||
|
lpos = offset + row
|
||||||
|
if lpos >= limit:
|
||||||
|
break
|
||||||
|
line = self.diff_lines[lpos]
|
||||||
|
if in_image:
|
||||||
|
if line.image_data is None:
|
||||||
|
in_image = False
|
||||||
|
continue
|
||||||
|
if line.image_data is not None:
|
||||||
|
left_placement, right_placement = line.image_data
|
||||||
|
if left_placement is not None:
|
||||||
|
if adjust(row, left_placement, True):
|
||||||
|
return True
|
||||||
|
in_image = True
|
||||||
|
if right_placement is not None:
|
||||||
|
if adjust(row, right_placement, False):
|
||||||
|
return True
|
||||||
|
in_image = True
|
||||||
|
return False
|
||||||
|
|
||||||
def place_images(self) -> None:
|
def place_images(self) -> None:
|
||||||
|
self.image_manager.update_image_placement_for_resend = self.update_image_placement_for_resend
|
||||||
self.cmd.clear_images_on_screen()
|
self.cmd.clear_images_on_screen()
|
||||||
offset = self.scroll_pos
|
offset = self.scroll_pos
|
||||||
limit = len(self.diff_lines)
|
limit = len(self.diff_lines)
|
||||||
@ -345,13 +381,20 @@ class DiffHandler(Handler):
|
|||||||
self.place_image(row, right_placement, False)
|
self.place_image(row, right_placement, False)
|
||||||
in_image = True
|
in_image = True
|
||||||
|
|
||||||
def place_image(self, row: int, placement: ImagePlacement, is_left: bool) -> None:
|
def xpos_for_image(self, row: int, placement: ImagePlacement, is_left: bool) -> Optional[Tuple[int, float]]:
|
||||||
xpos = (0 if is_left else (self.screen_size.cols // 2)) + placement.image.margin_size
|
xpos = (0 if is_left else (self.screen_size.cols // 2)) + placement.image.margin_size
|
||||||
image_height_in_rows = placement.image.rows
|
image_height_in_rows = placement.image.rows
|
||||||
topmost_visible_row = placement.row
|
topmost_visible_row = placement.row
|
||||||
num_visible_rows = image_height_in_rows - topmost_visible_row
|
num_visible_rows = image_height_in_rows - topmost_visible_row
|
||||||
visible_frac = min(num_visible_rows / image_height_in_rows, 1)
|
visible_frac = min(num_visible_rows / image_height_in_rows, 1)
|
||||||
if visible_frac > 0:
|
if visible_frac <= 0:
|
||||||
|
return None
|
||||||
|
return xpos, visible_frac
|
||||||
|
|
||||||
|
def place_image(self, row: int, placement: ImagePlacement, is_left: bool) -> None:
|
||||||
|
q = self.xpos_for_image(row, placement, is_left)
|
||||||
|
if q is not None:
|
||||||
|
xpos, visible_frac = q
|
||||||
height = int(visible_frac * placement.image.height)
|
height = int(visible_frac * placement.image.height)
|
||||||
top = placement.image.height - height
|
top = placement.image.height - height
|
||||||
self.image_manager.show_image(placement.image.image_id, xpos, row, src_rect=(
|
self.image_manager.show_image(placement.image.image_id, xpos, row, src_rect=(
|
||||||
|
|||||||
@ -10,7 +10,8 @@ from collections import defaultdict, deque
|
|||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from itertools import count
|
from itertools import count
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, DefaultDict, Deque, Dict, List, Optional, Sequence, Tuple, Union
|
Any, Callable, DefaultDict, Deque, Dict, List, Optional, Sequence, Tuple,
|
||||||
|
Union
|
||||||
)
|
)
|
||||||
|
|
||||||
from kitty.typing import (
|
from kitty.typing import (
|
||||||
@ -191,6 +192,7 @@ class ImageManager:
|
|||||||
self.image_id_to_converted_data: Dict[int, ImageKey] = {}
|
self.image_id_to_converted_data: Dict[int, ImageKey] = {}
|
||||||
self.transmission_status: Dict[int, Union[str, int]] = {}
|
self.transmission_status: Dict[int, Union[str, int]] = {}
|
||||||
self.placements_in_flight: DefaultDict[int, Deque[Placement]] = defaultdict(deque)
|
self.placements_in_flight: DefaultDict[int, Deque[Placement]] = defaultdict(deque)
|
||||||
|
self.update_image_placement_for_resend: Optional[Callable[[int, Placement], bool]]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def next_image_id(self) -> int:
|
def next_image_id(self) -> int:
|
||||||
@ -254,6 +256,8 @@ class ImageManager:
|
|||||||
self.placements_in_flight.pop(image_id, None)
|
self.placements_in_flight.pop(image_id, None)
|
||||||
|
|
||||||
def resend_image(self, image_id: int, pl: Placement) -> None:
|
def resend_image(self, image_id: int, pl: Placement) -> None:
|
||||||
|
if self.update_image_placement_for_resend is not None and not self.update_image_placement_for_resend(image_id, pl):
|
||||||
|
return
|
||||||
image_data = self.image_id_to_image_data[image_id]
|
image_data = self.image_id_to_image_data[image_id]
|
||||||
skey = self.image_id_to_converted_data[image_id]
|
skey = self.image_id_to_converted_data[image_id]
|
||||||
self.transmit_image(image_data, image_id, *skey)
|
self.transmit_image(image_data, image_id, *skey)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user