JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
improve selection handling, hover
[crayon_mockup.git] / auto.coffee
index c415d0b..63870d5 100644 (file)
@@ -24,14 +24,20 @@ json_to_svg = (json) ->
                                el.setAttribute k, v
        return el
 
+next_widget_id = 0
 # public vars: x, y, width, height, el
 class Widget
+       # required args: svg
        constructor: (args) ->
-               @style = STYLE_NORMAL
-               @x = args?.x ? 1
-               @y = args?.y ? 1
-               @width = args?.width ? 50
-               @height = args?.height ? 34
+               @id = next_widget_id
+               next_widget_id += 1
+               @svg = args.svg
+               @style = args.style ? STYLE_NORMAL
+               @x = args.x ? 1
+               @y = args.y ? 1
+               @width = args.width ? 50
+               @height = args.height ? 34
+       destruct: ->
        clone: ->
                return new Widget @
        move: (args) ->
@@ -67,11 +73,15 @@ class RectWidget extends Widget
                @css_class = 'box'
                @el = json_to_svg rect:
                        x: @x + 1
-                       y: @x + 1
+                       y: @y + 1
                        width: @width - 2
                        height: @height - 2
                        class: 'box'
-                       style: 'filter: url(#crayon)'
+                       style: if @style is STYLE_NORMAL then 'filter: url(#crayon)' else ''
+               @svg.appendChild @el
+       destruct: ->
+               if @el?
+                       @svg.removeChild @el
        clone: ->
                return new RectWidget @
        move: (args) ->
@@ -133,16 +143,15 @@ init = ->
                class: 'canvas_border'
        
        supply = [
-               new RectWidget()
-               new RectWidget width: 12, height: 50
-               new RectWidget width: 70, height: 12
+               new RectWidget svg: svg
+               new RectWidget svg: svg, width: 12, height: 50
+               new RectWidget svg: svg, width: 70, height: 12
        ]
        for widget, i in supply
                widget.move {
                        x: 30 + i * 90 + (70 - widget.width) / 2
                        y: (supply_height - widget.height) / 2
                }
-               svg.appendChild widget.el
        
        # editor state
        on_canvas = []
@@ -151,7 +160,18 @@ init = ->
        dragging = false
        dragging_offset = x: 0, y: 0 # from mouse x,y -> widget x,y
 
-       # todo ask widgets
+       deselect_all = (args) ->
+               except = args?.except ? null
+               found = false
+               for w in selected
+                       if w is except
+                               found = true
+                       else
+                               w.set_style STYLE_NORMAL
+               if found
+                       selected = [except]
+               else
+                       selected = []
        closest_widget = (widgets, xy) ->
                prox = PROX_MAX + 1
                closest = null
@@ -161,7 +181,7 @@ init = ->
                                prox = new_prox
                                closest = w
                if prox < PROX_MAX
-                       return [prox, closest]
+                       return closest
                return null
        svg_event_to_xy = (e) ->
                unless svg_offset?
@@ -170,33 +190,39 @@ init = ->
                        x: Math.round(e.pageX - svg_offset.left)
                        y: Math.round(e.pageY - svg_offset.top)
                }
-       $svg.mousedown (e) ->
+       mousedown = (e) ->
+               mousemove e
+               if dragging # two mousedowns in a row?! it happens
+                       return mouseup e
                xy = svg_event_to_xy e
                if xy.y < supply_height
                        closest = closest_widget supply, xy
                        if closest?
-                               closest[1] = closest[1].clone()
-                               svg.appendChild closest[1].el
+                               closest = closest.clone()
+                               on_canvas.push closest
                else
                        closest = closest_widget on_canvas, xy
                if closest?
-                       selected = [closest[1]]
-                       closest[1].set_style STYLE_DRAGGING
+                       deselect_all except: closest
+                       selected = [closest]
+                       closest.set_style STYLE_DRAGGING
                        dragging = true
-                       dragging_offset.x = closest[1].x - xy.x
-                       dragging_offset.y = closest[1].y - xy.y
-                       mousemove e
+                       dragging_offset.x = closest.x - xy.x
+                       dragging_offset.y = closest.y - xy.y
+               else
+                       deselect_all()
                return false
-       $svg.mouseup (e) ->
+       mouseup = (e) ->
                mousemove e
+               if dragging
+                       for w in selected
+                               if w.y < supply_height
+                                       w.destruct()
+                               else
+                                       w.set_style STYLE_SELECTED
                dragging = false
-               if selected[0]?
-                       if selected[0].y > supply_height
-                               on_canvas.push selected[0]
-                       else
-                               svg.removeChild selected[0].el
-                       selected = []
                return false
+       prev_hover = null
        mousemove = (e) ->
                xy = svg_event_to_xy e
                if dragging
@@ -204,17 +230,25 @@ init = ->
                        xy.y += dragging_offset.y
                        selected[0].move xy
                else
-                       closest = closest_widget on_canvas, xy
-                       if closest?
-                               hover = closest[1]
-                       else
-                               hover = null
-                       for w in on_canvas
-                               if w is hover
-                                       w.set_style STYLE_HOVER
-                               else
-                                       w.set_style STYLE_NORMAL
+                       hover = closest_widget on_canvas, xy
+                       unless hover?
+                               hover = closest_widget supply, xy
+                       if hover != prev_hover
+                               prev_hover = hover
+                               for w in selected
+                                       if w.style is STYLE_HOVER and w isnt hover
+                                               w.set_style STYLE_SELECTED
+                               for w in supply
+                                       if w.style is STYLE_HOVER and w isnt hover
+                                               w.set_style STYLE_NORMAL
+                               for w in on_canvas
+                                       if w.style is STYLE_HOVER and w isnt hover
+                                               w.set_style STYLE_NORMAL
+                               if hover
+                                       hover.set_style STYLE_HOVER
                return false
+       $svg.mousedown mousedown
+       $svg.mouseup mouseup
        $svg.mousemove mousemove
        #($ document).keydown (e) ->