emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: DocView AutoFitting via "doc-view-autofit-mode"


From: Moritz Maxeiner
Subject: Re: DocView AutoFitting via "doc-view-autofit-mode"
Date: Mon, 02 Apr 2012 19:58:45 +0200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:11.0) Gecko/20120314 Thunderbird/11.0

Hi,

 so I updated a few things:

`C-1 W' enables width
autofitting.

Done, see the added paragraph in the description, in short, either sets the 
type and if
off turns on autofitting, or if on and type is already sets turn off 
autofitting, e.g.
`C-1 W' `C-1 W' turns on autofitting and sets it to width and then turns it off 
again.

so you could just enable lexical binding for the complete
file and use just `let'

It is already enabled (bzr trunk), I just didn't see it. Strangely enough, using
`lexical-let' inside a lexical binding enabled file produces tons of "bad 
lexing"
errors when used with named functions (It doesn't in lexica-binding disabled 
files).

e.g. this will produce a [bad-lexical-ref] on `M-x eval-buffer RET' `M-x bar 
RET', but not
when the file header (which enables lexical-binding) is removed. So far reading 
the
information about lexical-binding in emacs has not let me to an understanding 
why, but meh.

;;; foo.el --- Foo -*- lexical-binding: t -*-

(defun foo (window)
  (message "%s" window))

(defun bar ()
  (interactive)
  (lexical-let ((foobar (selected-window)))
    (foo foobar)))

Which is why I made the part you comment on here

make that lambda a named function

a lambda instead of a named function in the first place (With a lambda is works
both with lexical-binding enabled and not, but not with a named function).

Well, it's let now instead of lexical-let since lexical-binding is enabled
for doc-view anyway.


Compare symbols with `eq'

Done, but any specific reason for that? `equal's doc-string states that symbols 
must match exactly,
so in the specific event of symbols, don't equal and eq behave the same?

Why 2 whens instead of one if?

'cause one alternative of the if has to use progn anyway and at the time I had 
just copy-pasted
the first and altered it to match. Changed to if now.


If I missed anything you suggested or someone has more suggestions to better 
the minor mode please
do say so.

Bye,
  cal


[Description]

This is a minor mode allowing documents viewed with DocView to be automaticly
refitted to the window they are shown in (no need to hit W/H/P every
time the window size changes).

Mode function is `doc-view-autofit-mode' and 
doc-view-fit-[width/height/page]-to-window
have been modified for a prefix argument, which if is non-nil and numeric value 
1 does
(type refers to the part in brackets):

1. If autofit mode is off, turn it on with this type
2. If autofit is on and already set to this type: Turn autofit off
3. If autofit is on and not set to this type: Set it to this type


It is implemented by adding a local hook to window-configuration-change-hook
for the buffer the document is in, which in turn either starts or increases
- if already started - a buffer local timer every time the hook is called.
When the timer runs out, it calls doc-view-fit-[width/height/page]-to-window
according to a buffer local variable.

The timer is used, so that when the hook triggers a lot in a short period
of time it doesn't cause too much overhead (Useful for slower computers).

[ChangeLog]

* doc-view.el (doc-view-fit-check-prefix doc-view-fit-width-to-window)
  (doc-view-fit-height-to-window doc-view-fit-page-to-window)
  (doc-view-autofit-timer-start doc-view-autofit-timer-inc)
  (doc-view-autofit-default-fit doc-view-autofit-timer-function) 
doc-view-fit-height-to-window
  (doc-view-autofit-fit doc-view-autofit-mode): New minor mode
  with customs and functions for automatic fitting in DocView buffers;
  also added prefix argument handling to doc-view-fit-*-to-window for
  setting the autofitting type easily.

[Patch]

*** doc-view.el    2012-04-02 18:49:03.380742235 +0200
--- doc-view.el    2012-04-02 19:09:03.163769708 +0200
*************** OpenDocument format)."
*** 676,752 ****
    (interactive (list doc-view-shrink-factor))
    (doc-view-enlarge (/ 1.0 factor)))

! (defun doc-view-fit-width-to-window ()
!   "Fit the image width to the window width."
!   (interactive)
!   (let ((win-width (- (nth 2 (window-inside-pixel-edges))
!                       (nth 0 (window-inside-pixel-edges))))
!         (slice (doc-view-current-slice)))
!     (if (not slice)
!         (let ((img-width (car (image-display-size
!                                (image-get-display-property) t))))
!           (doc-view-enlarge (/ (float win-width) (float img-width))))
!
!       ;; If slice is set
!       (let* ((slice-width (nth 2 slice))
!              (scale-factor (/ (float win-width) (float slice-width)))
!              (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!
!         (doc-view-enlarge scale-factor)
!         (setf (doc-view-current-slice) new-slice)
!         (doc-view-goto-page (doc-view-current-page))))))
!
! (defun doc-view-fit-height-to-window ()
!   "Fit the image height to the window height."
!   (interactive)
!   (let ((win-height (- (nth 3 (window-inside-pixel-edges))
!                        (nth 1 (window-inside-pixel-edges))))
!         (slice (doc-view-current-slice)))
!     (if (not slice)
!         (let ((img-height (cdr (image-display-size
!                                 (image-get-display-property) t))))
!           ;; When users call 'doc-view-fit-height-to-window',
!           ;; they might want to go to next page by typing SPC
!           ;; ONLY once. So I used '(- win-height 1)' instead of
!           ;; 'win-height'
!           (doc-view-enlarge (/ (float (- win-height 1)) (float img-height))))
!
!       ;; If slice is set
!       (let* ((slice-height (nth 3 slice))
!              (scale-factor (/ (float (- win-height 1)) (float slice-height)))
!              (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!
!         (doc-view-enlarge scale-factor)
!         (setf (doc-view-current-slice) new-slice)
!         (doc-view-goto-page (doc-view-current-page))))))
!
! (defun doc-view-fit-page-to-window ()
!   "Fit the image to the window.
  More specifically, this function enlarges image by:

  min {(window-width / image-width), (window-height / image-height)} times."
!   (interactive)
!   (let ((win-width (- (nth 2 (window-inside-pixel-edges))
!                       (nth 0 (window-inside-pixel-edges))))
!         (win-height (- (nth 3 (window-inside-pixel-edges))
!                        (nth 1 (window-inside-pixel-edges))))
!         (slice (doc-view-current-slice)))
!     (if (not slice)
!         (let ((img-width (car (image-display-size
!                                (image-get-display-property) t)))
!               (img-height (cdr (image-display-size
!                                 (image-get-display-property) t))))
!           (doc-view-enlarge (min (/ (float win-width) (float img-width))
!                                  (/ (float (- win-height 1)) (float 
img-height)))))
!       ;; If slice is set
!       (let* ((slice-width (nth 2 slice))
!              (slice-height (nth 3 slice))
!              (scale-factor (min (/ (float win-width) (float slice-width))
!                                 (/ (float (- win-height 1)) (float 
slice-height))))
!              (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!         (doc-view-enlarge scale-factor)
!         (setf (doc-view-current-slice) new-slice)
!         (doc-view-goto-page (doc-view-current-page))))))

  (defun doc-view-reconvert-doc ()
    "Reconvert the current document.
--- 676,773 ----
    (interactive (list doc-view-shrink-factor))
    (doc-view-enlarge (/ 1.0 factor)))

! (defun doc-view-fit-check-prefix (arg type)
!   "Called by `doc-view-fit-width-to-window', `doc-view-fit-height-to-window'
! and `doc-view-fit-page-to-window' to determine if a prefix argument
! was used and call the appropriate function for each value.
!
! Numeric value 1: Handle automatic fitting"
!   (if (and arg
!            (= (prefix-numeric-value arg) 1))
!       (if doc-view-autofit-mode
!           (if (eq type doc-view-autofit-type)
!               (doc-view-autofit-mode 'toggle)
!             (setq doc-view-autofit-type type) t)
!         (set (make-local-variable 'doc-view-autofit-type) type)
!         (doc-view-autofit-mode) nil) t))
!
! (defun doc-view-fit-width-to-window (arg)
!   "Fit the image width to the window width (Non-nil prefix argument
! with numeric value 1 enables doing this automaticly)."
!   (interactive "P")
!   (when (doc-view-fit-check-prefix arg 'width)
!     (let ((win-width (- (nth 2 (window-inside-pixel-edges))
!                         (nth 0 (window-inside-pixel-edges))))
!           (slice (doc-view-current-slice)))
!       (if (not slice)
!           (let ((img-width (car (image-display-size
!                                  (image-get-display-property) t))))
!             (doc-view-enlarge (/ (float win-width) (float img-width))))
!
!         ;; If slice is set
!         (let* ((slice-width (nth 2 slice))
!                (scale-factor (/ (float win-width) (float slice-width)))
!                (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!
!           (doc-view-enlarge scale-factor)
!           (setf (doc-view-current-slice) new-slice)
!           (doc-view-goto-page (doc-view-current-page)))))))
!
! (defun doc-view-fit-height-to-window (arg)
!   "Fit the image height to the window height (Non-nil prefix argument
! with numeric value 1 enables doing this automaticly)."
!   (interactive "P")
!   (when (doc-view-fit-check-prefix arg 'height)
!     (let ((win-height (- (nth 3 (window-inside-pixel-edges))
!                          (nth 1 (window-inside-pixel-edges))))
!           (slice (doc-view-current-slice)))
!       (if (not slice)
!           (let ((img-height (cdr (image-display-size
!                                   (image-get-display-property) t))))
!             ;; When users call 'doc-view-fit-height-to-window',
!             ;; they might want to go to next page by typing SPC
!             ;; ONLY once. So I used '(- win-height 1)' instead of
!             ;; 'win-height'
!             (doc-view-enlarge (/ (float (- win-height 1)) (float 
img-height))))
!
!         ;; If slice is set
!         (let* ((slice-height (nth 3 slice))
!                (scale-factor (/ (float (- win-height 1)) (float 
slice-height)))
!                (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!
!           (doc-view-enlarge scale-factor)
!           (setf (doc-view-current-slice) new-slice)
!           (doc-view-goto-page (doc-view-current-page)))))))
!
! (defun doc-view-fit-page-to-window (arg)
!   "Fit the image to the window (Non-nil prefix argument
! with numeric value 1 enables doing this automaticly).
  More specifically, this function enlarges image by:

  min {(window-width / image-width), (window-height / image-height)} times."
!   (interactive "P")
!   (when (doc-view-fit-check-prefix arg 'page)
!     (let ((win-width (- (nth 2 (window-inside-pixel-edges))
!                         (nth 0 (window-inside-pixel-edges))))
!           (win-height (- (nth 3 (window-inside-pixel-edges))
!                          (nth 1 (window-inside-pixel-edges))))
!           (slice (doc-view-current-slice)))
!       (if (not slice)
!           (let ((img-width (car (image-display-size
!                                  (image-get-display-property) t)))
!                 (img-height (cdr (image-display-size
!                                   (image-get-display-property) t))))
!             (doc-view-enlarge (min (/ (float win-width) (float img-width))
!                                    (/ (float (- win-height 1)) (float 
img-height)))))
!         ;; If slice is set
!         (let* ((slice-width (nth 2 slice))
!                (slice-height (nth 3 slice))
!                (scale-factor (min (/ (float win-width) (float slice-width))
!                                   (/ (float (- win-height 1)) (float 
slice-height))))
!                (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) 
slice)))
!           (doc-view-enlarge scale-factor)
!           (setf (doc-view-current-slice) new-slice)
!           (doc-view-goto-page (doc-view-current-page)))))))

  (defun doc-view-reconvert-doc ()
    "Reconvert the current document.
*************** See the command `doc-view-mode' for more
*** 1557,1562 ****
--- 1578,1654 ----
         (doc-view-goto-page page)))))


+ ;;;; Automatic fitting minor mode
+
+ (defcustom doc-view-autofit-timer-start 1.0
+   "Initial value (seconds) for the timer that delays the fitting when
+ `doc-view-autofit-fit' is called (Which is when a window
+ configuration change occurs and a document needs to be fitted)."
+   :type 'number
+   :group 'doc-view)
+
+ (defcustom doc-view-autofit-timer-inc 0.02
+   "Value to increase (seconds) the timer (see `doc-view-autofit-timer-start')
+ by, if there is another window configuration change occuring, before
+ it runs out."
+   :type 'number
+   :group 'doc-view)
+
+ (defcustom doc-view-autofit-default-fit 'width
+   "The fitting type initially used when mode is enabled.
+ Valid values are: width, height, page."
+   :type 'symbol
+   :group 'doc-view)
+
+ (defun doc-view-autofit-timer-function (window)
+   "The timer function used in `doc-view-autofit-fit' to be called delayed.
+ It expects `doc-view-autofit-timer' and `doc-view-autofit-type' to be
+ set to valid values."
+   (if (window-live-p window)
+       (save-selected-window
+         (select-window window)
+         (cancel-timer doc-view-autofit-timer)
+         (setq doc-view-autofit-timer nil)
+         (cond
+          ((eq 'width doc-view-autofit-type)
+           (doc-view-fit-width-to-window nil))
+          ((eq 'height doc-view-autofit-type)
+           (doc-view-fit-height-to-window nil))
+          ((eq 'page doc-view-autofit-type)
+           (doc-view-fit-page-to-window nil))))))
+
+ (defun doc-view-autofit-fit ()
+   "Fits the document in the selected window's buffer
+ delayed withdoc-view-autofit a timer, so multiple calls in succession
+ don't cause as much overhead."
+   (let ((window (selected-window)))
+     (if doc-view-autofit-timer
+         (timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc)
+       (setq doc-view-autofit-timer
+             (run-with-timer doc-view-autofit-timer-start nil
+                             'doc-view-autofit-timer-function window)))))
+
+ (define-minor-mode doc-view-autofit-mode
+   "Minor mode for automatic (timer based) fitting in DocView."
+   :lighter " AFit" :group 'doc-view
+   (if doc-view-autofit-mode
+       (progn (if (or (not (boundp 'doc-view-autofit-type))
+                      (not doc-view-autofit-type))
+                  (set (make-local-variable 'doc-view-autofit-type)
+                       doc-view-autofit-default-fit))
+              (set (make-local-variable 'doc-view-autofit-timer) nil)
+              (add-hook 'window-configuration-change-hook
+                        'doc-view-autofit-fit nil t)
+              (doc-view-autofit-fit))
+     (remove-hook 'window-configuration-change-hook
+                  'doc-view-autofit-fit t)
+     (when doc-view-autofit-timer
+       (cancel-timer doc-view-autofit-timer)
+       (setq doc-view-autofit-timer nil))
+     (setq doc-view-autofit-type nil))
+   doc-view-autofit-mode)
+
+
  (provide 'doc-view)

  ;; Local Variables:

Attachment: doc-view-autofit.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]