Exemple #1
0
 def scroll_smartly(self, max_scroll, backwards, axis_map, index=None):
     """ Applies a "smart scrolling" step to the current viewport position.
     If there are not enough Boxes to scroll to, the viewport is not moved
     and an appropriate value is returned.
     @param max_scroll: The maximum numbers of pixels to scroll in one step.
     @param backwards: True for backwards scrolling, False otherwise.
     @param axis_map: The index of the dimension to modify.
     @param index: The index of the Box the scrolling step is related to,
     or None to use the index of the current Box.
     @return: The index of the current Box after scrolling, or -1 if there
     were not enough Boxes to scroll backwards, or the number of Boxes if
     there were not enough Boxes to scroll forwards. """
     # TODO reconsider interface
     if (index == None) or (not self.wrap_individually):
         index = self.get_current_index()
     if not self.wrap_individually:
         wrapper_index = 0
     else:
         wrapper_index = index
     o = tools.vector_opposite(self.orientation) if backwards \
         else self.orientation
     new_pos = self.scroller.scroll_smartly(self.wrapper_boxes[wrapper_index],
         self.viewport_box, o, max_scroll, axis_map)
     if new_pos == []:
         if self.wrap_individually:
             index += -1 if backwards else 1
             n = len(self.get_content_boxes())
             if (index < n) and (index >= 0):
                 self.scroll_to_predefined(tools.vector_opposite(o), index)
             return index
         else:
             index = -1 if backwards else len(self.get_content_boxes())
             return index
     self.set_viewport_position(new_pos)
     return index
Exemple #2
0
 def scroll_smartly(self, max_scroll, backwards, axis_map, index=None):
     """ Applies a "smart scrolling" step to the current viewport position.
     If there are not enough Boxes to scroll to, the viewport is not moved
     and an appropriate value is returned.
     @param max_scroll: The maximum numbers of pixels to scroll in one step.
     @param backwards: True for backwards scrolling, False otherwise.
     @param axis_map: The index of the dimension to modify.
     @param index: The index of the Box the scrolling step is related to,
     or None to use the index of the current Box.
     @return: The index of the current Box after scrolling, or -1 if there
     were not enough Boxes to scroll backwards, or the number of Boxes if
     there were not enough Boxes to scroll forwards. """
     # TODO reconsider interface
     if (index == None) or (not self.wrap_individually):
         index = self.get_current_index()
     if not self.wrap_individually:
         wrapper_index = 0
     else:
         wrapper_index = index
     o = tools.vector_opposite(self.orientation) if backwards \
         else self.orientation
     new_pos = self.scroller.scroll_smartly(self.wrapper_boxes[wrapper_index],
         self.viewport_box, o, max_scroll, axis_map)
     if new_pos == []:
         if self.wrap_individually:
             index += -1 if backwards else 1
             n = len(self.get_content_boxes())
             if (index < n) and (index >= 0):
                 self.scroll_to_predefined(tools.vector_opposite(o), index)
             return index
         else:
             index = -1 if backwards else len(self.get_content_boxes())
             return index
     self.set_viewport_position(new_pos)
     return index
Exemple #3
0
    def _draw_image(self, scroll_to):

        self._update_toggles_visibility()

        self.osd.clear()

        if not self.filehandler.file_loaded:
            self._clear_main_area()
            self._waiting_for_redraw = False
            return False

        if self.imagehandler.page_is_available():
            distribution_axis = constants.DISTRIBUTION_AXIS
            alignment_axis = constants.ALIGNMENT_AXIS
            pixbuf_count = 2 if self.displayed_double(
            ) else 1  # XXX limited to at most 2 pages
            pixbuf_list = list(self.imagehandler.get_pixbufs(pixbuf_count))
            do_not_transform = [
                image_tools.disable_transform(x) for x in pixbuf_list
            ]
            size_list = [[pixbuf.get_width(),
                          pixbuf.get_height()] for pixbuf in pixbuf_list]

            if self.is_manga_mode:
                orientation = constants.MANGA_ORIENTATION
            else:
                orientation = constants.WESTERN_ORIENTATION

            # Rotation handling:
            # - apply Exif rotation on individual images
            # - apply automatic rotation (size based) on whole page
            # - apply manual rotation on whole page
            if prefs['auto rotate from exif']:
                rotation_list = [
                    image_tools.get_implied_rotation(pixbuf)
                    for pixbuf in pixbuf_list
                ]
            else:
                rotation_list = [0] * len(pixbuf_list)
            virtual_size = [0, 0]
            for i in range(pixbuf_count):
                if rotation_list[i] in (90, 270):
                    size_list[i].reverse()
                size = size_list[i]
                virtual_size[distribution_axis] += size[distribution_axis]
                virtual_size[alignment_axis] = max(
                    virtual_size[alignment_axis], size[alignment_axis])
            rotation = self._get_size_rotation(*virtual_size)
            rotation = (rotation + prefs['rotation']) % 360
            if rotation in (90, 270):
                distribution_axis, alignment_axis = alignment_axis, distribution_axis
                orientation = list(orientation)
                orientation.reverse()
                for i in range(pixbuf_count):
                    size_list[i].reverse()
            if rotation in (180, 270):
                orientation = tools.vector_opposite(orientation)
            for i in range(pixbuf_count):
                rotation_list[i] = (rotation_list[i] + rotation) % 360
            if prefs['vertical flip'] and rotation in (90, 270):
                orientation = tools.vector_opposite(orientation)
            if prefs['horizontal flip'] and rotation in (0, 180):
                orientation = tools.vector_opposite(orientation)

            viewport_size = ()  # dummy
            expand_area = False
            scrollbar_requests = [False] * len(self._scroll)
            # Visible area size is recomputed depending on scrollbar visibility
            while True:
                self._show_scrollbars(scrollbar_requests)
                new_viewport_size = self.get_visible_area_size()
                if new_viewport_size == viewport_size:
                    break
                viewport_size = new_viewport_size
                zoom_dummy_size = list(viewport_size)
                dasize = zoom_dummy_size[distribution_axis] - \
                    self._spacing * (pixbuf_count - 1)
                if dasize <= 0:
                    dasize = 1
                zoom_dummy_size[distribution_axis] = dasize
                scaled_sizes = self.zoom.get_zoomed_size(
                    size_list, zoom_dummy_size, distribution_axis,
                    do_not_transform)
                self.layout = layout.FiniteLayout(scaled_sizes, viewport_size,
                                                  orientation, self._spacing,
                                                  expand_area,
                                                  distribution_axis,
                                                  alignment_axis)
                union_scaled_size = self.layout.get_union_box().get_size()
                scrollbar_requests = [(old or new) for old, new in zip(
                    scrollbar_requests,
                    tools.smaller(viewport_size, union_scaled_size))]
                if len(tuple(filter(
                        None, scrollbar_requests))) > 1 and not expand_area:
                    expand_area = True
                    viewport_size = ()  # start anew

            for i in range(pixbuf_count):
                pixbuf_list[i] = image_tools.fit_pixbuf_to_rectangle(
                    pixbuf_list[i], scaled_sizes[i], rotation_list[i])

            for i in range(pixbuf_count):
                pixbuf_list[i] = image_tools.trans_pixbuf(
                    pixbuf_list[i],
                    flip=prefs['vertical flip'],
                    flop=prefs['horizontal flip'])
                pixbuf_list[i] = self.enhancer.enhance(pixbuf_list[i])

            for i in range(pixbuf_count):
                image_tools.set_from_pixbuf(self.images[i], pixbuf_list[i])

            resolutions = [
                (*size, scaled_size[0] / size[0])
                for scaled_size, size in zip(scaled_sizes, size_list)
            ]

            if self.is_manga_mode:
                resolutions.reverse()
            self.statusbar.set_resolution(resolutions)
            self.statusbar.update()

            smartbg = prefs['smart bg']
            smartthumbbg = prefs['show thumbnails'] and prefs['smart thumb bg']
            if smartbg or smartthumbbg:
                bg_color = self.imagehandler.get_pixbuf_auto_background(
                    pixbuf_count)
                if smartbg:
                    self.set_bg_color(bg_color)
                if smartthumbbg:
                    self.thumbnailsidebar.change_thumbnail_background_color(
                        bg_color)

            self._main_layout.get_bin_window().freeze_updates()

            self._main_layout.set_size(*union_scaled_size)
            content_boxes = self.layout.get_content_boxes()
            for i in range(pixbuf_count):
                self._main_layout.move(self.images[i],
                                       *content_boxes[i].get_position())

            for i in range(pixbuf_count):
                self.images[i].show()
            for i in range(pixbuf_count, len(self.images)):
                self.images[i].hide()

            # Reset orientation so scrolling behaviour is sane.
            if self.is_manga_mode:
                self.layout.set_orientation(constants.MANGA_ORIENTATION)
            else:
                self.layout.set_orientation(constants.WESTERN_ORIENTATION)

            if scroll_to is not None:
                destination = (scroll_to, ) * 2
                if constants.SCROLL_TO_START == scroll_to:
                    index = constants.FIRST_INDEX
                elif constants.SCROLL_TO_END == scroll_to:
                    index = constants.LAST_INDEX
                else:
                    index = None
                self.scroll_to_predefined(destination, index)

            self._main_layout.get_bin_window().thaw_updates()
        else:
            # Save scroll destination for when the page becomes available.
            self._last_scroll_destination = scroll_to
            # If the pixbuf for the current page(s) isn't available,
            # hide all images to clear any old pixbufs.
            # XXX How about calling self._clear_main_area?
            for i in range(len(self.images)):
                self.images[i].hide()
            self._show_scrollbars([False] * len(self._scroll))

        self._waiting_for_redraw = False

        return False
Exemple #4
0
    def _draw_image(self, scroll_to):

        self._update_toggles_visibility()

        if not self.filehandler.file_loaded:
            self._clear_main_area()
            self._waiting_for_redraw = False
            return False

        if self.imagehandler.page_is_available():
            distribution_axis = constants.DISTRIBUTION_AXIS
            alignment_axis = constants.ALIGNMENT_AXIS
            pixbuf_count = 2 if self.displayed_double() else 1 # XXX limited to at most 2 pages
            pixbuf_list = list(self.imagehandler.get_pixbufs(pixbuf_count))
            size_list = [[pixbuf.get_width(), pixbuf.get_height()]
                         for pixbuf in pixbuf_list]

            if self.is_manga_mode:
                orientation = constants.MANGA_ORIENTATION
            else:
                orientation = constants.WESTERN_ORIENTATION

            # Rotation handling:
            # - apply Exif rotation on individual images
            # - apply automatic rotation (size based) on whole page
            # - apply manual rotation on whole page
            if prefs['auto rotate from exif']:
                rotation_list = [image_tools.get_implied_rotation(pixbuf)
                                 for pixbuf in pixbuf_list]
            else:
                rotation_list = [0] * len(pixbuf_list)
            virtual_size = [0, 0]
            for i in range(pixbuf_count):
                if rotation_list[i] in (90, 270):
                    size_list[i].reverse()
                size = size_list[i]
                virtual_size[distribution_axis] += size[distribution_axis]
                virtual_size[alignment_axis] = max(virtual_size[alignment_axis],
                                                   size[alignment_axis])
            rotation = self._get_size_rotation(*virtual_size)
            rotation = (rotation + prefs['rotation']) % 360
            if rotation in (90, 270):
                distribution_axis, alignment_axis = alignment_axis, distribution_axis
                orientation = list(orientation)
                orientation.reverse()
                for i in range(pixbuf_count):
                    size_list[i].reverse()
            if rotation in (180, 270):
                orientation = tools.vector_opposite(orientation)
            for i in range(pixbuf_count):
                rotation_list[i] = (rotation_list[i] + rotation) % 360
            if prefs['vertical flip'] and rotation in (90, 270):
                orientation = tools.vector_opposite(orientation)
            if prefs['horizontal flip'] and rotation in (0, 180):
                orientation = tools.vector_opposite(orientation)

            viewport_size = () # dummy
            expand_area = False
            scrollbar_requests = [False] * len(self._scroll)
            # Visible area size is recomputed depending on scrollbar visibility
            while True:
                self._show_scrollbars(scrollbar_requests)
                new_viewport_size = self.get_visible_area_size()
                if new_viewport_size == viewport_size:
                    break
                viewport_size = new_viewport_size
                zoom_dummy_size = list(viewport_size)
                dasize = zoom_dummy_size[distribution_axis] - \
                    self._spacing * (pixbuf_count - 1)
                if dasize <= 0:
                    dasize = 1
                zoom_dummy_size[distribution_axis] = dasize
                scaled_sizes = self.zoom.get_zoomed_size(size_list, zoom_dummy_size,
                    distribution_axis)
                self.layout = layout.FiniteLayout(scaled_sizes,
                                                  viewport_size,
                                                  orientation,
                                                  self._spacing,
                                                  expand_area,
                                                  distribution_axis,
                                                  alignment_axis)
                union_scaled_size = self.layout.get_union_box().get_size()
                scrollbar_requests = map(operator.or_, scrollbar_requests,
                    tools.smaller(viewport_size, union_scaled_size))
                if len(filter(None, scrollbar_requests)) > 1 and not expand_area:
                    expand_area = True
                    viewport_size = () # start anew

            for i in range(pixbuf_count):
                pixbuf_list[i] = image_tools.fit_pixbuf_to_rectangle(
                    pixbuf_list[i], scaled_sizes[i], rotation_list[i])

            for i in range(pixbuf_count):
                if prefs['horizontal flip']:
                    pixbuf_list[i] = pixbuf_list[i].flip(horizontal=True)
                if prefs['vertical flip']:
                    pixbuf_list[i] = pixbuf_list[i].flip(horizontal=False)
                pixbuf_list[i] = self.enhancer.enhance(pixbuf_list[i])

            for i in range(pixbuf_count):
                image_tools.set_from_pixbuf(self.images[i], pixbuf_list[i])

            scales = tuple(map(lambda x, y: math.sqrt(tools.div(
                tools.volume(x), tools.volume(y))), scaled_sizes, size_list))

            resolutions = tuple(map(lambda x, y: x + [y,], size_list, scales))
            if self.is_manga_mode:
                resolutions = tuple(reversed(resolutions))
            self.statusbar.set_resolution(resolutions)
            self.statusbar.update()

            smartbg = prefs['smart bg']
            smartthumbbg = prefs['smart thumb bg'] and prefs['show thumbnails']
            if smartbg or smartthumbbg:
                bg_colour = self.imagehandler.get_pixbuf_auto_background(pixbuf_count)
            if smartbg:
                self.set_bg_colour(bg_colour)
            if smartthumbbg:
                self.thumbnailsidebar.change_thumbnail_background_color(bg_colour)

            self._main_layout.window.freeze_updates()

            self._main_layout.set_size(*union_scaled_size)
            content_boxes = self.layout.get_content_boxes()
            for i in range(pixbuf_count):
                self._main_layout.move(self.images[i],
                    *content_boxes[i].get_position())

            for i in range(pixbuf_count):
                self.images[i].show()
            for i in range(pixbuf_count, len(self.images)):
                self.images[i].hide()

            # Reset orientation so scrolling behaviour is sane.
            if self.is_manga_mode:
                self.layout.set_orientation(constants.MANGA_ORIENTATION)
            else:
                self.layout.set_orientation(constants.WESTERN_ORIENTATION)

            if scroll_to is not None:
                destination = (scroll_to,) * 2
                if constants.SCROLL_TO_START == scroll_to:
                    index = constants.FIRST_INDEX
                elif constants.SCROLL_TO_END == scroll_to:
                    index = constants.LAST_INDEX
                else:
                    index = None
                self.scroll_to_predefined(destination, index)

            self._main_layout.window.thaw_updates()
        else:
            # Save scroll destination for when the page becomes available.
            self._last_scroll_destination = scroll_to
            # If the pixbuf for the current page(s) isn't available,
            # hide all images to clear any old pixbufs.
            # XXX How about calling self._clear_main_area?
            for i in range(len(self.images)):
                self.images[i].hide()
            self._show_scrollbars([False] * len(self._scroll))

        self._waiting_for_redraw = False

        return False