[Split database-range-view into normal and cached subclass clinton@unknownlamer.org**20080115222533 Caching is useful in many cases but here it does not save too much consing and causes errors when instances are deleted from the database. A better solution would be to catch unbound persistent slot accesses and refresh the cache then. ] { hunk ./src/web-common.lisp 65 +;; Should be renamed to query-range-view with a query-view parent and +;; cached-query-view child class. The methods should maybe be renamed +;; as well. +;; Min/max support could perhaps be put into a mixin? It is probably +;; not worth the effort hunk ./src/web-common.lisp 75 - (current-window :initform nil :accessor range-view.current-window) hunk ./src/web-common.lisp 77 + ;; should total-items be cached? hunk ./src/web-common.lisp 83 +(defcomponent cached-database-range-view (database-range-view) + ((current-window :initform nil :accessor range-view.current-window))) + hunk ./src/web-common.lisp 88 +(defgeneric range-view.current-window (range)) + hunk ./src/web-common.lisp 106 +(defmethod range-view.current-window ((range database-range-view)) + (let ((limit (range-view.window-size range)) + (skip (* (range-view.window-size range) + (range-view.offset range)))) + (mapcar + (lambda (i) (cons (incf skip) i)) + (with-slots (minimum maximum) range + (if (reversep range) + (range-view-get-instances range minimum maximum + :from-end t :limit limit :skip skip) + (range-view-get-instances range minimum maximum + :from-end nil :limit limit :skip skip)))))) + hunk ./src/web-common.lisp 131 -(defun range-view-get-forward (range old-offset new-offset) - (let ((base-item (car (last (range-view.current-window-items range)))) - (limit (range-view.window-size range)) - (skip (if (= new-offset old-offset) - 0 - (* (range-view.window-size range) - (1- (- new-offset old-offset)))))) - (with-slots (minimum maximum) range - (if (reversep range) - (range-view-get-instances range minimum (or base-item maximum) - :from-end t :limit limit :skip skip) - (range-view-get-instances range (or base-item minimum) maximum - :from-end nil :limit limit :skip skip))))) - -(defun range-view-get-backward (range old-offset new-offset) - (let ((base-item (car (range-view.current-window-items range))) - (limit (range-view.window-size range)) - (skip (* (range-view.window-size range) - (1- (- old-offset new-offset))))) - (with-slots (minimum maximum) range - (if (reversep range) - (range-view-get-instances range (or base-item minimum) maximum - :from-end nil :limit limit :skip skip) - (range-view-get-instances range minimum (or base-item maximum) - :from-end t :limit limit :skip skip))))) - -(defmethod (setf range-view.offset) :around (new-offset - (range database-range-view)) - (assert (>= new-offset 0) (new-offset)) - (let ((old-offset (range-view.offset range))) - (call-next-method) - (setf - (range-view.current-window range) - (let ((start (* (range-view.window-size range) - (range-view.offset range)))) - (cond ;; Need to loop for the following cases when difference > 1 - ((>= new-offset old-offset) - (mapcar - (lambda (i) (cons (incf start) i)) - (range-view-get-forward range old-offset new-offset))) - ((< new-offset old-offset) - (nreverse - (mapcar (lambda (i) (cons (incf start) i)) - (range-view-get-backward range old-offset new-offset)))))))) - - new-offset) - hunk ./src/web-common.lisp 168 +;; cached database range view +(defun range-view-get-forward (range old-offset new-offset) + (let ((base-item (car (last (range-view.current-window-items range)))) + (limit (range-view.window-size range)) + (skip (if (= new-offset old-offset) + 0 + (* (range-view.window-size range) + (1- (- new-offset old-offset)))))) + (with-slots (minimum maximum) range + (if (reversep range) + (range-view-get-instances range minimum (or base-item maximum) + :from-end t :limit limit :skip skip) + (range-view-get-instances range (or base-item minimum) maximum + :from-end nil :limit limit :skip skip))))) + +(defun range-view-get-backward (range old-offset new-offset) + (let ((base-item (car (range-view.current-window-items range))) + (limit (range-view.window-size range)) + (skip (* (range-view.window-size range) + (1- (- old-offset new-offset))))) + (with-slots (minimum maximum) range + (if (reversep range) + (range-view-get-instances range (or base-item minimum) maximum + :from-end nil :limit limit :skip skip) + (range-view-get-instances range minimum (or base-item maximum) + :from-end t :limit limit :skip skip))))) + +(defun range-view-reload-instances (range old-offset new-offset) + + (let ((start (* (range-view.window-size range) + (range-view.offset range)))) + (setf + (range-view.current-window range) + (mapcar + (lambda (i) (cons (incf start) i)) + (cond + ((>= new-offset old-offset) + (range-view-get-forward range old-offset new-offset)) + ((< new-offset old-offset) + (nreverse + (range-view-get-backward range old-offset new-offset)))))))) + +(defmethod (setf range-view.offset) :around (new-offset + (range cached-database-range-view)) + (assert (>= new-offset 0) (new-offset)) + (let ((old-offset (range-view.offset range))) + (call-next-method) + (range-view-reload-instances range old-offset new-offset) + new-offset)) + hunk ./src/web-common.lisp 334 -(defmethod shows ((self ranged-show-list)) - (range-view.current-window-items self)) +(defmethod shows ((range ranged-show-list)) + (range-view.current-window-items range)) hunk ./src/web-common.lisp 351 - (