<commit_before>base = require('../base')
Collections = base.Collections
HasParent = base.HasParent
safebind = base.safebind
build_views = base.build_views

ContinuumView = require('./continuum_view').ContinuumView

LinearMapper = require('../mappers/1d/linear_mapper').LinearMapper
GridMapper = require('../mappers/2d/grid_mapper').GridMapper

ViewState = require('./view_state').ViewState


class PlotView extends ContinuumView

  view_options: () ->
    _.extend({plot_model: @model, plot_view: @}, @options)

  build_renderers: () ->
    build_views(@renderers, @mget_obj('renderers'), @view_options())

  build_axes: () ->
    build_views(@axes, @mget_obj('axes'), @view_options())

  build_tools: () ->
    build_views(@tools, @mget_obj('tools'), @view_options())

  build_overlays: () ->
    #add ids of renderer views into the overlay spec
    build_views(@overlays, @mget_obj('overlays'), @view_options())

  bind_overlays: () ->
    for overlayspec in @mget('overlays')
      @overlays[overlayspec.id].bind_events(this)

  bind_tools: () ->
    for toolspec in @mget('tools')
      @tools[toolspec.id].bind_events(this)

  events:
    "mousemove .canvas_wrapper": "_mousemove"
    "mousedown .canvas_wrapper": "_mousedown"

  _mousedown: (e) ->
    for f in @mousedownCallbacks
      f(e, e.layerX, e.layerY)

  _mousemove: (e) ->
    for f in @moveCallbacks
      f(e, e.layerX, e.layerY)


  initialize: (options) ->
    @throttled = _.throttle(@render_deferred_components, 50)

    super(_.defaults(options, @default_options))

    @view_state = new ViewState({
      canvas_width:  options.canvas_height ? @mget('canvas_height')
      canvas_height: options.canvas_width  ? @mget('canvas_width')
      x_offset:      options.x_offset      ? @mget('x_offset')
      y_offset:      options.y_offset      ? @mget('y_offset')
      outer_width:   options.outer_height  ? @mget('outer_height')
      outer_height:  options.outer_width   ? @mget('outer_width')
      border_top:    options.border_top    ? @mget('border_top')    ? @mget('border')
      border_bottom: options.border_bottom ? @mget('border_bottom') ? @mget('border')
      border_left:   options.border_left   ? @mget('border_left')   ? @mget('border')
      border_right:  options.border_right  ? @mget('border_right')  ? @mget('border')
    })

    @x_range = options.x_range ? @mget('x_range')
    @y_range = options.y_range ? @mget('y_range')

    @xmapper = new LinearMapper({
      source_range: @x_range
      target_range: @view_state.get('inner_range_horizontal')
    })

    @ymapper = new LinearMapper({
      source_range: @x_range
      target_range: @view_state.get('inner_range_vertical')
    })

    @mapper = new GridMapper({
      domain_mapper: @xmapper
      codomain_mapper: @ymapper
    })

    @renderers = {}
    @axes = {}
    @tools = {}
    @overlays = {}
    @eventSink = _.extend({}, Backbone.Events)
    @moveCallbacks = []
    @mousedownCallbacks = []
    @keydownCallbacks = []
    @render_init()
    @render()
    @build_subviews()
    @throttled()
    return this

  map_to_screen : (x, x_units, y, y_units, units) ->
    if x_units == 'screen'
      sx = x[..]
      sy = y[..]
    else
      [sx, sy] = @mapper.v_map_to_target(x, y)

    sx = @view_state.v_sx_to_device(sx)
    sy = @view_state.v_sy_to_device(sy)

    return [sx, sy]

  map_from_screen : (sx, sy, units) ->
    sx = @view_state.v_device_sx(sx[..])
    sy = @view_state.v_device_sx(sy[..])

    if units == 'screen'
      x = sx
      y = sy
    else
      [x, y] = @mapper.v_map_from_target(sx, sy)  # TODO: in-place?

    return [x, y]

  render_init: () ->
    #FIXME template
    @$el.append($("""
      <div class='button_bar'/>
      <div class='bokeh_canvas_wrapper'>
        <canvas class='bokeh_canvas'></canvas>
      </div>
      """))
    @canvas_wrapper = @$el.find('.bokeh_canvas_wrapper')
    @canvas = @$el.find('canvas.bokeh_canvas')

  build_subviews: ()->
    @build_renderers()
    @build_axes()
    @build_tools()
    @build_overlays()
    @bind_tools()
    @bind_overlays()

  bind_bokeh_events: () ->
    safebind(this, @view_state, 'change', @render)
    safebind(this, @model, 'change:renderers', @build_renderers)
    safebind(this, @model, 'change:axes', @build_axes)
    safebind(this, @model, 'change:tools', @build_tools)
    safebind(this, @model, 'change', @render)
    safebind(this, @model, 'destroy', () => @remove())

  # FIXME document throughly when render is called vs render_deferred
  # should we have a "render_init" "render" and a
  # "render_canvas" function add_dom is called at instatiation.
  # "render" is called for plot resizing.  render_canvas is called
  # when changes to the canvas are desired.  A ScatterRendererView
  # would only have a "render_canvas function

  render: () ->
    super()

    oh = @view_state.get('outer_height')
    ow = @view_state.get('outer_width')

    @canvas_wrapper.attr('style', "width:#{ow}px; height:#{oh}px")
    @canvas.attr('width', ow).attr('height', oh)
    @$el.attr("width", ow).attr('height', oh)

    @ctx = @canvas[0].getContext('2d')

    @render_end()

  render_deferred_components: (force) ->
    @ctx.clearRect(0,0,  @view_state.get('canvas_width'), @view_state.get('canvas_height'))
    @ctx.beginPath()
    @ctx.rect(
      @view_state.get('border_left'), @view_state.get('border_top'),
      @view_state.get('inner_width'), @view_state.get('inner_height'),
    )
    @ctx.clip()
    @ctx.beginPath()
    all_views = _.flatten(_.map([@renderers, @axes, @tools], _.values))
    for v in all_views
      v.render()
<commit_msg>only clip renderers, other layer unclipped<commit_after>base = require('../base')
Collections = base.Collections
HasParent = base.HasParent
safebind = base.safebind
build_views = base.build_views

ContinuumView = require('./continuum_view').ContinuumView

LinearMapper = require('../mappers/1d/linear_mapper').LinearMapper
GridMapper = require('../mappers/2d/grid_mapper').GridMapper

ViewState = require('./view_state').ViewState


class PlotView extends ContinuumView

  view_options: () ->
    _.extend({plot_model: @model, plot_view: @}, @options)

  build_renderers: () ->
    build_views(@renderers, @mget_obj('renderers'), @view_options())

  build_axes: () ->
    build_views(@axes, @mget_obj('axes'), @view_options())

  build_tools: () ->
    build_views(@tools, @mget_obj('tools'), @view_options())

  build_overlays: () ->
    #add ids of renderer views into the overlay spec
    build_views(@overlays, @mget_obj('overlays'), @view_options())

  bind_overlays: () ->
    for overlayspec in @mget('overlays')
      @overlays[overlayspec.id].bind_events(this)

  bind_tools: () ->
    for toolspec in @mget('tools')
      @tools[toolspec.id].bind_events(this)

  events:
    "mousemove .canvas_wrapper": "_mousemove"
    "mousedown .canvas_wrapper": "_mousedown"

  _mousedown: (e) ->
    for f in @mousedownCallbacks
      f(e, e.layerX, e.layerY)

  _mousemove: (e) ->
    for f in @moveCallbacks
      f(e, e.layerX, e.layerY)


  initialize: (options) ->
    @throttled = _.throttle(@render_deferred_components, 50)

    super(_.defaults(options, @default_options))

    @view_state = new ViewState({
      canvas_width:  options.canvas_height ? @mget('canvas_height')
      canvas_height: options.canvas_width  ? @mget('canvas_width')
      x_offset:      options.x_offset      ? @mget('x_offset')
      y_offset:      options.y_offset      ? @mget('y_offset')
      outer_width:   options.outer_height  ? @mget('outer_height')
      outer_height:  options.outer_width   ? @mget('outer_width')
      border_top:    options.border_top    ? @mget('border_top')    ? @mget('border')
      border_bottom: options.border_bottom ? @mget('border_bottom') ? @mget('border')
      border_left:   options.border_left   ? @mget('border_left')   ? @mget('border')
      border_right:  options.border_right  ? @mget('border_right')  ? @mget('border')
    })

    @x_range = options.x_range ? @mget('x_range')
    @y_range = options.y_range ? @mget('y_range')

    @xmapper = new LinearMapper({
      source_range: @x_range
      target_range: @view_state.get('inner_range_horizontal')
    })

    @ymapper = new LinearMapper({
      source_range: @x_range
      target_range: @view_state.get('inner_range_vertical')
    })

    @mapper = new GridMapper({
      domain_mapper: @xmapper
      codomain_mapper: @ymapper
    })

    @renderers = {}
    @axes = {}
    @tools = {}
    @overlays = {}
    @eventSink = _.extend({}, Backbone.Events)
    @moveCallbacks = []
    @mousedownCallbacks = []
    @keydownCallbacks = []
    @render_init()
    @render()
    @build_subviews()
    @throttled()
    return this

  map_to_screen : (x, x_units, y, y_units, units) ->
    if x_units == 'screen'
      sx = x[..]
      sy = y[..]
    else
      [sx, sy] = @mapper.v_map_to_target(x, y)

    sx = @view_state.v_sx_to_device(sx)
    sy = @view_state.v_sy_to_device(sy)

    return [sx, sy]

  map_from_screen : (sx, sy, units) ->
    sx = @view_state.v_device_sx(sx[..])
    sy = @view_state.v_device_sx(sy[..])

    if units == 'screen'
      x = sx
      y = sy
    else
      [x, y] = @mapper.v_map_from_target(sx, sy)  # TODO: in-place?

    return [x, y]

  render_init: () ->
    #FIXME template
    @$el.append($("""
      <div class='button_bar'/>
      <div class='bokeh_canvas_wrapper'>
        <canvas class='bokeh_canvas'></canvas>
      </div>
      """))
    @canvas_wrapper = @$el.find('.bokeh_canvas_wrapper')
    @canvas = @$el.find('canvas.bokeh_canvas')

  build_subviews: ()->
    @build_renderers()
    @build_axes()
    @build_tools()
    @build_overlays()
    @bind_tools()
    @bind_overlays()

  bind_bokeh_events: () ->
    safebind(this, @view_state, 'change', @render)
    safebind(this, @model, 'change:renderers', @build_renderers)
    safebind(this, @model, 'change:axes', @build_axes)
    safebind(this, @model, 'change:tools', @build_tools)
    safebind(this, @model, 'change', @render)
    safebind(this, @model, 'destroy', () => @remove())

  # FIXME document throughly when render is called vs render_deferred
  # should we have a "render_init" "render" and a
  # "render_canvas" function add_dom is called at instatiation.
  # "render" is called for plot resizing.  render_canvas is called
  # when changes to the canvas are desired.  A ScatterRendererView
  # would only have a "render_canvas function

  render: () ->
    super()

    oh = @view_state.get('outer_height')
    ow = @view_state.get('outer_width')

    @canvas_wrapper.attr('style', "width:#{ow}px; height:#{oh}px")
    @canvas.attr('width', ow).attr('height', oh)
    @$el.attr("width", ow).attr('height', oh)

    @ctx = @canvas[0].getContext('2d')

    @render_end()

  render_deferred_components: (force) ->
    @ctx.clearRect(0,0,  @view_state.get('canvas_width'), @view_state.get('canvas_height'))

    @ctx.save()

    @ctx.beginPath()
    @ctx.rect(
      @view_state.get('border_left'), @view_state.get('border_top'),
      @view_state.get('inner_width'), @view_state.get('inner_height'),
    )
    @ctx.clip()
    @ctx.beginPath()

    for v in _.flatten(_.map([@renderers], _.values))
      v.render()

    @ctx.restore()

    for v in _.flatten(_.map([@axes, @tools], _.values))
      v.render()



{'fraction_non_alphanumeric': 0.15788543140028288, 'fraction_numerical': 0.0014144271570014145, 'mean_word_length': 3.4521841794569066, 'pattern_counts': {'":': 4, '<': 13, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2865425', 'n_tokens_mistral': 4155, 'n_tokens_neox': 3992, 'n_words': 734}