<commit_before>React = require 'react'
PromiseRenderer = require '../components/promise-renderer'
loadImage = require '../lib/load-image'
Draggable = require '../lib/draggable'
{dispatch} = require '../lib/dispatcher'

drawingComponents =
  point: require './drawing-tools/point'
  ellipse: require './drawing-tools/ellipse'

module.exports = React.createClass
  displayName: 'SubjectViewer'

  getInitialState: ->
    width: 0
    height: 0
    selectedMark: null

  getScale: ->
    ALMOST_ZERO = 0.01 # Prevent divide-by-zero errors when there is no image.
    rect = @refs.subjectContainer?.getDOMNode().getBoundingClientRect()
    rect ?= width: 0, height: 0
    horizontal = rect.width / @state.width || ALMOST_ZERO
    vertical = rect.height / @state.height || ALMOST_ZERO
    {horizontal, vertical}

  getEventOffset: (e) ->
    rect = @refs.subjectContainer.getDOMNode().getBoundingClientRect()
    scale = @getScale()
    x = (e.pageX - pageXOffset - rect.left) / scale.horizontal
    y = (e.pageY - pageYOffset - rect.top) / scale.vertical
    {x, y}

  selectMark: (mark) ->
    index = @props.annotation.marks?.indexOf mark
    if index? and index isnt -1
      @props.annotation.marks.splice index, 1
      @props.annotation.marks.push mark
      @setState selectedMark: mark

  render: ->
    type = Object.keys(@props.subject.locations[0])[0].split('/')[0]
    renderApproprtiately = @["renderType_#{type}"]

    <div className="subject-viewer">
      <div ref="subjectContainer" className="subject-container" style={display: 'inline-block', position: 'relative'}>
        {renderApproprtiately()}
        {@renderMarkingSVG()}
      </div>

      {if @props.subject.locations.length > 1
        <div className="frame-selection">
          {for frame, i in @props.subject.locations
            <button onClick={@handleFrameChange.bind this, i}>{i + 1}</button>}
        </div>}
    </div>

  renderType_image: ->
    frameIndex = @props.classification._frame ? 0
    location = @props.subject.locations[frameIndex]
    knownGood = location['image/jpeg'] ? location['image/png'] ? location['image/gif']
    <img className="subject-image" src={knownGood} onLoad={@handleImageLoad} style={display: 'block'} />

  renderMarkingSVG: ->
    viewBox = [0, 0, @state.width, @state.height]
    svgStyle = height: '100%', left: 0, position: 'absolute', top: 0, width: '100%'

    <svg className="subject-viewer-svg" viewBox={viewBox} preserveAspectRatio="none" data-tool={@props.selectedDrawingTool?.type} style={svgStyle}>
      <Draggable onStart={@handleInitStart} onDrag={@handleInitDrag} onEnd={@handleInitRelease}>
        <rect width={@state.width} height={@state.height} fill="transparent" stroke="none" />
      </Draggable>

      <g className="subject-viewer-tools">{@renderTools()}</g>
    </svg>

  renderTools: ->
    scale = @getScale()
    @props.annotation.marks ?= [
      {_id: '0', _tool: {type: 'point'}, x: 20, y: 20}
      {_id: '1', _tool: {type: 'ellipse'}, x: 100, y: 100, rx: 20, ry: 40, angle: 10}
    ] # Demo

    for annotation in @props.classification.annotations when annotation.marks?
      for mark in annotation.marks
        Tool = drawingComponents[mark._tool.type]
        fromOtherAnnotation = annotation isnt @props.annotation

        toolProps =
          classification: @props.classification
          annotation: annotation
          mark: mark
          scale: scale
          disabled: fromOtherAnnotation
          selected: mark is @state.selectedMark and not fromOtherAnnotation

        toolFunctions =
          select: @selectMark.bind null, mark
          getEventOffset: @getEventOffset

        <Tool key={mark._id} {...toolProps} {...toolFunctions} />

  handleImageLoad: (e) ->
    {width, height} = e.target
    unless @state.width is width and @state.height is height
      @setState {width, height}

  handleFrameChange: (index) ->
    @props.classification.update _frame: index

  handleInitStart: (e) -><commit_msg>Remove demo marks<commit_after>React = require 'react'
PromiseRenderer = require '../components/promise-renderer'
loadImage = require '../lib/load-image'
Draggable = require '../lib/draggable'
{dispatch} = require '../lib/dispatcher'

drawingComponents =
  point: require './drawing-tools/point'
  ellipse: require './drawing-tools/ellipse'

module.exports = React.createClass
  displayName: 'SubjectViewer'

  getInitialState: ->
    width: 0
    height: 0
    selectedMark: null

  getScale: ->
    ALMOST_ZERO = 0.01 # Prevent divide-by-zero errors when there is no image.
    rect = @refs.subjectContainer?.getDOMNode().getBoundingClientRect()
    rect ?= width: 0, height: 0
    horizontal = rect.width / @state.width || ALMOST_ZERO
    vertical = rect.height / @state.height || ALMOST_ZERO
    {horizontal, vertical}

  getEventOffset: (e) ->
    rect = @refs.subjectContainer.getDOMNode().getBoundingClientRect()
    scale = @getScale()
    x = (e.pageX - pageXOffset - rect.left) / scale.horizontal
    y = (e.pageY - pageYOffset - rect.top) / scale.vertical
    {x, y}

  selectMark: (mark) ->
    index = @props.annotation.marks?.indexOf mark
    if index? and index isnt -1
      @props.annotation.marks.splice index, 1
      @props.annotation.marks.push mark
      @setState selectedMark: mark

  render: ->
    type = Object.keys(@props.subject.locations[0])[0].split('/')[0]
    renderApproprtiately = @["renderType_#{type}"]

    <div className="subject-viewer">
      <div ref="subjectContainer" className="subject-container" style={display: 'inline-block', position: 'relative'}>
        {renderApproprtiately()}
        {@renderMarkingSVG()}
      </div>

      {if @props.subject.locations.length > 1
        <div className="frame-selection">
          {for frame, i in @props.subject.locations
            <button onClick={@handleFrameChange.bind this, i}>{i + 1}</button>}
        </div>}
    </div>

  renderType_image: ->
    frameIndex = @props.classification._frame ? 0
    location = @props.subject.locations[frameIndex]
    knownGood = location['image/jpeg'] ? location['image/png'] ? location['image/gif']
    <img className="subject-image" src={knownGood} onLoad={@handleImageLoad} style={display: 'block'} />

  renderMarkingSVG: ->
    viewBox = [0, 0, @state.width, @state.height]
    svgStyle = height: '100%', left: 0, position: 'absolute', top: 0, width: '100%'

    <svg className="subject-viewer-svg" viewBox={viewBox} preserveAspectRatio="none" data-tool={@props.selectedDrawingTool?.type} style={svgStyle}>
      <Draggable onStart={@handleInitStart} onDrag={@handleInitDrag} onEnd={@handleInitRelease}>
        <rect width={@state.width} height={@state.height} fill="transparent" stroke="none" />
      </Draggable>

      <g className="subject-viewer-tools">{@renderTools()}</g>
    </svg>

  renderTools: ->
    scale = @getScale()

    for annotation in @props.classification.annotations when annotation.marks?
      for mark in annotation.marks
        Tool = drawingComponents[mark._tool.type]
        fromOtherAnnotation = annotation isnt @props.annotation

        toolProps =
          classification: @props.classification
          annotation: annotation
          mark: mark
          scale: scale
          disabled: fromOtherAnnotation
          selected: mark is @state.selectedMark and not fromOtherAnnotation

        toolFunctions =
          select: @selectMark.bind null, mark
          getEventOffset: @getEventOffset

        <Tool key={mark._id} {...toolProps} {...toolFunctions} />

  handleImageLoad: (e) ->
    {width, height} = e.target
    unless @state.width is width and @state.height is height
      @setState {width, height}

  handleFrameChange: (index) ->
    @props.classification.update _frame: index

  handleInitStart: (e) ->
{'fraction_non_alphanumeric': 0.14100423783228458, 'fraction_numerical': 0.008732502889431103, 'mean_word_length': 3.2627257799671594, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 61, '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': '7569090', 'n_tokens_mistral': 2440, 'n_tokens_neox': 2335, 'n_words': 538}