Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ardublockly/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<script src="../blockly/arduino_compressed.js"></script>
<!-- To use the uncompressed version comment out the above and comment in the ones below -->
<!--script src="../blockly/blockly_uncompressed.js"></script>
<script src="../blockly/blocks/component_variable.js"></script>
<script src="../blockly/blocks/logic.js"></script>
<script src="../blockly/blocks/loops.js"></script>
<script src="../blockly/blocks/math.js"></script>
Expand Down
178 changes: 69 additions & 109 deletions blockly/blocks/arduino/stepper.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,64 +28,6 @@ goog.require('Blockly.Types');
/** Common HSV hue for all blocks in this category. */
Blockly.Blocks.stepper.HUE = 80;

/** Strings for easy reference. */
Blockly.Blocks.stepper.noInstance = 'No_Instances';
Blockly.Blocks.stepper.noName = 'Empty_input_name';

/**
* Finds all user-created instances of the Stepper block config.
* @return {!Array.<string>} Array of instance names.
*/
Blockly.Blocks.stepper.stepperInstances = function() {
var stepperList = [];
var blocks = Blockly.mainWorkspace.getTopBlocks();
for (var x = 0; x < blocks.length; x++) {
var getStepperSetupInstance = blocks[x].getStepperSetupInstance;
if (getStepperSetupInstance) {
var stepperInstance = getStepperSetupInstance.call(blocks[x]);
if (stepperInstance) {
stepperList.push(stepperInstance);
}
}
}
return stepperList;
};

/**
* Return a sorted list of instances names for set dropdown menu.
* @return {!Array.<string>} Array of stepper instances names.
*/
Blockly.Blocks.stepper.stepperDropdownList = function() {
var stepperList = Blockly.Blocks.stepper.stepperInstances();
var options = [];
if (stepperList.length > 0) {
stepperList.sort(goog.string.caseInsensitiveCompare);
// Variables are not language-specific, use the name as both the
// user-facing text and the internal representation.
for (var x = 0; x < stepperList.length; x++) {
options[x] = [stepperList[x], stepperList[x]];
}
} else {
// There are no config blocks in the work area
options[0] = [Blockly.Blocks.stepper.noInstance,
Blockly.Blocks.stepper.noInstance];
}
return options;
};

/**
* Class for a variable's dropdown field.
* @extends {Blockly.FieldDropdown}
* @constructor
*/
Blockly.Blocks.stepper.FieldStepperInstance = function() {
Blockly.Blocks.stepper.FieldStepperInstance.superClass_.constructor
.call(this, Blockly.Blocks.stepper.stepperDropdownList);
};
goog.inherits(
Blockly.Blocks.stepper.FieldStepperInstance, Blockly.FieldDropdown);


Blockly.Blocks['stepper_config'] = {
/**
* Block for for the stepper generator configuration including creating
Expand All @@ -97,7 +39,8 @@ Blockly.Blocks['stepper_config'] = {
this.setColour(Blockly.Blocks.stepper.HUE);
this.appendDummyInput()
.appendField(Blockly.Msg.ARD_STEPPER_SETUP)
.appendField(new Blockly.FieldTextInput('MyStepper'), 'STEPPER_NAME')
.appendField(new Blockly.Blocks.ComponentFieldVariable(
Blockly.Msg.ARD_STEPPER_DEFAULT_NAME, 'Stepper'), 'STEPPER_NAME')
.appendField(Blockly.Msg.ARD_STEPPER_MOTOR);
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
Expand All @@ -118,18 +61,41 @@ Blockly.Blocks['stepper_config'] = {
this.setTooltip(Blockly.Msg.ARD_STEPPER_SETUP_TIP);
},
/**
* Returns the stepper instance name, defined in the 'STEPPER_NAME' input
* String block attached to this block.
* @return {!string} List with the instance name.
* Return the name of the component defined in this block
* @return {!<string>} The name of the component
* @this Blockly.Block
*/
getComponentName: function() {
return 'Stepper';
},
/**
* Return all variables referenced by this block.
* @return {!Array.<string>} List of variable names.
* @this Blockly.Block
*/
getStepperSetupInstance: function() {
var InstanceName = this.getFieldValue('STEPPER_NAME');
if (!InstanceName) {
InstanceName = Blockly.Blocks.stepper.noName;
getVars: function() {
return [this.getFieldValue('STEPPER_NAME')];
},
/**
* Notification that a variable is renaming.
* If the name matches one of this block's variables, rename it.
* @param {string} oldName Previous name of variable.
* @param {string} newName Renamed variable.
* @this Blockly.Block
*/
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getFieldValue('STEPPER_NAME'))) {
this.setFieldValue(newName, 'STEPPER_NAME');
}
// Replace all spaces with underscores
return InstanceName.replace(/ /g, '_');
},
/**
* Gets the variable type required.
* @param {!string} varName Name of the variable selected in this block to
* check.
* @return {string} String to indicate the variable type.
*/
getVarType: function(varName) {
return Blockly.Types.ARRAY;
},
/**
* Updates the content of the the pin related fields.
Expand All @@ -153,8 +119,8 @@ Blockly.Blocks['stepper_step'] = {
this.setColour(Blockly.Blocks.stepper.HUE);
this.appendDummyInput()
.appendField(Blockly.Msg.ARD_STEPPER_STEP)
.appendField(new Blockly.Blocks.stepper.FieldStepperInstance(),
'STEPPER_NAME');
.appendField(new Blockly.Blocks.ComponentFieldVariable(
Blockly.Msg.ARD_STEPPER_DEFAULT_NAME, 'Stepper'), 'STEPPER_NAME')
this.appendValueInput('STEPPER_STEPS')
.setCheck(Blockly.Types.NUMBER.checkList);
this.appendDummyInput()
Expand All @@ -163,6 +129,35 @@ Blockly.Blocks['stepper_step'] = {
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.ARD_STEPPER_STEP_TIP);
},
/**
* Return all variables referenced by this block.
* @return {!Array.<string>} List of variable names.
* @this Blockly.Block
*/
getVars: function() {
return [this.getFieldValue('STEPPER_NAME')];
},
/**
* Notification that a variable is renaming.
* If the name matches one of this block's variables, rename it.
* @param {string} oldName Previous name of variable.
* @param {string} newName Renamed variable.
* @this Blockly.Block
*/
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getFieldValue('STEPPER_NAME'))) {
this.setFieldValue(newName, 'STEPPER_NAME');
}
},
/**
* Gets the variable type required.
* @param {!string} varName Name of the variable selected in this block to
* check.
* @return {string} String to indicate the variable type.
*/
getVarType: function(varName) {
return Blockly.Types.ARRAY;
},
/**
* Called whenever anything on the workspace changes.
* It checks the instances of stepper_config and attaches a warning to this
Expand All @@ -173,46 +168,11 @@ Blockly.Blocks['stepper_step'] = {
if (!this.workspace) { return; } // Block has been deleted.

var currentDropdown = this.getFieldValue('STEPPER_NAME');
var instances = Blockly.Blocks.stepper.stepperDropdownList();

// Check for configuration block presence
if (instances[0][0] === Blockly.Blocks.stepper.noInstance) {
// Ensure dropdown menu says there is no config block
if (currentDropdown !== Blockly.Blocks.stepper.noInstance) {
this.setFieldValue(Blockly.Blocks.stepper.noInstance, 'STEPPER_NAME');
}
this.setWarningText(Blockly.Msg.ARD_STEPPER_STEP_WARN1);
if (Blockly.Blocks.ComponentFieldVariable.CheckSetupPresent(this.workspace, currentDropdown, 'Stepper')) {
this.setWarningText(null);
} else {
// Configuration blocks present, check if any selected and contains name
var existingConfigSelected = false;
for (var x = 0; x < instances.length; x++) {
// Check if any of the config blocks does not have a name
if (instances[x][0] === Blockly.Blocks.stepper.noName) {
// If selected config has no name either, set warning and exit func
if (currentDropdown === Blockly.Blocks.stepper.noName) {
this.setWarningText(Blockly.Msg.ARD_STEPPER_STEP_WARN2);
return;
}
} else if (instances[x][0] === currentDropdown) {
existingConfigSelected = true;
}
}

// At this point select config has a name, check if it exist
if (existingConfigSelected) {
// All good, just remove any warnings and exit the function
this.setWarningText(null);
} else {
if ((currentDropdown === Blockly.Blocks.stepper.noName) ||
(currentDropdown === Blockly.Blocks.stepper.noInstance)) {
// Just pick the first config block
this.setFieldValue(instances[0][0], 'STEPPER_NAME');
this.setWarningText(null);
} else {
// Al this point just set a warning to select a valid stepper config
this.setWarningText(Blockly.Msg.ARD_STEPPER_STEP_WARN3);
}
}
// Set a warning to select a valid stepper config
this.setWarningText(Blockly.Msg.ARD_COMPONENT_WARN1.replace('%1', Blockly.Msg.ARD_STEPPER_COMPONENT).replace('%1', Blockly.Msg.ARD_STEPPER_COMPONENT));
}
}
};
166 changes: 166 additions & 0 deletions blockly/blocks/component_variable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/**
* @license
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @fileoverview Variable input field of a specific component type.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';

goog.provide('Blockly.Blocks.ComponentFieldVariable');

goog.require('Blockly.Blocks');


/**
* Class for a variable's dropdown field.
* @param {?string} varname The default name for the variable. If null,
* a unique variable name will be generated.
* @param {?string} component_type The type of component to show in the dropdown list, eg 'Stepper'
* @param {Function=} opt_validator A function that is executed when a new
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

component_type is missing from the doc.

* option is selected. Its sole argument is the new option value.
* @extends {Blockly.FieldVariable}
* @constructor
*/
Blockly.Blocks.ComponentFieldVariable = function(varname, component_type, opt_validator) {
/** @type {string} */
this.component_type = component_type;
Blockly.Blocks.ComponentFieldVariable.superClass_.constructor.call(this,
varname, opt_validator);
this.setValue(varname || '');
};
goog.inherits(Blockly.Blocks.ComponentFieldVariable, Blockly.FieldVariable);

Blockly.Blocks.ComponentFieldVariable.ComponentVariables = function(root, component_type) {
var blocks;
if (root.getDescendants) {
// Root is Block.
blocks = root.getDescendants();
} else if (root.getAllBlocks) {
// Root is Workspace.
blocks = root.getAllBlocks();
} else {
throw 'Not Block or Workspace: ' + root;
}
var variableHash = Object.create(null);
// Iterate through every block and add each variable to the hash.
for (var x = 0; x < blocks.length; x++) {
if (blocks[x].getComponentName && blocks[x].getVars &&
(blocks[x].getComponentName() == component_type)) {
var blockVariables = blocks[x].getVars();
for (var y = 0; y < blockVariables.length; y++) {
var varName = blockVariables[y];
// Variable name may be null if the block is only half-built.
if (varName) {
variableHash[varName.toLowerCase()] = varName;
}
}
}
}
// Flatten the hash into a list.
var variableList = [];
for (var name in variableHash) {
variableList.push(variableHash[name]);
}
return variableList;
};


/**
* Return a sorted list of variable names for variable dropdown menus.
* Include a special option at the end for creating a new variable name.
* @return {!Array.<string>} Array of variable names.
* @this {!ComponentFieldVariable}
*/
Blockly.Blocks.ComponentFieldVariable.prototype.dropdownCreate = function() {
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
var variableList =
Blockly.Blocks.ComponentFieldVariable.ComponentVariables(this.sourceBlock_.workspace,
this.component_type);
} else {
var variableList = [];
}
// Ensure that the currently selected variable is an option.
var name = this.getText();
if (name && variableList.indexOf(name) == -1) {
variableList.push(name);
}
variableList.sort(goog.string.caseInsensitiveCompare);
variableList.push(Blockly.Msg.RENAME_VARIABLE);
variableList.push(Blockly.Msg.NEW_VARIABLE);
// Variables are not language-specific, use the name as both the user-facing
// text and the internal representation.
var options = [];
for (var x = 0; x < variableList.length; x++) {
options[x] = [variableList[x], variableList[x]];
}
return options;
};


/**
* Finds all user-created instances of the ComponentFieldVariable block config.
* @param {!Blockly.Workspace} workspace The block's workspace.
* @param {?string} component_type The type of component setup block to obtain instances from
* @return {!Array.<string>} Array of instance names.
*/
Blockly.Blocks.ComponentFieldVariable.Instances = function(workspace, component_type) {
var instList = [];
var blocks = Blockly.mainWorkspace.getAllBlocks();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blockly.Blocks.ComponentFieldVariable.CheckSetupPresent should be passed an instance of the workspace to pass to this function.

for (var x = 0; x < blocks.length; x++) {
var getSetupInstance = blocks[x].getComponentName;
if (getSetupInstance) {
var Instances = getSetupInstance.call();
if (Instances) {
if (Instances == component_type) {
instList.push(blocks[x].getVars()[0]);
}
}
}
}
return instList;
};

/**
* Check to know of a setup block (which sets pin number) is present for a used
* ComponentFieldVariable.
* @param {!Blockly.Workspace} workspace The block's workspace.
* @param {?string} currentDropdown The selected name in the dropdown for which to check
* if setup block present
* @param {?string} component_type The type of component setup block must be checked
* @return {<boolean>} Wether setup block is present or not
*/
Blockly.Blocks.ComponentFieldVariable.CheckSetupPresent = function(workspace, currentDropdown, component_type) {
var instances = Blockly.Blocks.ComponentFieldVariable.Instances(workspace, component_type);

// Check for configuration block presence
if (! instances) {
return false;
} else {
// Configuration blocks present, check if any selected in this block
var existingConfigSelected = false;
for (var x = 0; x < instances.length; x++) {
if (instances[x] === currentDropdown) {
existingConfigSelected = true;
}
}
return existingConfigSelected;
}
Copy link
Owner

@carlosperate carlosperate May 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion, I quite like the syntax return !!existingConfigSelected;, but taking in consideration existingConfigSelected is already a boolean, you can just return it directly.

}
Loading