Piece of pie including Sector, Label, LabelLine
@constructor
@extends {module:zrender/graphic/Group}
18070
function PiePiece(data, idx) {

    graphic.Group.call(this);

    var sector = new graphic.Sector({
        z2: 2
    });
    var polyline = new graphic.Polyline();
    var text = new graphic.Text();
    this.add(sector);
    this.add(polyline);
    this.add(text);

    this.updateData(data, idx, true);
}
1204686
function drawHorizontalExtendedLine() {
            baseLine = svg.select('.axis-group')
              .selectAll('line.extended-x-line')
              .data([0])
              .enter()
                .append('line')
                  .attr('class', 'extended-x-line')
                  .attr('x1', 0)
                  .attr('x2', chartWidth);
        }
1107265
function Group(options) {

	this.__proto__ = new Control();

	this.init = function(options) {
		this.type = options.type = 'Group';
		this.parent = options.parent;

		this.childopts = {};
		for (var o in options) {
			if ((o != 'childopts') && (o != 'type')) this.childopts[o] = options[o];
		}
		if (options.childopts) {
			for (var o in options.childopts) this.childopts[o] = options.childopts[o];
		}
		if (this.childopts.type == 'Group') this.childopts.type = 'Button';

		this.defaults = {
			x:48, y:48,
			w: this.childopts.w || 120,
			h: this.childopts.h || 48,

			value: 0,
			text: '',
			script: undefined,
			onload: undefined,
			fill: this.parent.fill,
			stroke: this.parent.stroke,
			'stroke-width': this.parent.control_stroke,
			fontsize: this.parent.fontsize,
			repeat: 0,
			running: 0,
			corner: this.parent.button_corner,
			subtype: undefined,
			group: undefined,
			row: undefined,
			col: undefined,
			autorun: undefined,
			highlighttrue: undefined,
			source: undefined,
			refresh: 0,

			noreadout: undefined,
			radio: undefined,
			//r: options.r || this.w/2,
			reversebits: undefined,
			numx: 1,
			numy: 3
		};
		this.fill_highlight = this.parent.lighter(this.stroke);
		this.setoptions(options);

		if (options.gutterx !== undefined) this.gutterx = options.gutterx;
		else if (options.gutter !== undefined) this.gutterx = options.gutter;
		else this.gutterx = 20;
		if (options.guttery !== undefined) this.guttery = options.guttery;
		else if (options.gutter !== undefined) this.guttery = options.gutter;
		else this.guttery = 20;

		this.nextstroke = 0;
		this.strokes = this.childopts.stroke || this.stroke;
		if (!(this.strokes instanceof Array)) this.strokes = [this.strokes];

		this.nextfill = 0;
		this.fills = this.childopts.fill || this.fill;
		if (!(this.fills instanceof Array)) this.fills = [this.fills];

		this.nexttext = 0;
		this.texts = this.childopts.text || this.text;
		if (!(this.texts instanceof Array)) this.texts = [this.texts];

		this.nextscript = 0;
		this.scripts = this.childopts.script || this.script;
		if (!(this.scripts instanceof Array)) this.scripts = [this.scripts];

		this.nextsource = 0;
		this.sources = this.childopts.source || this.source;
		if (!(this.sources instanceof Array)) this.sources = [this.sources];

		this.render();
		return this;
	};

	this.layout = function() {
		this.outerh = this.numy * (this.h + this.guttery) + this.guttery;
		if (this.childopts.type == 'Slider') {
			this.outerh += 3 * this.fontsize;
		}
	};

	this.render = function() {
		this.layout();

console.log('New group:', this);

		// bug: we don't have accurate this.w and this.h for path buttons here
		this.elt = this.parent.paper.rect(
			this.x - this.gutterx,
			this.y - this.guttery,
			this.numx * (this.w + this.gutterx) + this.gutterx,
			this.outerh, this.corner)
				.attr({fill:this.fill, stroke:this.stroke, 'stroke-width': this['stroke-width']});

		this.elts.push(this.elt);
		this.sethandlers();

		var x;
		var y = this.y;
		for (var row = 0; row < this.numy; row++) {
			x = this.x;
			for (var col=0; col< this.numx; col++) {
				var opts = {};
				for (var o in this.childopts) opts[o] = this.childopts[o];
				opts.id = this.itemid(row, col);
				opts.group = this.id;
				opts.x = x;
				opts.y = y;
				opts.row = row;
				opts.col = col;

				opts.stroke = this.strokes[this.nextstroke];
				if (++this.nextstroke >= this.strokes.length) this.nextstroke = 0;

				opts.fill = this.fills[this.nextfill];
				if (++this.nextfill >= this.fills.length) this.nextfill = 0;

				opts.text = this.texts[this.nexttext];
				if (++this.nexttext >= this.texts.length) this.nexttext = 0;

				opts.script = this.scripts[this.nextscript];
				if (++this.nextscript >= this.scripts.length) this.nextscript = 0;

				opts.source = this.sources[this.nextsource];
				if (++this.nextsource >= this.sources.length) this.nextsource = 0;

	console.log('Group add:', opts.type, opts);
				if (opts.type) this.parent.add([opts]);
				else this.parent.addButton(opts);
				x += (this.w + this.gutterx);
			}
			y += (this.h + this.guttery);
		}
	};

	this.itemid = function(row, col) {
		return  '' + this.id + '-' + row + '-' + col;
	};

	this.each = function(callback) {
		for (var row = 0; row < this.numy; row++) {
			for (var col = 0; col < this.numx; col++) {
				callback(this.parent.controls[this.itemid(row, col)]);
			}
		}
	};

	this.remove = function() {
		this.each(function(control) { control.parent.deletecontrol(control.id); });
		this.__proto__.remove.call(this);
	};

	this.attr = function(attrs) {
		this.each(function(control) { control.attr(attrs); });
		this.__proto__.attr.call(this);
	};

	// when a button in our group moves, it calls here to notify
	this.dragNotify = function(moved) {
		// calculate x,y of group from row, col of button[id]
		var newx = moved.x - moved.col * (this.w + this.gutterx);
		var newy = moved.y - moved.row * (this.h + this.guttery);
		console.log('dragNotify', moved, this.x, this.y, newx, newy);
		this.move(newx, newy);
	};

	this.move = function(newx, newy) {
		this.options.x = this.x = newx;
		this.options.y = this.y = newy;
		this.elt.attr({x:this.x - this.gutterx, y:this.y - this.guttery, width:this.w, height:this.h});

		var x;
		var y = this.y;
		for (var row = 0; row < this.numy; row++) {
			x = this.x;
			for (var col=0; col< this.numx; col++) {
				var control = this.parent.controls[this.itemid(row, col)];
				control.move(x, y);
				control.toFront();
				x += (this.w + this.gutterx);
			}
			y += (this.h + this.guttery);
		}
	};

	this.setValue = function(value) {
		console.log('Group setValue:', value);
		var bit = 0;
		this.value = value;
		if (typeof value == 'string') {
			for (var row = 0; row < this.numy; row++) {
				for (var col = 0; col < this.numx; col++) {
					var control = this.parent.controls[this.itemid(row, col)];
					if (this.value == control.text) control.highlight();
					else control.dehighlight();
				}
			}
		}
		else if (typeof value == 'number') {
			if (this.reversebits) {
				//console.log('reversing bits');
				for (var row = this.numy-1; row >= 0; row--) {
					for (var col = this.numx-1; col >= 0; col--) {
						var control = this.parent.controls[this.itemid(row, col)];
						var bitvalue = ((value & (1<<bit++)) !== 0) ? 1 : 0;
						if (bitvalue) control.highlight();
						else control.dehighlight();
					}
				}
			}
			else {
				for (var row = 0; row < this.numy; row++) {
					for (var col = 0; col < this.numx; col++) {
						var control = this.parent.controls[this.itemid(row, col)];
						var bitvalue = ((value & (1<<bit++)) !== 0) ? 1 : 0;
						if (bitvalue) control.highlight();
						else control.dehighlight();
					}
				}
			}
		}
		var update = {id: this.id, value: this.value};
		this.fire('update', update);
	};

	return this.init(options || {});
}
621542
function NodeLabelView() {
        NodeParasiticView.apply(this, arguments);

        /** @member {string} */
        this.underline = false;

        this.enabled = true;
        this.movable = MM_FREE;
        this.sizable = SZ_NONE;
        this.text = "";
        this.horizontalAlignment = Graphics.AL_CENTER;
        this.verticalAlignment = Graphics.AL_MIDDLE;
    }
868575
function (item) {
		var legend = this,
			chart = legend.chart,
			renderer = chart.renderer,
			options = legend.options,
			horizontal = options.layout === 'horizontal',
			symbolWidth = options.symbolWidth,
			symbolPadding = options.symbolPadding,
			itemStyle = legend.itemStyle,
			itemHiddenStyle = legend.itemHiddenStyle,
			padding = legend.padding,
			itemDistance = horizontal ? pick(options.itemDistance, 8) : 0,
			ltr = !options.rtl,
			itemHeight,
			widthOption = options.width,
			itemMarginBottom = options.itemMarginBottom || 0,
			itemMarginTop = legend.itemMarginTop,
			initialItemX = legend.initialItemX,
			bBox,
			itemWidth,
			li = item.legendItem,
			series = item.series || item,
			itemOptions = series.options,
			showCheckbox = itemOptions.showCheckbox,
			useHTML = options.useHTML;

		if (!li) { // generate it once, later move it

			// Generate the group box
			// A group to hold the symbol and text. Text is to be appended in Legend class.
			item.legendGroup = renderer.g('legend-item')
				.attr({ zIndex: 1 })
				.add(legend.scrollGroup);

			// Draw the legend symbol inside the group box
			series.drawLegendSymbol(legend, item);

			// Generate the list item text and add it to the group
			item.legendItem = li = renderer.text(
					options.labelFormat ? format(options.labelFormat, item) : options.labelFormatter.call(item),
					ltr ? symbolWidth + symbolPadding : -symbolPadding,
					legend.baseline,
					useHTML
				)
				.css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)
				.attr({
					align: ltr ? 'left' : 'right',
					zIndex: 2
				})
				.add(item.legendGroup);

			// Set the events on the item group, or in case of useHTML, the item itself (#1249)
			(useHTML ? li : item.legendGroup).on('mouseover', function () {
					item.setState(HOVER_STATE);
					li.css(legend.options.itemHoverStyle);
				})
				.on('mouseout', function () {
					li.css(item.visible ? itemStyle : itemHiddenStyle);
					item.setState();
				})
				.on('click', function (event) {
					var strLegendItemClick = 'legendItemClick',
						fnLegendItemClick = function () {
							item.setVisible();
						};
						
					// Pass over the click/touch event. #4.
					event = {
						browserEvent: event
					};

					// click the name or symbol
					if (item.firePointEvent) { // point
						item.firePointEvent(strLegendItemClick, event, fnLegendItemClick);
					} else {
						fireEvent(item, strLegendItemClick, event, fnLegendItemClick);
					}
				});

			// Colorize the items
			legend.colorizeItem(item, item.visible);

			// add the HTML checkbox on top
			if (itemOptions && showCheckbox) {
				item.checkbox = createElement('input', {
					type: 'checkbox',
					checked: item.selected,
					defaultChecked: item.selected // required by IE7
				}, options.itemCheckboxStyle, chart.container);

				addEvent(item.checkbox, 'click', function (event) {
					var target = event.target;
					fireEvent(item, 'checkboxClick', {
							checked: target.checked
						},
						function () {
							item.select();
						}
					);
				});
			}
		}

		// calculate the positions for the next line
		bBox = li.getBBox();

		itemWidth = item.legendItemWidth =
			options.itemWidth || symbolWidth + symbolPadding + bBox.width + itemDistance +
			(showCheckbox ? 20 : 0);
		legend.itemHeight = itemHeight = bBox.height;

		// if the item exceeds the width, start a new line
		if (horizontal && legend.itemX - initialItemX + itemWidth >
				(widthOption || (chart.chartWidth - 2 * padding - initialItemX))) {
			legend.itemX = initialItemX;
			legend.itemY += itemMarginTop + legend.lastLineHeight + itemMarginBottom;
			legend.lastLineHeight = 0; // reset for next line
		}

		// If the item exceeds the height, start a new column
		/*if (!horizontal && legend.itemY + options.y + itemHeight > chart.chartHeight - spacingTop - spacingBottom) {
			legend.itemY = legend.initialItemY;
			legend.itemX += legend.maxItemWidth;
			legend.maxItemWidth = 0;
		}*/

		// Set the edge positions
		legend.maxItemWidth = mathMax(legend.maxItemWidth, itemWidth);
		legend.lastItemY = itemMarginTop + legend.itemY + itemMarginBottom;
		legend.lastLineHeight = mathMax(itemHeight, legend.lastLineHeight); // #915

		// cache the position of the newly generated or reordered items
		item._legendItemPos = [legend.itemX, legend.itemY];

		// advance
		if (horizontal) {
			legend.itemX += itemWidth;

		} else {
			legend.itemY += itemMarginTop + itemHeight + itemMarginBottom;
			legend.lastLineHeight = itemHeight;
		}

		// the width of the widest item
		legend.offsetWidth = widthOption || mathMax(
			(horizontal ? legend.itemX - initialItemX - itemDistance : itemWidth) + padding,
			legend.offsetWidth
		);
	}
201814
function graph (processedTypes, typeTheme) {
  var result = ''

  if (typeTheme.group) {
    result += 'subgraph cluster_' + groupId++ + ' {'
    if (typeTheme.color) {
      result += 'color=' + typeTheme.color + ';'
    }
    if (typeTheme.groupLabel) {
      result += 'label="' + typeTheme.groupLabel + '";'
    }
  }

  result += _.map(processedTypes, v => {
    // sort if desired
    if (this.theme.field.sort) {
      v.fields = _.sortBy(v.fields, 'name')
    }

    var rows = _.map(v.fields, v => {
      return {
        text: createField.call(this, v),
        port: v.name + 'port'
      }
    })

    return createTable.call(this, {
      typeName: getTypeDisplayName(v.name),
      color: typeTheme.color,
      stereotype: typeTheme.stereotype,
      rows: rows
    })
  }).join('\n')

  if (typeTheme.group) {
    result += '}'
  }

  result += '\n\n'
  return result
}
89959
function FunnelPiece(data, idx) {

    graphic.Group.call(this);

    var polygon = new graphic.Polygon();
    var labelLine = new graphic.Polyline();
    var text = new graphic.Text();
    this.add(polygon);
    this.add(labelLine);
    this.add(text);

    this.highDownOnUpdate = function (fromState, toState) {
        if (toState === 'emphasis') {
            labelLine.ignore = labelLine.hoverIgnore;
            text.ignore = text.hoverIgnore;
        }
        else {
            labelLine.ignore = labelLine.normalIgnore;
            text.ignore = text.normalIgnore;
        }
    };

    this.updateData(data, idx, true);
}
1247413
function _addVertexGroupBubble(node, d) {
  var group;

  if(d.vertexGroup) {
    group = node.append('g');
    group.attr('class', 'group-bubble');
    group.append('use').attr('xlink:href', '#group-bubble');
    translateIfIE(group.append('text')
        .text(_trimText(d.get('vertexGroup.groupMembers.length'), 2)), 0, 4);

    translateIfIE(group, 38, 15);
  }
}
568327
function label(d) {

    delete d.d3plus_label

    if (vars.g.edges.selectAll("line, path").size() < vars.edges.large && vars.edges.label && d[vars.edges.label]) {

      if ("spline" in d.d3plus) {

        var length = this.getTotalLength(),
            center = this.getPointAtLength(length/2),
            prev = this.getPointAtLength((length/2)-(length*.1)),
            next = this.getPointAtLength((length/2)+(length*.1)),
            radians = Math.atan2(next.y-prev.y,next.x-prev.x),
            angle = radians*(180/Math.PI),
            bounding = this.parentNode.getBBox(),
            width = length*.8,
            x = center.x,
            y = center.y

      }
      else {

        var bounds = this.getBBox(),
            source = d[vars.edges.source],
            target = d[vars.edges.target],
            start = {"x": source.d3plus.edges[target[vars.id.value]].x, "y": source.d3plus.edges[target[vars.id.value]].y},
            end = {"x": target.d3plus.edges[source[vars.id.value]].x, "y": target.d3plus.edges[source[vars.id.value]].y},
            xdiff = end.x-start.x,
            ydiff = end.y-start.y,
            center = {"x": end.x-(xdiff)/2, "y": end.y-(ydiff)/2},
            radians = Math.atan2(ydiff,xdiff),
            angle = radians*(180/Math.PI),
            length = Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)),
            width = length,
            x = center.x,
            y = center.y

      }

      width += vars.labels.padding*2

      var m = 0
      if (vars.edges.arrows.value) {
        m = typeof vars.edges.arrows.value === "number"
          ? vars.edges.arrows.value : 8
        m = m/vars.zoom.behavior.scaleExtent()[1]
        width -= m*2
      }

      if (angle < -90 || angle > 90) {
        angle -= 180
      }

      if (width*vars.zoom.behavior.scaleExtent()[0] > 20) {

        d.d3plus_label = {
          "x": x,
          "y": y,
          "translate": {"x": x, "y": y},
          "w": width,
          "h": 15+vars.labels.padding*2,
          "angle": angle,
          "anchor": "middle",
          "valign": "center",
          "color": vars.edges.color,
          "resize": false,
          "names": [vars.format.value(d[vars.edges.label])],
          "background": 1
        }

      }

    }

  }
292116
function (group) {
            var options = this.options,
              formatOption = options.format,
              str = formatOption ?
                format(formatOption, this) :
                options.formatter.call(this);  // format the text in the label

            // Change the text to reflect the new total and set visibility to hidden in case the serie is hidden
            if (this.label) {
                this.label.attr({text: str, visibility: HIDDEN});
                // Create new label
            } else {
                this.label =
                  this.axis.chart.renderer.text(str, null, null, options.useHTML)		// dummy positions, actual position updated with setOffset method in columnseries
                    .css(options.style)				// apply style
                    .attr({
                        align: this.textAlign,				// fix the text-anchor
                        rotation: options.rotation,	// rotation
                        visibility: HIDDEN					// hidden until setOffset is called
                    })
                    .add(group);							// add to the labels-group
            }
        }
93739
function showEmbedding(data) {
  const margin = {top: 20, right: 15, bottom: 60, left: 60};
  const width = 800 - margin.left - margin.right;
  const height = 800 - margin.top - margin.bottom;

  const x = d3.scaleLinear().domain([0, 1]).range([0, width]);
  const y = d3.scaleLinear().domain([0, 1]).range([height, 0]);

  const chart = d3.select('body')
                    .append('svg')
                    .attr('width', width + margin.right + margin.left)
                    .attr('height', height + margin.top + margin.bottom)
                    .attr('class', 'chart');

  const main =
      chart.append('g')
          .attr(
              'transform', 'translate(' + margin.left + ',' + margin.top + ')')
          .attr('width', width)
          .attr('height', height)
          .attr('class', 'main');

  const xAxis = d3.axisBottom(x);
  main.append('g')
      .attr('transform', 'translate(0,' + height + ')')
      .attr('class', 'main axis date')
      .call(xAxis);

  const yAxis = d3.axisLeft(y);
  main.append('g')
      .attr('transform', 'translate(0,0)')
      .attr('class', 'main axis date')
      .call(yAxis);

  const dots = main.append('g');

  dots.selectAll('scatter-dots')
      .data(data)
      .enter()
      .append('svg:circle')
      .attr('cx', (d) => x(d[0]))
      .attr('cy', (d) => y(d[1]))
      .attr('stroke-width', 0.25)
      .attr('stroke', '#1f77b4')
      .attr('fill', 'none')
      .attr('r', 5);
}
453988
function group() {                              // experimental
   var o,i=0,a=arguments; 
   if(a[0].length) a = a[0]; 
   
   if((typeof(a[i]) == "object") && (a[i] instanceof CAG)) {
      o = a[i].extrude({offset: [0,0,0.1]});    // -- convert a 2D shape to a thin solid, note: do not a[i] = a[i].extrude()
   } else {
      o = a[i++];                               
   }
   for(; i<a.length; i++) { 
      var obj = a[i];
      if((typeof(a[i]) == "object") && (a[i] instanceof CAG)) {
         obj = a[i].extrude({offset: [0,0,0.1]});    // -- convert a 2D shape to a thin solid:
      }
      o = o.unionForNonIntersecting(obj); 
   } 
   return o; 
}
923427
function exports(_selection) {
            _selection.each(function(_data){
                chartWidth = width - margin.left - margin.right;
                chartHeight = height - margin.top - margin.bottom;
                data = cleanData(_data);

                buildColorScale();
                buildSVG(this);

                if (isHorizontal) {
                    drawHorizontalLegend();
                } else {
                    drawVerticalLegend();
                }

                if (highlightedEntryId) {
                    cleanFadedLines();
                    fadeLinesBut(highlightedEntryId);
                }
            });
        }
1206518
function drawDayLabels() {
            let dayLabelsGroup = svg.select('.day-labels-group');

            dayLabels = svg.select('.day-labels-group').selectAll('.day-label')
                .data(daysHuman);

            dayLabels.enter()
              .append('text')
                .text((label) => label)
                .attr('x', 0)
                .attr('y', (d, i) => i * boxSize)
                .style('text-anchor', 'start')
                .style('dominant-baseline', 'central')
                .attr('class', 'day-label');

            dayLabelsGroup.attr('transform', `translate(-${dayLabelWidth}, ${boxSize / 2})`);
        }
647489
function () {
      var el = this.el;
      var data = this.data;

      var quad = this.quad = document.createElement('a-entity');
      var self = this;

      quad.setAttribute('rotation', data.rotation);
      quad.setAttribute('text', {width: .25, color: '#fff', value: data.text, align: 'center'});
      el.appendChild(quad);

      // Line
      var material = this.material = new THREE.LineBasicMaterial({color: data.lineColor, opacity: data.opacity, transparent: data.opacity < 1});
      var geometry = this.geometry = new THREE.BufferGeometry();
      geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3));

      this.line = new THREE.Line(geometry, material);
      this.el.setObject3D('tooltip-line', this.line);

    }
10638
function(object) {

      var groupLeft = this.get('left'),
          groupTop = this.get('top'),
          groupAngle = this.getAngle() * (Math.PI / 180),
          objectLeft = object.get('originalLeft'),
          objectTop = object.get('originalTop'),
          rotatedTop = Math.cos(groupAngle) * object.get('top') + Math.sin(groupAngle) * object.get('left'),
          rotatedLeft = -Math.sin(groupAngle) * object.get('top') + Math.cos(groupAngle) * object.get('left');

      object.setAngle(object.getAngle() + this.getAngle());

      object.set('left', groupLeft + rotatedLeft * this.get('scaleX'));
      object.set('top', groupTop + rotatedTop * this.get('scaleY'));

      object.set('scaleX', object.get('scaleX') * this.get('scaleX'));
      object.set('scaleY', object.get('scaleY') * this.get('scaleY'));

      object.setCoords();
      object.hideCorners = false;
      object.setActive(false);
      object.setCoords();

      return this;
    }
306347
function drawHoverOverlay() {
            // Not ideal, we need to figure out how to call exit for nested elements
            if (overlay) {
                svg.selectAll('.overlay').remove();
            }

            overlay = svg.select('.metadata-group')
              .append('rect')
                .attr('class', 'overlay')
                .attr('y1', 0)
                .attr('y2', chartHeight)
                .attr('height', chartHeight)
                .attr('width', chartWidth)
                .attr('fill', overlayColor)
                .style('display', 'none');
        }