<commit_before>/** @jsx React.DOM */

var React = window.React = require('react'),
    LinesList = require('./ui/lines_list'),
    mountNode = document.getElementById('app');

var SvgScribblerApp = React.createClass({
  getInitialState: function() {
    var colors = randomColor({count: 2});
    var minStrokeWidth = 0;
    var maxStrokeWidth = 20;
    return {
      minStrokeWidth: minStrokeWidth,
      maxStrokeWidth: maxStrokeWidth,
      lines: [{
        points: [],
        stroke: colors[0],
        fill: colors[1],
        strokeWidth: this.getRandomStrokeWidth(minStrokeWidth, maxStrokeWidth),
        id: 1
      }],
      isDrawing: false
    };
  },
  getRandomStrokeWidth: function(min, max) {
    if (typeof min === 'undefined') {
      min = this.state.minStrokeWidth;
    }
    if (typeof max === 'undefined') {
      max = this.state.maxStrokeWidth;
    }
    return Math.floor(Math.random() * (max - min + 1) + min);
  },
  adjustSvgSize: function() {
    var svgWrapper = $('.svg-container');
    var footer = $('.footer');
    var height = $(window).height();
    height = height - svgWrapper.offset().top - footer.height();
    svgWrapper.css('height', height);
  },
  componentDidMount: function() {
    var self = this;
    $('#stroke-color-picker').spectrum({
      color: this.state.lines[0].stroke,
      change: function(color) {
        var line = self.getCurrentLine();
        line.stroke = color.toRgbString();
        self.updateCurrentLine(line);
      }
    });
    $('#fill-color-picker').spectrum({
      color: this.state.lines[0].fill,
      change: function(color) {
        var line = self.getCurrentLine();
        line.fill = color.toRgbString();
        self.updateCurrentLine(line);
      }
    });
    this.adjustSvgSize();
    $('[data-toggle="tooltip"]').tooltip();
  },
  doesPointExist: function(line, coords) {
    for (var i=0; i<line.length; i++) {
      var point = line[i];
      if (point.left === coords.x && point.top === coords.y) {
        return true;
      }
    }
    return false;
  },
  getCurrentLine: function() {
    var line = this.state.lines.slice(this.state.lines.length - 1)[0];
    var newLine = {};
    var props = Object.keys(line);
    for (var i=0; i<props.length; i++) {
      var prop = props[i];
      var originalValue = line[prop];
      if (Array.isArray(originalValue)) {
        newLine[prop] = originalValue.slice(0, originalValue.length);
      } else {
        newLine[prop] = originalValue;
      }
    }
    return newLine;
  },
  updateCurrentLine: function(line) {
    var newLines = this.state.lines.slice(0, this.state.lines.length - 1);
    newLines.push(line);
    this.setState({lines: newLines});
  },
  addPoint: function(coords) {
    var line = this.getCurrentLine();
    if (!this.doesPointExist(line, coords)) {
      var newPoint = {left: coords.x, top: coords.y, width: 10, height: 10};
      line.points.push(newPoint);
      this.updateCurrentLine(line);
    }
  },
  getCanvasCoords: function(e) {
    var canvas = $(e.target);
    var offset = canvas.offset();
    var left = offset.left;
    var top = offset.top;
    var x = e.pageX - left;
    var y = e.pageY - top;
    return {x: x, y: y};
  },
  addNewLineIfNecessary: function() {
    var lastLine = this.getCurrentLine();
    if (lastLine.points.length > 0) {
      var newLine = {
        points: [],
        stroke: lastLine.stroke,
        fill: lastLine.fill,
        strokeWidth: lastLine.strokeWidth,
        id: this.state.lines.length + 1
      };
      this.setState({lines: this.state.lines.concat(newLine)});
    }
  },
  onMouseDown: function(e) {
    this.setState({isDrawing: true});
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
  },
  onMouseMove: function(e) {
    if (!this.state.isDrawing) {
      return;
    }
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
  },
  onMouseUp: function(e) {
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
    this.setState({isDrawing: false});
    this.addNewLineIfNecessary();
  },
  onMouseLeave: function(e) {
    this.setState({isDrawing: false});
    this.addNewLineIfNecessary();
  },
  getPointsList: function(line) {
    var pairs = [];
    for (var i=0; i<line.points.length; i++) {
      var point = line.points[i];
      pairs.push(point.left + ',' + point.top);
    }
    return pairs.join(' ');
  },
  getPolylineStyle: function(line) {
    return {
      stroke: line.stroke,
      fill: line.fill,
      strokeWidth: line.strokeWidth
    };
  },
  getPolylineSource: function() {
    var polylines = [];
    for (var i=0; i<this.state.lines.length; i++) {
      var line = this.state.lines[i];
      if (line.points.length < 2) {
        continue;
      }
      var svgPoints = [];
      for (var j=0; j<line.points.length; j++) {
        var point = line.points[j];
        svgPoints.push(point.left + ',' + point.top);
      }
      svgPoints = svgPoints.join(' ');
      var svgStyle = 'stroke: ' + line.stroke + '; fill: ' + line.fill +
                     '; stroke-width: ' + line.strokeWidth;
      polylines.push('  <polyline points="' + svgPoints + '" style="' +
                     svgStyle + '" />');
    }
    return polylines.join("\n") + "\n";
  },
  downloadSvg: function(e) {
    var button = $(e.target);
    var svgEl = $('svg.svg-result');
    var svgSource = $(svgEl.wrap('<div>').parent().html());
    svgSource.find('*').removeAttr('data-reactid');
    svgSource = svgSource.html();
    svgSource = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg">' +
                "\n" + svgSource + "\n</svg>";
    svgEl.unwrap('<div>');
    console.log(svgSource);
    var b64 = Base64.encode(svgSource);
    var fileName = 'svg-scribbler-' + moment().format('YYYY-MM-DD-hh-mm-ss-a') +
                   '.svg';
    var link = $('<a>').attr('href-lang', 'image/svg+xml').
                        attr('href', "data:image/svg+xml;base64,\n" + b64).
                        attr('download', fileName).text(' ');
    $('body').append(link);
    link[0].click();
    link.remove();
    button.blur();
  },
  downloadButtonStyle: function() {
    var display;
    if (this.state.lines.length > 1) {
      display = 'inline-block';
    } else {
      var line = this.getCurrentLine();
      display = line.points.length > 0 ? 'inline-block' : 'none';
    }
    return {display: display};
  },
  setLineColor: function(type, color) {
    $('#' + type + '-color-picker').spectrum('set', color);
    var line = this.getCurrentLine();
    line[type] = color;
    this.updateCurrentLine(line);
  },
  randomizeStroke: function() {
    this.setLineColor('stroke', randomColor());
  },
  randomizeFill: function() {
    this.setLineColor('fill', randomColor());
  },
  clearStroke: function() {
    this.setLineColor('stroke', 'transparent');
  },
  clearFill: function() {
    this.setLineColor('fill', 'transparent');
  },
  setStrokeWidth: function(e) {
    var slider = $(e.target);
    var line = this.getCurrentLine();
    line.strokeWidth = slider.val();
    this.updateCurrentLine(line);
  },
  deleteLine: function(lineToDelete) {
    var index;
    for (var i=0; i<this.state.lines.length; i++) {
      var line = this.state.lines[i];
      if (line.id === lineToDelete.id) {
        index = i;
        break;
      }
    }
    if (typeof index !== 'undefined') {
      var newLines = this.state.lines.slice(0, index).
                          concat(this.state.lines.slice(index + 1));
      this.setState({lines: newLines});
    }
  },
  render: function() {
    var self = this;
    return (
      <div>
        <div className="page-header clearfix">
          <button type="button" className="pull-right btn btn-info download-button" onClick={this.downloadSvg} style={this.downloadButtonStyle()}>
            <i className="fa fa-download"></i>
            Download SVG
          </button>
          <h1>SVG Scribbler</h1>
        </div>
        <div role="tabpanel">
          <ul className="nav nav-tabs" role="tablist">
            <li role="presentation" className="active">
              <a href="#canvas-tab" aria-controls="canvas-tab" role="tab" data-toggle="tab">
                Draw
              </a>
            </li>
            <li role="presentation">
              <a href="#source-tab" aria-controls="source-tab" role="tab" data-toggle="tab">
                View SVG Source
              </a>
            </li>
          </ul>
          <div className="tab-content">
            <div role="tabpanel" className="tab-pane fade in active" id="canvas-tab">
              <div className="row">
                <div className="col-sm-9 col-md-10">
                  <div className="color-controls">
                    <div className="form-inline">
                      <div className="form-group">
                        <label htmlFor="stroke-color-picker">Border:</label>
                        <input type="text" id="stroke-color-picker" className="color-picker" />
                        <button type="button" className="randomize-color btn btn-flat btn-sm" data-toggle="tooltip" title="Randomize" onClick={this.randomizeStroke}>
                          <i className="fa fa-random"></i>
                        </button>
                        <button type="button" className="clear-color btn btn-flat btn-sm" data-toggle="tooltip" title="Clear" onClick={this.clearStroke}>
                          <i className="fa fa-remove"></i>
                        </button>
                      </div>
                      <div className="form-group">
                        <label htmlFor="fill-color-picker">Fill:</label>
                        <input type="text" id="fill-color-picker" className="color-picker" />
                        <button type="button" className="randomize-color btn btn-flat btn-sm" data-toggle="tooltip" title="Randomize" onClick={this.randomizeFill}>
                          <i className="fa fa-random"></i>
                        </button>
                        <button type="button" className="clear-color btn btn-flat btn-sm" data-toggle="tooltip" title="Clear" onClick={this.clearFill}>
                          <i className="fa fa-remove"></i>
                        </button>
                      </div>
                      <div className="form-group">
                        <label htmlFor="stroke-width-slider">Border width:</label>
                        <span className="range-input-wrapper">
                          <span className="help-inline">
                            {this.state.minStrokeWidth}
                          </span>
                          <input onInput={this.setStrokeWidth} type="range" id="stroke-width-slider" min={this.state.minStrokeWidth} defaultValue={this.getCurrentLine().strokeWidth} step="1" max={this.state.maxStrokeWidth} />
                          <span className="help-inline">
                            {this.state.maxStrokeWidth}
                          </span>
                        </span>
                      </div>
                    </div>
                  </div>
                  <div className="svg-container clearfix">
                    <svg className="svg-result" version="1.1" xmlns="http://www.w3.org/2000/svg">
                      {
                        this.state.lines.map(function(line) {
                          if (line.points.length > 1) {
                            return <polyline points={self.getPointsList(line)} style={self.getPolylineStyle(line)} />
                          }
                        })
                      }
                    </svg><commit_msg>Can randomize stroke width with button<commit_after>/** @jsx React.DOM */

var React = window.React = require('react'),
    LinesList = require('./ui/lines_list'),
    mountNode = document.getElementById('app');

var SvgScribblerApp = React.createClass({
  getInitialState: function() {
    var colors = randomColor({count: 2});
    var minStrokeWidth = 0;
    var maxStrokeWidth = 20;
    return {
      minStrokeWidth: minStrokeWidth,
      maxStrokeWidth: maxStrokeWidth,
      lines: [{
        points: [],
        stroke: colors[0],
        fill: colors[1],
        strokeWidth: this.getRandomStrokeWidth(minStrokeWidth, maxStrokeWidth),
        id: 1
      }],
      isDrawing: false
    };
  },
  getRandomStrokeWidth: function(min, max) {
    if (typeof min === 'undefined') {
      min = this.state.minStrokeWidth;
    }
    if (typeof max === 'undefined') {
      max = this.state.maxStrokeWidth;
    }
    return Math.floor(Math.random() * (max - min + 1) + min);
  },
  adjustSvgSize: function() {
    var svgWrapper = $('.svg-container');
    var footer = $('.footer');
    var height = $(window).height();
    height = height - svgWrapper.offset().top - footer.height();
    svgWrapper.css('height', height);
  },
  componentDidMount: function() {
    var self = this;
    $('#stroke-color-picker').spectrum({
      color: this.state.lines[0].stroke,
      change: function(color) {
        var line = self.getCurrentLine();
        line.stroke = color.toRgbString();
        self.updateCurrentLine(line);
      }
    });
    $('#fill-color-picker').spectrum({
      color: this.state.lines[0].fill,
      change: function(color) {
        var line = self.getCurrentLine();
        line.fill = color.toRgbString();
        self.updateCurrentLine(line);
      }
    });
    this.adjustSvgSize();
    $('[data-toggle="tooltip"]').tooltip();
  },
  doesPointExist: function(line, coords) {
    for (var i=0; i<line.length; i++) {
      var point = line[i];
      if (point.left === coords.x && point.top === coords.y) {
        return true;
      }
    }
    return false;
  },
  getCurrentLine: function() {
    var line = this.state.lines.slice(this.state.lines.length - 1)[0];
    var newLine = {};
    var props = Object.keys(line);
    for (var i=0; i<props.length; i++) {
      var prop = props[i];
      var originalValue = line[prop];
      if (Array.isArray(originalValue)) {
        newLine[prop] = originalValue.slice(0, originalValue.length);
      } else {
        newLine[prop] = originalValue;
      }
    }
    return newLine;
  },
  updateCurrentLine: function(line) {
    var newLines = this.state.lines.slice(0, this.state.lines.length - 1);
    newLines.push(line);
    this.setState({lines: newLines});
  },
  addPoint: function(coords) {
    var line = this.getCurrentLine();
    if (!this.doesPointExist(line, coords)) {
      var newPoint = {left: coords.x, top: coords.y, width: 10, height: 10};
      line.points.push(newPoint);
      this.updateCurrentLine(line);
    }
  },
  getCanvasCoords: function(e) {
    var canvas = $(e.target);
    var offset = canvas.offset();
    var left = offset.left;
    var top = offset.top;
    var x = e.pageX - left;
    var y = e.pageY - top;
    return {x: x, y: y};
  },
  addNewLineIfNecessary: function() {
    var lastLine = this.getCurrentLine();
    if (lastLine.points.length > 0) {
      var newLine = {
        points: [],
        stroke: lastLine.stroke,
        fill: lastLine.fill,
        strokeWidth: lastLine.strokeWidth,
        id: this.state.lines.length + 1
      };
      this.setState({lines: this.state.lines.concat(newLine)});
    }
  },
  onMouseDown: function(e) {
    this.setState({isDrawing: true});
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
  },
  onMouseMove: function(e) {
    if (!this.state.isDrawing) {
      return;
    }
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
  },
  onMouseUp: function(e) {
    var coords = this.getCanvasCoords(e);
    this.addPoint(coords);
    this.setState({isDrawing: false});
    this.addNewLineIfNecessary();
  },
  onMouseLeave: function(e) {
    this.setState({isDrawing: false});
    this.addNewLineIfNecessary();
  },
  getPointsList: function(line) {
    var pairs = [];
    for (var i=0; i<line.points.length; i++) {
      var point = line.points[i];
      pairs.push(point.left + ',' + point.top);
    }
    return pairs.join(' ');
  },
  getPolylineStyle: function(line) {
    return {
      stroke: line.stroke,
      fill: line.fill,
      strokeWidth: line.strokeWidth
    };
  },
  getPolylineSource: function() {
    var polylines = [];
    for (var i=0; i<this.state.lines.length; i++) {
      var line = this.state.lines[i];
      if (line.points.length < 2) {
        continue;
      }
      var svgPoints = [];
      for (var j=0; j<line.points.length; j++) {
        var point = line.points[j];
        svgPoints.push(point.left + ',' + point.top);
      }
      svgPoints = svgPoints.join(' ');
      var svgStyle = 'stroke: ' + line.stroke + '; fill: ' + line.fill +
                     '; stroke-width: ' + line.strokeWidth;
      polylines.push('  <polyline points="' + svgPoints + '" style="' +
                     svgStyle + '" />');
    }
    return polylines.join("\n") + "\n";
  },
  downloadSvg: function(e) {
    var button = $(e.target);
    var svgEl = $('svg.svg-result');
    var svgSource = $(svgEl.wrap('<div>').parent().html());
    svgSource.find('*').removeAttr('data-reactid');
    svgSource = svgSource.html();
    svgSource = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg">' +
                "\n" + svgSource + "\n</svg>";
    svgEl.unwrap('<div>');
    console.log(svgSource);
    var b64 = Base64.encode(svgSource);
    var fileName = 'svg-scribbler-' + moment().format('YYYY-MM-DD-hh-mm-ss-a') +
                   '.svg';
    var link = $('<a>').attr('href-lang', 'image/svg+xml').
                        attr('href', "data:image/svg+xml;base64,\n" + b64).
                        attr('download', fileName).text(' ');
    $('body').append(link);
    link[0].click();
    link.remove();
    button.blur();
  },
  downloadButtonStyle: function() {
    var display;
    if (this.state.lines.length > 1) {
      display = 'inline-block';
    } else {
      var line = this.getCurrentLine();
      display = line.points.length > 0 ? 'inline-block' : 'none';
    }
    return {display: display};
  },
  setLineColor: function(type, color) {
    $('#' + type + '-color-picker').spectrum('set', color);
    var line = this.getCurrentLine();
    line[type] = color;
    this.updateCurrentLine(line);
  },
  randomizeStroke: function() {
    this.setLineColor('stroke', randomColor());
  },
  randomizeFill: function() {
    this.setLineColor('fill', randomColor());
  },
  clearStroke: function() {
    this.setLineColor('stroke', 'transparent');
  },
  clearFill: function() {
    this.setLineColor('fill', 'transparent');
  },
  setStrokeWidth: function(e) {
    var slider = $(e.target);
    var line = this.getCurrentLine();
    line.strokeWidth = slider.val();
    this.updateCurrentLine(line);
  },
  randomizeStrokeWidth: function() {
    var line = this.getCurrentLine();
    var currentStrokeWidth = line.strokeWidth;
    while (currentStrokeWidth === line.strokeWidth) {
      line.strokeWidth = this.getRandomStrokeWidth();
    }
    this.updateCurrentLine(line);
  },
  deleteLine: function(lineToDelete) {
    var index;
    for (var i=0; i<this.state.lines.length; i++) {
      var line = this.state.lines[i];
      if (line.id === lineToDelete.id) {
        index = i;
        break;
      }
    }
    if (typeof index !== 'undefined') {
      var newLines = this.state.lines.slice(0, index).
                          concat(this.state.lines.slice(index + 1));
      this.setState({lines: newLines});
    }
  },
  render: function() {
    var self = this;
    return (
      <div>
        <div className="page-header clearfix">
          <button type="button" className="pull-right btn btn-info download-button" onClick={this.downloadSvg} style={this.downloadButtonStyle()}>
            <i className="fa fa-download"></i>
            Download SVG
          </button>
          <h1>SVG Scribbler</h1>
        </div>
        <div role="tabpanel">
          <ul className="nav nav-tabs" role="tablist">
            <li role="presentation" className="active">
              <a href="#canvas-tab" aria-controls="canvas-tab" role="tab" data-toggle="tab">
                Draw
              </a>
            </li>
            <li role="presentation">
              <a href="#source-tab" aria-controls="source-tab" role="tab" data-toggle="tab">
                View SVG Source
              </a>
            </li>
          </ul>
          <div className="tab-content">
            <div role="tabpanel" className="tab-pane fade in active" id="canvas-tab">
              <div className="row">
                <div className="col-sm-9 col-md-10">
                  <div className="color-controls">
                    <div className="form-inline">
                      <div className="form-group">
                        <label htmlFor="stroke-color-picker">Border:</label>
                        <input type="text" id="stroke-color-picker" className="color-picker" />
                        <button type="button" className="randomize-color btn btn-flat btn-sm" data-toggle="tooltip" title="Randomize" onClick={this.randomizeStroke}>
                          <i className="fa fa-random"></i>
                        </button>
                        <button type="button" className="clear-color btn btn-flat btn-sm" data-toggle="tooltip" title="Clear" onClick={this.clearStroke}>
                          <i className="fa fa-remove"></i>
                        </button>
                      </div>
                      <div className="form-group">
                        <label htmlFor="fill-color-picker">Fill:</label>
                        <input type="text" id="fill-color-picker" className="color-picker" />
                        <button type="button" className="randomize-color btn btn-flat btn-sm" data-toggle="tooltip" title="Randomize" onClick={this.randomizeFill}>
                          <i className="fa fa-random"></i>
                        </button>
                        <button type="button" className="clear-color btn btn-flat btn-sm" data-toggle="tooltip" title="Clear" onClick={this.clearFill}>
                          <i className="fa fa-remove"></i>
                        </button>
                      </div>
                      <div className="form-group">
                        <label htmlFor="stroke-width-slider">Border width:</label>
                        <span className="range-input-wrapper">
                          <span className="help-inline">
                            {this.state.minStrokeWidth}
                          </span>
                          <input onInput={this.setStrokeWidth} type="range" id="stroke-width-slider" min={this.state.minStrokeWidth} value={this.getCurrentLine().strokeWidth} step="1" max={this.state.maxStrokeWidth} />
                          <span className="help-inline">
                            {this.state.maxStrokeWidth}
                          </span>
                        </span>
                        <button type="button" className="randomize-stroke-width btn btn-flat btn-sm" data-toggle="tooltip" title="Randomize" onClick={this.randomizeStrokeWidth}>
                          <i className="fa fa-random"></i>
                        </button>
                      </div>
                    </div>
                  </div>
                  <div className="svg-container clearfix">
                    <svg className="svg-result" version="1.1" xmlns="http://www.w3.org/2000/svg">
                      {
                        this.state.lines.map(function(line) {
                          if (line.points.length > 1) {
                            return <polyline points={self.getPointsList(line)} style={self.getPolylineStyle(line)} />
                          }
                        })
                      }
                    </svg>
{'fraction_non_alphanumeric': 0.15590452261306534, 'fraction_numerical': 0.005192629815745394, 'mean_word_length': 2.032122905027933, 'pattern_counts': {'":': 0, '<': 171, '<?xml version=': 0, '>': 165, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5678158', 'n_tokens_mistral': 7273, 'n_tokens_neox': 7113, 'n_words': 1365}