12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391 |
- 'use strict';
- goog.provide('Blockly.Flyout');
- goog.require('Blockly.Block');
- goog.require('Blockly.Comment');
- goog.require('Blockly.Events');
- goog.require('Blockly.FlyoutButton');
- goog.require('Blockly.Touch');
- goog.require('Blockly.WorkspaceSvg');
- goog.require('goog.dom');
- goog.require('goog.events');
- goog.require('goog.math.Rect');
- goog.require('goog.userAgent');
- Blockly.Flyout = function(workspaceOptions) {
- workspaceOptions.getMetrics = this.getMetrics_.bind(this);
- workspaceOptions.setMetrics = this.setMetrics_.bind(this);
-
- this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions);
- this.workspace_.isFlyout = true;
-
- this.RTL = !!workspaceOptions.RTL;
-
- this.horizontalLayout_ = workspaceOptions.horizontalLayout;
-
- this.toolboxPosition_ = workspaceOptions.toolboxPosition;
-
- this.eventWrappers_ = [];
-
- this.backgroundButtons_ = [];
-
- this.buttons_ = [];
-
- this.listeners_ = [];
-
- this.permanentlyDisabled_ = [];
-
- this.startDragMouseY_ = 0;
-
- this.startDragMouseX_ = 0;
- };
- Blockly.Flyout.startFlyout_ = null;
- Blockly.Flyout.startDownEvent_ = null;
- Blockly.Flyout.startBlock_ = null;
- Blockly.Flyout.onMouseUpWrapper_ = null;
- Blockly.Flyout.onMouseMoveWrapper_ = null;
- Blockly.Flyout.onMouseMoveBlockWrapper_ = null;
- Blockly.Flyout.prototype.autoClose = true;
- Blockly.Flyout.prototype.CORNER_RADIUS = 8;
- Blockly.Flyout.prototype.DRAG_RADIUS = 10;
- Blockly.Flyout.prototype.MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS;
- Blockly.Flyout.prototype.GAP_X = Blockly.Flyout.prototype.MARGIN * 3;
- Blockly.Flyout.prototype.GAP_Y = Blockly.Flyout.prototype.MARGIN * 3;
- Blockly.Flyout.prototype.SCROLLBAR_PADDING = 2;
- Blockly.Flyout.prototype.width_ = 0;
- Blockly.Flyout.prototype.height_ = 0;
- Blockly.Flyout.prototype.dragMode_ = Blockly.DRAG_NONE;
- Blockly.Flyout.prototype.dragAngleRange_ = 70;
- Blockly.Flyout.prototype.createDom = function() {
-
- this.svgGroup_ = Blockly.createSvgElement('g',
- {'class': 'blocklyFlyout'}, null);
- this.svgBackground_ = Blockly.createSvgElement('path',
- {'class': 'blocklyFlyoutBackground'}, this.svgGroup_);
- this.svgGroup_.appendChild(this.workspace_.createDom());
- return this.svgGroup_;
- };
- Blockly.Flyout.prototype.init = function(targetWorkspace) {
- this.targetWorkspace_ = targetWorkspace;
- this.workspace_.targetWorkspace = targetWorkspace;
-
- this.scrollbar_ = new Blockly.Scrollbar(this.workspace_,
- this.horizontalLayout_, false);
- this.hide();
- Array.prototype.push.apply(this.eventWrappers_,
- Blockly.bindEventWithChecks_(this.svgGroup_, 'wheel', this, this.wheel_));
- if (!this.autoClose) {
- this.filterWrapper_ = this.filterForCapacity_.bind(this);
- this.targetWorkspace_.addChangeListener(this.filterWrapper_);
- }
-
- Array.prototype.push.apply(this.eventWrappers_,
- Blockly.bindEventWithChecks_(this.svgGroup_, 'mousedown', this,
- this.onMouseDown_));
- };
- Blockly.Flyout.prototype.dispose = function() {
- this.hide();
- Blockly.unbindEvent_(this.eventWrappers_);
- if (this.filterWrapper_) {
- this.targetWorkspace_.removeChangeListener(this.filterWrapper_);
- this.filterWrapper_ = null;
- }
- if (this.scrollbar_) {
- this.scrollbar_.dispose();
- this.scrollbar_ = null;
- }
- if (this.workspace_) {
- this.workspace_.targetWorkspace = null;
- this.workspace_.dispose();
- this.workspace_ = null;
- }
- if (this.svgGroup_) {
- goog.dom.removeNode(this.svgGroup_);
- this.svgGroup_ = null;
- }
- this.svgBackground_ = null;
- this.targetWorkspace_ = null;
- };
- Blockly.Flyout.prototype.getWidth = function() {
- return this.width_;
- };
- Blockly.Flyout.prototype.getHeight = function() {
- return this.height_;
- };
- Blockly.Flyout.prototype.getMetrics_ = function() {
- if (!this.isVisible()) {
-
- return null;
- }
- try {
- var optionBox = this.workspace_.getCanvas().getBBox();
- } catch (e) {
-
- var optionBox = {height: 0, y: 0, width: 0, x: 0};
- }
- var absoluteTop = this.SCROLLBAR_PADDING;
- var absoluteLeft = this.SCROLLBAR_PADDING;
- if (this.horizontalLayout_) {
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
- absoluteTop = 0;
- }
- var viewHeight = this.height_;
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) {
- viewHeight -= this.SCROLLBAR_PADDING;
- }
- var viewWidth = this.width_ - 2 * this.SCROLLBAR_PADDING;
- } else {
- absoluteLeft = 0;
- var viewHeight = this.height_ - 2 * this.SCROLLBAR_PADDING;
- var viewWidth = this.width_;
- if (!this.RTL) {
- viewWidth -= this.SCROLLBAR_PADDING;
- }
- }
- var metrics = {
- viewHeight: viewHeight,
- viewWidth: viewWidth,
- contentHeight: (optionBox.height + 2 * this.MARGIN) * this.workspace_.scale,
- contentWidth: (optionBox.width + 2 * this.MARGIN) * this.workspace_.scale,
- viewTop: -this.workspace_.scrollY,
- viewLeft: -this.workspace_.scrollX,
- contentTop: optionBox.y,
- contentLeft: optionBox.x,
- absoluteTop: absoluteTop,
- absoluteLeft: absoluteLeft
- };
- return metrics;
- };
- Blockly.Flyout.prototype.setMetrics_ = function(xyRatio) {
- var metrics = this.getMetrics_();
-
- if (!metrics) {
- return;
- }
- if (!this.horizontalLayout_ && goog.isNumber(xyRatio.y)) {
- this.workspace_.scrollY = -metrics.contentHeight * xyRatio.y;
- } else if (this.horizontalLayout_ && goog.isNumber(xyRatio.x)) {
- this.workspace_.scrollX = -metrics.contentWidth * xyRatio.x;
- }
- this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
- this.workspace_.scrollY + metrics.absoluteTop);
- };
- Blockly.Flyout.prototype.position = function() {
- if (!this.isVisible()) {
- return;
- }
- var targetWorkspaceMetrics = this.targetWorkspace_.getMetrics();
- if (!targetWorkspaceMetrics) {
-
- return;
- }
- var edgeWidth = this.horizontalLayout_ ?
- targetWorkspaceMetrics.viewWidth - 2 * this.CORNER_RADIUS :
- this.width_ - this.CORNER_RADIUS;
- var edgeHeight = this.horizontalLayout_ ?
- this.height_ - this.CORNER_RADIUS :
- targetWorkspaceMetrics.viewHeight - 2 * this.CORNER_RADIUS;
- this.setBackgroundPath_(edgeWidth, edgeHeight);
- var x = targetWorkspaceMetrics.absoluteLeft;
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) {
- x += targetWorkspaceMetrics.viewWidth;
- x -= this.width_;
- }
- var y = targetWorkspaceMetrics.absoluteTop;
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
- y += targetWorkspaceMetrics.viewHeight;
- y -= this.height_;
- }
- this.svgGroup_.setAttribute('transform', 'translate(' + x + ',' + y + ')');
-
-
- if (this.horizontalLayout_) {
- this.width_ = targetWorkspaceMetrics.viewWidth;
- } else {
- this.height_ = targetWorkspaceMetrics.viewHeight;
- }
-
- if (this.scrollbar_) {
- this.scrollbar_.resize();
- }
- };
- Blockly.Flyout.prototype.setBackgroundPath_ = function(width, height) {
- if (this.horizontalLayout_) {
- this.setBackgroundPathHorizontal_(width, height);
- } else {
- this.setBackgroundPathVertical_(width, height);
- }
- };
- Blockly.Flyout.prototype.setBackgroundPathVertical_ = function(width, height) {
- var atRight = this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT;
- var totalWidth = width + this.CORNER_RADIUS;
-
- var path = ['M ' + (atRight ? totalWidth : 0) + ',0'];
-
- path.push('h', atRight ? -width : width);
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
- atRight ? 0 : 1,
- atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS,
- this.CORNER_RADIUS);
-
- path.push('v', Math.max(0, height));
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,
- atRight ? 0 : 1,
- atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS,
- this.CORNER_RADIUS);
-
- path.push('h', atRight ? width : -width);
- path.push('z');
- this.svgBackground_.setAttribute('d', path.join(' '));
- };
- Blockly.Flyout.prototype.setBackgroundPathHorizontal_ = function(width,
- height) {
- var atTop = this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP;
-
- var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];
- if (atTop) {
-
- path.push('h', width + 2 * this.CORNER_RADIUS);
-
- path.push('v', height);
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
- -this.CORNER_RADIUS, this.CORNER_RADIUS);
- path.push('h', -1 * width);
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
- -this.CORNER_RADIUS, -this.CORNER_RADIUS);
- path.push('z');
- } else {
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
- this.CORNER_RADIUS, -this.CORNER_RADIUS);
- path.push('h', width);
-
- path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
- this.CORNER_RADIUS, this.CORNER_RADIUS);
- path.push('v', height);
-
- path.push('h', -width - 2 * this.CORNER_RADIUS);
-
- path.push('z');
- }
- this.svgBackground_.setAttribute('d', path.join(' '));
- };
- Blockly.Flyout.prototype.scrollToStart = function() {
- this.scrollbar_.set((this.horizontalLayout_ && this.RTL) ? Infinity : 0);
- };
- Blockly.Flyout.prototype.wheel_ = function(e) {
- var delta = this.horizontalLayout_ ? e.deltaX : e.deltaY;
- if (delta) {
- if (goog.userAgent.GECKO) {
-
- delta *= 10;
- }
- var metrics = this.getMetrics_();
- var pos = this.horizontalLayout_ ? metrics.viewLeft + delta :
- metrics.viewTop + delta;
- var limit = this.horizontalLayout_ ?
- metrics.contentWidth - metrics.viewWidth :
- metrics.contentHeight - metrics.viewHeight;
- pos = Math.min(pos, limit);
- pos = Math.max(pos, 0);
- this.scrollbar_.set(pos);
- }
-
- e.preventDefault();
-
- e.stopPropagation();
- };
- Blockly.Flyout.prototype.isVisible = function() {
- return this.svgGroup_ && this.svgGroup_.style.display == 'block';
- };
- Blockly.Flyout.prototype.hide = function() {
- if (!this.isVisible()) {
- return;
- }
- this.svgGroup_.style.display = 'none';
-
- for (var x = 0, listen; listen = this.listeners_[x]; x++) {
- Blockly.unbindEvent_(listen);
- }
- this.listeners_.length = 0;
- if (this.reflowWrapper_) {
- this.workspace_.removeChangeListener(this.reflowWrapper_);
- this.reflowWrapper_ = null;
- }
-
-
- };
- Blockly.Flyout.prototype.show = function(xmlList) {
- this.hide();
- this.clearOldBlocks_();
- if (xmlList == Blockly.Variables.NAME_TYPE) {
-
- xmlList =
- Blockly.Variables.flyoutCategory(this.workspace_.targetWorkspace);
- } else if (xmlList == Blockly.Procedures.NAME_TYPE) {
-
- xmlList =
- Blockly.Procedures.flyoutCategory(this.workspace_.targetWorkspace);
- }
- this.svgGroup_.style.display = 'block';
-
- var contents = [];
- var gaps = [];
- this.permanentlyDisabled_.length = 0;
- for (var i = 0, xml; xml = xmlList[i]; i++) {
- if (xml.tagName) {
- var tagName = xml.tagName.toUpperCase();
- var default_gap = this.horizontalLayout_ ? this.GAP_X : this.GAP_Y;
- if (tagName == 'BLOCK') {
- var curBlock = Blockly.Xml.domToBlock(xml, this.workspace_);
- if (curBlock.disabled) {
-
-
- this.permanentlyDisabled_.push(curBlock);
- }
- contents.push({type: 'block', block: curBlock});
- var gap = parseInt(xml.getAttribute('gap'), 10);
- gaps.push(isNaN(gap) ? default_gap : gap);
- } else if (xml.tagName.toUpperCase() == 'SEP') {
-
-
-
-
-
-
- var newGap = parseInt(xml.getAttribute('gap'), 10);
-
- if (!isNaN(newGap) && gaps.length > 0) {
- gaps[gaps.length - 1] = newGap;
- } else {
- gaps.push(default_gap);
- }
- } else if (tagName == 'BUTTON' || tagName == 'LABEL') {
-
- var isLabel = tagName == 'LABEL';
- var text = xml.getAttribute('text');
- var callbackKey = xml.getAttribute('callbackKey');
- var curButton = new Blockly.FlyoutButton(this.workspace_,
- this.targetWorkspace_, text, callbackKey, isLabel);
- contents.push({type: 'button', button: curButton});
- gaps.push(default_gap);
- }
- }
- }
- this.layout_(contents, gaps);
-
-
- var deselectAll = function() {
- var topBlocks = this.workspace_.getTopBlocks(false);
- for (var i = 0, block; block = topBlocks[i]; i++) {
- block.removeSelect();
- }
- };
- this.listeners_.push(Blockly.bindEventWithChecks_(this.svgBackground_,
- 'mouseover', this, deselectAll));
- if (this.horizontalLayout_) {
- this.height_ = 0;
- } else {
- this.width_ = 0;
- }
- this.reflow();
- this.filterForCapacity_();
-
- this.position();
- this.reflowWrapper_ = this.reflow.bind(this);
- this.workspace_.addChangeListener(this.reflowWrapper_);
- };
- Blockly.Flyout.prototype.layout_ = function(contents, gaps) {
- this.workspace_.scale = this.targetWorkspace_.scale;
- var margin = this.MARGIN;
- var cursorX = this.RTL ? margin : margin + Blockly.BlockSvg.TAB_WIDTH;
- var cursorY = margin;
- if (this.horizontalLayout_ && this.RTL) {
- contents = contents.reverse();
- }
- for (var i = 0, item; item = contents[i]; i++) {
- if (item.type == 'block') {
- var block = item.block;
- var allBlocks = block.getDescendants();
- for (var j = 0, child; child = allBlocks[j]; j++) {
-
-
-
- child.isInFlyout = true;
- }
- block.render();
- var root = block.getSvgRoot();
- var blockHW = block.getHeightWidth();
- var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0;
- if (this.horizontalLayout_) {
- cursorX += tab;
- }
- block.moveBy((this.horizontalLayout_ && this.RTL) ?
- cursorX + blockHW.width - tab : cursorX,
- cursorY);
- if (this.horizontalLayout_) {
- cursorX += (blockHW.width + gaps[i] - tab);
- } else {
- cursorY += blockHW.height + gaps[i];
- }
-
-
- var rect = Blockly.createSvgElement('rect', {'fill-opacity': 0}, null);
- rect.tooltip = block;
- Blockly.Tooltip.bindMouseEvents(rect);
-
- this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot());
- block.flyoutRect_ = rect;
- this.backgroundButtons_[i] = rect;
- this.addBlockListeners_(root, block, rect);
- } else if (item.type == 'button') {
- var button = item.button;
- var buttonSvg = button.createDom();
- button.moveTo(cursorX, cursorY);
- button.show();
- Blockly.bindEventWithChecks_(buttonSvg, 'mouseup', button,
- button.onMouseUp);
- this.buttons_.push(button);
- if (this.horizontalLayout_) {
- cursorX += (button.width + gaps[i]);
- } else {
- cursorY += button.height + gaps[i];
- }
- }
- }
- };
- Blockly.Flyout.prototype.clearOldBlocks_ = function() {
-
- var oldBlocks = this.workspace_.getTopBlocks(false);
- for (var i = 0, block; block = oldBlocks[i]; i++) {
- if (block.workspace == this.workspace_) {
- block.dispose(false, false);
- }
- }
-
- for (var j = 0, rect; rect = this.backgroundButtons_[j]; j++) {
- goog.dom.removeNode(rect);
- }
- this.backgroundButtons_.length = 0;
- for (var i = 0, button; button = this.buttons_[i]; i++) {
- button.dispose();
- }
- this.buttons_.length = 0;
- };
- Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) {
- this.listeners_.push(Blockly.bindEventWithChecks_(root, 'mousedown', null,
- this.blockMouseDown_(block)));
- this.listeners_.push(Blockly.bindEventWithChecks_(rect, 'mousedown', null,
- this.blockMouseDown_(block)));
- this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block,
- block.addSelect));
- this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block,
- block.removeSelect));
- this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block,
- block.addSelect));
- this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block,
- block.removeSelect));
- };
- Blockly.Flyout.blockRightClick_ = function(e, block) {
- Blockly.terminateDrag_();
- Blockly.hideChaff(true);
- block.showContextMenu_(e);
-
- Blockly.Touch.clearTouchIdentifier();
- };
- Blockly.Flyout.prototype.blockMouseDown_ = function(block) {
- var flyout = this;
- return function(e) {
- if (Blockly.isRightButton(e)) {
- Blockly.Flyout.blockRightClick_(e, block);
- } else {
- Blockly.terminateDrag_();
- Blockly.hideChaff(true);
-
- Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED);
-
- flyout.startDragMouseY_ = e.clientY;
- flyout.startDragMouseX_ = e.clientX;
- Blockly.Flyout.startDownEvent_ = e;
- Blockly.Flyout.startBlock_ = block;
- Blockly.Flyout.startFlyout_ = flyout;
- Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEventWithChecks_(document,
- 'mouseup', flyout, flyout.onMouseUp_);
- Blockly.Flyout.onMouseMoveBlockWrapper_ = Blockly.bindEventWithChecks_(
- document, 'mousemove', flyout, flyout.onMouseMoveBlock_);
- }
-
- e.stopPropagation();
- e.preventDefault();
- };
- };
- Blockly.Flyout.prototype.onMouseDown_ = function(e) {
- if (Blockly.isRightButton(e)) {
-
- Blockly.Touch.clearTouchIdentifier();
- return;
- }
- Blockly.hideChaff(true);
- this.dragMode_ = Blockly.DRAG_FREE;
- this.startDragMouseY_ = e.clientY;
- this.startDragMouseX_ = e.clientX;
- Blockly.Flyout.startFlyout_ = this;
- Blockly.Flyout.onMouseMoveWrapper_ = Blockly.bindEventWithChecks_(document,
- 'mousemove', this, this.onMouseMove_);
- Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEventWithChecks_(document,
- 'mouseup', this, Blockly.Flyout.terminateDrag_);
-
- e.preventDefault();
- e.stopPropagation();
- };
- Blockly.Flyout.prototype.onMouseUp_ = function(e) {
- if (!this.workspace_.isDragging()) {
-
- Blockly.Touch.clearTouchIdentifier();
- if (this.autoClose) {
- this.createBlockFunc_(Blockly.Flyout.startBlock_)(
- Blockly.Flyout.startDownEvent_);
- } else if (!Blockly.WidgetDiv.isVisible()) {
- Blockly.Events.fire(
- new Blockly.Events.Ui(Blockly.Flyout.startBlock_, 'click',
- undefined, undefined));
- }
- }
- Blockly.terminateDrag_();
- };
- Blockly.Flyout.prototype.onMouseMove_ = function(e) {
- var metrics = this.getMetrics_();
- if (this.horizontalLayout_) {
- if (metrics.contentWidth - metrics.viewWidth < 0) {
- return;
- }
- var dx = e.clientX - this.startDragMouseX_;
- this.startDragMouseX_ = e.clientX;
- var x = metrics.viewLeft - dx;
- x = goog.math.clamp(x, 0, metrics.contentWidth - metrics.viewWidth);
- this.scrollbar_.set(x);
- } else {
- if (metrics.contentHeight - metrics.viewHeight < 0) {
- return;
- }
- var dy = e.clientY - this.startDragMouseY_;
- this.startDragMouseY_ = e.clientY;
- var y = metrics.viewTop - dy;
- y = goog.math.clamp(y, 0, metrics.contentHeight - metrics.viewHeight);
- this.scrollbar_.set(y);
- }
- };
- Blockly.Flyout.prototype.onMouseMoveBlock_ = function(e) {
- if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&
- e.button == 0) {
-
- e.stopPropagation();
- return;
- }
- var dx = e.clientX - Blockly.Flyout.startDownEvent_.clientX;
- var dy = e.clientY - Blockly.Flyout.startDownEvent_.clientY;
- var createBlock = this.determineDragIntention_(dx, dy);
- if (createBlock) {
- Blockly.longStop_();
- this.createBlockFunc_(Blockly.Flyout.startBlock_)(
- Blockly.Flyout.startDownEvent_);
- } else if (this.dragMode_ == Blockly.DRAG_FREE) {
- Blockly.longStop_();
-
- this.onMouseMove_(e);
- }
- e.stopPropagation();
- };
- Blockly.Flyout.prototype.determineDragIntention_ = function(dx, dy) {
- if (this.dragMode_ == Blockly.DRAG_FREE) {
-
- return false;
- }
- var dragDistance = Math.sqrt(dx * dx + dy * dy);
- if (dragDistance < this.DRAG_RADIUS) {
-
- this.dragMode_ = Blockly.DRAG_STICKY;
- return false;
- } else {
- if (this.isDragTowardWorkspace_(dx, dy) || !this.scrollbar_.isVisible()) {
-
- return true;
- } else {
-
- this.dragMode_ = Blockly.DRAG_FREE;
- return false;
- }
- }
- };
- Blockly.Flyout.prototype.isDragTowardWorkspace_ = function(dx, dy) {
-
- var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
- var range = this.dragAngleRange_;
- if (this.horizontalLayout_) {
-
- if ((dragDirection < 90 + range && dragDirection > 90 - range) ||
- (dragDirection > -90 - range && dragDirection < -90 + range)) {
- return true;
- }
- } else {
-
- if ((dragDirection < range && dragDirection > -range) ||
- (dragDirection < -180 + range || dragDirection > 180 - range)) {
- return true;
- }
- }
- return false;
- };
- Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) {
- var flyout = this;
- return function(e) {
- if (Blockly.isRightButton(e)) {
-
- return;
- }
- if (originBlock.disabled) {
-
- return;
- }
- Blockly.Events.disable();
- try {
- var block = flyout.placeNewBlock_(originBlock);
- } finally {
- Blockly.Events.enable();
- }
- if (Blockly.Events.isEnabled()) {
- Blockly.Events.setGroup(true);
- Blockly.Events.fire(new Blockly.Events.Create(block));
- }
- if (flyout.autoClose) {
- flyout.hide();
- } else {
- flyout.filterForCapacity_();
- }
-
- block.onMouseDown_(e);
- Blockly.dragMode_ = Blockly.DRAG_FREE;
- block.setDragging_(true);
-
- flyout.targetWorkspace_.setResizesEnabled(false);
- };
- };
- Blockly.Flyout.prototype.placeNewBlock_ = function(originBlock) {
- var targetWorkspace = this.targetWorkspace_;
- var svgRootOld = originBlock.getSvgRoot();
- if (!svgRootOld) {
- throw 'originBlock is not rendered.';
- }
-
-
- var xyOld = Blockly.getSvgXY_(svgRootOld, targetWorkspace);
-
-
-
-
- var scrollX = this.workspace_.scrollX;
- var scale = this.workspace_.scale;
- xyOld.x += scrollX / scale - scrollX;
-
-
-
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) {
- scrollX = targetWorkspace.getMetrics().viewWidth - this.width_;
- scale = targetWorkspace.scale;
-
- xyOld.x += scrollX / scale - scrollX;
- }
-
-
-
-
- var scrollY = this.workspace_.scrollY;
- scale = this.workspace_.scale;
- xyOld.y += scrollY / scale - scrollY;
-
-
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
- scrollY = targetWorkspace.getMetrics().viewHeight - this.height_;
- scale = targetWorkspace.scale;
- xyOld.y += scrollY / scale - scrollY;
- }
-
- var xml = Blockly.Xml.blockToDom(originBlock);
- var block = Blockly.Xml.domToBlock(xml, targetWorkspace);
- var svgRootNew = block.getSvgRoot();
- if (!svgRootNew) {
- throw 'block is not rendered.';
- }
-
-
-
-
- var xyNew = Blockly.getSvgXY_(svgRootNew, targetWorkspace);
-
- xyNew.x +=
- targetWorkspace.scrollX / targetWorkspace.scale - targetWorkspace.scrollX;
- xyNew.y +=
- targetWorkspace.scrollY / targetWorkspace.scale - targetWorkspace.scrollY;
-
- if (targetWorkspace.toolbox_ && !targetWorkspace.scrollbar) {
- xyNew.x += targetWorkspace.toolbox_.getWidth() / targetWorkspace.scale;
- xyNew.y += targetWorkspace.toolbox_.getHeight() / targetWorkspace.scale;
- }
-
- block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);
- return block;
- };
- Blockly.Flyout.prototype.filterForCapacity_ = function() {
- var remainingCapacity = this.targetWorkspace_.remainingCapacity();
- 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();
- block.setDisabled(allBlocks.length > remainingCapacity);
- }
- }
- };
- Blockly.Flyout.prototype.getClientRect = function() {
- if (!this.svgGroup_) {
- return null;
- }
- var flyoutRect = this.svgGroup_.getBoundingClientRect();
-
-
-
- var BIG_NUM = 1000000000;
- var x = flyoutRect.left;
- var y = flyoutRect.top;
- var width = flyoutRect.width;
- var height = flyoutRect.height;
- if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) {
- return new goog.math.Rect(-BIG_NUM, y - BIG_NUM, BIG_NUM * 2,
- BIG_NUM + height);
- } else if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
- return new goog.math.Rect(-BIG_NUM, y, BIG_NUM * 2,
- BIG_NUM + height);
- } else if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_LEFT) {
- return new goog.math.Rect(x - BIG_NUM, -BIG_NUM, BIG_NUM + width,
- BIG_NUM * 2);
- } else {
- return new goog.math.Rect(x, -BIG_NUM, BIG_NUM + width, BIG_NUM * 2);
- }
- };
- Blockly.Flyout.terminateDrag_ = function() {
- if (Blockly.Flyout.startFlyout_) {
-
- if (Blockly.Flyout.startFlyout_.dragMode_ == Blockly.DRAG_FREE) {
- Blockly.Touch.clearTouchIdentifier();
- }
- Blockly.Flyout.startFlyout_.dragMode_ = Blockly.DRAG_NONE;
- Blockly.Flyout.startFlyout_ = null;
- }
- if (Blockly.Flyout.onMouseUpWrapper_) {
- Blockly.unbindEvent_(Blockly.Flyout.onMouseUpWrapper_);
- Blockly.Flyout.onMouseUpWrapper_ = null;
- }
- if (Blockly.Flyout.onMouseMoveBlockWrapper_) {
- Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveBlockWrapper_);
- Blockly.Flyout.onMouseMoveBlockWrapper_ = null;
- }
- if (Blockly.Flyout.onMouseMoveWrapper_) {
- Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveWrapper_);
- Blockly.Flyout.onMouseMoveWrapper_ = null;
- }
- Blockly.Flyout.startDownEvent_ = null;
- Blockly.Flyout.startBlock_ = null;
- };
- Blockly.Flyout.prototype.reflowHorizontal = function(blocks) {
- this.workspace_.scale = this.targetWorkspace_.scale;
- var flyoutHeight = 0;
- for (var i = 0, block; block = blocks[i]; i++) {
- flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
- }
- flyoutHeight += this.MARGIN * 1.5;
- flyoutHeight *= this.workspace_.scale;
- flyoutHeight += Blockly.Scrollbar.scrollbarThickness;
- if (this.height_ != flyoutHeight) {
- for (var i = 0, block; block = blocks[i]; i++) {
- var blockHW = block.getHeightWidth();
- if (block.flyoutRect_) {
- block.flyoutRect_.setAttribute('width', blockHW.width);
- block.flyoutRect_.setAttribute('height', blockHW.height);
-
- var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0;
- var blockXY = block.getRelativeToSurfaceXY();
- block.flyoutRect_.setAttribute('y', blockXY.y);
- block.flyoutRect_.setAttribute('x',
- this.RTL ? blockXY.x - blockHW.width + tab : blockXY.x - tab);
-
-
- var hatOffset =
- block.startHat_ ? Blockly.BlockSvg.START_HAT_HEIGHT : 0;
- if (hatOffset) {
- block.moveBy(0, hatOffset);
- }
- block.flyoutRect_.setAttribute('y', blockXY.y);
- }
- }
-
- this.height_ = flyoutHeight;
-
-
- this.targetWorkspace_.resize();
- }
- };
- Blockly.Flyout.prototype.reflowVertical = function(blocks) {
- this.workspace_.scale = this.targetWorkspace_.scale;
- var flyoutWidth = 0;
- for (var i = 0, block; block = blocks[i]; i++) {
- var width = block.getHeightWidth().width;
- if (block.outputConnection) {
- width -= Blockly.BlockSvg.TAB_WIDTH;
- }
- flyoutWidth = Math.max(flyoutWidth, width);
- }
- for (var i = 0, button; button = this.buttons_[i]; i++) {
- flyoutWidth = Math.max(flyoutWidth, button.width);
- }
- flyoutWidth += this.MARGIN * 1.5 + Blockly.BlockSvg.TAB_WIDTH;
- flyoutWidth *= this.workspace_.scale;
- flyoutWidth += Blockly.Scrollbar.scrollbarThickness;
- if (this.width_ != flyoutWidth) {
- for (var i = 0, block; block = blocks[i]; i++) {
- var blockHW = block.getHeightWidth();
- if (this.RTL) {
-
- var oldX = block.getRelativeToSurfaceXY().x;
- var newX = flyoutWidth / this.workspace_.scale - this.MARGIN;
- newX -= Blockly.BlockSvg.TAB_WIDTH;
- block.moveBy(newX - oldX, 0);
- }
- if (block.flyoutRect_) {
- block.flyoutRect_.setAttribute('width', blockHW.width);
- block.flyoutRect_.setAttribute('height', blockHW.height);
-
- var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0;
- var blockXY = block.getRelativeToSurfaceXY();
- block.flyoutRect_.setAttribute('x',
- this.RTL ? blockXY.x - blockHW.width + tab : blockXY.x - tab);
-
-
- var hatOffset =
- block.startHat_ ? Blockly.BlockSvg.START_HAT_HEIGHT : 0;
- if (hatOffset) {
- block.moveBy(0, hatOffset);
- }
- block.flyoutRect_.setAttribute('y', blockXY.y);
- }
- }
-
- this.width_ = flyoutWidth;
-
-
- this.targetWorkspace_.resize();
- }
- };
- Blockly.Flyout.prototype.reflow = function() {
- if (this.reflowWrapper_) {
- this.workspace_.removeChangeListener(this.reflowWrapper_);
- }
- var blocks = this.workspace_.getTopBlocks(false);
- if (this.horizontalLayout_) {
- this.reflowHorizontal(blocks);
- } else {
- this.reflowVertical(blocks);
- }
- if (this.reflowWrapper_) {
- this.workspace_.addChangeListener(this.reflowWrapper_);
- }
- };
|