diff --git a/core/block_render_svg.js b/core/block_render_svg.js index 017bc3402..2a8ee7443 100644 --- a/core/block_render_svg.js +++ b/core/block_render_svg.js @@ -288,7 +288,7 @@ Blockly.BlockSvg.prototype.render = function(opt_bubble) { parentBlock.render(true); } else { // Top-most block. Fire an event to allow scrollbars to resize. - Blockly.asyncSvgResize(this.workspace); + Blockly.resizeSvgContents(this.workspace); } } Blockly.Field.stopCache(); diff --git a/core/block_svg.js b/core/block_svg.js index ef39321dc..c84220606 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -232,9 +232,9 @@ Blockly.BlockSvg.onMouseMoveWrapper_ = null; /** * Stop binding to the global mouseup and mousemove events. - * @private + * @package */ -Blockly.BlockSvg.terminateDrag_ = function() { +Blockly.BlockSvg.terminateDrag = function() { Blockly.BlockSvg.disconnectUiStop_(); if (Blockly.BlockSvg.onMouseUpWrapper_) { Blockly.unbindEvent_(Blockly.BlockSvg.onMouseUpWrapper_); @@ -273,7 +273,7 @@ Blockly.BlockSvg.terminateDrag_ = function() { Blockly.Events.setGroup(false); }, Blockly.BUMP_DELAY); // Fire an event to allow scrollbars to resize. - Blockly.asyncSvgResize(this.workspace); + Blockly.resizeSvgContents(selected.workspace); } } Blockly.dragMode_ = Blockly.DRAG_NONE; @@ -531,8 +531,6 @@ Blockly.BlockSvg.prototype.onMouseDown_ = function(e) { return; } this.workspace.markFocused(); - // Update Blockly's knowledge of its own location. - Blockly.svgResize(this.workspace); Blockly.terminateDrag_(); this.select(); Blockly.hideChaff(); @@ -611,11 +609,14 @@ Blockly.BlockSvg.prototype.onMouseUp_ = function(e) { if (trashcan) { goog.Timer.callOnce(trashcan.close, 100, trashcan); } + // Save the block's workspace temporarily so we can resize the + // contents once the block is disposed. + var selectedWorkspace = Blockly.selected.workspace; Blockly.selected.dispose(false, true); // Dropping a block on the trash can will usually cause the workspace to // resize to contain the newly positioned block. Force a second resize // now that the block has been deleted. - Blockly.asyncSvgResize(this.workspace); + Blockly.resizeSvgContents(selectedWorkspace); } if (Blockly.highlightedConnection_) { Blockly.highlightedConnection_.unhighlight(); diff --git a/core/blockly.js b/core/blockly.js index 3e9881e04..4fd5de0ca 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -141,36 +141,24 @@ Blockly.svgSize = function(svg) { }; /** - * Schedule a call to the resize handler. Groups of simultaneous events (e.g. - * a tree of blocks being deleted) are merged into one call. - * @param {Blockly.WorkspaceSvg} workspace Any workspace in the SVG. + * Size the workspace when the contents change. This also updates + * scrollbars accordingly. + * @param {!Blockly.WorkspaceSvg} workspace The workspace to resize. */ -Blockly.asyncSvgResize = function(workspace) { - if (Blockly.svgResizePending_) { - return; - } - if (!workspace) { - workspace = Blockly.getMainWorkspace(); - } - Blockly.svgResizePending_ = true; - setTimeout(function() {Blockly.svgResize(workspace);}, 0); +Blockly.resizeSvgContents = function(workspace) { + workspace.resizeContents(); }; -/** - * Flag indicating a resize event is scheduled. - * Used to fire only one resize after multiple changes. - * @type {boolean} - * @private - */ -Blockly.svgResizePending_ = false; /** - * Size the SVG image to completely fill its container. + * Size the SVG image to completely fill its container. Call this when the view + * actually changes sizes (e.g. on a window resize/device orientation change). + * See Blockly.resizeSvgContents to resize the workspace when the contents + * change (e.g. when a block is added or removed). * Record the height/width of the SVG image. * @param {!Blockly.WorkspaceSvg} workspace Any workspace in the SVG. */ Blockly.svgResize = function(workspace) { - Blockly.svgResizePending_ = false; var mainWorkspace = workspace; while (mainWorkspace.options.parentWorkspace) { mainWorkspace = mainWorkspace.options.parentWorkspace; @@ -316,7 +304,7 @@ Blockly.onKeyDown_ = function(e) { * @private */ Blockly.terminateDrag_ = function() { - Blockly.BlockSvg.terminateDrag_(); + Blockly.BlockSvg.terminateDrag(); Blockly.Flyout.terminateDrag_(); }; diff --git a/core/flyout.js b/core/flyout.js index 5dce8223f..3caa8deaa 100644 --- a/core/flyout.js +++ b/core/flyout.js @@ -591,8 +591,9 @@ Blockly.Flyout.prototype.show = function(xmlList) { this.offsetHorizontalRtlBlocks(this.workspace_.getTopBlocks(false)); this.filterForCapacity_(); - // Fire a resize event to update the flyout's scrollbar. - Blockly.svgResize(this.workspace_); + // Correctly position the flyout's scrollbar when it opens. + this.position(); + this.reflowWrapper_ = this.reflow.bind(this); this.workspace_.addChangeListener(this.reflowWrapper_); }; @@ -1039,7 +1040,7 @@ Blockly.Flyout.prototype.reflowHorizontal = function(blocks) { } // Record the height for .getMetrics_ and .position. this.height_ = flyoutHeight; - Blockly.asyncSvgResize(this.workspace_); + Blockly.resizeSvgContents(this.workspace_); } }; @@ -1092,7 +1093,7 @@ Blockly.Flyout.prototype.reflowVertical = function(blocks) { } // Record the width for .getMetrics_ and .position. this.width_ = flyoutWidth; - Blockly.asyncSvgResize(this.workspace_); + Blockly.resizeSvgContents(this.workspace_); } }; diff --git a/core/inject.js b/core/inject.js index 17bfccc0b..d8e6e3d20 100644 --- a/core/inject.js +++ b/core/inject.js @@ -56,6 +56,7 @@ Blockly.inject = function(container, opt_options) { Blockly.init_(workspace); workspace.markFocused(); Blockly.bindEvent_(svg, 'focus', workspace, workspace.markFocused); + Blockly.svgResize(workspace); return workspace; }; @@ -266,7 +267,7 @@ Blockly.init_ = function(mainWorkspace) { Blockly.bindEvent_(window, 'resize', null, function() { Blockly.hideChaff(true); - Blockly.asyncSvgResize(mainWorkspace); + Blockly.svgResize(mainWorkspace); }); Blockly.inject.bindDocumentEvents_(); @@ -322,7 +323,8 @@ Blockly.inject.bindDocumentEvents_ = function() { // Some iPad versions don't fire resize after portrait to landscape change. if (goog.userAgent.IPAD) { Blockly.bindEvent_(window, 'orientationchange', document, function() { - Blockly.asyncSvgResize(); + // TODO(#397): Fix for multiple blockly workspaces. + Blockly.svgResize(Blockly.getMainWorkspace()); }); } } diff --git a/core/toolbox.js b/core/toolbox.js index 2eb9cbb54..d9ca56dcc 100644 --- a/core/toolbox.js +++ b/core/toolbox.js @@ -348,7 +348,7 @@ Blockly.Toolbox.prototype.populate_ = function(newTree) { } // Fire a resize event since the toolbox may have changed width and height. - Blockly.asyncSvgResize(this.workspace_); + Blockly.resizeSvgContents(this.workspace_); }; /** @@ -533,7 +533,9 @@ Blockly.Toolbox.TreeNode = function(toolbox, html, opt_config, opt_domHelper) { goog.ui.tree.TreeNode.call(this, html, opt_config, opt_domHelper); if (toolbox) { var resize = function() { - Blockly.asyncSvgResize(toolbox.workspace_); + // Even though the div hasn't changed size, the visible workspace + // surface of the workspace has, so we may need to reposition everything. + Blockly.svgResize(toolbox.workspace_); }; // Fire a resize event since the toolbox may have changed width. goog.events.listen(toolbox.tree_, diff --git a/core/workspace_svg.js b/core/workspace_svg.js index a1788868e..2a88ec761 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -300,7 +300,26 @@ Blockly.WorkspaceSvg.prototype.addFlyout_ = function() { }; /** - * Resize this workspace and its containing objects. + * Resize the parts of the workspace that change when the workspace + * contents (e.g. block positions) change. This will also scroll the + * workspace contents if needed. + * @package + */ +Blockly.WorkspaceSvg.prototype.resizeContents = function() { + if (this.scrollbar) { + // TODO(picklesrus): Once rachel-fenichel's scrollbar refactoring + // is complete, call the method that only resizes scrollbar + // based on contents. + this.scrollbar.resize(); + } +}; + +/** + * Resize and reposition all of the workspace chrome (toolbox, + * trash, scrollbars etc.) + * This should be called when something changes that + * requires recalculating dimensions and positions of the + * trash, zoom, toolbox, etc. (e.g. window resize). */ Blockly.WorkspaceSvg.prototype.resize = function() { if (this.toolbox_) { @@ -576,7 +595,6 @@ Blockly.WorkspaceSvg.prototype.onMouseDown_ = function(e) { if (Blockly.isTargetInput_(e)) { return; } - Blockly.svgResize(this); Blockly.terminateDrag_(); // In case mouse-up event was lost. Blockly.hideChaff(); var isTargetWorkspace = e.target && e.target.nodeName && @@ -716,7 +734,7 @@ Blockly.WorkspaceSvg.prototype.cleanUp_ = function() { } Blockly.Events.setGroup(false); // Fire an event to allow scrollbars to resize. - Blockly.asyncSvgResize(this); + Blockly.resizeSvgContents(this); }; /** diff --git a/core/xml.js b/core/xml.js index 48cef7216..3f4652bf8 100644 --- a/core/xml.js +++ b/core/xml.js @@ -351,8 +351,9 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) { } }, 1); topBlock.updateDisabled(); - // Fire an event to allow scrollbars to resize. - Blockly.asyncSvgResize(workspace); + // Allow the scrollbars to resize and move based on the new contents. + // TODO(@picklesrus): #387. Remove when domToBlock avoids resizing. + Blockly.resizeSvgContents(workspace); } Blockly.Events.enable(); if (Blockly.Events.isEnabled()) { diff --git a/demos/code/code.js b/demos/code/code.js index e75b452d4..a55633754 100644 --- a/demos/code/code.js +++ b/demos/code/code.js @@ -294,7 +294,7 @@ Code.tabClick = function(clickedName) { if (clickedName == 'blocks') { Code.workspace.setVisible(true); } - Blockly.asyncSvgResize(this.workspace_); + Blockly.svgResize(Code.workspace); }; /** @@ -380,7 +380,6 @@ Code.init = function() { // Account for the 19 pixel margin and on each side. } }; - onresize(); window.addEventListener('resize', onresize, false); var toolbox = document.getElementById('toolbox'); @@ -432,6 +431,8 @@ Code.init = function() { Code.bindClick('tab_' + name, function(name_) {return function() {Code.tabClick(name_);};}(name)); } + onresize(); + Blockly.svgResize(Code.workspace); // Lazy-load the syntax-highlighting. window.setTimeout(Code.importPrettify, 1); diff --git a/demos/graph/index.html b/demos/graph/index.html index 7e9daf2dd..ce720ccde 100644 --- a/demos/graph/index.html +++ b/demos/graph/index.html @@ -328,6 +328,7 @@ Graph.plot = function(code) { Graph.resize = function() { var width = Math.max(window.innerWidth - 440, 250); document.getElementById('blocklyDiv').style.width = width + 'px'; + Blockly.svgResize(Graph.workspace); }; /** @@ -344,6 +345,7 @@ Graph.init = function() { // When Blockly changes, update the graph. Graph.workspace.addChangeListener(Graph.drawVisualization); + Graph.resize(); }; window.addEventListener('load', Graph.init);