@@ -13,6 +13,8 @@ import {isLegacyProcedureDefBlock} from './interfaces/i_legacy_procedure_blocks.
1313import { isVariableBackedParameterModel } from './interfaces/i_variable_backed_parameter_model.js' ;
1414import { IVariableModel , IVariableState } from './interfaces/i_variable_model.js' ;
1515import { Msg } from './msg.js' ;
16+ import * as deprecation from './utils/deprecation.js' ;
17+ import type { BlockInfo , FlyoutItemInfo } from './utils/toolbox.js' ;
1618import * as utilsXml from './utils/xml.js' ;
1719import type { Workspace } from './workspace.js' ;
1820import type { WorkspaceSvg } from './workspace_svg.js' ;
@@ -84,19 +86,165 @@ export function allDeveloperVariables(workspace: Workspace): string[] {
8486 return Array . from ( variables . values ( ) ) ;
8587}
8688
89+ /**
90+ * Internal wrapper that returns the contents of the variables category.
91+ *
92+ * @internal
93+ * @param workspace The workspace to populate variable blocks for.
94+ */
95+ export function internalFlyoutCategory (
96+ workspace : WorkspaceSvg ,
97+ ) : FlyoutItemInfo [ ] {
98+ return flyoutCategory ( workspace , false ) ;
99+ }
100+
101+ export function flyoutCategory (
102+ workspace : WorkspaceSvg ,
103+ useXml : true ,
104+ ) : Element [ ] ;
105+ export function flyoutCategory (
106+ workspace : WorkspaceSvg ,
107+ useXml : false ,
108+ ) : FlyoutItemInfo [ ] ;
87109/**
88110 * Construct the elements (blocks and button) required by the flyout for the
89111 * variable category.
90112 *
91113 * @param workspace The workspace containing variables.
92- * @returns Array of XML elements.
114+ * @param useXml True to return the contents as XML, false to use JSON.
115+ * @returns List of flyout contents as either XML or JSON.
93116 */
94- export function flyoutCategory ( workspace : WorkspaceSvg ) : Element [ ] {
117+ export function flyoutCategory (
118+ workspace : WorkspaceSvg ,
119+ useXml = true ,
120+ ) : Element [ ] | FlyoutItemInfo [ ] {
95121 if ( ! Blocks [ 'variables_set' ] && ! Blocks [ 'variables_get' ] ) {
96122 console . warn (
97123 'There are no variable blocks, but there is a variable category.' ,
98124 ) ;
99125 }
126+
127+ if ( useXml ) {
128+ deprecation . warn (
129+ 'The XML return value of Blockly.Variables.flyoutCategory()' ,
130+ 'v12' ,
131+ 'v13' ,
132+ 'the same method, but handle a return type of FlyoutItemInfo[] (JSON) instead.' ,
133+ ) ;
134+ return xmlFlyoutCategory ( workspace ) ;
135+ }
136+
137+ workspace . registerButtonCallback ( 'CREATE_VARIABLE' , function ( button ) {
138+ createVariableButtonHandler ( button . getTargetWorkspace ( ) ) ;
139+ } ) ;
140+
141+ return [
142+ {
143+ 'kind' : 'button' ,
144+ 'text' : '%{BKY_NEW_VARIABLE}' ,
145+ 'callbackkey' : 'CREATE_VARIABLE' ,
146+ } ,
147+ ...jsonFlyoutCategoryBlocks (
148+ workspace ,
149+ workspace . getVariablesOfType ( '' ) ,
150+ true ,
151+ ) ,
152+ ] ;
153+ }
154+
155+ /**
156+ * Returns the JSON definition for a variable field.
157+ *
158+ * @param variable The variable the field should reference.
159+ * @returns JSON for a variable field.
160+ */
161+ function generateVariableFieldJson ( variable : IVariableModel < IVariableState > ) {
162+ return {
163+ 'VAR' : {
164+ 'name' : variable . getName ( ) ,
165+ 'type' : variable . getType ( ) ,
166+ } ,
167+ } ;
168+ }
169+
170+ /**
171+ * Construct the blocks required by the flyout for the variable category.
172+ *
173+ * @internal
174+ * @param workspace The workspace containing variables.
175+ * @param variables List of variables to create blocks for.
176+ * @param includeChangeBlocks True to include `change x by _` blocks.
177+ * @param getterType The type of the variable getter block to generate.
178+ * @param setterType The type of the variable setter block to generate.
179+ * @returns JSON list of blocks.
180+ */
181+ export function jsonFlyoutCategoryBlocks (
182+ workspace : Workspace ,
183+ variables : IVariableModel < IVariableState > [ ] ,
184+ includeChangeBlocks : boolean ,
185+ getterType = 'variables_get' ,
186+ setterType = 'variables_set' ,
187+ ) : BlockInfo [ ] {
188+ includeChangeBlocks &&= Blocks [ 'math_change' ] ;
189+
190+ const blocks = [ ] ;
191+ const mostRecentVariable = variables . slice ( - 1 ) [ 0 ] ;
192+ if ( mostRecentVariable ) {
193+ // Show one setter block, with the name of the most recently created variable.
194+ if ( Blocks [ setterType ] ) {
195+ blocks . push ( {
196+ kind : 'block' ,
197+ type : setterType ,
198+ gap : includeChangeBlocks ? 8 : 24 ,
199+ fields : generateVariableFieldJson ( mostRecentVariable ) ,
200+ } ) ;
201+ }
202+
203+ if ( includeChangeBlocks ) {
204+ blocks . push ( {
205+ 'kind' : 'block' ,
206+ 'type' : 'math_change' ,
207+ 'gap' : Blocks [ getterType ] ? 20 : 8 ,
208+ 'fields' : generateVariableFieldJson ( mostRecentVariable ) ,
209+ 'inputs' : {
210+ 'DELTA' : {
211+ 'shadow' : {
212+ 'type' : 'math_number' ,
213+ 'fields' : {
214+ 'NUM' : 1 ,
215+ } ,
216+ } ,
217+ } ,
218+ } ,
219+ } ) ;
220+ }
221+ }
222+
223+ if ( Blocks [ getterType ] ) {
224+ // Show one getter block for each variable, sorted in alphabetical order.
225+ blocks . push (
226+ ...variables . sort ( compareByName ) . map ( ( variable ) => {
227+ return {
228+ 'kind' : 'block' ,
229+ 'type' : getterType ,
230+ 'gap' : 8 ,
231+ 'fields' : generateVariableFieldJson ( variable ) ,
232+ } ;
233+ } ) ,
234+ ) ;
235+ }
236+
237+ return blocks ;
238+ }
239+
240+ /**
241+ * Construct the elements (blocks and button) required by the flyout for the
242+ * variable category.
243+ *
244+ * @param workspace The workspace containing variables.
245+ * @returns Array of XML elements.
246+ */
247+ function xmlFlyoutCategory ( workspace : WorkspaceSvg ) : Element [ ] {
100248 let xmlList = new Array < Element > ( ) ;
101249 const button = document . createElement ( 'button' ) ;
102250 button . setAttribute ( 'text' , '%{BKY_NEW_VARIABLE}' ) ;
0 commit comments