(fn attach-imstate [view] (set view.imstate {}) (local cls view.__index) (fn view.on_mouse_pressed [self button x y clicks] (tset self.imstate button :pressed) (cls.on_mouse_pressed self button x y clicks)) (fn view.on_mouse_moved [self x y dx dy] (cls.on_mouse_moved self x y dx dy)) (fn view.on_mouse_released [self button x y] (tset self.imstate button :released) (cls.on_mouse_released self button x y)) (fn view.draw [self] (cls.draw self) (when (= self.imstate.left :released) (set self.imstate.active nil)) (each [_ button (pairs [:left :middle :right])] (tset self.imstate button (match (. self.imstate button) :pressed :down :down :down :released nil))))) (fn make-tag [tag] (match (type tag) :string tag :table (table.concat tag "::") _ (tostring tag))) (fn mouse-inside [x y w h] (local (mx my) (values (love.mouse.getX) (love.mouse.getY))) (and (>= mx x) (<= mx (+ x w)) (>= my y) (<= my (+ y h)))) (fn activate [view tag x y w h] (when (and (= view.imstate.left :pressed) (mouse-inside x y w h)) (set view.imstate.active (make-tag tag)) true)) (fn active? [view tag] (= view.imstate.active (make-tag tag))) (fn button [view tag x y w h] (activate view tag x y w h) (and (active? view tag) (= view.imstate.left :released) (mouse-inside x y w h))) {: attach-imstate : mouse-inside : activate : active? : button}