<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2013 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

/**
 * Provide the Topology class.
 *
 * @module topology
 */

YUI.add('juju-topology', function(Y) {
  var views = Y.namespace('juju.views'),
      models = Y.namespace('juju.models'),
      components = Y.namespace('d3-components'),
      d3 = Y.namespace('d3'),
      utils = Y.namespace('juju.topology.utils');

  /**
   * Topology models and renders the SVG of the envionment topology
   * with its associated behaviors.
   *
   * The line of where to put code (in the Topology vs a Module) is not 100%
   * clear. The rule of thumb to follow is that shared state, policy and
   * configuration belong here. If the only shared requirement on shared state
   * is watch/event like behavior, fire an event and place the logic in a
   * module.
   *
   * ## Emitted events:
   *
   * - zoom: When the zoom level of the canvas changes a 'zoom'
   *   event is fired. Analogous to d3's zoom event.
   *
   * @class Topology
   */
  var Topology = Y.Base.create('Topology', components.Component, [], {
    initializer: function(options) {
      this.options = Y.mix(options || {}, {
        minZoom: 0.25,
        maxZoom: 2,
        minSlider: 25,
        maxSlider: 200
      });
      Topology.superclass.constructor.apply(this, arguments);
      // Build a service.id -> BoundingBox map for services.
      this.service_boxes = {};
      this._subscriptions = [];
    },

    /**
     * Called by render, conditionally attach container to the DOM if
     * it isn't already. The framework calls this before module
     * rendering so that d3 Events will have attached DOM elements. If
     * your application doesn't need this behavior feel free to override.
     *
     * In this case we currently rely on app.showView to do all the
     * container management, this only works on a preserved view.
     *
     * @method attachContainer
     * @chainable
     */
    attachContainer: function() {
      return this;
    },

    /**
     * Remove container from DOM returning container. This
     * is explicitly not chainable.
     *
     * @method detachContainer
     */
    detachContainer: function() {
      return;
    },

    renderOnce: function() {
      var svg,
          vis,
          width = this.get('width'),
          height = this.get('height'),
          container = this.get('container'),
          templateName = this.options.template || 'overview';

      if (this._templateRendered) {
        return;
      }
      //container.setHTML(views.Templates[templateName]());
      // Take the first element.
      this._templateRendered = true;

      // These are defaults, a (Viewport) Module
      // can implement policy around them.
      this.computeScales();

      // Set up the visualization with a pack layout.
      var canvas = d3.select(container.getDOMNode());
      var base = canvas.select('.topology-canvas');
      if (base.empty()) {
        base = canvas.append('div')
              .classed('topology-canvas', true);
      }

      // Cache the canvas element for style modifications.
      this.set('canvas', container.one('.topology-canvas'));

      svg = base.append('svg:svg')
                .attr('width', width)
                .attr('height', height)
                .attr('class', 'the-canvas');
      this.svg = svg;

      this.zoomPlane = svg.append('rect')
                          .attr('class', 'zoom-plane')
                          .attr('width', width)
                          .attr('height', height)
                          .attr('pointer-events', 'all')
                          .call(this.zoom)
                          .on('dblclick.zoom', null);

      vis = svg.append('svg:g');
      this.vis = vis;

      // Only add the plus service block when requested, leaving it out of
      // the bundle details view.
      if (this.options.includePlus) {
        // Disable max-len, in order to maintain an easy way to paste in new
        // assets from design should they arrive.
        /*eslint-disable max-len*/
        vis.html('<g class="plus-service included-plus" transform="translate(0,0)">' +
            '<circle cx="64" cy="64" r="80" stroke="#888888" stroke-width="1" fill="transparent" stroke-dasharray="5, 5" class="plus-service__halo" id="yui_3_11_0_1_1444041610389_7098"></circle>' +
            '<path class="plus-service__inner-circle" fill="#FAFBFB" d="M63.5 126.5c-34.738 0-63-28.262-63-63s28.262-63 63-63 63 28.262 63 63-28.262 63-63 63z"/>' +
            '<path fill="#CECDCD" d="M63.5 1C97.962 1 126 29.038 126 63.5S97.962 126 63.5 126 1 97.962 1 63.5 29.038 1 63.5 1m0-1C28.43 0 0 28.43 0 63.5S28.43 127 63.5 127 127 98.57 127 63.5 98.57 0 63.5 0z"/>' +
            '<circle fill="#DC4A26" cx="63.5" cy="63.5" r="32.5"/>' +
            '<g fill="none" stroke="#FFF" stroke-width="2" stroke-miterlimit="10">' +
            '<path d="M63.5 54.5v18M72.5 63.5h-18"/>' +
            '</g>' +
            '</g>');
        /*eslint-enable max-len*/
        var plusIndicator = vis.select('.included-plus');
        var self = this;
        plusIndicator.on('click', function() {
          self.fire('changeState', {
            sectionC: {
              component: 'charmbrowser',
              metadata: {
                activeComponent: 'mid-point'
              }
            }
          });<commit_msg>Stop the plus circle click event if it is being dragged.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2013 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

/**
 * Provide the Topology class.
 *
 * @module topology
 */

YUI.add('juju-topology', function(Y) {
  var views = Y.namespace('juju.views'),
      models = Y.namespace('juju.models'),
      components = Y.namespace('d3-components'),
      d3 = Y.namespace('d3'),
      utils = Y.namespace('juju.topology.utils');

  /**
   * Topology models and renders the SVG of the envionment topology
   * with its associated behaviors.
   *
   * The line of where to put code (in the Topology vs a Module) is not 100%
   * clear. The rule of thumb to follow is that shared state, policy and
   * configuration belong here. If the only shared requirement on shared state
   * is watch/event like behavior, fire an event and place the logic in a
   * module.
   *
   * ## Emitted events:
   *
   * - zoom: When the zoom level of the canvas changes a 'zoom'
   *   event is fired. Analogous to d3's zoom event.
   *
   * @class Topology
   */
  var Topology = Y.Base.create('Topology', components.Component, [], {
    initializer: function(options) {
      this.options = Y.mix(options || {}, {
        minZoom: 0.25,
        maxZoom: 2,
        minSlider: 25,
        maxSlider: 200
      });
      Topology.superclass.constructor.apply(this, arguments);
      // Build a service.id -> BoundingBox map for services.
      this.service_boxes = {};
      this._subscriptions = [];
    },

    /**
     * Called by render, conditionally attach container to the DOM if
     * it isn't already. The framework calls this before module
     * rendering so that d3 Events will have attached DOM elements. If
     * your application doesn't need this behavior feel free to override.
     *
     * In this case we currently rely on app.showView to do all the
     * container management, this only works on a preserved view.
     *
     * @method attachContainer
     * @chainable
     */
    attachContainer: function() {
      return this;
    },

    /**
     * Remove container from DOM returning container. This
     * is explicitly not chainable.
     *
     * @method detachContainer
     */
    detachContainer: function() {
      return;
    },

    renderOnce: function() {
      var svg,
          vis,
          width = this.get('width'),
          height = this.get('height'),
          container = this.get('container'),
          templateName = this.options.template || 'overview';

      if (this._templateRendered) {
        return;
      }
      //container.setHTML(views.Templates[templateName]());
      // Take the first element.
      this._templateRendered = true;

      // These are defaults, a (Viewport) Module
      // can implement policy around them.
      this.computeScales();

      // Set up the visualization with a pack layout.
      var canvas = d3.select(container.getDOMNode());
      var base = canvas.select('.topology-canvas');
      if (base.empty()) {
        base = canvas.append('div')
              .classed('topology-canvas', true);
      }

      // Cache the canvas element for style modifications.
      this.set('canvas', container.one('.topology-canvas'));

      svg = base.append('svg:svg')
                .attr('width', width)
                .attr('height', height)
                .attr('class', 'the-canvas');
      this.svg = svg;

      this.zoomPlane = svg.append('rect')
                          .attr('class', 'zoom-plane')
                          .attr('width', width)
                          .attr('height', height)
                          .attr('pointer-events', 'all')
                          .call(this.zoom)
                          .on('dblclick.zoom', null);

      vis = svg.append('svg:g');
      this.vis = vis;

      // Only add the plus service block when requested, leaving it out of
      // the bundle details view.
      if (this.options.includePlus) {
        // Disable max-len, in order to maintain an easy way to paste in new
        // assets from design should they arrive.
        /*eslint-disable max-len*/
        vis.html('<g class="plus-service included-plus" transform="translate(0,0)">' +
            '<circle cx="64" cy="64" r="80" stroke="#888888" stroke-width="1" fill="transparent" stroke-dasharray="5, 5" class="plus-service__halo" id="yui_3_11_0_1_1444041610389_7098"></circle>' +
            '<path class="plus-service__inner-circle" fill="#FAFBFB" d="M63.5 126.5c-34.738 0-63-28.262-63-63s28.262-63 63-63 63 28.262 63 63-28.262 63-63 63z"/>' +
            '<path fill="#CECDCD" d="M63.5 1C97.962 1 126 29.038 126 63.5S97.962 126 63.5 126 1 97.962 1 63.5 29.038 1 63.5 1m0-1C28.43 0 0 28.43 0 63.5S28.43 127 63.5 127 127 98.57 127 63.5 98.57 0 63.5 0z"/>' +
            '<circle fill="#DC4A26" cx="63.5" cy="63.5" r="32.5"/>' +
            '<g fill="none" stroke="#FFF" stroke-width="2" stroke-miterlimit="10">' +
            '<path d="M63.5 54.5v18M72.5 63.5h-18"/>' +
            '</g>' +
            '</g>');
        /*eslint-enable max-len*/
        var plusIndicator = vis.select('.included-plus');
        var self = this;
        plusIndicator.on('click', function() {
          if (d3.event.defaultPrevented) {
            // Don't allow the click if the element is being dragged.
            return;
          }
          self.fire('changeState', {
            sectionC: {
              component: 'charmbrowser',
              metadata: {
                activeComponent: 'mid-point'
              }
            }
          });
{'fraction_non_alphanumeric': 0.121216999356085, 'fraction_numerical': 0.0424179008370895, 'mean_word_length': 2.2114241406048074, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '5007572', 'n_tokens_mistral': 3987, 'n_tokens_neox': 3587, 'n_words': 1165}