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