
class WCO_CLINETOOL

  @@ltcursor = 0
  # This is the standard Ruby initialize method that is called when you create
  # a new object.
  def initialize
    @ip1 = nil
    @ip2 = nil
    @xdown = 0
    @ydown = 0
    if @@ltcursor == 0
      c = File.join(File.dirname(__FILE__),  "WCO_CLINETOOL", "clinetool_cursor.png")
      @@ltcursor = UI::create_cursor(c, 1, 30)
    end
  end

  def onSetCursor
    UI::set_cursor(@@ltcursor)
  end

  # The activate method is called by SketchUp when the tool is first selected.
  # it is a good place to put most of your initialization
  def activate
    # The Sketchup::InputPoint class is used to get 3D points from screen
    # positions.  It uses the SketchUp inferencing code.
    # In this tool, we will have two points for the endpoints of the line.
    @ip1 = Sketchup::InputPoint.new
    @ip2 = Sketchup::InputPoint.new
    @ip = Sketchup::InputPoint.new
    @drawn = false

    # This sets the label for the VCB
    Sketchup::set_status_text "Length", SB_VCB_LABEL

    self.reset(nil)
  end

  # deactivate is called when the tool is deactivated because
  # a different tool was selected
  def deactivate(view)
    view.invalidate if @drawn
  end

  # The onMouseMove method is called whenever the user moves the mouse.
  # because it is called so often, it is important to try to make it efficient.
  # In a lot of tools, your main interaction will occur in this method.
  def onMouseMove(flags, x, y, view)
    if( @state == 0 )
      # We are getting the first end of the line.  Call the pick method
      # on the InputPoint to get a 3D position from the 2D screen position
      # that is bassed as an argument to this method.
      @ip.pick view, x, y
      if( @ip != @ip1 )
  # if the point has changed from the last one we got, then
  # see if we need to display the point.  We need to display it
  # if it has a display representation or if the previous point
  # was displayed.  The invalidate method on the view is used
  # to tell the view that something has changed so that you need
  # to refresh the view.
  view.invalidate if( @ip.display? or @ip1.display? )
  @ip1.copy! @ip

  # set the tooltip that should be displayed to this point
  view.tooltip = @ip1.tooltip
      end
    else
      # Getting the second end of the line
      # If you pass in another InputPoint on the pick method of InputPoint
      # it uses that second point to do additional inferencing such as
      # parallel to an axis.
      @ip2.pick view, x, y, @ip1
      view.tooltip = @ip2.tooltip if( @ip2.valid? )
      view.invalidate

      # Update the length displayed in the VCB
      if( @ip2.valid? )
  length = @ip1.position.distance(@ip2.position)
  Sketchup::set_status_text length.to_s, SB_VCB_VALUE
      end

      # Check to see if the mouse was moved far enough to create a line.
      # This is used so that you can create a line by either draggin
      # or doing click-move-click
      if( (x-@xdown).abs > 10 || (y-@ydown).abs > 10 )
  @dragging = true
      end
    end
  end

  # The onLButtonDOwn method is called when the user presses the left mouse button.
  def onLButtonDown(flags, x, y, view)
    # When the user clicks the first time, we switch to getting the
    # second point.  When they click a second time we create the line
    if( @state == 0 )
      @ip1.pick view, x, y
      if( @ip1.valid? )
  @state = 1
  Sketchup::set_status_text "Select second end", SB_PROMPT
  @xdown = x
  @ydown = y
      end
    else
      # create the line on the second click
      if( @ip2.valid? )
  self.create_geometry(@ip1.position, @ip2.position,view)
  self.reset(view)
      end
    end

    # Clear any inference lock
    view.lock_inference
  end

  # The onLButtonUp method is called when the user releases the left mouse button.
  def onLButtonUp(flags, x, y, view)
    # If we are doing a drag, then create the line on the mouse up event
    if( @dragging && @ip2.valid? )
      self.create_geometry(@ip1.position, @ip2.position,view)
      self.reset(view)
    end
  end

  # onKeyDown is called when the user presses a key on the keyboard.
  # We are checking it here to see if the user pressed the shift key
  # so that we can do inference locking
  def onKeyDown(key, repeat, flags, view)
    if( key == CONSTRAIN_MODIFIER_KEY && repeat == 1 )
      @shift_down_time = Time.now

      # if we already have an inference lock, then unlock it
      if( view.inference_locked? )
  # calling lock_inference with no arguments actually unlocks
  view.lock_inference
      elsif( @state == 0 && @ip1.valid? )
  view.lock_inference @ip1
      view.line_width = 3
      elsif( @state == 1 && @ip2.valid? )
  view.lock_inference @ip2, @ip1
      view.line_width = 3
      end
    end
  end

  # onKeyUp is called when the user releases the key
  # We use this to unlock the interence
  # If the user holds down the shift key for more than 1/2 second, then we
  # unlock the inference on the release.  Otherwise, the user presses shift
  # once to lock and a second time to unlock.
  def onKeyUp(key, repeat, flags, view)
    if( key == CONSTRAIN_MODIFIER_KEY &&
       view.inference_locked? &&
       (Time.now - @shift_down_time) > 0.5 )
      view.lock_inference
    end
  end

  # onUserText is called when the user enters something into the VCB
  # In this implementation, we create a line of the entered length if
  # the user types a length while selecting the second point
  def onUserText(text, view)
    # We only accept input when the state is 1 (i.e. getting the second point)
    # This could be enhanced to also modify the last line created if a length
    # is entered after creating a line.
    return if not @state == 1
    return if not @ip2.valid?

    # The user may type in something that we can't parse as a length
    # so we set up some exception handling to trap that
    begin
      value = text.to_l
    rescue
      # Error parsing the text
      UI.beep
      puts "Cannot convert #{text} to a Length"
      value = nil
      Sketchup::set_status_text "", SB_VCB_VALUE
    end
    return if !value

    # Compute the direction and the second point
    pt1 = @ip1.position
    vec = @ip2.position - pt1
    if( vec.length == 0.0 )
      UI.beep
      return
    end
    vec.length = value
    pt2 = pt1 + vec

    # Create a line
    self.create_geometry(pt1, pt2, view)
    self.reset(view)
  end

  # The draw method is called whenever the view is refreshed.  It lets the
  # tool draw any temporary geometry that it needs to.
  def draw(view)
    if( @ip1.valid? )
      if( @ip1.display? )
  @ip1.draw(view)
  @drawn = true
      end

      if( @ip2.valid? )
  @ip2.draw(view) if( @ip2.display? )

  # The set_color_from_line method determines what color
  # to use to draw a line based on its direction.  For example
  # red, green or blue.
  view.set_color_from_line(@ip1, @ip2)
  self.draw_geometry(@ip1.position, @ip2.position, view)
  @drawn = true
      end
    end
  end

  # onCancel is called when the user hits the escape key
  def onCancel(flag, view)
    self.reset(view)
  end


  # The following methods are not directly called from SketchUp.  They are
  # internal methods that are used to support the other methods in this class.

  # Reset the tool back to its initial state
  def reset(view)
    # This variable keeps track of which point we are currently getting
    @state = 0

    # Display a prompt on the status bar
    Sketchup::set_status_text("Select first end", SB_PROMPT)

    # clear the InputPoints
    @ip1.clear
    @ip2.clear
    @ip.clear

    if( view )
      view.tooltip = nil
      view.invalidate if @drawn
    end

    @drawn = false
    @dragging = false
  end

  # Create new geometry when the user has selected two points.
  def create_geometry(p1, p2, view)
    view.model.entities.add_cpoint(p1)
    view.model.entities.add_cpoint(p2)
    view.model.entities.add_cline(p1,p2)

  end

  # Draw the geometry
  def draw_geometry(pt1, pt2, view)
    view.draw_line(pt1, pt2)
  end

end # class LineTool


toolbar = UI::Toolbar.new "WCO-Toolbar"

cmd = UI::Command.new("Draw Construction-Line...") {
  Sketchup.active_model.select_tool WCO_CLINETOOL.new
}
cmd.small_icon =  "WCO_CLINETOOL/clinetool_icon.png"
cmd.large_icon =  "WCO_CLINETOOL/clinetool_icon.png"
cmd.tooltip = "Construction Line"
cmd.status_bar_text = "Construction Line"
cmd.menu_text = "Construction Line"
toolbar.add_item cmd