diff --git a/editor/extension.ts b/editor/extension.ts index 9a822927..957a41da 100644 --- a/editor/extension.ts +++ b/editor/extension.ts @@ -3,7 +3,7 @@ import { deployCoreAsync, initAsync } from "./deploy"; import { FieldPorts } from "./field_ports"; -import { FieldImages } from "./field_images"; +import { FieldMotors } from "./field_motors"; import { FieldSpeed } from "./field_speed"; import { FieldBrickButtons } from "./field_brickbuttons"; import { FieldTurnRatio } from "./field_turnratio"; @@ -17,8 +17,8 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P selector: "ports", editor: FieldPorts }, { - selector: "images", - editor: FieldImages + selector: "motors", + editor: FieldMotors }, { selector: "speed", editor: FieldSpeed diff --git a/editor/field_brickbuttons.ts b/editor/field_brickbuttons.ts index 94f2bc2b..f55ed62b 100644 --- a/editor/field_brickbuttons.ts +++ b/editor/field_brickbuttons.ts @@ -155,5 +155,6 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly. Blockly.DropDownDiv.content_.removeAttribute('role'); Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup'); Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant'); + Blockly.DropDownDiv.getContentDiv().style.width = ''; }; } \ No newline at end of file diff --git a/editor/field_images.ts b/editor/field_images.ts deleted file mode 100644 index 2357a580..00000000 --- a/editor/field_images.ts +++ /dev/null @@ -1,114 +0,0 @@ -/// -/// -/// - -export interface FieldImagesOptions extends pxtblockly.FieldImageDropdownOptions { -} - -export class FieldImages extends pxtblockly.FieldImageDropdown implements Blockly.FieldCustom { - public isFieldCustom_ = true; - - constructor(text: string, options: FieldImagesOptions, validator?: Function) { - super(text, options, validator); - } - - /** - * Create a dropdown menu under the text. - * @private - */ - public showEditor_() { - // If there is an existing drop-down we own, this is a request to hide the drop-down. - if (Blockly.DropDownDiv.hideIfOwner(this)) { - return; - } - // If there is an existing drop-down someone else owns, hide it immediately and clear it. - Blockly.DropDownDiv.hideWithoutAnimation(); - Blockly.DropDownDiv.clearContent(); - // Populate the drop-down with the icons for this field. - let dropdownDiv = Blockly.DropDownDiv.getContentDiv(); - let contentDiv = document.createElement('div'); - // Accessibility properties - contentDiv.setAttribute('role', 'menu'); - contentDiv.setAttribute('aria-haspopup', 'true'); - const options = this.getOptions(); - for (let i = 0, option: any; option = options[i]; i++) { - let content = (options[i] as any)[0]; // Human-readable text or image. - const value = (options[i] as any)[1]; // Language-neutral value. - // Icons with the type property placeholder take up space but don't have any functionality - // Use for special-case layouts - if (content.type == 'placeholder') { - let placeholder = document.createElement('span'); - placeholder.setAttribute('class', 'blocklyDropDownPlaceholder'); - placeholder.style.width = content.width + 'px'; - placeholder.style.height = content.height + 'px'; - contentDiv.appendChild(placeholder); - continue; - } - let button = document.createElement('button'); - button.setAttribute('id', ':' + i); // For aria-activedescendant - button.setAttribute('role', 'menuitem'); - button.setAttribute('class', 'blocklyDropDownButton'); - button.title = content.alt; - if ((this as any).columns_) { - button.style.width = (((this as any).width_ / (this as any).columns_) - 8) + 'px'; - //button.style.height = ((this.width_ / this.columns_) - 8) + 'px'; - } else { - button.style.width = content.width + 'px'; - button.style.height = content.height + 'px'; - } - let backgroundColor = this.sourceBlock_.getColour(); - if (value == this.getValue()) { - // This icon is selected, show it in a different colour - backgroundColor = this.sourceBlock_.getColourTertiary(); - button.setAttribute('aria-selected', 'true'); - } - button.style.backgroundColor = backgroundColor; - button.style.borderColor = this.sourceBlock_.getColourTertiary(); - Blockly.bindEvent_(button, 'click', this, (this as any).buttonClick_); - Blockly.bindEvent_(button, 'mouseup', this, (this as any).buttonClick_); - // These are applied manually instead of using the :hover pseudoclass - // because Android has a bad long press "helper" menu and green highlight - // that we must prevent with ontouchstart preventDefault - Blockly.bindEvent_(button, 'mousedown', button, function (e) { - this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); - e.preventDefault(); - }); - Blockly.bindEvent_(button, 'mouseover', button, function () { - this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); - contentDiv.setAttribute('aria-activedescendant', this.id); - }); - Blockly.bindEvent_(button, 'mouseout', button, function () { - this.setAttribute('class', 'blocklyDropDownButton'); - contentDiv.removeAttribute('aria-activedescendant'); - }); - let buttonImg = document.createElement('img'); - buttonImg.src = content.src; - //buttonImg.alt = icon.alt; - // Upon click/touch, we will be able to get the clicked element as e.target - // Store a data attribute on all possible click targets so we can match it to the icon. - button.setAttribute('data-value', value); - buttonImg.setAttribute('data-value', value); - button.appendChild(buttonImg); - contentDiv.appendChild(button); - } - contentDiv.style.width = (this as any).width_ + 'px'; - dropdownDiv.appendChild(contentDiv); - - Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary()); - - // Calculate positioning based on the field position. - var scale = this.sourceBlock_.workspace.scale; - var bBox = { width: this.size_.width, height: this.size_.height }; - bBox.width *= scale; - bBox.height *= scale; - var position = this.fieldGroup_.getBoundingClientRect(); - var primaryX = position.left + bBox.width / 2; - var primaryY = position.top + bBox.height; - var secondaryX = primaryX; - var secondaryY = position.top; - // Set bounds to workspace; show the drop-down. - (Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); - (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, - (this as any).onHide_.bind(this)); - } -} \ No newline at end of file diff --git a/editor/field_motors.ts b/editor/field_motors.ts new file mode 100644 index 00000000..64984eee --- /dev/null +++ b/editor/field_motors.ts @@ -0,0 +1,565 @@ +/// +/// + +export interface FieldMotorsOptions extends Blockly.FieldCustomDropdownOptions { + +} + +export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldCustom { + public isFieldCustom_ = true; + + private box2_: SVGRectElement; + private textElement2_: SVGTextElement; + private arrow2_: SVGImageElement; + + // Width in pixels + protected itemWidth_: number; + + // Number of rows to display (if there are extra rows, the picker will be scrollable) + protected maxRows_: number; + + protected backgroundColour_: string; + protected itemColour_: string; + protected borderColour_: string; + + private isFirst_: boolean; // which of the two dropdowns is selected + + constructor(text: string, options: FieldMotorsOptions, validator?: Function) { + super(options.data, validator); + + this.itemWidth_ = 75; + this.backgroundColour_ = pxtblockly.parseColour(options.colour); + this.itemColour_ = "rgba(255, 255, 255, 0.6)"; + this.borderColour_ = Blockly.PXTUtils.fadeColour(this.backgroundColour_, 0.4, false); + } + + init() { + if (this.fieldGroup_) { + // Field has already been initialized once. + return; + } + // Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL) + // Positioned on render, after text size is calculated. + /** @type {Number} */ + (this as any).arrowSize_ = 12; + /** @type {Number} */ + (this as any).arrowX_ = 0; + /** @type {Number} */ + this.arrowY_ = 11; + this.arrow_ = Blockly.utils.createSvgElement('image', { + 'height': (this as any).arrowSize_ + 'px', + 'width': (this as any).arrowSize_ + 'px' + }); + this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink', + 'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI); + + this.arrow2_ = Blockly.utils.createSvgElement('image', { + 'height': (this as any).arrowSize_ + 'px', + 'width': (this as any).arrowSize_ + 'px' + }); + this.arrow2_.setAttributeNS('http://www.w3.org/1999/xlink', + 'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI); + (this as any).className_ += ' blocklyDropdownText'; + + // Build the DOM. + this.fieldGroup_ = Blockly.utils.createSvgElement('g', {}, null); + if (!this.visible_) { + (this.fieldGroup_ as any).style.display = 'none'; + } + // Adjust X to be flipped for RTL. Position is relative to horizontal start of source block. + var size = this.getSize(); + var fieldX = (this.sourceBlock_.RTL) ? -size.width / 2 : size.width / 2; + /** @type {!Element} */ + this.textElement_ = Blockly.utils.createSvgElement('text', + { + 'class': (this as any).className_, + 'x': fieldX, + 'dy': '0.7ex', + 'y': size.height / 2 + }, + this.fieldGroup_); + fieldX += 10; // size of first group. + this.textElement2_ = Blockly.utils.createSvgElement('text', + { + 'class': (this as any).className_, + 'x': fieldX, + 'dy': '0.7ex', + 'y': this.size_.height / 2 + }, + this.fieldGroup_); + + this.updateEditable(); + this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_); + // Force a render. + this.render_(); + this.size_.width = 0; + (this as any).mouseDownWrapper_ = + Blockly.bindEventWithChecks_((this as any).getClickTarget_(), 'mousedown', this, + (this as any).onMouseDown_); + + // Add second dropdown + if (this.shouldShowRect_()) { + this.box_ = Blockly.utils.createSvgElement('rect', { + 'rx': (Blockly.BlockSvg as any).CORNER_RADIUS, + 'ry': (Blockly.BlockSvg as any).CORNER_RADIUS, + 'x': 0, + 'y': 0, + 'width': this.size_.width, + 'height': this.size_.height, + 'stroke': this.sourceBlock_.getColourTertiary(), + 'fill': this.sourceBlock_.getColour(), + 'class': 'blocklyBlockBackground', + 'fill-opacity': 1 + }, null); + this.fieldGroup_.insertBefore(this.box_, this.textElement_); + this.box2_ = Blockly.utils.createSvgElement('rect', { + 'rx': (Blockly.BlockSvg as any).CORNER_RADIUS, + 'ry': (Blockly.BlockSvg as any).CORNER_RADIUS, + 'x': 0, + 'y': 0, + 'width': this.size_.width, + 'height': this.size_.height, + 'stroke': this.sourceBlock_.getColourTertiary(), + 'fill': this.sourceBlock_.getColour(), + 'class': 'blocklyBlockBackground', + 'fill-opacity': 1 + }, null); + this.fieldGroup_.insertBefore(this.box2_, this.textElement2_); + } + + // Force a reset of the text to add the arrow. + var text = this.text_; + this.text_ = null; + this.setText(text); + } + + getFirstValue(text: string) { + // Get first set of words up until last space + return this.normalizeText_(text.substring(0, text.lastIndexOf(' '))); + } + + getSecondValue(text: string) { + // Get last word + return this.normalizeText_(text.match(/\S*$/)[0]); + } + + private normalizeText_(text: string) { + if (!text) { + // Prevent the field from disappearing if empty. + return Blockly.Field.NBSP; + } + if (text.length > this.maxDisplayLength) { + // Truncate displayed string and add an ellipsis ('...'). + text = text.substring(0, this.maxDisplayLength - 2) + '\u2026'; + } + // Replace whitespace with non-breaking spaces so the text doesn't collapse. + text = text.replace(/\s/g, Blockly.Field.NBSP); + if (this.sourceBlock_.RTL) { + // The SVG is LTR, force text to be RTL. + text += '\u200F'; + } + return text; + } + + updateTextNode2_() { + if (!this.textElement2_) { + // Not rendered yet. + return; + } + var text = this.text_; + if (text.length > this.maxDisplayLength) { + // Truncate displayed string and add an ellipsis ('...'). + text = text.substring(0, this.maxDisplayLength - 2) + '\u2026'; + // Add special class for sizing font when truncated + this.textElement2_.setAttribute('class', (this as any).className_ + ' blocklyTextTruncated'); + } else { + this.textElement2_.setAttribute('class', (this as any).className_); + } + // Empty the text element. + goog.dom.removeChildren(/** @type {!Element} */(this.textElement2_)); + // Replace whitespace with non-breaking spaces so the text doesn't collapse. + text = text.replace(/\s/g, Blockly.Field.NBSP); + if (this.sourceBlock_.RTL && text) { + // The SVG is LTR, force text to be RTL. + text += '\u200F'; + } + if (!text) { + // Prevent the field from disappearing if empty. + text = Blockly.Field.NBSP; + } + var textNode = document.createTextNode(text); + this.textElement2_.appendChild(textNode); + + // Cached width is obsolete. Clear it. + this.size_.width = 0; + }; + + patchDualMotorText(text: string) { + if (text === null) { + return text; + } + if (text.indexOf(' ') == -1) { + text = `large motors ${text}`; + } + return text; + } + + setText(text: string) { + if (text === null || text === this.text_) { + // No change if null. + return; + } + text = this.patchDualMotorText(text); + this.text_ = text; + this.updateTextNode_(); + this.updateTextNode2_(); + + if (this.textElement_) { + this.textElement_.parentNode.appendChild(this.arrow_); + } + if (this.textElement2_) { + this.textElement2_.parentNode.appendChild(this.arrow2_); + } + if (this.sourceBlock_ && this.sourceBlock_.rendered) { + this.sourceBlock_.render(); + this.sourceBlock_.bumpNeighbours_(); + } + } + + positionArrow2(start: number, x: number) { + if (!this.arrow2_) { + return 0; + } + + var addedWidth = 0; + if (this.sourceBlock_.RTL) { + (this as any).arrow2X_ = (this as any).arrowSize_ - (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING; + addedWidth = (this as any).arrowSize_ + (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING; + } else { + (this as any).arrow2X_ = x + (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING / 2; + addedWidth = (this as any).arrowSize_ + (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING; + } + if (this.box_) { + // Bump positioning to the right for a box-type drop-down. + (this as any).arrow2X_ += Blockly.BlockSvg.BOX_FIELD_PADDING; + } + (this as any).arrow2X_ += start; + this.arrow2_.setAttribute('transform', + 'translate(' + (this as any).arrow2X_ + ',' + this.arrowY_ + ')' + ); + return addedWidth; + }; + + updateWidth() { + // Calculate width of field + var width = Blockly.Field.getCachedWidth(this.textElement_); + var width2 = Blockly.Field.getCachedWidth(this.textElement2_); + + // Add padding to left and right of text. + if (this.EDITABLE) { + width += Blockly.BlockSvg.EDITABLE_FIELD_PADDING; + width2 += Blockly.BlockSvg.EDITABLE_FIELD_PADDING; + } + + // Adjust width for drop-down arrow. + this.arrowWidth_ = 0; + if (this.positionArrow) { + this.arrowWidth_ = this.positionArrow(width); + width += this.arrowWidth_; + } + + // Add padding to any drawn box. + if (this.box_) { + width += 2 * Blockly.BlockSvg.BOX_FIELD_PADDING; + } + + // Adjust width for second drop-down arrow. + (this as any).arrowWidth2_ = 0; + if (this.positionArrow2) { + (this as any).arrowWidth2_ = this.positionArrow2(width + Blockly.BlockSvg.BOX_FIELD_PADDING, width2); + width2 += (this as any).arrowWidth2_; + } + + // Add padding to any drawn box. + if (this.box2_) { + width2 += 2 * Blockly.BlockSvg.BOX_FIELD_PADDING; + } + + // Set width of the field. + this.size_.width = width + Blockly.BlockSvg.BOX_FIELD_PADDING + width2; + (this as any).width1 = width; + (this as any).width2 = width2; + }; + + render_() { + if (this.visible_ && this.textElement_) { + goog.dom.removeChildren(/** @type {!Element} */(this.textElement_)); + goog.dom.removeChildren(/** @type {!Element} */(this.textElement2_)); + + var text = this.text_; + text = this.patchDualMotorText(text); + + // First dropdown + const textNode1 = document.createTextNode(this.getFirstValue(text)); + this.textElement_.appendChild(textNode1); + + // Second dropdown + if (this.textElement2_) { + const textNode2 = document.createTextNode(this.getSecondValue(text)); + this.textElement2_.appendChild(textNode2); + } + this.updateWidth(); + + // Update text centering, based on newly calculated width. + let centerTextX = ((this as any).width1 - this.arrowWidth_) / 2; + if (this.sourceBlock_.RTL) { + centerTextX += this.arrowWidth_; + } + + // In a text-editing shadow block's field, + // if half the text length is not at least center of + // visible field (FIELD_WIDTH), center it there instead, + // unless there is a drop-down arrow. + if (this.sourceBlock_.isShadow() && !this.positionArrow) { + let minOffset = (Blockly.BlockSvg as any).FIELD_WIDTH / 2; + if (this.sourceBlock_.RTL) { + // X position starts at the left edge of the block, in both RTL and LTR. + // First offset by the width of the block to move to the right edge, + // and then subtract to move to the same position as LTR. + let minCenter = (this as any).width1 - minOffset; + centerTextX = Math.min(minCenter, centerTextX); + } else { + // (width / 2) should exceed Blockly.BlockSvg.FIELD_WIDTH / 2 + // if the text is longer. + centerTextX = Math.max(minOffset, centerTextX); + } + } + + // Apply new text element x position. + var width = Blockly.Field.getCachedWidth(this.textElement_); + var newX = centerTextX - width / 2; + this.textElement_.setAttribute('x', `${newX}`); + + // Update text centering, based on newly calculated width. + let centerTextX2 = ((this as any).width2 - (this as any).arrowWidth2_) / 2; + if (this.sourceBlock_.RTL) { + centerTextX2 += (this as any).arrowWidth2_; + } + + // In a text-editing shadow block's field, + // if half the text length is not at least center of + // visible field (FIELD_WIDTH), center it there instead, + // unless there is a drop-down arrow. + if (this.sourceBlock_.isShadow() && !this.positionArrow2) { + let minOffset = (Blockly.BlockSvg as any).FIELD_WIDTH / 2; + if (this.sourceBlock_.RTL) { + // X position starts at the left edge of the block, in both RTL and LTR. + // First offset by the width of the block to move to the right edge, + // and then subtract to move to the same position as LTR. + let minCenter = (this as any).width2 - minOffset; + centerTextX2 = Math.min(minCenter, centerTextX2); + } else { + // (width / 2) should exceed Blockly.BlockSvg.FIELD_WIDTH / 2 + // if the text is longer. + centerTextX2 = Math.max(minOffset, centerTextX2); + } + } + + // Apply new text element x position. + var width2 = Blockly.Field.getCachedWidth(this.textElement2_); + var newX2 = centerTextX2 - width2 / 2; + this.textElement2_.setAttribute('x', `${newX2 + (this as any).width1 + Blockly.BlockSvg.BOX_FIELD_PADDING}`); + } + + // Update any drawn box to the correct width and height. + if (this.box_) { + this.box_.setAttribute('width', `${(this as any).width1}`); + this.box_.setAttribute('height', `${this.size_.height}`); + } + + // Update any drawn box to the correct width and height. + if (this.box2_) { + this.box2_.setAttribute('x', `${(this as any).width1 + Blockly.BlockSvg.BOX_FIELD_PADDING}`); + this.box2_.setAttribute('width', `${(this as any).width2}`); + this.box2_.setAttribute('height', `${this.size_.height}`); + } + }; + + showEditor_(e?: MouseEvent) { + // If there is an existing drop-down we own, this is a request to hide the drop-down. + if (Blockly.DropDownDiv.hideIfOwner(this)) { + return; + } + this.isFirst_ = e.clientX - this.getScaledBBox_().left < ((this as any).width1 * this.sourceBlock_.workspace.scale); + // If there is an existing drop-down someone else owns, hide it immediately and clear it. + Blockly.DropDownDiv.hideWithoutAnimation(); + Blockly.DropDownDiv.clearContent(); + // Populate the drop-down with the icons for this field. + let dropdownDiv = Blockly.DropDownDiv.getContentDiv(); + let contentDiv = document.createElement('div'); + // Accessibility properties + contentDiv.setAttribute('role', 'menu'); + contentDiv.setAttribute('aria-haspopup', 'true'); + let options = this.getOptions(); + + // Hashmap of options + let opts = {}; + let conts = {}; + let vals = {}; + for (let opt in options) { + let text = options[opt][0].alt ? options[opt][0].alt : options[opt][0]; + if (text.indexOf(' ') == -1) { + // Patch dual motors as they don't have prefixes. + text = this.patchDualMotorText(text); + if (options[opt][0].alt) options[opt][0].alt = text; + } + const value = options[opt][1]; + const firstValue = this.getFirstValue(text); + const secondValue = this.getSecondValue(text); + if (!opts[firstValue]) opts[firstValue] = [secondValue]; + else opts[firstValue].push(secondValue); + // Store a hash of the original key value pairs for later + conts[text] = options[opt][0]; + vals[text] = value; + } + + const currentFirst = this.getFirstValue(this.text_); + const currentSecond = this.getSecondValue(this.text_); + + if (!this.isFirst_) { + options = opts[currentFirst]; + } else { + options = Object.keys(opts); + // Flip the first and second options to make it sorted the way we want it (medium, large, dual) + if (options.length == 3) { + const temp = options[1]; + options[1] = options[0]; + options[0] = temp; + } else { + options.reverse(); + } + } + + const isFirstUrl = { + 'large motors': FieldMotors.DUAL_MOTORS_DATAURI, + 'large motor': FieldMotors.MOTORS_LARGE_DATAURI, + 'medium motor': FieldMotors.MOTORS_MEDIUM_DATAURI + } + const columns = options.length; + + for (let i = 0, option: any; option = options[i]; i++) { + let text = this.isFirst_ ? option + ' ' + opts[option][0] : currentFirst + ' ' + option; + text = text.replace(/\xA0/g, ' '); + const content: any = conts[text]; + const value = vals[text]; + // Icons with the type property placeholder take up space but don't have any functionality + // Use for special-case layouts + if (content.type == 'placeholder') { + let placeholder = document.createElement('span'); + placeholder.setAttribute('class', 'blocklyDropDownPlaceholder'); + placeholder.style.width = content.width + 'px'; + placeholder.style.height = content.height + 'px'; + contentDiv.appendChild(placeholder); + continue; + } + let button = document.createElement('button'); + button.setAttribute('id', ':' + i); // For aria-activedescendant + button.setAttribute('role', 'menuitem'); + button.setAttribute('class', 'blocklyDropDownButton'); + button.title = this.isFirst_ ? this.getFirstValue(content.alt) : content.alt; + button.style.width = ((this.itemWidth_) - 8) + 'px'; + button.style.height = ((this.itemWidth_) - 8) + 'px'; + let backgroundColor = this.backgroundColour_; + if (value == this.getValue()) { + // This icon is selected, show it in a different colour + backgroundColor = this.sourceBlock_.getColourTertiary(); + button.setAttribute('aria-selected', 'true'); + } + button.style.backgroundColor = backgroundColor; + button.style.borderColor = this.borderColour_; + Blockly.bindEvent_(button, 'click', this, this.buttonClick_); + Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_); + // These are applied manually instead of using the :hover pseudoclass + // because Android has a bad long press "helper" menu and green highlight + // that we must prevent with ontouchstart preventDefault + Blockly.bindEvent_(button, 'mousedown', button, function (e) { + this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); + e.preventDefault(); + }); + Blockly.bindEvent_(button, 'mouseover', button, function () { + this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); + contentDiv.setAttribute('aria-activedescendant', this.id); + }); + Blockly.bindEvent_(button, 'mouseout', button, function () { + this.setAttribute('class', 'blocklyDropDownButton'); + contentDiv.removeAttribute('aria-activedescendant'); + }); + let buttonImg = document.createElement('img'); + buttonImg.src = this.isFirst_ ? isFirstUrl[option.replace(/\xA0/g, ' ')] : content.src; + //buttonImg.alt = icon.alt; + // Upon click/touch, we will be able to get the clicked element as e.target + // Store a data attribute on all possible click targets so we can match it to the icon. + button.setAttribute('data-value', value); + buttonImg.setAttribute('data-value', value); + button.appendChild(buttonImg); + contentDiv.appendChild(button); + } + contentDiv.style.width = (this.itemWidth_ * columns) + 'px'; + dropdownDiv.appendChild(contentDiv); + + Blockly.DropDownDiv.setColour(this.backgroundColour_, this.borderColour_); + + // Calculate positioning based on the field position. + let scale = this.sourceBlock_.workspace.scale; + let width = this.isFirst_ ? (this as any).width1 : (this as any).width2; + let bBox = { width: this.size_.width, height: this.size_.height }; + width *= scale; + bBox.height *= scale; + let position = this.fieldGroup_.getBoundingClientRect(); + let leftPosition = this.isFirst_ ? position.left : position.left + (scale * (this as any).width1) + Blockly.BlockSvg.BOX_FIELD_PADDING; + let primaryX = leftPosition + width / 2; + let primaryY = position.top + bBox.height; + let secondaryX = primaryX; + let secondaryY = position.top; + // Set bounds to workspace; show the drop-down. + (Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); + (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, + this.onHide_.bind(this)); + + // Update colour to look selected. + if (this.isFirst_ && this.box_) { + this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary()); + } else if (!this.isFirst_ && this.box2_) { + this.box2_.setAttribute('fill', this.sourceBlock_.getColourTertiary()); + } + } + + protected buttonClick_ = function (e: any) { + let value = e.target.getAttribute('data-value'); + this.setValue(value); + Blockly.DropDownDiv.hide(); + }; + + + /** + * Callback for when the drop-down is hidden. + */ + protected onHide_ = function () { + Blockly.DropDownDiv.content_.removeAttribute('role'); + Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup'); + Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant'); + Blockly.DropDownDiv.getContentDiv().style.width = ''; + if (this.isFirst_ && this.box_) { + this.box_.setAttribute('fill', this.sourceBlock_.getColour()); + } else if (!this.isFirst_ && this.box2_) { + this.box2_.setAttribute('fill', this.sourceBlock_.getColour()); + } + }; + + static MOTORS_MEDIUM_DATAURI = 'data:image/png;base64,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'; + + + static MOTORS_LARGE_DATAURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALiQAAC4kBN8nLrQAAActpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+d3d3Lmlua3NjYXBlLm9yZzwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KGMtVWAAAFAhJREFUeAHtXXt0FNd5/2Z3tdrVrt5CCARUgISEkCoeiXFxeMS1E+q0PfVxSaCQ/hPn2HGbYrvHjx6f9kBrH7dpc1zHdqiJbJ+TtjYmTlICNgZsgymER3EwD/ESCD1BL4S0euxK+5h+vytmWa1WqxXs7sys9jtnd2bu3Llz5/vN993vfvfebyRKUlgOyETSrvkzio0Gw7eMsrzMR3IVSXIWJ7dKEh33yfIeMns/f+hka0fYglQ6Kal0X83floE17KkoXC/L0haurC24wj0GE10zpVKW103TvEMky3TSIBsfXX2+4XfBedU8TgIcgvu7KqbNN8rGA3wqP8RpOpGaTnvTcolfAkGVQ330J/2dBGb6iD7MzqA1y440O2+dVnVjUPXuGrz5xxWF32Zwz3HVQoLby5L7SQC4eIQzZjtdTEkTT8MM/VaPgxo/XFBUIBJU/ksCHADARwsK/5xV8vsBSaN224wp5B2VStTK6jqA8iTy1H20qGBKQJoqu0mAb7Edalki6RfjoZDLbW4oyglKZ3VtlQaNx99csiQlVP54pSUBZk7DoDLIpk8jYXq2z0NLXY4RWWe6XbSA2+FRJElFs5yt/zwqPY4JSSOLmb27fMYGtpD+M1K+15ks5OC2uN9gpGyW3FL3ABnDXJzilfMeuNByI0yWmJ0KV6+Y3VRLBaOfW5uffqjTaE79pX0q7bbl0TlzmgAO0hpMTga1OqOQLnEeB7fHK13dlMp9pHDkM0jSf3c49oXLE6tzk1pFb9q0KeP9e+b9vocM6e/aC6iJDSUYUB1GM/0ifSp1MYDB1Ga4ndYnGcjiC2VyBV0l0V/jRQpKjcuhKS530eBNtmzZ8khWdtYHlhMzuxqaG6mPJTOQPIwHuj5Wk48dVzIVu51kk72U6x6kxZ3NNCXVzC23Maxq9pcnk3VvxfQZdPZakz8tTjuTUoK3bN3yXYALHhtdfTmGMVQskvdas2kXq+0v2LlxQ5bolM9IH3q4LzzgoSVDvRHD5JGMsyPOHMWMk06Ct1ZvfSLdnv6GwkNjr4N+z+OiXHY33mDVrFCq7KMc3xC5WQ2DnC4nbRq63dc1s8J18gvgMxqpiw2u6Z5BIc1edlA3sBGGq2ay1Ct6weDzThcFxflvUgH81ltv/TDNlvaTQB5LLpcAYX1fOx2wZlELg5zDxtUqZzeZuANVPtRPrZyW4fVwxzZFgIrr63wGesFtoe9YzfSJNYdgkK3ta6N3bVOpxzjMVvSN13NaBp+TZCMPUMSfJgvAUnV19QsM7j8Fs9hnTydDdxelMwjwJwfTw/23BolYFHMkmV53m4W1VG5grzPTNeOwVNv4+n0MtAIuzsFI28cq/hEugzV7K9LiTZOhDZaq367+e5vdNgpcMFtOz4yY5+gMWfhXwuA+njIkfvBNwzwuHRoQ0h9cWEsKruD7eOXrweficZzoEiy9/fO3/9Vqtv7tWMz0FBSSsenqWKf96ddZTe/NzKfVrLLzPENEbv4x/WXvdULf2Mxt9nmzTez7L+IdxbU5ZDZdDEyP134iS7D0zjvv/Fs4cMFkd9mCiHhdl2IlSOtRSyYd57Y6kKzcF+bJAPSHzi4yBVjkAH3lwE3OKtU//GV9d+A18dpPWAnmfu4yi9Xy9HiM9MyaTaId7gvf5SljdyTck42sckt4PxTNYkv6cUcLe8JsYqwYBloWDCyiF0Llj0dawgIsy5hWEwGxeh1c8SBZP/pVyMzwUx1g4+ksgwZaPOigr7l6xH6ov0wG9A8Cz8vUm5rfvD1U3nikJbKKjph/g4vuIV9eyPF92s/gHrVkCE8XvF0H2So+xmo6UmIv2LqvH6DRTu1IC7jLfAkLsM/gg9EbGTFw/Y98lyh12OINvOj0LckdmWYPPAy3X736fMuH4TLE+lzCAmwidiJPgLz5BdT/8DqSDSNZYmTPVDAZ/LOxgs/cPpZJ3re6pvmx2ynq7I18GnXqoJm7ukvKqX/990m2Ds+vQsUWDo42vkKlBT1E9fGaltX8akzoJQsqIyqHiWxkRa6iA1jpKSqm3kc3UtruX5Pp8gVa4bwpuj5nePwXfmWA+5UQoN8qoo97Sd9+6Fzz7oAiVd1NWIAn1AYHQeDLyqG+dd8jU/1lshz5nO7j7X08sD82SXV87gXLlKYP1DSoQtUvYQEO9bATTYM09/FPGhyklLpLJHV1kKG3l6QhF/lsdvL46FDHvoN/+kRjI7wZmqREAph7JMNaefPmzRLbQanR4ricmkpD8ytHFcf3m/HEW/+lWXBRYV0DvH37djMz+e/YYv0rfpYp729/n5eQyDRz1kyVJsiMegdUT9AtwPv37ze1tbcdyc3NXTx//nyyWqzU1tZGZ2vODjP1jkws1fGIegV0C/D19utrszOzF9//9ft5UvNwby8nJ4fS03nd0L69JIXov0abe6wtRneSo32TuyxPt/1gXoWwZs6cOX5wFT4UFhZSGvdjfXHogvJLpHk9oWeAc02m0ArIaEKPNfaUlOBY8lgmqbmpedQduru7qb+/X6xHGXVyEiboVoKB1fXW63TiixPk4olzsJ7b29vp8OHDYj8OGloXr0toHaeLqhNNnTqVbty4QTt+s0O0xUaewjp9+nRy8FRYTHNNks77wQurFlJWVhb19fWR2+2mzMxMYT33OnqpkVcrJEnnAAPYXnYdXrt2jTw8bxndpOnTptOAc4Bk7Ru4cXn/dK2iD//2sGBSUVERZWZkUk1NDZ06dYqcTidJXs13UZMAR8qBRQsXkdlsprqrdeTx3Jodo2vzMdInHz+friW4pLiE5s6dK8DFo8Kr1d3TTfv2xWcpLvvANf8a6RrgzKxMYVgp77HdbqeUlNvrd5X0ybzVNcC1l2qps6OTFi0aVtGnT5+mrptdAk9J+27iuLx3mlcx4bjQ4+ih+oZ60U1Cvqv1V6m1dXiNV9KKHuacrgGGSg70R2MEacoU1UNThXsn435O1yq6YkEFTZs2zT+i9OADD5LFYiEM/A8MhF5eEncOq3xDXQN88+ZNau9oFwP9kN68vDyaO2cu+XwcE/bW9B2V+av67XUN8MVLF8lms9G8efPIauUZHa1t9Olnn9LQEC/tTPo5xMula4DT0tLom9/4pr9rNHPGTOGbPnT4kOqSo5UK6NrIKikp8YOrMFRxfPCMDyVpUm/1C7CBnJYQi8WAJtKTbfDwe61bgNmR8VsM+AcTZnP0YjF3UoAFa3QLMLskX29sbOw/f+G8X1r7+vsII0yQ3kAVjeOJ/IJfGj0f6/o9f++99xZJBmkHOztmov+L8WEAiSk86CrBCMMxRpgGefkJ0sIRZoRgVArOk0im3Xp93qYNf7FhVrgy1T6nWwkG49atW3fywvkLRe4hd+FA/0AZ4pax5JY7nI5Kj9vzNMAFsPhhEMJsMY/949iTABhdLPxw7XhkIMNwqJ3xMqp4XtfdJPBt06ZNEMtrwTx85ZVXzGYGbYjDHdnSbAK84Dyhjt0et98LBmkeS5JZ6Q91dHT8WagytJSmawkOx0jM0WIpFmoakhkppZhSyGa1CalHGaEkmdP6mxubyzdu3HhrnUykpcc/X8ICzO1uipnjSJpuxY2cCGtNKSbxYsAiDwaYR6l6W5pbKp999tkrEylTrbwJCzC7MO1m0+3osRNlMAwtc4p5BMA+2dfZVN9U9swzz1ydaHlq5U9YgD1RiFzE7awfYLbA22sv1lY+99xzo9p7tcCL5L66N7LGekiDzzC+GTzWxUHpLLlNZ8+cXfTyyy+r8mGNoOpM6DBhAQYXgtvPYM6MZSEH5mPJrec1UIsZXE2v5A+sc+B+wgLsGHBIma7wEelgXeOH9cWhwGZHRu2J/zvxlddee23kh5ICOajxfV0B/MYbbxRz0Ik5rH5HeOBYymQGyOmVGBKv1+MadBk5yuwD4TxXABTdKHi50N8F0MEg112uW6VncPHu6QbgV199dVZ2bvYF9lpx5F6OsGLmGCsjYL4zUXI5XeRwOCgjI2MUyLxacXiK5p0VrYmrdGFFP/XUU9a8/LxDQ4NDxkHXIPFW+JujwUEOOSzmcWGNE0v/iHabw0FEzVCLRl3vpAw9SLBUtbjqXYNkmBloNLFlO+7gwXgMUVQypvtgmi0GKxDjY6w2ebzytHhe8wD/7O2fPZ6akip8vhgw8HmHgcWAABaZBYI+EQYDXLS7YhCC2+A0Sxr1e/sFyJiOqwR2mUiZWsyraYDZqFpoT7P/VGEcQIHzAduMzIy7DtMALYAXBcOLMLQwvDjgGhAhIDCZLxFIswC/+eabeelZ6QcZT0GQVIDBdjIJCcMHq+7SyOLhPjJZTeT1eAWwkFrE23IOOIfjfCQAwpo0stasWWNcsXLFJzwtJx08BrjKoD2kjNvjqLIeUXkwigSVj7JhXPFWZsPrLl+hqFbzjgqLLqfuqAqjL3rxxRf/nbtBVTgDcNGfhQGE8d07GR0afYfRKamWVNHu4l58T8mebqfyqvKy0Tn1laK5N/Tw0cPfqCyv3NPZ2UnHjh8T4PJsDaGOoZpjSXiJUjnwKAwvkHPQ+Vn3je5N+fn5bsVjYDFZBl1prisbHtqgC++WpiSYg4tOKS8t/x8FREivMpeKv1ymJMdsGzhRDzfh4/v5vgdZhR8xSaYjmfbMIzm5Ob+zuqxd27Zv2xyzikSxYM0YWWh3ly9ffoC7LlY8H8DFjAr8AG4w86PIg4iKWrJkCRXPLRZ5uU5G1i7/sG3btitr1679eUQFqJRJMxL80ksvvc5dk3LwAeAqRhWsWvRX1aQZhTP84KIeUOFL71mKrtW/qFmvSO6tCYCPHDnyRwUFBY8rFVaMKvR3U8zqh2QIteYYIHMIiQJuVtR9+xSmjbFVHeAdO3ZM5XjP/s+OAVys7UXMyXi0u2PwZUSyiH05ImX4AOkMvuYM1cCqqgow3v577733c3YwiC9SKUYV1v0iRKHa7a7CKIRnwmBEINXW1vqn1wama21fVSOLg6f8Bzv6S8EUxaiC5NZerhUeK60wC/YAgowjPjUcLQj80tzSrJXqha2HagAfO3bsjzmY6KNK7TBU19PTQw0NDVEbClTKvtvt4kWLxQLzxqZG0XTk5uSKdcmnz5wWgx93W34sr1cFYLS780rnfaA8mNLu4psLnV2dmlHNSv0Q5BSRbdnhIax7SDEMQGz7evuUbJrcqgJwWVnZPxoNRvHZG6Xd7erqoqamJs2BC9TOnT9HNedqiJeqCBAx8oSwxQjZhBiZWiZVAGajym/cKdJbe6WWMHynRYJmgcSuXLFSBHr5eM/HVF9fL6qqdYD9jFaLsWh74QPGNBytEmZ8TCuYRvwJH7G0FNKLiD56IFUkOJAxUNFalVylnnBRLliwQDkkGF3QPB/80m9G+M9pbUd1CQZDAPJ45OhxCKaCsbC2cQ2kX+mfYlBCCX4GBwQmB0SLME6MIOMKwT+OmZiR1Fu5Rq2tJgAe7+EBGAJ9t7e1iz7o6VOnBbBNjU106stTYkYGHA81Z2tEUdjiOFp0+cpl2rlzp3C+oMzP9n9Ge/buiVbxMS1HdRUdydPB0QBC2H6jPOz6hfQiXUgyT+MRx3wehH1Mw4k2YXE4COXrhXQhwWozs6ioiMpKy8RyUtQF8TGXf225mBygdt3Gu78uJHi8h4j1+eysbJo9e7aIiznQMkCl80qFkwOBX7ROSYAjQOjy5cviq6Yw8DA+DYMLXSUYdWMFY4ug2LhkSQIcAZsRWG1+2XyqqKgQkw9g9B09dlTMNongclWzJNvgCNg/NX8qVVVV+WeWYFL8smXL/McRFKFaliTAEbAeRlUwQVVnZ2cHJ2vuOAlwBJDAiRKKON2zatUqTfeZkgCHQi4oDR/7CAa5ubkZ3qxf8yDE+G64oPLieZg0siLgNhan7d27l0rLSkXUPAwbsqeshVc6PhbB5apmSQIcnv0DPBDSwVLqgz/6y5NfYnVjl+yTf8VTeX+yfv16bY/287MlAQ4DsFf2/vQHj/3gmTBZNH9KE20wBtOTFBsOqA4wwA2Y4BGbp4ywVGVxeYTZdZFNdYABLtx9klFdKQa4GJlKNG2iCYAxiS3DxiEZVCRE70E0Aa1ok2ixQnWAITGYflpcXKza8BvGeTn+luApwjckEqliRfOojN81BIAhwZh7XFlRSQ1NDYTpORiwV6bEQIVjTrLdZhcqFPtIQ8gjDL4j/AKG9NKsacTTccWEOAzlYV8hTA4IHKjHfdlKFtHuMEqkEPIgko/ByOENZUn3aKsCMM+i/EJhKLZgtgCEl4liBiMcC8osDgXkpUuXBl4yah/fEFaosrJS2R2xrampobb2Nn+aEkYJq/qhonEvqGiAC+LPAZzyZ9bpjioAX7lyZRuv83mdGZym8A0gY0kmfrEK1cBLVOnkyZPU2taq3Na/NdqMYlKfshaZTa7+S32XPvJn0OmOaqbrgQMHvlq1sOp/lRUO8eIf1PFYICt1YHAHWztav/r0D58+o6TpdasawGDYrl27slmSn2OJvY8lB0FGJf7l8G9eLBkKVXzmzJmDHOilhzWHf7BANshut8t9iJeuvvP888/3xLIO8SpbVYBDPSQHHl1QMq8k5l8z2fmbnZbdu3f7jb1QdUmENFXa4HCM43bSk5WVFS5LVM6x1vBLblQK1GghmgOYp8MguHfM2cWzMSYFwKo7OmKO5CS/QRLgBH8BNAcwe5ImheqM13ulOYC5CxOPGJB9W7duHXY+x4vTKt1HcwA/+eSTbexo+CSm/JDpxzEtX0OFaw5g8Oam4ebD/Mmbz+GPjurP7enmQYzvcXzJzRrCIKZViX1/5A6r/6Mf/+g7dqt92x1eHvIyHhas3vg3G78f8mSCJv4/fjDRRpvZhV8AAAAASUVORK5CYII='; + + static DUAL_MOTORS_DATAURI = 'data:image/png;base64,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'; +} \ No newline at end of file diff --git a/editor/field_ports.ts b/editor/field_ports.ts index ff6a51b9..53778ecf 100644 --- a/editor/field_ports.ts +++ b/editor/field_ports.ts @@ -1,4 +1,5 @@ /// +/// /// export interface FieldPortsOptions extends Blockly.FieldCustomDropdownOptions { @@ -6,146 +7,31 @@ export interface FieldPortsOptions extends Blockly.FieldCustomDropdownOptions { width?: string; } -export class FieldPorts extends Blockly.FieldDropdown implements Blockly.FieldCustom { +export class FieldPorts extends pxtblockly.FieldImages implements Blockly.FieldCustom { public isFieldCustom_ = true; - // Width in pixels - private width_: number; - - // Columns in grid - private columns_: number; - - private savedPrimary_: string; - constructor(text: string, options: FieldPortsOptions, validator?: Function) { - super(options.data); + super(text, options, validator); this.columns_ = parseInt(options.columns) || 4; this.width_ = parseInt(options.width) || 300; + + this.setText = Blockly.FieldDropdown.prototype.setText; + this.updateWidth = (Blockly.Field as any).prototype.updateWidth; + this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_; } trimOptions_() { } - /** - * Create a dropdown menu under the text. - * @private - */ - public showEditor_() { - // If there is an existing drop-down we own, this is a request to hide the drop-down. - if (Blockly.DropDownDiv.hideIfOwner(this)) { - return; - } - // If there is an existing drop-down someone else owns, hide it immediately and clear it. - Blockly.DropDownDiv.hideWithoutAnimation(); - Blockly.DropDownDiv.clearContent(); - // Populate the drop-down with the icons for this field. - let dropdownDiv = Blockly.DropDownDiv.getContentDiv(); - let contentDiv = document.createElement('div'); - // Accessibility properties - contentDiv.setAttribute('role', 'menu'); - contentDiv.setAttribute('aria-haspopup', 'true'); - let options = this.getOptions(); - options = options.sort(); - for (let i = 0, option: any; option = options[i]; i++) { - let content = (options[i] as any)[0]; // Human-readable text or image. - const value = (options[i] as any)[1]; // Language-neutral value. - // Icons with the type property placeholder take up space but don't have any functionality - // Use for special-case layouts - if (content.type == 'placeholder') { - let placeholder = document.createElement('span'); - placeholder.setAttribute('class', 'blocklyDropDownPlaceholder'); - placeholder.style.width = content.width + 'px'; - placeholder.style.height = content.height + 'px'; - contentDiv.appendChild(placeholder); - continue; - } - let button = document.createElement('button'); - button.setAttribute('id', ':' + i); // For aria-activedescendant - button.setAttribute('role', 'menuitem'); - button.setAttribute('class', 'blocklyDropDownButton'); - button.title = content.alt; - if (this.columns_) { - button.style.width = ((this.width_ / this.columns_) - 8) + 'px'; - button.style.height = ((this.width_ / this.columns_) - 8) + 'px'; - } else { - button.style.width = content.width + 'px'; - button.style.height = content.height + 'px'; - } - let backgroundColor = this.sourceBlock_.getColour(); - if (value == this.getValue()) { - // This icon is selected, show it in a different colour - backgroundColor = this.sourceBlock_.getColourTertiary(); - button.setAttribute('aria-selected', 'true'); - } - button.style.backgroundColor = backgroundColor; - button.style.borderColor = this.sourceBlock_.getColourTertiary(); - Blockly.bindEvent_(button, 'click', this, this.buttonClick_); - Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_); - // These are applied manually instead of using the :hover pseudoclass - // because Android has a bad long press "helper" menu and green highlight - // that we must prevent with ontouchstart preventDefault - Blockly.bindEvent_(button, 'mousedown', button, function (e) { - this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); - e.preventDefault(); - }); - Blockly.bindEvent_(button, 'mouseover', button, function () { - this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover'); - contentDiv.setAttribute('aria-activedescendant', this.id); - }); - Blockly.bindEvent_(button, 'mouseout', button, function () { - this.setAttribute('class', 'blocklyDropDownButton'); - contentDiv.removeAttribute('aria-activedescendant'); - }); - let buttonImg = document.createElement('img'); - buttonImg.src = content.src; - //buttonImg.alt = icon.alt; - // Upon click/touch, we will be able to get the clicked element as e.target - // Store a data attribute on all possible click targets so we can match it to the icon. - button.setAttribute('data-value', value); - buttonImg.setAttribute('data-value', value); - button.appendChild(buttonImg); - contentDiv.appendChild(button); - } - contentDiv.style.width = this.width_ + 'px'; - dropdownDiv.appendChild(contentDiv); - - Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary()); - - // Calculate positioning based on the field position. - var scale = this.sourceBlock_.workspace.scale; - var bBox = { width: this.size_.width, height: this.size_.height }; - bBox.width *= scale; - bBox.height *= scale; - var position = this.fieldGroup_.getBoundingClientRect(); - var primaryX = position.left + bBox.width / 2; - var primaryY = position.top + bBox.height; - var secondaryX = primaryX; - var secondaryY = position.top; - // Set bounds to workspace; show the drop-down. - (Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); - (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, - this.onHide_.bind(this)); + getOptions() { + const options = super.getOptions(); + return options ? options.sort() : undefined; } - /** - * Callback for when a button is clicked inside the drop-down. - * Should be bound to the FieldIconMenu. - * @param {Event} e DOM event for the click/touch - * @private - */ - private buttonClick_ = function (e: any) { + protected buttonClick_ = function (e: any) { let value = e.target.getAttribute('data-value'); this.setValue(value); Blockly.DropDownDiv.hide(); }; - - /** - * Callback for when the drop-down is hidden. - */ - private onHide_ = function () { - Blockly.DropDownDiv.content_.removeAttribute('role'); - Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup'); - Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant'); - }; } \ No newline at end of file diff --git a/legoresources/SVGassets/Large Motor.svg b/legoresources/SVGassets/Large Motor.svg index ee3d43a7..351e4e41 100644 --- a/legoresources/SVGassets/Large Motor.svg +++ b/legoresources/SVGassets/Large Motor.svg @@ -13,7 +13,7 @@ sodipodi:docname="Large Motor.svg" width="153.634" height="153.634" - inkscape:version="0.92.1 r15371" + inkscape:version="0.91 r13725" inkscape:export-filename="C:\gh\pxt-ev3\libs\core\jres\icons\motorLarge-icon.png" inkscape:export-xdpi="74.983398" inkscape:export-ydpi="74.983398"> @@ -25,7 +25,7 @@ image/svg+xml - + @@ -38,15 +38,15 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1600" - inkscape:window-height="837" + inkscape:window-width="2560" + inkscape:window-height="1395" id="namedview7026" showgrid="false" - inkscape:zoom="1.5361183" - inkscape:cx="39.260502" - inkscape:cy="76.817001" - inkscape:window-x="-8" - inkscape:window-y="-8" + inkscape:zoom="3.0722366" + inkscape:cx="-73.361033" + inkscape:cy="76.817002" + inkscape:window-x="0" + inkscape:window-y="1" inkscape:window-maximized="1" inkscape:current-layer="svg7024" /> + transform="matrix(-1,0,0,-1,3003.735,6879.9214)"> + transform="translate(-1.623,0)"> @@ -358,8 +358,8 @@ id="Path_36" data-name="Path 36" class="cls-1" - d="m 0.607,0 h 26.262 a 0.607,0.607 0 0 1 0.607,0.607 V 5.9 A 0.607,0.607 0 0 1 26.869,6.507 H 0.607 A 0.607,0.607 0 0 1 0,5.9 V 0.607 A 0.607,0.607 0 0 1 0.607,0 Z" - transform="translate(41.1)" + d="m 0.607,0 26.262,0 a 0.607,0.607 0 0 1 0.607,0.607 l 0,5.293 a 0.607,0.607 0 0 1 -0.607,0.607 l -26.262,0 A 0.607,0.607 0 0 1 0,5.9 L 0,0.607 A 0.607,0.607 0 0 1 0.607,0 Z" + transform="translate(41.1,0)" inkscape:connector-curvature="0" style="fill:#a8a9a8" /> @@ -380,7 +380,7 @@ id="Path_2-2" data-name="Path 2" class="cls-3" - d="m 5610.158,939.234 a 4.151,4.151 0 0 1 -2.342,0.705 5.131,5.131 0 0 1 -2.988,-0.705 c -1.257,-0.931 -1.229,0.1 -1.229,0.1 v 1.8 c 0,0.45 0.553,0.846 1.229,0.459 0.676,-0.387 1,-0.581 1,-0.581 0,0 0.361,-0.184 0.361,0.335 v 2.62 c 0,0 0.021,0.786 -0.73,0.768 -0.751,-0.018 -1.38,0 -1.38,0 0,0 -0.293,0.248 -0.293,1.385 0,1.137 0.293,1.322 0.293,1.322 h 1.38 c 0,0 0.73,-0.024 0.73,0.649 v 1.3 c 0,0 0.227,0.359 1.169,0.306 a 3.6,3.6 0 0 0 1.4,-0.306 v -1.3 a 0.67,0.67 0 0 1 0.66,-0.649 c 0.631,-0.01 1.257,0 1.257,0 0,0 0.252,-0.191 0.287,-1.322 0.035,-1.131 -0.287,-1.385 -0.287,-1.385 h -1.257 c 0,0 -0.805,-0.052 -0.817,-0.768 -0.012,-0.716 0,-2.62 0,-2.62 0,0 -0.047,-0.515 0.332,-0.335 0.379,0.18 1.215,0.581 1.215,0.581 0,0 0.83,0.407 0.814,-0.459 -0.016,-0.866 0,-1.8 0,-1.8 0,0 -0.072,-0.534 -0.804,-0.1 z" + d="m 5610.158,939.234 a 4.151,4.151 0 0 1 -2.342,0.705 5.131,5.131 0 0 1 -2.988,-0.705 c -1.257,-0.931 -1.229,0.1 -1.229,0.1 l 0,1.8 c 0,0.45 0.553,0.846 1.229,0.459 0.676,-0.387 1,-0.581 1,-0.581 0,0 0.361,-0.184 0.361,0.335 l 0,2.62 c 0,0 0.021,0.786 -0.73,0.768 -0.751,-0.018 -1.38,0 -1.38,0 0,0 -0.293,0.248 -0.293,1.385 0,1.137 0.293,1.322 0.293,1.322 l 1.38,0 c 0,0 0.73,-0.024 0.73,0.649 l 0,1.3 c 0,0 0.227,0.359 1.169,0.306 a 3.6,3.6 0 0 0 1.4,-0.306 l 0,-1.3 a 0.67,0.67 0 0 1 0.66,-0.649 c 0.631,-0.01 1.257,0 1.257,0 0,0 0.252,-0.191 0.287,-1.322 0.035,-1.131 -0.287,-1.385 -0.287,-1.385 l -1.257,0 c 0,0 -0.805,-0.052 -0.817,-0.768 -0.012,-0.716 0,-2.62 0,-2.62 0,0 -0.047,-0.515 0.332,-0.335 0.379,0.18 1.215,0.581 1.215,0.581 0,0 0.83,0.407 0.814,-0.459 -0.016,-0.866 0,-1.8 0,-1.8 0,0 -0.072,-0.534 -0.804,-0.1 z" transform="translate(-5553.893,-845.301)" inkscape:connector-curvature="0" style="fill:#ffffff" /> @@ -388,7 +388,7 @@ id="Path_3" data-name="Path 3" class="cls-3" - d="m 5601.9,1015.336 a 0.83,0.83 0 0 1 1.2,-0.594 6.516,6.516 0 0 0 2.85,0.772 5.05,5.05 0 0 0 2.768,-0.772 c 0.829,-0.4 1.067,0.594 1.067,0.594 v 1.76 a 0.71,0.71 0 0 1 -1.067,0.561 5.791,5.791 0 0 0 -2.768,-0.837 7.06,7.06 0 0 0 -2.85,0.837 c 0,0 -1.178,0.239 -1.2,-0.561 -0.022,-0.8 0,-1.76 0,-1.76 z" + d="m 5601.9,1015.336 a 0.83,0.83 0 0 1 1.2,-0.594 6.516,6.516 0 0 0 2.85,0.772 5.05,5.05 0 0 0 2.768,-0.772 c 0.829,-0.4 1.067,0.594 1.067,0.594 l 0,1.76 a 0.71,0.71 0 0 1 -1.067,0.561 5.791,5.791 0 0 0 -2.768,-0.837 7.06,7.06 0 0 0 -2.85,0.837 c 0,0 -1.178,0.239 -1.2,-0.561 -0.022,-0.8 0,-1.76 0,-1.76 z" transform="translate(-5552.485,-909.604)" inkscape:connector-curvature="0" style="fill:#ffffff" /> @@ -415,7 +415,7 @@ id="Path_2-3" data-name="Path 2" class="cls-1" - d="m 1484.037,521.285 v 17.253 c 0,0 0.019,0.845 0.3,1.121 0.281,0.276 3.516,3.626 3.516,3.626 a 1.566,1.566 0 0 0 1.157,0.4 c 0.758,-0.025 11.627,0 11.627,0 l 4.429,-4.7 v -7.963 l -10.662,-0.567 z" + d="m 1484.037,521.285 0,17.253 c 0,0 0.019,0.845 0.3,1.121 0.281,0.276 3.516,3.626 3.516,3.626 a 1.566,1.566 0 0 0 1.157,0.4 c 0.758,-0.025 11.627,0 11.627,0 l 4.429,-4.7 0,-7.963 -10.662,-0.567 z" transform="translate(676.31,5680.52)" inkscape:connector-curvature="0" style="fill:#a8a9a8" /> @@ -428,7 +428,7 @@ id="Path_44" data-name="Path 44" class="cls-1" - d="m 5.461,0 h 5.612 a 5.461,5.461 0 0 1 5.461,5.461 v 22.9 a 5.461,5.461 0 0 1 -5.461,5.461 H 5.461 A 5.461,5.461 0 0 1 0,28.365 V 5.461 A 5.461,5.461 0 0 1 5.461,0 Z" + d="m 5.461,0 5.612,0 a 5.461,5.461 0 0 1 5.461,5.461 l 0,22.9 a 5.461,5.461 0 0 1 -5.461,5.461 l -5.612,0 A 5.461,5.461 0 0 1 0,28.365 L 0,5.461 A 5.461,5.461 0 0 1 5.461,0 Z" inkscape:connector-curvature="0" style="fill:#a8a9a8" /> @@ -461,7 +461,7 @@ id="Path_6" data-name="Path 6" class="cls-3" - d="m 5601.9,1015.336 a 0.83,0.83 0 0 1 1.2,-0.594 6.516,6.516 0 0 0 2.85,0.772 5.05,5.05 0 0 0 2.768,-0.772 c 0.829,-0.4 1.067,0.594 1.067,0.594 v 1.76 a 0.71,0.71 0 0 1 -1.067,0.561 5.791,5.791 0 0 0 -2.768,-0.837 7.06,7.06 0 0 0 -2.85,0.837 c 0,0 -1.178,0.239 -1.2,-0.561 -0.022,-0.8 0,-1.76 0,-1.76 z" + d="m 5601.9,1015.336 a 0.83,0.83 0 0 1 1.2,-0.594 6.516,6.516 0 0 0 2.85,0.772 5.05,5.05 0 0 0 2.768,-0.772 c 0.829,-0.4 1.067,0.594 1.067,0.594 l 0,1.76 a 0.71,0.71 0 0 1 -1.067,0.561 5.791,5.791 0 0 0 -2.768,-0.837 7.06,7.06 0 0 0 -2.85,0.837 c 0,0 -1.178,0.239 -1.2,-0.561 -0.022,-0.8 0,-1.76 0,-1.76 z" transform="translate(-5600.979,-993.616)" inkscape:connector-curvature="0" style="fill:#ffffff" /> @@ -475,7 +475,7 @@ id="Path_1-4" data-name="Path 1" class="cls-1" - d="m 5.784,0 h 42.66 a 5.784,5.784 0 0 1 5.784,5.784 v 29.64 C 43.86,49.487 36.1,59.29 36.1,59.29 h -0.595 c 0,0 -19.462,-0.147 -23.864,-0.147 A 2.28,2.28 0 0 1 9.263,58.158 L 0,48.582 V 5.784 A 5.784,5.784 0 0 1 5.784,0 Z" + d="m 5.784,0 42.66,0 a 5.784,5.784 0 0 1 5.784,5.784 l 0,29.64 C 43.86,49.487 36.1,59.29 36.1,59.29 l -0.595,0 c 0,0 -19.462,-0.147 -23.864,-0.147 A 2.28,2.28 0 0 1 9.263,58.158 L 0,48.582 0,5.784 A 5.784,5.784 0 0 1 5.784,0 Z" transform="translate(2159.6,6153.16)" inkscape:connector-curvature="0" style="fill:#a8a9a8" /> @@ -492,7 +492,7 @@ id="hvid-2" data-name="hvid" class="cls-5" - d="m 1498.578,449.051 7.155,7.37 23.789,31.08 v 14.857 l 13.063,-16.131 v -31.221 l -0.993,-7.691 z" + d="m 1498.578,449.051 7.155,7.37 23.789,31.08 0,14.857 13.063,-16.131 0,-31.221 -0.993,-7.691 z" transform="translate(-1487.315,-449.455)" inkscape:connector-curvature="0" style="fill:#f2f2f2" /> @@ -507,7 +507,7 @@ id="Path_4-2" data-name="Path 4" class="cls-1" - d="M 5.784,0 H 36.875 A 5.784,5.784 0 0 1 42.66,5.784 V 28.032 C 34.013,39.3 27.1,48.444 27.1,48.444 H 5.784 A 5.784,5.784 0 0 1 0,42.66 V 5.784 A 5.784,5.784 0 0 1 5.784,0 Z" + d="m 5.784,0 31.091,0 a 5.784,5.784 0 0 1 5.785,5.784 l 0,22.248 C 34.013,39.3 27.1,48.444 27.1,48.444 l -21.316,0 A 5.784,5.784 0 0 1 0,42.66 L 0,5.784 A 5.784,5.784 0 0 1 5.784,0 Z" transform="translate(2165.38,6158.22)" inkscape:connector-curvature="0" style="fill:#a8a9a8" /> @@ -525,7 +525,7 @@ id="Union_1" data-name="Union 1" class="cls-7" - d="M 14.461,28.56 V 1.085 a 1.085,1.085 0 1 1 2.169,0 V 28.56 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 V 1.085 a 1.085,1.085 0 1 1 2.169,0 V 28.56 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 V 1.085 a 1.085,1.085 0 1 1 2.169,0 V 28.56 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 V 1.085 a 1.085,1.085 0 1 1 2.169,0 V 28.56 a 1.085,1.085 0 1 1 -2.169,0 z M 0,28.56 V 1.085 a 1.085,1.085 0 1 1 2.169,0 V 28.56 A 1.085,1.085 0 1 1 0,28.56 Z" + d="m 14.461,28.56 0,-27.475 a 1.085,1.085 0 1 1 2.169,0 l 0,27.475 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 0,-27.475 a 1.085,1.085 0 1 1 2.169,0 l 0,27.475 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 0,-27.475 a 1.085,1.085 0 1 1 2.169,0 l 0,27.475 a 1.085,1.085 0 1 1 -2.169,0 z m -3.615,0 0,-27.475 a 1.085,1.085 0 1 1 2.169,0 l 0,27.475 a 1.085,1.085 0 1 1 -2.169,0 z M 0,28.56 0,1.085 a 1.085,1.085 0 1 1 2.169,0 l 0,27.475 A 1.085,1.085 0 1 1 0,28.56 Z" transform="translate(15.907,-5.365)" inkscape:connector-curvature="0" style="fill:#6a6a6a" /> @@ -573,7 +573,7 @@ class="cls-10" cx="3.7920001" cy="3.7920001" - transform="translate(11.528)" + transform="translate(11.528,0)" r="3.7920001" style="fill:#3c3c3c" /> @@ -623,28 +623,361 @@ id="Path_7" data-name="Path 7" class="cls-10" - d="M 0.455,0.155 2.016,0 3.64,0.155 A 0.455,0.455 0 0 1 4.1,0.61 V 2.734 A 0.455,0.455 0 0 1 3.645,3.189 L 2.094,2.979 0.46,3.189 A 0.455,0.455 0 0 1 0,2.734 V 0.61 A 0.455,0.455 0 0 1 0.455,0.155 Z" - transform="rotate(-90,12.71,4.628)" + d="M 0.455,0.155 2.016,0 3.64,0.155 A 0.455,0.455 0 0 1 4.1,0.61 l 0,2.124 A 0.455,0.455 0 0 1 3.645,3.189 L 2.094,2.979 0.46,3.189 A 0.455,0.455 0 0 1 0,2.734 L 0,0.61 A 0.455,0.455 0 0 1 0.455,0.155 Z" + transform="matrix(0,-1,1,0,8.082,17.338)" inkscape:connector-curvature="0" style="fill:#3c3c3c" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legoresources/SVGassets/Large Motors.svg b/legoresources/SVGassets/Large Motors.svg new file mode 100644 index 00000000..93fd9212 --- /dev/null +++ b/legoresources/SVGassets/Large Motors.svg @@ -0,0 +1,983 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legoresources/SVGassets/icn_port.svg b/legoresources/SVGassets/icn_port.svg index 64b2aad2..05ff8074 100644 --- a/legoresources/SVGassets/icn_port.svg +++ b/legoresources/SVGassets/icn_port.svg @@ -13,10 +13,10 @@ sodipodi:docname="icn_port.svg" width="58.928001" height="58.928001" - inkscape:export-filename="C:\gh\pxt-ev3\libs\core\jres\icons\portB.png" - inkscape:export-xdpi="156.39424" - inkscape:export-ydpi="156.39424" - inkscape:version="0.92.1 r15371"> + inkscape:export-filename="/Users/sam/pxt-ev3/libs/core/jres/icons/portCD-icon.png" + inkscape:export-xdpi="146.62" + inkscape:export-ydpi="146.62" + inkscape:version="0.91 r13725"> @@ -25,7 +25,7 @@ image/svg+xml - + @@ -38,15 +38,15 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1600" - inkscape:window-height="837" + inkscape:window-width="2560" + inkscape:window-height="1395" id="namedview6350" showgrid="false" inkscape:zoom="4.0048872" - inkscape:cx="24.98" + inkscape:cx="-18.217222" inkscape:cy="29.464001" - inkscape:window-x="-8" - inkscape:window-y="-8" + inkscape:window-x="0" + inkscape:window-y="1" inkscape:window-maximized="1" inkscape:current-layer="svg6348" /> B + x="1457.2511" + y="6184.4844" + style="font-size:27.5px">CD diff --git a/libs/core/icons.jres b/libs/core/icons.jres index 03a5e0a5..e71a83f9 100644 --- a/libs/core/icons.jres +++ b/libs/core/icons.jres @@ -12,8 +12,11 @@ "motorMedium": { "icon": "data:image/png;base64,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" }, + "dualMotorLarge": { + "icon": "data:image/png;base64,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" + }, "motorLarge": { - "icon": "data:image/png;base64,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" + "icon": "data:image/png;base64,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" }, "touchSensor": { "icon": "data:image/png;base64,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" @@ -43,12 +46,27 @@ "icon": "data:image/png;base64,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" }, "portA": { - "icon": "data:image/png;base64,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" + "icon": "data:image/png;base64,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" }, "portB": { - "icon": "data:image/png;base64,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" + "icon": "data:image/png;base64,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" }, "portC": { - "icon": "data:image/png;base64,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" + "icon": "data:image/png;base64,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" + }, + "portD": { + "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWjAAAFowBCIRjdgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAXySURBVHic7ZxfTFNXHMe/vbf/Sy1l3lqolkQNtA4ETViihL0444x7domPzhk3XWbi3Hx1LzDfZzJ1Pps537Doi75MX4juQTBAbhVjpLUD26b0Smnt3YOmUO5tS+W0J5Tf543fuf39TvKBe+nvnHsMsVhMBcENgfcENjokgDMkgDNG3hNgydOnT5FW0kxzdnd1w2q1Ms25nIYSoLxVkEqlmOZ89+4d03wroVsQZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZ0gAZxqqGVcLYrEYzBZzyXF3sxt2u/2j868rAZFIBNPT0yXHFzILzGs+n35edjwYDG4cAdlcFm8X3vKeBlPoGcAZEsAZEsAZEsAZEsAZEsAZEsAZEsAZEsCZNX0TXlhYwIsXL1jNpSKp+aVNVyOhEWSz2VV9zmqzQhREmMwmOJ1OuFwuSJIEp9NZq6mumjUJyGazeDXzitVcquLWrVuYn59fUw6n0wl/ux/BQBC7Pt2FQCAAQajvTWFd9YJYk0qlMD42jvGxceBvwOVyYX//fhw+fBgej6cuc6BnwDKSySRGQiM4++NZXPnjCvN9pno01F9As7sZZrN+734xswhFUbC4uFgxTz6fx7179zA6OoozP5xBT08P66kWaCgBp78/je7d3WWvyeVyiMfjkGUZsixjcmISsizrXptKpTA0OITj3xzHwYMHazHlxhKwGoxGIyRJgiRJ2LdvHwAgGolieHgY9+/f12xHV1UV1/+8DqvVioGBAebzoWcAAG+rFye+PYHBoUH4/X7NuKqquHb1Gl6+fMm8NglYht/vx8VfLyIQCGjGMpkMrl65ClVl+1IpCViBzWbD+Z/Pw+v1asampqYwOjrKtB4J0MHhcODUd6dgMBg0Y6HbIaa1SEAJAoEA9u7dq4lPTEwgGokyq0MCynDoy0O68UePHjGrQQLK0NXVpbvnZ2x8jFkNElAGQRCwc+dOTfxZ+Bm7GswyNSgdHR2aWDKZZNYnIgEV2LZtm278zZs3TPKTgAo4mhy68UQ8wSQ/CaiAw6EvILOYYZKfBFSg1M7n1bS1VwMJqEAul9ONi4LIJD8JqEA6rX/8TamFn2ohARVQFEU3brPbmOQnARVIJpK68RZ3C5P8JKAC4WdhTUwQBLR8QgLqwtTklCbW1tZGz4B6oCiK7jLkjh07mNUgAWV4+PCh7plxvb29zGqQgBLk83ncHr6tiZvNZuzu2c2sDgkowd07dxGJRDTx/v7+ku2Jj4EE6BAOh3Hjxg1NXBRFHPnqCNNaG25jViVkWcal3y4hk9E22w58cQBbt25lWo8EfCCXyyEUCuHmXzd13zvw+Xw4duwY87obXkAikcCDfx5g5M4IZv+b1b3G5XLh3E/nanKEcUMJiCfiiL2OaeIqVKTTaSiKgnQ6jXg8jrAchizLiEajZXe7bZY248IvF9DW1laTOTeUgMu/X2aar++zPpw8ebKmrzI1lABWbN++HUe/Psr0C1cpSMAHnE4n+vr6MPD5AILBYN3qbjgBoihi06ZN8Hg88Pl88Pv9CAQD8Pv9dX9BD1jHAgaHBqHmV79V3GQ2wWKxrOl0q1qwbgVIksR7CkygVgRnSABnSABnSABn1vQQNhqNcLvdZa8RRVHz7108Hi9qeLW4W2Czvd/mMROZKWoNtLa2QjAIUKFiZmamEG9ubobD/r4vn0gmCvt3TCYTPNLSMQNzc3OF80RFUYR3y9K7X5FoBPl8vvCzw+Goeq3XYrZUdf1K1iTAZrNhT++eqj/3+N/HSCSWNrf6fL7CfzXR19GiZcDOjk4IggBVLRbg3eIt9GcmJycLAqxWKzo7OwvXPXnypCDAZDIVjc3OzRa1ndvb24sE1QO6BXGGBHCGBHCGBHCGBHCGBHCGBHCGBHCGBHCGBHCGy4KM3W4vajcYjUvTaGpqKurPLGf57oTlPRuL1VIYW7niZbPZCmMr+zYWiwWCYel3UBTZvHhXDYZYLMb2CCiiKugWxBkSwBkSwBkSwBkSwBkSwBkSwJn/AZFGpFU1+FqzAAAAAElFTkSuQmCC" + }, + "portAB": { + "icon": "data:image/png;base64,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" + }, + "portBC": { + "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWjAAAFowBCIRjdgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAlSSURBVHic7Zx7TFRXHse/d+5chnmADO/HiERFB7EiuOAjNYpWq6irraFrW5OKXdP9p2w3sck22f7jdt11k61ma7fZZiXGBJI1itFaaVjNGo1Vl4JEFDCioCIjDMMwM8IAA3P3D+PIYWYYmLkz51rP5797XvOb+cy999zzuFxPT48IBjUUtAN41WECKMMEUEZJOwApaW5uxsDggKRtvrbwNURHR0va5nh+VgIGnYNwOByStjk2NiZpexNhlyDKMAGUYQIowwRQhgmgDBNAGSaAMkwAZZgAyjABlGECKMMEUOZnNRgXDnp6ehClivKbr4/TQ6PRBN3+SyXAZDKho6PDb/7Q8JDkn9ne0T5pfk5OzqsjwDXqgnPISTsMSWH3AMowAZRhAijDBFCGCaAME0AZJoAyTABlmADKhPQkPDQ0hAcPHkgVS0AcT6VddCUHQhLgcrnwuOuxVLG8krBLEGWYAMowAZSRfDhaFEVcv359yuUFpYBodTRiYmKQlpYGQRCkDsnD/fv30dLcgo6ODtjtdthsNjgcDiiVSmi1WsTGxiIrKwvZ87JhNBqh1WrDFstzJBfgdrtx6OChoOryPI+MjAwsXboUq1atQmJSYsjxOJ1OXLhwAbW1tejp7glYvrGxEQAgCAKWLFmC4jXFWLRoETiOCzkWX3ChbNJzOByo+6mOSBsbG8P7770fcmCCIGDLL7dg+/bt4Hk+qDauXbuGo0ePot/aH1IsRqMRu8p2ISsryysvJycHaalpQbct23uAy+VC9clqHDp4CKOjo9Oq63a7UVFRgUMHD/n98TUaDdIz0mE0GmE0GpGeng61Wu2zbGtrKz77/WdTOoOmS0SmJNevX48FuQv85tvtdjx69AgN9Q2wWCxEXl1dHU6dOoXS0tIpfZYoivj68Ne4cuWKV158QjzWr1uPvMV5yMrK8nlZefjwIRoaGnDt6jVi/lkUxWn/EaZCRATMnjMby5YtC1iurKwMNedqUFlZCbfb7Uk/c/oMNmzYgJiYmIBtVFZWev34PM+jtLQUJZtKEBXlf4UDAGRmZiIzMxNbt25FXV0djv/7ODo7OwN+brDI6hKkUCiwafMmvPOrd4h0l8uF+vr6gPVv3ryJ789+T6SpVCrs/XQvtr21LeCPPx6O41BUVIQDfz2AzVs2h+0mLCsBzykp8f6ndrR3TFpnbGwMR/51BKJI9inKy8uRn58fdCw8z2Pnzp0o/205hCjpu8iyFBAVFQWDwUCk2Wy2SetcvHgR3d3dRFpxcTGW/GKJJDEtX74cSUlJkrQ1HlkKAJ5dOsYTqCt6/j/niWNBEPDue+9KHpfUyFaAuddMHCckJvgt+8T0BO3t5Aq2oqIixMbGhiU2KZGlgLa2NvSae4m0+fPn+y3//Ol1PK+vfF3yuMKB7AQ8ffoU3/7zWyItMTEReXl5fuu0tbURxxzHYe7cuWGJT2pkszbUbDaj/qd6nD59Glar1ZPO8zz27Nkz6T3g8WNyUig5OXlKzwxyICICqiqrUF1d7TNPdIuw2+0YHh72youNjcVHv/kIeYv9//sBeL0fIiUlJfhgI0xEBNjtdtjt9imXNxgMKNlUghUrVkzpTSUDA+QbUkJZLh5pZHcPAIDOzk6cPHEStbW1Ps+M8YyOjsLpJJesv0wCInIGGAwG6PV6n3lu0Q3noBN9fX3o738xcmmxWFBVWYWL/72IT373CTIzM33Wn/jkCyBswwbhICICNm/ZjNWrVwcs12vuxaVLl3DmzBkMDT3b7dLV1YUv/vgF9u3bh9S0VK86giBApVIRZ8rg4KBksYcbWV2CEpMS8fb2t7H/z/sxY8YMT7rdbsfhw4eJEdLx6HQ64pgJCJH09HR8+OsPibS2tjbcaLjhs/zELqfZbPZZTo7IUgAAFBYWEmcBAFy+fNln2fT0dOLYZDJ59YzkimwFcByHOXPmEGl37971WXZiOVEUce/evbDFJiWyFQDAazCtv7/fZ6/H14OarylJOSJrAcMj5DOA2+32eSM2GAyYOXMmkXb1x6svxWVI1gJMXSbiWKfT+R0TWrduHXE8MjKCEydOhC02qZCtALPZ7LX0feLNdjzFa4qRkEDOGfxQ8wNu374tSTyNjY1eKzakQJYCRFHEsWPHvK73BQUFfusIgoBdZbu82vnyb1+itbU1pFiqT1bjwF8OYHho8mGRYJCdAIfDga/+/hXq/keuuFOr1Vi1etWkdQsLC7H2jbVE2sDAAPb/aT9qa2un/RbcW7du4fM/fI7jx4/7vPlLQUSGIjo7O9HU1OQzz+VywTnohMViwd22u2i80QiXy+VVbseOHYiLiwv4Wbt374al10LMko2MjKDiSAVqztVg48aNWJS3CKmp3sMawLPhkIYbDbj641W0tLRM8RsGT0QEnP3uLM5+dzbo+tve2oY3N7w5pbI8z2Pvp3vxzT++8eqKmkwmVFRUAAD0ej0SEhIQExsDDhxsNhusViv6+vp8tstxHHhlcGtUJ0M2M2K+iI+PR1lZGQqLCqdVT6lU4uPyj7FgwQJUVVX57I5arVZi5m0y5s2bhw92fRCWiR7ZCdBqtcjOzsbKlStRtLQopP0Ca99Yi6KlRag5V4Pz589Pa1JIoVAgPz8fa9auQUFBwcuzPH26GzSAZ2uANBoN9HF6JKckBxvOpLjdbrQ0t6C5pRkd7R3o7u6GzWbD6OgolEoldDodYmJiMHv2bGRnZyM3Nxdx+sD3nFCXp0t+BnAcN6WFuJFGoVAgd2Euchfm0g6FQHbd0FcNJoAyTABlmADKMAGUCakXpFQq/S43eQ7P81AoSM9Wq5UYbojXx3s2yHWZuohxl7S0NCg4BUSI6Orq8qTHxcVBq3m2j7ff1u952BIEAclJL7qyFovF8z5RnueRmvJiCML0xETML2i12mntogEAVZQqcKFJCEmAWq1G/uLp7z5puNFArAHKyMjwbH540v2EGDSbP28+FAoFRJEUkJqS6hmevnPnjkdAdHQ0sZK6qanJI0AQBCKv19JLLGeZNWsWISgSsEsQZZgAyjABlGECKMMEUIYJoAwTQBkmgDJMAGWYAMpQmRPWaDTEcINS+SIMnU7ndyPG+H0A48dsVNEqT97E/WFqtdqTN3HcRqVSQcG9+A8G+2auUAhpTpgROuwSRBkmgDJMAGWYAMowAZRhAijDBFDm/6pe/z5SveP9AAAAAElFTkSuQmCC" + }, + "portCD": { + "icon": "data:image/png;base64,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" + }, + "portAD": { + "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWjAAAFowBCIRjdgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAjxSURBVHic7Z1PUFNJHse/ySPmH4GA/EkEBaUUAjtFUBQwhK1ZXN0qZ28zt5nDeJg9ju7srMNhttapnapN7eyUd0960/KyzsEqa0efEP8jCFgqCBkFJU5WDCQQAiG8PVg+6fcIJqTzehz7c6J/3fn1D74v/bp/3e+hC4VCEjjM0LMO4F2HC8AYLgBj8lgHQJN79+5hLjZH1ed7v3kPJpOJqs+V/KoEiM3HEI1GqfpMJpNU/SnhQxBjuACM4QIwhgvAGC4AY7gAjOECMIYLwBguAGO4AIzhAjCGC8CYX1UyLheEQiFsMG5IWV9kL4LFYlm3/7dKgGAwiEePHqWsjy/Eqff506Of1qx3uVzvjgCJpQTm4/Osw6AKvwcwhgvAGC4AY7gAjOECMIYLwBguAGO4AIzhAjAmq5VwPB7H48ePacXyRqKzdA9d/RLISoBEIoGnk09pxfJOwocgxnABGMMFYAyTdPTw8DDC4TBh27p1K8rLy7PyOz4+jsnJyTXb6HQ6WCwWWK1WmM1mmE1mFBQWQK9ncy1qLsDS0hK++9d3qmPkbW1t+Pzw51n59vv9OPefcxl/zmAwwOFwoKamBq56F3bu3AmbzZZVLOmiuQC3e2+veoa/t7cXs7OzyM/P1zokJBIJTExMYGJiAqIoQhAENDY24oM/foD6+vqc9q35904UxVXtiUQCV69c1TaYFCSTSfT19eGbY9/A5/Ph+f+e56wvTb8B4XAYAwMDKetFUcT+A/up9VdYWIhPD326al0sFkMsFkNkJoLR0VEEAgHE4+o95f6+fnQ97MLhI4fR0NBALbZXaCpAT3cPlpeX5bLb7cbw8DDm51/u8wYCAYyPj2PLli1U+jOZTGhtbU2r7fLyMgYHB3H+/HkMDgxCkl4/Ph2NRuH7pw9fdX1FfUjSdAhSDj/7fr8PrW3kH0i8RLbRCr1eD7fbja6uLnz9t69RVFRE1C8uLuL48eOq2VvW/VL1tgYjIyPEFNFms6GpqQkdHR1EO7/fj6WlJa3CWpX6+nr4fD5UVlYS9shMBKdOnaLal2YCKK9sj8cDQRBQV1eHsrIy2R6JRNDf169VWCkpKCzAF3/5QnXm5/q161QTkJoIsLCwgGvXrhE2b4cXwMuF0aufX5FqpqQ1TqcTH370IWGTJAkXLlyg1ocmAty4cUO+0QJARUUFampq5LLX64VOp5PLd+7cwXR4WovQ3khnZ6dqbXLr5i1iMpENmgigHH6U477D4cCOHTvkcjKZhN/v1yK0N2I0GtHW1kbYIpHImkckMyHnAoRCIdy/f18u63Q6tHvbVe2Uw9DFixdzHVra1NbVqmyBQICK75wLIIoiMaduaGjAxo0bVe3a2tpgMBjk8uTkJEZHR3MdXlps375dZZt8unbSL11yKoAkSeju7iZsHb/tWLWt1WpFc3MzYWO1JlBSWlpK3KMAYGpqiorvnApwd+gukUcxGo3Ys2dPyvbKYejq1atYWFjIWXzpotfrYTabCdvs3Cwd31S8pEA5nWxpaVnz1S+NjY2w2+1yORaLofdWb67Cywir1UqUE4sJKn5zJkAsFkNvL/nHU17hSgRBwN69ewnbL2VNsPI+RpOcCXDFf4UYPoqLi9PKJirvEXfv3s1pOjhd5ubIF0Ft2JD6saVMyJkAyivX2+FNa9uvurqayIaudiPXmuXlZVWqmtaOWU4EeDLxBGNjY4TN27728LMS5UJNvCzmbAhIh1AopOq/qLgoRevMyMl+gPLqFwQBJ0+eTPvzsViMKId+frmYy/X2YCoejjxU2SoqKqj4pi5AMplET0+PyjY0NJSVX/GSyEyA4eFhlW1lLisbqA9B/f39mJmZoe1WldDTivn5eVUmt6CwAFVVVVT8U/8GKFevBoNh3TOGeDwuv7VwYWEB169dx/u/ez/bEDPi0sVLqhlQS0uLamW8XqgKEJmJoL+f3Ez57E+fwetN/wa8khMnTuDH//4ol0VR1FSAYDCIs2fPEjadTof9++kdHKA6BPX09BDv2TQajdi9e/e6/Xk8HqI8MjKCYDC4bn+ZEI1G8f2/v1dNCDweDzZv3kytH6oCKGc/zc3NWb111uVyEZlTSZJwWby8bn/p8uDBAxw9ehQTExOE3W634+NPPqbaFzUBxsbGVAHv9exN0To9dDqdykd3dze13aiVSJKEgYEB+Hw+HPv7MbyYekHUG41GHD5ymMhV0YDaPUB59dtsNjQ2Nmbt1+Px4IdzP8jlFy9eYHBwEG63+42fXVxcXHX6G4/HEZuLYS42h+npaYyNjiEQCKScZdlsNhz58xHU1dWt/xdJARUBVjtW2Nrairy87N1XV1ejsrIST548kW3iJTEtAcLhML79x7dZ9b+reRcOHTq06iYSDagIcPPmTdVUzdPuSdE6czweD06fPi2Xb9++ndODvIIgwN3kxsGDB3O++KMigHL4KSkpQW2teh91vXg8Hpw5c0bOxyQSCVzxX8GBPxyg4j8vLw9OpxPbarbB5XJh165db8/xdEmSsG/fPnR2dsq2kpISagsVACgrL8OXf/0Si4uLsq24uFjVrr29Hdu2bXujP7PZDLPZDIvFAovZgkJ7IQRBoBZvJuiy+Sc+0WgUt3pv0YznrcPlcsHpcK778/wZMcZwARjDBWAMF4AxXADGZDUNzcvLUz1JokQQBNVmfDgcRiLx+lxNcVGxfPBpMjhJ7L86nU7odXpIkIgHPOx2O6yWl2d1pmem5YWgwWBAWenr5w2mpqbk94kKggBHuUOuCz4LEnklq9Wa8d6FcYMxo/ZKshLAbDajyd2U8ef6+vswPf36+HlFRQVKS0sBAM9+fkaktGt31EKv10OSSAEc5Q5s2rQJwMstw1cCmEwmYhE4NDQkC2AwGIi651PPiaMzVVVVhEBawIcgxnABGMMFYAwXgDFcAMZwARjDBWAMF4AxXADGcAEYw+SdcRaLhUg3rDw9kZ+fn/Lcz8p92pU5G6PJKNcp3+1gNpvlOmXexmg0Qq97fQ2y2JbMakuSkz18CGIMF4AxXADGcAEYwwVgDBeAMVwAxvwfhhv7WJgwSfcAAAAASUVORK5CYII=" } } \ No newline at end of file diff --git a/libs/core/jres/icons/dualMotorLarge-icon.png b/libs/core/jres/icons/dualMotorLarge-icon.png new file mode 100644 index 00000000..0cd76b09 Binary files /dev/null and b/libs/core/jres/icons/dualMotorLarge-icon.png differ diff --git a/libs/core/jres/icons/motorLarge-icon.png b/libs/core/jres/icons/motorLarge-icon.png index 32bf7796..3ed0fca4 100644 Binary files a/libs/core/jres/icons/motorLarge-icon.png and b/libs/core/jres/icons/motorLarge-icon.png differ diff --git a/libs/core/jres/icons/portA-icon.png b/libs/core/jres/icons/portA-icon.png index c9550307..97887a58 100644 Binary files a/libs/core/jres/icons/portA-icon.png and b/libs/core/jres/icons/portA-icon.png differ diff --git a/libs/core/jres/icons/portAB-icon.png b/libs/core/jres/icons/portAB-icon.png new file mode 100644 index 00000000..d79814e6 Binary files /dev/null and b/libs/core/jres/icons/portAB-icon.png differ diff --git a/libs/core/jres/icons/portAD-icon.png b/libs/core/jres/icons/portAD-icon.png new file mode 100644 index 00000000..59fe830b Binary files /dev/null and b/libs/core/jres/icons/portAD-icon.png differ diff --git a/libs/core/jres/icons/portB-icon.png b/libs/core/jres/icons/portB-icon.png index d5112f5d..f12e7830 100644 Binary files a/libs/core/jres/icons/portB-icon.png and b/libs/core/jres/icons/portB-icon.png differ diff --git a/libs/core/jres/icons/portBC-icon.png b/libs/core/jres/icons/portBC-icon.png new file mode 100644 index 00000000..15b1b5f4 Binary files /dev/null and b/libs/core/jres/icons/portBC-icon.png differ diff --git a/libs/core/jres/icons/portC-icon.png b/libs/core/jres/icons/portC-icon.png index 628b2410..4baa4c41 100644 Binary files a/libs/core/jres/icons/portC-icon.png and b/libs/core/jres/icons/portC-icon.png differ diff --git a/libs/core/jres/icons/portCD-icon.png b/libs/core/jres/icons/portCD-icon.png new file mode 100644 index 00000000..f5b69733 Binary files /dev/null and b/libs/core/jres/icons/portCD-icon.png differ diff --git a/libs/core/jres/icons/portD-icon.png b/libs/core/jres/icons/portD-icon.png index 3122fd14..20b26828 100644 Binary files a/libs/core/jres/icons/portD-icon.png and b/libs/core/jres/icons/portD-icon.png differ diff --git a/libs/core/output.ts b/libs/core/output.ts index 861f959d..4481f05e 100644 --- a/libs/core/output.ts +++ b/libs/core/output.ts @@ -163,6 +163,7 @@ namespace motors { * @param brake a value indicating if the motor should break when off */ //% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff" + //% motor.fieldEditor="motors" //% weight=60 blockGap=8 //% group="Properties" //% help=motors/motor/set-brake @@ -175,6 +176,7 @@ namespace motors { * Inverts the motor polarity */ //% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff" + //% motor.fieldEditor="motors" //% weight=59 blockGap=8 //% group="Properties" //% help=motors/motor/set-inverted @@ -192,6 +194,7 @@ namespace motors { //% group="Move" //% help=motors/motor/stop //% blockId=motorStop block="stop %motors|" + //% motors.fieldEditor="motors" stop() { this.init(); stop(this._port, this._brake); @@ -212,6 +215,7 @@ namespace motors { //% group="Move" //% help=motors/motor/reset //% blockId=motorReset block="reset %motors|" + //% motors.fieldEditor="motors" reset() { this.init(); reset(this._port); @@ -226,6 +230,7 @@ namespace motors { //% blockId=motorRun block="run %motor at %speed=motorSpeedPicker|\\%||for %value %unit" //% weight=100 blockGap=8 //% group="Move" + //% motor.fieldEditor="motors" //% expandableArgumentMode=toggle //% help=motors/motor/run run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) { @@ -287,6 +292,7 @@ namespace motors { * @param timeOut optional maximum pausing time in milliseconds */ //% blockId=motorPauseUntilRead block="pause until %motor|ready" + //% motor.fieldEditor="motors" //% weight=90 //% group="Move" pauseUntilReady(timeOut?: number) { @@ -343,6 +349,7 @@ namespace motors { * @param value true for regulated motor */ //% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff" + //% motor.fieldEditor="motors" //% weight=58 //% group="Properties" //% help=motors/motor/set-regulated @@ -355,6 +362,7 @@ namespace motors { * @param motor the port which connects to the motor */ //% blockId=motorSpeed block="%motor|speed" + //% motor.fieldEditor="motors" //% weight=72 //% blockGap=8 //% group="Counters" @@ -369,6 +377,7 @@ namespace motors { * @param motor the port which connects to the motor */ //% blockId=motorAngle block="%motor|angle" + //% motor.fieldEditor="motors" //% weight=70 //% blockGap=8 //% group="Counters" @@ -382,6 +391,7 @@ namespace motors { * Clears the motor count */ //% blockId=motorClearCount block="clear %motor|counters" + //% motor.fieldEditor="motors" //% weight=68 //% blockGap=8 //% group="Counters" @@ -406,28 +416,28 @@ namespace motors { } } - //% whenUsed fixedInstance block="large motor A" + //% whenUsed fixedInstance block="large motor A" jres=icons.portA export const largeA = new Motor(Output.A, true); - //% whenUsed fixedInstance block="large motor B" + //% whenUsed fixedInstance block="large motor B" jres=icons.portB export const largeB = new Motor(Output.B, true); - //% whenUsed fixedInstance block="large motor C" + //% whenUsed fixedInstance block="large motor C" jres=icons.portC export const largeC = new Motor(Output.C, true); - //% whenUsed fixedInstance block="large motor D" + //% whenUsed fixedInstance block="large motor D" jres=icons.portD export const largeD = new Motor(Output.D, true); - //% whenUsed fixedInstance block="medium motor A" + //% whenUsed fixedInstance block="medium motor A" jres=icons.portA export const mediumA = new Motor(Output.A, false); - //% whenUsed fixedInstance block="medium motor B" + //% whenUsed fixedInstance block="medium motor B" jres=icons.portB export const mediumB = new Motor(Output.B, false); - //% whenUsed fixedInstance block="medium motor C" + //% whenUsed fixedInstance block="medium motor C" jres=icons.portC export const mediumC = new Motor(Output.C, false); - //% whenUsed fixedInstance block="medium motor D" + //% whenUsed fixedInstance block="medium motor D" jres=icons.portD export const mediumD = new Motor(Output.D, false); //% fixedInstances @@ -481,7 +491,8 @@ namespace motors { * @param value (optional) move duration or rotation * @param unit (optional) unit of the value */ - //% blockId=motorPairTank block="tank %motors %speedLeft=motorSpeedPicker|\\% %speedRight=motorSpeedPicker|\\%||for %value %unit" + //% blockId=motorPairTank block="tank **motors** %motors %speedLeft=motorSpeedPicker|\\% %speedRight=motorSpeedPicker|\\%||for %value %unit" + //% motors.fieldEditor="ports" //% weight=96 blockGap=8 //% inlineInputMode=inline //% group="Move" @@ -508,7 +519,8 @@ namespace motors { * @param value (optional) move duration or rotation * @param unit (optional) unit of the value */ - //% blockId=motorPairSteer block="steer %chassis turn ratio %turnRatio=motorTurnRatioPicker speed %speed=motorSpeedPicker|\\%||for %value %unit" + //% blockId=motorPairSteer block="steer **motors** %chassis turn ratio %turnRatio=motorTurnRatioPicker speed %speed=motorSpeedPicker|\\%||for %value %unit" + //% chassis.fieldEditor="ports" //% weight=95 //% turnRatio.min=-200 turnRatio=200 //% inlineInputMode=inline @@ -571,16 +583,16 @@ namespace motors { } } - //% whenUsed fixedInstance block="large motors B+C" + //% whenUsed fixedInstance block="B+C" jres=icons.portBC export const largeBC = new SynchedMotorPair(Output.BC); - //% whenUsed fixedInstance block="large motors A+D" + //% whenUsed fixedInstance block="A+D" jres=icons.portAD export const largeAD = new SynchedMotorPair(Output.AD); - //% whenUsed fixedInstance block="large motors A+B" + //% whenUsed fixedInstance block="A+B" jres=icons.portAB export const largeAB = new SynchedMotorPair(Output.AB); - //% whenUsed fixedInstance block="large motors C+D" + //% whenUsed fixedInstance block="C+D" jres=icons.portCD export const largeCD = new SynchedMotorPair(Output.CD); function reset(out: Output) {