diff --git a/hyperplane/assets/folder-closed.svg b/hyperplane/assets/folder-closed.svg index 616dcb8..2393e2c 100644 --- a/hyperplane/assets/folder-closed.svg +++ b/hyperplane/assets/folder-closed.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/hyperplane/assets/folder-open.svg b/hyperplane/assets/folder-open.svg index ed584af..afa436f 100644 --- a/hyperplane/assets/folder-open.svg +++ b/hyperplane/assets/folder-open.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/hyperplane/item.py b/hyperplane/item.py index 34809da..09e9555 100644 --- a/hyperplane/item.py +++ b/hyperplane/item.py @@ -337,7 +337,9 @@ def __zoom(self, _obj: Any, zoom_level: int) -> None: match zoom_level: case 1: - self.thumbnail.set_size_request(96, 80) + # This is not the exact aspect ratio, but it is close enough. + # It's good for keeping the folder textures sharp + self.thumbnail.set_size_request(96, 74) case 2: self.thumbnail.set_size_request(96, 96) case _: @@ -373,12 +375,11 @@ def __zoom(self, _obj: Any, zoom_level: int) -> None: self.dir_thumbnail_2.set_size_request(56, 56) self.dir_thumbnail_3.set_size_request(56, 56) + # Pixel size is set instead of icon size because otherwise GTK gets confused + # and it can lead to graphical glitches after zooming if zoom_level < 2: - self.icon.set_pixel_size(20) + self.icon.set_pixel_size(16) else: - # Pixel size is set instead of GTK_ICON_SIZE_LARGE - # because otherwise GTK gets confused even if pixel-size is reset to -1 - # and it can lead to graphical glitches after zooming self.icon.set_pixel_size(32) def __select_self(self) -> None: diff --git a/hyperplane/items_page.py b/hyperplane/items_page.py index 678825c..8c77ef2 100644 --- a/hyperplane/items_page.py +++ b/hyperplane/items_page.py @@ -159,6 +159,17 @@ def __init__( self.create_action("trash-delete", self.__trash_delete, ("Delete",)) self.create_action("trash-restore", self.__trash_restore) + # Set up zoom scrolling + + self.scroll = Gtk.EventControllerScroll.new( + ( + Gtk.EventControllerScrollFlags.VERTICAL + | Gtk.EventControllerScrollFlags.DISCRETE + ), + ) + self.scroll.connect("scroll", self.__scroll) + self.scrolled_window.add_controller(self.scroll) + def reload(self) -> None: """Refresh the view.""" if isinstance(self.dir_list, Gtk.DirectoryList): @@ -747,3 +758,15 @@ def __trash_restore(self, *_args: Any) -> None: for gfile in gfiles: restore(gfile) + + def __scroll( + self, _scroll: Gtk.EventControllerScroll, _dx: float, dy: float + ) -> None: + if self.scroll.get_current_event_state() != Gdk.ModifierType.CONTROL_MASK: + return + + if dy < 0: + self.get_root().zoom_in() + return + + self.get_root().zoom_out() diff --git a/hyperplane/properties.py b/hyperplane/properties.py index 601222a..65bdd4f 100644 --- a/hyperplane/properties.py +++ b/hyperplane/properties.py @@ -101,7 +101,7 @@ def __init__(self, gfile: Gio.File, **kwargs) -> None: icon_group.add( Adw.Clamp( child=Adw.Clamp(child=picture, maximum_size=150), - maximum_size=100, + maximum_size=120, orientation=Gtk.Orientation.VERTICAL, ) ) diff --git a/hyperplane/window.py b/hyperplane/window.py index a6d7f38..c6ff8ec 100644 --- a/hyperplane/window.py +++ b/hyperplane/window.py @@ -116,12 +116,12 @@ def __init__(self, **kwargs: Any) -> None: self.create_action( "zoom-in", - self.__zoom_in, + self.zoom_in, ("plus", "KP_Add", "equal"), ) self.create_action( "zoom-out", - self.__zoom_out, + self.zoom_out, ("minus", "KP_Subtract", "underscore"), ) self.create_action( @@ -177,6 +177,21 @@ def __init__(self, **kwargs: Any) -> None: self.rename_entry.connect("entry-activated", self.__do_rename) self.rename_button.connect("clicked", self.__do_rename) + # Set up search + + self.searched_page = self.get_visible_page() + self.search_entry.set_key_capture_widget(self) + + # Build sidebar + + self.sidebar_items = set() + self.__update_tags() + + self.__trash_changed() + shared.trash_list.connect("notify::n-items", self.__trash_changed) + + # Set up sidebar actions + sidebar_items = { self.sidebar_recent: Gio.File.new_for_uri("recent://"), self.sidebar_home: Gio.File.new_for_path(str(shared.home)), @@ -197,19 +212,6 @@ def __init__(self, **kwargs: Any) -> None: self.__set_actions() - # Set up search - - self.searched_page = self.get_visible_page() - self.search_entry.set_key_capture_widget(self) - - # Build sidebar - - self.sidebar_items = set() - self.__update_tags() - - self.__trash_changed() - shared.trash_list.connect("notify::n-items", self.__trash_changed) - def send_toast(self, message: str, undo: bool = False) -> None: """Displays a toast with the given message and optionally an undo button in the window.""" toast = Adw.Toast.new(message) @@ -598,14 +600,18 @@ def __forward(self, *_args: Any) -> None: nav_bin.view.push(nav_bin.next_pages[-1]) - def __zoom_in(self, *_args: Any) -> None: + def zoom_in(self, *_args: Any) -> None: + """Increases the zoom level of all views.""" + if (zoom_level := shared.state_schema.get_uint("zoom-level")) > 4: return shared.state_schema.set_uint("zoom-level", zoom_level + 1) self.update_zoom() - def __zoom_out(self, *_args: Any) -> None: + def zoom_out(self, *_args: Any) -> None: + """Decreases the zoom level of all views.""" + if (zoom_level := shared.state_schema.get_uint("zoom-level")) < 2: return