mirror of
https://github.com/google/blockly.git
synced 2026-01-06 16:40:07 +01:00
feat: add serialization and deserialization of comments (#5216)
* Add tests for (de)seralizing icons * Add logic for (de)serializing icons * fix: add docs for saveIcons * fix: add timeout for setting comment visible
This commit is contained in:
committed by
alschmiedt
parent
91922aa571
commit
1b47953c58
@@ -20,6 +20,7 @@ const Connection = goog.requireType('Blockly.Connection');
|
||||
const Events = goog.require('Blockly.Events');
|
||||
const {MissingBlockType, MissingConnection, BadConnectionCheck} =
|
||||
goog.require('Blockly.serialization.exceptions');
|
||||
const Size = goog.require('Blockly.utils.Size');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const Xml = goog.require('Blockly.Xml');
|
||||
@@ -54,6 +55,7 @@ exports.ConnectionState = ConnectionState;
|
||||
* inline: (boolean|undefined),
|
||||
* data: (string|undefined),
|
||||
* extra-state: *,
|
||||
* icons: (!Object<string, *>|undefined),
|
||||
* fields: (!Object<string, *>|undefined),
|
||||
* inputs: (!Object<string, !ConnectionState>|undefined),
|
||||
* next: (!ConnectionState|undefined)
|
||||
@@ -99,6 +101,7 @@ const save = function(
|
||||
}
|
||||
saveAttributes(block, state);
|
||||
saveExtraState(block, state);
|
||||
saveIcons(block, state);
|
||||
saveFields(block, state);
|
||||
if (addInputBlocks) {
|
||||
saveInputBlocks(block, state);
|
||||
@@ -171,6 +174,25 @@ const saveExtraState = function(block, state) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the state of all of the icons on the block to the given state object.
|
||||
* @param {!Block} block The block to serialize the icon state of.
|
||||
* @param {!State} state The state object to append to.
|
||||
*/
|
||||
const saveIcons = function(block, state) {
|
||||
// TODO(#2105): Remove this logic and put it in the icon.
|
||||
if (block.getCommentText()) {
|
||||
state['icons'] = {
|
||||
'comment': {
|
||||
'text': block.getCommentText(),
|
||||
'pinned': block.commentModel.pinned,
|
||||
'height': Math.round(block.commentModel.size.height),
|
||||
'width': Math.round(block.commentModel.size.width),
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the state of all of the fields on the block to the given state object.
|
||||
* @param {!Block} block The block to serialize the field state of.
|
||||
@@ -178,7 +200,7 @@ const saveExtraState = function(block, state) {
|
||||
*/
|
||||
const saveFields = function(block, state) {
|
||||
let hasFieldState = false;
|
||||
let fields = Object.create(null);
|
||||
const fields = Object.create(null);
|
||||
for (let i = 0; i < block.inputList.length; i++) {
|
||||
const input = block.inputList[i];
|
||||
for (let j = 0; j < input.fieldRow.length; j++) {
|
||||
@@ -322,7 +344,7 @@ const loadInternal = function(state, workspace, parentConnection = undefined) {
|
||||
loadAttributes(block, state);
|
||||
loadExtraState(block, state);
|
||||
tryToConnectParent(parentConnection, block, state);
|
||||
// loadIcons(block, state);
|
||||
loadIcons(block, state);
|
||||
loadFields(block, state);
|
||||
loadInputBlocks(block, state);
|
||||
loadNextBlocks(block, state);
|
||||
@@ -427,6 +449,29 @@ const tryToConnectParent = function(parentConnection, child, state) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies icon state to the icons on the block, based on the given state
|
||||
* object.
|
||||
* @param {!Block} block The block to set the icon state of.
|
||||
* @param {!State} state The state object to reference.
|
||||
*/
|
||||
const loadIcons = function(block, state) {
|
||||
if (!state['icons']) {
|
||||
return;
|
||||
}
|
||||
// TODO(#2105): Remove this logic and put it in the icon.
|
||||
const comment = state['icons']['comment'];
|
||||
if (comment) {
|
||||
block.setCommentText(comment['text']);
|
||||
block.commentModel.pinned = comment['pinned'];
|
||||
block.commentModel.size = new Size(comment['width'], comment['height']);
|
||||
if (comment['pinned'] && block.getCommentIcon && !block.isInFlyout) {
|
||||
// Give the block a chance to be positioned and rendered before showing.
|
||||
setTimeout(() => block.getCommentIcon().setVisible(true), 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies any field information available on the state object to the block.
|
||||
* @param {!Block} block The block to set the field state of.
|
||||
|
||||
@@ -196,7 +196,7 @@ goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Ren
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.workspaces', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.inputTypes', 'Blockly.serialization.exceptions'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.inputTypes', 'Blockly.serialization.exceptions', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/exceptions.js', ['Blockly.serialization.exceptions'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/variables.js', ['Blockly.serialization.variables'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/workspaces.js', ['Blockly.serialization.workspaces'], ['Blockly.Events', 'Blockly.Workspace', 'Blockly.serialization.blocks', 'Blockly.serialization.variables', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
|
||||
@@ -274,6 +274,67 @@ suite('JSO Serialization', function() {
|
||||
});
|
||||
});
|
||||
|
||||
suite('Icons', function() {
|
||||
suite('Comment', function() {
|
||||
test('Basic', function() {
|
||||
const block = this.workspace.newBlock('row_block');
|
||||
block.setCommentText('test');
|
||||
const jso = Blockly.serialization.blocks.save(block);
|
||||
assertProperty(
|
||||
jso,
|
||||
'icons',
|
||||
{
|
||||
'comment': {
|
||||
'text': 'test',
|
||||
'pinned': false,
|
||||
'height': 80,
|
||||
'width': 160,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('Pinned', function() {
|
||||
const block = this.workspace.newBlock('row_block');
|
||||
block.setCommentText('test');
|
||||
block.commentModel.pinned = true;
|
||||
const jso = Blockly.serialization.blocks.save(block);
|
||||
assertProperty(
|
||||
jso,
|
||||
'icons',
|
||||
{
|
||||
'comment': {
|
||||
'text': 'test',
|
||||
'pinned': true,
|
||||
'height': 80,
|
||||
'width': 160,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('Size', function() {
|
||||
const block = this.workspace.newBlock('row_block');
|
||||
block.setCommentText('test');
|
||||
block.commentModel.size.height = 40;
|
||||
block.commentModel.size.width = 320;
|
||||
const jso = Blockly.serialization.blocks.save(block);
|
||||
assertProperty(
|
||||
jso,
|
||||
'icons',
|
||||
{
|
||||
'comment': {
|
||||
'text': 'test',
|
||||
'pinned': false,
|
||||
'height': 40,
|
||||
'width': 320,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Fields', function() {
|
||||
class StringStateField extends Blockly.Field {
|
||||
constructor(value, validator = undefined, config = undefined) {
|
||||
|
||||
@@ -1834,5 +1834,4 @@ var runSerializerTestSuite = (serializer, deserializer, testSuite) => {
|
||||
};
|
||||
|
||||
runSerializerTestSuite(null, null, Serializer);
|
||||
Serializer.Icons.skip = true;
|
||||
runSerializerTestSuite(state => state, state => state, Serializer);
|
||||
|
||||
Reference in New Issue
Block a user