diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index d27e91668c10580cc8a407b89e66902857b94e36..9bf3aafb8e35a68438c72316741b999d20e91065 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -6,6 +6,15 @@ const VM = require('scratch-vm'); const BlocksComponent = require('../components/blocks/blocks.jsx'); +const addFunctionListener = (object, property, callback) => { + const oldFn = object[property]; + object[property] = function () { + const result = oldFn.apply(this, arguments); + callback.apply(this, result); + return result; + }; +}; + class Blocks extends React.Component { constructor (props) { super(props); @@ -19,14 +28,24 @@ class Blocks extends React.Component { 'onBlockGlowOff', 'onVisualReport', 'onWorkspaceUpdate', + 'onWorkspaceMetricsChange', 'setBlocks' ]); + this.state = {workspaceMetrics: {}}; } componentDidMount () { const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options); this.workspace = this.ScratchBlocks.inject(this.blocks, workspaceConfig); + + // @todo change this when blockly supports UI events + addFunctionListener(this.workspace, 'translate', this.onWorkspaceMetricsChange); + addFunctionListener(this.workspace, 'zoom', this.onWorkspaceMetricsChange); + this.attachVM(); } + shouldComponentUpdate () { + return false; + } componentWillUnmount () { this.detachVM(); this.workspace.dispose(); @@ -52,6 +71,19 @@ class Blocks extends React.Component { this.props.vm.off('VISUAL_REPORT', this.onVisualReport); this.props.vm.off('workspaceUpdate', this.onWorkspaceUpdate); } + onWorkspaceMetricsChange () { + const target = this.props.vm.editingTarget; + if (target && target.id) { + const workspaceMetrics = Object.assign({}, this.state.workspaceMetrics, { + [target.id]: { + scrollX: this.workspace.scrollX, + scrollY: this.workspace.scrollY, + scale: this.workspace.scale + } + }); + this.setState({workspaceMetrics}); + } + } onScriptGlowOn (data) { this.workspace.glowStack(data.id, true); } @@ -68,12 +100,25 @@ class Blocks extends React.Component { this.workspace.reportValue(data.id, data.value); } onWorkspaceUpdate (data) { + if (this.props.vm.editingTarget && !this.state.workspaceMetrics[this.props.vm.editingTarget.id]) { + this.onWorkspaceMetricsChange(); + } + this.ScratchBlocks.Events.disable(); this.workspace.clear(); + const dom = this.ScratchBlocks.Xml.textToDom(data.xml); this.ScratchBlocks.Xml.domToWorkspace(dom, this.workspace); this.ScratchBlocks.Events.enable(); this.workspace.toolbox_.refreshSelection(); + + if (this.props.vm.editingTarget && this.state.workspaceMetrics[this.props.vm.editingTarget.id]) { + const {scrollX, scrollY, scale} = this.state.workspaceMetrics[this.props.vm.editingTarget.id]; + this.workspace.scrollX = scrollX; + this.workspace.scrollY = scrollY; + this.workspace.scale = scale; + this.workspace.resize(); + } } setBlocks (blocks) { this.blocks = blocks;