mirror of
https://github.com/google/blockly.git
synced 2026-06-17 00:25:14 +02:00
+4
-1
@@ -1,14 +1,17 @@
|
||||
*_compressed*.js
|
||||
*_uncompressed*.js
|
||||
blockly_node_javascript_en.js
|
||||
gulpfile.js
|
||||
/msg/*
|
||||
/core/css.js
|
||||
/tests/blocks/*
|
||||
/tests/compile/*
|
||||
/tests/jsunit/*
|
||||
/tests/generators/*
|
||||
/tests/test_runner.js
|
||||
/tests/workspace_svg/*
|
||||
/generators/*
|
||||
/demos/*
|
||||
/accessible/*
|
||||
/appengine/*
|
||||
/externs/svg-externs.js
|
||||
/externs/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"curly": ["error", "multi-line"],
|
||||
"curly": ["error"],
|
||||
"eol-last": ["error"],
|
||||
"indent": [
|
||||
"error", 2, # Blockly/Google use 2-space indents
|
||||
@@ -50,6 +50,7 @@
|
||||
"quotes": ["off"], # Blockly uses single quotes except for JSON blobs, which must use double quotes.
|
||||
"semi": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "never"], # Blockly doesn't have space before function paren
|
||||
"space-infix-ops": ["error"],
|
||||
"strict": ["off"], # Blockly uses 'use strict' in files
|
||||
"no-cond-assign": ["off"], # Blockly often uses cond-assignment in loops
|
||||
"no-redeclare": ["off"], # Closure style allows redeclarations
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
blockly_node_javascript_en.js
|
||||
node_modules
|
||||
npm-debug.log
|
||||
.DS_Store
|
||||
|
||||
+3
-11
@@ -13,21 +13,13 @@ matrix:
|
||||
node_js: stable
|
||||
osx_image: xcode8.3
|
||||
|
||||
before_install:
|
||||
- npm install google-closure-library
|
||||
- npm install google-closure-compiler
|
||||
- npm install webdriverio
|
||||
# Symlink closure library
|
||||
- ln -s $(npm root)/google-closure-library ../closure-library
|
||||
|
||||
before_script:
|
||||
# Symlink closure library used by test/jsunit
|
||||
- ln -s $(npm root)/google-closure-library ../closure-library
|
||||
- export DISPLAY=:99.0
|
||||
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then ( tests/scripts/setup_linux_env.sh ) fi
|
||||
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then ( tests/scripts/setup_osx_env.sh ) fi
|
||||
- sleep 2
|
||||
|
||||
script:
|
||||
- set -x
|
||||
- npm run lint
|
||||
- npm test
|
||||
- cd tests/compile; compile.sh; cd ..
|
||||
- tests/run_all_tests.sh
|
||||
|
||||
@@ -101,7 +101,7 @@ blocklyApp.BlockConnectionService = ng.core.Class({
|
||||
},
|
||||
attachToMarkedConnection: function(block) {
|
||||
var xml = Blockly.Xml.blockToDom(block);
|
||||
var reconstitutedBlock = Blockly.Xml.domToBlock(blocklyApp.workspace, xml);
|
||||
var reconstitutedBlock = Blockly.Xml.domToBlock(xml, blocklyApp.workspace);
|
||||
|
||||
var targetConnection = null;
|
||||
if (this.markedConnection_.targetBlock() &&
|
||||
|
||||
@@ -182,7 +182,7 @@ blocklyApp.FieldSegmentComponent = ng.core.Component({
|
||||
},
|
||||
// Sets the value on a dropdown input.
|
||||
setDropdownValue: function(optionValue) {
|
||||
this.optionValue = optionValue
|
||||
this.optionValue = optionValue;
|
||||
if (this.optionValue == 'NO_ACTION') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
.blocklySidebarButton[disabled] {
|
||||
border: 1px solid #ccc;
|
||||
opacity: 0.5;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.blocklyAriaLiveStatus {
|
||||
|
||||
@@ -71,7 +71,7 @@ blocklyApp.ToolboxModalService = ng.core.Class({
|
||||
this.allToolboxCategories = Array.from(toolboxCategoryElts).map(
|
||||
function(categoryElt) {
|
||||
var tmpWorkspace = new Blockly.Workspace();
|
||||
var custom = categoryElt.attributes.custom
|
||||
var custom = categoryElt.attributes.custom;
|
||||
// TODO (corydiers): Implement custom flyouts once #1153 is solved.
|
||||
if (custom && custom.value == Blockly.VARIABLE_CATEGORY_NAME) {
|
||||
var varBlocks =
|
||||
@@ -95,7 +95,7 @@ blocklyApp.ToolboxModalService = ng.core.Class({
|
||||
// containing all the top-level blocks.
|
||||
var tmpWorkspace = new Blockly.Workspace();
|
||||
Array.from(toolboxXmlElt.children).forEach(function(topLevelNode) {
|
||||
Blockly.Xml.domToBlock(tmpWorkspace, topLevelNode);
|
||||
Blockly.Xml.domToBlock(topLevelNode, tmpWorkspace);
|
||||
});
|
||||
|
||||
that.allToolboxCategories = [{
|
||||
@@ -214,7 +214,7 @@ blocklyApp.ToolboxModalService = ng.core.Class({
|
||||
this.showModal_(this.toolboxCategoriesForNewGroup, function(block) {
|
||||
var blockDescription = that.utilsService.getBlockDescription(block);
|
||||
var xml = Blockly.Xml.blockToDom(block);
|
||||
var newBlockId = Blockly.Xml.domToBlock(blocklyApp.workspace, xml).id;
|
||||
var newBlockId = Blockly.Xml.domToBlock(xml, blocklyApp.workspace).id;
|
||||
|
||||
// Invoke a digest cycle, so that the DOM settles.
|
||||
setTimeout(function() {
|
||||
|
||||
@@ -71,7 +71,7 @@ blocklyApp.VariableAddModalComponent = ng.core.Component({
|
||||
this.workspace = blocklyApp.workspace;
|
||||
this.variableModalService = variableService;
|
||||
this.audioService = audioService;
|
||||
this.keyboardInputService = keyboardService
|
||||
this.keyboardInputService = keyboardService;
|
||||
this.modalIsVisible = false;
|
||||
this.activeButtonIndex = -1;
|
||||
|
||||
@@ -103,7 +103,7 @@ blocklyApp.VariableAddModalComponent = ng.core.Component({
|
||||
getInteractiveElements: Blockly.CommonModal.getInteractiveElements,
|
||||
// Gets the container with interactive elements.
|
||||
getInteractiveContainer: function() {
|
||||
return document.getElementById("varForm");
|
||||
return document.getElementById('varForm');
|
||||
},
|
||||
// Submits the name change for the variable.
|
||||
submit: function() {
|
||||
|
||||
@@ -74,17 +74,17 @@ blocklyApp.VariableRemoveModalComponent = ng.core.Component({
|
||||
this.treeService = treeService;
|
||||
this.variableModalService = variableService;
|
||||
this.audioService = audioService;
|
||||
this.keyboardInputService = keyboardService
|
||||
this.keyboardInputService = keyboardService;
|
||||
this.modalIsVisible = false;
|
||||
this.activeButtonIndex = -1;
|
||||
this.currentVariableName = "";
|
||||
this.currentVariableName = '';
|
||||
this.count = 0;
|
||||
|
||||
var that = this;
|
||||
this.variableModalService.registerPreRemoveShowHook(
|
||||
function(name, count) {
|
||||
that.currentVariableName = name;
|
||||
that.count = count
|
||||
that.count = count;
|
||||
that.modalIsVisible = true;
|
||||
|
||||
Blockly.CommonModal.setupKeyboardOverrides(that);
|
||||
@@ -106,7 +106,7 @@ blocklyApp.VariableRemoveModalComponent = ng.core.Component({
|
||||
getInteractiveElements: Blockly.CommonModal.getInteractiveElements,
|
||||
// Gets the container with interactive elements.
|
||||
getInteractiveContainer: function() {
|
||||
return document.getElementById("varForm");
|
||||
return document.getElementById('varForm');
|
||||
},
|
||||
getNumVariables: function() {
|
||||
return this.variableModalService.getNumVariables(this.currentVariableName);
|
||||
|
||||
@@ -72,10 +72,10 @@ blocklyApp.VariableRenameModalComponent = ng.core.Component({
|
||||
this.workspace = blocklyApp.workspace;
|
||||
this.variableModalService = variableService;
|
||||
this.audioService = audioService;
|
||||
this.keyboardInputService = keyboardService
|
||||
this.keyboardInputService = keyboardService;
|
||||
this.modalIsVisible = false;
|
||||
this.activeButtonIndex = -1;
|
||||
this.currentVariableName = "";
|
||||
this.currentVariableName = '';
|
||||
|
||||
var that = this;
|
||||
this.variableModalService.registerPreRenameShowHook(
|
||||
@@ -106,7 +106,7 @@ blocklyApp.VariableRenameModalComponent = ng.core.Component({
|
||||
getInteractiveElements: Blockly.CommonModal.getInteractiveElements,
|
||||
// Gets the container with interactive elements.
|
||||
getInteractiveContainer: function() {
|
||||
return document.getElementById("varForm");
|
||||
return document.getElementById('varForm');
|
||||
},
|
||||
// Submits the name change for the variable.
|
||||
submit: function() {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
print("Status: 302")
|
||||
print("Status: 301")
|
||||
print("Location: /static/demos/index.html")
|
||||
print("")
|
||||
|
||||
+26
-24
@@ -22,35 +22,32 @@ limitations under the License.
|
||||
__author__ = "q.neutron@gmail.com (Quynh Neutron)"
|
||||
|
||||
import cgi
|
||||
import hashlib
|
||||
from random import randint
|
||||
from google.appengine.ext import db
|
||||
from google.appengine.api import memcache
|
||||
import logging
|
||||
from google.appengine.ext import ndb
|
||||
|
||||
print "Content-Type: text/plain\n"
|
||||
|
||||
def keyGen():
|
||||
# Generate a random string of length KEY_LEN.
|
||||
KEY_LEN = 6
|
||||
CHARS = "abcdefghijkmnopqrstuvwxyz23456789" # Exclude l, 0, 1.
|
||||
CHARS = "abcdefghijkmnopqrstuvwxyz23456789" # Exclude l, 0, 1.
|
||||
max_index = len(CHARS) - 1
|
||||
return "".join([CHARS[randint(0, max_index)] for x in range(KEY_LEN)])
|
||||
|
||||
class Xml(db.Model):
|
||||
class Xml(ndb.Model):
|
||||
# A row in the database.
|
||||
xml_hash = db.IntegerProperty()
|
||||
xml_content = db.TextProperty()
|
||||
xml_hash = ndb.IntegerProperty()
|
||||
xml_content = ndb.TextProperty()
|
||||
|
||||
forms = cgi.FieldStorage()
|
||||
if "xml" in forms:
|
||||
def xmlToKey(xml_content):
|
||||
# Store XML and return a generated key.
|
||||
xml_content = forms["xml"].value
|
||||
xml_hash = hash(xml_content)
|
||||
lookup_query = db.Query(Xml)
|
||||
lookup_query.filter("xml_hash =", xml_hash)
|
||||
xml_hash = long(hashlib.sha1(xml_content).hexdigest(), 16)
|
||||
xml_hash = int(xml_hash % (2 ** 64) - (2 ** 63))
|
||||
lookup_query = Xml.query(Xml.xml_hash == xml_hash)
|
||||
lookup_result = lookup_query.get()
|
||||
if lookup_result:
|
||||
xml_key = lookup_result.key().name()
|
||||
xml_key = lookup_result.key.string_id()
|
||||
else:
|
||||
trials = 0
|
||||
result = True
|
||||
@@ -59,27 +56,32 @@ if "xml" in forms:
|
||||
if trials == 100:
|
||||
raise Exception("Sorry, the generator failed to get a key for you.")
|
||||
xml_key = keyGen()
|
||||
result = db.get(db.Key.from_path("Xml", xml_key))
|
||||
xml = db.Text(xml_content, encoding="utf_8")
|
||||
row = Xml(key_name = xml_key, xml_hash = xml_hash, xml_content = xml)
|
||||
result = Xml.get_by_id(xml_key)
|
||||
row = Xml(id = xml_key, xml_hash = xml_hash, xml_content = xml_content)
|
||||
row.put()
|
||||
print xml_key
|
||||
return xml_key
|
||||
|
||||
if "key" in forms:
|
||||
def keyToXml(key_provided):
|
||||
# Retrieve stored XML based on the provided key.
|
||||
key_provided = forms["key"].value
|
||||
# Normalize the string.
|
||||
key_provided = key_provided.lower().strip()
|
||||
# Check memcache for a quick match.
|
||||
xml = memcache.get("XML_" + key_provided)
|
||||
if xml is None:
|
||||
# Check datastore for a definitive match.
|
||||
result = db.get(db.Key.from_path("Xml", key_provided))
|
||||
result = Xml.get_by_id(key_provided)
|
||||
if not result:
|
||||
xml = ""
|
||||
else:
|
||||
xml = result.xml_content
|
||||
# Save to memcache for next hit.
|
||||
if not memcache.add("XML_" + key_provided, xml, 3600):
|
||||
logging.error("Memcache set failed.")
|
||||
print xml.encode("utf-8")
|
||||
memcache.add("XML_" + key_provided, xml, 3600)
|
||||
return xml.encode("utf-8")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Content-Type: text/plain\n")
|
||||
forms = cgi.FieldStorage()
|
||||
if "xml" in forms:
|
||||
print(xmlToKey(forms["xml"].value))
|
||||
if "key" in forms:
|
||||
print(keyToXml(forms["key"].value))
|
||||
|
||||
+473
-390
File diff suppressed because it is too large
Load Diff
@@ -61,22 +61,23 @@ goog.addDependency("../../../" + dir + "/accessible/variable-rename-modal.compon
|
||||
goog.addDependency("../../../" + dir + "/accessible/workspace-block.component.js", ['blocklyApp.WorkspaceBlockComponent'], ['blocklyApp.UtilsService', 'blocklyApp.AudioService', 'blocklyApp.BlockConnectionService', 'blocklyApp.FieldSegmentComponent', 'blocklyApp.TranslatePipe', 'blocklyApp.TreeService']);
|
||||
goog.addDependency("../../../" + dir + "/accessible/workspace.component.js", ['blocklyApp.WorkspaceComponent'], ['blocklyApp.NotificationsService', 'blocklyApp.ToolboxModalService', 'blocklyApp.TranslatePipe', 'blocklyApp.TreeService', 'blocklyApp.WorkspaceBlockComponent']);
|
||||
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.Blocks', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.array', 'goog.asserts', 'goog.math.Coordinate', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_animations.js", ['Blockly.BlockAnimations'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/block_drag_surface.js", ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_dragger.js", ['Blockly.BlockDragger'], ['Blockly.DraggedConnectionManager', 'Blockly.Events.BlockMove', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_dragger.js", ['Blockly.BlockDragger'], ['Blockly.BlockAnimations', 'Blockly.DraggedConnectionManager', 'Blockly.Events.BlockMove', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_events.js", ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_render_svg.js", ['Blockly.BlockSvg.render'], ['Blockly.BlockSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.ContextMenu', 'Blockly.Events.Ui', 'Blockly.Events.BlockMove', 'Blockly.Grid', 'Blockly.RenderedConnection', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'goog.Timer', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.BlockAnimations', 'Blockly.ContextMenu', 'Blockly.Events.Ui', 'Blockly.Events.BlockMove', 'Blockly.Grid', 'Blockly.RenderedConnection', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color']);
|
||||
goog.addDependency("../../../" + dir + "/core/blocks.js", ['Blockly.Blocks'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble.js", ['Blockly.Bubble'], ['Blockly.Touch', 'Blockly.Workspace', 'goog.dom', 'goog.math', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble_dragger.js", ['Blockly.BubbleDragger'], ['goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble_dragger.js", ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.Events.CommentMove', 'Blockly.WorkspaceCommentSvg', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/comment.js", ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/connection.js", ['Blockly.Connection'], ['Blockly.Events.BlockMove', 'goog.asserts', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/connection_db.js", ['Blockly.ConnectionDB'], ['Blockly.Connection']);
|
||||
goog.addDependency("../../../" + dir + "/core/constants.js", ['Blockly.constants'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/contextmenu.js", ['Blockly.ContextMenu'], ['Blockly.Events.BlockCreate', 'Blockly.utils', 'Blockly.utils.uiMenu', 'goog.dom', 'goog.events', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/css.js", ['Blockly.Css'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/dragged_connection_manager.js", ['Blockly.DraggedConnectionManager'], ['Blockly.RenderedConnection', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/dragged_connection_manager.js", ['Blockly.DraggedConnectionManager'], ['Blockly.BlockAnimations', 'Blockly.RenderedConnection', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/events.js", ['Blockly.Events'], ['goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/events_abstract.js", ['Blockly.Events.Abstract'], ['Blockly.Events', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/extensions.js", ['Blockly.Extensions'], ['Blockly.Mutator', 'Blockly.utils', 'goog.string']);
|
||||
@@ -97,13 +98,13 @@ goog.addDependency("../../../" + dir + "/core/flyout_dragger.js", ['Blockly.Flyo
|
||||
goog.addDependency("../../../" + dir + "/core/flyout_horizontal.js", ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.FlyoutButton', 'Blockly.Flyout', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/flyout_vertical.js", ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.Flyout', 'Blockly.FlyoutButton', 'Blockly.utils', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/generator.js", ['Blockly.Generator'], ['Blockly.Block', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/gesture.js", ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.constants', 'Blockly.Events.Ui', 'Blockly.FlyoutDragger', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/gesture.js", ['Blockly.Gesture'], ['Blockly.BlockAnimations', 'Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.constants', 'Blockly.Events.Ui', 'Blockly.FlyoutDragger', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/grid.js", ['Blockly.Grid'], ['Blockly.utils', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/icon.js", ['Blockly.Icon'], ['goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/inject.js", ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.Grid', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.WorkspaceDragSurfaceSvg', 'goog.dom', 'goog.ui.Component', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/input.js", ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/msg.js", ['Blockly.Msg'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/mutator.js", ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'goog.Timer', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/mutator.js", ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/names.js", ['Blockly.Names'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/options.js", ['Blockly.Options'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/procedures.js", ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.constants', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Names', 'Blockly.Workspace']);
|
||||
@@ -113,7 +114,7 @@ goog.addDependency("../../../" + dir + "/core/toolbox.js", ['Blockly.Toolbox'],
|
||||
goog.addDependency("../../../" + dir + "/core/tooltip.js", ['Blockly.Tooltip'], ['goog.dom', 'goog.dom.TagName']);
|
||||
goog.addDependency("../../../" + dir + "/core/touch.js", ['Blockly.Touch'], ['goog.events', 'goog.events.BrowserFeature', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/touch_gesture.js", ['Blockly.TouchGesture'], ['Blockly.Gesture', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/trashcan.js", ['Blockly.Trashcan'], ['goog.Timer', 'goog.dom', 'goog.math', 'goog.math.Rect']);
|
||||
goog.addDependency("../../../" + dir + "/core/trashcan.js", ['Blockly.Trashcan'], ['goog.dom', 'goog.math', 'goog.math.Rect']);
|
||||
goog.addDependency("../../../" + dir + "/core/ui_events.js", ['Blockly.Events.Ui'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/ui_menu_utils.js", ['Blockly.utils.uiMenu'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/utils.js", ['Blockly.utils'], ['Blockly.Touch', 'goog.dom', 'goog.events.BrowserFeature', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
@@ -124,12 +125,16 @@ goog.addDependency("../../../" + dir + "/core/variables.js", ['Blockly.Variables
|
||||
goog.addDependency("../../../" + dir + "/core/variables_dynamic.js", ['Blockly.VariablesDynamic'], ['Blockly.Variables', 'Blockly.Blocks', 'Blockly.constants', 'Blockly.VariableModel', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/warning.js", ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events.Ui', 'Blockly.Icon']);
|
||||
goog.addDependency("../../../" + dir + "/core/widgetdiv.js", ['Blockly.WidgetDiv'], ['Blockly.Css', 'goog.dom', 'goog.dom.TagName', 'goog.style']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace.js", ['Blockly.Workspace'], ['Blockly.VariableMap', 'goog.array', 'goog.math']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace.js", ['Blockly.Workspace'], ['Blockly.VariableMap', 'Blockly.WorkspaceComment', 'goog.array', 'goog.math']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_audio.js", ['Blockly.WorkspaceAudio'], ['goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment.js", ['Blockly.WorkspaceComment'], ['Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment_render_svg.js", ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.WorkspaceCommentSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment_svg.js", ['Blockly.WorkspaceCommentSvg'], ['Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.WorkspaceComment']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_drag_surface_svg.js", ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_dragger.js", ['Blockly.WorkspaceDragger'], ['goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_svg.js", ['Blockly.WorkspaceSvg'], ['Blockly.ConnectionDB', 'Blockly.constants', 'Blockly.Events.BlockCreate', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.ZoomControls', 'goog.array', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/xml.js", ['Blockly.Xml'], ['Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'goog.asserts', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_svg.js", ['Blockly.WorkspaceSvg'], ['Blockly.ConnectionDB', 'Blockly.constants', 'Blockly.Events.BlockCreate', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceComment', 'Blockly.WorkspaceCommentSvg', 'Blockly.WorkspaceCommentSvg.render', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.ZoomControls', 'goog.array', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/ws_comment_events.js", ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/xml.js", ['Blockly.Xml'], ['Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/zoom_controls.js", ['Blockly.ZoomControls'], ['Blockly.Touch', 'goog.dom']);
|
||||
goog.addDependency("../../alltests.js", [], []);
|
||||
goog.addDependency("../../browser_capabilities.js", [], []);
|
||||
@@ -1751,6 +1756,7 @@ goog.addDependency("window/window_test.js", ['goog.windowTest'], ['goog.Promise'
|
||||
// Load Blockly.
|
||||
goog.require('Blockly');
|
||||
goog.require('Blockly.Block');
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.BlockDragSurfaceSvg');
|
||||
goog.require('Blockly.BlockDragger');
|
||||
goog.require('Blockly.BlockSvg');
|
||||
@@ -1773,6 +1779,11 @@ goog.require('Blockly.Events.BlockCreate');
|
||||
goog.require('Blockly.Events.BlockDelete');
|
||||
goog.require('Blockly.Events.BlockMove');
|
||||
goog.require('Blockly.Events.Change');
|
||||
goog.require('Blockly.Events.CommentBase');
|
||||
goog.require('Blockly.Events.CommentChange');
|
||||
goog.require('Blockly.Events.CommentCreate');
|
||||
goog.require('Blockly.Events.CommentDelete');
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.Events.Create');
|
||||
goog.require('Blockly.Events.Delete');
|
||||
goog.require('Blockly.Events.Move');
|
||||
@@ -1824,6 +1835,9 @@ goog.require('Blockly.Warning');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
goog.require('Blockly.Workspace');
|
||||
goog.require('Blockly.WorkspaceAudio');
|
||||
goog.require('Blockly.WorkspaceComment');
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
goog.require('Blockly.WorkspaceDragSurfaceSvg');
|
||||
goog.require('Blockly.WorkspaceDragger');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
|
||||
+477
-394
File diff suppressed because it is too large
Load Diff
+24
-10
@@ -35,22 +35,23 @@ this.BLOCKLY_BOOT = function(root) {
|
||||
}
|
||||
// Execute after Closure has loaded.
|
||||
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.Blocks', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.array', 'goog.asserts', 'goog.math.Coordinate', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_animations.js", ['Blockly.BlockAnimations'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/block_drag_surface.js", ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_dragger.js", ['Blockly.BlockDragger'], ['Blockly.DraggedConnectionManager', 'Blockly.Events.BlockMove', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_dragger.js", ['Blockly.BlockDragger'], ['Blockly.BlockAnimations', 'Blockly.DraggedConnectionManager', 'Blockly.Events.BlockMove', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_events.js", ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_render_svg.js", ['Blockly.BlockSvg.render'], ['Blockly.BlockSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.ContextMenu', 'Blockly.Events.Ui', 'Blockly.Events.BlockMove', 'Blockly.Grid', 'Blockly.RenderedConnection', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'goog.Timer', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.BlockAnimations', 'Blockly.ContextMenu', 'Blockly.Events.Ui', 'Blockly.Events.BlockMove', 'Blockly.Grid', 'Blockly.RenderedConnection', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color']);
|
||||
goog.addDependency("../../../" + dir + "/core/blocks.js", ['Blockly.Blocks'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble.js", ['Blockly.Bubble'], ['Blockly.Touch', 'Blockly.Workspace', 'goog.dom', 'goog.math', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble_dragger.js", ['Blockly.BubbleDragger'], ['goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble_dragger.js", ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.Events.CommentMove', 'Blockly.WorkspaceCommentSvg', 'goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/comment.js", ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/connection.js", ['Blockly.Connection'], ['Blockly.Events.BlockMove', 'goog.asserts', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/connection_db.js", ['Blockly.ConnectionDB'], ['Blockly.Connection']);
|
||||
goog.addDependency("../../../" + dir + "/core/constants.js", ['Blockly.constants'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/contextmenu.js", ['Blockly.ContextMenu'], ['Blockly.Events.BlockCreate', 'Blockly.utils', 'Blockly.utils.uiMenu', 'goog.dom', 'goog.events', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/css.js", ['Blockly.Css'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/dragged_connection_manager.js", ['Blockly.DraggedConnectionManager'], ['Blockly.RenderedConnection', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/dragged_connection_manager.js", ['Blockly.DraggedConnectionManager'], ['Blockly.BlockAnimations', 'Blockly.RenderedConnection', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/events.js", ['Blockly.Events'], ['goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/events_abstract.js", ['Blockly.Events.Abstract'], ['Blockly.Events', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/extensions.js", ['Blockly.Extensions'], ['Blockly.Mutator', 'Blockly.utils', 'goog.string']);
|
||||
@@ -71,13 +72,13 @@ goog.addDependency("../../../" + dir + "/core/flyout_dragger.js", ['Blockly.Flyo
|
||||
goog.addDependency("../../../" + dir + "/core/flyout_horizontal.js", ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.FlyoutButton', 'Blockly.Flyout', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/flyout_vertical.js", ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.Flyout', 'Blockly.FlyoutButton', 'Blockly.utils', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/generator.js", ['Blockly.Generator'], ['Blockly.Block', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/gesture.js", ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.constants', 'Blockly.Events.Ui', 'Blockly.FlyoutDragger', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/gesture.js", ['Blockly.Gesture'], ['Blockly.BlockAnimations', 'Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.constants', 'Blockly.Events.Ui', 'Blockly.FlyoutDragger', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/grid.js", ['Blockly.Grid'], ['Blockly.utils', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/icon.js", ['Blockly.Icon'], ['goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/inject.js", ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.Grid', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.WorkspaceDragSurfaceSvg', 'goog.dom', 'goog.ui.Component', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/input.js", ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/msg.js", ['Blockly.Msg'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/mutator.js", ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'goog.Timer', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/mutator.js", ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events.BlockChange', 'Blockly.Events.Ui', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/names.js", ['Blockly.Names'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/options.js", ['Blockly.Options'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/procedures.js", ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.constants', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Names', 'Blockly.Workspace']);
|
||||
@@ -87,7 +88,7 @@ goog.addDependency("../../../" + dir + "/core/toolbox.js", ['Blockly.Toolbox'],
|
||||
goog.addDependency("../../../" + dir + "/core/tooltip.js", ['Blockly.Tooltip'], ['goog.dom', 'goog.dom.TagName']);
|
||||
goog.addDependency("../../../" + dir + "/core/touch.js", ['Blockly.Touch'], ['goog.events', 'goog.events.BrowserFeature', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/touch_gesture.js", ['Blockly.TouchGesture'], ['Blockly.Gesture', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/trashcan.js", ['Blockly.Trashcan'], ['goog.Timer', 'goog.dom', 'goog.math', 'goog.math.Rect']);
|
||||
goog.addDependency("../../../" + dir + "/core/trashcan.js", ['Blockly.Trashcan'], ['goog.dom', 'goog.math', 'goog.math.Rect']);
|
||||
goog.addDependency("../../../" + dir + "/core/ui_events.js", ['Blockly.Events.Ui'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.array', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/ui_menu_utils.js", ['Blockly.utils.uiMenu'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/utils.js", ['Blockly.utils'], ['Blockly.Touch', 'goog.dom', 'goog.events.BrowserFeature', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
@@ -98,12 +99,16 @@ goog.addDependency("../../../" + dir + "/core/variables.js", ['Blockly.Variables
|
||||
goog.addDependency("../../../" + dir + "/core/variables_dynamic.js", ['Blockly.VariablesDynamic'], ['Blockly.Variables', 'Blockly.Blocks', 'Blockly.constants', 'Blockly.VariableModel', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/warning.js", ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events.Ui', 'Blockly.Icon']);
|
||||
goog.addDependency("../../../" + dir + "/core/widgetdiv.js", ['Blockly.WidgetDiv'], ['Blockly.Css', 'goog.dom', 'goog.dom.TagName', 'goog.style']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace.js", ['Blockly.Workspace'], ['Blockly.VariableMap', 'goog.array', 'goog.math']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace.js", ['Blockly.Workspace'], ['Blockly.VariableMap', 'Blockly.WorkspaceComment', 'goog.array', 'goog.math']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_audio.js", ['Blockly.WorkspaceAudio'], ['goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment.js", ['Blockly.WorkspaceComment'], ['Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment_render_svg.js", ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.WorkspaceCommentSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_comment_svg.js", ['Blockly.WorkspaceCommentSvg'], ['Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.WorkspaceComment']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_drag_surface_svg.js", ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'goog.asserts', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_dragger.js", ['Blockly.WorkspaceDragger'], ['goog.math.Coordinate', 'goog.asserts']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_svg.js", ['Blockly.WorkspaceSvg'], ['Blockly.ConnectionDB', 'Blockly.constants', 'Blockly.Events.BlockCreate', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.ZoomControls', 'goog.array', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/xml.js", ['Blockly.Xml'], ['Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'goog.asserts', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/workspace_svg.js", ['Blockly.WorkspaceSvg'], ['Blockly.ConnectionDB', 'Blockly.constants', 'Blockly.Events.BlockCreate', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Touch', 'Blockly.TouchGesture', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceComment', 'Blockly.WorkspaceCommentSvg', 'Blockly.WorkspaceCommentSvg.render', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.ZoomControls', 'goog.array', 'goog.dom', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/ws_comment_events.js", ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'goog.math.Coordinate']);
|
||||
goog.addDependency("../../../" + dir + "/core/xml.js", ['Blockly.Xml'], ['Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'goog.dom']);
|
||||
goog.addDependency("../../../" + dir + "/core/zoom_controls.js", ['Blockly.ZoomControls'], ['Blockly.Touch', 'goog.dom']);
|
||||
goog.addDependency("../../alltests.js", [], []);
|
||||
goog.addDependency("../../browser_capabilities.js", [], []);
|
||||
@@ -1725,6 +1730,7 @@ goog.addDependency("window/window_test.js", ['goog.windowTest'], ['goog.Promise'
|
||||
// Load Blockly.
|
||||
goog.require('Blockly');
|
||||
goog.require('Blockly.Block');
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.BlockDragSurfaceSvg');
|
||||
goog.require('Blockly.BlockDragger');
|
||||
goog.require('Blockly.BlockSvg');
|
||||
@@ -1746,6 +1752,11 @@ goog.require('Blockly.Events.BlockCreate');
|
||||
goog.require('Blockly.Events.BlockDelete');
|
||||
goog.require('Blockly.Events.BlockMove');
|
||||
goog.require('Blockly.Events.Change');
|
||||
goog.require('Blockly.Events.CommentBase');
|
||||
goog.require('Blockly.Events.CommentChange');
|
||||
goog.require('Blockly.Events.CommentCreate');
|
||||
goog.require('Blockly.Events.CommentDelete');
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.Events.Create');
|
||||
goog.require('Blockly.Events.Delete');
|
||||
goog.require('Blockly.Events.Move');
|
||||
@@ -1797,6 +1808,9 @@ goog.require('Blockly.Warning');
|
||||
goog.require('Blockly.WidgetDiv');
|
||||
goog.require('Blockly.Workspace');
|
||||
goog.require('Blockly.WorkspaceAudio');
|
||||
goog.require('Blockly.WorkspaceComment');
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
goog.require('Blockly.WorkspaceDragSurfaceSvg');
|
||||
goog.require('Blockly.WorkspaceDragger');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Blocks.colour'); // Deprecated
|
||||
goog.provide('Blockly.Constants.Colour');
|
||||
goog.provide('Blockly.Constants.Colour'); // deprecated, 2018 April 5
|
||||
|
||||
goog.require('Blockly.Blocks');
|
||||
goog.require('Blockly');
|
||||
@@ -38,7 +38,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.COLOUR_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['COLOUR_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Colour.HUE = 20;
|
||||
|
||||
|
||||
+103
-103
@@ -30,14 +30,14 @@
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Blocks.lists'); // Deprecated
|
||||
goog.provide('Blockly.Constants.Lists');
|
||||
goog.provide('Blockly.Constants.Lists'); // deprecated, 2018 April 5
|
||||
|
||||
goog.require('Blockly.Blocks');
|
||||
goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.LISTS_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['LISTS_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Lists.HUE = 260;
|
||||
|
||||
@@ -132,13 +132,13 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_CREATE_WITH_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_CREATE_WITH_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.itemCount_ = 3;
|
||||
this.updateShape_();
|
||||
this.setOutput(true, 'Array');
|
||||
this.setMutator(new Blockly.Mutator(['lists_create_with_item']));
|
||||
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['LISTS_CREATE_WITH_TOOLTIP']);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent list inputs.
|
||||
@@ -231,14 +231,14 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
this.removeInput('EMPTY');
|
||||
} else if (!this.itemCount_ && !this.getInput('EMPTY')) {
|
||||
this.appendDummyInput('EMPTY')
|
||||
.appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
|
||||
.appendField(Blockly.Msg['LISTS_CREATE_EMPTY_TITLE']);
|
||||
}
|
||||
// Add new inputs.
|
||||
for (var i = 0; i < this.itemCount_; i++) {
|
||||
if (!this.getInput('ADD' + i)) {
|
||||
var input = this.appendValueInput('ADD' + i);
|
||||
if (i == 0) {
|
||||
input.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);
|
||||
input.appendField(Blockly.Msg['LISTS_CREATE_WITH_INPUT_WITH']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,11 +256,11 @@ Blockly.Blocks['lists_create_with_container'] = {
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD);
|
||||
.appendField(Blockly.Msg['LISTS_CREATE_WITH_CONTAINER_TITLE_ADD']);
|
||||
this.appendStatementInput('STACK');
|
||||
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['LISTS_CREATE_WITH_CONTAINER_TOOLTIP']);
|
||||
this.contextMenu = false;
|
||||
}
|
||||
};
|
||||
@@ -271,12 +271,12 @@ Blockly.Blocks['lists_create_with_item'] = {
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE);
|
||||
.appendField(Blockly.Msg['LISTS_CREATE_WITH_ITEM_TITLE']);
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['LISTS_CREATE_WITH_ITEM_TOOLTIP']);
|
||||
this.contextMenu = false;
|
||||
}
|
||||
};
|
||||
@@ -289,22 +289,22 @@ Blockly.Blocks['lists_indexOf'] = {
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[
|
||||
[Blockly.Msg.LISTS_INDEX_OF_FIRST, 'FIRST'],
|
||||
[Blockly.Msg.LISTS_INDEX_OF_LAST, 'LAST']
|
||||
[Blockly.Msg['LISTS_INDEX_OF_FIRST'], 'FIRST'],
|
||||
[Blockly.Msg['LISTS_INDEX_OF_LAST'], 'LAST']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_INDEX_OF_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.setOutput(true, 'Number');
|
||||
this.appendValueInput('VALUE')
|
||||
.setCheck('Array')
|
||||
.appendField(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST);
|
||||
.appendField(Blockly.Msg['LISTS_INDEX_OF_INPUT_IN_LIST']);
|
||||
this.appendValueInput('FIND')
|
||||
.appendField(new Blockly.FieldDropdown(OPERATORS), 'END');
|
||||
this.setInputsInline(true);
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
return Blockly.Msg.LISTS_INDEX_OF_TOOLTIP.replace('%1',
|
||||
return Blockly.Msg['LISTS_INDEX_OF_TOOLTIP'].replace('%1',
|
||||
thisBlock.workspace.options.oneBasedIndex ? '0' : '-1');
|
||||
});
|
||||
}
|
||||
@@ -318,34 +318,34 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
init: function() {
|
||||
var MODE =
|
||||
[
|
||||
[Blockly.Msg.LISTS_GET_INDEX_GET, 'GET'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE, 'GET_REMOVE'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_REMOVE, 'REMOVE']
|
||||
[Blockly.Msg['LISTS_GET_INDEX_GET'], 'GET'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_GET_REMOVE'], 'GET_REMOVE'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_REMOVE'], 'REMOVE']
|
||||
];
|
||||
this.WHERE_OPTIONS =
|
||||
[
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FIRST'], 'FIRST'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_LAST'], 'LAST'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_RANDOM'], 'RANDOM']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_GET_INDEX_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
var modeMenu = new Blockly.FieldDropdown(MODE, function(value) {
|
||||
var isStatement = (value == 'REMOVE');
|
||||
this.sourceBlock_.updateStatement_(isStatement);
|
||||
});
|
||||
this.appendValueInput('VALUE')
|
||||
.setCheck('Array')
|
||||
.appendField(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST);
|
||||
.appendField(Blockly.Msg['LISTS_GET_INDEX_INPUT_IN_LIST']);
|
||||
this.appendDummyInput()
|
||||
.appendField(modeMenu, 'MODE')
|
||||
.appendField('', 'SPACE');
|
||||
this.appendDummyInput('AT');
|
||||
if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {
|
||||
if (Blockly.Msg['LISTS_GET_INDEX_TAIL']) {
|
||||
this.appendDummyInput('TAIL')
|
||||
.appendField(Blockly.Msg.LISTS_GET_INDEX_TAIL);
|
||||
.appendField(Blockly.Msg['LISTS_GET_INDEX_TAIL']);
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true);
|
||||
@@ -359,48 +359,48 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
switch (mode + ' ' + where) {
|
||||
case 'GET FROM_START':
|
||||
case 'GET FROM_END':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_FROM'];
|
||||
break;
|
||||
case 'GET FIRST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_FIRST'];
|
||||
break;
|
||||
case 'GET LAST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_LAST'];
|
||||
break;
|
||||
case 'GET RANDOM':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_RANDOM'];
|
||||
break;
|
||||
case 'GET_REMOVE FROM_START':
|
||||
case 'GET_REMOVE FROM_END':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM'];
|
||||
break;
|
||||
case 'GET_REMOVE FIRST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST'];
|
||||
break;
|
||||
case 'GET_REMOVE LAST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST'];
|
||||
break;
|
||||
case 'GET_REMOVE RANDOM':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM'];
|
||||
break;
|
||||
case 'REMOVE FROM_START':
|
||||
case 'REMOVE FROM_END':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM'];
|
||||
break;
|
||||
case 'REMOVE FIRST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST'];
|
||||
break;
|
||||
case 'REMOVE LAST':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST'];
|
||||
break;
|
||||
case 'REMOVE RANDOM':
|
||||
tooltip = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM;
|
||||
tooltip = Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM'];
|
||||
break;
|
||||
}
|
||||
if (where == 'FROM_START' || where == 'FROM_END') {
|
||||
var msg = (where == 'FROM_START') ?
|
||||
Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP :
|
||||
Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP;
|
||||
Blockly.Msg['LISTS_INDEX_FROM_START_TOOLTIP'] :
|
||||
Blockly.Msg['LISTS_INDEX_FROM_END_TOOLTIP'];
|
||||
tooltip += ' ' + msg.replace('%1',
|
||||
thisBlock.workspace.options.oneBasedIndex ? '#1' : '#0');
|
||||
}
|
||||
@@ -469,9 +469,9 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
// Create either a value 'AT' input or a dummy input.
|
||||
if (isAt) {
|
||||
this.appendValueInput('AT').setCheck('Number');
|
||||
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
|
||||
if (Blockly.Msg['ORDINAL_NUMBER_SUFFIX']) {
|
||||
this.appendDummyInput('ORDINAL')
|
||||
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
|
||||
.appendField(Blockly.Msg['ORDINAL_NUMBER_SUFFIX']);
|
||||
}
|
||||
} else {
|
||||
this.appendDummyInput('AT');
|
||||
@@ -489,7 +489,7 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
return undefined;
|
||||
});
|
||||
this.getInput('AT').appendField(menu, 'WHERE');
|
||||
if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {
|
||||
if (Blockly.Msg['LISTS_GET_INDEX_TAIL']) {
|
||||
this.moveInputBefore('TAIL', null);
|
||||
}
|
||||
}
|
||||
@@ -503,32 +503,32 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
init: function() {
|
||||
var MODE =
|
||||
[
|
||||
[Blockly.Msg.LISTS_SET_INDEX_SET, 'SET'],
|
||||
[Blockly.Msg.LISTS_SET_INDEX_INSERT, 'INSERT']
|
||||
[Blockly.Msg['LISTS_SET_INDEX_SET'], 'SET'],
|
||||
[Blockly.Msg['LISTS_SET_INDEX_INSERT'], 'INSERT']
|
||||
];
|
||||
this.WHERE_OPTIONS =
|
||||
[
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],
|
||||
[Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_FIRST'], 'FIRST'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_LAST'], 'LAST'],
|
||||
[Blockly.Msg['LISTS_GET_INDEX_RANDOM'], 'RANDOM']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_SET_INDEX_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.appendValueInput('LIST')
|
||||
.setCheck('Array')
|
||||
.appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST);
|
||||
.appendField(Blockly.Msg['LISTS_SET_INDEX_INPUT_IN_LIST']);
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldDropdown(MODE), 'MODE')
|
||||
.appendField('', 'SPACE');
|
||||
this.appendDummyInput('AT');
|
||||
this.appendValueInput('TO')
|
||||
.appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO);
|
||||
.appendField(Blockly.Msg['LISTS_SET_INDEX_INPUT_TO']);
|
||||
this.setInputsInline(true);
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['LISTS_SET_INDEX_TOOLTIP']);
|
||||
this.updateAt_(true);
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
@@ -539,33 +539,33 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
switch (mode + ' ' + where) {
|
||||
case 'SET FROM_START':
|
||||
case 'SET FROM_END':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_SET_FROM'];
|
||||
break;
|
||||
case 'SET FIRST':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_SET_FIRST'];
|
||||
break;
|
||||
case 'SET LAST':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_SET_LAST'];
|
||||
break;
|
||||
case 'SET RANDOM':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_SET_RANDOM'];
|
||||
break;
|
||||
case 'INSERT FROM_START':
|
||||
case 'INSERT FROM_END':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_INSERT_FROM'];
|
||||
break;
|
||||
case 'INSERT FIRST':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST'];
|
||||
break;
|
||||
case 'INSERT LAST':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_INSERT_LAST'];
|
||||
break;
|
||||
case 'INSERT RANDOM':
|
||||
tooltip = Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM;
|
||||
tooltip = Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM'];
|
||||
break;
|
||||
}
|
||||
if (where == 'FROM_START' || where == 'FROM_END') {
|
||||
tooltip += ' ' + Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP
|
||||
tooltip += ' ' + Blockly.Msg['LISTS_INDEX_FROM_START_TOOLTIP']
|
||||
.replace('%1',
|
||||
thisBlock.workspace.options.oneBasedIndex ? '#1' : '#0');
|
||||
}
|
||||
@@ -607,9 +607,9 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
// Create either a value 'AT' input or a dummy input.
|
||||
if (isAt) {
|
||||
this.appendValueInput('AT').setCheck('Number');
|
||||
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
|
||||
if (Blockly.Msg['ORDINAL_NUMBER_SUFFIX']) {
|
||||
this.appendDummyInput('ORDINAL')
|
||||
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
|
||||
.appendField(Blockly.Msg['ORDINAL_NUMBER_SUFFIX']);
|
||||
}
|
||||
} else {
|
||||
this.appendDummyInput('AT');
|
||||
@@ -643,32 +643,32 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
init: function() {
|
||||
this['WHERE_OPTIONS_1'] =
|
||||
[
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST']
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_START_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_START_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_START_FIRST'], 'FIRST']
|
||||
];
|
||||
this['WHERE_OPTIONS_2'] =
|
||||
[
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST']
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_END_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_END_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['LISTS_GET_SUBLIST_END_LAST'], 'LAST']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_GET_SUBLIST_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.appendValueInput('LIST')
|
||||
.setCheck('Array')
|
||||
.appendField(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST);
|
||||
.appendField(Blockly.Msg['LISTS_GET_SUBLIST_INPUT_IN_LIST']);
|
||||
this.appendDummyInput('AT1');
|
||||
this.appendDummyInput('AT2');
|
||||
if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {
|
||||
if (Blockly.Msg['LISTS_GET_SUBLIST_TAIL']) {
|
||||
this.appendDummyInput('TAIL')
|
||||
.appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL);
|
||||
.appendField(Blockly.Msg['LISTS_GET_SUBLIST_TAIL']);
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'Array');
|
||||
this.updateAt_(1, true);
|
||||
this.updateAt_(2, true);
|
||||
this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['LISTS_GET_SUBLIST_TOOLTIP']);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there are 'AT' inputs.
|
||||
@@ -710,9 +710,9 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
// Create either a value 'AT' input or a dummy input.
|
||||
if (isAt) {
|
||||
this.appendValueInput('AT' + n).setCheck('Number');
|
||||
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
|
||||
if (Blockly.Msg['ORDINAL_NUMBER_SUFFIX']) {
|
||||
this.appendDummyInput('ORDINAL' + n)
|
||||
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
|
||||
.appendField(Blockly.Msg['ORDINAL_NUMBER_SUFFIX']);
|
||||
}
|
||||
} else {
|
||||
this.appendDummyInput('AT' + n);
|
||||
@@ -740,7 +740,7 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
this.moveInputBefore('ORDINAL1', 'AT2');
|
||||
}
|
||||
}
|
||||
if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {
|
||||
if (Blockly.Msg['LISTS_GET_SUBLIST_TAIL']) {
|
||||
this.moveInputBefore('TAIL', null);
|
||||
}
|
||||
}
|
||||
@@ -753,23 +753,23 @@ Blockly.Blocks['lists_sort'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.LISTS_SORT_TITLE,
|
||||
"message0": Blockly.Msg['LISTS_SORT_TITLE'],
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "TYPE",
|
||||
"options": [
|
||||
[Blockly.Msg.LISTS_SORT_TYPE_NUMERIC, "NUMERIC"],
|
||||
[Blockly.Msg.LISTS_SORT_TYPE_TEXT, "TEXT"],
|
||||
[Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE, "IGNORE_CASE"]
|
||||
[Blockly.Msg['LISTS_SORT_TYPE_NUMERIC'], "NUMERIC"],
|
||||
[Blockly.Msg['LISTS_SORT_TYPE_TEXT'], "TEXT"],
|
||||
[Blockly.Msg['LISTS_SORT_TYPE_IGNORECASE'], "IGNORE_CASE"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "DIRECTION",
|
||||
"options": [
|
||||
[Blockly.Msg.LISTS_SORT_ORDER_ASCENDING, "1"],
|
||||
[Blockly.Msg.LISTS_SORT_ORDER_DESCENDING, "-1"]
|
||||
[Blockly.Msg['LISTS_SORT_ORDER_ASCENDING'], "1"],
|
||||
[Blockly.Msg['LISTS_SORT_ORDER_DESCENDING'], "-1"]
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -779,9 +779,9 @@ Blockly.Blocks['lists_sort'] = {
|
||||
}
|
||||
],
|
||||
"output": "Array",
|
||||
"colour": Blockly.Msg.LISTS_HUE,
|
||||
"tooltip": Blockly.Msg.LISTS_SORT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.LISTS_SORT_HELPURL
|
||||
"colour": Blockly.Msg['LISTS_HUE'],
|
||||
"tooltip": Blockly.Msg['LISTS_SORT_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['LISTS_SORT_HELPURL']
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -796,28 +796,28 @@ Blockly.Blocks['lists_split'] = {
|
||||
var thisBlock = this;
|
||||
var dropdown = new Blockly.FieldDropdown(
|
||||
[
|
||||
[Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT, 'SPLIT'],
|
||||
[Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST, 'JOIN']
|
||||
[Blockly.Msg['LISTS_SPLIT_LIST_FROM_TEXT'], 'SPLIT'],
|
||||
[Blockly.Msg['LISTS_SPLIT_TEXT_FROM_LIST'], 'JOIN']
|
||||
],
|
||||
function(newMode) {
|
||||
thisBlock.updateType_(newMode);
|
||||
});
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_SPLIT_HELPURL);
|
||||
this.setColour(Blockly.Msg.LISTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['LISTS_SPLIT_HELPURL']);
|
||||
this.setColour(Blockly.Msg['LISTS_HUE']);
|
||||
this.appendValueInput('INPUT')
|
||||
.setCheck('String')
|
||||
.appendField(dropdown, 'MODE');
|
||||
this.appendValueInput('DELIM')
|
||||
.setCheck('String')
|
||||
.appendField(Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER);
|
||||
.appendField(Blockly.Msg['LISTS_SPLIT_WITH_DELIMITER']);
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'Array');
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('MODE');
|
||||
if (mode == 'SPLIT') {
|
||||
return Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT;
|
||||
return Blockly.Msg['LISTS_SPLIT_TOOLTIP_SPLIT'];
|
||||
} else if (mode == 'JOIN') {
|
||||
return Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN;
|
||||
return Blockly.Msg['LISTS_SPLIT_TOOLTIP_JOIN'];
|
||||
}
|
||||
throw 'Unknown mode: ' + mode;
|
||||
});
|
||||
|
||||
+16
-49
@@ -37,7 +37,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.LOGIC_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['LOGIC_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Logic.HUE = 210;
|
||||
|
||||
@@ -133,10 +133,10 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
|
||||
"options": [
|
||||
["=", "EQ"],
|
||||
["\u2260", "NEQ"],
|
||||
["<", "LT"],
|
||||
["\u2264", "LTE"],
|
||||
[">", "GT"],
|
||||
["\u2265", "GTE"]
|
||||
["\u200F<", "LT"],
|
||||
["\u200F\u2264", "LTE"],
|
||||
["\u200F>", "GT"],
|
||||
["\u200F\u2265", "GTE"]
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -445,13 +445,13 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = {
|
||||
for (var i = 1; i <= this.elseifCount_; i++) {
|
||||
this.appendValueInput('IF' + i)
|
||||
.setCheck('Boolean')
|
||||
.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);
|
||||
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']);
|
||||
this.appendStatementInput('DO' + i)
|
||||
.appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);
|
||||
.appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']);
|
||||
}
|
||||
if (this.elseCount_) {
|
||||
this.appendStatementInput('ELSE')
|
||||
.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);
|
||||
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE']);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -469,13 +469,13 @@ Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION = function() {
|
||||
|
||||
this.setTooltip(function() {
|
||||
if (!this.elseifCount_ && !this.elseCount_) {
|
||||
return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;
|
||||
return Blockly.Msg['CONTROLS_IF_TOOLTIP_1'];
|
||||
} else if (!this.elseifCount_ && this.elseCount_) {
|
||||
return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;
|
||||
return Blockly.Msg['CONTROLS_IF_TOOLTIP_2'];
|
||||
} else if (this.elseifCount_ && !this.elseCount_) {
|
||||
return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;
|
||||
return Blockly.Msg['CONTROLS_IF_TOOLTIP_3'];
|
||||
} else if (this.elseifCount_ && this.elseCount_) {
|
||||
return Blockly.Msg.CONTROLS_IF_TOOLTIP_4;
|
||||
return Blockly.Msg['CONTROLS_IF_TOOLTIP_4'];
|
||||
}
|
||||
return '';
|
||||
}.bind(this));
|
||||
@@ -485,35 +485,8 @@ Blockly.Extensions.register('controls_if_tooltip',
|
||||
Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION);
|
||||
|
||||
/**
|
||||
* Corrects the logic_compare dropdown label with respect to language direction.
|
||||
* @this Blockly.Block
|
||||
* @package
|
||||
*/
|
||||
Blockly.Constants.Logic.fixLogicCompareRtlOpLabels =
|
||||
function() {
|
||||
var rtlOpLabels = {
|
||||
'LT': '\u200F<\u200F',
|
||||
'LTE': '\u200F\u2264\u200F',
|
||||
'GT': '\u200F>\u200F',
|
||||
'GTE': '\u200F\u2265\u200F'
|
||||
};
|
||||
var opDropdown = this.getField('OP');
|
||||
if (opDropdown) {
|
||||
var options = opDropdown.getOptions();
|
||||
for (var i = 0; i < options.length; ++i) {
|
||||
var tuple = options[i];
|
||||
var op = tuple[1];
|
||||
var rtlLabel = rtlOpLabels[op];
|
||||
if (goog.isString(tuple[0]) && rtlLabel) {
|
||||
// Replace LTR text label
|
||||
tuple[0] = rtlLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds dynamic type validation for the left and right sides of a logic_compare block.
|
||||
* Adds dynamic type validation for the left and right sides of a logic_compare
|
||||
* block.
|
||||
* @mixin
|
||||
* @augments Blockly.Block
|
||||
* @package
|
||||
@@ -564,19 +537,13 @@ Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN = {
|
||||
};
|
||||
|
||||
/**
|
||||
* "logic_compare" extension function. Corrects direction of operators in the
|
||||
* dropdown labels, and adds type left and right side type checking to
|
||||
* "logic_compare" blocks.
|
||||
* "logic_compare" extension function. Adds type left and right side type
|
||||
* checking to "logic_compare" blocks.
|
||||
* @this Blockly.Block
|
||||
* @package
|
||||
* @readonly
|
||||
*/
|
||||
Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION = function() {
|
||||
// Fix operator labels in RTL.
|
||||
if (this.RTL) {
|
||||
Blockly.Constants.Logic.fixLogicCompareRtlOpLabels.apply(this);
|
||||
}
|
||||
|
||||
// Add onchange handler to ensure types are compatible.
|
||||
this.mixin(Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN);
|
||||
};
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.LOOPS_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['LOOPS_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Loops.HUE = 120;
|
||||
|
||||
@@ -266,7 +266,7 @@ Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN = {
|
||||
if (!this.isCollapsed() && varName != null) {
|
||||
var option = {enabled: true};
|
||||
option.text =
|
||||
Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', varName);
|
||||
Blockly.Msg['VARIABLES_SET_CREATE_GET'].replace('%1', varName);
|
||||
var xmlField = Blockly.Variables.generateVariableFieldDom(variable);
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
@@ -330,7 +330,7 @@ Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN = {
|
||||
this.setDisabled(false);
|
||||
}
|
||||
} else {
|
||||
this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);
|
||||
this.setWarningText(Blockly.Msg['CONTROLS_FLOW_STATEMENTS_WARNING']);
|
||||
if (!this.isInFlyout && !this.getInheritedDisabled()) {
|
||||
this.setDisabled(true);
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.MATH_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['MATH_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Math.HUE = 230;
|
||||
|
||||
|
||||
+42
-42
@@ -40,19 +40,19 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
Blockly.Procedures.rename);
|
||||
nameField.setSpellcheck(false);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE)
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFNORETURN_TITLE'])
|
||||
.appendField(nameField, 'NAME')
|
||||
.appendField('', 'PARAMS');
|
||||
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
|
||||
if ((this.workspace.options.comments ||
|
||||
(this.workspace.options.parentWorkspace &&
|
||||
this.workspace.options.parentWorkspace.options.comments)) &&
|
||||
Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT) {
|
||||
this.setCommentText(Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT);
|
||||
Blockly.Msg['PROCEDURES_DEFNORETURN_COMMENT']) {
|
||||
this.setCommentText(Blockly.Msg['PROCEDURES_DEFNORETURN_COMMENT']);
|
||||
}
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
this.setTooltip(Blockly.Msg['PROCEDURES_DEFNORETURN_TOOLTIP']);
|
||||
this.setHelpUrl(Blockly.Msg['PROCEDURES_DEFNORETURN_HELPURL']);
|
||||
this.arguments_ = [];
|
||||
this.argumentVarModels_ = [];
|
||||
this.setStatements_(true);
|
||||
@@ -69,7 +69,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
}
|
||||
if (hasStatements) {
|
||||
this.appendStatementInput('STACK')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFNORETURN_DO']);
|
||||
if (this.getInput('RETURN')) {
|
||||
this.moveInputBefore('STACK', 'RETURN');
|
||||
}
|
||||
@@ -96,14 +96,14 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
hash['arg_' + this.arguments_[i].toLowerCase()] = true;
|
||||
}
|
||||
if (badArg) {
|
||||
this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING);
|
||||
this.setWarningText(Blockly.Msg['PROCEDURES_DEF_DUPLICATE_WARNING']);
|
||||
} else {
|
||||
this.setWarningText(null);
|
||||
}
|
||||
// Merge the arguments into a human-readable list.
|
||||
var paramString = '';
|
||||
if (this.arguments_.length) {
|
||||
paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS +
|
||||
paramString = Blockly.Msg['PROCEDURES_BEFORE_PARAMS'] +
|
||||
' ' + this.arguments_.join(', ');
|
||||
}
|
||||
// The params field is deterministic based on the mutation,
|
||||
@@ -356,7 +356,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
// Add option to create caller.
|
||||
var option = {enabled: true};
|
||||
var name = this.getFieldValue('NAME');
|
||||
option.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace('%1', name);
|
||||
option.text = Blockly.Msg['PROCEDURES_CREATE_DO'].replace('%1', name);
|
||||
var xmlMutation = goog.dom.createDom('mutation');
|
||||
xmlMutation.setAttribute('name', name);
|
||||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
@@ -375,7 +375,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
var option = {enabled: true};
|
||||
var argVar = this.argumentVarModels_[i];
|
||||
var name = argVar.name;
|
||||
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
|
||||
option.text = Blockly.Msg['VARIABLES_SET_CREATE_GET'].replace('%1', name);
|
||||
|
||||
var xmlField = Blockly.Variables.generateVariableFieldDom(argVar);
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
@@ -398,22 +398,22 @@ Blockly.Blocks['procedures_defreturn'] = {
|
||||
Blockly.Procedures.rename);
|
||||
nameField.setSpellcheck(false);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE)
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_TITLE'])
|
||||
.appendField(nameField, 'NAME')
|
||||
.appendField('', 'PARAMS');
|
||||
this.appendValueInput('RETURN')
|
||||
.setAlign(Blockly.ALIGN_RIGHT)
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']);
|
||||
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
|
||||
if ((this.workspace.options.comments ||
|
||||
(this.workspace.options.parentWorkspace &&
|
||||
this.workspace.options.parentWorkspace.options.comments)) &&
|
||||
Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT) {
|
||||
this.setCommentText(Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT);
|
||||
Blockly.Msg['PROCEDURES_DEFRETURN_COMMENT']) {
|
||||
this.setCommentText(Blockly.Msg['PROCEDURES_DEFRETURN_COMMENT']);
|
||||
}
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
this.setTooltip(Blockly.Msg['PROCEDURES_DEFRETURN_TOOLTIP']);
|
||||
this.setHelpUrl(Blockly.Msg['PROCEDURES_DEFRETURN_HELPURL']);
|
||||
this.arguments_ = [];
|
||||
this.argumentVarModels_ = [];
|
||||
this.setStatements_(true);
|
||||
@@ -452,13 +452,13 @@ Blockly.Blocks['procedures_mutatorcontainer'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);
|
||||
.appendField(Blockly.Msg['PROCEDURES_MUTATORCONTAINER_TITLE']);
|
||||
this.appendStatementInput('STACK');
|
||||
this.appendDummyInput('STATEMENT_INPUT')
|
||||
.appendField(Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS)
|
||||
.appendField(Blockly.Msg['PROCEDURES_ALLOW_STATEMENTS'])
|
||||
.appendField(new Blockly.FieldCheckbox('TRUE'), 'STATEMENTS');
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
this.setTooltip(Blockly.Msg['PROCEDURES_MUTATORCONTAINER_TOOLTIP']);
|
||||
this.contextMenu = false;
|
||||
}
|
||||
};
|
||||
@@ -480,12 +480,12 @@ Blockly.Blocks['procedures_mutatorarg'] = {
|
||||
field.showEditor_ = newShowEditorFn;
|
||||
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE)
|
||||
.appendField(Blockly.Msg['PROCEDURES_MUTATORARG_TITLE'])
|
||||
.appendField(field, 'NAME');
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
this.setTooltip(Blockly.Msg['PROCEDURES_MUTATORARG_TOOLTIP']);
|
||||
this.contextMenu = false;
|
||||
|
||||
// Create the default variable when we drag the block in from the flyout.
|
||||
@@ -557,9 +557,9 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
.appendField(this.id, 'NAME');
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
// Tooltip is set in renameProcedure.
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['PROCEDURES_CALLNORETURN_HELPURL']);
|
||||
this.arguments_ = [];
|
||||
this.argumentVarModels_ = [];
|
||||
this.quarkConnections_ = {};
|
||||
@@ -585,8 +585,8 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
if (Blockly.Names.equals(oldName, this.getProcedureCall())) {
|
||||
this.setFieldValue(newName, 'NAME');
|
||||
var baseMsg = this.outputConnection ?
|
||||
Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP :
|
||||
Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP;
|
||||
Blockly.Msg['PROCEDURES_CALLRETURN_TOOLTIP'] :
|
||||
Blockly.Msg['PROCEDURES_CALLNORETURN_TOOLTIP'];
|
||||
this.setTooltip(baseMsg.replace('%1', newName));
|
||||
}
|
||||
},
|
||||
@@ -726,7 +726,7 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
if (topRow) {
|
||||
if (this.arguments_.length) {
|
||||
if (!this.getField('WITH')) {
|
||||
topRow.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS, 'WITH');
|
||||
topRow.appendField(Blockly.Msg['PROCEDURES_CALL_BEFORE_PARAMS'], 'WITH');
|
||||
topRow.init();
|
||||
}
|
||||
} else {
|
||||
@@ -851,7 +851,7 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
var option = {enabled: true};
|
||||
option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;
|
||||
option.text = Blockly.Msg['PROCEDURES_HIGHLIGHT_DEF'];
|
||||
var name = this.getProcedureCall();
|
||||
var workspace = this.workspace;
|
||||
option.callback = function() {
|
||||
@@ -875,9 +875,9 @@ Blockly.Blocks['procedures_callreturn'] = {
|
||||
this.appendDummyInput('TOPROW')
|
||||
.appendField('', 'NAME');
|
||||
this.setOutput(true);
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
// Tooltip is set in domToMutation.
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['PROCEDURES_CALLRETURN_HELPURL']);
|
||||
this.arguments_ = [];
|
||||
this.quarkConnections_ = {};
|
||||
this.quarkIds_ = null;
|
||||
@@ -904,15 +904,15 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
init: function() {
|
||||
this.appendValueInput('CONDITION')
|
||||
.setCheck('Boolean')
|
||||
.appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);
|
||||
.appendField(Blockly.Msg['CONTROLS_IF_MSG_IF']);
|
||||
this.appendValueInput('VALUE')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']);
|
||||
this.setInputsInline(true);
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setColour(Blockly.Msg.PROCEDURES_HUE);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_IFRETURN_HELPURL);
|
||||
this.setColour(Blockly.Msg['PROCEDURES_HUE']);
|
||||
this.setTooltip(Blockly.Msg['PROCEDURES_IFRETURN_TOOLTIP']);
|
||||
this.setHelpUrl(Blockly.Msg['PROCEDURES_IFRETURN_HELPURL']);
|
||||
this.hasReturnValue_ = true;
|
||||
},
|
||||
/**
|
||||
@@ -936,7 +936,7 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
if (!this.hasReturnValue_) {
|
||||
this.removeInput('VALUE');
|
||||
this.appendDummyInput('VALUE')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']);
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -964,13 +964,13 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) {
|
||||
this.removeInput('VALUE');
|
||||
this.appendDummyInput('VALUE')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']);
|
||||
this.hasReturnValue_ = false;
|
||||
} else if (block.type == 'procedures_defreturn' &&
|
||||
!this.hasReturnValue_) {
|
||||
this.removeInput('VALUE');
|
||||
this.appendValueInput('VALUE')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
.appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']);
|
||||
this.hasReturnValue_ = true;
|
||||
}
|
||||
this.setWarningText(null);
|
||||
@@ -978,7 +978,7 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
this.setDisabled(false);
|
||||
}
|
||||
} else {
|
||||
this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING);
|
||||
this.setWarningText(Blockly.Msg['PROCEDURES_IFRETURN_WARNING']);
|
||||
if (!this.isInFlyout && !this.getInheritedDisabled()) {
|
||||
this.setDisabled(true);
|
||||
}
|
||||
|
||||
+67
-67
@@ -33,7 +33,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.TEXTS_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['TEXTS_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Text.HUE = 160;
|
||||
|
||||
@@ -211,31 +211,31 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this['WHERE_OPTIONS_1'] = [
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST, 'FIRST']
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_START_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_START_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_START_FIRST'], 'FIRST']
|
||||
];
|
||||
this['WHERE_OPTIONS_2'] = [
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START, 'FROM_START'],
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END, 'FROM_END'],
|
||||
[Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST, 'LAST']
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_END_FROM_START'], 'FROM_START'],
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_END_FROM_END'], 'FROM_END'],
|
||||
[Blockly.Msg['TEXT_GET_SUBSTRING_END_LAST'], 'LAST']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL);
|
||||
this.setColour(Blockly.Msg.TEXTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['TEXT_GET_SUBSTRING_HELPURL']);
|
||||
this.setColour(Blockly.Msg['TEXTS_HUE']);
|
||||
this.appendValueInput('STRING')
|
||||
.setCheck('String')
|
||||
.appendField(Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT);
|
||||
.appendField(Blockly.Msg['TEXT_GET_SUBSTRING_INPUT_IN_TEXT']);
|
||||
this.appendDummyInput('AT1');
|
||||
this.appendDummyInput('AT2');
|
||||
if (Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) {
|
||||
if (Blockly.Msg['TEXT_GET_SUBSTRING_TAIL']) {
|
||||
this.appendDummyInput('TAIL')
|
||||
.appendField(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL);
|
||||
.appendField(Blockly.Msg['TEXT_GET_SUBSTRING_TAIL']);
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'String');
|
||||
this.updateAt_(1, true);
|
||||
this.updateAt_(2, true);
|
||||
this.setTooltip(Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['TEXT_GET_SUBSTRING_TOOLTIP']);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there are 'AT' inputs.
|
||||
@@ -277,18 +277,18 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
// Create either a value 'AT' input or a dummy input.
|
||||
if (isAt) {
|
||||
this.appendValueInput('AT' + n).setCheck('Number');
|
||||
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
|
||||
if (Blockly.Msg['ORDINAL_NUMBER_SUFFIX']) {
|
||||
this.appendDummyInput('ORDINAL' + n)
|
||||
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
|
||||
.appendField(Blockly.Msg['ORDINAL_NUMBER_SUFFIX']);
|
||||
}
|
||||
} else {
|
||||
this.appendDummyInput('AT' + n);
|
||||
}
|
||||
// Move tail, if present, to end of block.
|
||||
if (n == 2 && Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) {
|
||||
if (n == 2 && Blockly.Msg['TEXT_GET_SUBSTRING_TAIL']) {
|
||||
this.removeInput('TAIL', true);
|
||||
this.appendDummyInput('TAIL')
|
||||
.appendField(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL);
|
||||
.appendField(Blockly.Msg['TEXT_GET_SUBSTRING_TAIL']);
|
||||
}
|
||||
var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n],
|
||||
function(value) {
|
||||
@@ -324,17 +324,17 @@ Blockly.Blocks['text_changeCase'] = {
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS = [
|
||||
[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE, 'UPPERCASE'],
|
||||
[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE, 'LOWERCASE'],
|
||||
[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE, 'TITLECASE']
|
||||
[Blockly.Msg['TEXT_CHANGECASE_OPERATOR_UPPERCASE'], 'UPPERCASE'],
|
||||
[Blockly.Msg['TEXT_CHANGECASE_OPERATOR_LOWERCASE'], 'LOWERCASE'],
|
||||
[Blockly.Msg['TEXT_CHANGECASE_OPERATOR_TITLECASE'], 'TITLECASE']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_CHANGECASE_HELPURL);
|
||||
this.setColour(Blockly.Msg.TEXTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['TEXT_CHANGECASE_HELPURL']);
|
||||
this.setColour(Blockly.Msg['TEXTS_HUE']);
|
||||
this.appendValueInput('TEXT')
|
||||
.setCheck('String')
|
||||
.appendField(new Blockly.FieldDropdown(OPERATORS), 'CASE');
|
||||
this.setOutput(true, 'String');
|
||||
this.setTooltip(Blockly.Msg.TEXT_CHANGECASE_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['TEXT_CHANGECASE_TOOLTIP']);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -345,17 +345,17 @@ Blockly.Blocks['text_trim'] = {
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS = [
|
||||
[Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH, 'BOTH'],
|
||||
[Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT, 'LEFT'],
|
||||
[Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT, 'RIGHT']
|
||||
[Blockly.Msg['TEXT_TRIM_OPERATOR_BOTH'], 'BOTH'],
|
||||
[Blockly.Msg['TEXT_TRIM_OPERATOR_LEFT'], 'LEFT'],
|
||||
[Blockly.Msg['TEXT_TRIM_OPERATOR_RIGHT'], 'RIGHT']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_TRIM_HELPURL);
|
||||
this.setColour(Blockly.Msg.TEXTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['TEXT_TRIM_HELPURL']);
|
||||
this.setColour(Blockly.Msg['TEXTS_HUE']);
|
||||
this.appendValueInput('TEXT')
|
||||
.setCheck('String')
|
||||
.appendField(new Blockly.FieldDropdown(OPERATORS), 'MODE');
|
||||
this.setOutput(true, 'String');
|
||||
this.setTooltip(Blockly.Msg.TEXT_TRIM_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['TEXT_TRIM_TOOLTIP']);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -366,7 +366,7 @@ Blockly.Blocks['text_print'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.TEXT_PRINT_TITLE,
|
||||
"message0": Blockly.Msg['TEXT_PRINT_TITLE'],
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
@@ -375,9 +375,9 @@ Blockly.Blocks['text_print'] = {
|
||||
],
|
||||
"previousStatement": null,
|
||||
"nextStatement": null,
|
||||
"colour": Blockly.Msg.TEXTS_HUE,
|
||||
"tooltip": Blockly.Msg.TEXT_PRINT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.TEXT_PRINT_HELPURL
|
||||
"colour": Blockly.Msg['TEXTS_HUE'],
|
||||
"tooltip": Blockly.Msg['TEXT_PRINT_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['TEXT_PRINT_HELPURL']
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -389,11 +389,11 @@ Blockly.Blocks['text_prompt_ext'] = {
|
||||
*/
|
||||
init: function() {
|
||||
var TYPES = [
|
||||
[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'],
|
||||
[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER, 'NUMBER']
|
||||
[Blockly.Msg['TEXT_PROMPT_TYPE_TEXT'], 'TEXT'],
|
||||
[Blockly.Msg['TEXT_PROMPT_TYPE_NUMBER'], 'NUMBER']
|
||||
];
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL);
|
||||
this.setColour(Blockly.Msg.TEXTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['TEXT_PROMPT_HELPURL']);
|
||||
this.setColour(Blockly.Msg['TEXTS_HUE']);
|
||||
// Assign 'this' to a variable for use in the closures below.
|
||||
var thisBlock = this;
|
||||
var dropdown = new Blockly.FieldDropdown(TYPES, function(newOp) {
|
||||
@@ -404,8 +404,8 @@ Blockly.Blocks['text_prompt_ext'] = {
|
||||
this.setOutput(true, 'String');
|
||||
this.setTooltip(function() {
|
||||
return (thisBlock.getFieldValue('TYPE') == 'TEXT') ?
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT :
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER;
|
||||
Blockly.Msg['TEXT_PROMPT_TOOLTIP_TEXT'] :
|
||||
Blockly.Msg['TEXT_PROMPT_TOOLTIP_NUMBER'];
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -446,14 +446,14 @@ Blockly.Blocks['text_prompt'] = {
|
||||
init: function() {
|
||||
this.mixin(Blockly.Constants.Text.QUOTE_IMAGE_MIXIN);
|
||||
var TYPES = [
|
||||
[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'],
|
||||
[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER, 'NUMBER']
|
||||
[Blockly.Msg['TEXT_PROMPT_TYPE_TEXT'], 'TEXT'],
|
||||
[Blockly.Msg['TEXT_PROMPT_TYPE_NUMBER'], 'NUMBER']
|
||||
];
|
||||
|
||||
// Assign 'this' to a variable for use in the closures below.
|
||||
var thisBlock = this;
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL);
|
||||
this.setColour(Blockly.Msg.TEXTS_HUE);
|
||||
this.setHelpUrl(Blockly.Msg['TEXT_PROMPT_HELPURL']);
|
||||
this.setColour(Blockly.Msg['TEXTS_HUE']);
|
||||
var dropdown = new Blockly.FieldDropdown(TYPES, function(newOp) {
|
||||
thisBlock.updateType_(newOp);
|
||||
});
|
||||
@@ -465,8 +465,8 @@ Blockly.Blocks['text_prompt'] = {
|
||||
this.setOutput(true, 'String');
|
||||
this.setTooltip(function() {
|
||||
return (thisBlock.getFieldValue('TYPE') == 'TEXT') ?
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT :
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER;
|
||||
Blockly.Msg['TEXT_PROMPT_TOOLTIP_TEXT'] :
|
||||
Blockly.Msg['TEXT_PROMPT_TOOLTIP_NUMBER'];
|
||||
});
|
||||
},
|
||||
updateType_: Blockly.Blocks['text_prompt_ext'].updateType_,
|
||||
@@ -481,7 +481,7 @@ Blockly.Blocks['text_count'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.TEXT_COUNT_MESSAGE0,
|
||||
"message0": Blockly.Msg['TEXT_COUNT_MESSAGE0'],
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
@@ -496,9 +496,9 @@ Blockly.Blocks['text_count'] = {
|
||||
],
|
||||
"output": "Number",
|
||||
"inputsInline": true,
|
||||
"colour": Blockly.Msg.TEXTS_HUE,
|
||||
"tooltip": Blockly.Msg.TEXT_COUNT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.TEXT_COUNT_HELPURL
|
||||
"colour": Blockly.Msg['TEXTS_HUE'],
|
||||
"tooltip": Blockly.Msg['TEXT_COUNT_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['TEXT_COUNT_HELPURL']
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -510,7 +510,7 @@ Blockly.Blocks['text_replace'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.TEXT_REPLACE_MESSAGE0,
|
||||
"message0": Blockly.Msg['TEXT_REPLACE_MESSAGE0'],
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
@@ -530,9 +530,9 @@ Blockly.Blocks['text_replace'] = {
|
||||
],
|
||||
"output": "String",
|
||||
"inputsInline": true,
|
||||
"colour": Blockly.Msg.TEXTS_HUE,
|
||||
"tooltip": Blockly.Msg.TEXT_REPLACE_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.TEXT_REPLACE_HELPURL
|
||||
"colour": Blockly.Msg['TEXTS_HUE'],
|
||||
"tooltip": Blockly.Msg['TEXT_REPLACE_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['TEXT_REPLACE_HELPURL']
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -544,7 +544,7 @@ Blockly.Blocks['text_reverse'] = {
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.TEXT_REVERSE_MESSAGE0,
|
||||
"message0": Blockly.Msg['TEXT_REVERSE_MESSAGE0'],
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
@@ -554,9 +554,9 @@ Blockly.Blocks['text_reverse'] = {
|
||||
],
|
||||
"output": "String",
|
||||
"inputsInline": true,
|
||||
"colour": Blockly.Msg.TEXTS_HUE,
|
||||
"tooltip": Blockly.Msg.TEXT_REVERSE_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.TEXT_REVERSE_HELPURL
|
||||
"colour": Blockly.Msg['TEXTS_HUE'],
|
||||
"tooltip": Blockly.Msg['TEXT_REVERSE_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['TEXT_REVERSE_HELPURL']
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -626,7 +626,7 @@ Blockly.Constants.Text.QUOTE_IMAGE_MIXIN = {
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
newQuote_: function(open) {
|
||||
var isLeft = this.RTL? !open : open;
|
||||
var isLeft = this.RTL ? !open : open;
|
||||
var dataUri = isLeft ?
|
||||
this.QUOTE_IMAGE_LEFT_DATAURI :
|
||||
this.QUOTE_IMAGE_RIGHT_DATAURI;
|
||||
@@ -753,7 +753,7 @@ Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN = {
|
||||
if (!this.getInput('ADD' + i)) {
|
||||
var input = this.appendValueInput('ADD' + i);
|
||||
if (i == 0) {
|
||||
input.appendField(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH);
|
||||
input.appendField(Blockly.Msg['TEXT_JOIN_TITLE_CREATEWITH']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -792,7 +792,7 @@ Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION = function() {
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
return Blockly.Msg.TEXT_INDEXOF_TOOLTIP.replace('%1',
|
||||
return Blockly.Msg['TEXT_INDEXOF_TOOLTIP'].replace('%1',
|
||||
thisBlock.workspace.options.oneBasedIndex ? '0' : '-1');
|
||||
});
|
||||
};
|
||||
@@ -838,15 +838,15 @@ Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = {
|
||||
// Create either a value 'AT' input or a dummy input.
|
||||
if (isAt) {
|
||||
this.appendValueInput('AT').setCheck('Number');
|
||||
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
|
||||
if (Blockly.Msg['ORDINAL_NUMBER_SUFFIX']) {
|
||||
this.appendDummyInput('ORDINAL')
|
||||
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
|
||||
.appendField(Blockly.Msg['ORDINAL_NUMBER_SUFFIX']);
|
||||
}
|
||||
}
|
||||
if (Blockly.Msg.TEXT_CHARAT_TAIL) {
|
||||
if (Blockly.Msg['TEXT_CHARAT_TAIL']) {
|
||||
this.removeInput('TAIL', true);
|
||||
this.appendDummyInput('TAIL')
|
||||
.appendField(Blockly.Msg.TEXT_CHARAT_TAIL);
|
||||
.appendField(Blockly.Msg['TEXT_CHARAT_TAIL']);
|
||||
}
|
||||
|
||||
this.isAt_ = isAt;
|
||||
@@ -875,11 +875,11 @@ Blockly.Constants.Text.TEXT_CHARAT_EXTENSION = function() {
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
var where = thisBlock.getFieldValue('WHERE');
|
||||
var tooltip = Blockly.Msg.TEXT_CHARAT_TOOLTIP;
|
||||
var tooltip = Blockly.Msg['TEXT_CHARAT_TOOLTIP'];
|
||||
if (where == 'FROM_START' || where == 'FROM_END') {
|
||||
var msg = (where == 'FROM_START') ?
|
||||
Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP :
|
||||
Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP;
|
||||
Blockly.Msg['LISTS_INDEX_FROM_START_TOOLTIP'] :
|
||||
Blockly.Msg['LISTS_INDEX_FROM_END_TOOLTIP'];
|
||||
if (msg) {
|
||||
tooltip += ' ' + msg.replace('%1',
|
||||
thisBlock.workspace.options.oneBasedIndex ? '#1' : '#0');
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.VARIABLES_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['VARIABLES_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.Variables.HUE = 330;
|
||||
|
||||
@@ -106,10 +106,10 @@ Blockly.Constants.Variables.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
// Getter blocks have the option to create a setter block, and vice versa.
|
||||
if (this.type == 'variables_get') {
|
||||
var opposite_type = 'variables_set';
|
||||
var contextMenuMsg = Blockly.Msg.VARIABLES_GET_CREATE_SET;
|
||||
var contextMenuMsg = Blockly.Msg['VARIABLES_GET_CREATE_SET'];
|
||||
} else {
|
||||
var opposite_type = 'variables_get';
|
||||
var contextMenuMsg = Blockly.Msg.VARIABLES_SET_CREATE_GET;
|
||||
var contextMenuMsg = Blockly.Msg['VARIABLES_SET_CREATE_GET'];
|
||||
}
|
||||
|
||||
var option = {enabled: this.workspace.remainingCapacity() > 0};
|
||||
|
||||
@@ -37,7 +37,7 @@ goog.require('Blockly');
|
||||
|
||||
/**
|
||||
* Unused constant for the common HSV hue for all blocks in this category.
|
||||
* @deprecated Use Blockly.Msg.VARIABLES_DYNAMIC_HUE. (2018 April 5)
|
||||
* @deprecated Use Blockly.Msg['VARIABLES_DYNAMIC_HUE']. (2018 April 5)
|
||||
*/
|
||||
Blockly.Constants.VariablesDynamic.HUE = 310;
|
||||
|
||||
@@ -104,10 +104,10 @@ Blockly.Constants.VariablesDynamic.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MI
|
||||
var contextMenuMsg;
|
||||
if (this.type == 'variables_get_dynamic') {
|
||||
opposite_type = 'variables_set_dynamic';
|
||||
contextMenuMsg = Blockly.Msg.VARIABLES_GET_CREATE_SET;
|
||||
contextMenuMsg = Blockly.Msg['VARIABLES_GET_CREATE_SET'];
|
||||
} else {
|
||||
opposite_type = 'variables_get_dynamic';
|
||||
contextMenuMsg = Blockly.Msg.VARIABLES_SET_CREATE_GET;
|
||||
contextMenuMsg = Blockly.Msg['VARIABLES_SET_CREATE_GET'];
|
||||
}
|
||||
|
||||
var option = {enabled: this.workspace.remainingCapacity() > 0};
|
||||
|
||||
@@ -41,7 +41,7 @@ Blockly.Blocks.lists_split={init:function(){var a=this,b=new Blockly.FieldDropdo
|
||||
this.getFieldValue("MODE"));return a},domToMutation:function(a){this.updateType_(a.getAttribute("mode"))}};Blockly.Blocks.logic={};Blockly.Constants.Logic={};Blockly.Constants.Logic.HUE=210;
|
||||
Blockly.defineBlocksWithJsonArray([{type:"logic_boolean",message0:"%1",args0:[{type:"field_dropdown",name:"BOOL",options:[["%{BKY_LOGIC_BOOLEAN_TRUE}","TRUE"],["%{BKY_LOGIC_BOOLEAN_FALSE}","FALSE"]]}],output:"Boolean",colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKY_LOGIC_BOOLEAN_TOOLTIP}",helpUrl:"%{BKY_LOGIC_BOOLEAN_HELPURL}"},{type:"controls_if",message0:"%{BKY_CONTROLS_IF_MSG_IF} %1",args0:[{type:"input_value",name:"IF0",check:"Boolean"}],message1:"%{BKY_CONTROLS_IF_MSG_THEN} %1",args1:[{type:"input_statement",
|
||||
name:"DO0"}],previousStatement:null,nextStatement:null,colour:"%{BKY_LOGIC_HUE}",helpUrl:"%{BKY_CONTROLS_IF_HELPURL}",mutator:"controls_if_mutator",extensions:["controls_if_tooltip"]},{type:"controls_ifelse",message0:"%{BKY_CONTROLS_IF_MSG_IF} %1",args0:[{type:"input_value",name:"IF0",check:"Boolean"}],message1:"%{BKY_CONTROLS_IF_MSG_THEN} %1",args1:[{type:"input_statement",name:"DO0"}],message2:"%{BKY_CONTROLS_IF_MSG_ELSE} %1",args2:[{type:"input_statement",name:"ELSE"}],previousStatement:null,nextStatement:null,
|
||||
colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKYCONTROLS_IF_TOOLTIP_2}",helpUrl:"%{BKY_CONTROLS_IF_HELPURL}",extensions:["controls_if_tooltip"]},{type:"logic_compare",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A"},{type:"field_dropdown",name:"OP",options:[["=","EQ"],["\u2260","NEQ"],["<","LT"],["\u2264","LTE"],[">","GT"],["\u2265","GTE"]]},{type:"input_value",name:"B"}],inputsInline:!0,output:"Boolean",colour:"%{BKY_LOGIC_HUE}",helpUrl:"%{BKY_LOGIC_COMPARE_HELPURL}",extensions:["logic_compare",
|
||||
colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKYCONTROLS_IF_TOOLTIP_2}",helpUrl:"%{BKY_CONTROLS_IF_HELPURL}",extensions:["controls_if_tooltip"]},{type:"logic_compare",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A"},{type:"field_dropdown",name:"OP",options:[["=","EQ"],["\u2260","NEQ"],["\u200f<","LT"],["\u200f\u2264","LTE"],["\u200f>","GT"],["\u200f\u2265","GTE"]]},{type:"input_value",name:"B"}],inputsInline:!0,output:"Boolean",colour:"%{BKY_LOGIC_HUE}",helpUrl:"%{BKY_LOGIC_COMPARE_HELPURL}",extensions:["logic_compare",
|
||||
"logic_op_tooltip"]},{type:"logic_operation",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Boolean"},{type:"field_dropdown",name:"OP",options:[["%{BKY_LOGIC_OPERATION_AND}","AND"],["%{BKY_LOGIC_OPERATION_OR}","OR"]]},{type:"input_value",name:"B",check:"Boolean"}],inputsInline:!0,output:"Boolean",colour:"%{BKY_LOGIC_HUE}",helpUrl:"%{BKY_LOGIC_OPERATION_HELPURL}",extensions:["logic_op_tooltip"]},{type:"logic_negate",message0:"%{BKY_LOGIC_NEGATE_TITLE}",args0:[{type:"input_value",name:"BOOL",
|
||||
check:"Boolean"}],output:"Boolean",colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKY_LOGIC_NEGATE_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NEGATE_HELPURL}"},{type:"logic_null",message0:"%{BKY_LOGIC_NULL}",output:null,colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKY_LOGIC_NULL_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NULL_HELPURL}"},{type:"logic_ternary",message0:"%{BKY_LOGIC_TERNARY_CONDITION} %1",args0:[{type:"input_value",name:"IF",check:"Boolean"}],message1:"%{BKY_LOGIC_TERNARY_IF_TRUE} %1",args1:[{type:"input_value",name:"THEN"}],
|
||||
message2:"%{BKY_LOGIC_TERNARY_IF_FALSE} %1",args2:[{type:"input_value",name:"ELSE"}],output:null,colour:"%{BKY_LOGIC_HUE}",tooltip:"%{BKY_LOGIC_TERNARY_TOOLTIP}",helpUrl:"%{BKY_LOGIC_TERNARY_HELPURL}",extensions:["logic_ternary"]}]);
|
||||
@@ -54,9 +54,8 @@ break;case "controls_if_else":this.elseCount_++;d=b.statementConnection_;break;d
|
||||
b);a.valueConnection_=c&&c.connection.targetConnection;a.statementConnection_=d&&d.connection.targetConnection;b++;break;case "controls_if_else":d=this.getInput("ELSE");a.statementConnection_=d&&d.connection.targetConnection;break;default:throw"Unknown block type.";}a=a.nextConnection&&a.nextConnection.targetBlock()}},updateShape_:function(){this.getInput("ELSE")&&this.removeInput("ELSE");for(var a=1;this.getInput("IF"+a);)this.removeInput("IF"+a),this.removeInput("DO"+a),a++;for(a=1;a<=this.elseifCount_;a++)this.appendValueInput("IF"+
|
||||
a).setCheck("Boolean").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+a).appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);this.elseCount_&&this.appendStatementInput("ELSE").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE)}};Blockly.Extensions.registerMutator("controls_if_mutator",Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN,null,["controls_if_elseif","controls_if_else"]);
|
||||
Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION=function(){this.setTooltip(function(){if(this.elseifCount_||this.elseCount_){if(!this.elseifCount_&&this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;if(this.elseifCount_&&!this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;if(this.elseifCount_&&this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_4}else return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;return""}.bind(this))};Blockly.Extensions.register("controls_if_tooltip",Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION);
|
||||
Blockly.Constants.Logic.fixLogicCompareRtlOpLabels=function(){var a={LT:"\u200f<\u200f",LTE:"\u200f\u2264\u200f",GT:"\u200f>\u200f",GTE:"\u200f\u2265\u200f"},b=this.getField("OP");if(b){b=b.getOptions();for(var c=0;c<b.length;++c){var d=b[c],e=a[d[1]];goog.isString(d[0])&&e&&(d[0]=e)}}};
|
||||
Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN={onchange:function(a){this.prevBlocks_||(this.prevBlocks_=[null,null]);var b=this.getInputTargetBlock("A"),c=this.getInputTargetBlock("B");b&&c&&!b.outputConnection.checkType_(c.outputConnection)&&(Blockly.Events.setGroup(a.group),a=this.prevBlocks_[0],a!==b&&(b.unplug(),a&&!a.isShadow()&&this.getInput("A").connection.connect(a.outputConnection)),b=this.prevBlocks_[1],b!==c&&(c.unplug(),b&&!b.isShadow()&&this.getInput("B").connection.connect(b.outputConnection)),
|
||||
this.bumpNeighbours_(),Blockly.Events.setGroup(!1));this.prevBlocks_[0]=this.getInputTargetBlock("A");this.prevBlocks_[1]=this.getInputTargetBlock("B")}};Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION=function(){this.RTL&&Blockly.Constants.Logic.fixLogicCompareRtlOpLabels.apply(this);this.mixin(Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN)};Blockly.Extensions.register("logic_compare",Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION);
|
||||
this.bumpNeighbours_(),Blockly.Events.setGroup(!1));this.prevBlocks_[0]=this.getInputTargetBlock("A");this.prevBlocks_[1]=this.getInputTargetBlock("B")}};Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION=function(){this.mixin(Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN)};Blockly.Extensions.register("logic_compare",Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION);
|
||||
Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN={prevParentConnection_:null,onchange:function(a){var b=this.getInputTargetBlock("THEN"),c=this.getInputTargetBlock("ELSE"),d=this.outputConnection.targetConnection;if((b||c)&&d)for(var e=0;2>e;e++){var f=1==e?b:c;f&&!f.outputConnection.checkType_(d)&&(Blockly.Events.setGroup(a.group),d===this.prevParentConnection_?(this.unplug(),d.getSourceBlock().bumpNeighbours_()):(f.unplug(),f.bumpNeighbours_()),Blockly.Events.setGroup(!1))}this.prevParentConnection_=
|
||||
d}};Blockly.Extensions.registerMixin("logic_ternary",Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN);Blockly.Blocks.loops={};Blockly.Constants.Loops={};Blockly.Constants.Loops.HUE=120;
|
||||
Blockly.defineBlocksWithJsonArray([{type:"controls_repeat_ext",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"input_value",name:"TIMES",check:"Number"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,colour:"%{BKY_LOOPS_HUE}",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_repeat",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"field_number",name:"TIMES",
|
||||
|
||||
+44
-20
@@ -87,13 +87,13 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
|
||||
|
||||
/**
|
||||
* @type {Blockly.Block}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.parentBlock_ = null;
|
||||
|
||||
/**
|
||||
* @type {!Array.<!Blockly.Block>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.childBlocks_ = [];
|
||||
|
||||
@@ -123,7 +123,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.collapsed_ = false;
|
||||
|
||||
@@ -259,6 +259,10 @@ Blockly.Block.prototype.dispose = function(healStack) {
|
||||
// well as corruption of the connection database. Therefore we must
|
||||
// methodically step through the blocks and carefully disassemble them.
|
||||
|
||||
if (Blockly.selected == this) {
|
||||
Blockly.selected = null;
|
||||
}
|
||||
|
||||
// First, dispose of all my children.
|
||||
for (var i = this.childBlocks_.length - 1; i >= 0; i--) {
|
||||
this.childBlocks_[i].dispose(false);
|
||||
@@ -365,7 +369,7 @@ Blockly.Block.prototype.getConnections_ = function(_all) {
|
||||
* @return {Blockly.Connection} The last next connection on the stack, or null.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Block.prototype.lastConnectionInStack_ = function() {
|
||||
Blockly.Block.prototype.lastConnectionInStack = function() {
|
||||
var nextConnection = this.nextConnection;
|
||||
while (nextConnection) {
|
||||
var nextBlock = nextConnection.targetBlock();
|
||||
@@ -382,7 +386,7 @@ Blockly.Block.prototype.lastConnectionInStack_ = function() {
|
||||
/**
|
||||
* Bump unconnected blocks out of alignment. Two blocks which aren't actually
|
||||
* connected should not coincidentally line up on screen.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Block.prototype.bumpNeighbours_ = function() {
|
||||
console.warn('Not expected to reach this bumpNeighbours_ function. The ' +
|
||||
@@ -457,12 +461,30 @@ Blockly.Block.prototype.getRootBlock = function() {
|
||||
|
||||
/**
|
||||
* Find all the blocks that are directly nested inside this one.
|
||||
* Includes value and block inputs, as well as any following statement.
|
||||
* Includes value and statement inputs, as well as any following statement.
|
||||
* Excludes any connection on an output tab or any preceding statement.
|
||||
* Blocks are optionally sorted by position; top to bottom.
|
||||
* @param {boolean} ordered Sort the list if true.
|
||||
* @return {!Array.<!Blockly.Block>} Array of blocks.
|
||||
*/
|
||||
Blockly.Block.prototype.getChildren = function() {
|
||||
return this.childBlocks_;
|
||||
Blockly.Block.prototype.getChildren = function(ordered) {
|
||||
if (!ordered) {
|
||||
return this.childBlocks_;
|
||||
}
|
||||
var blocks = [];
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
if (input.connection) {
|
||||
var child = input.connection.targetBlock();
|
||||
if (child) {
|
||||
blocks.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
var next = this.getNextBlock();
|
||||
if (next) {
|
||||
blocks.push(next);
|
||||
}
|
||||
return blocks;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -504,14 +526,17 @@ Blockly.Block.prototype.setParent = function(newParent) {
|
||||
/**
|
||||
* Find all the blocks that are directly or indirectly nested inside this one.
|
||||
* Includes this block in the list.
|
||||
* Includes value and block inputs, as well as any following statements.
|
||||
* Includes value and statement inputs, as well as any following statements.
|
||||
* Excludes any connection on an output tab or any preceding statements.
|
||||
* Blocks are optionally sorted by position; top to bottom.
|
||||
* @param {boolean} ordered Sort the list if true.
|
||||
* @return {!Array.<!Blockly.Block>} Flattened array of blocks.
|
||||
*/
|
||||
Blockly.Block.prototype.getDescendants = function() {
|
||||
Blockly.Block.prototype.getDescendants = function(ordered) {
|
||||
var blocks = [this];
|
||||
for (var child, x = 0; child = this.childBlocks_[x]; x++) {
|
||||
blocks.push.apply(blocks, child.getDescendants());
|
||||
var childBlocks = this.getChildren(ordered);
|
||||
for (var child, i = 0; child = childBlocks[i]; i++) {
|
||||
blocks.push.apply(blocks, child.getDescendants(ordered));
|
||||
}
|
||||
return blocks;
|
||||
};
|
||||
@@ -730,7 +755,7 @@ Blockly.Block.prototype.getVars = function() {
|
||||
var vars = [];
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldVariable) {
|
||||
if (field.referencesVariables()) {
|
||||
vars.push(field.getValue());
|
||||
}
|
||||
}
|
||||
@@ -747,7 +772,7 @@ Blockly.Block.prototype.getVarModels = function() {
|
||||
var vars = [];
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldVariable) {
|
||||
if (field.referencesVariables()) {
|
||||
var model = this.workspace.getVariableById(field.getValue());
|
||||
// Check if the variable actually exists (and isn't just a potential
|
||||
// variable).
|
||||
@@ -769,7 +794,7 @@ Blockly.Block.prototype.getVarModels = function() {
|
||||
Blockly.Block.prototype.updateVarName = function(variable) {
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldVariable &&
|
||||
if (field.referencesVariables() &&
|
||||
variable.getId() == field.getValue()) {
|
||||
field.setText(variable.name);
|
||||
}
|
||||
@@ -787,7 +812,7 @@ Blockly.Block.prototype.updateVarName = function(variable) {
|
||||
Blockly.Block.prototype.renameVarById = function(oldId, newId) {
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldVariable &&
|
||||
if (field.referencesVariables() &&
|
||||
oldId == field.getValue()) {
|
||||
field.setValue(newId);
|
||||
}
|
||||
@@ -1125,8 +1150,8 @@ Blockly.Block.prototype.jsonInit = function(json) {
|
||||
|
||||
if (Array.isArray(json['extensions'])) {
|
||||
var extensionNames = json['extensions'];
|
||||
for (var i = 0; i < extensionNames.length; ++i) {
|
||||
var extensionName = extensionNames[i];
|
||||
for (var j = 0; j < extensionNames.length; ++j) {
|
||||
var extensionName = extensionNames[j];
|
||||
Blockly.Extensions.apply(extensionName, this, false);
|
||||
}
|
||||
}
|
||||
@@ -1261,7 +1286,6 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) {
|
||||
case 'input_dummy':
|
||||
input = this.appendDummyInput(element['name']);
|
||||
break;
|
||||
|
||||
default:
|
||||
field = Blockly.Field.fromJson(element);
|
||||
|
||||
@@ -1305,7 +1329,7 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) {
|
||||
* @param {string} name Language-neutral identifier which may used to find this
|
||||
* input again. Should be unique to this block.
|
||||
* @return {!Blockly.Input} The input object created.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Block.prototype.appendInput_ = function(type, name) {
|
||||
var connection = null;
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2018 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 Methods animating a block on connection and disconnection.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BlockAnimations');
|
||||
|
||||
|
||||
/**
|
||||
* PID of disconnect UI animation. There can only be one at a time.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockAnimations.disconnectPid_ = 0;
|
||||
|
||||
/**
|
||||
* SVG group of wobbling block. There can only be one at a time.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockAnimations.disconnectGroup_ = null;
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, animation) when disposing of a block.
|
||||
* @param {!Blockly.BlockSvg} block The block being disposed of.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BlockAnimations.disposeUiEffect = function(block) {
|
||||
var workspace = block.workspace;
|
||||
var svgGroup = block.getSvgRoot();
|
||||
workspace.getAudioManager().play('delete');
|
||||
|
||||
var xy = workspace.getSvgXY(svgGroup);
|
||||
// Deeply clone the current block.
|
||||
var clone = svgGroup.cloneNode(true);
|
||||
clone.translateX_ = xy.x;
|
||||
clone.translateY_ = xy.y;
|
||||
clone.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')');
|
||||
workspace.getParentSvg().appendChild(clone);
|
||||
clone.bBox_ = clone.getBBox();
|
||||
// Start the animation.
|
||||
Blockly.BlockAnimations.disposeUiStep_(clone, workspace.RTL, new Date,
|
||||
workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Animate a cloned block and eventually dispose of it.
|
||||
* This is a class method, not an instance method since the original block has
|
||||
* been destroyed and is no longer accessible.
|
||||
* @param {!Element} clone SVG element to animate and dispose of.
|
||||
* @param {boolean} rtl True if RTL, false if LTR.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockAnimations.disposeUiStep_ = function(clone, rtl, start,
|
||||
workspaceScale) {
|
||||
var ms = new Date - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(clone);
|
||||
} else {
|
||||
var x = clone.translateX_ +
|
||||
(rtl ? -1 : 1) * clone.bBox_.width * workspaceScale / 2 * percent;
|
||||
var y = clone.translateY_ + clone.bBox_.height * workspaceScale * percent;
|
||||
var scale = (1 - percent) * workspaceScale;
|
||||
clone.setAttribute('transform', 'translate(' + x + ',' + y + ')' +
|
||||
' scale(' + scale + ')');
|
||||
setTimeout(Blockly.BlockAnimations.disposeUiStep_, 10, clone, rtl, start,
|
||||
workspaceScale);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, ripple) after a connection has been established.
|
||||
* @param {!Blockly.BlockSvg} block The block being connected.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BlockAnimations.connectionUiEffect = function(block) {
|
||||
var workspace = block.workspace;
|
||||
var scale = workspace.scale;
|
||||
workspace.getAudioManager().play('click');
|
||||
if (scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Determine the absolute coordinates of the inferior block.
|
||||
var xy = workspace.getSvgXY(block.getSvgRoot());
|
||||
// Offset the coordinates based on the two connection types, fix scale.
|
||||
if (block.outputConnection) {
|
||||
xy.x += (block.RTL ? 3 : -3) * scale;
|
||||
xy.y += 13 * scale;
|
||||
} else if (block.previousConnection) {
|
||||
xy.x += (block.RTL ? -23 : 23) * scale;
|
||||
xy.y += 3 * scale;
|
||||
}
|
||||
var ripple = Blockly.utils.createSvgElement('circle',
|
||||
{
|
||||
'cx': xy.x,
|
||||
'cy': xy.y,
|
||||
'r': 0,
|
||||
'fill': 'none',
|
||||
'stroke': '#888',
|
||||
'stroke-width': 10
|
||||
},
|
||||
workspace.getParentSvg());
|
||||
// Start the animation.
|
||||
Blockly.BlockAnimations.connectionUiStep_(ripple, new Date, scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a ripple around a connection.
|
||||
* @param {!Element} ripple Element to animate.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} scale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockAnimations.connectionUiStep_ = function(ripple, start, scale) {
|
||||
var ms = new Date - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(ripple);
|
||||
} else {
|
||||
ripple.setAttribute('r', percent * 25 * scale);
|
||||
ripple.style.opacity = 1 - percent;
|
||||
Blockly.BlockAnimations.disconnectPid_ = setTimeout(
|
||||
Blockly.BlockAnimations.connectionUiStep_, 10, ripple, start, scale);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, animation) when disconnecting a block.
|
||||
* @param {!Blockly.BlockSvg} block The block being disconnected.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BlockAnimations.disconnectUiEffect = function(block) {
|
||||
block.workspace.getAudioManager().play('disconnect');
|
||||
if (block.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Horizontal distance for bottom of block to wiggle.
|
||||
var DISPLACEMENT = 10;
|
||||
// Scale magnitude of skew to height of block.
|
||||
var height = block.getHeightWidth().height;
|
||||
var magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180;
|
||||
if (!block.RTL) {
|
||||
magnitude *= -1;
|
||||
}
|
||||
// Start the animation.
|
||||
Blockly.BlockAnimations.disconnectUiStep_(
|
||||
block.getSvgRoot(), magnitude, new Date);
|
||||
};
|
||||
/**
|
||||
* Animate a brief wiggle of a disconnected block.
|
||||
* @param {!Element} group SVG element to animate.
|
||||
* @param {number} magnitude Maximum degrees skew (reversed for RTL).
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockAnimations.disconnectUiStep_ = function(group, magnitude, start) {
|
||||
var DURATION = 200; // Milliseconds.
|
||||
var WIGGLES = 3; // Half oscillations.
|
||||
|
||||
var ms = new Date - start;
|
||||
var percent = ms / DURATION;
|
||||
|
||||
if (percent > 1) {
|
||||
group.skew_ = '';
|
||||
} else {
|
||||
var skew = Math.round(
|
||||
Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude);
|
||||
group.skew_ = 'skewX(' + skew + ')';
|
||||
Blockly.BlockAnimations.disconnectGroup_ = group;
|
||||
Blockly.BlockAnimations.disconnectPid_ =
|
||||
setTimeout(Blockly.BlockAnimations.disconnectUiStep_, 10, group,
|
||||
magnitude, start);
|
||||
}
|
||||
group.setAttribute('transform', group.translate_ + group.skew_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop the disconnect UI animation immediately.
|
||||
* @package
|
||||
*/
|
||||
Blockly.BlockAnimations.disconnectUiStop = function() {
|
||||
if (Blockly.BlockAnimations.disconnectGroup_) {
|
||||
clearTimeout(Blockly.BlockAnimations.disconnectPid_);
|
||||
var group = Blockly.BlockAnimations.disconnectGroup_;
|
||||
group.skew_ = '';
|
||||
group.setAttribute('transform', group.translate_);
|
||||
Blockly.BlockAnimations.disconnectGroup_ = null;
|
||||
}
|
||||
};
|
||||
@@ -135,7 +135,7 @@ Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function(x, y, sc
|
||||
var fixedX = x.toFixed(0);
|
||||
var fixedY = y.toFixed(0);
|
||||
this.dragGroup_.setAttribute('transform',
|
||||
'translate('+ fixedX + ','+ fixedY + ') scale(' + scale + ')');
|
||||
'translate(' + fixedX + ',' + fixedY + ') scale(' + scale + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+12
-7
@@ -26,6 +26,7 @@
|
||||
|
||||
goog.provide('Blockly.BlockDragger');
|
||||
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.DraggedConnectionManager');
|
||||
goog.require('Blockly.Events.BlockMove');
|
||||
|
||||
@@ -124,7 +125,7 @@ Blockly.BlockDragger.prototype.dispose = function() {
|
||||
Blockly.BlockDragger.initIconData_ = function(block) {
|
||||
// Build a list of icons that need to be moved and where they started.
|
||||
var dragIconData = [];
|
||||
var descendants = block.getDescendants();
|
||||
var descendants = block.getDescendants(false);
|
||||
for (var i = 0, descendant; descendant = descendants[i]; i++) {
|
||||
var icons = descendant.getIcons();
|
||||
for (var j = 0; j < icons.length; j++) {
|
||||
@@ -153,7 +154,7 @@ Blockly.BlockDragger.prototype.startBlockDrag = function(currentDragDeltaXY, hea
|
||||
}
|
||||
|
||||
this.workspace_.setResizesEnabled(false);
|
||||
Blockly.BlockSvg.disconnectUiStop_();
|
||||
Blockly.BlockAnimations.disconnectUiStop();
|
||||
|
||||
if (this.draggingBlock_.getParent() ||
|
||||
(healStack && this.draggingBlock_.nextConnection &&
|
||||
@@ -163,7 +164,7 @@ Blockly.BlockDragger.prototype.startBlockDrag = function(currentDragDeltaXY, hea
|
||||
var newLoc = goog.math.Coordinate.sum(this.startXY_, delta);
|
||||
|
||||
this.draggingBlock_.translate(newLoc.x, newLoc.y);
|
||||
this.draggingBlock_.disconnectUiEffect();
|
||||
Blockly.BlockAnimations.disconnectUiEffect(this.draggingBlock_);
|
||||
}
|
||||
this.draggingBlock_.setDragging(true);
|
||||
// For future consideration: we may be able to put moveToDragSurface inside
|
||||
@@ -212,7 +213,7 @@ Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) {
|
||||
this.dragBlock(e, currentDragDeltaXY);
|
||||
this.dragIconData_ = [];
|
||||
|
||||
Blockly.BlockSvg.disconnectUiStop_();
|
||||
Blockly.BlockAnimations.disconnectUiStop();
|
||||
|
||||
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
|
||||
var newLoc = goog.math.Coordinate.sum(this.startXY_, delta);
|
||||
@@ -223,9 +224,13 @@ Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) {
|
||||
// These are expensive and don't need to be done if we're deleting.
|
||||
this.draggingBlock_.moveConnections_(delta.x, delta.y);
|
||||
this.draggingBlock_.setDragging(false);
|
||||
this.draggedConnectionManager_.applyConnections();
|
||||
this.draggingBlock_.render();
|
||||
this.fireMoveEvent_();
|
||||
if (this.draggedConnectionManager_.wouldConnectBlock()) {
|
||||
// Applying connections also rerenders the relevant blocks.
|
||||
this.draggedConnectionManager_.applyConnections();
|
||||
} else {
|
||||
this.draggingBlock_.render();
|
||||
}
|
||||
this.draggingBlock_.scheduleSnapAndBump();
|
||||
}
|
||||
this.workspace_.setResizesEnabled(true);
|
||||
@@ -261,7 +266,7 @@ Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
|
||||
|
||||
if (this.wouldDeleteBlock_) {
|
||||
if (trashcan) {
|
||||
goog.Timer.callOnce(trashcan.close, 100, trashcan);
|
||||
setTimeout(trashcan.close.bind(trashcan), 100);
|
||||
}
|
||||
// Fire a move event, so we know where to go back to for an undo.
|
||||
this.fireMoveEvent_();
|
||||
|
||||
@@ -145,7 +145,7 @@ Blockly.Events.Change.prototype.fromJson = function(json) {
|
||||
|
||||
/**
|
||||
* Does this event record any change of state?
|
||||
* @return {boolean} True if something changed.
|
||||
* @return {boolean} False if something changed.
|
||||
*/
|
||||
Blockly.Events.Change.prototype.isNull = function() {
|
||||
return this.oldValue == this.newValue;
|
||||
@@ -470,7 +470,7 @@ Blockly.Events.Move.prototype.currentLocation_ = function() {
|
||||
|
||||
/**
|
||||
* Does this event record any change of state?
|
||||
* @return {boolean} True if something changed.
|
||||
* @return {boolean} False if something changed.
|
||||
*/
|
||||
Blockly.Events.Move.prototype.isNull = function() {
|
||||
return this.oldParentId == this.newParentId &&
|
||||
|
||||
+415
-258
@@ -30,6 +30,40 @@ goog.provide('Blockly.BlockSvg.render');
|
||||
goog.require('Blockly.BlockSvg');
|
||||
|
||||
|
||||
/**
|
||||
* An object that holds information about the paths that are used to render the
|
||||
* block. Each path is built up as an array of steps during the render process.
|
||||
* The arrays are then turned into strings, which are set in the block's SVG.
|
||||
* @constructor
|
||||
* @struct
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.PathObject = function() {
|
||||
/**
|
||||
* The primary outline of the block.
|
||||
* @type {!Array.<string|number>}
|
||||
*/
|
||||
this.steps = [];
|
||||
|
||||
/**
|
||||
* The highlight on the primary outline of the block.
|
||||
* @type {!Array.<string|number>}
|
||||
*/
|
||||
this.highlightSteps = [];
|
||||
|
||||
/**
|
||||
* The holes in the block for inline inputs.
|
||||
* @type {!Array.<string|number>}
|
||||
*/
|
||||
this.inlineSteps = [];
|
||||
|
||||
/**
|
||||
* The highlights on holes in the block for inline inputs.
|
||||
* @type {!Array.<string|number>}
|
||||
*/
|
||||
this.highlightInlineSteps = [];
|
||||
};
|
||||
|
||||
// UI constants for rendering blocks.
|
||||
/**
|
||||
* Horizontal space between elements.
|
||||
@@ -541,24 +575,34 @@ Blockly.BlockSvg.prototype.renderDraw_ = function(iconWidth, inputRows) {
|
||||
}
|
||||
|
||||
// Assemble the block's path.
|
||||
var steps = [];
|
||||
var inlineSteps = [];
|
||||
// The highlighting applies to edges facing the upper-left corner.
|
||||
// Since highlighting is a two-pixel wide border, it would normally overhang
|
||||
// the edge of the block by a pixel. So undersize all measurements by a pixel.
|
||||
var highlightSteps = [];
|
||||
var highlightInlineSteps = [];
|
||||
/**
|
||||
* @type !Blockly.BlockSvg.PathObject
|
||||
*/
|
||||
var pathObject = new Blockly.BlockSvg.PathObject();
|
||||
|
||||
this.renderDrawTop_(steps, highlightSteps, inputRows.rightEdge);
|
||||
var cursorY = this.renderDrawRight_(steps, highlightSteps, inlineSteps,
|
||||
highlightInlineSteps, inputRows, iconWidth);
|
||||
this.renderDrawBottom_(steps, highlightSteps, cursorY);
|
||||
this.renderDrawLeft_(steps, highlightSteps);
|
||||
this.renderDrawTop_(pathObject, inputRows.rightEdge);
|
||||
var cursorY = this.renderDrawRight_(pathObject, inputRows, iconWidth);
|
||||
this.renderDrawBottom_(pathObject, cursorY);
|
||||
this.renderDrawLeft_(pathObject);
|
||||
|
||||
var pathString = steps.join(' ') + '\n' + inlineSteps.join(' ');
|
||||
this.setPaths_(pathObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the block's SVG paths based on the paths that were computed during
|
||||
* this render pass.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.setPaths_ = function(pathObject) {
|
||||
var pathString = pathObject.steps.join(' ') + '\n' +
|
||||
pathObject.inlineSteps.join(' ');
|
||||
this.svgPath_.setAttribute('d', pathString);
|
||||
this.svgPathDark_.setAttribute('d', pathString);
|
||||
pathString = highlightSteps.join(' ') + '\n' + highlightInlineSteps.join(' ');
|
||||
|
||||
pathString = pathObject.highlightSteps.join(' ') + '\n' +
|
||||
pathObject.highlightInlineSteps.join(' ');
|
||||
this.svgPathLight_.setAttribute('d', pathString);
|
||||
if (this.RTL) {
|
||||
// Mirror the block's path.
|
||||
@@ -601,18 +645,18 @@ Blockly.BlockSvg.prototype.renderMoveConnections_ = function() {
|
||||
this.nextConnection.tighten_();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the top edge of the block.
|
||||
* @param {!Array.<string|number>} steps Path of block outline.
|
||||
* @param {!Array.<string|number>} highlightSteps Path of block highlights.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {number} rightEdge Minimum width of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawTop_ = function(steps,
|
||||
highlightSteps, rightEdge) {
|
||||
Blockly.BlockSvg.prototype.renderDrawTop_ = function(pathObject, rightEdge) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
// Position the cursor at the top-left starting point.
|
||||
if (this.squareTopLeftCorner_) {
|
||||
steps.push('m 0,0');
|
||||
@@ -651,269 +695,73 @@ Blockly.BlockSvg.prototype.renderDrawTop_ = function(steps,
|
||||
|
||||
/**
|
||||
* Render the right edge of the block.
|
||||
* @param {!Array.<string|number>} steps Path of block outline.
|
||||
* @param {!Array.<string|number>} highlightSteps Path of block highlights.
|
||||
* @param {!Array.<string|number>} inlineSteps Inline block outlines.
|
||||
* @param {!Array.<string|number>} highlightInlineSteps Inline block highlights.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {number} Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawRight_ = function(steps, highlightSteps,
|
||||
inlineSteps, highlightInlineSteps, inputRows, iconWidth) {
|
||||
var cursorX;
|
||||
var cursorY = 0;
|
||||
var connectionX, connectionY;
|
||||
Blockly.BlockSvg.prototype.renderDrawRight_ = function(pathObject, inputRows,
|
||||
iconWidth) {
|
||||
// Objects to pass to helper functions, which encapsulate a lot of the
|
||||
// information we're passing around. Helper functions will update these
|
||||
// objects.
|
||||
var cursor = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
var connectionPos = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
for (var y = 0, row; row = inputRows[y]; y++) {
|
||||
cursorX = Blockly.BlockSvg.SEP_SPACE_X;
|
||||
cursor.x = Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (y == 0) {
|
||||
cursorX += this.RTL ? -iconWidth : iconWidth;
|
||||
cursor.x += this.RTL ? -iconWidth : iconWidth;
|
||||
}
|
||||
highlightSteps.push('M', (inputRows.rightEdge - 0.5) + ',' +
|
||||
(cursorY + 0.5));
|
||||
pathObject.highlightSteps.push('M', (inputRows.rightEdge - 0.5) + ',' +
|
||||
(cursor.y + 0.5));
|
||||
if (this.isCollapsed()) {
|
||||
// Jagged right edge.
|
||||
var input = row[0];
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push(Blockly.BlockSvg.JAGGED_TEETH);
|
||||
highlightSteps.push('h 8');
|
||||
var remainder = row.height - Blockly.BlockSvg.JAGGED_TEETH_HEIGHT;
|
||||
steps.push('v', remainder);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v 3.9 l 7.2,3.4 m -14.5,8.9 l 7.3,3.5');
|
||||
highlightSteps.push('v', remainder - 0.7);
|
||||
}
|
||||
this.width += Blockly.BlockSvg.JAGGED_TEETH_WIDTH;
|
||||
this.renderJaggedEdge_(pathObject, row, cursor);
|
||||
} else if (row.type == Blockly.BlockSvg.INLINE) {
|
||||
// Inline inputs.
|
||||
for (var x = 0, input; input = row[x]; x++) {
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (row.thicker) {
|
||||
// Lower the field slightly.
|
||||
fieldY += Blockly.BlockSvg.INLINE_PADDING_Y;
|
||||
}
|
||||
// TODO: Align inline field rows (left/right/centre).
|
||||
cursorX = this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
if (input.type != Blockly.DUMMY_INPUT) {
|
||||
cursorX += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
if (input.type == Blockly.INPUT_VALUE) {
|
||||
inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X) +
|
||||
',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y));
|
||||
inlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 -
|
||||
input.renderWidth);
|
||||
inlineSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN);
|
||||
inlineSteps.push('v', input.renderHeight + 1 -
|
||||
Blockly.BlockSvg.TAB_HEIGHT);
|
||||
inlineSteps.push('h', input.renderWidth + 2 -
|
||||
Blockly.BlockSvg.TAB_WIDTH);
|
||||
inlineSteps.push('z');
|
||||
if (this.RTL) {
|
||||
// Highlight right edge, around back of tab, and bottom.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursorX - Blockly.BlockSvg.SEP_SPACE_X - 2.5 +
|
||||
Blockly.BlockSvg.TAB_WIDTH - input.renderWidth) + ',' +
|
||||
(cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5));
|
||||
highlightInlineSteps.push(
|
||||
Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL);
|
||||
highlightInlineSteps.push('v',
|
||||
input.renderHeight - Blockly.BlockSvg.TAB_HEIGHT + 2.5);
|
||||
highlightInlineSteps.push('h',
|
||||
input.renderWidth - Blockly.BlockSvg.TAB_WIDTH + 2);
|
||||
} else {
|
||||
// Highlight right edge, bottom.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursorX - Blockly.BlockSvg.SEP_SPACE_X + 0.5) + ',' +
|
||||
(cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5));
|
||||
highlightInlineSteps.push('v', input.renderHeight + 1);
|
||||
highlightInlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 -
|
||||
input.renderWidth);
|
||||
// Short highlight glint at bottom of tab.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursorX - input.renderWidth - Blockly.BlockSvg.SEP_SPACE_X +
|
||||
0.9) + ',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y +
|
||||
Blockly.BlockSvg.TAB_HEIGHT - 0.7));
|
||||
highlightInlineSteps.push('l',
|
||||
(Blockly.BlockSvg.TAB_WIDTH * 0.46) + ',-2.1');
|
||||
}
|
||||
// Create inline input connection.
|
||||
if (this.RTL) {
|
||||
connectionX = -cursorX -
|
||||
Blockly.BlockSvg.TAB_WIDTH + Blockly.BlockSvg.SEP_SPACE_X +
|
||||
input.renderWidth + 1;
|
||||
} else {
|
||||
connectionX = cursorX +
|
||||
Blockly.BlockSvg.TAB_WIDTH - Blockly.BlockSvg.SEP_SPACE_X -
|
||||
input.renderWidth - 1;
|
||||
}
|
||||
connectionY = cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 1;
|
||||
input.connection.setOffsetInBlock(connectionX, connectionY);
|
||||
}
|
||||
}
|
||||
|
||||
cursorX = Math.max(cursorX, inputRows.rightEdge);
|
||||
this.width = Math.max(this.width, cursorX);
|
||||
steps.push('H', cursorX);
|
||||
highlightSteps.push('H', cursorX - 0.5);
|
||||
steps.push('v', row.height);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', row.height - 1);
|
||||
}
|
||||
this.renderInlineRow_(
|
||||
pathObject, row, cursor, connectionPos, inputRows.rightEdge);
|
||||
} else if (row.type == Blockly.INPUT_VALUE) {
|
||||
// External input.
|
||||
var input = row[0];
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.rightEdge - input.fieldWidth -
|
||||
Blockly.BlockSvg.TAB_WIDTH - 2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push(Blockly.BlockSvg.TAB_PATH_DOWN);
|
||||
var v = row.height - Blockly.BlockSvg.TAB_HEIGHT;
|
||||
steps.push('v', v);
|
||||
if (this.RTL) {
|
||||
// Highlight around back of tab.
|
||||
highlightSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('v', v + 0.5);
|
||||
} else {
|
||||
// Short highlight glint at bottom of tab.
|
||||
highlightSteps.push('M', (inputRows.rightEdge - 5) + ',' +
|
||||
(cursorY + Blockly.BlockSvg.TAB_HEIGHT - 0.7));
|
||||
highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * 0.46) +
|
||||
',-2.1');
|
||||
}
|
||||
// Create external input connection.
|
||||
connectionX = this.RTL ? -inputRows.rightEdge - 1 :
|
||||
inputRows.rightEdge + 1;
|
||||
input.connection.setOffsetInBlock(connectionX, cursorY);
|
||||
if (input.connection.isConnected()) {
|
||||
this.width = Math.max(this.width, inputRows.rightEdge +
|
||||
input.connection.targetBlock().getHeightWidth().width -
|
||||
Blockly.BlockSvg.TAB_WIDTH + 1);
|
||||
}
|
||||
this.renderExternalValueInput_(
|
||||
pathObject, row, cursor, connectionPos, inputRows.rightEdge);
|
||||
} else if (row.type == Blockly.DUMMY_INPUT) {
|
||||
// External naked field.
|
||||
var input = row[0];
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.rightEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (inputRows.hasValue) {
|
||||
fieldRightX -= Blockly.BlockSvg.TAB_WIDTH;
|
||||
}
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push('v', row.height);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', row.height - 1);
|
||||
}
|
||||
this.renderDummyInput_(
|
||||
pathObject, row, cursor, inputRows.rightEdge, inputRows.hasValue);
|
||||
} else if (row.type == Blockly.NEXT_STATEMENT) {
|
||||
// Nested statement.
|
||||
var input = row[0];
|
||||
if (y == 0) {
|
||||
// If the first input is a statement stack, add a small row on top.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1);
|
||||
}
|
||||
cursorY += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.statementEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
cursorX = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH;
|
||||
steps.push('H', cursorX);
|
||||
steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER);
|
||||
steps.push('v', row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER);
|
||||
steps.push('H', inputRows.rightEdge);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('M',
|
||||
(cursorX - Blockly.BlockSvg.NOTCH_WIDTH +
|
||||
Blockly.BlockSvg.DISTANCE_45_OUTSIDE) +
|
||||
',' + (cursorY + Blockly.BlockSvg.DISTANCE_45_OUTSIDE));
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('v',
|
||||
row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS);
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('H', inputRows.rightEdge - 0.5);
|
||||
} else {
|
||||
highlightSteps.push('M',
|
||||
(cursorX - Blockly.BlockSvg.NOTCH_WIDTH +
|
||||
Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' +
|
||||
(cursorY + row.height - Blockly.BlockSvg.DISTANCE_45_OUTSIDE));
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR);
|
||||
highlightSteps.push('H', inputRows.rightEdge - 0.5);
|
||||
}
|
||||
// Create statement connection.
|
||||
connectionX = this.RTL ? -cursorX : cursorX + 1;
|
||||
input.connection.setOffsetInBlock(connectionX, cursorY + 1);
|
||||
|
||||
if (input.connection.isConnected()) {
|
||||
this.width = Math.max(this.width, inputRows.statementEdge +
|
||||
input.connection.targetBlock().getHeightWidth().width);
|
||||
}
|
||||
if (y == inputRows.length - 1 ||
|
||||
inputRows[y + 1].type == Blockly.NEXT_STATEMENT) {
|
||||
// If the final input is a statement stack, add a small row underneath.
|
||||
// Consecutive statement stacks are also separated by a small divider.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1);
|
||||
}
|
||||
cursorY += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
this.renderStatementInput_(
|
||||
pathObject, row, cursor, connectionPos, inputRows, y);
|
||||
}
|
||||
cursorY += row.height;
|
||||
cursor.y += row.height;
|
||||
}
|
||||
if (!inputRows.length) {
|
||||
cursorY = Blockly.BlockSvg.MIN_BLOCK_Y;
|
||||
steps.push('V', cursorY);
|
||||
cursor.y = Blockly.BlockSvg.MIN_BLOCK_Y;
|
||||
pathObject.steps.push('V', cursor.y);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('V', cursorY - 1);
|
||||
pathObject.highlightSteps.push('V', cursor.y - 1);
|
||||
}
|
||||
}
|
||||
return cursorY;
|
||||
return cursor.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the bottom edge of the block.
|
||||
* @param {!Array.<string|number>} steps Path of block outline.
|
||||
* @param {!Array.<string|number>} highlightSteps Path of block highlights.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,
|
||||
highlightSteps, cursorY) {
|
||||
Blockly.BlockSvg.prototype.renderDrawBottom_ = function(pathObject, cursorY) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
this.height += cursorY + 1; // Add one for the shadow.
|
||||
if (this.nextConnection) {
|
||||
steps.push('H', (Blockly.BlockSvg.NOTCH_WIDTH + (this.RTL ? 0.5 : - 0.5)) +
|
||||
@@ -953,11 +801,13 @@ Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,
|
||||
|
||||
/**
|
||||
* Render the left edge of the block.
|
||||
* @param {!Array.<string|number>} steps Path of block outline.
|
||||
* @param {!Array.<string|number>} highlightSteps Path of block highlights.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawLeft_ = function(steps, highlightSteps) {
|
||||
Blockly.BlockSvg.prototype.renderDrawLeft_ = function(pathObject) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
if (this.outputConnection) {
|
||||
// Create output connection.
|
||||
this.outputConnection.setOffsetInBlock(0, 0);
|
||||
@@ -987,3 +837,310 @@ Blockly.BlockSvg.prototype.renderDrawLeft_ = function(steps, highlightSteps) {
|
||||
}
|
||||
steps.push('z');
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the jagged edge of an input that shows on a collapsed block.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Object>} row An object containing position information about
|
||||
* inputs on this row of the block.
|
||||
* @param {!Object} cursor An object containing the position of the cursor,
|
||||
* which determines where to start laying out fields.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderJaggedEdge_ = function(pathObject, row,
|
||||
cursor) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
var input = row[0];
|
||||
this.renderFields_(input.fieldRow, cursor.x, cursor.y);
|
||||
steps.push(Blockly.BlockSvg.JAGGED_TEETH);
|
||||
highlightSteps.push('h 8');
|
||||
var remainder = row.height - Blockly.BlockSvg.JAGGED_TEETH_HEIGHT;
|
||||
steps.push('v', remainder);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v 3.9 l 7.2,3.4 m -14.5,8.9 l 7.3,3.5');
|
||||
highlightSteps.push('v', remainder - 0.7);
|
||||
}
|
||||
this.width += Blockly.BlockSvg.JAGGED_TEETH_WIDTH;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right side of an inline row on a block.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Object>} row An object containing position information about
|
||||
* inputs on this row of the block.
|
||||
* @param {!Object} cursor An object containing the position of the cursor,
|
||||
* which determines where to start laying out fields.
|
||||
* @param {!Object} connectionPos An object containing the position of the
|
||||
* connection on this input.
|
||||
* @param {number} rightEdge The position of the right edge of the block, which
|
||||
* is based on the widest row that has been encountered so far.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderInlineRow_ = function(pathObject, row, cursor,
|
||||
connectionPos, rightEdge) {
|
||||
var inlineSteps = pathObject.inlineSteps;
|
||||
var highlightInlineSteps = pathObject.highlightInlineSteps;
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
|
||||
for (var x = 0, input; input = row[x]; x++) {
|
||||
var fieldX = cursor.x;
|
||||
var fieldY = cursor.y;
|
||||
if (row.thicker) {
|
||||
// Lower the field slightly.
|
||||
fieldY += Blockly.BlockSvg.INLINE_PADDING_Y;
|
||||
}
|
||||
// TODO: Align inline field rows (left/right/centre).
|
||||
cursor.x = this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
if (input.type != Blockly.DUMMY_INPUT) {
|
||||
cursor.x += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
if (input.type == Blockly.INPUT_VALUE) {
|
||||
inlineSteps.push('M', (cursor.x - Blockly.BlockSvg.SEP_SPACE_X) +
|
||||
',' + (cursor.y + Blockly.BlockSvg.INLINE_PADDING_Y));
|
||||
inlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 -
|
||||
input.renderWidth);
|
||||
inlineSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN);
|
||||
inlineSteps.push('v', input.renderHeight + 1 -
|
||||
Blockly.BlockSvg.TAB_HEIGHT);
|
||||
inlineSteps.push('h', input.renderWidth + 2 -
|
||||
Blockly.BlockSvg.TAB_WIDTH);
|
||||
inlineSteps.push('z');
|
||||
if (this.RTL) {
|
||||
// Highlight right edge, around back of tab, and bottom.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursor.x - Blockly.BlockSvg.SEP_SPACE_X - 2.5 +
|
||||
Blockly.BlockSvg.TAB_WIDTH - input.renderWidth) + ',' +
|
||||
(cursor.y + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5));
|
||||
highlightInlineSteps.push(
|
||||
Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL);
|
||||
highlightInlineSteps.push('v',
|
||||
input.renderHeight - Blockly.BlockSvg.TAB_HEIGHT + 2.5);
|
||||
highlightInlineSteps.push('h',
|
||||
input.renderWidth - Blockly.BlockSvg.TAB_WIDTH + 2);
|
||||
} else {
|
||||
// Highlight right edge, bottom.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursor.x - Blockly.BlockSvg.SEP_SPACE_X + 0.5) + ',' +
|
||||
(cursor.y + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5));
|
||||
highlightInlineSteps.push('v', input.renderHeight + 1);
|
||||
highlightInlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 -
|
||||
input.renderWidth);
|
||||
// Short highlight glint at bottom of tab.
|
||||
highlightInlineSteps.push('M',
|
||||
(cursor.x - input.renderWidth - Blockly.BlockSvg.SEP_SPACE_X +
|
||||
0.9) + ',' + (cursor.y + Blockly.BlockSvg.INLINE_PADDING_Y +
|
||||
Blockly.BlockSvg.TAB_HEIGHT - 0.7));
|
||||
highlightInlineSteps.push('l',
|
||||
(Blockly.BlockSvg.TAB_WIDTH * 0.46) + ',-2.1');
|
||||
}
|
||||
// Create inline input connection.
|
||||
if (this.RTL) {
|
||||
connectionPos.x = -cursor.x -
|
||||
Blockly.BlockSvg.TAB_WIDTH + Blockly.BlockSvg.SEP_SPACE_X +
|
||||
input.renderWidth + 1;
|
||||
} else {
|
||||
connectionPos.x = cursor.x +
|
||||
Blockly.BlockSvg.TAB_WIDTH - Blockly.BlockSvg.SEP_SPACE_X -
|
||||
input.renderWidth - 1;
|
||||
}
|
||||
connectionPos.y = cursor.y + Blockly.BlockSvg.INLINE_PADDING_Y + 1;
|
||||
input.connection.setOffsetInBlock(connectionPos.x, connectionPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
cursor.x = Math.max(cursor.x, rightEdge);
|
||||
this.width = Math.max(this.width, cursor.x);
|
||||
steps.push('H', cursor.x);
|
||||
highlightSteps.push('H', cursor.x - 0.5);
|
||||
steps.push('v', row.height);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', row.height - 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right side of an inline row on a block.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Object>} row An object containing position information about
|
||||
* inputs on this row of the block.
|
||||
* @param {!Object} cursor An object containing the position of the cursor,
|
||||
* which determines where to start laying out fields.
|
||||
* @param {!Object} connectionPos An object containing the position of the
|
||||
* connection on this input.
|
||||
* @param {number} rightEdge The position of the right edge of the block, which
|
||||
* is based on the widest row that has been encountered so far.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderExternalValueInput_ = function(pathObject, row,
|
||||
cursor, connectionPos, rightEdge) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
// External input.
|
||||
var input = row[0];
|
||||
var fieldX = cursor.x;
|
||||
var fieldY = cursor.y;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = rightEdge - input.fieldWidth -
|
||||
Blockly.BlockSvg.TAB_WIDTH - 2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push(Blockly.BlockSvg.TAB_PATH_DOWN);
|
||||
var v = row.height - Blockly.BlockSvg.TAB_HEIGHT;
|
||||
steps.push('v', v);
|
||||
if (this.RTL) {
|
||||
// Highlight around back of tab.
|
||||
highlightSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('v', v + 0.5);
|
||||
} else {
|
||||
// Short highlight glint at bottom of tab.
|
||||
highlightSteps.push('M', (rightEdge - 5) + ',' +
|
||||
(cursor.y + Blockly.BlockSvg.TAB_HEIGHT - 0.7));
|
||||
highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * 0.46) +
|
||||
',-2.1');
|
||||
}
|
||||
// Create external input connection.
|
||||
connectionPos.x = this.RTL ? -rightEdge - 1 : rightEdge + 1;
|
||||
input.connection.setOffsetInBlock(connectionPos.x, cursor.y);
|
||||
if (input.connection.isConnected()) {
|
||||
this.width = Math.max(this.width, rightEdge +
|
||||
input.connection.targetBlock().getHeightWidth().width -
|
||||
Blockly.BlockSvg.TAB_WIDTH + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right side of an inline row on a block.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Object>} row An object containing position information about
|
||||
* inputs on this row of the block.
|
||||
* @param {!Object} cursor An object containing the position of the cursor,
|
||||
* which determines where to start laying out fields.
|
||||
* @param {number} rightEdge The position of the right edge of the block, which
|
||||
* is based on the widest row that has been encountered so far.
|
||||
* @param {boolean} hasValue True if this block has at least one value input.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDummyInput_ = function(pathObject, row,
|
||||
cursor, rightEdge, hasValue) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
var input = row[0];
|
||||
var fieldX = cursor.x;
|
||||
var fieldY = cursor.y;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = rightEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (hasValue) {
|
||||
fieldRightX -= Blockly.BlockSvg.TAB_WIDTH;
|
||||
}
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push('v', row.height);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', row.height - 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render the right side of an inline row on a block.
|
||||
* @param {!Blockly.BlockSvg.PathObject} pathObject The object containing
|
||||
* partially constructed SVG paths, which will be modified by this function.
|
||||
* @param {!Array.<!Object>} row An object containing position information about
|
||||
* inputs on this row of the block.
|
||||
* @param {!Object} cursor An object containing the position of the cursor,
|
||||
* which determines where to start laying out fields.
|
||||
* @param {!Object} connectionPos An object containing the position of the
|
||||
* connection on this input.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @param {number} index The index of the current row in the inputRows array.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderStatementInput_ = function(pathObject, row,
|
||||
cursor, connectionPos, inputRows, index) {
|
||||
var steps = pathObject.steps;
|
||||
var highlightSteps = pathObject.highlightSteps;
|
||||
var input = row[0];
|
||||
if (index == 0) {
|
||||
// If the first input is a statement stack, add a small row on top.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1);
|
||||
}
|
||||
cursor.y += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
var fieldX = cursor.x;
|
||||
var fieldY = cursor.y;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.statementEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
cursor.x = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH;
|
||||
steps.push('H', cursor.x);
|
||||
steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER);
|
||||
steps.push('v', row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER);
|
||||
steps.push('H', inputRows.rightEdge);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('M',
|
||||
(cursor.x - Blockly.BlockSvg.NOTCH_WIDTH +
|
||||
Blockly.BlockSvg.DISTANCE_45_OUTSIDE) +
|
||||
',' + (cursor.y + Blockly.BlockSvg.DISTANCE_45_OUTSIDE));
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('v',
|
||||
row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS);
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL);
|
||||
highlightSteps.push('H', inputRows.rightEdge - 0.5);
|
||||
} else {
|
||||
highlightSteps.push('M',
|
||||
(cursor.x - Blockly.BlockSvg.NOTCH_WIDTH +
|
||||
Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' +
|
||||
(cursor.y + row.height - Blockly.BlockSvg.DISTANCE_45_OUTSIDE));
|
||||
highlightSteps.push(
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR);
|
||||
highlightSteps.push('H', inputRows.rightEdge - 0.5);
|
||||
}
|
||||
// Create statement connection.
|
||||
connectionPos.x = this.RTL ? -cursor.x : cursor.x + 1;
|
||||
input.connection.setOffsetInBlock(connectionPos.x, cursor.y + 1);
|
||||
|
||||
if (input.connection.isConnected()) {
|
||||
this.width = Math.max(this.width, inputRows.statementEdge +
|
||||
input.connection.targetBlock().getHeightWidth().width);
|
||||
}
|
||||
if (index == inputRows.length - 1 ||
|
||||
inputRows[index + 1].type == Blockly.NEXT_STATEMENT) {
|
||||
// If the final input is a statement stack, add a small row underneath.
|
||||
// Consecutive statement stacks are also separated by a small divider.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
if (this.RTL) {
|
||||
highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1);
|
||||
}
|
||||
cursor.y += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
};
|
||||
|
||||
+34
-193
@@ -27,6 +27,7 @@
|
||||
goog.provide('Blockly.BlockSvg');
|
||||
|
||||
goog.require('Blockly.Block');
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.ContextMenu');
|
||||
goog.require('Blockly.Events.Ui');
|
||||
goog.require('Blockly.Events.BlockMove');
|
||||
@@ -35,7 +36,7 @@ goog.require('Blockly.RenderedConnection');
|
||||
goog.require('Blockly.Tooltip');
|
||||
goog.require('Blockly.Touch');
|
||||
goog.require('Blockly.utils');
|
||||
goog.require('goog.Timer');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.math.Coordinate');
|
||||
@@ -250,28 +251,36 @@ Blockly.BlockSvg.prototype.getIcons = function() {
|
||||
* @param {Blockly.BlockSvg} newParent New parent block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.setParent = function(newParent) {
|
||||
if (newParent == this.parentBlock_) {
|
||||
var oldParent = this.parentBlock_;
|
||||
if (newParent == oldParent) {
|
||||
return;
|
||||
}
|
||||
var svgRoot = this.getSvgRoot();
|
||||
if (this.parentBlock_ && svgRoot) {
|
||||
// Move this block up the DOM. Keep track of x/y translations.
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.workspace.getCanvas().appendChild(svgRoot);
|
||||
svgRoot.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')');
|
||||
}
|
||||
|
||||
Blockly.Field.startCache();
|
||||
Blockly.BlockSvg.superClass_.setParent.call(this, newParent);
|
||||
Blockly.Field.stopCache();
|
||||
|
||||
var svgRoot = this.getSvgRoot();
|
||||
|
||||
// Bail early if workspace is clearing, or we aren't rendered.
|
||||
// We won't need to reattach ourselves anywhere.
|
||||
if (this.workspace.isClearing || !svgRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldXY = this.getRelativeToSurfaceXY();
|
||||
if (newParent) {
|
||||
var oldXY = this.getRelativeToSurfaceXY();
|
||||
newParent.getSvgRoot().appendChild(svgRoot);
|
||||
var newXY = this.getRelativeToSurfaceXY();
|
||||
// Move the connections to match the child's new position.
|
||||
this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y);
|
||||
}
|
||||
// If we are losing a parent, we want to move our DOM element to the
|
||||
// root of the workspace.
|
||||
else if (oldParent) {
|
||||
this.workspace.getCanvas().appendChild(svgRoot);
|
||||
this.translate(oldXY.x, oldXY.y);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -319,13 +328,18 @@ Blockly.BlockSvg.prototype.getRelativeToSurfaceXY = function() {
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.moveBy = function(dx, dy) {
|
||||
goog.asserts.assert(!this.parentBlock_, 'Block has parent.');
|
||||
var event = new Blockly.Events.BlockMove(this);
|
||||
var eventsEnabled = Blockly.Events.isEnabled();
|
||||
if (eventsEnabled) {
|
||||
var event = new Blockly.Events.BlockMove(this);
|
||||
}
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.translate(xy.x + dx, xy.y + dy);
|
||||
this.moveConnections_(dx, dy);
|
||||
event.recordNew();
|
||||
if (eventsEnabled) {
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
}
|
||||
this.workspace.resizeContents();
|
||||
Blockly.Events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -569,7 +583,7 @@ Blockly.BlockSvg.prototype.createTabList_ = function() {
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.onMouseDown_ = function(e) {
|
||||
var gesture = this.workspace.getGesture(e);
|
||||
var gesture = this.workspace && this.workspace.getGesture(e);
|
||||
if (gesture) {
|
||||
gesture.handleBlockStart(e, this);
|
||||
}
|
||||
@@ -616,7 +630,7 @@ Blockly.BlockSvg.prototype.showContextMenu_ = function(e) {
|
||||
var inlineOption = {enabled: true};
|
||||
var isInline = this.getInputsInline();
|
||||
inlineOption.text = isInline ?
|
||||
Blockly.Msg.EXTERNAL_INPUTS : Blockly.Msg.INLINE_INPUTS;
|
||||
Blockly.Msg['EXTERNAL_INPUTS'] : Blockly.Msg['INLINE_INPUTS'];
|
||||
inlineOption.callback = function() {
|
||||
block.setInputsInline(!isInline);
|
||||
};
|
||||
@@ -630,14 +644,14 @@ Blockly.BlockSvg.prototype.showContextMenu_ = function(e) {
|
||||
// Option to collapse/expand block.
|
||||
if (this.collapsed_) {
|
||||
var expandOption = {enabled: true};
|
||||
expandOption.text = Blockly.Msg.EXPAND_BLOCK;
|
||||
expandOption.text = Blockly.Msg['EXPAND_BLOCK'];
|
||||
expandOption.callback = function() {
|
||||
block.setCollapsed(false);
|
||||
};
|
||||
menuOptions.push(expandOption);
|
||||
} else {
|
||||
var collapseOption = {enabled: true};
|
||||
collapseOption.text = Blockly.Msg.COLLAPSE_BLOCK;
|
||||
collapseOption.text = Blockly.Msg['COLLAPSE_BLOCK'];
|
||||
collapseOption.callback = function() {
|
||||
block.setCollapsed(true);
|
||||
};
|
||||
@@ -649,7 +663,7 @@ Blockly.BlockSvg.prototype.showContextMenu_ = function(e) {
|
||||
// Option to disable/enable block.
|
||||
var disableOption = {
|
||||
text: this.disabled ?
|
||||
Blockly.Msg.ENABLE_BLOCK : Blockly.Msg.DISABLE_BLOCK,
|
||||
Blockly.Msg['ENABLE_BLOCK'] : Blockly.Msg['DISABLE_BLOCK'],
|
||||
enabled: !this.getInheritedDisabled(),
|
||||
callback: function() {
|
||||
block.setDisabled(!block.disabled);
|
||||
@@ -807,7 +821,7 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) {
|
||||
|
||||
if (animate && this.rendered) {
|
||||
this.unplug(healStack);
|
||||
this.disposeUiEffect();
|
||||
Blockly.BlockAnimations.disposeUiEffect(this);
|
||||
}
|
||||
// Stop rerendering.
|
||||
this.rendered = false;
|
||||
@@ -841,179 +855,6 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) {
|
||||
Blockly.Field.stopCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, animation) when disposing of a block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.disposeUiEffect = function() {
|
||||
this.workspace.getAudioManager().play('delete');
|
||||
|
||||
var xy = this.workspace.getSvgXY(/** @type {!Element} */ (this.svgGroup_));
|
||||
// Deeply clone the current block.
|
||||
var clone = this.svgGroup_.cloneNode(true);
|
||||
clone.translateX_ = xy.x;
|
||||
clone.translateY_ = xy.y;
|
||||
clone.setAttribute('transform',
|
||||
'translate(' + clone.translateX_ + ',' + clone.translateY_ + ')');
|
||||
this.workspace.getParentSvg().appendChild(clone);
|
||||
clone.bBox_ = clone.getBBox();
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.disposeUiStep_(clone, this.RTL, new Date,
|
||||
this.workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Animate a cloned block and eventually dispose of it.
|
||||
* This is a class method, not an instance method since the original block has
|
||||
* been destroyed and is no longer accessible.
|
||||
* @param {!Element} clone SVG element to animate and dispose of.
|
||||
* @param {boolean} rtl True if RTL, false if LTR.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.disposeUiStep_ = function(clone, rtl, start, workspaceScale) {
|
||||
var ms = new Date - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(clone);
|
||||
} else {
|
||||
var x = clone.translateX_ +
|
||||
(rtl ? -1 : 1) * clone.bBox_.width * workspaceScale / 2 * percent;
|
||||
var y = clone.translateY_ + clone.bBox_.height * workspaceScale * percent;
|
||||
var scale = (1 - percent) * workspaceScale;
|
||||
clone.setAttribute('transform', 'translate(' + x + ',' + y + ')' +
|
||||
' scale(' + scale + ')');
|
||||
setTimeout(
|
||||
Blockly.BlockSvg.disposeUiStep_, 10, clone, rtl, start, workspaceScale);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, ripple) after a connection has been established.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect = function() {
|
||||
this.workspace.getAudioManager().play('click');
|
||||
if (this.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Determine the absolute coordinates of the inferior block.
|
||||
var xy = this.workspace.getSvgXY(/** @type {!Element} */ (this.svgGroup_));
|
||||
// Offset the coordinates based on the two connection types, fix scale.
|
||||
if (this.outputConnection) {
|
||||
xy.x += (this.RTL ? 3 : -3) * this.workspace.scale;
|
||||
xy.y += 13 * this.workspace.scale;
|
||||
} else if (this.previousConnection) {
|
||||
xy.x += (this.RTL ? -23 : 23) * this.workspace.scale;
|
||||
xy.y += 3 * this.workspace.scale;
|
||||
}
|
||||
var ripple = Blockly.utils.createSvgElement('circle',
|
||||
{
|
||||
'cx': xy.x,
|
||||
'cy': xy.y,
|
||||
'r': 0,
|
||||
'fill': 'none',
|
||||
'stroke': '#888',
|
||||
'stroke-width': 10
|
||||
},
|
||||
this.workspace.getParentSvg());
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, new Date, this.workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a ripple around a connection.
|
||||
* @param {!Element} ripple Element to animate.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.connectionUiStep_ = function(ripple, start, workspaceScale) {
|
||||
var ms = new Date - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(ripple);
|
||||
} else {
|
||||
ripple.setAttribute('r', percent * 25 * workspaceScale);
|
||||
ripple.style.opacity = 1 - percent;
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid_ = setTimeout(
|
||||
Blockly.BlockSvg.connectionUiStep_, 10, ripple, start, workspaceScale);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, animation) when disconnecting a block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.disconnectUiEffect = function() {
|
||||
this.workspace.getAudioManager().play('disconnect');
|
||||
if (this.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Horizontal distance for bottom of block to wiggle.
|
||||
var DISPLACEMENT = 10;
|
||||
// Scale magnitude of skew to height of block.
|
||||
var height = this.getHeightWidth().height;
|
||||
var magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180;
|
||||
if (!this.RTL) {
|
||||
magnitude *= -1;
|
||||
}
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.disconnectUiStep_(this.svgGroup_, magnitude, new Date);
|
||||
};
|
||||
|
||||
/**
|
||||
* Animate a brief wiggle of a disconnected block.
|
||||
* @param {!Element} group SVG element to animate.
|
||||
* @param {number} magnitude Maximum degrees skew (reversed for RTL).
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.disconnectUiStep_ = function(group, magnitude, start) {
|
||||
var DURATION = 200; // Milliseconds.
|
||||
var WIGGLES = 3; // Half oscillations.
|
||||
|
||||
var ms = new Date - start;
|
||||
var percent = ms / DURATION;
|
||||
|
||||
if (percent > 1) {
|
||||
group.skew_ = '';
|
||||
} else {
|
||||
var skew = Math.round(
|
||||
Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude);
|
||||
group.skew_ = 'skewX(' + skew + ')';
|
||||
Blockly.BlockSvg.disconnectUiStop_.group = group;
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid =
|
||||
setTimeout(
|
||||
Blockly.BlockSvg.disconnectUiStep_, 10, group, magnitude, start);
|
||||
}
|
||||
group.setAttribute('transform', group.translate_ + group.skew_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop the disconnect UI animation immediately.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.disconnectUiStop_ = function() {
|
||||
if (Blockly.BlockSvg.disconnectUiStop_.group) {
|
||||
clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid);
|
||||
var group = Blockly.BlockSvg.disconnectUiStop_.group;
|
||||
group.skew_ = '';
|
||||
group.setAttribute('transform', group.translate_);
|
||||
Blockly.BlockSvg.disconnectUiStop_.group = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* PID of disconnect UI animation. There can only be one at a time.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid = 0;
|
||||
|
||||
/**
|
||||
* SVG group of wobbling block. There can only be one at a time.
|
||||
* @type {Element}
|
||||
*/
|
||||
Blockly.BlockSvg.disconnectUiStop_.group = null;
|
||||
|
||||
/**
|
||||
* Change the colour of a block.
|
||||
*/
|
||||
@@ -1070,7 +911,7 @@ Blockly.BlockSvg.prototype.updateDisabled = function() {
|
||||
this.updateColour();
|
||||
}
|
||||
}
|
||||
var children = this.getChildren();
|
||||
var children = this.getChildren(false);
|
||||
for (var i = 0, child; child = children[i]; i++) {
|
||||
child.updateDisabled();
|
||||
}
|
||||
|
||||
+29
-21
@@ -246,35 +246,41 @@ Blockly.onKeyDown_ = function(e) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a block onto the local clipboard.
|
||||
* @param {!Blockly.Block} block Block to be copied.
|
||||
* Copy a block or workspace comment onto the local clipboard.
|
||||
* @param {!Blockly.Block | !Blockly.WorkspaceComment} toCopy Block or Workspace Comment
|
||||
* to be copied.
|
||||
* @private
|
||||
*/
|
||||
Blockly.copy_ = function(block) {
|
||||
var xmlBlock = Blockly.Xml.blockToDom(block);
|
||||
// Copy only the selected block and internal blocks.
|
||||
Blockly.Xml.deleteNext(xmlBlock);
|
||||
// Encode start position in XML.
|
||||
var xy = block.getRelativeToSurfaceXY();
|
||||
xmlBlock.setAttribute('x', block.RTL ? -xy.x : xy.x);
|
||||
xmlBlock.setAttribute('y', xy.y);
|
||||
Blockly.clipboardXml_ = xmlBlock;
|
||||
Blockly.clipboardSource_ = block.workspace;
|
||||
Blockly.copy_ = function(toCopy) {
|
||||
if (toCopy.isComment) {
|
||||
var xml = toCopy.toXmlWithXY();
|
||||
} else {
|
||||
var xml = Blockly.Xml.blockToDom(toCopy);
|
||||
// Copy only the selected block and internal blocks.
|
||||
Blockly.Xml.deleteNext(xml);
|
||||
// Encode start position in XML.
|
||||
var xy = toCopy.getRelativeToSurfaceXY();
|
||||
xml.setAttribute('x', toCopy.RTL ? -xy.x : xy.x);
|
||||
xml.setAttribute('y', xy.y);
|
||||
}
|
||||
Blockly.clipboardXml_ = xml;
|
||||
Blockly.clipboardSource_ = toCopy.workspace;
|
||||
};
|
||||
|
||||
/**
|
||||
* Duplicate this block and its children.
|
||||
* @param {!Blockly.Block} block Block to be copied.
|
||||
* Duplicate this block and its children, or a workspace comment.
|
||||
* @param {!Blockly.Block | !Blockly.WorkspaceComment} toDuplicate Block or
|
||||
* Workspace Comment to be copied.
|
||||
* @private
|
||||
*/
|
||||
Blockly.duplicate_ = function(block) {
|
||||
Blockly.duplicate_ = function(toDuplicate) {
|
||||
// Save the clipboard.
|
||||
var clipboardXml = Blockly.clipboardXml_;
|
||||
var clipboardSource = Blockly.clipboardSource_;
|
||||
|
||||
// Create a duplicate via a copy/paste operation.
|
||||
Blockly.copy_(block);
|
||||
block.workspace.paste(Blockly.clipboardXml_);
|
||||
Blockly.copy_(toDuplicate);
|
||||
toDuplicate.workspace.paste(Blockly.clipboardXml_);
|
||||
|
||||
// Restore the clipboard.
|
||||
Blockly.clipboardXml_ = clipboardXml;
|
||||
@@ -380,6 +386,7 @@ Blockly.prompt = function(message, defaultValue, callback) {
|
||||
* @private
|
||||
*/
|
||||
Blockly.jsonInitFactory_ = function(jsonDef) {
|
||||
/** @this Blockly.Block */
|
||||
return function() {
|
||||
this.jsonInit(jsonDef);
|
||||
};
|
||||
@@ -457,7 +464,7 @@ Blockly.bindEventWithChecks_ = function(node, name, thisObject, func,
|
||||
};
|
||||
|
||||
var bindData = [];
|
||||
if (window && window.PointerEvent && (name in Blockly.Touch.TOUCH_MAP)) {
|
||||
if (goog.global.PointerEvent && (name in Blockly.Touch.TOUCH_MAP)) {
|
||||
for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) {
|
||||
node.addEventListener(type, wrapFunc, false);
|
||||
bindData.push([node, type, wrapFunc]);
|
||||
@@ -509,6 +516,7 @@ Blockly.bindEvent_ = function(node, name, thisObject, func) {
|
||||
};
|
||||
|
||||
var bindData = [];
|
||||
var window = goog.global['window'];
|
||||
if (window && window.PointerEvent && (name in Blockly.Touch.TOUCH_MAP)) {
|
||||
for (var i = 0, type; type = Blockly.Touch.TOUCH_MAP[name][i]; i++) {
|
||||
node.addEventListener(type, wrapFunc, false);
|
||||
@@ -624,7 +632,7 @@ Blockly.checkBlockColourConstant_ = function(
|
||||
msgName, blocklyNamePath, expectedValue) {
|
||||
var namePath = 'Blockly';
|
||||
var value = Blockly;
|
||||
for (var i =0; i < blocklyNamePath.length; ++i) {
|
||||
for (var i = 0; i < blocklyNamePath.length; ++i) {
|
||||
namePath += '.' + blocklyNamePath[i];
|
||||
if (value) {
|
||||
value = value[blocklyNamePath[i]];
|
||||
@@ -633,8 +641,8 @@ Blockly.checkBlockColourConstant_ = function(
|
||||
|
||||
if (value && value !== expectedValue) {
|
||||
var warningPattern = (expectedValue === undefined) ?
|
||||
'%1 has been removed. Use Blockly.Msg.%2.' :
|
||||
'%1 is deprecated and unused. Override Blockly.Msg.%2.';
|
||||
'%1 has been removed. Use Blockly.Msg["%2"].' :
|
||||
'%1 is deprecated and unused. Override Blockly.Msg["%2"].';
|
||||
var warning = warningPattern.replace('%1', namePath).replace('%2', msgName);
|
||||
console.warn(warning);
|
||||
}
|
||||
|
||||
@@ -304,6 +304,25 @@ Blockly.Bubble.prototype.bubbleMouseDown_ = function(e) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the context menu for this bubble.
|
||||
* @param {!Event} _e Mouse event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Bubble.prototype.showContextMenu_ = function(_e) {
|
||||
// NOP on bubbles, but used by the bubble dragger to pass events to
|
||||
// workspace comments.
|
||||
};
|
||||
|
||||
/**
|
||||
* Get whether this bubble is deletable or not.
|
||||
* @return {boolean} True if deletable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Bubble.prototype.isDeletable = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on bubble's resize corner.
|
||||
* @param {!Event} e Mouse down event.
|
||||
|
||||
+106
-12
@@ -26,21 +26,27 @@
|
||||
|
||||
goog.provide('Blockly.BubbleDragger');
|
||||
|
||||
goog.require('Blockly.Bubble');
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a bubble dragger. It moves bubbles around the workspace when they
|
||||
* are being dragged by a mouse or touch.
|
||||
* @param {!Blockly.Bubble} bubble The bubble to drag.
|
||||
* Class for a bubble dragger. It moves things on the bubble canvas around the
|
||||
* workspace when they are being dragged by a mouse or touch. These can be
|
||||
* block comments, mutators, warnings, or workspace comments.
|
||||
* @param {!Blockly.Bubble|!Blockly.WorkspaceCommentSvg} bubble The item on the
|
||||
* bubble canvas to drag.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
/**
|
||||
* The bubble that is being dragged.
|
||||
* @type {!Blockly.Bubble}
|
||||
* The item on the bubble canvas that is being dragged.
|
||||
* @type {!Blockly.Bubble|!Blockly.WorkspaceCommentSvg}
|
||||
* @private
|
||||
*/
|
||||
this.draggingBubble_ = bubble;
|
||||
@@ -52,6 +58,22 @@ Blockly.BubbleDragger = function(bubble, workspace) {
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
|
||||
/**
|
||||
* Which delete area the mouse pointer is over, if any.
|
||||
* One of {@link Blockly.DELETE_AREA_TRASH},
|
||||
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
|
||||
* @type {?number}
|
||||
* @private
|
||||
*/
|
||||
this.deleteArea_ = null;
|
||||
|
||||
/**
|
||||
* Whether the bubble would be deleted if dropped immediately.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.wouldDeleteBubble_ = false;
|
||||
|
||||
/**
|
||||
* The location of the top left corner of the dragging bubble's body at the
|
||||
* beginning of the drag, in workspace coordinates.
|
||||
@@ -95,6 +117,15 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() {
|
||||
if (this.dragSurface_) {
|
||||
this.moveToDragSurface_();
|
||||
}
|
||||
|
||||
this.draggingBubble_.setDragging && this.draggingBubble_.setDragging(true);
|
||||
|
||||
var toolbox = this.workspace_.getToolbox();
|
||||
if (toolbox) {
|
||||
var style = this.draggingBubble_.isDeletable() ? 'blocklyToolboxDelete' :
|
||||
'blocklyToolboxGrab';
|
||||
toolbox.addStyle(style);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -110,8 +141,55 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
|
||||
var newLoc = goog.math.Coordinate.sum(this.startXY_, delta);
|
||||
|
||||
this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc);
|
||||
// TODO (fenichel): Possibly update the cursor if dragging to the trash can
|
||||
// is allowed.
|
||||
|
||||
if (this.draggingBubble_.isDeletable()) {
|
||||
this.deleteArea_ = this.workspace_.isDeleteArea(e);
|
||||
this.updateCursorDuringBubbleDrag_();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shut the trash can and, if necessary, delete the dragging bubble.
|
||||
* Should be called at the end of a bubble drag.
|
||||
* @return {boolean} whether the bubble was deleted.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() {
|
||||
var trashcan = this.workspace_.trashcan;
|
||||
|
||||
if (this.wouldDeleteBubble_) {
|
||||
if (trashcan) {
|
||||
setTimeout(trashcan.close.bind(trashcan), 100);
|
||||
}
|
||||
// Fire a move event, so we know where to go back to for an undo.
|
||||
this.fireMoveEvent_();
|
||||
this.draggingBubble_.dispose(false, true);
|
||||
} else if (trashcan) {
|
||||
// Make sure the trash can is closed.
|
||||
trashcan.close();
|
||||
}
|
||||
return this.wouldDeleteBubble_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the cursor (and possibly the trash can lid) to reflect whether the
|
||||
* dragging bubble would be deleted if released immediately.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() {
|
||||
this.wouldDeleteBubble_ = this.deleteArea_ != Blockly.DELETE_AREA_NONE;
|
||||
var trashcan = this.workspace_.trashcan;
|
||||
if (this.wouldDeleteBubble_) {
|
||||
this.draggingBubble_.setDeleteStyle(true);
|
||||
if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) {
|
||||
trashcan.setOpen_(true);
|
||||
}
|
||||
} else {
|
||||
this.draggingBubble_.setDeleteStyle(false);
|
||||
if (trashcan) {
|
||||
trashcan.setOpen_(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -131,14 +209,24 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(
|
||||
|
||||
// Move the bubble to its final location.
|
||||
this.draggingBubble_.moveTo(newLoc.x, newLoc.y);
|
||||
// Put everything back onto the bubble canvas.
|
||||
if (this.dragSurface_) {
|
||||
this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas());
|
||||
}
|
||||
var deleted = this.maybeDeleteBubble_();
|
||||
|
||||
this.fireMoveEvent_();
|
||||
if (!deleted) {
|
||||
// Put everything back onto the bubble canvas.
|
||||
if (this.dragSurface_) {
|
||||
this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas());
|
||||
}
|
||||
|
||||
this.draggingBubble_.setDragging && this.draggingBubble_.setDragging(false);
|
||||
this.fireMoveEvent_();
|
||||
}
|
||||
this.workspace_.setResizesEnabled(true);
|
||||
|
||||
if (this.workspace_.toolbox_) {
|
||||
var style = this.draggingBubble_.isDeletable() ? 'blocklyToolboxDelete' :
|
||||
'blocklyToolboxGrab';
|
||||
this.workspace_.toolbox_.removeStyle(style);
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
};
|
||||
|
||||
@@ -147,6 +235,12 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(
|
||||
* @private
|
||||
*/
|
||||
Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() {
|
||||
if (this.draggingBubble_.isComment) {
|
||||
var event = new Blockly.Events.CommentMove(this.draggingBubble_);
|
||||
event.setOldCoordinate(this.startXY_);
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
}
|
||||
// TODO (fenichel): move events for comments.
|
||||
return;
|
||||
};
|
||||
|
||||
+11
-11
@@ -41,7 +41,7 @@ goog.require('goog.dom');
|
||||
Blockly.Connection = function(source, type) {
|
||||
/**
|
||||
* @type {!Blockly.Block}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.sourceBlock_ = source;
|
||||
/** @type {number} */
|
||||
@@ -89,28 +89,28 @@ Blockly.Connection.prototype.shadowDom_ = null;
|
||||
/**
|
||||
* Horizontal location of this connection.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.x_ = 0;
|
||||
|
||||
/**
|
||||
* Vertical location of this connection.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.y_ = 0;
|
||||
|
||||
/**
|
||||
* Has this connection been added to the connection database?
|
||||
* @type {boolean}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.inDB_ = false;
|
||||
|
||||
/**
|
||||
* Connection database for connections of this type on the current workspace.
|
||||
* @type {Blockly.ConnectionDB}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.db_ = null;
|
||||
|
||||
@@ -118,14 +118,14 @@ Blockly.Connection.prototype.db_ = null;
|
||||
* Connection database for connections compatible with this type on the
|
||||
* current workspace.
|
||||
* @type {Blockly.ConnectionDB}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.dbOpposite_ = null;
|
||||
|
||||
/**
|
||||
* Whether this connections is hidden (not tracked in a database) or not.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.hidden_ = null;
|
||||
|
||||
@@ -133,7 +133,7 @@ Blockly.Connection.prototype.hidden_ = null;
|
||||
* Connect two connections together. This is the connection on the superior
|
||||
* block.
|
||||
* @param {!Blockly.Connection} childConnection Connection on inferior block.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.connect_ = function(childConnection) {
|
||||
var parentConnection = this;
|
||||
@@ -498,7 +498,7 @@ Blockly.Connection.prototype.disconnect = function() {
|
||||
* Disconnect two blocks that are connected by this connection.
|
||||
* @param {!Blockly.Block} parentBlock The superior block.
|
||||
* @param {!Blockly.Block} childBlock The inferior block.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.disconnectInternal_ = function(parentBlock,
|
||||
childBlock) {
|
||||
@@ -518,7 +518,7 @@ Blockly.Connection.prototype.disconnectInternal_ = function(parentBlock,
|
||||
|
||||
/**
|
||||
* Respawn the shadow block if there was one connected to the this connection.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.respawnShadow_ = function() {
|
||||
var parentBlock = this.getSourceBlock();
|
||||
@@ -552,7 +552,7 @@ Blockly.Connection.prototype.targetBlock = function() {
|
||||
* value type system. E.g. square_root("Hello") is not compatible.
|
||||
* @param {!Blockly.Connection} otherConnection Connection to compare against.
|
||||
* @return {boolean} True if the connections share a type.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.checkType_ = function(otherConnection) {
|
||||
if (!this.check_ || !otherConnection.check_) {
|
||||
|
||||
+109
-9
@@ -215,15 +215,15 @@ Blockly.ContextMenu.callbackFactory = function(block, xml) {
|
||||
Blockly.ContextMenu.blockDeleteOption = function(block) {
|
||||
// Option to delete this block but not blocks lower in the stack.
|
||||
// Count the number of blocks that are nested in this block.
|
||||
var descendantCount = block.getDescendants(true).length;
|
||||
var descendantCount = block.getDescendants(false).length;
|
||||
var nextBlock = block.getNextBlock();
|
||||
if (nextBlock) {
|
||||
// Blocks in the current stack would survive this block's deletion.
|
||||
descendantCount -= nextBlock.getDescendants(true).length;
|
||||
descendantCount -= nextBlock.getDescendants(false).length;
|
||||
}
|
||||
var deleteOption = {
|
||||
text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK :
|
||||
Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(descendantCount)),
|
||||
text: descendantCount == 1 ? Blockly.Msg['DELETE_BLOCK'] :
|
||||
Blockly.Msg['DELETE_X_BLOCKS'].replace('%1', String(descendantCount)),
|
||||
enabled: true,
|
||||
callback: function() {
|
||||
Blockly.Events.setGroup(true);
|
||||
@@ -244,7 +244,7 @@ Blockly.ContextMenu.blockHelpOption = function(block) {
|
||||
var url = goog.isFunction(block.helpUrl) ? block.helpUrl() : block.helpUrl;
|
||||
var helpOption = {
|
||||
enabled: !!url,
|
||||
text: Blockly.Msg.HELP,
|
||||
text: Blockly.Msg['HELP'],
|
||||
callback: function() {
|
||||
block.showHelp_();
|
||||
}
|
||||
@@ -260,11 +260,12 @@ Blockly.ContextMenu.blockHelpOption = function(block) {
|
||||
*/
|
||||
Blockly.ContextMenu.blockDuplicateOption = function(block) {
|
||||
var enabled = true;
|
||||
if (block.getDescendants().length > block.workspace.remainingCapacity()) {
|
||||
if (block.getDescendants(false).length >
|
||||
block.workspace.remainingCapacity()) {
|
||||
enabled = false;
|
||||
}
|
||||
var duplicateOption = {
|
||||
text: Blockly.Msg.DUPLICATE_BLOCK,
|
||||
text: Blockly.Msg['DUPLICATE_BLOCK'],
|
||||
enabled: enabled,
|
||||
callback: function() {
|
||||
Blockly.duplicate_(block);
|
||||
@@ -286,16 +287,115 @@ Blockly.ContextMenu.blockCommentOption = function(block) {
|
||||
};
|
||||
// If there's already a comment, add an option to delete it.
|
||||
if (block.comment) {
|
||||
commentOption.text = Blockly.Msg.REMOVE_COMMENT;
|
||||
commentOption.text = Blockly.Msg['REMOVE_COMMENT'];
|
||||
commentOption.callback = function() {
|
||||
block.setCommentText(null);
|
||||
};
|
||||
} else {
|
||||
// If there's no comment, add an option to create a comment.
|
||||
commentOption.text = Blockly.Msg.ADD_COMMENT;
|
||||
commentOption.text = Blockly.Msg['ADD_COMMENT'];
|
||||
commentOption.callback = function() {
|
||||
block.setCommentText('');
|
||||
};
|
||||
}
|
||||
return commentOption;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a context menu option for deleting the current workspace comment.
|
||||
* @param {!Blockly.WorkspaceCommentSvg} comment The workspace comment where the
|
||||
* right-click originated.
|
||||
* @return {!Object} A menu option, containing text, enabled, and a callback.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ContextMenu.commentDeleteOption = function(comment) {
|
||||
var deleteOption = {
|
||||
text: Blockly.Msg.REMOVE_COMMENT,
|
||||
enabled: true,
|
||||
callback: function() {
|
||||
Blockly.Events.setGroup(true);
|
||||
comment.dispose(true, true);
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
};
|
||||
return deleteOption;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a context menu option for duplicating the current workspace comment.
|
||||
* @param {!Blockly.WorkspaceCommentSvg} comment The workspace comment where the
|
||||
* right-click originated.
|
||||
* @return {!Object} A menu option, containing text, enabled, and a callback.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ContextMenu.commentDuplicateOption = function(comment) {
|
||||
var duplicateOption = {
|
||||
text: Blockly.Msg.DUPLICATE_COMMENT,
|
||||
enabled: true,
|
||||
callback: function() {
|
||||
Blockly.duplicate_(comment);
|
||||
}
|
||||
};
|
||||
return duplicateOption;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a context menu option for adding a comment on the workspace.
|
||||
* @param {!Blockly.WorkspaceSvg} ws The workspace where the right-click
|
||||
* originated.
|
||||
* @param {!Event} e The right-click mouse event.
|
||||
* @return {!Object} A menu option, containing text, enabled, and a callback.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ContextMenu.workspaceCommentOption = function(ws, e) {
|
||||
// Helper function to create and position a comment correctly based on the
|
||||
// location of the mouse event.
|
||||
var addWsComment = function() {
|
||||
var comment = new Blockly.WorkspaceCommentSvg(
|
||||
ws, Blockly.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT,
|
||||
Blockly.WorkspaceCommentSvg.DEFAULT_SIZE,
|
||||
Blockly.WorkspaceCommentSvg.DEFAULT_SIZE);
|
||||
|
||||
var injectionDiv = ws.getInjectionDiv();
|
||||
// Bounding rect coordinates are in client coordinates, meaning that they
|
||||
// are in pixels relative to the upper left corner of the visible browser
|
||||
// window. These coordinates change when you scroll the browser window.
|
||||
var boundingRect = injectionDiv.getBoundingClientRect();
|
||||
|
||||
// The client coordinates offset by the injection div's upper left corner.
|
||||
var clientOffsetPixels = new goog.math.Coordinate(
|
||||
e.clientX - boundingRect.left, e.clientY - boundingRect.top);
|
||||
|
||||
// The offset in pixels between the main workspace's origin and the upper
|
||||
// left corner of the injection div.
|
||||
var mainOffsetPixels = ws.getOriginOffsetInPixels();
|
||||
|
||||
// The position of the new comment in pixels relative to the origin of the
|
||||
// main workspace.
|
||||
var finalOffsetPixels = goog.math.Coordinate.difference(clientOffsetPixels,
|
||||
mainOffsetPixels);
|
||||
|
||||
// The position of the new comment in main workspace coordinates.
|
||||
var finalOffsetMainWs = finalOffsetPixels.scale(1 / ws.scale);
|
||||
|
||||
var commentX = finalOffsetMainWs.x;
|
||||
var commentY = finalOffsetMainWs.y;
|
||||
comment.moveBy(commentX, commentY);
|
||||
if (ws.rendered) {
|
||||
comment.initSvg();
|
||||
comment.render(false);
|
||||
comment.select();
|
||||
}
|
||||
};
|
||||
|
||||
var wsCommentOption = {
|
||||
// Foreign objects don't work in IE. Don't let the user create comments
|
||||
// that they won't be able to edit.
|
||||
enabled: !goog.userAgent.IE
|
||||
};
|
||||
wsCommentOption.text = Blockly.Msg.ADD_COMMENT;
|
||||
wsCommentOption.callback = function() {
|
||||
addWsComment();
|
||||
};
|
||||
return wsCommentOption;
|
||||
};
|
||||
|
||||
+62
-6
@@ -189,7 +189,7 @@ Blockly.Css.CONTENT = [
|
||||
'}',
|
||||
|
||||
'.blocklyResizeLine {',
|
||||
'stroke: #888;',
|
||||
'stroke: #515A5A;',
|
||||
'stroke-width: 1;',
|
||||
'}',
|
||||
|
||||
@@ -383,17 +383,76 @@ Blockly.Css.CONTENT = [
|
||||
'padding: 0;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentForeignObject {',
|
||||
'position: relative;',
|
||||
'z-index: 0;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentRect {',
|
||||
'fill: #E7DE8E;',
|
||||
'stroke: #bcA903;',
|
||||
'stroke-width: 1px',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentTarget {',
|
||||
'fill: transparent;',
|
||||
'stroke: #bcA903;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentTargetFocused {',
|
||||
'fill: none;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentHandleTarget {',
|
||||
'fill: none;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentHandleTargetFocused {',
|
||||
'fill: transparent;',
|
||||
'}',
|
||||
|
||||
'.blocklyFocused>.blocklyCommentRect {',
|
||||
'fill: #B9B272;',
|
||||
'stroke: #B9B272;',
|
||||
'}',
|
||||
|
||||
'.blocklySelected>.blocklyCommentTarget {',
|
||||
'stroke: #fc3;',
|
||||
'stroke-width: 3px;',
|
||||
'}',
|
||||
|
||||
|
||||
'.blocklyCommentTextarea {',
|
||||
'background-color: #ffc;',
|
||||
'background-color: #fef49c;',
|
||||
'border: 0;',
|
||||
'outline: 0;',
|
||||
'margin: 0;',
|
||||
'padding: 2px;',
|
||||
'padding: 3px;',
|
||||
'resize: none;',
|
||||
'display: block;',
|
||||
'overflow: hidden;',
|
||||
'}',
|
||||
|
||||
'.blocklyCommentDeleteIcon {',
|
||||
'cursor: pointer;',
|
||||
'fill: #000;',
|
||||
'display: none',
|
||||
'}',
|
||||
|
||||
'.blocklySelected > .blocklyCommentDeleteIcon {',
|
||||
'display: block',
|
||||
'}',
|
||||
|
||||
'.blocklyDeleteIconShape {',
|
||||
'fill: #000;',
|
||||
'stroke: #000;',
|
||||
'stroke-width: 1px;',
|
||||
'}',
|
||||
|
||||
'.blocklyDeleteIconShape.blocklyDeleteIconHighlighted {',
|
||||
'stroke: #fc3;',
|
||||
'}',
|
||||
|
||||
'.blocklyHtmlInput {',
|
||||
'border: none;',
|
||||
'border-radius: 4px;',
|
||||
@@ -508,9 +567,6 @@ Blockly.Css.CONTENT = [
|
||||
|
||||
'.blocklyDropdownMenu {',
|
||||
'padding: 0 !important;',
|
||||
/* max-height value is same as the constant
|
||||
* Blockly.FieldDropdown.MAX_MENU_HEIGHT defined in field_dropdown.js. */
|
||||
'max-height: 300px !important;',
|
||||
'}',
|
||||
|
||||
/* Override the default Closure URL. */
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
goog.provide('Blockly.DraggedConnectionManager');
|
||||
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.RenderedConnection');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
@@ -124,6 +125,16 @@ Blockly.DraggedConnectionManager.prototype.wouldDeleteBlock = function() {
|
||||
return this.wouldDeleteBlock_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether the block would be connected if dropped immediately, based on
|
||||
* information from the most recent move event.
|
||||
* @return {boolean} true if the block would be connected if dropped immediately.
|
||||
* @package
|
||||
*/
|
||||
Blockly.DraggedConnectionManager.prototype.wouldConnectBlock = function() {
|
||||
return !!this.closestConnection_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the closest connection and render the results.
|
||||
* This should be called at the end of a drag.
|
||||
@@ -138,7 +149,8 @@ Blockly.DraggedConnectionManager.prototype.applyConnections = function() {
|
||||
// Determine which connection is inferior (lower in the source stack).
|
||||
var inferiorConnection = this.localConnection_.isSuperior() ?
|
||||
this.closestConnection_ : this.localConnection_;
|
||||
inferiorConnection.getSourceBlock().connectionUiEffect();
|
||||
Blockly.BlockAnimations.connectionUiEffect(
|
||||
inferiorConnection.getSourceBlock());
|
||||
// Bring the just-edited stack to the front.
|
||||
var rootBlock = this.topBlock_.getRootBlock();
|
||||
rootBlock.bringToFront();
|
||||
@@ -213,7 +225,7 @@ Blockly.DraggedConnectionManager.prototype.addHighlighting_ = function() {
|
||||
Blockly.DraggedConnectionManager.prototype.initAvailableConnections_ = function() {
|
||||
var available = this.topBlock_.getConnections_(false);
|
||||
// Also check the last connection on this stack
|
||||
var lastOnStack = this.topBlock_.lastConnectionInStack_();
|
||||
var lastOnStack = this.topBlock_.lastConnectionInStack();
|
||||
if (lastOnStack && lastOnStack != this.topBlock_.nextConnection) {
|
||||
available.push(lastOnStack);
|
||||
}
|
||||
|
||||
+50
-7
@@ -126,6 +126,30 @@ Blockly.Events.VAR_RENAME = 'var_rename';
|
||||
*/
|
||||
Blockly.Events.UI = 'ui';
|
||||
|
||||
/**
|
||||
* Name of event that creates a comment.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Events.COMMENT_CREATE = 'comment_create';
|
||||
|
||||
/**
|
||||
* Name of event that deletes a comment.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Events.COMMENT_DELETE = 'comment_delete';
|
||||
|
||||
/**
|
||||
* Name of event that changes a comment.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Events.COMMENT_CHANGE = 'comment_change';
|
||||
|
||||
/**
|
||||
* Name of event that moves a comment.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Events.COMMENT_MOVE = 'comment_move';
|
||||
|
||||
/**
|
||||
* List of events queued for firing.
|
||||
* @private
|
||||
@@ -180,15 +204,22 @@ Blockly.Events.filter = function(queueIn, forward) {
|
||||
for (var i = 0, event; event = queue[i]; i++) {
|
||||
if (!event.isNull()) {
|
||||
var key = [event.type, event.blockId, event.workspaceId].join(' ');
|
||||
var lastEvent = hash[key];
|
||||
if (!lastEvent) {
|
||||
hash[key] = event;
|
||||
|
||||
var lastEntry = hash[key];
|
||||
var lastEvent = lastEntry ? lastEntry.event : null;
|
||||
if (!lastEntry) {
|
||||
// Each item in the hash table has the event and the index of that event
|
||||
// in the input array. This lets us make sure we only merge adjacent
|
||||
// move events.
|
||||
hash[key] = { event: event, index: i};
|
||||
mergedQueue.push(event);
|
||||
} else if (event.type == Blockly.Events.MOVE) {
|
||||
} else if (event.type == Blockly.Events.MOVE &&
|
||||
lastEntry.index == i - 1) {
|
||||
// Merge move events.
|
||||
lastEvent.newParentId = event.newParentId;
|
||||
lastEvent.newInputName = event.newInputName;
|
||||
lastEvent.newCoordinate = event.newCoordinate;
|
||||
lastEntry.index = i;
|
||||
} else if (event.type == Blockly.Events.CHANGE &&
|
||||
event.element == lastEvent.element &&
|
||||
event.name == lastEvent.name) {
|
||||
@@ -203,7 +234,7 @@ Blockly.Events.filter = function(queueIn, forward) {
|
||||
lastEvent.newValue = event.newValue;
|
||||
} else {
|
||||
// Collision: newer events should merge into this event to maintain order
|
||||
hash[key] = event;
|
||||
hash[key] = { event: event, index: 1};
|
||||
mergedQueue.push(event);
|
||||
}
|
||||
}
|
||||
@@ -287,7 +318,7 @@ Blockly.Events.setGroup = function(state) {
|
||||
*/
|
||||
Blockly.Events.getDescendantIds_ = function(block) {
|
||||
var ids = [];
|
||||
var descendants = block.getDescendants();
|
||||
var descendants = block.getDescendants(false);
|
||||
for (var i = 0, descendant; descendant = descendants[i]; i++) {
|
||||
ids[i] = descendant.id;
|
||||
}
|
||||
@@ -328,6 +359,18 @@ Blockly.Events.fromJson = function(json, workspace) {
|
||||
case Blockly.Events.UI:
|
||||
event = new Blockly.Events.Ui(null);
|
||||
break;
|
||||
case Blockly.Events.COMMENT_CREATE:
|
||||
event = new Blockly.Events.CommentCreate(null);
|
||||
break;
|
||||
case Blockly.Events.COMMENT_CHANGE:
|
||||
event = new Blockly.Events.CommentChange(null);
|
||||
break;
|
||||
case Blockly.Events.COMMENT_MOVE:
|
||||
event = new Blockly.Events.CommentMove(null);
|
||||
break;
|
||||
case Blockly.Events.COMMENT_DELETE:
|
||||
event = new Blockly.Events.CommentDelete(null);
|
||||
break;
|
||||
default:
|
||||
throw 'Unknown event type.';
|
||||
}
|
||||
@@ -350,7 +393,7 @@ Blockly.Events.disableOrphans = function(event) {
|
||||
var block = workspace.getBlockById(event.blockId);
|
||||
if (block) {
|
||||
if (block.getParent() && !block.getParent().disabled) {
|
||||
var children = block.getDescendants();
|
||||
var children = block.getDescendants(false);
|
||||
for (var i = 0, child; child = children[i]; i++) {
|
||||
child.setDisabled(false);
|
||||
}
|
||||
|
||||
+12
-4
@@ -360,10 +360,7 @@ Blockly.Field.prototype.render_ = function() {
|
||||
}
|
||||
|
||||
// Replace the text.
|
||||
goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_));
|
||||
var textNode = document.createTextNode(this.getDisplayText_());
|
||||
this.textElement_.appendChild(textNode);
|
||||
|
||||
this.textElement_.textContent = this.getDisplayText_();
|
||||
this.updateWidth();
|
||||
};
|
||||
|
||||
@@ -604,3 +601,14 @@ Blockly.Field.prototype.setTooltip = function(_newTip) {
|
||||
Blockly.Field.prototype.getAbsoluteXY_ = function() {
|
||||
return goog.style.getPageOffset(this.borderRect_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether this field references any Blockly variables. If true it may need to
|
||||
* be handled differently during serialization and deserialization. Subclasses
|
||||
* may override this.
|
||||
* @return {boolean} True if this field has any variable references.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Field.prototype.referencesVariables = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
+51
-50
@@ -53,7 +53,11 @@ goog.require('goog.userAgent');
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldDropdown = function(menuGenerator, opt_validator) {
|
||||
if (!goog.isFunction(menuGenerator)) {
|
||||
Blockly.FieldDropdown.validateOptions_(menuGenerator);
|
||||
}
|
||||
this.menuGenerator_ = menuGenerator;
|
||||
|
||||
this.trimOptions_();
|
||||
var firstTuple = this.getOptions()[0];
|
||||
|
||||
@@ -80,10 +84,9 @@ Blockly.FieldDropdown.fromJson = function(options) {
|
||||
Blockly.FieldDropdown.CHECKMARK_OVERHANG = 25;
|
||||
|
||||
/**
|
||||
* Maximum height of the dropdown menu,it's also referenced in css.js as
|
||||
* part of .blocklyDropdownMenu.
|
||||
* Maximum height of the dropdown menu, as a percentage of the viewport height.
|
||||
*/
|
||||
Blockly.FieldDropdown.MAX_MENU_HEIGHT = 300;
|
||||
Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH = 0.45;
|
||||
|
||||
/**
|
||||
* Android can't (in 2014) display "▾", so use "▼" instead.
|
||||
@@ -141,19 +144,8 @@ Blockly.FieldDropdown.prototype.init = function() {
|
||||
Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
||||
Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, null);
|
||||
var menu = this.createMenu_();
|
||||
this.addEventListeners_(menu);
|
||||
this.positionMenu_(menu);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add event listeners for actions on the items in the dropdown menu.
|
||||
* @param {!goog.ui.Menu} menu The menu to add listeners to.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.addEventListeners_ = function(menu) {
|
||||
this.addActionListener_(menu);
|
||||
this.addTouchStartListener_(menu);
|
||||
this.addTouchEndListener_(menu);
|
||||
this.positionMenu_(menu);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -177,38 +169,6 @@ Blockly.FieldDropdown.prototype.addActionListener_ = function(menu) {
|
||||
goog.events.listen(menu, goog.ui.Component.EventType.ACTION, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a listener for touch start events on menu items.
|
||||
* @param {!goog.ui.Menu} menu The menu to add the listener to.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.addTouchStartListener_ = function(menu) {
|
||||
// Listen for touch events (why doesn't Closure handle this already?).
|
||||
function callback(e) {
|
||||
var control = this.getOwnerControl(/** @type {Node} */ (e.target));
|
||||
// Highlight the menu item.
|
||||
control.handleMouseDown(e);
|
||||
}
|
||||
menu.getHandler().listen(
|
||||
menu.getElement(), goog.events.EventType.TOUCHSTART, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a listener for touch end events on menu items.
|
||||
* @param {!goog.ui.Menu} menu The menu to add the listener to.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.addTouchEndListener_ = function(menu) {
|
||||
// Listen for touch events (why doesn't Closure handle this already?).
|
||||
function callbackTouchEnd(e) {
|
||||
var control = this.getOwnerControl(/** @type {Node} */ (e.target));
|
||||
// Activate the menu item.
|
||||
control.performActionInternal(e);
|
||||
}
|
||||
menu.getHandler().listen(
|
||||
menu.getElement(), goog.events.EventType.TOUCHEND, callbackTouchEnd);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and populate the menu and menu items for this dropdown, based on
|
||||
* the options list.
|
||||
@@ -254,8 +214,10 @@ Blockly.FieldDropdown.prototype.positionMenu_ = function(menu) {
|
||||
this.createWidget_(menu);
|
||||
var menuSize = Blockly.utils.uiMenu.getSize(menu);
|
||||
|
||||
if (menuSize.height > Blockly.FieldDropdown.MAX_MENU_HEIGHT) {
|
||||
menuSize.height = Blockly.FieldDropdown.MAX_MENU_HEIGHT;
|
||||
var menuMaxHeightPx = Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH
|
||||
* document.documentElement.clientHeight;
|
||||
if (menuSize.height > menuMaxHeightPx) {
|
||||
menuSize.height = menuMaxHeightPx;
|
||||
}
|
||||
|
||||
if (this.sourceBlock_.RTL) {
|
||||
@@ -407,10 +369,13 @@ Blockly.FieldDropdown.prototype.isOptionListDynamic = function() {
|
||||
* Return a list of the options for this dropdown.
|
||||
* @return {!Array.<!Array>} Array of option tuples:
|
||||
* (human-readable text or image, language-neutral name).
|
||||
* @throws If generated options are incorrectly structured.
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.getOptions = function() {
|
||||
if (goog.isFunction(this.menuGenerator_)) {
|
||||
return this.menuGenerator_.call(this);
|
||||
var generatedOptions = this.menuGenerator_.call(this);
|
||||
Blockly.FieldDropdown.validateOptions_(generatedOptions);
|
||||
return generatedOptions;
|
||||
}
|
||||
return /** @type {!Array.<!Array.<string>>} */ (this.menuGenerator_);
|
||||
};
|
||||
@@ -565,4 +530,40 @@ Blockly.FieldDropdown.prototype.dispose = function() {
|
||||
Blockly.FieldDropdown.superClass_.dispose.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the data structure to be processed as an options list.
|
||||
* @param {?} options The proposed dropdown options.
|
||||
* @throws If proposed options are incorrectly structured.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.validateOptions_ = function(options) {
|
||||
if (!goog.isArray(options)) {
|
||||
throw 'FieldDropdown options must be an array.';
|
||||
}
|
||||
var foundError = false;
|
||||
for (var i = 0; i < options.length; ++i) {
|
||||
var tuple = options[i];
|
||||
if (!goog.isArray(options)) {
|
||||
foundError = true;
|
||||
console.error(
|
||||
'Invalid option[' + i + ']: Each FieldDropdown option must be an ' +
|
||||
'array. Found: ', tuple);
|
||||
} else if (!goog.isString(tuple[1])) {
|
||||
foundError = true;
|
||||
console.error(
|
||||
'Invalid option[' + i + ']: Each FieldDropdown option id must be ' +
|
||||
'a string. Found ' + tuple[1] + ' in: ', tuple);
|
||||
} else if (!goog.isString(tuple[0]) && !goog.isString(tuple[0].src)) {
|
||||
foundError = true;
|
||||
console.error(
|
||||
'Invalid option[' + i + ']: Each FieldDropdown option must have a ' +
|
||||
'string label or image description. Found' + tuple[0] + ' in: ',
|
||||
tuple);
|
||||
}
|
||||
}
|
||||
if (foundError) {
|
||||
throw 'Found invalid FieldDropdown options.';
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Field.register('field_dropdown', Blockly.FieldDropdown);
|
||||
|
||||
@@ -173,7 +173,7 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showPromptEditor_ = function() {
|
||||
var fieldText = this;
|
||||
Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_,
|
||||
Blockly.prompt(Blockly.Msg['CHANGE_VALUE_TITLE'], this.text_,
|
||||
function(newValue) {
|
||||
if (fieldText.sourceBlock_) {
|
||||
newValue = fieldText.callValidator(newValue);
|
||||
|
||||
+13
-3
@@ -314,11 +314,11 @@ Blockly.FieldVariable.dropdownCreate = function() {
|
||||
// Set the UUID as the internal representation of the variable.
|
||||
options[i] = [variableModelList[i].name, variableModelList[i].getId()];
|
||||
}
|
||||
options.push([Blockly.Msg.RENAME_VARIABLE, Blockly.RENAME_VARIABLE_ID]);
|
||||
if (Blockly.Msg.DELETE_VARIABLE) {
|
||||
options.push([Blockly.Msg['RENAME_VARIABLE'], Blockly.RENAME_VARIABLE_ID]);
|
||||
if (Blockly.Msg['DELETE_VARIABLE']) {
|
||||
options.push(
|
||||
[
|
||||
Blockly.Msg.DELETE_VARIABLE.replace('%1', name),
|
||||
Blockly.Msg['DELETE_VARIABLE'].replace('%1', name),
|
||||
Blockly.DELETE_VARIABLE_ID
|
||||
]
|
||||
);
|
||||
@@ -353,4 +353,14 @@ Blockly.FieldVariable.prototype.onItemSelected = function(menu, menuItem) {
|
||||
this.setValue(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Overrides referencesVariables(), indicating this field refers to a variable.
|
||||
* @return {boolean} True.
|
||||
* @package
|
||||
* @override
|
||||
*/
|
||||
Blockly.FieldVariable.prototype.referencesVariables = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
Blockly.Field.register('field_variable', Blockly.FieldVariable);
|
||||
|
||||
+21
-14
@@ -50,7 +50,7 @@ Blockly.Flyout = function(workspaceOptions) {
|
||||
|
||||
/**
|
||||
* @type {!Blockly.Workspace}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions);
|
||||
this.workspace_.isFlyout = true;
|
||||
@@ -64,7 +64,7 @@ Blockly.Flyout = function(workspaceOptions) {
|
||||
/**
|
||||
* Position of the toolbox and flyout relative to the workspace.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.toolboxPosition_ = workspaceOptions.toolboxPosition;
|
||||
|
||||
@@ -86,7 +86,7 @@ Blockly.Flyout = function(workspaceOptions) {
|
||||
/**
|
||||
* List of visible buttons.
|
||||
* @type {!Array.<!Blockly.FlyoutButton>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
this.buttons_ = [];
|
||||
|
||||
@@ -165,14 +165,14 @@ Blockly.Flyout.prototype.SCROLLBAR_PADDING = 2;
|
||||
/**
|
||||
* Width of flyout.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.width_ = 0;
|
||||
|
||||
/**
|
||||
* Height of flyout.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.height_ = 0;
|
||||
|
||||
@@ -190,7 +190,7 @@ Blockly.Flyout.prototype.height_ = 0;
|
||||
* This is used to know when to create a new block and when to scroll the
|
||||
* flyout. Setting it to 360 means that all drags create a new block.
|
||||
* @type {number}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.dragAngleRange_ = 70;
|
||||
|
||||
@@ -366,13 +366,20 @@ Blockly.Flyout.prototype.updateDisplay_ = function() {
|
||||
* @param {number} height The computed height of the flyout's SVG group.
|
||||
* @param {number} x The computed x origin of the flyout's SVG group.
|
||||
* @param {number} y The computed y origin of the flyout's SVG group.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) {
|
||||
this.svgGroup_.setAttribute("width", width);
|
||||
this.svgGroup_.setAttribute("height", height);
|
||||
var transform = 'translate(' + x + 'px,' + y + 'px)';
|
||||
Blockly.utils.setCssTransform(this.svgGroup_, transform);
|
||||
if (this.svgGroup_.tagName == 'svg') {
|
||||
var transform = 'translate(' + x + 'px,' + y + 'px)';
|
||||
Blockly.utils.setCssTransform(this.svgGroup_, transform);
|
||||
} else {
|
||||
// IE and Edge don't support CSS transforms on SVG elements so
|
||||
// it's important to set the transform on the SVG element itself
|
||||
var transform = 'translate(' + x + ',' + y + ')';
|
||||
this.svgGroup_.setAttribute("transform", transform);
|
||||
}
|
||||
|
||||
// Update the scrollbar (if one exists).
|
||||
if (this.scrollbar_) {
|
||||
@@ -537,7 +544,7 @@ Blockly.Flyout.prototype.clearOldBlocks_ = function() {
|
||||
* @param {!Blockly.Block} block The block to add listeners for.
|
||||
* @param {!Element} rect The invisible rectangle under the block that acts as
|
||||
* a mat for that block.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) {
|
||||
this.listeners_.push(Blockly.bindEventWithChecks_(root, 'mousedown', null,
|
||||
@@ -629,7 +636,7 @@ Blockly.Flyout.prototype.createBlock = function(originalBlock) {
|
||||
* @param {!Blockly.FlyoutButton} button The button to initialize and place.
|
||||
* @param {number} x The x position of the cursor during this layout pass.
|
||||
* @param {number} y The y position of the cursor during this layout pass.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) {
|
||||
var buttonSvg = button.createDom();
|
||||
@@ -655,7 +662,7 @@ Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) {
|
||||
* placed.
|
||||
* @return {!SVGElement} Newly created SVG element for the rectangle behind the
|
||||
* block.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) {
|
||||
// Create an invisible rectangle under the block to act as a button. Just
|
||||
@@ -683,7 +690,7 @@ Blockly.Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) {
|
||||
* hats, and any other protrusions we invent.
|
||||
* @param {!SVGElement} rect The rectangle to move directly behind the block.
|
||||
* @param {!Blockly.BlockSvg} block The block the rectangle should be behind.
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.moveRectToBlock_ = function(rect, block) {
|
||||
var blockHW = block.getHeightWidth();
|
||||
@@ -717,7 +724,7 @@ Blockly.Flyout.prototype.filterForCapacity_ = function() {
|
||||
var blocks = this.workspace_.getTopBlocks(false);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
if (this.permanentlyDisabled_.indexOf(block) == -1) {
|
||||
var allBlocks = block.getDescendants();
|
||||
var allBlocks = block.getDescendants(false);
|
||||
block.setDisabled(allBlocks.length > remainingCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ Blockly.FlyoutButton.prototype.createDom = function() {
|
||||
'text-anchor': 'middle'
|
||||
},
|
||||
this.svgGroup_);
|
||||
svgText.textContent = this.text_;
|
||||
svgText.textContent = Blockly.utils.replaceMessageReferences(this.text_);
|
||||
|
||||
this.width = Blockly.Field.getCachedWidth(svgText);
|
||||
this.height = 20; // Can't compute it :(
|
||||
@@ -179,8 +179,8 @@ Blockly.FlyoutButton.prototype.createDom = function() {
|
||||
|
||||
this.updateTransform_();
|
||||
|
||||
this.mouseUpWrapper_ = Blockly.bindEventWithChecks_(this.svgGroup_, 'mouseup',
|
||||
this, this.onMouseUp_);
|
||||
this.onMouseUpWrapper_ = Blockly.bindEventWithChecks_(
|
||||
this.svgGroup_, 'mouseup', this, this.onMouseUp_);
|
||||
return this.svgGroup_;
|
||||
};
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
for (var i = 0, item; item = contents[i]; i++) {
|
||||
if (item.type == 'block') {
|
||||
var block = item.block;
|
||||
var allBlocks = block.getDescendants();
|
||||
var allBlocks = block.getDescendants(false);
|
||||
for (var j = 0, child; child = allBlocks[j]; j++) {
|
||||
// Mark blocks as being inside a flyout. This is used to detect and
|
||||
// prevent the closure of the flyout if the user right-clicks on such a
|
||||
|
||||
@@ -212,8 +212,9 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
var delta = e.deltaY;
|
||||
|
||||
if (delta) {
|
||||
if (goog.userAgent.GECKO) {
|
||||
// Firefox's deltas are a tenth that of Chrome/Safari.
|
||||
// Firefox's mouse wheel deltas are a tenth that of Chrome/Safari.
|
||||
// DeltaMode is 1 for a mouse wheel, but not for a trackpad scroll event
|
||||
if (goog.userAgent.GECKO && (e.deltaMode === 1)) {
|
||||
delta *= 10;
|
||||
}
|
||||
var metrics = this.getMetrics_();
|
||||
@@ -247,7 +248,7 @@ Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) {
|
||||
for (var i = 0, item; item = contents[i]; i++) {
|
||||
if (item.type == 'block') {
|
||||
var block = item.block;
|
||||
var allBlocks = block.getDescendants();
|
||||
var allBlocks = block.getDescendants(false);
|
||||
for (var j = 0, child; child = allBlocks[j]; j++) {
|
||||
// Mark blocks as being inside a flyout. This is used to detect and
|
||||
// prevent the closure of the flyout if the user right-clicks on such a
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ Blockly.Generator.prototype.prefixLines = function(text, prefix) {
|
||||
*/
|
||||
Blockly.Generator.prototype.allNestedComments = function(block) {
|
||||
var comments = [];
|
||||
var blocks = block.getDescendants();
|
||||
var blocks = block.getDescendants(true);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var comment = blocks[i].getCommentText();
|
||||
if (comment) {
|
||||
|
||||
+14
-7
@@ -27,6 +27,7 @@
|
||||
|
||||
goog.provide('Blockly.Gesture');
|
||||
|
||||
goog.require('Blockly.BlockAnimations');
|
||||
goog.require('Blockly.BlockDragger');
|
||||
goog.require('Blockly.BubbleDragger');
|
||||
goog.require('Blockly.constants');
|
||||
@@ -68,7 +69,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
|
||||
* @type {goog.math.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.currentDragDeltaXY_ = 0;
|
||||
this.currentDragDeltaXY_ = null;
|
||||
|
||||
/**
|
||||
* The bubble that the gesture started on, or null if it did not start on a
|
||||
@@ -468,7 +469,6 @@ Blockly.Gesture.prototype.startDraggingBubble_ = function() {
|
||||
this.bubbleDragger_.dragBubble(this.mostRecentEvent_,
|
||||
this.currentDragDeltaXY_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a gesture: update the workspace to indicate that a gesture is in
|
||||
* progress and bind mousemove and mouseup handlers.
|
||||
@@ -482,7 +482,7 @@ Blockly.Gesture.prototype.doStart = function(e) {
|
||||
}
|
||||
this.hasStarted_ = true;
|
||||
|
||||
Blockly.BlockSvg.disconnectUiStop_();
|
||||
Blockly.BlockAnimations.disconnectUiStop();
|
||||
this.startWorkspace_.updateScreenCalculationsIfScrolled();
|
||||
if (this.startWorkspace_.isMutator) {
|
||||
// Mutator's coordinate system could be out of date because the bubble was
|
||||
@@ -627,6 +627,8 @@ Blockly.Gesture.prototype.handleRightClick = function(e) {
|
||||
this.bringBlockToFront_();
|
||||
Blockly.hideChaff(this.flyout_);
|
||||
this.targetBlock_.showContextMenu_(e);
|
||||
} else if (this.startBubble_) {
|
||||
this.startBubble_.showContextMenu_(e);
|
||||
} else if (this.startWorkspace_ && !this.flyout_) {
|
||||
Blockly.hideChaff();
|
||||
this.startWorkspace_.showContextMenu_(e);
|
||||
@@ -705,8 +707,9 @@ Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) {
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doBubbleClick_ = function() {
|
||||
// TODO: This isn't really enough, is it.
|
||||
this.startBubble_.promote_();
|
||||
// TODO (#1673): Consistent handling of single clicks.
|
||||
this.startBubble_.setFocus && this.startBubble_.setFocus();
|
||||
this.startBubble_.select && this.startBubble_.select();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -751,6 +754,7 @@ Blockly.Gesture.prototype.doWorkspaceClick_ = function() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* End functions defining what actions to take to execute clicks on each type
|
||||
* of target. */
|
||||
|
||||
@@ -801,7 +805,8 @@ Blockly.Gesture.prototype.setStartBubble = function(bubble) {
|
||||
* @package
|
||||
*/
|
||||
Blockly.Gesture.prototype.setStartBlock = function(block) {
|
||||
if (!this.startBlock_) {
|
||||
// If the gesture already went through a bubble, don't set the start block.
|
||||
if (!this.startBlock_ && !this.startBubble_) {
|
||||
this.startBlock_ = block;
|
||||
if (block.isInFlyout && block != block.getRootBlock()) {
|
||||
this.setTargetBlock_(block.getRootBlock());
|
||||
@@ -848,6 +853,7 @@ Blockly.Gesture.prototype.setStartFlyout_ = function(flyout) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* End functions for populating a gesture at mouse down. */
|
||||
|
||||
/* Begin helper functions defining types of clicks. Any developer wanting
|
||||
@@ -898,7 +904,8 @@ Blockly.Gesture.prototype.isFieldClick_ = function() {
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.isWorkspaceClick_ = function() {
|
||||
var onlyTouchedWorkspace = !this.startBlock_ && !this.startField_;
|
||||
var onlyTouchedWorkspace = !this.startBlock_ && !this.startBubble_ &&
|
||||
!this.startField_;
|
||||
return onlyTouchedWorkspace && !this.hasExceededDragRadius_;
|
||||
};
|
||||
|
||||
|
||||
+1
-2
@@ -32,7 +32,6 @@ goog.require('Blockly.Events.BlockChange');
|
||||
goog.require('Blockly.Events.Ui');
|
||||
goog.require('Blockly.Icon');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
@@ -258,7 +257,7 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
|
||||
}
|
||||
|
||||
this.rootBlock_ = this.block_.decompose(this.workspace_);
|
||||
var blocks = this.rootBlock_.getDescendants();
|
||||
var blocks = this.rootBlock_.getDescendants(false);
|
||||
for (var i = 0, child; child = blocks[i]; i++) {
|
||||
child.render();
|
||||
}
|
||||
|
||||
+2
-2
@@ -188,7 +188,7 @@ Blockly.Procedures.flyoutCategory = function(workspace) {
|
||||
block.setAttribute('type', 'procedures_defnoreturn');
|
||||
block.setAttribute('gap', 16);
|
||||
var nameField = goog.dom.createDom('field', null,
|
||||
Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE);
|
||||
Blockly.Msg['PROCEDURES_DEFNORETURN_PROCEDURE']);
|
||||
nameField.setAttribute('name', 'NAME');
|
||||
block.appendChild(nameField);
|
||||
xmlList.push(block);
|
||||
@@ -201,7 +201,7 @@ Blockly.Procedures.flyoutCategory = function(workspace) {
|
||||
block.setAttribute('type', 'procedures_defreturn');
|
||||
block.setAttribute('gap', 16);
|
||||
var nameField = goog.dom.createDom('field', null,
|
||||
Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE);
|
||||
Blockly.Msg['PROCEDURES_DEFRETURN_PROCEDURE']);
|
||||
nameField.setAttribute('name', 'NAME');
|
||||
block.appendChild(nameField);
|
||||
xmlList.push(block);
|
||||
|
||||
@@ -180,16 +180,14 @@ Blockly.RenderedConnection.prototype.tighten_ = function() {
|
||||
* Find the closest compatible connection to this connection.
|
||||
* All parameters are in workspace units.
|
||||
* @param {number} maxLimit The maximum radius to another connection.
|
||||
* @param {number} dx Horizontal offset between this connection's location
|
||||
* in the database and the current location (as a result of dragging).
|
||||
* @param {number} dy Vertical offset between this connection's location
|
||||
* @param {!goog.math.Coordinate} dxy Offset between this connection's location
|
||||
* in the database and the current location (as a result of dragging).
|
||||
* @return {!{connection: ?Blockly.Connection, radius: number}} Contains two
|
||||
* properties: 'connection' which is either another connection or null,
|
||||
* and 'radius' which is the distance.
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.closest = function(maxLimit, dx, dy) {
|
||||
return this.dbOpposite_.searchForClosest(this, maxLimit, dx, dy);
|
||||
Blockly.RenderedConnection.prototype.closest = function(maxLimit, dxy) {
|
||||
return this.dbOpposite_.searchForClosest(this, maxLimit, dxy);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -286,7 +284,7 @@ Blockly.RenderedConnection.prototype.setHidden = function(hidden) {
|
||||
Blockly.RenderedConnection.prototype.hideAll = function() {
|
||||
this.setHidden(true);
|
||||
if (this.targetConnection) {
|
||||
var blocks = this.targetBlock().getDescendants();
|
||||
var blocks = this.targetBlock().getDescendants(false);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var block = blocks[i];
|
||||
// Hide all connections of all children.
|
||||
|
||||
+11
-7
@@ -334,15 +334,19 @@ Blockly.Toolbox.prototype.syncTrees_ = function(treeIn, treeOut, pathToMedia) {
|
||||
// (eg. `%{BKY_MATH_HUE}`).
|
||||
var colour = Blockly.utils.replaceMessageReferences(
|
||||
childIn.getAttribute('colour'));
|
||||
if (goog.isString(colour)) {
|
||||
if (/^#[0-9a-fA-F]{6}$/.test(colour)) {
|
||||
childOut.hexColour = colour;
|
||||
} else {
|
||||
childOut.hexColour = Blockly.hueToRgb(Number(colour));
|
||||
}
|
||||
if (colour === null || colour === '') {
|
||||
// No attribute. No colour.
|
||||
childOut.hexColour = '';
|
||||
} else if (/^#[0-9a-fA-F]{6}$/.test(colour)) {
|
||||
childOut.hexColour = colour;
|
||||
this.hasColours_ = true;
|
||||
} else if (typeof colour === 'number'
|
||||
|| (typeof colour === 'string' && !isNaN(Number(colour)))) {
|
||||
childOut.hexColour = Blockly.hueToRgb(Number(colour));
|
||||
this.hasColours_ = true;
|
||||
} else {
|
||||
childOut.hexColour = '';
|
||||
console.warn('Toolbox category "' + categoryName + '" has unrecognized colour attribute: ' + colour);
|
||||
}
|
||||
if (childIn.getAttribute('expanded') == 'true') {
|
||||
if (childOut.blocks.length) {
|
||||
@@ -396,7 +400,7 @@ Blockly.Toolbox.prototype.syncTrees_ = function(treeIn, treeOut, pathToMedia) {
|
||||
*/
|
||||
Blockly.Toolbox.prototype.addColour_ = function(opt_tree) {
|
||||
var tree = opt_tree || this.tree_;
|
||||
var children = tree.getChildren();
|
||||
var children = tree.getChildren(false);
|
||||
for (var i = 0, child; child = children[i]; i++) {
|
||||
var element = child.getRowElement();
|
||||
if (element) {
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ Blockly.Touch.touchIdentifier_ = null;
|
||||
* @type {Object}
|
||||
*/
|
||||
Blockly.Touch.TOUCH_MAP = {};
|
||||
if (window && window.PointerEvent) {
|
||||
if (goog.global.PointerEvent) {
|
||||
Blockly.Touch.TOUCH_MAP = {
|
||||
'mousedown': ['pointerdown'],
|
||||
'mouseenter': ['pointerenter'],
|
||||
|
||||
+3
-4
@@ -26,7 +26,6 @@
|
||||
|
||||
goog.provide('Blockly.Trashcan');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Rect');
|
||||
@@ -234,7 +233,7 @@ Blockly.Trashcan.prototype.dispose = function() {
|
||||
}
|
||||
this.svgLid_ = null;
|
||||
this.workspace_ = null;
|
||||
goog.Timer.clear(this.lidTask_);
|
||||
clearTimeout(this.lidTask_);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -299,7 +298,7 @@ Blockly.Trashcan.prototype.setOpen_ = function(state) {
|
||||
if (this.isOpen == state) {
|
||||
return;
|
||||
}
|
||||
goog.Timer.clear(this.lidTask_);
|
||||
clearTimeout(this.lidTask_);
|
||||
this.isOpen = state;
|
||||
this.animateLid_();
|
||||
};
|
||||
@@ -319,7 +318,7 @@ Blockly.Trashcan.prototype.animateLid_ = function() {
|
||||
var opacity = goog.math.lerp(0.4, 0.8, this.lidOpen_);
|
||||
this.svgGroup_.style.opacity = opacity;
|
||||
if (this.lidOpen_ > 0 && this.lidOpen_ < 1) {
|
||||
this.lidTask_ = goog.Timer.callOnce(this.animateLid_, 20, this);
|
||||
this.lidTask_ = setTimeout(this.animateLid_.bind(this), 20);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+7
-6
@@ -34,6 +34,10 @@ goog.require('goog.math.Coordinate');
|
||||
|
||||
/**
|
||||
* Class for a UI event.
|
||||
* UI events are events that don't need to be sent over the wire for multi-user
|
||||
* editing to work (e.g. scrolling the workspace, zooming, opening toolbox
|
||||
* categories).
|
||||
* UI events do not undo or redo.
|
||||
* @param {Blockly.Block} block The affected block.
|
||||
* @param {string} element One of 'selected', 'comment', 'mutator', etc.
|
||||
* @param {*} oldValue Previous value of element.
|
||||
@@ -42,16 +46,13 @@ goog.require('goog.math.Coordinate');
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.Ui = function(block, element, oldValue, newValue) {
|
||||
if (!block) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
|
||||
Blockly.Events.Ui.superClass_.constructor.call(this);
|
||||
this.blockId = block.id;
|
||||
this.workspaceId = block.workspace.id;
|
||||
this.blockId = block ? block.id : null;
|
||||
this.workspaceId = block ? block.workspace.id : null;
|
||||
this.element = element;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
// UI events do not undo or redo.
|
||||
this.recordUndo = false;
|
||||
};
|
||||
goog.inherits(Blockly.Events.Ui, Blockly.Events.Abstract);
|
||||
|
||||
+5
-47
@@ -39,19 +39,6 @@ goog.require('goog.math.Coordinate');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* To allow ADVANCED_OPTIMIZATIONS, combining variable.name and variable['name']
|
||||
* is not possible. To access the exported Blockly.Msg.Something it needs to be
|
||||
* accessed through the exact name that was exported. Note, that all the exports
|
||||
* are happening as the last thing in the generated js files, so they won't be
|
||||
* accessible before JavaScript loads!
|
||||
* @return {!Object.<string, string>} The message array.
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.getMessageArray_ = function() {
|
||||
return goog.global['Blockly']['Msg'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an attribute from a element even if it's in IE 10.
|
||||
* Similar to Element.removeAttribute() but it works on SVG elements in IE 10.
|
||||
@@ -210,9 +197,8 @@ Blockly.utils.getInjectionDivXY_ = function(element) {
|
||||
var y = 0;
|
||||
while (element) {
|
||||
var xy = Blockly.utils.getRelativeXY(element);
|
||||
var scale = Blockly.utils.getScale_(element);
|
||||
x = (x * scale) + xy.x;
|
||||
y = (y * scale) + xy.y;
|
||||
x = x + xy.x;
|
||||
y = y + xy.y;
|
||||
var classes = element.getAttribute('class') || '';
|
||||
if ((' ' + classes + ' ').indexOf(' injectionDiv ') != -1) {
|
||||
break;
|
||||
@@ -222,25 +208,6 @@ Blockly.utils.getInjectionDivXY_ = function(element) {
|
||||
return new goog.math.Coordinate(x, y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the scale of this element.
|
||||
* @param {!Element} element The element to find the coordinates of.
|
||||
* @return {!number} number represending the scale applied to the element.
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.getScale_ = function(element) {
|
||||
var scale = 1;
|
||||
var transform = element.getAttribute('transform');
|
||||
if (transform) {
|
||||
var transformComponents =
|
||||
transform.match(Blockly.utils.getScale_.REGEXP_);
|
||||
if (transformComponents && transformComponents[0]) {
|
||||
scale = parseFloat(transformComponents[0]);
|
||||
}
|
||||
}
|
||||
return scale;
|
||||
};
|
||||
|
||||
/**
|
||||
* Static regex to pull the x,y values out of an SVG translate() directive.
|
||||
* Note that Firefox and IE (9,10) return 'translate(12)' instead of
|
||||
@@ -253,15 +220,6 @@ Blockly.utils.getScale_ = function(element) {
|
||||
Blockly.utils.getRelativeXY.XY_REGEX_ =
|
||||
/translate\(\s*([-+\d.e]+)([ ,]\s*([-+\d.e]+)\s*\))?/;
|
||||
|
||||
|
||||
/**
|
||||
* Static regex to pull the scale values out of a transform style property.
|
||||
* Accounts for same exceptions as XY_REGEXP_.
|
||||
* @type {!RegExp}
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.getScale_REGEXP_ = /scale\(\s*([-+\d.e]+)\s*\)/;
|
||||
|
||||
/**
|
||||
* Static regex to pull the x,y,z values out of a translate3d() style property.
|
||||
* Accounts for same exceptions as XY_REGEXP_.
|
||||
@@ -464,7 +422,7 @@ Blockly.utils.replaceMessageReferences = function(message) {
|
||||
Blockly.utils.checkMessageReferences = function(message) {
|
||||
var validSoFar = true;
|
||||
|
||||
var msgTable = Blockly.utils.getMessageArray_();
|
||||
var msgTable = Blockly.Msg;
|
||||
|
||||
// TODO(#1169): Implement support for other string tables, prefixes other than BKY_.
|
||||
var regex = /%{(BKY_[A-Z][A-Z0-9_]*)}/gi;
|
||||
@@ -569,8 +527,8 @@ Blockly.utils.tokenizeInterpolation_ = function(message,
|
||||
// are defined in ../msgs/ files.
|
||||
var bklyKey = goog.string.startsWith(keyUpper, 'BKY_') ?
|
||||
keyUpper.substring(4) : null;
|
||||
if (bklyKey && bklyKey in Blockly.utils.getMessageArray_()) {
|
||||
var rawValue = Blockly.utils.getMessageArray_()[bklyKey];
|
||||
if (bklyKey && bklyKey in Blockly.Msg) {
|
||||
var rawValue = Blockly.Msg[bklyKey];
|
||||
if (goog.isString(rawValue)) {
|
||||
// Attempt to dereference substrings, too, appending to the end.
|
||||
Array.prototype.push.apply(tokens,
|
||||
|
||||
@@ -230,7 +230,7 @@ Blockly.VariableMap.prototype.deleteVariableById = function(id) {
|
||||
if (block.type == 'procedures_defnoreturn' ||
|
||||
block.type == 'procedures_defreturn') {
|
||||
var procedureName = block.getFieldValue('NAME');
|
||||
var deleteText = Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE.
|
||||
var deleteText = Blockly.Msg['CANNOT_DELETE_VARIABLE_PROCEDURE'].
|
||||
replace('%1', variableName).
|
||||
replace('%2', procedureName);
|
||||
Blockly.alert(deleteText);
|
||||
@@ -241,7 +241,7 @@ Blockly.VariableMap.prototype.deleteVariableById = function(id) {
|
||||
var map = this;
|
||||
if (uses.length > 1) {
|
||||
// Confirm before deleting multiple blocks.
|
||||
var confirmText = Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.
|
||||
var confirmText = Blockly.Msg['DELETE_VARIABLE_CONFIRMATION'].
|
||||
replace('%1', String(uses.length)).
|
||||
replace('%2', variableName);
|
||||
Blockly.confirm(confirmText,
|
||||
|
||||
+8
-8
@@ -129,7 +129,7 @@ Blockly.Variables.allDeveloperVariables = function(workspace) {
|
||||
Blockly.Variables.flyoutCategory = function(workspace) {
|
||||
var xmlList = [];
|
||||
var button = goog.dom.createDom('button');
|
||||
button.setAttribute('text', Blockly.Msg.NEW_VARIABLE);
|
||||
button.setAttribute('text', '%{BKY_NEW_VARIABLE}');
|
||||
button.setAttribute('callbackKey', 'CREATE_VARIABLE');
|
||||
|
||||
workspace.registerButtonCallback('CREATE_VARIABLE', function(button) {
|
||||
@@ -267,7 +267,7 @@ Blockly.Variables.createVariableButtonHandler = function(
|
||||
var type = opt_type || '';
|
||||
// This function needs to be named so it can be called recursively.
|
||||
var promptAndCheckWithAlert = function(defaultName) {
|
||||
Blockly.Variables.promptName(Blockly.Msg.NEW_VARIABLE_TITLE, defaultName,
|
||||
Blockly.Variables.promptName(Blockly.Msg['NEW_VARIABLE_TITLE'], defaultName,
|
||||
function(text) {
|
||||
if (text) {
|
||||
var existing =
|
||||
@@ -275,10 +275,10 @@ Blockly.Variables.createVariableButtonHandler = function(
|
||||
if (existing) {
|
||||
var lowerCase = text.toLowerCase();
|
||||
if (existing.type == type) {
|
||||
var msg = Blockly.Msg.VARIABLE_ALREADY_EXISTS.replace(
|
||||
var msg = Blockly.Msg['VARIABLE_ALREADY_EXISTS'].replace(
|
||||
'%1', lowerCase);
|
||||
} else {
|
||||
var msg = Blockly.Msg.VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE;
|
||||
var msg = Blockly.Msg['VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE'];
|
||||
msg = msg.replace('%1', lowerCase).replace('%2', existing.type);
|
||||
}
|
||||
Blockly.alert(msg,
|
||||
@@ -336,14 +336,14 @@ Blockly.Variables.renameVariable = function(workspace, variable,
|
||||
// This function needs to be named so it can be called recursively.
|
||||
var promptAndCheckWithAlert = function(defaultName) {
|
||||
var promptText =
|
||||
Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', variable.name);
|
||||
Blockly.Msg['RENAME_VARIABLE_TITLE'].replace('%1', variable.name);
|
||||
Blockly.Variables.promptName(promptText, defaultName,
|
||||
function(newName) {
|
||||
if (newName) {
|
||||
var existing = Blockly.Variables.nameUsedWithOtherType_(newName,
|
||||
variable.type, workspace);
|
||||
if (existing) {
|
||||
var msg = Blockly.Msg.VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE
|
||||
var msg = Blockly.Msg['VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE']
|
||||
.replace('%1', newName.toLowerCase())
|
||||
.replace('%2', existing.type);
|
||||
Blockly.alert(msg,
|
||||
@@ -380,8 +380,8 @@ Blockly.Variables.promptName = function(promptText, defaultText, callback) {
|
||||
// Beyond this, all names are legal.
|
||||
if (newVar) {
|
||||
newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
|
||||
if (newVar == Blockly.Msg.RENAME_VARIABLE ||
|
||||
newVar == Blockly.Msg.NEW_VARIABLE) {
|
||||
if (newVar == Blockly.Msg['RENAME_VARIABLE'] ||
|
||||
newVar == Blockly.Msg['NEW_VARIABLE']) {
|
||||
// Ok, not ALL names are legal...
|
||||
newVar = null;
|
||||
}
|
||||
|
||||
@@ -54,14 +54,14 @@ Blockly.VariablesDynamic.onCreateVariableButtonClick_Colour = function(button) {
|
||||
Blockly.VariablesDynamic.flyoutCategory = function(workspace) {
|
||||
var xmlList = [];
|
||||
var button = goog.dom.createDom('button');
|
||||
button.setAttribute('text', Blockly.Msg.NEW_STRING_VARIABLE);
|
||||
button.setAttribute('text', Blockly.Msg['NEW_STRING_VARIABLE']);
|
||||
button.setAttribute('callbackKey', 'CREATE_VARIABLE_STRING');
|
||||
xmlList.push(button);
|
||||
button = goog.dom.createDom('button');
|
||||
button.setAttribute('text', Blockly.Msg.NEW_NUMBER_VARIABLE);
|
||||
button.setAttribute('text', Blockly.Msg['NEW_NUMBER_VARIABLE']);
|
||||
button.setAttribute('callbackKey', 'CREATE_VARIABLE_NUMBER');
|
||||
xmlList.push(button);button = goog.dom.createDom('button');
|
||||
button.setAttribute('text', Blockly.Msg.NEW_COLOUR_VARIABLE);
|
||||
button.setAttribute('text', Blockly.Msg['NEW_COLOUR_VARIABLE']);
|
||||
button.setAttribute('callbackKey', 'CREATE_VARIABLE_COLOUR');
|
||||
xmlList.push(button);
|
||||
|
||||
|
||||
+123
-19
@@ -27,6 +27,7 @@
|
||||
goog.provide('Blockly.Workspace');
|
||||
|
||||
goog.require('Blockly.VariableMap');
|
||||
goog.require('Blockly.WorkspaceComment');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
|
||||
@@ -55,6 +56,16 @@ Blockly.Workspace = function(opt_options) {
|
||||
* @private
|
||||
*/
|
||||
this.topBlocks_ = [];
|
||||
/**
|
||||
* @type {!Array.<!Blockly.WorkspaceComment>}
|
||||
* @private
|
||||
*/
|
||||
this.topComments_ = [];
|
||||
/**
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
this.commentDB_ = Object.create(null);
|
||||
/**
|
||||
* @type {!Array.<!Function>}
|
||||
* @private
|
||||
@@ -104,6 +115,13 @@ Blockly.Workspace = function(opt_options) {
|
||||
*/
|
||||
Blockly.Workspace.prototype.rendered = false;
|
||||
|
||||
/**
|
||||
* Returns `true` if the workspace is currently in the process of a bulk clear.
|
||||
* @type {boolean}
|
||||
* @package
|
||||
*/
|
||||
Blockly.Workspace.prototype.isClearing = false;
|
||||
|
||||
/**
|
||||
* Maximum number of undo events in stack. `0` turns off undo, `Infinity` sets it to unlimited.
|
||||
* @type {number}
|
||||
@@ -171,34 +189,109 @@ Blockly.Workspace.prototype.getTopBlocks = function(ordered) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Find all blocks in workspace. No particular order.
|
||||
* Add a comment to the list of top comments.
|
||||
* @param {!Blockly.WorkspaceComment} comment comment to add.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Workspace.prototype.addTopComment = function(comment) {
|
||||
this.topComments_.push(comment);
|
||||
|
||||
// Note: If the comment database starts to hold block comments, this may need
|
||||
// to move to a separate function.
|
||||
if (this.commentDB_[comment.id]) {
|
||||
console.warn('Overriding an existing comment on this workspace, with id "' +
|
||||
comment.id + '"');
|
||||
}
|
||||
this.commentDB_[comment.id] = comment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a comment from the list of top comments.
|
||||
* @param {!Blockly.WorkspaceComment} comment comment to remove.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Workspace.prototype.removeTopComment = function(comment) {
|
||||
if (!goog.array.remove(this.topComments_, comment)) {
|
||||
throw 'Comment not present in workspace\'s list of top-most comments.';
|
||||
}
|
||||
// Note: If the comment database starts to hold block comments, this may need
|
||||
// to move to a separate function.
|
||||
delete this.commentDB_[comment.id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds the top-level comments and returns them. Comments are optionally sorted
|
||||
* by position; top to bottom (with slight LTR or RTL bias).
|
||||
* @param {boolean} ordered Sort the list if true.
|
||||
* @return {!Array.<!Blockly.WorkspaceComment>} The top-level comment objects.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Workspace.prototype.getTopComments = function(ordered) {
|
||||
// Copy the topComments_ list.
|
||||
var comments = [].concat(this.topComments_);
|
||||
if (ordered && comments.length > 1) {
|
||||
var offset = Math.sin(goog.math.toRadians(Blockly.Workspace.SCAN_ANGLE));
|
||||
if (this.RTL) {
|
||||
offset *= -1;
|
||||
}
|
||||
comments.sort(function(a, b) {
|
||||
var aXY = a.getRelativeToSurfaceXY();
|
||||
var bXY = b.getRelativeToSurfaceXY();
|
||||
return (aXY.y + offset * aXY.x) - (bXY.y + offset * bXY.x);
|
||||
});
|
||||
}
|
||||
return comments;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find all blocks in workspace. Blocks are optionally sorted
|
||||
* by position; top to bottom (with slight LTR or RTL bias).
|
||||
* @param {boolean} ordered Sort the list if true.
|
||||
* @return {!Array.<!Blockly.Block>} Array of blocks.
|
||||
*/
|
||||
Blockly.Workspace.prototype.getAllBlocks = function() {
|
||||
var blocks = this.getTopBlocks(false);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
blocks.push.apply(blocks, blocks[i].getChildren());
|
||||
Blockly.Workspace.prototype.getAllBlocks = function(ordered) {
|
||||
if (ordered) {
|
||||
// Slow, but ordered.
|
||||
var topBlocks = this.getTopBlocks(true);
|
||||
var blocks = [];
|
||||
for (var i = 0; i < topBlocks.length; i++) {
|
||||
blocks.push.apply(blocks, topBlocks[i].getDescendants(true));
|
||||
}
|
||||
} else {
|
||||
// Fast, but in no particular order.
|
||||
var blocks = this.getTopBlocks(false);
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
blocks.push.apply(blocks, blocks[i].getChildren(false));
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of all blocks in workspace.
|
||||
* Dispose of all blocks and comments in workspace.
|
||||
*/
|
||||
Blockly.Workspace.prototype.clear = function() {
|
||||
var existingGroup = Blockly.Events.getGroup();
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(true);
|
||||
}
|
||||
while (this.topBlocks_.length) {
|
||||
this.topBlocks_[0].dispose();
|
||||
}
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
this.variableMap_.clear();
|
||||
if (this.potentialVariableMap_) {
|
||||
this.potentialVariableMap_.clear();
|
||||
this.isClearing = true;
|
||||
try {
|
||||
var existingGroup = Blockly.Events.getGroup();
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(true);
|
||||
}
|
||||
while (this.topBlocks_.length) {
|
||||
this.topBlocks_[0].dispose();
|
||||
}
|
||||
while (this.topComments_.length) {
|
||||
this.topComments_[this.topComments_.length - 1].dispose();
|
||||
}
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
this.variableMap_.clear();
|
||||
if (this.potentialVariableMap_) {
|
||||
this.potentialVariableMap_.clear();
|
||||
}
|
||||
} finally {
|
||||
this.isClearing = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -446,6 +539,17 @@ Blockly.Workspace.prototype.getBlockById = function(id) {
|
||||
return this.blockDB_[id] || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the comment on this workspace with the specified ID.
|
||||
* @param {string} id ID of comment to find.
|
||||
* @return {Blockly.WorkspaceComment} The sought after comment or null if not
|
||||
* found.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Workspace.prototype.getCommentById = function(id) {
|
||||
return this.commentDB_[id] || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether all value and statement inputs in the workspace are filled
|
||||
* with blocks.
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2017 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 Object representing a code comment on the workspace.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceComment');
|
||||
|
||||
goog.require('Blockly.Events.CommentChange');
|
||||
goog.require('Blockly.Events.CommentCreate');
|
||||
goog.require('Blockly.Events.CommentDelete');
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a workspace comment.
|
||||
* @param {!Blockly.Workspace} workspace The block's workspace.
|
||||
* @param {string} content The content of this workspace comment.
|
||||
* @param {number} height Height of the comment.
|
||||
* @param {number} width Width of the comment.
|
||||
* @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
|
||||
* create a new ID.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) {
|
||||
/** @type {string} */
|
||||
this.id = (opt_id && !workspace.getCommentById(opt_id)) ?
|
||||
opt_id : Blockly.utils.genUid();
|
||||
|
||||
workspace.addTopComment(this);
|
||||
|
||||
/**
|
||||
* The comment's position in workspace units. (0, 0) is at the workspace's
|
||||
* origin; scale does not change this value.
|
||||
* @type {!goog.math.Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.xy_ = new goog.math.Coordinate(0, 0);
|
||||
|
||||
/**
|
||||
* The comment's height in workspace units. Scale does not change this value.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.height_ = height;
|
||||
|
||||
/**
|
||||
* The comment's width in workspace units. Scale does not change this value.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.width_ = width;
|
||||
|
||||
/**
|
||||
* @type {!Blockly.Workspace}
|
||||
*/
|
||||
this.workspace = workspace;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.RTL = workspace.RTL;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.deletable_ = true;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.movable_ = true;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!string}
|
||||
*/
|
||||
this.content_ = content;
|
||||
|
||||
/**
|
||||
* @package
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.isComment = true;
|
||||
|
||||
Blockly.WorkspaceComment.fireCreateEvent(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of this comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.dispose = function() {
|
||||
if (!this.workspace) {
|
||||
// The comment has already been deleted.
|
||||
return;
|
||||
}
|
||||
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
Blockly.Events.fire(new Blockly.Events.CommentDelete(this));
|
||||
}
|
||||
|
||||
// Remove from the list of top comments and the comment database.
|
||||
this.workspace.removeTopComment(this);
|
||||
this.workspace = null;
|
||||
};
|
||||
|
||||
// Height, width, x, and y are all stored on even non-rendered comments, to
|
||||
// preserve state if you pass the contents through a headless workspace.
|
||||
|
||||
/**
|
||||
* Get comment height.
|
||||
* @return {number} comment height.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getHeight = function() {
|
||||
return this.height_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set comment height.
|
||||
* @param {number} height comment height.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setHeight = function(height) {
|
||||
this.height_ = height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get comment width.
|
||||
* @return {number} comment width.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getWidth = function() {
|
||||
return this.width_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set comment width.
|
||||
* @param {number} width comment width.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setWidth = function(width) {
|
||||
this.width_ = width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get stored location.
|
||||
* @return {!goog.math.Coordinate} The comment's stored location. This is not
|
||||
* valid if the comment is currently being dragged.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getXY = function() {
|
||||
return this.xy_.clone();
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a comment by a relative offset.
|
||||
* @param {number} dx Horizontal offset, in workspace units.
|
||||
* @param {number} dy Vertical offset, in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.moveBy = function(dx, dy) {
|
||||
var event = new Blockly.Events.CommentMove(this);
|
||||
this.xy_.translate(dx, dy);
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get whether this comment is deletable or not.
|
||||
* @return {boolean} True if deletable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.isDeletable = function() {
|
||||
return this.deletable_ &&
|
||||
!(this.workspace && this.workspace.options.readOnly);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this comment is deletable or not.
|
||||
* @param {boolean} deletable True if deletable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setDeletable = function(deletable) {
|
||||
this.deletable_ = deletable;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get whether this comment is movable or not.
|
||||
* @return {boolean} True if movable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.isMovable = function() {
|
||||
return this.movable_ &&
|
||||
!(this.workspace && this.workspace.options.readOnly);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this comment is movable or not.
|
||||
* @param {boolean} movable True if movable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setMovable = function(movable) {
|
||||
this.movable_ = movable;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this comment's text.
|
||||
* @return {string} Comment text.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.getContent = function() {
|
||||
return this.content_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set this comment's content.
|
||||
* @param {string} content Comment content.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.setContent = function(content) {
|
||||
if (this.content_ != content) {
|
||||
Blockly.Events.fire(
|
||||
new Blockly.Events.CommentChange(this, this.content_, content));
|
||||
this.content_ = content;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a comment subtree as XML with XY coordinates.
|
||||
* @param {boolean=} opt_noId True if the encoder should skip the comment id.
|
||||
* @return {!Element} Tree of XML elements.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) {
|
||||
var element = this.toXml(opt_noId);
|
||||
element.setAttribute('x', Math.round(this.xy_.x));
|
||||
element.setAttribute('y', Math.round(this.xy_.y));
|
||||
element.setAttribute('h', this.height_);
|
||||
element.setAttribute('w', this.width_);
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a comment subtree as XML, but don't serialize the XY coordinates.
|
||||
* This method avoids some expensive metrics-related calls that are made in
|
||||
* toXmlWithXY().
|
||||
* @param {boolean=} opt_noId True if the encoder should skip the comment id.
|
||||
* @return {!Element} Tree of XML elements.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.prototype.toXml = function(opt_noId) {
|
||||
var commentElement = goog.dom.createDom('comment');
|
||||
if (!opt_noId) {
|
||||
commentElement.setAttribute('id', this.id);
|
||||
}
|
||||
commentElement.textContent = this.getContent();
|
||||
return commentElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire a create event for the given workspace comment, if comments are enabled.
|
||||
* @param {!Blockly.WorkspaceComment} comment The comment that was just created.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.fireCreateEvent = function(comment) {
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
var existingGroup = Blockly.Events.getGroup();
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(true);
|
||||
}
|
||||
try {
|
||||
Blockly.Events.fire(new Blockly.Events.CommentCreate(comment));
|
||||
} finally {
|
||||
if (!existingGroup) {
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode an XML comment tag and create a comment on the workspace.
|
||||
* @param {!Element} xmlComment XML comment element.
|
||||
* @param {!Blockly.Workspace} workspace The workspace.
|
||||
* @return {!Blockly.WorkspaceComment} The created workspace comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.fromXml = function(xmlComment, workspace) {
|
||||
var info = Blockly.WorkspaceComment.parseAttributes(xmlComment);
|
||||
|
||||
var comment = new Blockly.WorkspaceComment(
|
||||
workspace, info.content, info.h, info.w, info.id);
|
||||
|
||||
var commentX = parseInt(xmlComment.getAttribute('x'), 10);
|
||||
var commentY = parseInt(xmlComment.getAttribute('y'), 10);
|
||||
if (!isNaN(commentX) && !isNaN(commentY)) {
|
||||
comment.moveBy(commentX, commentY);
|
||||
}
|
||||
|
||||
Blockly.WorkspaceComment.fireCreateEvent(comment);
|
||||
return comment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode an XML comment tag and return the results in an object.
|
||||
* @param {!Element} xml XML comment element.
|
||||
* @return {!Object} An object containing the information about the comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceComment.parseAttributes = function(xml) {
|
||||
var xmlH = xml.getAttribute('h');
|
||||
var xmlW = xml.getAttribute('w');
|
||||
|
||||
return {
|
||||
/* @type {string} */
|
||||
id: xml.getAttribute('id'),
|
||||
/**
|
||||
* The height of the comment in workspace units, or 100 if not specified.
|
||||
* @type {number}
|
||||
*/
|
||||
h: xmlH ? parseInt(xmlH, 10) : 100,
|
||||
/**
|
||||
* The width of the comment in workspace units, or 100 if not specified.
|
||||
* @type {number}
|
||||
*/
|
||||
w: xmlW ? parseInt(xmlW, 10) : 100,
|
||||
/**
|
||||
* The x position of the comment in workspace coordinates, or NaN if not
|
||||
* specified in the XML.
|
||||
* @type {number}
|
||||
*/
|
||||
x: parseInt(xml.getAttribute('x'), 10),
|
||||
/**
|
||||
* The y position of the comment in workspace coordinates, or NaN if not
|
||||
* specified in the XML.
|
||||
* @type {number}
|
||||
*/
|
||||
y: parseInt(xml.getAttribute('y'), 10),
|
||||
/* @type {string} */
|
||||
content: xml.textContent
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2017 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 Methods for rendering a workspace comment as SVG
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceCommentSvg.render');
|
||||
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
|
||||
|
||||
/**
|
||||
* Size of the resize icon.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.RESIZE_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Radius of the border around the comment.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.BORDER_RADIUS = 3;
|
||||
|
||||
/**
|
||||
* Offset from the foreignobject edge to the textarea edge.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET = 2;
|
||||
|
||||
/**
|
||||
* Offset from the top to make room for a top bar.
|
||||
* @type {number}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.TOP_OFFSET = 10;
|
||||
|
||||
/**
|
||||
* Returns a bounding box describing the dimensions of this comment.
|
||||
* @return {!{height: number, width: number}} Object with height and width
|
||||
* properties in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getHeightWidth = function() {
|
||||
return { width: this.getWidth(), height: this.getHeight() };
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the workspace comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.render = function() {
|
||||
if (this.rendered_) {
|
||||
return;
|
||||
}
|
||||
|
||||
var size = this.getHeightWidth();
|
||||
|
||||
// Add text area
|
||||
this.createEditor_();
|
||||
this.svgGroup_.appendChild(this.foreignObject_);
|
||||
|
||||
this.svgHandleTarget_ = Blockly.utils.createSvgElement('rect',
|
||||
{
|
||||
'class': 'blocklyCommentHandleTarget',
|
||||
'x': 0,
|
||||
'y': 0
|
||||
});
|
||||
this.svgGroup_.appendChild(this.svgHandleTarget_);
|
||||
this.svgRectTarget_ = Blockly.utils.createSvgElement('rect',
|
||||
{
|
||||
'class': 'blocklyCommentTarget',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS,
|
||||
'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS
|
||||
});
|
||||
this.svgGroup_.appendChild(this.svgRectTarget_);
|
||||
|
||||
// Add the resize icon
|
||||
this.addResizeDom_();
|
||||
if (this.isDeletable()) {
|
||||
// Add the delete icon
|
||||
this.addDeleteDom_();
|
||||
}
|
||||
|
||||
this.setSize_(size.width, size.height);
|
||||
|
||||
// Set the content
|
||||
this.textarea_.value = this.content_;
|
||||
|
||||
this.rendered_ = true;
|
||||
|
||||
if (this.resizeGroup_) {
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_);
|
||||
}
|
||||
|
||||
if (this.isDeletable()) {
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_);
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_);
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the text area for the comment.
|
||||
* @return {!Element} The top-level node of the editor.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.createEditor_ = function() {
|
||||
/* Create the editor. Here's the markup that will be generated:
|
||||
<foreignObject class="blocklyCommentForeignObject" x="0" y="10" width="164" height="164">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" class="blocklyMinimalBody">
|
||||
<textarea xmlns="http://www.w3.org/1999/xhtml"
|
||||
class="blocklyCommentTextarea"
|
||||
style="height: 164px; width: 164px;"></textarea>
|
||||
</body>
|
||||
</foreignObject>
|
||||
*/
|
||||
this.foreignObject_ = Blockly.utils.createSvgElement(
|
||||
'foreignObject',
|
||||
{
|
||||
'x': 0,
|
||||
'y': Blockly.WorkspaceCommentSvg.TOP_OFFSET,
|
||||
'class': 'blocklyCommentForeignObject'
|
||||
},
|
||||
null);
|
||||
var body = document.createElementNS(Blockly.HTML_NS, 'body');
|
||||
body.setAttribute('xmlns', Blockly.HTML_NS);
|
||||
body.className = 'blocklyMinimalBody';
|
||||
var textarea = document.createElementNS(Blockly.HTML_NS, 'textarea');
|
||||
textarea.className = 'blocklyCommentTextarea';
|
||||
textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR');
|
||||
body.appendChild(textarea);
|
||||
this.textarea_ = textarea;
|
||||
this.foreignObject_.appendChild(body);
|
||||
// Don't zoom with mousewheel.
|
||||
Blockly.bindEventWithChecks_(textarea, 'wheel', this, function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
Blockly.bindEventWithChecks_(textarea, 'change', this, function(
|
||||
/* eslint-disable no-unused-vars */ e
|
||||
/* eslint-enable no-unused-vars */) {
|
||||
this.setContent(textarea.value);
|
||||
});
|
||||
return this.foreignObject_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the resize icon to the DOM
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addResizeDom_ = function() {
|
||||
this.resizeGroup_ = Blockly.utils.createSvgElement(
|
||||
'g',
|
||||
{
|
||||
'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE'
|
||||
},
|
||||
this.svgGroup_);
|
||||
var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE;
|
||||
Blockly.utils.createSvgElement(
|
||||
'polygon',
|
||||
{'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())},
|
||||
this.resizeGroup_);
|
||||
Blockly.utils.createSvgElement(
|
||||
'line',
|
||||
{
|
||||
'class': 'blocklyResizeLine',
|
||||
'x1': resizeSize / 3, 'y1': resizeSize - 1,
|
||||
'x2': resizeSize - 1, 'y2': resizeSize / 3
|
||||
}, this.resizeGroup_);
|
||||
Blockly.utils.createSvgElement(
|
||||
'line',
|
||||
{
|
||||
'class': 'blocklyResizeLine',
|
||||
'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1,
|
||||
'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3
|
||||
}, this.resizeGroup_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the delete icon to the DOM
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addDeleteDom_ = function() {
|
||||
this.deleteGroup_ = Blockly.utils.createSvgElement(
|
||||
'g',
|
||||
{
|
||||
'class': 'blocklyCommentDeleteIcon'
|
||||
},
|
||||
this.svgGroup_);
|
||||
this.deleteIconBorder_ = Blockly.utils.createSvgElement('circle',
|
||||
{
|
||||
'class': 'blocklyDeleteIconShape',
|
||||
'r': '7',
|
||||
'cx': '7.5',
|
||||
'cy': '7.5'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
// x icon.
|
||||
Blockly.utils.createSvgElement(
|
||||
'line',
|
||||
{
|
||||
'x1': '5', 'y1': '10',
|
||||
'x2': '10', 'y2': '5',
|
||||
'stroke': '#fff',
|
||||
'stroke-width': '2'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
Blockly.utils.createSvgElement(
|
||||
'line',
|
||||
{
|
||||
'x1': '5', 'y1': '5',
|
||||
'x2': '10', 'y2': '10',
|
||||
'stroke': '#fff',
|
||||
'stroke-width': '2'
|
||||
},
|
||||
this.deleteGroup_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on comment's resize corner.
|
||||
* @param {!Event} e Mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) {
|
||||
//this.promote_();
|
||||
this.unbindDragEvents_();
|
||||
if (Blockly.utils.isRightButton(e)) {
|
||||
// No right-click.
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
// Left-click (or middle click)
|
||||
this.workspace.startDrag(e, new goog.math.Coordinate(
|
||||
this.workspace.RTL ? -this.width_ : this.width_, this.height_));
|
||||
|
||||
this.onMouseUpWrapper_ = Blockly.bindEventWithChecks_(
|
||||
document, 'mouseup', this, this.resizeMouseUp_);
|
||||
this.onMouseMoveWrapper_ = Blockly.bindEventWithChecks_(
|
||||
document, 'mousemove', this, this.resizeMouseMove_);
|
||||
Blockly.hideChaff();
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on comment's delete icon.
|
||||
* @param {!Event} e Mouse down event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) {
|
||||
// highlight the delete icon
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.deleteIconBorder_), 'blocklyDeleteIconHighlighted');
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-out on comment's delete icon.
|
||||
* @param {!Event} e Mouse out event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(/*e*/) {
|
||||
// restore highlight on the delete icon
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.deleteIconBorder_), 'blocklyDeleteIconHighlighted');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-up on comment's delete icon.
|
||||
* @param {!Event} e Mouse up event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) {
|
||||
// Delete this comment
|
||||
this.dispose(true, true);
|
||||
// This event has been handled. No need to bubble up to the document.
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop binding to the global mouseup and mousemove events.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() {
|
||||
if (this.onMouseUpWrapper_) {
|
||||
Blockly.unbindEvent_(this.onMouseUpWrapper_);
|
||||
this.onMouseUpWrapper_ = null;
|
||||
}
|
||||
if (this.onMouseMoveWrapper_) {
|
||||
Blockly.unbindEvent_(this.onMouseMoveWrapper_);
|
||||
this.onMouseMoveWrapper_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle a mouse-up event while dragging a comment's border or resize handle.
|
||||
* @param {!Event} e Mouse up event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/*e*/) {
|
||||
Blockly.Touch.clearTouchIdentifier();
|
||||
this.unbindDragEvents_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize this comment to follow the mouse.
|
||||
* @param {!Event} e Mouse move event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) {
|
||||
this.autoLayout_ = false;
|
||||
var newXY = this.workspace.moveDrag(e);
|
||||
this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function triggered when the comment has resized.
|
||||
* Resize the text area accordingly.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.resizeComment_ = function() {
|
||||
var size = this.getHeightWidth();
|
||||
var topOffset = Blockly.WorkspaceCommentSvg.TOP_OFFSET;
|
||||
var textOffset = Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET * 2;
|
||||
|
||||
this.foreignObject_.setAttribute('width',
|
||||
size.width);
|
||||
this.foreignObject_.setAttribute('height',
|
||||
size.height - topOffset);
|
||||
if (this.RTL) {
|
||||
this.foreignObject_.setAttribute('x',
|
||||
-size.width);
|
||||
}
|
||||
this.textarea_.style.width =
|
||||
(size.width - textOffset) + 'px';
|
||||
this.textarea_.style.height =
|
||||
(size.height - textOffset - topOffset) + 'px';
|
||||
};
|
||||
|
||||
/**
|
||||
* Set size
|
||||
* @param {number} width width of the container
|
||||
* @param {number} height height of the container
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setSize_ = function(width, height) {
|
||||
// Minimum size of a comment.
|
||||
width = Math.max(width, 45);
|
||||
height = Math.max(height, 20 + Blockly.WorkspaceCommentSvg.TOP_OFFSET);
|
||||
this.width_ = width;
|
||||
this.height_ = height;
|
||||
this.svgRect_.setAttribute('width', width);
|
||||
this.svgRect_.setAttribute('height', height);
|
||||
this.svgRectTarget_.setAttribute('width', width);
|
||||
this.svgRectTarget_.setAttribute('height', height);
|
||||
this.svgHandleTarget_.setAttribute('width', width);
|
||||
this.svgHandleTarget_.setAttribute('height', Blockly.WorkspaceCommentSvg.TOP_OFFSET);
|
||||
if (this.RTL) {
|
||||
this.svgRect_.setAttribute('transform', 'scale(-1 1)');
|
||||
this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)');
|
||||
}
|
||||
|
||||
var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE;
|
||||
if (this.resizeGroup_) {
|
||||
if (this.RTL) {
|
||||
// Mirror the resize group.
|
||||
this.resizeGroup_.setAttribute('transform', 'translate(' +
|
||||
(-width + resizeSize) + ',' + (height - resizeSize) + ') scale(-1 1)');
|
||||
this.deleteGroup_.setAttribute('transform', 'translate(' +
|
||||
(-width + resizeSize) + ',' + (-resizeSize) + ') scale(-1 1)');
|
||||
} else {
|
||||
this.resizeGroup_.setAttribute('transform', 'translate(' +
|
||||
(width - resizeSize) + ',' +
|
||||
(height - resizeSize) + ')');
|
||||
this.deleteGroup_.setAttribute('transform', 'translate(' +
|
||||
(width - resizeSize) + ',' +
|
||||
(-resizeSize) + ')');
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the contents to resize.
|
||||
this.resizeComment_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispose of any rendered comment components.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.disposeInternal_ = function() {
|
||||
this.textarea_ = null;
|
||||
this.foreignObject_ = null;
|
||||
this.svgRectTarget_ = null;
|
||||
this.svgHandleTarget_ = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the focus on the text area.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setFocus = function() {
|
||||
var comment = this;
|
||||
this.focused_ = true;
|
||||
// Defer CSS changes.
|
||||
setTimeout(function() {
|
||||
comment.textarea_.focus();
|
||||
comment.addFocus();
|
||||
Blockly.utils.addClass(
|
||||
comment.svgRectTarget_, 'blocklyCommentTargetFocused');
|
||||
Blockly.utils.addClass(
|
||||
comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove focus from the text area.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.blurFocus = function() {
|
||||
var comment = this;
|
||||
this.focused_ = false;
|
||||
// Defer CSS changes.
|
||||
setTimeout(function() {
|
||||
comment.textarea_.blur();
|
||||
comment.removeFocus();
|
||||
Blockly.utils.removeClass(
|
||||
comment.svgRectTarget_, 'blocklyCommentTargetFocused');
|
||||
Blockly.utils.removeClass(
|
||||
comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
|
||||
}, 0);
|
||||
};
|
||||
@@ -0,0 +1,591 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2017 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 Object representing a code comment on a rendered workspace.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.WorkspaceCommentSvg');
|
||||
|
||||
goog.require('Blockly.Events.CommentCreate');
|
||||
goog.require('Blockly.Events.CommentDelete');
|
||||
goog.require('Blockly.Events.CommentMove');
|
||||
goog.require('Blockly.WorkspaceComment');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a workspace comment's SVG representation.
|
||||
* @param {!Blockly.Workspace} workspace The block's workspace.
|
||||
* @param {string} content The content of this workspace comment.
|
||||
* @param {number} height Height of the comment.
|
||||
* @param {number} width Width of the comment.
|
||||
* @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
|
||||
* create a new ID.
|
||||
* @extends {Blockly.WorkspaceComment}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg = function(workspace, content, height, width,
|
||||
opt_id) {
|
||||
// Create core elements for the block.
|
||||
/**
|
||||
* @type {SVGElement}
|
||||
* @private
|
||||
*/
|
||||
this.svgGroup_ = Blockly.utils.createSvgElement(
|
||||
'g', {'class': 'blocklyComment'}, null);
|
||||
this.svgGroup_.translate_ = '';
|
||||
|
||||
this.svgRect_ = Blockly.utils.createSvgElement(
|
||||
'rect',
|
||||
{
|
||||
'class': 'blocklyCommentRect',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS,
|
||||
'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS
|
||||
});
|
||||
this.svgGroup_.appendChild(this.svgRect_);
|
||||
|
||||
/**
|
||||
* Whether the comment is rendered onscreen and is a part of the DOM.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.rendered_ = false;
|
||||
|
||||
/**
|
||||
* Whether to move the comment to the drag surface when it is dragged.
|
||||
* True if it should move, false if it should be translated directly.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.useDragSurface_ =
|
||||
Blockly.utils.is3dSupported() && !!workspace.blockDragSurface_;
|
||||
|
||||
Blockly.WorkspaceCommentSvg.superClass_.constructor.call(this,
|
||||
workspace, content, height, width, opt_id);
|
||||
|
||||
this.render();
|
||||
}; goog.inherits(Blockly.WorkspaceCommentSvg, Blockly.WorkspaceComment);
|
||||
|
||||
/**
|
||||
* The width and height to use to size a workspace comment when it is first
|
||||
* added, before it has been edited by the user.
|
||||
* @type {number}
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.DEFAULT_SIZE = 100;
|
||||
|
||||
/**
|
||||
* Dispose of this comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.dispose = function() {
|
||||
if (!this.workspace) {
|
||||
// The comment has already been deleted.
|
||||
return;
|
||||
}
|
||||
// If this comment is being dragged, unlink the mouse events.
|
||||
if (Blockly.selected == this) {
|
||||
this.unselect();
|
||||
this.workspace.cancelCurrentGesture();
|
||||
}
|
||||
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
Blockly.Events.fire(new Blockly.Events.CommentDelete(this));
|
||||
}
|
||||
|
||||
goog.dom.removeNode(this.svgGroup_);
|
||||
// Sever JavaScript to DOM connections.
|
||||
this.svgGroup_ = null;
|
||||
this.svgRect_ = null;
|
||||
// Dispose of any rendered components
|
||||
this.disposeInternal_();
|
||||
|
||||
Blockly.Events.disable();
|
||||
Blockly.WorkspaceCommentSvg.superClass_.dispose.call(this);
|
||||
Blockly.Events.enable();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and initialize the SVG representation of a workspace comment.
|
||||
* May be called more than once.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.initSvg = function() {
|
||||
goog.asserts.assert(this.workspace.rendered, 'Workspace is headless.');
|
||||
if (!this.workspace.options.readOnly && !this.eventsInit_) {
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.svgRectTarget_, 'mousedown', this, this.pathMouseDown_);
|
||||
Blockly.bindEventWithChecks_(
|
||||
this.svgHandleTarget_, 'mousedown', this, this.pathMouseDown_);
|
||||
}
|
||||
this.eventsInit_ = true;
|
||||
|
||||
this.updateMovable();
|
||||
if (!this.getSvgRoot().parentNode) {
|
||||
this.workspace.getBubbleCanvas().appendChild(this.getSvgRoot());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-down on an SVG comment.
|
||||
* @param {!Event} e Mouse down event or touch start event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.pathMouseDown_ = function(e) {
|
||||
var gesture = this.workspace.getGesture(e);
|
||||
if (gesture) {
|
||||
gesture.handleBubbleStart(e, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the context menu for this workspace comment.
|
||||
* @param {!Event} e Mouse event.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.showContextMenu_ = function(e) {
|
||||
if (this.workspace.options.readOnly) {
|
||||
return;
|
||||
}
|
||||
// Save the current workspace comment in a variable for use in closures.
|
||||
var comment = this;
|
||||
var menuOptions = [];
|
||||
|
||||
if (this.isDeletable() && this.isMovable()) {
|
||||
menuOptions.push(Blockly.ContextMenu.commentDuplicateOption(comment));
|
||||
menuOptions.push(Blockly.ContextMenu.commentDeleteOption(comment));
|
||||
}
|
||||
|
||||
Blockly.ContextMenu.show(e, menuOptions, this.RTL);
|
||||
};
|
||||
|
||||
/**
|
||||
* Select this comment. Highlight it visually.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.select = function() {
|
||||
if (Blockly.selected == this) {
|
||||
return;
|
||||
}
|
||||
var oldId = null;
|
||||
if (Blockly.selected) {
|
||||
oldId = Blockly.selected.id;
|
||||
// Unselect any previously selected block.
|
||||
Blockly.Events.disable();
|
||||
try {
|
||||
Blockly.selected.unselect();
|
||||
} finally {
|
||||
Blockly.Events.enable();
|
||||
}
|
||||
}
|
||||
var event = new Blockly.Events.Ui(null, 'selected', oldId, this.id);
|
||||
event.workspaceId = this.workspace.id;
|
||||
Blockly.Events.fire(event);
|
||||
Blockly.selected = this;
|
||||
this.addSelect();
|
||||
};
|
||||
|
||||
/**
|
||||
* Unselect this comment. Remove its highlighting.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.unselect = function() {
|
||||
if (Blockly.selected != this) {
|
||||
return;
|
||||
}
|
||||
var event = new Blockly.Events.Ui(null, 'selected', this.id, null);
|
||||
event.workspaceId = this.workspace.id;
|
||||
Blockly.Events.fire(event);
|
||||
Blockly.selected = null;
|
||||
this.removeSelect();
|
||||
this.blurFocus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Select this comment. Highlight it visually.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addSelect = function() {
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklySelected');
|
||||
this.setFocus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Unselect this comment. Remove its highlighting.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.removeSelect = function() {
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklySelected');
|
||||
this.blurFocus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Focus this comment. Highlight it visually.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.addFocus = function() {
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyFocused');
|
||||
};
|
||||
|
||||
/**
|
||||
* Unfocus this comment. Remove its highlighting.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.removeFocus = function() {
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyFocused');
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the coordinates of the top-left corner of this comment relative to the
|
||||
* drawing surface's origin (0,0), in workspace units.
|
||||
* If the comment is on the workspace, (0, 0) is the origin of the workspace
|
||||
* coordinate system.
|
||||
* This does not change with workspace scale.
|
||||
* @return {!goog.math.Coordinate} Object with .x and .y properties in
|
||||
* workspace coordinates.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getRelativeToSurfaceXY = function() {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
|
||||
var dragSurfaceGroup = this.useDragSurface_ ?
|
||||
this.workspace.blockDragSurface_.getGroup() : null;
|
||||
|
||||
var element = this.getSvgRoot();
|
||||
if (element) {
|
||||
do {
|
||||
// Loop through this comment and every parent.
|
||||
var xy = Blockly.utils.getRelativeXY(element);
|
||||
x += xy.x;
|
||||
y += xy.y;
|
||||
// If this element is the current element on the drag surface, include
|
||||
// the translation of the drag surface itself.
|
||||
if (this.useDragSurface_ &&
|
||||
this.workspace.blockDragSurface_.getCurrentBlock() == element) {
|
||||
var surfaceTranslation =
|
||||
this.workspace.blockDragSurface_.getSurfaceTranslation();
|
||||
x += surfaceTranslation.x;
|
||||
y += surfaceTranslation.y;
|
||||
}
|
||||
element = element.parentNode;
|
||||
} while (element && element != this.workspace.getBubbleCanvas() &&
|
||||
element != dragSurfaceGroup);
|
||||
}
|
||||
this.xy_ = new goog.math.Coordinate(x, y);
|
||||
return this.xy_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a comment by a relative offset.
|
||||
* @param {number} dx Horizontal offset, in workspace units.
|
||||
* @param {number} dy Vertical offset, in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.moveBy = function(dx, dy) {
|
||||
var event = new Blockly.Events.CommentMove(this);
|
||||
// TODO: Do I need to look up the relative to surface XY position here?
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.translate(xy.x + dx, xy.y + dy);
|
||||
this.xy_ = new goog.math.Coordinate(xy.x + dx, xy.y + dy);
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
this.workspace.resizeContents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms a comment by setting the translation on the transform attribute
|
||||
* of the block's SVG.
|
||||
* @param {number} x The x coordinate of the translation in workspace units.
|
||||
* @param {number} y The y coordinate of the translation in workspace units.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.translate = function(x, y) {
|
||||
this.xy_ = new goog.math.Coordinate(x, y);
|
||||
this.getSvgRoot().setAttribute('transform',
|
||||
'translate(' + x + ',' + y + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this comment to its workspace's drag surface, accounting for positioning.
|
||||
* Generally should be called at the same time as setDragging(true).
|
||||
* Does nothing if useDragSurface_ is false.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.moveToDragSurface_ = function() {
|
||||
if (!this.useDragSurface_) {
|
||||
return;
|
||||
}
|
||||
// The translation for drag surface blocks,
|
||||
// is equal to the current relative-to-surface position,
|
||||
// to keep the position in sync as it move on/off the surface.
|
||||
// This is in workspace coordinates.
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
this.clearTransformAttributes_();
|
||||
this.workspace.blockDragSurface_.translateSurface(xy.x, xy.y);
|
||||
// Execute the move on the top-level SVG component
|
||||
this.workspace.blockDragSurface_.setBlocksAndShow(this.getSvgRoot());
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this comment back to the workspace block canvas.
|
||||
* Generally should be called at the same time as setDragging(false).
|
||||
* Does nothing if useDragSurface_ is false.
|
||||
* @param {!goog.math.Coordinate} newXY The position the comment should take on
|
||||
* on the workspace canvas, in workspace coordinates.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.moveOffDragSurface_ = function(newXY) {
|
||||
if (!this.useDragSurface_) {
|
||||
return;
|
||||
}
|
||||
// Translate to current position, turning off 3d.
|
||||
this.translate(newXY.x, newXY.y);
|
||||
this.workspace.blockDragSurface_.clearAndHide(this.workspace.getCanvas());
|
||||
};
|
||||
|
||||
/**
|
||||
* Move this comment during a drag, taking into account whether we are using a
|
||||
* drag surface to translate blocks.
|
||||
* @param {?Blockly.BlockDragSurfaceSvg} dragSurface The surface that carries
|
||||
* rendered items during a drag, or null if no drag surface is in use.
|
||||
* @param {!goog.math.Coordinate} newLoc The location to translate to, in
|
||||
* workspace coordinates.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.moveDuringDrag = function(dragSurface, newLoc) {
|
||||
if (dragSurface) {
|
||||
dragSurface.translateSurface(newLoc.x, newLoc.y);
|
||||
} else {
|
||||
this.svgGroup_.translate_ = 'translate(' + newLoc.x + ',' + newLoc.y + ')';
|
||||
this.svgGroup_.setAttribute('transform',
|
||||
this.svgGroup_.translate_ + this.svgGroup_.skew_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the bubble group to the specified location in workspace coordinates.
|
||||
* @param {number} x The x position to move to.
|
||||
* @param {number} y The y position to move to.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.moveTo = function(x, y) {
|
||||
this.translate(x, y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the comment of transform="..." attributes.
|
||||
* Used when the comment is switching from 3d to 2d transform or vice versa.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.clearTransformAttributes_ = function() {
|
||||
Blockly.utils.removeAttribute(this.getSvgRoot(), 'transform');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the coordinates of a bounding box describing the dimensions of this
|
||||
* comment.
|
||||
* Coordinate system: workspace coordinates.
|
||||
* @return {!{topLeft: goog.math.Coordinate, bottomRight: goog.math.Coordinate}}
|
||||
* Object with top left and bottom right coordinates of the bounding box.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getBoundingRectangle = function() {
|
||||
var blockXY = this.getRelativeToSurfaceXY();
|
||||
var commentBounds = this.getHeightWidth();
|
||||
var topLeft;
|
||||
var bottomRight;
|
||||
if (this.RTL) {
|
||||
topLeft = new goog.math.Coordinate(blockXY.x - (commentBounds.width),
|
||||
blockXY.y);
|
||||
// Add the width of the tab/puzzle piece knob to the x coordinate
|
||||
// since X is the corner of the rectangle, not the whole puzzle piece.
|
||||
bottomRight = new goog.math.Coordinate(blockXY.x,
|
||||
blockXY.y + commentBounds.height);
|
||||
} else {
|
||||
// Subtract the width of the tab/puzzle piece knob to the x coordinate
|
||||
// since X is the corner of the rectangle, not the whole puzzle piece.
|
||||
topLeft = new goog.math.Coordinate(blockXY.x, blockXY.y);
|
||||
bottomRight = new goog.math.Coordinate(blockXY.x + commentBounds.width,
|
||||
blockXY.y + commentBounds.height);
|
||||
}
|
||||
return {topLeft: topLeft, bottomRight: bottomRight};
|
||||
};
|
||||
|
||||
/**
|
||||
* Add or remove the UI indicating if this comment is movable or not.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.updateMovable = function() {
|
||||
if (this.isMovable()) {
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDraggable');
|
||||
} else {
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDraggable');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this comment is movable or not.
|
||||
* @param {boolean} movable True if movable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setMovable = function(movable) {
|
||||
Blockly.WorkspaceCommentSvg.superClass_.setMovable.call(this, movable);
|
||||
this.updateMovable();
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively adds or removes the dragging class to this node and its children.
|
||||
* @param {boolean} adding True if adding, false if removing.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setDragging = function(adding) {
|
||||
if (adding) {
|
||||
var group = this.getSvgRoot();
|
||||
group.translate_ = '';
|
||||
group.skew_ = '';
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDragging');
|
||||
} else {
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDragging');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the root node of the SVG or null if none exists.
|
||||
* @return {Element} The root SVG node (probably a group).
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getSvgRoot = function() {
|
||||
return this.svgGroup_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this comment's text.
|
||||
* @return {string} Comment text.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.getContent = function() {
|
||||
return this.textarea_ ? this.textarea_.value : this.content_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set this comment's content.
|
||||
* @param {string} content Comment content.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setContent = function(content) {
|
||||
Blockly.WorkspaceCommentSvg.superClass_.setContent.call(this, content);
|
||||
if (this.textarea_) {
|
||||
this.textarea_.value = content;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the cursor over this comment by adding or removing a class.
|
||||
* @param {boolean} enable True if the delete cursor should be shown, false
|
||||
* otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.setDeleteStyle = function(enable) {
|
||||
if (enable) {
|
||||
Blockly.utils.addClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDraggingDelete');
|
||||
} else {
|
||||
Blockly.utils.removeClass(
|
||||
/** @type {!Element} */ (this.svgGroup_), 'blocklyDraggingDelete');
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.WorkspaceCommentSvg.prototype.setAutoLayout = function() {
|
||||
// NOP for compatibility with the bubble dragger.
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode an XML comment tag and create a rendered comment on the workspace.
|
||||
* @param {!Element} xmlComment XML comment element.
|
||||
* @param {!Blockly.Workspace} workspace The workspace.
|
||||
* @param {number=} opt_wsWidth The width of the workspace, which is used to
|
||||
* position comments correctly in RTL.
|
||||
* @return {!Blockly.WorkspaceCommentSvg} The created workspace comment.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.fromXml = function(xmlComment, workspace,
|
||||
opt_wsWidth) {
|
||||
Blockly.Events.disable();
|
||||
try {
|
||||
var info = Blockly.WorkspaceComment.parseAttributes(xmlComment);
|
||||
|
||||
var comment = new Blockly.WorkspaceCommentSvg(workspace,
|
||||
info.content, info.h, info.w, info.id);
|
||||
if (workspace.rendered) {
|
||||
comment.initSvg();
|
||||
comment.render(false);
|
||||
}
|
||||
// Position the comment correctly, taking into account the width of a
|
||||
// rendered RTL workspace.
|
||||
if (!isNaN(info.x) && !isNaN(info.y)) {
|
||||
if (workspace.RTL) {
|
||||
var wsWidth = opt_wsWidth || workspace.getWidth();
|
||||
comment.moveBy(wsWidth - info.x, info.y);
|
||||
} else {
|
||||
comment.moveBy(info.x, info.y);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Blockly.Events.enable();
|
||||
}
|
||||
Blockly.WorkspaceComment.fireCreateEvent(comment);
|
||||
|
||||
return comment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a comment subtree as XML with XY coordinates.
|
||||
* @param {boolean=} opt_noId True if the encoder should skip the comment id.
|
||||
* @return {!Element} Tree of XML elements.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceCommentSvg.prototype.toXmlWithXY = function(opt_noId) {
|
||||
var width; // Not used in LTR.
|
||||
if (this.workspace.RTL) {
|
||||
// Here be performance dragons: This calls getMetrics().
|
||||
width = this.workspace.getWidth();
|
||||
}
|
||||
var element = this.toXml(opt_noId);
|
||||
var xy = this.getRelativeToSurfaceXY();
|
||||
element.setAttribute('x',
|
||||
Math.round(this.workspace.RTL ? width - xy.x : xy.x));
|
||||
element.setAttribute('y', Math.round(xy.y));
|
||||
element.setAttribute('h', this.getHeight());
|
||||
element.setAttribute('w', this.getWidth());
|
||||
return element;
|
||||
};
|
||||
+113
-19
@@ -41,6 +41,9 @@ goog.require('Blockly.Trashcan');
|
||||
goog.require('Blockly.VariablesDynamic');
|
||||
goog.require('Blockly.Workspace');
|
||||
goog.require('Blockly.WorkspaceAudio');
|
||||
goog.require('Blockly.WorkspaceComment');
|
||||
goog.require('Blockly.WorkspaceCommentSvg');
|
||||
goog.require('Blockly.WorkspaceCommentSvg.render');
|
||||
goog.require('Blockly.WorkspaceDragSurfaceSvg');
|
||||
goog.require('Blockly.Xml');
|
||||
goog.require('Blockly.ZoomControls');
|
||||
@@ -243,6 +246,14 @@ Blockly.WorkspaceSvg.prototype.useWorkspaceDragSurface_ = false;
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.isDragSurfaceActive_ = false;
|
||||
|
||||
/**
|
||||
* The first parent div with 'injectionDiv' in the name, or null if not set.
|
||||
* Access this with getInjectionDiv.
|
||||
* @type {!Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.injectionDiv_ = null;
|
||||
|
||||
/**
|
||||
* Last known position of the page scroll.
|
||||
* This is used to determine whether we have recalculated screen coordinate
|
||||
@@ -290,22 +301,37 @@ Blockly.WorkspaceSvg.prototype.targetWorkspace = null;
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.inverseScreenCTM_ = null;
|
||||
|
||||
/**
|
||||
* Inverted screen CTM is dirty, recalculate it.
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.inverseScreenCTMDirty_ = true;
|
||||
|
||||
/**
|
||||
* Getter for the inverted screen CTM.
|
||||
* @return {SVGMatrix} The matrix to use in mouseToSvg
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.getInverseScreenCTM = function() {
|
||||
|
||||
// Defer getting the screen CTM until we actually need it, this should
|
||||
// avoid forced reflows from any calls to updateInverseScreenCTM.
|
||||
if (this.inverseScreenCTMDirty_) {
|
||||
var ctm = this.getParentSvg().getScreenCTM();
|
||||
if (ctm) {
|
||||
this.inverseScreenCTM_ = ctm.inverse();
|
||||
this.inverseScreenCTMDirty_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.inverseScreenCTM_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the inverted screen CTM.
|
||||
* Mark the inverse screen CTM as dirty.
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.updateInverseScreenCTM = function() {
|
||||
var ctm = this.getParentSvg().getScreenCTM();
|
||||
if (ctm) {
|
||||
this.inverseScreenCTM_ = ctm.inverse();
|
||||
}
|
||||
this.inverseScreenCTMDirty_ = true;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -352,6 +378,29 @@ Blockly.WorkspaceSvg.prototype.getOriginOffsetInPixels = function() {
|
||||
return Blockly.utils.getInjectionDivXY_(this.svgBlockCanvas_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the injection div that is a parent of this workspace.
|
||||
* Walks the DOM the first time it's called, then returns a cached value.
|
||||
* @return {!Element} The first parent div with 'injectionDiv' in the name.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.getInjectionDiv = function() {
|
||||
// NB: it would be better to pass this in at createDom, but is more likely to
|
||||
// break existing uses of Blockly.
|
||||
if (!this.injectionDiv_) {
|
||||
var element = this.svgGroup_;
|
||||
while (element) {
|
||||
var classes = element.getAttribute('class') || '';
|
||||
if ((' ' + classes + ' ').indexOf(' injectionDiv ') != -1) {
|
||||
this.injectionDiv_ = element;
|
||||
break;
|
||||
}
|
||||
element = element.parentNode;
|
||||
}
|
||||
}
|
||||
return this.injectionDiv_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save resize handler data so we can delete it later in dispose.
|
||||
* @param {!Array.<!Array>} handler Data that can be passed to unbindEvent_.
|
||||
@@ -897,6 +946,18 @@ Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) {
|
||||
if (this.currentGesture_) {
|
||||
this.currentGesture_.cancel(); // Dragging while pasting? No.
|
||||
}
|
||||
if (xmlBlock.tagName.toLowerCase() == 'comment') {
|
||||
this.pasteWorkspaceComment_(xmlBlock);
|
||||
} else {
|
||||
this.pasteBlock_(xmlBlock);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Paste the provided block onto the workspace.
|
||||
* @param {!Element} xmlBlock XML block element.
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.pasteBlock_ = function(xmlBlock) {
|
||||
Blockly.Events.disable();
|
||||
try {
|
||||
var block = Blockly.Xml.domToBlock(xmlBlock, this);
|
||||
@@ -952,6 +1013,37 @@ Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) {
|
||||
block.select();
|
||||
};
|
||||
|
||||
/**
|
||||
* Paste the provided comment onto the workspace.
|
||||
* @param {!Element} xmlComment XML workspace comment element.
|
||||
* @private
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.pasteWorkspaceComment_ = function(xmlComment) {
|
||||
Blockly.Events.disable();
|
||||
try {
|
||||
var comment = Blockly.WorkspaceCommentSvg.fromXml(xmlComment, this);
|
||||
// Move the duplicate to original position.
|
||||
var commentX = parseInt(xmlComment.getAttribute('x'), 10);
|
||||
var commentY = parseInt(xmlComment.getAttribute('y'), 10);
|
||||
if (!isNaN(commentX) && !isNaN(commentY)) {
|
||||
if (this.RTL) {
|
||||
commentX = -commentX;
|
||||
}
|
||||
// Offset workspace comment.
|
||||
// TODO: #1719 properly offset comment such that it's not interfereing with any blocks
|
||||
commentX += 50;
|
||||
commentY += 50;
|
||||
comment.moveBy(commentX, commentY);
|
||||
}
|
||||
} finally {
|
||||
Blockly.Events.enable();
|
||||
}
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
// TODO: Fire a Workspace Comment Create event
|
||||
}
|
||||
comment.select();
|
||||
};
|
||||
|
||||
/**
|
||||
* Refresh the toolbox unless there's a drag in progress.
|
||||
* @package
|
||||
@@ -1126,17 +1218,19 @@ Blockly.WorkspaceSvg.prototype.onMouseWheel_ = function(e) {
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox = function() {
|
||||
var topBlocks = this.getTopBlocks(false);
|
||||
var topComments = this.getTopComments(false);
|
||||
var topElements = topBlocks.concat(topComments);
|
||||
// There are no blocks, return empty rectangle.
|
||||
if (!topBlocks.length) {
|
||||
if (!topElements.length) {
|
||||
return {x: 0, y: 0, width: 0, height: 0};
|
||||
}
|
||||
|
||||
// Initialize boundary using the first block.
|
||||
var boundary = topBlocks[0].getBoundingRectangle();
|
||||
var boundary = topElements[0].getBoundingRectangle();
|
||||
|
||||
// Start at 1 since the 0th block was used for initialization
|
||||
for (var i = 1; i < topBlocks.length; i++) {
|
||||
var blockBoundary = topBlocks[i].getBoundingRectangle();
|
||||
for (var i = 1; i < topElements.length; i++) {
|
||||
var blockBoundary = topElements[i].getBoundingRectangle();
|
||||
if (blockBoundary.topLeft.x < boundary.topLeft.x) {
|
||||
boundary.topLeft.x = blockBoundary.topLeft.x;
|
||||
}
|
||||
@@ -1193,12 +1287,12 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
|
||||
// Options to undo/redo previous action.
|
||||
var undoOption = {};
|
||||
undoOption.text = Blockly.Msg.UNDO;
|
||||
undoOption.text = Blockly.Msg['UNDO'];
|
||||
undoOption.enabled = this.undoStack_.length > 0;
|
||||
undoOption.callback = this.undo.bind(this, false);
|
||||
menuOptions.push(undoOption);
|
||||
var redoOption = {};
|
||||
redoOption.text = Blockly.Msg.REDO;
|
||||
redoOption.text = Blockly.Msg['REDO'];
|
||||
redoOption.enabled = this.redoStack_.length > 0;
|
||||
redoOption.callback = this.undo.bind(this, true);
|
||||
menuOptions.push(redoOption);
|
||||
@@ -1206,7 +1300,7 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
// Option to clean up blocks.
|
||||
if (this.scrollbar) {
|
||||
var cleanOption = {};
|
||||
cleanOption.text = Blockly.Msg.CLEAN_UP;
|
||||
cleanOption.text = Blockly.Msg['CLEAN_UP'];
|
||||
cleanOption.enabled = topBlocks.length > 1;
|
||||
cleanOption.callback = this.cleanUp.bind(this);
|
||||
menuOptions.push(cleanOption);
|
||||
@@ -1248,7 +1342,7 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
|
||||
// Option to collapse top blocks.
|
||||
var collapseOption = {enabled: hasExpandedBlocks};
|
||||
collapseOption.text = Blockly.Msg.COLLAPSE_ALL;
|
||||
collapseOption.text = Blockly.Msg['COLLAPSE_ALL'];
|
||||
collapseOption.callback = function() {
|
||||
toggleOption(true);
|
||||
};
|
||||
@@ -1256,7 +1350,7 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
|
||||
// Option to expand top blocks.
|
||||
var expandOption = {enabled: hasCollapsedBlocks};
|
||||
expandOption.text = Blockly.Msg.EXPAND_ALL;
|
||||
expandOption.text = Blockly.Msg['EXPAND_ALL'];
|
||||
expandOption.callback = function() {
|
||||
toggleOption(false);
|
||||
};
|
||||
@@ -1268,9 +1362,9 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
var deleteList = [];
|
||||
function addDeletableBlocks(block) {
|
||||
if (block.isDeletable()) {
|
||||
deleteList = deleteList.concat(block.getDescendants());
|
||||
deleteList = deleteList.concat(block.getDescendants(false));
|
||||
} else {
|
||||
var children = block.getChildren();
|
||||
var children = block.getChildren(false);
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
addDeletableBlocks(children[i]);
|
||||
}
|
||||
@@ -1295,8 +1389,8 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
}
|
||||
|
||||
var deleteOption = {
|
||||
text: deleteList.length == 1 ? Blockly.Msg.DELETE_BLOCK :
|
||||
Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(deleteList.length)),
|
||||
text: deleteList.length == 1 ? Blockly.Msg['DELETE_BLOCK'] :
|
||||
Blockly.Msg['DELETE_X_BLOCKS'].replace('%1', String(deleteList.length)),
|
||||
enabled: deleteList.length > 0,
|
||||
callback: function() {
|
||||
if (ws.currentGesture_) {
|
||||
@@ -1306,7 +1400,7 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
||||
deleteNext();
|
||||
} else {
|
||||
Blockly.confirm(
|
||||
Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1', deleteList.length),
|
||||
Blockly.Msg['DELETE_ALL_BLOCKS'].replace('%1', deleteList.length),
|
||||
function(ok) {
|
||||
if (ok) {
|
||||
deleteNext();
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2018 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 Classes for all comment events.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Events.CommentBase');
|
||||
goog.provide('Blockly.Events.CommentChange');
|
||||
goog.provide('Blockly.Events.CommentCreate');
|
||||
goog.provide('Blockly.Events.CommentDelete');
|
||||
goog.provide('Blockly.Events.CommentMove');
|
||||
|
||||
goog.require('Blockly.Events');
|
||||
goog.require('Blockly.Events.Abstract');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class for a comment event.
|
||||
* @param {Blockly.WorkspaceComment} comment The comment this event corresponds
|
||||
* to.
|
||||
* @extends {Blockly.Events.Abstract}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.CommentBase = function(comment) {
|
||||
/**
|
||||
* The ID of the comment this event pertains to.
|
||||
* @type {string}
|
||||
*/
|
||||
this.commentId = comment.id;
|
||||
|
||||
/**
|
||||
* The workspace identifier for this event.
|
||||
* @type {string}
|
||||
*/
|
||||
this.workspaceId = comment.workspace.id;
|
||||
|
||||
/**
|
||||
* The event group id for the group this event belongs to. Groups define
|
||||
* events that should be treated as an single action from the user's
|
||||
* perspective, and should be undone together.
|
||||
* @type {string}
|
||||
*/
|
||||
this.group = Blockly.Events.group_;
|
||||
|
||||
/**
|
||||
* Sets whether the event should be added to the undo stack.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.recordUndo = Blockly.Events.recordUndo;
|
||||
};
|
||||
goog.inherits(Blockly.Events.CommentBase, Blockly.Events.Abstract);
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
* @return {!Object} JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentBase.prototype.toJson = function() {
|
||||
var json = {
|
||||
'type': this.type
|
||||
};
|
||||
if (this.group) {
|
||||
json['group'] = this.group;
|
||||
}
|
||||
if (this.commentId) {
|
||||
json['commentId'] = this.commentId;
|
||||
}
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the JSON event.
|
||||
* @param {!Object} json JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentBase.prototype.fromJson = function(json) {
|
||||
this.commentId = json['commentId'];
|
||||
this.group = json['group'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for a comment change event.
|
||||
* @param {Blockly.WorkspaceComment} comment The comment that is being changed.
|
||||
* Null for a blank event.
|
||||
* @param {string} oldContents Previous contents of the comment.
|
||||
* @param {string} newContents New contents of the comment.
|
||||
* @extends {Blockly.Events.CommentBase}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.CommentChange = function(comment, oldContents, newContents) {
|
||||
if (!comment) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
Blockly.Events.CommentChange.superClass_.constructor.call(this, comment);
|
||||
this.oldContents_ = oldContents;
|
||||
this.newContents_ = newContents;
|
||||
};
|
||||
goog.inherits(Blockly.Events.CommentChange, Blockly.Events.CommentBase);
|
||||
|
||||
/**
|
||||
* Type of this event.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.Events.CommentChange.prototype.type = Blockly.Events.COMMENT_CHANGE;
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
* @return {!Object} JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentChange.prototype.toJson = function() {
|
||||
var json = Blockly.Events.CommentChange.superClass_.toJson.call(this);
|
||||
json['newContents'] = this.newContents_;
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the JSON event.
|
||||
* @param {!Object} json JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentChange.prototype.fromJson = function(json) {
|
||||
Blockly.Events.CommentChange.superClass_.fromJson.call(this, json);
|
||||
this.newContents_ = json['newValue'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Does this event record any change of state?
|
||||
* @return {boolean} False if something changed.
|
||||
*/
|
||||
Blockly.Events.CommentChange.prototype.isNull = function() {
|
||||
return this.oldContents_ == this.newContents_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a change event.
|
||||
* @param {boolean} forward True if run forward, false if run backward (undo).
|
||||
*/
|
||||
Blockly.Events.CommentChange.prototype.run = function(forward) {
|
||||
var workspace = this.getEventWorkspace_();
|
||||
var comment = workspace.getCommentById(this.commentId);
|
||||
if (!comment) {
|
||||
console.warn('Can\'t change non-existent comment: ' + this.commentId);
|
||||
return;
|
||||
}
|
||||
var contents = forward ? this.newContents_ : this.oldContents_;
|
||||
|
||||
comment.setContent(contents);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for a comment creation event.
|
||||
* @param {Blockly.WorkspaceComment} comment The created comment.
|
||||
* Null for a blank event.
|
||||
* @extends {Blockly.Events.CommentBase}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.CommentCreate = function(comment) {
|
||||
if (!comment) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
Blockly.Events.CommentCreate.superClass_.constructor.call(this, comment);
|
||||
|
||||
this.xml = comment.toXmlWithXY();
|
||||
};
|
||||
goog.inherits(Blockly.Events.CommentCreate, Blockly.Events.CommentBase);
|
||||
|
||||
/**
|
||||
* Type of this event.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.Events.CommentCreate.prototype.type = Blockly.Events.COMMENT_CREATE;
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
* TODO (#1266): "Full" and "minimal" serialization.
|
||||
* @return {!Object} JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentCreate.prototype.toJson = function() {
|
||||
var json = Blockly.Events.CommentCreate.superClass_.toJson.call(this);
|
||||
json['xml'] = Blockly.Xml.domToText(this.xml);
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the JSON event.
|
||||
* @param {!Object} json JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentCreate.prototype.fromJson = function(json) {
|
||||
Blockly.Events.CommentCreate.superClass_.fromJson.call(this, json);
|
||||
this.xml = Blockly.Xml.textToDom('<xml>' + json['xml'] + '</xml>').firstChild;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a creation event.
|
||||
* @param {boolean} forward True if run forward, false if run backward (undo).
|
||||
*/
|
||||
Blockly.Events.CommentCreate.prototype.run = function(forward) {
|
||||
var workspace = this.getEventWorkspace_();
|
||||
if (forward) {
|
||||
var xml = goog.dom.createDom('xml');
|
||||
xml.appendChild(this.xml);
|
||||
Blockly.Xml.domToWorkspace(xml, workspace);
|
||||
} else {
|
||||
var comment = workspace.getCommentById(this.commentId);
|
||||
if (comment) {
|
||||
comment.dispose(false, false);
|
||||
} else {
|
||||
// Only complain about root-level block.
|
||||
console.warn("Can't uncreate non-existent comment: " + this.commentId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for a comment deletion event.
|
||||
* @param {Blockly.WorkspaceComment} comment The deleted comment.
|
||||
* Null for a blank event.
|
||||
* @extends {Blockly.Events.CommentBase}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.CommentDelete = function(comment) {
|
||||
if (!comment) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
Blockly.Events.CommentDelete.superClass_.constructor.call(this, comment);
|
||||
|
||||
this.xml = comment.toXmlWithXY();
|
||||
};
|
||||
goog.inherits(Blockly.Events.CommentDelete, Blockly.Events.CommentBase);
|
||||
|
||||
/**
|
||||
* Type of this event.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.Events.CommentDelete.prototype.type = Blockly.Events.COMMENT_DELETE;
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
* TODO (#1266): "Full" and "minimal" serialization.
|
||||
* @return {!Object} JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentDelete.prototype.toJson = function() {
|
||||
var json = Blockly.Events.CommentDelete.superClass_.toJson.call(this);
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the JSON event.
|
||||
* @param {!Object} json JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentDelete.prototype.fromJson = function(json) {
|
||||
Blockly.Events.CommentDelete.superClass_.fromJson.call(this, json);
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a creation event.
|
||||
* @param {boolean} forward True if run forward, false if run backward (undo).
|
||||
*/
|
||||
Blockly.Events.CommentDelete.prototype.run = function(forward) {
|
||||
var workspace = this.getEventWorkspace_();
|
||||
if (forward) {
|
||||
var comment = workspace.getCommentById(this.commentId);
|
||||
if (comment) {
|
||||
comment.dispose(false, false);
|
||||
} else {
|
||||
// Only complain about root-level block.
|
||||
console.warn("Can't uncreate non-existent comment: " + this.commentId);
|
||||
}
|
||||
} else {
|
||||
var xml = goog.dom.createDom('xml');
|
||||
xml.appendChild(this.xml);
|
||||
Blockly.Xml.domToWorkspace(xml, workspace);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for a comment move event. Created before the move.
|
||||
* @param {Blockly.WorkspaceComment} comment The comment that is being moved.
|
||||
* Null for a blank event.
|
||||
* @extends {Blockly.Events.CommentBase}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Events.CommentMove = function(comment) {
|
||||
if (!comment) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
Blockly.Events.CommentMove.superClass_.constructor.call(this, comment);
|
||||
|
||||
/**
|
||||
* The comment that is being moved. Will be cleared after recording the new
|
||||
* location.
|
||||
* @type {?Blockly.WorkspaceComment}
|
||||
*/
|
||||
this.comment_ = comment;
|
||||
|
||||
/**
|
||||
* The location before the move, in workspace coordinates.
|
||||
* @type {!goog.math.Coordinate}
|
||||
*/
|
||||
this.oldCoordinate_ = comment.getXY();
|
||||
|
||||
/**
|
||||
* The location after the move, in workspace coordinates.
|
||||
* @type {!goog.math.Coordinate}
|
||||
*/
|
||||
this.newCoordinate_ = null;
|
||||
};
|
||||
goog.inherits(Blockly.Events.CommentMove, Blockly.Events.CommentBase);
|
||||
|
||||
/**
|
||||
* Record the comment's new location. Called after the move. Can only be
|
||||
* called once.
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.recordNew = function() {
|
||||
if (!this.comment_) {
|
||||
throw new Error('Tried to record the new position of a comment on the ' +
|
||||
'same event twice.');
|
||||
}
|
||||
this.newCoordinate_ = this.comment_.getXY();
|
||||
this.comment_ = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of this event.
|
||||
* @type {string}
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.type = Blockly.Events.COMMENT_MOVE;
|
||||
|
||||
/**
|
||||
* Override the location before the move. Use this if you don't create the
|
||||
* event until the end of the move, but you know the original location.
|
||||
* @param {!goog.math.Coordinate} xy The location before the move, in workspace
|
||||
* coordinates.
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.setOldCoordinate = function(xy) {
|
||||
this.oldCoordinate_ = xy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
* TODO (#1266): "Full" and "minimal" serialization.
|
||||
* @return {!Object} JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.toJson = function() {
|
||||
var json = Blockly.Events.CommentMove.superClass_.toJson.call(this);
|
||||
if (this.newCoordinate_) {
|
||||
json['newCoordinate'] = Math.round(this.newCoordinate_.x) + ',' +
|
||||
Math.round(this.newCoordinate_.y);
|
||||
}
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the JSON event.
|
||||
* @param {!Object} json JSON representation.
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.fromJson = function(json) {
|
||||
Blockly.Events.CommentMove.superClass_.fromJson.call(this, json);
|
||||
|
||||
if (json['newCoordinate']) {
|
||||
var xy = json['newCoordinate'].split(',');
|
||||
this.newCoordinate_ =
|
||||
new goog.math.Coordinate(parseFloat(xy[0]), parseFloat(xy[1]));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Does this event record any change of state?
|
||||
* @return {boolean} False if something changed.
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.isNull = function() {
|
||||
return goog.math.Coordinate.equals(this.oldCoordinate_, this.newCoordinate_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a move event.
|
||||
* @param {boolean} forward True if run forward, false if run backward (undo).
|
||||
*/
|
||||
Blockly.Events.CommentMove.prototype.run = function(forward) {
|
||||
var workspace = this.getEventWorkspace_();
|
||||
var comment = workspace.getCommentById(this.commentId);
|
||||
if (!comment) {
|
||||
console.warn('Can\'t move non-existent comment: ' + this.commentId);
|
||||
return;
|
||||
}
|
||||
|
||||
var target = forward ? this.newCoordinate_ : this.oldCoordinate_;
|
||||
// TODO: Check if the comment is being dragged, and give up if so.
|
||||
var current = comment.getXY();
|
||||
comment.moveBy(target.x - current.x, target.y - current.y);
|
||||
};
|
||||
+77
-36
@@ -33,7 +33,6 @@ goog.provide('Blockly.Xml');
|
||||
goog.require('Blockly.Events.BlockCreate');
|
||||
goog.require('Blockly.Events.VarCreate');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
@@ -45,9 +44,11 @@ goog.require('goog.dom');
|
||||
*/
|
||||
Blockly.Xml.workspaceToDom = function(workspace, opt_noId) {
|
||||
var xml = goog.dom.createDom('xml');
|
||||
var variables = Blockly.Variables.allUsedVarModels(workspace);
|
||||
if (variables.length) {
|
||||
xml.appendChild(Blockly.Xml.variablesToDom(variables));
|
||||
xml.appendChild(Blockly.Xml.variablesToDom(
|
||||
Blockly.Variables.allUsedVarModels(workspace)));
|
||||
var comments = workspace.getTopComments(true);
|
||||
for (var i = 0, comment; comment = comments[i]; i++) {
|
||||
xml.appendChild(comment.toXmlWithXY(opt_noId));
|
||||
}
|
||||
var blocks = workspace.getTopBlocks(true);
|
||||
for (var i = 0, block; block = blocks[i]; i++) {
|
||||
@@ -136,7 +137,7 @@ Blockly.Xml.fieldToDomVariable_ = function(field) {
|
||||
*/
|
||||
Blockly.Xml.fieldToDom_ = function(field) {
|
||||
if (field.name && field.EDITABLE) {
|
||||
if (field instanceof Blockly.FieldVariable) {
|
||||
if (field.referencesVariables()) {
|
||||
return Blockly.Xml.fieldToDomVariable_(field);
|
||||
} else {
|
||||
var container = goog.dom.createDom('field', null, field.getValue());
|
||||
@@ -344,22 +345,49 @@ Blockly.Xml.domToPrettyText = function(dom) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts plain text into a DOM structure.
|
||||
* Throws an error if XML doesn't parse.
|
||||
* @param {string} text Text representation.
|
||||
* @return {!Element} A tree of XML elements.
|
||||
* Converts an XML string into a DOM tree. This method will be overridden in
|
||||
* the Node.js build of Blockly. See gulpfile.js, blockly_javascript_en task.
|
||||
* @param {string} text XML string.
|
||||
* @return {!Element} The DOM document.
|
||||
* @throws if XML doesn't parse.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Xml.textToDomDocument_ = function(text) {
|
||||
var oParser = new DOMParser();
|
||||
return oParser.parseFromString(text, 'text/xml');
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an XML string into a DOM structure. It requires the XML to have a
|
||||
* root element of <xml>. Other XML string will result in throwing an error.
|
||||
* @param {string} text An XML string.
|
||||
* @return {!Element} A DOM object representing the singular child of the document element.
|
||||
* @throws if XML doesn't parse or is not the expected structure.
|
||||
*/
|
||||
Blockly.Xml.textToDom = function(text) {
|
||||
var oParser = new DOMParser();
|
||||
var dom = oParser.parseFromString(text, 'text/xml');
|
||||
// The DOM should have one and only one top-level node, an XML tag.
|
||||
if (!dom || !dom.firstChild ||
|
||||
dom.firstChild.nodeName.toLowerCase() != 'xml' ||
|
||||
dom.firstChild !== dom.lastChild) {
|
||||
// Whatever we got back from the parser is not XML.
|
||||
goog.asserts.fail('Blockly.Xml.textToDom did not obtain a valid XML tree.');
|
||||
var doc = Blockly.Xml.textToDomDocument_(text);
|
||||
// This function only accepts <xml> documents.
|
||||
if (!doc || !doc.documentElement ||
|
||||
doc.documentElement.nodeName.toLowerCase() != 'xml') {
|
||||
// Whatever we got back from the parser is not the expected structure.
|
||||
throw Error('Blockly.Xml.textToDom expected an <xml> document.');
|
||||
}
|
||||
return dom.firstChild;
|
||||
return doc.documentElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the given workspace then decode an XML DOM and
|
||||
* create blocks on the workspace.
|
||||
* @param {!Element} xml XML DOM.
|
||||
* @param {!Blockly.Workspace} workspace The workspace.
|
||||
* @return {Array.<string>} An array containing new block ids.
|
||||
*/
|
||||
Blockly.Xml.clearWorkspaceAndLoadFromXml = function(xml, workspace) {
|
||||
workspace.setResizesEnabled(false);
|
||||
workspace.clear();
|
||||
var blockIds = Blockly.Xml.domToWorkspace(xml, workspace);
|
||||
workspace.setResizesEnabled(true);
|
||||
return blockIds;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -376,6 +404,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
|
||||
console.warn('Deprecated call to Blockly.Xml.domToWorkspace, ' +
|
||||
'swap the arguments.');
|
||||
}
|
||||
|
||||
var width; // Not used in LTR.
|
||||
if (workspace.RTL) {
|
||||
width = workspace.getWidth();
|
||||
@@ -416,8 +445,13 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
|
||||
}
|
||||
variablesFirst = false;
|
||||
} else if (name == 'shadow') {
|
||||
goog.asserts.fail('Shadow block cannot be a top-level block.');
|
||||
variablesFirst = false;
|
||||
throw Error('Shadow block cannot be a top-level block.');
|
||||
} else if (name == 'comment') {
|
||||
if (workspace.rendered) {
|
||||
Blockly.WorkspaceCommentSvg.fromXml(xmlChild, workspace, width);
|
||||
} else {
|
||||
Blockly.WorkspaceComment.fromXml(xmlChild, workspace);
|
||||
}
|
||||
} else if (name == 'variables') {
|
||||
if (variablesFirst) {
|
||||
Blockly.Xml.domToVariables(xmlChild, workspace);
|
||||
@@ -517,7 +551,7 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) {
|
||||
try {
|
||||
var topBlock = Blockly.Xml.domToBlockHeadless_(xmlBlock, workspace);
|
||||
// Generate list of all blocks.
|
||||
var blocks = topBlock.getDescendants();
|
||||
var blocks = topBlock.getDescendants(false);
|
||||
if (workspace.rendered) {
|
||||
// Hide connections to speed up assembly.
|
||||
topBlock.setConnectionsHidden(true);
|
||||
@@ -562,6 +596,7 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) {
|
||||
return topBlock;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode an XML list of variables and add the variables to the workspace.
|
||||
* @param {!Element} xmlVariables List of XML variable elements.
|
||||
@@ -592,8 +627,9 @@ Blockly.Xml.domToVariables = function(xmlVariables, workspace) {
|
||||
Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
|
||||
var block = null;
|
||||
var prototypeName = xmlBlock.getAttribute('type');
|
||||
goog.asserts.assert(
|
||||
prototypeName, 'Block type unspecified: %s', xmlBlock.outerHTML);
|
||||
if (!prototypeName) {
|
||||
throw Error('Block type unspecified: ' + xmlBlock.outerHTML);
|
||||
}
|
||||
var id = xmlBlock.getAttribute('id');
|
||||
block = workspace.newBlock(prototypeName, id);
|
||||
|
||||
@@ -681,7 +717,7 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
|
||||
} else if (blockChild.previousConnection) {
|
||||
input.connection.connect(blockChild.previousConnection);
|
||||
} else {
|
||||
goog.asserts.fail(
|
||||
throw Error(
|
||||
'Child block does not have output or previous statement.');
|
||||
}
|
||||
}
|
||||
@@ -691,15 +727,18 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
|
||||
block.nextConnection.setShadowDom(childShadowElement);
|
||||
}
|
||||
if (childBlockElement) {
|
||||
goog.asserts.assert(block.nextConnection,
|
||||
'Next statement does not exist.');
|
||||
if (!block.nextConnection) {
|
||||
throw Error('Next statement does not exist.');
|
||||
}
|
||||
// If there is more than one XML 'next' tag.
|
||||
goog.asserts.assert(!block.nextConnection.isConnected(),
|
||||
'Next statement is already connected.');
|
||||
if (block.nextConnection.isConnected()) {
|
||||
throw Error('Next statement is already connected.');
|
||||
}
|
||||
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockElement,
|
||||
workspace);
|
||||
goog.asserts.assert(blockChild.previousConnection,
|
||||
'Next block does not have previous statement.');
|
||||
if (!blockChild.previousConnection) {
|
||||
throw Error('Next block does not have previous statement.');
|
||||
}
|
||||
block.nextConnection.connect(blockChild.previousConnection);
|
||||
}
|
||||
break;
|
||||
@@ -735,14 +774,16 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
|
||||
}
|
||||
if (xmlBlock.nodeName.toLowerCase() == 'shadow') {
|
||||
// Ensure all children are also shadows.
|
||||
var children = block.getChildren();
|
||||
var children = block.getChildren(false);
|
||||
for (var i = 0, child; child = children[i]; i++) {
|
||||
goog.asserts.assert(
|
||||
child.isShadow(), 'Shadow block not allowed non-shadow child.');
|
||||
if (child.isShadow()) {
|
||||
throw Error('Shadow block not allowed non-shadow child.');
|
||||
}
|
||||
}
|
||||
// Ensure this block doesn't have any variable inputs.
|
||||
goog.asserts.assert(block.getVarModels().length == 0,
|
||||
'Shadow blocks cannot have variable references.');
|
||||
if (block.getVarModels().length) {
|
||||
throw Error('Shadow blocks cannot have variable references.');
|
||||
}
|
||||
block.setShadow(true);
|
||||
}
|
||||
return block;
|
||||
@@ -796,7 +837,7 @@ Blockly.Xml.domToField_ = function(block, fieldName, xml) {
|
||||
|
||||
var workspace = block.workspace;
|
||||
var text = xml.textContent;
|
||||
if (field instanceof Blockly.FieldVariable) {
|
||||
if (field.referencesVariables()) {
|
||||
Blockly.Xml.domToFieldVariable_(workspace, xml, text, field);
|
||||
} else {
|
||||
field.setValue(text);
|
||||
|
||||
+156
-99
@@ -93,106 +93,16 @@ Blockly.ZoomControls.prototype.top_ = 0;
|
||||
* @return {!Element} The zoom controls SVG group.
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createDom = function() {
|
||||
var workspace = this.workspace_;
|
||||
/* Here's the markup that will be generated:
|
||||
<g class="blocklyZoom">
|
||||
<clippath id="blocklyZoomoutClipPath837493">
|
||||
<rect width="32" height="32" y="77"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-64" y="-15" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomoutClipPath837493)"></image>
|
||||
<clippath id="blocklyZoominClipPath837493">
|
||||
<rect width="32" height="32" y="43"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-32" y="-49" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoominClipPath837493)"></image>
|
||||
<clippath id="blocklyZoomresetClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" y="-92" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomresetClipPath837493)"></image>
|
||||
</g>
|
||||
*/
|
||||
this.svgGroup_ = Blockly.utils.createSvgElement('g',
|
||||
{'class': 'blocklyZoom'}, null);
|
||||
var clip;
|
||||
this.svgGroup_ =
|
||||
Blockly.utils.createSvgElement('g', {'class': 'blocklyZoom'}, null);
|
||||
|
||||
// Each filter/pattern needs a unique ID for the case of multiple Blockly
|
||||
// instances on a page. Browser behaviour becomes undefined otherwise.
|
||||
// https://neil.fraser.name/news/2015/11/01/
|
||||
var rnd = String(Math.random()).substring(2);
|
||||
|
||||
clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoomoutClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32, 'y': 77},
|
||||
clip);
|
||||
var zoomoutSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'x': -64,
|
||||
'y': -15,
|
||||
'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoominClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32, 'y': 43},
|
||||
clip);
|
||||
var zoominSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height,
|
||||
'x': -32,
|
||||
'y': -49,
|
||||
'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{'id': 'blocklyZoomresetClipPath' + rnd},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{'width': 32, 'height': 32},
|
||||
clip);
|
||||
var zoomresetSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'y': -92,
|
||||
'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
workspace.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
// Attach event listeners.
|
||||
Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.setScale(workspace.options.zoomOptions.startScale);
|
||||
workspace.scrollCenter();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
Blockly.bindEventWithChecks_(zoominSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.zoomCenter(1);
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
Blockly.bindEventWithChecks_(zoomoutSvg, 'mousedown', null, function(e) {
|
||||
workspace.markFocused();
|
||||
workspace.zoomCenter(-1);
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
|
||||
this.createZoomOutSvg_(rnd);
|
||||
this.createZoomInSvg_(rnd);
|
||||
this.createZoomResetSvg_(rnd);
|
||||
return this.svgGroup_;
|
||||
};
|
||||
|
||||
@@ -251,3 +161,150 @@ Blockly.ZoomControls.prototype.position = function() {
|
||||
this.svgGroup_.setAttribute('transform',
|
||||
'translate(' + this.left_ + ',' + this.top_ + ')');
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the zoom in icon and its event handler.
|
||||
* @param {string} rnd The random string to use as a suffix in the clip path's
|
||||
* ID. These IDs must be unique in case there are multiple Blockly
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the "blocklyZoom" group:
|
||||
<clippath id="blocklyZoomoutClipPath837493">
|
||||
<rect width="32" height="32" y="77"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-64" y="-15" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomoutClipPath837493)"></image>
|
||||
*/
|
||||
var ws = this.workspace_;
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{
|
||||
'id': 'blocklyZoomoutClipPath' + rnd
|
||||
},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{
|
||||
'width': 32,
|
||||
'height': 32,
|
||||
'y': 77
|
||||
},
|
||||
clip);
|
||||
var zoomoutSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'x': -64,
|
||||
'y': -15,
|
||||
'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
ws.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
// Attach listener.
|
||||
Blockly.bindEventWithChecks_(zoomoutSvg, 'mousedown', null, function(e) {
|
||||
ws.markFocused();
|
||||
ws.zoomCenter(-1);
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the zoom out icon and its event handler.
|
||||
* @param {string} rnd The random string to use as a suffix in the clip path's
|
||||
* ID. These IDs must be unique in case there are multiple Blockly
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the "blocklyZoom" group:
|
||||
<clippath id="blocklyZoominClipPath837493">
|
||||
<rect width="32" height="32" y="43"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-32" y="-49" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoominClipPath837493)"></image>
|
||||
*/
|
||||
var ws = this.workspace_;
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{
|
||||
'id': 'blocklyZoominClipPath' + rnd
|
||||
},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{
|
||||
'width': 32,
|
||||
'height': 32,
|
||||
'y': 43
|
||||
},
|
||||
clip);
|
||||
var zoominSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height,
|
||||
'x': -32,
|
||||
'y': -49,
|
||||
'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
ws.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
// Attach listener.
|
||||
Blockly.bindEventWithChecks_(zoominSvg, 'mousedown', null, function(e) {
|
||||
ws.markFocused();
|
||||
ws.zoomCenter(1);
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the zoom reset icon and its event handler.
|
||||
* @param {string} rnd The random string to use as a suffix in the clip path's
|
||||
* ID. These IDs must be unique in case there are multiple Blockly
|
||||
* instances on the same page.
|
||||
* @private
|
||||
*/
|
||||
Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) {
|
||||
/* This markup will be generated and added to the "blocklyZoom" group:
|
||||
<clippath id="blocklyZoomresetClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" y="-92" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomresetClipPath837493)"></image>
|
||||
*/
|
||||
var ws = this.workspace_;
|
||||
var clip = Blockly.utils.createSvgElement('clipPath',
|
||||
{
|
||||
'id': 'blocklyZoomresetClipPath' + rnd
|
||||
},
|
||||
this.svgGroup_);
|
||||
Blockly.utils.createSvgElement('rect',
|
||||
{
|
||||
'width': 32,
|
||||
'height': 32
|
||||
},
|
||||
clip);
|
||||
var zoomresetSvg = Blockly.utils.createSvgElement('image',
|
||||
{
|
||||
'width': Blockly.SPRITE.width,
|
||||
'height': Blockly.SPRITE.height, 'y': -92,
|
||||
'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')'
|
||||
},
|
||||
this.svgGroup_);
|
||||
zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
|
||||
ws.options.pathToMedia + Blockly.SPRITE.url);
|
||||
|
||||
// Attach event listeners.
|
||||
Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) {
|
||||
ws.markFocused();
|
||||
ws.setScale(ws.options.zoomOptions.startScale);
|
||||
ws.scrollCenter();
|
||||
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
|
||||
e.stopPropagation(); // Don't start a workspace scroll.
|
||||
e.preventDefault(); // Stop double-clicking from selecting text.
|
||||
});
|
||||
};
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
* @fileoverview Stubbed interface functions for analytics integration.
|
||||
*/
|
||||
|
||||
goog.provide('BlocklyDevTools.Analytics');
|
||||
var BlocklyDevTools = BlocklyDevTools || Object.create(null);
|
||||
BlocklyDevTools.Analytics = BlocklyDevTools.Analytics || Object.create(null);
|
||||
|
||||
/**
|
||||
* Whether these stub methods should log analytics calls to the console.
|
||||
|
||||
@@ -25,17 +25,8 @@
|
||||
*
|
||||
* @author quachtina96 (Tina Quach)
|
||||
*/
|
||||
goog.provide('AppController');
|
||||
|
||||
goog.require('BlockFactory');
|
||||
goog.require('BlocklyDevTools.Analytics');
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('BlockLibraryController');
|
||||
goog.require('BlockExporterController');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.ui.PopupColorPicker');
|
||||
goog.require('goog.ui.ColorPicker');
|
||||
|
||||
goog.require('goog.dom.xml'); // Used to detect Closure
|
||||
|
||||
/**
|
||||
* Controller for the Blockly Factory
|
||||
@@ -161,9 +152,7 @@ AppController.prototype.exportBlockLibraryToFile = function() {
|
||||
*/
|
||||
AppController.prototype.formatBlockLibraryForExport_ = function(blockXmlMap) {
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml', {
|
||||
'xmlns':"http://www.w3.org/1999/xhtml"
|
||||
});
|
||||
var xmlDom = document.createElementNS('http://www.w3.org/1999/xhtml', 'xml');
|
||||
|
||||
// Append each block node to XML DOM.
|
||||
for (var blockType in blockXmlMap) {
|
||||
@@ -184,29 +173,25 @@ AppController.prototype.formatBlockLibraryForExport_ = function(blockXmlMap) {
|
||||
* @private
|
||||
*/
|
||||
AppController.prototype.formatBlockLibraryForImport_ = function(xmlText) {
|
||||
var xmlDom = Blockly.Xml.textToDom(xmlText);
|
||||
|
||||
// Get array of XMLs. Use an asterisk (*) instead of a tag name for the XPath
|
||||
// selector, to match all elements at that level and get all factory_base
|
||||
// blocks.
|
||||
var blockNodes = goog.dom.xml.selectNodes(xmlDom, '*');
|
||||
var inputXml = Blockly.Xml.textToDom(xmlText);
|
||||
// Convert the live HTMLCollection of child Elements into a static array,
|
||||
// since the addition to editorWorkspaceXml below removes it from inputXml.
|
||||
var inputChildren = Array.from(inputXml.children);
|
||||
|
||||
// Create empty map. The line below creates a truly empy object. It doesn't
|
||||
// have built-in attributes/functions such as length or toString.
|
||||
var blockXmlTextMap = Object.create(null);
|
||||
|
||||
// Populate map.
|
||||
for (var i = 0, blockNode; blockNode = blockNodes[i]; i++) {
|
||||
|
||||
for (var i = 0, blockNode; blockNode = inputChildren[i]; i++) {
|
||||
// Add outer XML tag to the block for proper injection in to the
|
||||
// main workspace.
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml', {
|
||||
'xmlns':"http://www.w3.org/1999/xhtml"
|
||||
});
|
||||
xmlDom.appendChild(blockNode);
|
||||
var editorWorkspaceXml =
|
||||
document.createElementNS('http://www.w3.org/1999/xhtml', 'xml');
|
||||
editorWorkspaceXml.appendChild(blockNode);
|
||||
|
||||
xmlText = Blockly.Xml.domToText(xmlDom);
|
||||
xmlText = Blockly.Xml.domToText(editorWorkspaceXml);
|
||||
// All block types should be lowercase.
|
||||
var blockType = this.getBlockTypeFromXml_(xmlText).toLowerCase();
|
||||
// Some names are invalid so fix them up.
|
||||
@@ -376,9 +361,9 @@ AppController.prototype.onTab = function() {
|
||||
AppController.prototype.styleTabs_ = function() {
|
||||
for (var tabName in this.tabMap) {
|
||||
if (this.selectedTab == tabName) {
|
||||
goog.dom.classlist.addRemove(this.tabMap[tabName], 'taboff', 'tabon');
|
||||
this.tabMap[tabName].classList.replace('taboff', 'tabon');
|
||||
} else {
|
||||
goog.dom.classlist.addRemove(this.tabMap[tabName], 'tabon', 'taboff');
|
||||
this.tabMap[tabName].classList.replace('tabon', 'taboff');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,21 +23,15 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Namespace for BlockDefinitionExtractor.
|
||||
*/
|
||||
goog.provide('BlockDefinitionExtractor');
|
||||
|
||||
|
||||
/**
|
||||
* Class to contain all functions needed to extract block definition from
|
||||
* Namespace to contain all functions needed to extract block definition from
|
||||
* the block preview data structure.
|
||||
* @namespace
|
||||
*/
|
||||
BlockDefinitionExtractor = BlockDefinitionExtractor || Object.create(null);
|
||||
var BlockDefinitionExtractor = BlockDefinitionExtractor || Object.create(null);
|
||||
|
||||
/**
|
||||
* Builds a BlockFactory workspace that reflects the block structure of the
|
||||
* exmaple block.
|
||||
* example block.
|
||||
*
|
||||
* @param {!Blockly.Block} block The reference block from which the definition
|
||||
* will be extracted.
|
||||
@@ -45,7 +39,7 @@ BlockDefinitionExtractor = BlockDefinitionExtractor || Object.create(null);
|
||||
* workspace.
|
||||
*/
|
||||
BlockDefinitionExtractor.buildBlockFactoryWorkspace = function(block) {
|
||||
var workspaceXml = goog.dom.createDom('xml');
|
||||
var workspaceXml = document.createElement('xml');
|
||||
workspaceXml.append(
|
||||
BlockDefinitionExtractor.factoryBase_(block, block.type));
|
||||
|
||||
@@ -64,7 +58,7 @@ BlockDefinitionExtractor.buildBlockFactoryWorkspace = function(block) {
|
||||
*/
|
||||
BlockDefinitionExtractor.newDomElement_ = function(name, opt_attrs, opt_text) {
|
||||
// Avoid createDom(..)'s attributes argument for being too HTML specific.
|
||||
var elem = goog.dom.createDom(name);
|
||||
var elem = document.createElement(name);
|
||||
if (opt_attrs) {
|
||||
for (var key in opt_attrs) {
|
||||
elem.setAttribute(key, opt_attrs[key]);
|
||||
@@ -164,16 +158,17 @@ BlockDefinitionExtractor.factoryBase_ = function(block, name) {
|
||||
factoryBaseEl.append(helpUrlValue);
|
||||
|
||||
// Convert colour_ to hue value 0-360 degrees
|
||||
// TODO(#1247): Solve off-by-one errors.
|
||||
// TODO: Deal with colors that don't map to standard hues. (Needs improved
|
||||
// block definitions.)
|
||||
var colour_hue = Math.floor(
|
||||
goog.color.hexToHsv(block.colour_)[0]); // Off by one... sometimes
|
||||
var colourBlock = BlockDefinitionExtractor.colourBlockFromHue_(colour_hue);
|
||||
var colourInputValue =
|
||||
BlockDefinitionExtractor.newDomElement_('value', {name: 'COLOUR'});
|
||||
colourInputValue.append(colourBlock);
|
||||
factoryBaseEl.append(colourInputValue);
|
||||
var colour_hue = block.getHue(); // May be null if not set via hue.
|
||||
if (colour_hue) {
|
||||
var colourBlock = BlockDefinitionExtractor.colourBlockFromHue_(colour_hue);
|
||||
var colourInputValue =
|
||||
BlockDefinitionExtractor.newDomElement_('value', {name: 'COLOUR'});
|
||||
colourInputValue.append(colourBlock);
|
||||
factoryBaseEl.append(colourInputValue);
|
||||
} else {
|
||||
// Editor will not have a colour block and preview will render black.
|
||||
// TODO: Support RGB colours in the block editor.
|
||||
}
|
||||
return factoryBaseEl;
|
||||
};
|
||||
|
||||
@@ -480,7 +475,7 @@ BlockDefinitionExtractor.buildFieldDropdown_ = function(dropdown) {
|
||||
var menuGenerator = dropdown.menuGenerator_;
|
||||
if (typeof menuGenerator === 'function') {
|
||||
var options = menuGenerator();
|
||||
} else if (goog.isArray(menuGenerator)) {
|
||||
} else if (Array.isArray(menuGenerator)) {
|
||||
var options = menuGenerator;
|
||||
} else {
|
||||
throw new Error('Unrecognized type of menuGenerator: ' + menuGenerator);
|
||||
|
||||
@@ -29,22 +29,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockExporterController');
|
||||
|
||||
goog.require('BlocklyDevTools.Analytics');
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('StandardCategories');
|
||||
goog.require('BlockExporterView');
|
||||
goog.require('BlockExporterTools');
|
||||
goog.require('goog.dom.xml');
|
||||
|
||||
|
||||
/**
|
||||
* BlockExporter Controller Class
|
||||
* @param {!BlockLibrary.Storage} blockLibStorage Block Library Storage.
|
||||
* @constructor
|
||||
*/
|
||||
BlockExporterController = function(blockLibStorage) {
|
||||
function BlockExporterController(blockLibStorage) {
|
||||
// BlockLibrary.Storage object containing user's saved blocks.
|
||||
this.blockLibStorage = blockLibStorage;
|
||||
// Utils for generating code to export.
|
||||
@@ -132,11 +122,11 @@ BlockExporterController.prototype.export = function() {
|
||||
BlocklyDevTools.Analytics.onWarning(msg);
|
||||
alert(msg);
|
||||
} else {
|
||||
|
||||
|
||||
// Get generator stub code in the selected language for the blocks.
|
||||
var genStubs = this.tools.getGeneratorCode(blockXmlMap,
|
||||
language);
|
||||
|
||||
|
||||
// Download the file.
|
||||
FactoryUtils.createAndDownloadFile(
|
||||
genStubs, generatorStub_filename + '.js', 'javascript');
|
||||
|
||||
@@ -28,25 +28,15 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockExporterTools');
|
||||
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('BlockOption');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.xml');
|
||||
|
||||
|
||||
/**
|
||||
* Block Exporter Tools Class
|
||||
* @constructor
|
||||
*/
|
||||
BlockExporterTools = function() {
|
||||
function BlockExporterTools() {
|
||||
// Create container for hidden workspace.
|
||||
this.container = goog.dom.createDom('div', {
|
||||
'id': 'blockExporterTools_hiddenWorkspace'
|
||||
}, ''); // Empty quotes for empty div.
|
||||
// Hide hidden workspace.
|
||||
this.container.style.display = 'none';
|
||||
this.container = document.createElement('div');
|
||||
this.container.id = 'blockExporterTools_hiddenWorkspace';
|
||||
this.container.style.display = 'none'; // Hide the hidden workspace.
|
||||
document.body.appendChild(this.container);
|
||||
/**
|
||||
* Hidden workspace for the Block Exporter that holds pieces that make
|
||||
@@ -167,45 +157,6 @@ BlockExporterTools.prototype.addBlockDefinitions = function(blockXmlMap) {
|
||||
eval(blockDefs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Pulls information about all blocks in the block library to generate XML
|
||||
* for the selector workpace's toolbox.
|
||||
* @param {!BlockLibraryStorage} blockLibStorage Block Library Storage object.
|
||||
* @return {!Element} XML representation of the toolbox.
|
||||
*/
|
||||
BlockExporterTools.prototype.generateToolboxFromLibrary
|
||||
= function(blockLibStorage) {
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml', {
|
||||
'id' : 'blockExporterTools_toolbox',
|
||||
'style' : 'display:none'
|
||||
});
|
||||
|
||||
var allBlockTypes = blockLibStorage.getBlockTypes();
|
||||
// Object mapping block type to XML.
|
||||
var blockXmlMap = blockLibStorage.getBlockXmlMap(allBlockTypes);
|
||||
|
||||
// Define the custom blocks in order to be able to create instances of
|
||||
// them in the exporter workspace.
|
||||
this.addBlockDefinitions(blockXmlMap);
|
||||
|
||||
for (var blockType in blockXmlMap) {
|
||||
// Get block.
|
||||
var block = FactoryUtils.getDefinedBlock(blockType, this.hiddenWorkspace);
|
||||
var category = FactoryUtils.generateCategoryXml([block], blockType);
|
||||
xmlDom.appendChild(category);
|
||||
}
|
||||
|
||||
// If there are no blocks in library and the map is empty, append dummy
|
||||
// category.
|
||||
if (Object.keys(blockXmlMap).length == 0) {
|
||||
var category = goog.dom.createDom('category');
|
||||
category.setAttribute('name','Next Saved Block');
|
||||
xmlDom.appendChild(category);
|
||||
}
|
||||
return xmlDom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate XML for the workspace factory's category from imported block
|
||||
* definitions.
|
||||
|
||||
@@ -27,19 +27,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockExporterView');
|
||||
|
||||
goog.require('BlockExporterTools');
|
||||
goog.require('BlockOption');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
/**
|
||||
* BlockExporter View Class
|
||||
* @param {!Object} blockOptions Map of block types to BlockOption objects.
|
||||
* @constructor
|
||||
*/
|
||||
BlockExporterView = function(blockOptions) {
|
||||
function BlockExporterView(blockOptions) {
|
||||
// Map of block types to BlockOption objects to select from.
|
||||
this.blockOptions = blockOptions;
|
||||
};
|
||||
|
||||
@@ -32,14 +32,6 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockLibraryController');
|
||||
|
||||
goog.require('BlocklyDevTools.Analytics');
|
||||
goog.require('BlockLibraryStorage');
|
||||
goog.require('BlockLibraryView');
|
||||
goog.require('BlockFactory');
|
||||
|
||||
|
||||
/**
|
||||
* Block Library Controller Class
|
||||
* @param {string} blockLibraryName Desired name of Block Library, also used
|
||||
@@ -48,7 +40,7 @@ goog.require('BlockFactory');
|
||||
* object that allows user to import a block library.
|
||||
* @constructor
|
||||
*/
|
||||
BlockLibraryController = function(blockLibraryName, opt_blockLibraryStorage) {
|
||||
function BlockLibraryController(blockLibraryName, opt_blockLibraryStorage) {
|
||||
this.name = blockLibraryName;
|
||||
// Create a new, empty Block Library Storage object, or load existing one.
|
||||
this.storage = opt_blockLibraryStorage || new BlockLibraryStorage(this.name);
|
||||
@@ -144,7 +136,7 @@ BlockLibraryController.prototype.saveToBlockLibrary = function() {
|
||||
}
|
||||
|
||||
// Create block XML.
|
||||
var xmlElement = goog.dom.createDom('xml');
|
||||
var xmlElement = document.createElement('xml');
|
||||
var block = FactoryUtils.getRootBlock(BlockFactory.mainWorkspace);
|
||||
xmlElement.appendChild(Blockly.Xml.blockToDomWithXY(block));
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockLibraryStorage');
|
||||
|
||||
|
||||
/**
|
||||
* Represents a block library's storage.
|
||||
* @param {string} blockLibraryName Desired name of Block Library, also used
|
||||
@@ -37,7 +34,7 @@ goog.provide('BlockLibraryStorage');
|
||||
* @param {Object} opt_blocks Object mapping block type to XML.
|
||||
* @constructor
|
||||
*/
|
||||
BlockLibraryStorage = function(blockLibraryName, opt_blocks) {
|
||||
function BlockLibraryStorage(blockLibraryName, opt_blocks) {
|
||||
// Add prefix to this.name to avoid collisions in local storage.
|
||||
this.name = 'BlockLibraryStorage.' + blockLibraryName;
|
||||
if (!opt_blocks) {
|
||||
@@ -60,9 +57,7 @@ BlockLibraryStorage = function(blockLibraryName, opt_blocks) {
|
||||
* Reads the named block library from local storage and saves it in this.blocks.
|
||||
*/
|
||||
BlockLibraryStorage.prototype.loadFromLocalStorage = function() {
|
||||
// goog.global is synonymous to window, and allows for flexibility
|
||||
// between browsers.
|
||||
var object = goog.global.localStorage[this.name];
|
||||
var object = localStorage[this.name];
|
||||
this.blocks = object ? JSON.parse(object) : null;
|
||||
};
|
||||
|
||||
@@ -70,7 +65,7 @@ BlockLibraryStorage.prototype.loadFromLocalStorage = function() {
|
||||
* Writes the current block library (this.blocks) to local storage.
|
||||
*/
|
||||
BlockLibraryStorage.prototype.saveToLocalStorage = function() {
|
||||
goog.global.localStorage[this.name] = JSON.stringify(this.blocks);
|
||||
localStorage[this.name] = JSON.stringify(this.blocks);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockLibraryView');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.classlist');
|
||||
|
||||
|
||||
/**
|
||||
* BlockLibraryView Class
|
||||
* @constructor
|
||||
@@ -59,10 +53,10 @@ var BlockLibraryView = function() {
|
||||
*/
|
||||
BlockLibraryView.prototype.addOption = function(blockType, selected) {
|
||||
// Create option.
|
||||
var option = goog.dom.createDom('a', {
|
||||
'id': 'dropdown_' + blockType,
|
||||
'class': 'blockLibOpt'
|
||||
}, blockType);
|
||||
var option = document.createElement('a');
|
||||
option.id ='dropdown_' + blockType;
|
||||
option.classList.add('blockLibOpt');
|
||||
option.textContent = blockType;
|
||||
|
||||
// Add option to dropdown.
|
||||
this.dropdown.appendChild(option);
|
||||
@@ -99,7 +93,7 @@ BlockLibraryView.prototype.setSelectedBlockType = function(blockTypeToSelect) {
|
||||
* @private
|
||||
*/
|
||||
BlockLibraryView.prototype.selectOption_ = function(option) {
|
||||
goog.dom.classlist.add(option, 'dropdown-content-selected');
|
||||
option.classList.add('dropdown-content-selected');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -109,7 +103,7 @@ BlockLibraryView.prototype.selectOption_ = function(option) {
|
||||
* @private
|
||||
*/
|
||||
BlockLibraryView.prototype.deselectOption_ = function(option) {
|
||||
goog.dom.classlist.remove(option, 'dropdown-content-selected');
|
||||
option.classList.remove('dropdown-content-selected');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -150,13 +144,12 @@ BlockLibraryView.prototype.updateButtons =
|
||||
if (blockType == 'block_type') {
|
||||
buttonFormatClass = 'button_alert';
|
||||
}
|
||||
goog.dom.classlist.add(this.saveButton, buttonFormatClass);
|
||||
this.saveButton.classList.add(buttonFormatClass);
|
||||
this.saveButton.disabled = false;
|
||||
|
||||
} else {
|
||||
// No changes to save.
|
||||
var classesToRemove = ['button_alert', 'button_warn'];
|
||||
goog.dom.classlist.removeAll(this.saveButton, classesToRemove);
|
||||
this.saveButton.classList.remove('button_alert', 'button_warn');
|
||||
this.saveButton.disabled = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,18 +19,15 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Javascript for the BlockOption class, used to represent each of
|
||||
* the various blocks that you may select. Each block option has a checkbox,
|
||||
* a label, and a preview workspace through which to view the block.
|
||||
* @fileoverview Javascript for the BlockOption class, used to represent each
|
||||
* of the various blocks that you may select in the Block Selector. Each block
|
||||
* option has a checkbox, a label, and a preview workspace through which to
|
||||
* view the block.
|
||||
*
|
||||
* @author quachtina96 (Tina Quach)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('BlockOption');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
/**
|
||||
* BlockOption Class
|
||||
* A block option includes checkbox, label, and div element that shows a preview
|
||||
@@ -70,48 +67,42 @@ var BlockOption = function(blockSelector, blockType, previewBlockXml) {
|
||||
*/
|
||||
BlockOption.prototype.createDom = function() {
|
||||
// Create the div for the block option.
|
||||
var blockOptContainer = goog.dom.createDom('div', {
|
||||
'id': this.blockType,
|
||||
'class': 'blockOption'
|
||||
}, ''); // Empty quotes for empty div.
|
||||
var blockOptContainer = document.createElement('div');
|
||||
blockOptContainer.id = this.blockType;
|
||||
blockOptContainer.classList.add('blockOption');
|
||||
|
||||
// Create and append div in which to inject the workspace for viewing the
|
||||
// block option.
|
||||
var blockOptionPreview = goog.dom.createDom('div', {
|
||||
'id' : this.blockType + '_workspace',
|
||||
'class': 'blockOption_preview'
|
||||
}, '');
|
||||
var blockOptionPreview = document.createElement('div');
|
||||
blockOptionPreview.id = this.blockType + '_workspace';
|
||||
blockOptionPreview.classList.add('blockOption_preview');
|
||||
blockOptContainer.appendChild(blockOptionPreview);
|
||||
|
||||
// Create and append container to hold checkbox and label.
|
||||
var checkLabelContainer = goog.dom.createDom('div', {
|
||||
'class': 'blockOption_checkLabel'
|
||||
}, '');
|
||||
var checkLabelContainer = document.createElement('div');
|
||||
checkLabelContainer.classList.add('blockOption_checkLabel');
|
||||
blockOptContainer.appendChild(checkLabelContainer);
|
||||
|
||||
// Create and append container for checkbox.
|
||||
var checkContainer = goog.dom.createDom('div', {
|
||||
'class': 'blockOption_check'
|
||||
}, '');
|
||||
var checkContainer = document.createElement('div');
|
||||
checkContainer.classList.add('blockOption_check');
|
||||
checkLabelContainer.appendChild(checkContainer);
|
||||
|
||||
// Create and append checkbox.
|
||||
this.checkbox = goog.dom.createDom('input', {
|
||||
'type': 'checkbox',
|
||||
'id': this.blockType + '_check'
|
||||
}, '');
|
||||
this.checkbox = document.createElement('input');
|
||||
this.checkbox.id = this.blockType + '_check';
|
||||
this.checkbox.setAttribute('type', 'checkbox');
|
||||
checkContainer.appendChild(this.checkbox);
|
||||
|
||||
// Create and append container for block label.
|
||||
var labelContainer = goog.dom.createDom('div', {
|
||||
'class': 'blockOption_label'
|
||||
}, '');
|
||||
var labelContainer = document.createElement('div');
|
||||
labelContainer.classList.add('blockOption_label');
|
||||
checkLabelContainer.appendChild(labelContainer);
|
||||
|
||||
// Create and append text node for the label.
|
||||
var labelText = goog.dom.createDom('p', {
|
||||
'id': this.blockType + '_text'
|
||||
}, this.blockType);
|
||||
var labelText = document.createElement('p');
|
||||
labelText.id = this.blockType + '_text';
|
||||
labelText.textContent = this.blockType;
|
||||
labelContainer.appendChild(labelText);
|
||||
|
||||
this.dom = blockOptContainer;
|
||||
|
||||
@@ -32,10 +32,7 @@
|
||||
/**
|
||||
* Namespace for Block Factory.
|
||||
*/
|
||||
goog.provide('BlockFactory');
|
||||
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('StandardCategories');
|
||||
var BlockFactory = BlockFactory || Object.create(null);
|
||||
|
||||
/**
|
||||
* Workspace for user to build block.
|
||||
@@ -151,7 +148,7 @@ BlockFactory.updateLanguage = function() {
|
||||
if (!BlockFactory.updateBlocksFlagDelayed) {
|
||||
var languagePre = document.getElementById('languagePre');
|
||||
var languageTA = document.getElementById('languageTA');
|
||||
code = languagePre.textContent.trim();
|
||||
code = languagePre.innerText.trim();
|
||||
languageTA.value = code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,7 @@
|
||||
/**
|
||||
* Namespace for FactoryUtils.
|
||||
*/
|
||||
goog.provide('FactoryUtils');
|
||||
|
||||
goog.require('BlockDefinitionExtractor');
|
||||
|
||||
var FactoryUtils = FactoryUtils || Object.create(null);
|
||||
|
||||
/**
|
||||
* Get block definition code for the current block.
|
||||
@@ -768,7 +765,7 @@ FactoryUtils.getBlockTypeFromJsDefinition = function(blockDef) {
|
||||
*/
|
||||
FactoryUtils.generateCategoryXml = function(blocks, categoryName) {
|
||||
// Create category DOM element.
|
||||
var categoryElement = goog.dom.createDom('category');
|
||||
var categoryElement = document.createElement('category');
|
||||
categoryElement.setAttribute('name', categoryName);
|
||||
|
||||
// For each block, add block element to category.
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/**
|
||||
* Namespace for StandardCategories
|
||||
*/
|
||||
goog.provide('StandardCategories');
|
||||
var StandardCategories = StandardCategories || Object.create(null);
|
||||
|
||||
|
||||
// Map of standard category information necessary to add a standard category
|
||||
|
||||
@@ -34,11 +34,6 @@
|
||||
* @author Emma Dauterman (evd2014)
|
||||
*/
|
||||
|
||||
goog.require('BlocklyDevTools.Analytics');
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('StandardCategories');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a WorkspaceFactoryController
|
||||
* @param {string} toolboxName Name of workspace toolbox XML.
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
* @author Emma Dauterman (evd2014)
|
||||
*/
|
||||
|
||||
goog.require('FactoryUtils');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a WorkspaceFactoryGenerator
|
||||
@@ -61,11 +59,10 @@ WorkspaceFactoryGenerator = function(model) {
|
||||
*/
|
||||
WorkspaceFactoryGenerator.prototype.generateToolboxXml = function() {
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml',
|
||||
{
|
||||
'id' : 'toolbox',
|
||||
'style' : 'display:none'
|
||||
});
|
||||
var xmlDom = document.createElement('xml');
|
||||
xmlDom.id = 'toolbox';
|
||||
xmlDom.style.display = 'none';
|
||||
|
||||
if (!this.model.hasElements()) {
|
||||
// Toolbox has no categories. Use XML directly from workspace.
|
||||
this.loadToHiddenWorkspace_(this.model.getSelectedXml());
|
||||
@@ -88,10 +85,10 @@ WorkspaceFactoryGenerator.prototype.generateToolboxXml = function() {
|
||||
var element = toolboxList[i];
|
||||
if (element.type == ListElement.TYPE_SEPARATOR) {
|
||||
// If the next element is a separator.
|
||||
var nextElement = goog.dom.createDom('sep');
|
||||
var nextElement = document.createElement('sep');
|
||||
} else if (element.type == ListElement.TYPE_CATEGORY) {
|
||||
// If the next element is a category.
|
||||
var nextElement = goog.dom.createDom('category');
|
||||
var nextElement = document.createElement('category');
|
||||
nextElement.setAttribute('name', element.name);
|
||||
// Add a colour attribute if one exists.
|
||||
if (element.color != null) {
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
* @author Emma Dauterman (evd2014)
|
||||
*/
|
||||
|
||||
goog.require('FactoryUtils');
|
||||
goog.require('goog.ui.PopupColorPicker');
|
||||
goog.require('goog.ui.ColorPicker');
|
||||
|
||||
/**
|
||||
* Namespace for workspace factory initialization methods.
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
* @author Emma Dauterman (edauterman)
|
||||
*/
|
||||
|
||||
goog.require('FactoryUtils');
|
||||
|
||||
/**
|
||||
* Class for a WorkspaceFactoryView
|
||||
|
||||
+1
-1
@@ -538,7 +538,7 @@ Code.runJS = function() {
|
||||
Code.discard = function() {
|
||||
var count = Code.workspace.getAllBlocks().length;
|
||||
if (count < 2 ||
|
||||
window.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1', count))) {
|
||||
window.confirm(Blockly.Msg['DELETE_ALL_BLOCKS'].replace('%1', count))) {
|
||||
Code.workspace.clear();
|
||||
if (window.location.hash) {
|
||||
window.location.hash = '';
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Inputs" colour="230">
|
||||
<category name="Inputs" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number" gap="32">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
@@ -47,8 +47,8 @@
|
||||
</block>
|
||||
</category>
|
||||
<sep></sep>
|
||||
<category name="Variables" colour="330" custom="VARIABLE"></category>
|
||||
<category name="Functions" colour="290" custom="PROCEDURE"></category>
|
||||
<category name="Variables" colour="%{BKY_VARIABLES_HUE}" custom="VARIABLE"></category>
|
||||
<category name="Functions" colour="%{BKY_PROCEDURES_HUE}" custom="PROCEDURE"></category>
|
||||
</xml>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
<h1><a href="https://developers.google.com/blockly/">Blockly</a> >
|
||||
<a href="../index.html">Demos</a> > Generating JavaScript</h1>
|
||||
|
||||
<p>This is a simple demo of generating code from blocks.</p>
|
||||
<p>This is a simple demo of generating code from blocks and running
|
||||
the code in a sandboxed JavaScript interpreter.</p>
|
||||
|
||||
<p>→ More info on <a href="https://developers.google.com/blockly/guides/configure/web/code-generators">Code Generators</a>…</p>
|
||||
<p>→ More info on <a href="https://developers.google.com/blockly/guides/configure/web/code-generators">Code Generators</a> and <a href="https://developers.google.com/blockly/guides/app-integration/running-javascript">Running JavaScript</a>.</p>
|
||||
|
||||
<p>
|
||||
<button onclick="showCode()">Show JavaScript</button>
|
||||
@@ -34,14 +35,14 @@
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -51,14 +52,14 @@
|
||||
</block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
</category>
|
||||
<category name="Text">
|
||||
<category name="Text" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_length"></block>
|
||||
<block type="text_print"></block>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
@@ -146,10 +146,10 @@
|
||||
</block>
|
||||
<block type="math_random_float"></block>
|
||||
</category>
|
||||
<category name="Variables">
|
||||
<category name="Variables" colour="%{BKY_VARIABLES_HUE}">
|
||||
<block type="graph_get_x"></block>
|
||||
</category>
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
@@ -196,9 +196,9 @@ Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "graph_get_x",
|
||||
"message0": "x",
|
||||
"output": "Number",
|
||||
"colour": Blockly.Msg.VARIABLES_HUE,
|
||||
"tooltip": Blockly.Msg.VARIABLES_GET_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.VARIABLES_GET_HELPURL
|
||||
"colour": Blockly.Msg['VARIABLES_HUE'],
|
||||
"tooltip": Blockly.Msg['VARIABLES_GET_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['VARIABLES_GET_HELPURL']
|
||||
}]);
|
||||
|
||||
Blockly.JavaScript['graph_get_x'] = function(block) {
|
||||
@@ -216,9 +216,9 @@ Blockly.defineBlocksWithJsonArray([{
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"colour": Blockly.Msg.VARIABLES_HUE,
|
||||
"tooltip": Blockly.Msg.VARIABLES_SET_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.VARIABLES_SET_HELPURL
|
||||
"colour": Blockly.Msg['VARIABLES_HUE'],
|
||||
"tooltip": Blockly.Msg['VARIABLES_SET_TOOLTIP'],
|
||||
"helpUrl": Blockly.Msg['VARIABLES_SET_HELPURL']
|
||||
}]);
|
||||
|
||||
Blockly.JavaScript['graph_set_y'] = function(block) {
|
||||
|
||||
@@ -41,14 +41,14 @@
|
||||
</div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -58,14 +58,14 @@
|
||||
</block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
</category>
|
||||
<category name="Text">
|
||||
<category name="Text" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_length"></block>
|
||||
<block type="text_print"></block>
|
||||
@@ -75,8 +75,11 @@
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Variables" custom="VARIABLE"></category>
|
||||
<category name="Functions" custom="PROCEDURE"></category>
|
||||
<sep></sep>
|
||||
<category name="Variables" custom="VARIABLE" colour="%{BKY_VARIABLES_HUE}">
|
||||
</category>
|
||||
<category name="Functions" custom="PROCEDURE" colour="%{BKY_PROCEDURES_HUE}">
|
||||
</category>
|
||||
</xml>
|
||||
|
||||
<xml id="startBlocks" style="display: none">
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
</div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -65,14 +65,14 @@
|
||||
</block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
</category>
|
||||
<category name="Text">
|
||||
<category name="Text" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_length"></block>
|
||||
<block type="text_print"></block>
|
||||
@@ -82,8 +82,11 @@
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Variables" custom="VARIABLE"></category>
|
||||
<category name="Functions" custom="PROCEDURE"></category>
|
||||
<sep></sep>
|
||||
<category name="Variables" custom="VARIABLE" colour="%{BKY_VARIABLES_HUE}">
|
||||
</category>
|
||||
<category name="Functions" custom="PROCEDURE" colour="%{BKY_PROCEDURES_HUE}">
|
||||
</category>
|
||||
</xml>
|
||||
|
||||
<xml id="startBlocks" style="display: none">
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -67,14 +67,14 @@
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
</category>
|
||||
<category name="Text">
|
||||
<category name="Text" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_length"></block>
|
||||
<block type="text_print"></block>
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
Blockly.Blocks['plane_set_seats'] = {
|
||||
// Block seat variable setter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['VARIABLES_SET_HELPURL']);
|
||||
this.setColour(330);
|
||||
this.appendValueInput('VALUE')
|
||||
.appendField(Plane.getMsg('Plane_setSeats'));
|
||||
this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP);
|
||||
this.setTooltip(Blockly.Msg['VARIABLES_SET_TOOLTIP']);
|
||||
this.setDeletable(false);
|
||||
}
|
||||
};
|
||||
@@ -45,7 +45,7 @@ Blockly.JavaScript['plane_set_seats'] = function(block) {
|
||||
Blockly.Blocks['plane_get_rows'] = {
|
||||
// Block for row variable getter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['VARIABLES_GET_HELPURL']);
|
||||
this.setColour(330);
|
||||
this.appendDummyInput()
|
||||
.appendField(Plane.getMsg('Plane_getRows'), 'title');
|
||||
@@ -65,7 +65,7 @@ Blockly.JavaScript['plane_get_rows'] = function(block) {
|
||||
Blockly.Blocks['plane_get_rows1st'] = {
|
||||
// Block for first class row variable getter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['VARIABLES_GET_HELPURL']);
|
||||
this.setColour(330);
|
||||
this.appendDummyInput()
|
||||
.appendField(Plane.getMsg('Plane_getRows1'), 'title');
|
||||
@@ -85,7 +85,7 @@ Blockly.JavaScript['plane_get_rows1st'] = function(block) {
|
||||
Blockly.Blocks['plane_get_rows2nd'] = {
|
||||
// Block for second class row variable getter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
|
||||
this.setHelpUrl(Blockly.Msg['VARIABLES_GET_HELPURL']);
|
||||
this.setColour(330);
|
||||
this.appendDummyInput()
|
||||
.appendField(Plane.getMsg('Plane_getRows2'), 'title');
|
||||
|
||||
+11
-8
@@ -42,7 +42,7 @@
|
||||
<div id="blocklyDiv"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="منطق">
|
||||
<category name="منطق" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
@@ -51,7 +51,7 @@
|
||||
<block type="logic_null"></block>
|
||||
<block type="logic_ternary"></block>
|
||||
</category>
|
||||
<category name="الحلقات">
|
||||
<category name="الحلقات" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -80,7 +80,7 @@
|
||||
<block type="controls_forEach"></block>
|
||||
<block type="controls_flow_statements"></block>
|
||||
</category>
|
||||
<category name="رياضيات">
|
||||
<category name="رياضيات" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
@@ -118,7 +118,7 @@
|
||||
</block>
|
||||
<block type="math_random_float"></block>
|
||||
</category>
|
||||
<category name="نص">
|
||||
<category name="نص" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_join"></block>
|
||||
<block type="text_append">
|
||||
@@ -139,7 +139,7 @@
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="قوائم">
|
||||
<category name="قوائم" colour="%{BKY_LISTS_HUE}">
|
||||
<block type="lists_create_empty"></block>
|
||||
<block type="lists_create_with"></block>
|
||||
<block type="lists_repeat">
|
||||
@@ -155,13 +155,16 @@
|
||||
<block type="lists_getIndex"></block>
|
||||
<block type="lists_setIndex"></block>
|
||||
</category>
|
||||
<category name="لون">
|
||||
<category name="لون" colour="%{BKY_COLOUR_HUE}">
|
||||
<block type="colour_picker"></block>
|
||||
<block type="colour_rgb"></block>
|
||||
<block type="colour_blend"></block>
|
||||
</category>
|
||||
<category name="متغيرات" custom="VARIABLE"></category>
|
||||
<category name="إجراءات" custom="PROCEDURE"></category>
|
||||
<sep></sep>
|
||||
<category name="متغيرات" custom="VARIABLE" colour="%{BKY_VARIABLES_HUE}">
|
||||
</category>
|
||||
<category name="إجراءات" custom="PROCEDURE" colour="%{BKY_PROCEDURES_HUE}">
|
||||
</category>
|
||||
</xml>
|
||||
|
||||
<xml id="startBlocks" style="display: none">
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -67,14 +67,14 @@
|
||||
</block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
</category>
|
||||
<category name="Text">
|
||||
<category name="Text" colour="%{BKY_TEXTS_HUE}">
|
||||
<block type="text"></block>
|
||||
<block type="text_length"></block>
|
||||
<block type="text_print"></block>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div id="blocklyDiv" style="height: 600px; width: 800px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic">
|
||||
<category name="Logic" colour="%{BKY_LOGIC_HUE}">
|
||||
<category name="If">
|
||||
<block type="controls_if"></block>
|
||||
<block type="controls_if">
|
||||
@@ -38,7 +38,7 @@
|
||||
<mutation elseif="1" else="1"></mutation>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Boolean">
|
||||
<category name="Boolean" colour="%{BKY_LOGIC_HUE}">
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
@@ -47,7 +47,7 @@
|
||||
<block type="logic_ternary"></block>
|
||||
</category>
|
||||
</category>
|
||||
<category name="Loops">
|
||||
<category name="Loops" colour="%{BKY_LOOPS_HUE}">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<block type="math_number">
|
||||
@@ -77,7 +77,7 @@
|
||||
<block type="controls_forEach"></block>
|
||||
<block type="controls_flow_statements"></block>
|
||||
</category>
|
||||
<category name="Math">
|
||||
<category name="Math" colour="%{BKY_MATH_HUE}">
|
||||
<block type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</block>
|
||||
@@ -115,7 +115,7 @@
|
||||
</block>
|
||||
<block type="math_random_float"></block>
|
||||
</category>
|
||||
<category name="Lists">
|
||||
<category name="Lists" colour="%{BKY_LISTS_HUE}">
|
||||
<block type="lists_create_empty"></block>
|
||||
<block type="lists_create_with"></block>
|
||||
<block type="lists_repeat">
|
||||
@@ -131,8 +131,11 @@
|
||||
<block type="lists_getIndex"></block>
|
||||
<block type="lists_setIndex"></block>
|
||||
</category>
|
||||
<category name="Variables" custom="VARIABLE"></category>
|
||||
<category name="Functions" custom="PROCEDURE"></category>
|
||||
<sep></sep>
|
||||
<category name="Variables" custom="VARIABLE" colour="%{BKY_VARIABLES_HUE}">
|
||||
</category>
|
||||
<category name="Functions" custom="PROCEDURE" colour="%{BKY_PROCEDURES_HUE}">
|
||||
</category>
|
||||
<sep></sep>
|
||||
<category name="Library" expanded="true">
|
||||
<category name="Randomize">
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2018 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 Gulp script to build Blockly for Node & NPM.
|
||||
* Run this script by calling "npm install" in this directory.
|
||||
*/
|
||||
|
||||
var gulp = require('gulp');
|
||||
gulp.shell = require('gulp-shell');
|
||||
gulp.concat = require('gulp-concat');
|
||||
var insert = require('gulp-insert');
|
||||
|
||||
// Rebuilds Blockly, including the following:
|
||||
// - blockly_compressed.js
|
||||
// - blocks_compressed.js
|
||||
// - Localization string tables in msg/js/*.js
|
||||
// - Generators in generators/*.js
|
||||
// These files are already up-to-date in the master branch.
|
||||
gulp.task('build', gulp.shell.task([
|
||||
'python build.py'
|
||||
]));
|
||||
|
||||
// Concatenates the necessary files to load Blockly in a Node.js VM. Blockly's
|
||||
// individual libraries target use in a browser, where globals (via the window
|
||||
// objects) are used to share state and APIs. By concatenating all the
|
||||
// necessary components into a single file, Blockly can be loaded as a Node.js
|
||||
// module.
|
||||
//
|
||||
// This task builds Node with the assumption that the app needs English blocks
|
||||
// and JavaScript code generation. If you need another localization or
|
||||
// generator language, just copy and edit the srcs. Only one localization
|
||||
// language can be included.
|
||||
gulp.task('blockly_javascript_en', function() {
|
||||
var srcs = [
|
||||
'blockly_compressed.js',
|
||||
'blocks_compressed.js',
|
||||
'javascript_compressed.js',
|
||||
'msg/js/en.js'
|
||||
];
|
||||
// Concatenate the sources, appending the module export at the bottom.
|
||||
// Override textToDomDocument_, providing Node alternative to DOMParser.
|
||||
return gulp.src(srcs)
|
||||
.pipe(gulp.concat('blockly_node_javascript_en.js'))
|
||||
.pipe(insert.append(`
|
||||
if (typeof DOMParser !== 'function') {
|
||||
var JSDOM = require('jsdom').JSDOM;
|
||||
Blockly.Xml.textToDomDocument_ = function(text) {
|
||||
var jsdom = new JSDOM(text, { contentType: 'text/xml' });
|
||||
return jsdom.window.document;
|
||||
};
|
||||
}
|
||||
if (typeof module === 'object') { module.exports = Blockly; }
|
||||
if (typeof window === 'object') { window.Blockly = Blockly; }\n`))
|
||||
.pipe(gulp.dest(''));
|
||||
});
|
||||
|
||||
/**
|
||||
* Task-builder for the watch function. Currently any change invokes the whole
|
||||
* build script. Invoke with "gulp watch".
|
||||
*
|
||||
* @param {?string=} concatTask Name of the concatenating task for node usage.
|
||||
*/
|
||||
// TODO: Only run the necessary phases of the build script for a given change.
|
||||
function buildWatchTaskFn(concatTask) {
|
||||
return function() {
|
||||
// Tasks to trigger.
|
||||
var tasks = ['build'];
|
||||
if (concatTask) {
|
||||
tasks.push(concatTask);
|
||||
}
|
||||
|
||||
// Currently any changes invokes the whole build script. (To fix.)
|
||||
var srcs = [
|
||||
'core/**/*.js', // Blockly core code
|
||||
'blocks/*.js', // Block definitions
|
||||
'generators/**/*.js', // Code generation
|
||||
'msg/messages.js', 'msg/json/*.json' // Localization data
|
||||
];
|
||||
var options = {
|
||||
debounceDelay: 2000 // Milliseconds to delay rebuild.
|
||||
};
|
||||
gulp.watch(srcs, options, tasks);
|
||||
};
|
||||
}
|
||||
|
||||
// Watch Blockly files for changes and trigger automatic rebuilds, including
|
||||
// the Node-ready blockly_node_javascript_en.js file.
|
||||
gulp.task('watch', buildWatchTaskFn('blockly_javascript_en'));
|
||||
|
||||
// The default task concatenates files for Node.js, using English language
|
||||
// blocks and the JavaScript generator.
|
||||
gulp.task('default', ['build', 'blockly_javascript_en']);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user