6393 </xsl:text> |
6382 </xsl:text> |
6394 </xsl:for-each> |
6383 </xsl:for-each> |
6395 <xsl:text> ], |
6384 <xsl:text> ], |
6396 </xsl:text> |
6385 </xsl:text> |
6397 </xsl:template> |
6386 </xsl:template> |
|
6387 <xsl:template match="widget[@type='PathSlider']" mode="widget_desc"> |
|
6388 <type> |
|
6389 <xsl:value-of select="@type"/> |
|
6390 </type> |
|
6391 <longdesc> |
|
6392 <xsl:text>PathSlider - |
|
6393 </xsl:text> |
|
6394 </longdesc> |
|
6395 <shortdesc> |
|
6396 <xsl:text>Slide an SVG element along a path by dragging it</xsl:text> |
|
6397 </shortdesc> |
|
6398 <path name="value" accepts="HMI_INT,HMI_REAL"> |
|
6399 <xsl:text>value</xsl:text> |
|
6400 </path> |
|
6401 <path name="min" count="optional" accepts="HMI_INT,HMI_REAL"> |
|
6402 <xsl:text>min</xsl:text> |
|
6403 </path> |
|
6404 <path name="max" count="optional" accepts="HMI_INT,HMI_REAL"> |
|
6405 <xsl:text>max</xsl:text> |
|
6406 </path> |
|
6407 <arg name="min" count="optional" accepts="int,real"> |
|
6408 <xsl:text>minimum value</xsl:text> |
|
6409 </arg> |
|
6410 <arg name="max" count="optional" accepts="int,real"> |
|
6411 <xsl:text>maximum value</xsl:text> |
|
6412 </arg> |
|
6413 </xsl:template> |
|
6414 <xsl:template match="widget[@type='PathSlider']" mode="widget_class"> |
|
6415 <xsl:text>class </xsl:text> |
|
6416 <xsl:text>PathSliderWidget</xsl:text> |
|
6417 <xsl:text> extends Widget{ |
|
6418 </xsl:text> |
|
6419 <xsl:text> frequency = 10; |
|
6420 </xsl:text> |
|
6421 <xsl:text> position = undefined; |
|
6422 </xsl:text> |
|
6423 <xsl:text> min = 0; |
|
6424 </xsl:text> |
|
6425 <xsl:text> max = 100; |
|
6426 </xsl:text> |
|
6427 <xsl:text> scannedPoints = []; |
|
6428 </xsl:text> |
|
6429 <xsl:text> pathLength = undefined; |
|
6430 </xsl:text> |
|
6431 <xsl:text> precision = undefined; |
|
6432 </xsl:text> |
|
6433 <xsl:text> origPt = undefined; |
|
6434 </xsl:text> |
|
6435 <xsl:text> |
|
6436 </xsl:text> |
|
6437 <xsl:text> |
|
6438 </xsl:text> |
|
6439 <xsl:text> scanPath() { |
|
6440 </xsl:text> |
|
6441 <xsl:text> this.pathLength = this.path_elt.getTotalLength(); |
|
6442 </xsl:text> |
|
6443 <xsl:text> this.precision = Math.floor(this.pathLength / 10); |
|
6444 </xsl:text> |
|
6445 <xsl:text> |
|
6446 </xsl:text> |
|
6447 <xsl:text> // save linear scan for coarse approximation |
|
6448 </xsl:text> |
|
6449 <xsl:text> for (var scanLength = 0; scanLength <= this.pathLength; scanLength += this.precision) { |
|
6450 </xsl:text> |
|
6451 <xsl:text> this.scannedPoints.push([this.path_elt.getPointAtLength(scanLength), scanLength]); |
|
6452 </xsl:text> |
|
6453 <xsl:text> } |
|
6454 </xsl:text> |
|
6455 <xsl:text> [this.origPt,] = this.scannedPoints[0]; |
|
6456 </xsl:text> |
|
6457 <xsl:text> } |
|
6458 </xsl:text> |
|
6459 <xsl:text> |
|
6460 </xsl:text> |
|
6461 <xsl:text> closestPoint(point) { |
|
6462 </xsl:text> |
|
6463 <xsl:text> var bestPoint, |
|
6464 </xsl:text> |
|
6465 <xsl:text> bestLength, |
|
6466 </xsl:text> |
|
6467 <xsl:text> bestDistance = Infinity, |
|
6468 </xsl:text> |
|
6469 <xsl:text> scanDistance; |
|
6470 </xsl:text> |
|
6471 <xsl:text> |
|
6472 </xsl:text> |
|
6473 <xsl:text> // use linear scan for coarse approximation |
|
6474 </xsl:text> |
|
6475 <xsl:text> for (let [scanPoint, scanLength] of this.scannedPoints){ |
|
6476 </xsl:text> |
|
6477 <xsl:text> if ((scanDistance = distance2(scanPoint)) < bestDistance) { |
|
6478 </xsl:text> |
|
6479 <xsl:text> bestPoint = scanPoint, |
|
6480 </xsl:text> |
|
6481 <xsl:text> bestLength = scanLength, |
|
6482 </xsl:text> |
|
6483 <xsl:text> bestDistance = scanDistance; |
|
6484 </xsl:text> |
|
6485 <xsl:text> } |
|
6486 </xsl:text> |
|
6487 <xsl:text> } |
|
6488 </xsl:text> |
|
6489 <xsl:text> |
|
6490 </xsl:text> |
|
6491 <xsl:text> // binary search for more precise estimate |
|
6492 </xsl:text> |
|
6493 <xsl:text> let precision = this.precision / 2; |
|
6494 </xsl:text> |
|
6495 <xsl:text> while (precision > 0.5) { |
|
6496 </xsl:text> |
|
6497 <xsl:text> var beforePoint, |
|
6498 </xsl:text> |
|
6499 <xsl:text> afterPoint, |
|
6500 </xsl:text> |
|
6501 <xsl:text> beforeLength, |
|
6502 </xsl:text> |
|
6503 <xsl:text> afterLength, |
|
6504 </xsl:text> |
|
6505 <xsl:text> beforeDistance, |
|
6506 </xsl:text> |
|
6507 <xsl:text> afterDistance; |
|
6508 </xsl:text> |
|
6509 <xsl:text> if ((beforeLength = bestLength - precision) >= 0 && |
|
6510 </xsl:text> |
|
6511 <xsl:text> (beforeDistance = distance2(beforePoint = this.path_elt.getPointAtLength(beforeLength))) < bestDistance) { |
|
6512 </xsl:text> |
|
6513 <xsl:text> bestPoint = beforePoint, |
|
6514 </xsl:text> |
|
6515 <xsl:text> bestLength = beforeLength, |
|
6516 </xsl:text> |
|
6517 <xsl:text> bestDistance = beforeDistance; |
|
6518 </xsl:text> |
|
6519 <xsl:text> } else if ((afterLength = bestLength + precision) <= this.pathLength && |
|
6520 </xsl:text> |
|
6521 <xsl:text> (afterDistance = distance2(afterPoint = this.path_elt.getPointAtLength(afterLength))) < bestDistance) { |
|
6522 </xsl:text> |
|
6523 <xsl:text> bestPoint = afterPoint, |
|
6524 </xsl:text> |
|
6525 <xsl:text> bestLength = afterLength, |
|
6526 </xsl:text> |
|
6527 <xsl:text> bestDistance = afterDistance; |
|
6528 </xsl:text> |
|
6529 <xsl:text> } |
|
6530 </xsl:text> |
|
6531 <xsl:text> precision /= 2; |
|
6532 </xsl:text> |
|
6533 <xsl:text> } |
|
6534 </xsl:text> |
|
6535 <xsl:text> |
|
6536 </xsl:text> |
|
6537 <xsl:text> return [bestPoint, bestLength]; |
|
6538 </xsl:text> |
|
6539 <xsl:text> |
|
6540 </xsl:text> |
|
6541 <xsl:text> function distance2(p) { |
|
6542 </xsl:text> |
|
6543 <xsl:text> var dx = p.x - point.x, |
|
6544 </xsl:text> |
|
6545 <xsl:text> dy = p.y - point.y; |
|
6546 </xsl:text> |
|
6547 <xsl:text> return dx * dx + dy * dy; |
|
6548 </xsl:text> |
|
6549 <xsl:text> } |
|
6550 </xsl:text> |
|
6551 <xsl:text> } |
|
6552 </xsl:text> |
|
6553 <xsl:text> |
|
6554 </xsl:text> |
|
6555 <xsl:text> dispatch(value,oldval, index) { |
|
6556 </xsl:text> |
|
6557 <xsl:text> switch(index) { |
|
6558 </xsl:text> |
|
6559 <xsl:text> case 0: |
|
6560 </xsl:text> |
|
6561 <xsl:text> this.position = value; |
|
6562 </xsl:text> |
|
6563 <xsl:text> break; |
|
6564 </xsl:text> |
|
6565 <xsl:text> case 1: |
|
6566 </xsl:text> |
|
6567 <xsl:text> this.min = value; |
|
6568 </xsl:text> |
|
6569 <xsl:text> break; |
|
6570 </xsl:text> |
|
6571 <xsl:text> case 2: |
|
6572 </xsl:text> |
|
6573 <xsl:text> this.max = value; |
|
6574 </xsl:text> |
|
6575 <xsl:text> break; |
|
6576 </xsl:text> |
|
6577 <xsl:text> } |
|
6578 </xsl:text> |
|
6579 <xsl:text> |
|
6580 </xsl:text> |
|
6581 <xsl:text> this.request_animate(); |
|
6582 </xsl:text> |
|
6583 <xsl:text> } |
|
6584 </xsl:text> |
|
6585 <xsl:text> |
|
6586 </xsl:text> |
|
6587 <xsl:text> get_current_point(){ |
|
6588 </xsl:text> |
|
6589 <xsl:text> let currLength = this.pathLength * (this.position - this.min) / (this.max - this.min) |
|
6590 </xsl:text> |
|
6591 <xsl:text> return this.path_elt.getPointAtLength(currLength); |
|
6592 </xsl:text> |
|
6593 <xsl:text> } |
|
6594 </xsl:text> |
|
6595 <xsl:text> |
|
6596 </xsl:text> |
|
6597 <xsl:text> animate(){ |
|
6598 </xsl:text> |
|
6599 <xsl:text> if(this.position == undefined) |
|
6600 </xsl:text> |
|
6601 <xsl:text> return; |
|
6602 </xsl:text> |
|
6603 <xsl:text> |
|
6604 </xsl:text> |
|
6605 <xsl:text> let currPt = this.get_current_point(); |
|
6606 </xsl:text> |
|
6607 <xsl:text> this.cursor_transform.setTranslate(currPt.x - this.origPt.x, currPt.y - this.origPt.y); |
|
6608 </xsl:text> |
|
6609 <xsl:text> } |
|
6610 </xsl:text> |
|
6611 <xsl:text> |
|
6612 </xsl:text> |
|
6613 <xsl:text> init() { |
|
6614 </xsl:text> |
|
6615 <xsl:text> if(this.args.length == 2) |
|
6616 </xsl:text> |
|
6617 <xsl:text> [this.min, this.max]=this.args; |
|
6618 </xsl:text> |
|
6619 <xsl:text> |
|
6620 </xsl:text> |
|
6621 <xsl:text> this.scanPath(); |
|
6622 </xsl:text> |
|
6623 <xsl:text> |
|
6624 </xsl:text> |
|
6625 <xsl:text> this.cursor_transform = svg_root.createSVGTransform(); |
|
6626 </xsl:text> |
|
6627 <xsl:text> |
|
6628 </xsl:text> |
|
6629 <xsl:text> this.cursor_elt.transform.baseVal.appendItem(this.cursor_transform); |
|
6630 </xsl:text> |
|
6631 <xsl:text> |
|
6632 </xsl:text> |
|
6633 <xsl:text> this.cursor_elt.onpointerdown = (e) => this.on_cursor_down(e); |
|
6634 </xsl:text> |
|
6635 <xsl:text> |
|
6636 </xsl:text> |
|
6637 <xsl:text> this.bound_drag = this.drag.bind(this); |
|
6638 </xsl:text> |
|
6639 <xsl:text> this.bound_drop = this.drop.bind(this); |
|
6640 </xsl:text> |
|
6641 <xsl:text> } |
|
6642 </xsl:text> |
|
6643 <xsl:text> |
|
6644 </xsl:text> |
|
6645 <xsl:text> start_dragging_from_event(e){ |
|
6646 </xsl:text> |
|
6647 <xsl:text> let clientPoint = new DOMPoint(e.clientX, e.clientY); |
|
6648 </xsl:text> |
|
6649 <xsl:text> let point = clientPoint.matrixTransform(this.invctm); |
|
6650 </xsl:text> |
|
6651 <xsl:text> let currPt = this.get_current_point(); |
|
6652 </xsl:text> |
|
6653 <xsl:text> this.draggingOffset = new DOMPoint(point.x - currPt.x , point.y - currPt.y); |
|
6654 </xsl:text> |
|
6655 <xsl:text> } |
|
6656 </xsl:text> |
|
6657 <xsl:text> |
|
6658 </xsl:text> |
|
6659 <xsl:text> apply_position_from_event(e){ |
|
6660 </xsl:text> |
|
6661 <xsl:text> let clientPoint = new DOMPoint(e.clientX, e.clientY); |
|
6662 </xsl:text> |
|
6663 <xsl:text> let rawPoint = clientPoint.matrixTransform(this.invctm); |
|
6664 </xsl:text> |
|
6665 <xsl:text> let point = new DOMPoint(rawPoint.x - this.draggingOffset.x , rawPoint.y - this.draggingOffset.y); |
|
6666 </xsl:text> |
|
6667 <xsl:text> let [closestPoint, closestLength] = this.closestPoint(point); |
|
6668 </xsl:text> |
|
6669 <xsl:text> let new_position = this.min + (this.max - this.min) * closestLength / this.pathLength; |
|
6670 </xsl:text> |
|
6671 <xsl:text> this.position = Math.round(Math.max(Math.min(new_position, this.max), this.min)); |
|
6672 </xsl:text> |
|
6673 <xsl:text> this.apply_hmi_value(0, this.position); |
|
6674 </xsl:text> |
|
6675 <xsl:text> } |
|
6676 </xsl:text> |
|
6677 <xsl:text> |
|
6678 </xsl:text> |
|
6679 <xsl:text> on_cursor_down(e){ |
|
6680 </xsl:text> |
|
6681 <xsl:text> // get scrollbar -> root transform |
|
6682 </xsl:text> |
|
6683 <xsl:text> let ctm = this.path_elt.getCTM(); |
|
6684 </xsl:text> |
|
6685 <xsl:text> // root -> path transform |
|
6686 </xsl:text> |
|
6687 <xsl:text> this.invctm = ctm.inverse(); |
|
6688 </xsl:text> |
|
6689 <xsl:text> this.start_dragging_from_event(e); |
|
6690 </xsl:text> |
|
6691 <xsl:text> svg_root.addEventListener("pointerup", this.bound_drop, true); |
|
6692 </xsl:text> |
|
6693 <xsl:text> svg_root.addEventListener("pointermove", this.bound_drag, true); |
|
6694 </xsl:text> |
|
6695 <xsl:text> } |
|
6696 </xsl:text> |
|
6697 <xsl:text> |
|
6698 </xsl:text> |
|
6699 <xsl:text> drop(e) { |
|
6700 </xsl:text> |
|
6701 <xsl:text> svg_root.removeEventListener("pointerup", this.bound_drop, true); |
|
6702 </xsl:text> |
|
6703 <xsl:text> svg_root.removeEventListener("pointermove", this.bound_drag, true); |
|
6704 </xsl:text> |
|
6705 <xsl:text> } |
|
6706 </xsl:text> |
|
6707 <xsl:text> |
|
6708 </xsl:text> |
|
6709 <xsl:text> drag(e) { |
|
6710 </xsl:text> |
|
6711 <xsl:text> this.apply_position_from_event(e); |
|
6712 </xsl:text> |
|
6713 <xsl:text> } |
|
6714 </xsl:text> |
|
6715 <xsl:text>} |
|
6716 </xsl:text> |
|
6717 </xsl:template> |
|
6718 <xsl:template match="widget[@type='PathSlider']" mode="widget_defs"> |
|
6719 <xsl:param name="hmi_element"/> |
|
6720 <xsl:call-template name="defs_by_labels"> |
|
6721 <xsl:with-param name="hmi_element" select="$hmi_element"/> |
|
6722 <xsl:with-param name="labels"> |
|
6723 <xsl:text>cursor path</xsl:text> |
|
6724 </xsl:with-param> |
|
6725 </xsl:call-template> |
|
6726 </xsl:template> |
6398 <xsl:template match="widget[@type='ScrollBar']" mode="widget_desc"> |
6727 <xsl:template match="widget[@type='ScrollBar']" mode="widget_desc"> |
6399 <type> |
6728 <type> |
6400 <xsl:value-of select="@type"/> |
6729 <xsl:value-of select="@type"/> |
6401 </type> |
6730 </type> |
6402 <longdesc> |
6731 <longdesc> |
6403 <xsl:text>ScrollBar - documentation to be written |
6732 <xsl:text>ScrollBar - svg:rect based scrollbar |
6404 </xsl:text> |
6733 </xsl:text> |
6405 </longdesc> |
6734 </longdesc> |
6406 <shortdesc> |
6735 <shortdesc> |
6407 <xsl:text>ScrollBar</xsl:text> |
6736 <xsl:text>ScrollBar</xsl:text> |
6408 </shortdesc> |
6737 </shortdesc> |