                              (this-as this
                                (let [props (props this)
                                      world (get props :world)
-                                     _ (assert (instance? Atom world) "world should be atom?")
                                      wld @world
-                                     desc (:desc wld)
+                                     editor (get props :editor)
+                                     ed @editor
+                                     desc (or (:draft-desc ed) (:desc wld))
                                      container-w (:view-width wld)
                                      _ (assert (number? container-w))
                                      container-h (:view-height wld)

                                     ha-starts (:objects desc)
                                     polys (apply concat (vals (:seen-polys wld)))

                                     editor (get props :editor)
                                     ed @editor
                                     sel (:selection ed)]
                                 (sab/html [:div {:style   {:backgroundColor "blue"
                                                            :width           (+ container-w 20)
                                                            :height          (+ container-h 20)
                                                            :position        "relative"
                                                            :overflow        "scroll"}
                                                  :onClick (fn [evt]
                                                             (let [t (.-currentTarget evt)
                                                                   mx (+ (- (.-pageX evt) (.-offsetLeft t))
                                                                         (.-scrollLeft t))
                                                                   my (+ (- (.-pageY evt) (.-offsetTop t))
                                                                         (.-scrollTop t))
                                                                   [wx wy] (view->world props mx my)
                                                                   found-things (things-under wld wx wy)]
                                                               (println "click at" mx my "->" wx wy)
                                                               (println "found under mouse:" found-things)
                                                               (swap! editor assoc
                                                                      :selection
                                                                      (if-let [new-sel (first found-things)]
                                                                        (if (.-shiftKey evt)
                                                                          (if (contains? sel new-sel)
                                                                            (disj sel new-sel)
                                                                            (conj sel new-sel))
                                                                          #{new-sel})
                                                                        (if (.-shiftKey evt)
                                                                          sel
                                                                          #{})))))
                                                  :onScroll
                                                           (fn [scroll-evt]
                                                             (let [n (.-target scroll-evt)]
                                                               (update-world! world
                                                                              (fn [w]
                                                                                (let [[sx sy] (view->world props (.-scrollLeft n) (+ (.-scrollTop n) container-h))]
                                                                                  #_(println "update from scroll:"
                                                                                             (.-scrollLeft n) (+ (.-scrollTop n) container-h)
                                                                                             "->" sx sy)
                                                                                  (assoc w :scroll-x sx
                                                                                           :scroll-y sy))))))}
                                            [:svg {:width               (* world-w x-scale)
                                                   :height              (* world-h y-scale)
                                                   :style               {:position "absolute"}

                   [:objects id])
                 (has-under wld x y)))))

(def drag-threshold 2)

(defn editor-start-new-thing [ed x y now-x now-y]
  ;todo: HA _or_ wall
  (let [new-id (inc (apply max (map first (:walls (:draft-desc ed)))))
        _ (println "create new wall" new-id x y now-x now-y)
        new-thing-handle [:walls new-id]
        ax x
        ay y
        bx now-x
        by now-y]
    (assoc ed
      :move-mode :resizing
      :selection #{new-thing-handle}
      :draft-desc (assoc-in
                    (:draft-desc ed)
                    new-thing-handle
                    {:x (.min js/Math ax bx)
                     :y (.min js/Math ay by)
                     :w (.abs js/Math (- bx ax))
                     :h (.abs js/Math (- by ay))}))))

(defn editor-move-selection [ed dx dy]
  (println "move selection by" dx dy)
  (assoc ed
    :move-mode :moving
    :draft-desc
    (reduce
      (fn [desc sel-path]
        (update-in desc sel-path (fn [{x :x y :y :as obj}]
                                   (assoc obj :x (+ x dx)
                                              :y (+ y dy)))))
      (:draft-desc ed)
      (:selection ed))))

(defn editor-resize-selection [ed dx dy]
  (println "resize selection"
           (first (:selection ed))
           (get-in (:draft-desc ed)
                   (first (:selection ed)))
           "by" dx dy)
  (let [[sx sy] (:last-loc ed)
        {x :x y :y w :w h :h} (get-in (:draft-desc ed) (first (:selection ed)))
        ; if sx is rightish, adjust width only; else adjust width and x
        [nx nw] (if (> sx (+ x (/ w 2)))
                  [x (+ w dx)]
                  [(+ x dx) (- w dx)])
        ; if sy is toppish, adjust height only; else adjust height and y
        [ny nh] (if (> sy (+ y (/ h 2)))
                  [y (+ h dy)]
                  [(+ y dy) (- h dy)])
        [nx nw] (if (< nw 0)
                  [(+ nx nw) (.abs js/Math nw)]
                  [nx nw])
        [ny nh] (if (< nh 0)
                  [(+ ny nh) (.abs js/Math nh)]
                  [ny nh])]
    (assoc ed :draft-desc (update-in (:draft-desc ed)
                                     (first (:selection ed))
                                     assoc
                                     :x nx :y ny
                                     :w nw :h nh)
              :move-mode :resizing)))

(def resize-threshold 4)

(defn wall-centerish-point? [wld wx wy]
  (some (fn [{x :x y :y w :w h :h}]
          (and (<= (+ x resize-threshold) wx (- (+ x w) resize-threshold))
               (<= (+ y resize-threshold) wy (- (+ y h) resize-threshold))))
        (:walls (:desc wld))))

(def world-widget
  (let [props (fn [this] (aget (.-props this) "args"))
        ; world -> view: scale up and flip
