Skip to content
This repository was archived by the owner on Jul 24, 2019. It is now read-only.

Commit af9348a

Browse files
author
Aaron Imming
committed
Custom class names, logic for collapsing/expanding
1 parent 26d8441 commit af9348a

File tree

1 file changed

+171
-15
lines changed

1 file changed

+171
-15
lines changed

src/scratch/hooks/toolbox.js

Lines changed: 171 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,86 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { ArrowIcon } from '../../components/Icons.jsx';
4+
import { translate } from '../../utils/lang/i18n';
5+
16
/* eslint-disable func-names, no-underscore-dangle */
27

8+
/**
9+
* Initializes the toolbox.
10+
*/
11+
Blockly.Toolbox.prototype.init = function() {
12+
const workspace = this.workspace_;
13+
const svg = this.workspace_.getParentSvg();
14+
15+
/**
16+
* HTML container for the Toolbox menu.
17+
* @type {Element}
18+
*/
19+
this.HtmlDiv = goog.dom.createDom(goog.dom.TagName.DIV, 'toolbox');
20+
this.HtmlDiv.setAttribute('dir', workspace.RTL ? 'RTL' : 'LTR');
21+
22+
// deriv-bot: Create Toolbox header
23+
const el_toolbox_header = goog.dom.createDom(goog.dom.TagName.DIV, 'toolbox__header');
24+
const el_toolbox_title = goog.dom.createDom(goog.dom.TagName.DIV, 'toolbox__title');
25+
const el_toolbox_arrow = goog.dom.createDom(goog.dom.TagName.DIV, 'toolbox__arrow');
26+
27+
el_toolbox_title.textContent = translate('Blocks Library');
28+
el_toolbox_header.appendChild(el_toolbox_title);
29+
el_toolbox_header.appendChild(el_toolbox_arrow);
30+
this.HtmlDiv.appendChild(el_toolbox_header);
31+
32+
ReactDOM.render(<ArrowIcon className='arrow' />, el_toolbox_arrow);
33+
svg.parentNode.insertBefore(this.HtmlDiv, svg);
34+
35+
// deriv-bot: Clicking on toolbox arrow collapses it
36+
Blockly.bindEventWithChecks_(el_toolbox_arrow, 'mousedown', this, () => {
37+
const is_collapsed = this.HtmlDiv.classList.contains('toolbox--collapsed');
38+
39+
if (is_collapsed) {
40+
this.HtmlDiv.classList.remove('toolbox--collapsed');
41+
} else {
42+
this.HtmlDiv.classList.add('toolbox--collapsed');
43+
}
44+
45+
// Fire an event to re-position flyout.
46+
window.dispatchEvent(new Event('resize'));
47+
});
48+
49+
// Clicking on toolbox closes popups.
50+
Blockly.bindEventWithChecks_(this.HtmlDiv, 'mousedown', this, function(e) {
51+
// Cancel any gestures in progress.
52+
this.workspace_.cancelCurrentGesture();
53+
54+
if (Blockly.utils.isRightButton(e) || e.target === this.HtmlDiv) {
55+
// Close flyout.
56+
Blockly.hideChaff(false);
57+
} else {
58+
// Just close popups.
59+
Blockly.hideChaff(true);
60+
}
61+
Blockly.Touch.clearTouchIdentifier(); // Don't block future drags.
62+
}, /* opt_noCaptureIdentifier */ false, /* opt_noPreventDefault */ true);
63+
64+
this.createFlyout_();
65+
this.categoryMenu_ = new Blockly.Toolbox.CategoryMenu(this, this.HtmlDiv);
66+
this.populate_(workspace.options.languageTree);
67+
this.position();
68+
};
69+
370
/**
471
* Fill the toolbox with categories and blocks.
572
* @param {!Node} newTree DOM tree of blocks.
673
* @private
774
*/
8-
Blockly.Toolbox.prototype.populate_ = function(newTree) {
75+
Blockly.Toolbox.prototype.populate_ = function (newTree) {
976
this.categoryMenu_.populate(newTree);
1077
};
1178

1279
/**
13-
* Show blocks for specific category in flyout
14-
* This is different from Scratch as they show everything in one single flyout.
80+
* deriv-bot: Show blocks for a specific category in flyout
1581
* @private
1682
*/
17-
Blockly.Toolbox.prototype.showCategory_ = function(category_id) {
83+
Blockly.Toolbox.prototype.showCategory_ = function (category_id) {
1884
let allContents = [];
1985

2086
const category = this.categoryMenu_.categories_.find(menuCategory => menuCategory.id_ === category_id);
@@ -28,12 +94,99 @@ Blockly.Toolbox.prototype.showCategory_ = function(category_id) {
2894
this.flyout_.show(allContents);
2995
};
3096

97+
/**
98+
* Create the DOM for the category menu.
99+
* deriv-bot: Custom class names
100+
*/
101+
Blockly.Toolbox.CategoryMenu.prototype.createDom = function() {
102+
const className = this.parent_.horizontalLayout_ ? 'toolbox__horizontal-category-menu' : 'toolbox__category-menu';
103+
104+
this.table = goog.dom.createDom('div', className);
105+
this.parentHtml_.appendChild(this.table);
106+
};
107+
108+
/**
109+
* Fill the toolbox with categories and blocks by creating a new
110+
* {Blockly.Toolbox.Category} for every category tag in the toolbox xml.
111+
* deriv-bot: Port from Google Blockly
112+
* @param {Node} domTree DOM tree of blocks, or null.
113+
*/
114+
Blockly.Toolbox.CategoryMenu.prototype.populate = function(domTree) {
115+
if (!domTree) {
116+
return;
117+
}
118+
119+
// Remove old categories
120+
this.dispose();
121+
this.createDom();
122+
123+
const categories = [];
124+
125+
// Find actual categories from the DOM tree.
126+
domTree.childNodes.forEach((child) => {
127+
if (child.tagName && child.tagName.toUpperCase() === 'CATEGORY') {
128+
categories.push(child);
129+
}
130+
});
131+
132+
categories.forEach((child) => {
133+
const row = goog.dom.createDom(goog.dom.TagName.DIV, 'toolbox__row');
134+
135+
this.table.appendChild(row);
136+
137+
if (child) {
138+
this.categories_.push(new Blockly.Toolbox.Category(this, row, child));
139+
}
140+
});
141+
142+
this.height_ = this.table.offsetHeight;
143+
};
144+
145+
/**
146+
* Used to determine the css classes for the menu item for this category
147+
* based on its current state.
148+
* @private
149+
* @param {boolean=} selected Indication whether the category is currently selected.
150+
* @return {string} The css class names to be applied, space-separated.
151+
* deriv-bot: Custom class names
152+
*/
153+
Blockly.Toolbox.Category.prototype.getMenuItemClassName_ = function(selected) {
154+
const classNames = ['toolbox__item', `toolbox__category--${this.id_}`];
155+
156+
if (selected) {
157+
classNames.push('toolbox__category--selected');
158+
}
159+
160+
return classNames.join(' ');
161+
};
162+
163+
/**
164+
* Create the DOM for a category in the toolbox.
165+
* deriv-bot: Custom class names
166+
*/
167+
Blockly.Toolbox.Category.prototype.createDom = function () {
168+
const toolbox = this.parent_.parent_;
169+
170+
this.item_ = goog.dom.createDom('div', { class: this.getMenuItemClassName_() });
171+
this.label_ = goog.dom.createDom('div', {
172+
class: 'toolbox__label',
173+
}, Blockly.utils.replaceMessageReferences(this.name_));
174+
175+
const el_toolbox_row_color = goog.dom.createDom('div', { class: 'toolbox__color' });
176+
this.item_.appendChild(el_toolbox_row_color);
177+
178+
this.item_.appendChild(this.label_);
179+
this.parentHtml_.appendChild(this.item_);
180+
181+
Blockly.bindEvent_(this.item_, 'mouseup', toolbox, toolbox.setSelectedItemFactory(this));
182+
};
183+
31184
/**
32185
* Opens the selected category
33-
* deriv-bot: unlike in Scratch, we want to have category-specific flyouts + removed opt_shouldScroll
186+
* deriv-bot: Category-specific flyouts + removed opt_shouldScroll
34187
* @param {Blockly.Toolbox.Category} item The category to select.
35188
*/
36-
Blockly.Toolbox.prototype.setSelectedItem = function(item) {
189+
Blockly.Toolbox.prototype.setSelectedItem = function (item) {
37190
if (this.selectedItem_) {
38191
// They selected a different category but one was already open. Close it.
39192
this.selectedItem_.setSelected(false);
@@ -62,36 +215,39 @@ Blockly.Toolbox.prototype.refreshSelection = function() {
62215

63216
/**
64217
* Move the toolbox to the edge.
218+
* deriv-bot: Don't set height of toolbox inline
65219
*/
66-
Blockly.Toolbox.prototype.position = function() {
220+
Blockly.Toolbox.prototype.position = function () {
67221
const treeDiv = this.HtmlDiv;
222+
68223
if (!treeDiv) {
69224
// Not initialized yet.
70225
return;
71226
}
227+
72228
const svg = this.workspace_.getParentSvg();
73229
const svgSize = Blockly.svgSize(svg);
230+
74231
if (this.horizontalLayout_) {
75232
treeDiv.style.left = '0';
76233
treeDiv.style.height = 'auto';
77234
treeDiv.style.width = `${svgSize.width}px`;
78235
this.height = treeDiv.offsetHeight;
236+
79237
if (this.toolboxPosition === Blockly.TOOLBOX_AT_TOP) {
80238
// Top
81239
treeDiv.style.top = '0';
82240
} else {
83241
// Bottom
84242
treeDiv.style.bottom = '0';
85243
}
244+
} else if (this.toolboxPosition === Blockly.TOOLBOX_AT_RIGHT) {
245+
// Right
246+
treeDiv.style.right = '0';
86247
} else {
87-
if (this.toolboxPosition === Blockly.TOOLBOX_AT_RIGHT) {
88-
// Right
89-
treeDiv.style.right = '0';
90-
} else {
91-
// Left
92-
treeDiv.style.left = '0';
93-
}
94-
treeDiv.style.height = '100%';
248+
// Left
249+
treeDiv.style.left = '0';
95250
}
251+
96252
this.flyout_.position();
97253
};

0 commit comments

Comments
 (0)