Skip to content

Commit 5d25471

Browse files
author
hartsantler
committed
updated GoogleBlockly bindings and test
1 parent 9599fec commit 5d25471

3 files changed

Lines changed: 82 additions & 32 deletions

File tree

bindings/blockly.py

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,31 @@ def initialize_blockly( blockly_id='blocklyDiv', toolbox_id='toolbox', on_change
99
print 'initialize_blockly'
1010
if len( BlocklyBlockGenerators.keys() ):
1111
toolbox = document.getElementById( toolbox_id )
12-
cat = document.createElement('category')
13-
cat.setAttribute('name', 'Callbacks')
14-
toolbox.appendChild( cat )
12+
defaults = []
13+
cats = {}
1514
for block_name in BlocklyBlockGenerators.keys():
1615
e = document.createElement('block')
1716
e.setAttribute('type', block_name)
18-
cat.appendChild( e )
1917

18+
b = BlocklyBlockGenerators[ block_name ]
19+
if b.category:
20+
if b.category in cats:
21+
cats[ b.category ].appendChild( e )
22+
else:
23+
cat = document.createElement('category')
24+
cat.setAttribute('name', b.category)
25+
cat.appendChild( e )
26+
toolbox.appendChild( cat )
27+
cats[ b.category ] = cat
28+
else:
29+
defaults.append( e )
30+
31+
if len(defaults):
32+
cat = document.createElement('category')
33+
cat.setAttribute('name', 'Callbacks')
34+
toolbox.appendChild( cat )
35+
for e in defaults:
36+
cat.appendChild( e )
2037

2138
with javascript:
2239
Blockly.inject(
@@ -50,15 +67,16 @@ class BlocklyBlock:
5067
. a bare block can have no inputs or output, and no previous or next statement notches.
5168
5269
'''
53-
def __init__(self, name, title=None, color=None):
54-
self.setup( name, title=title, color=color )
70+
def __init__(self, name, title=None, color=None, category=None):
71+
self.setup( name, title=title, color=color, category=None )
5572

56-
def setup(self, name, title=None, color=None):
73+
def setup(self, name, title=None, color=None, category=None):
5774
if name in BlocklyBlockGenerators: raise TypeError
5875
BlocklyBlockGenerators[ name ] = self
5976
self.name = name
6077
self.title = title
6178
self.color = color
79+
self.category = category
6280
self.input_values = []
6381
self.input_statements = []
6482
self.output = None
@@ -70,16 +88,21 @@ def setup(self, name, title=None, color=None):
7088
self.on_click_callback = None
7189

7290
def callback(self, jsfunc): ## decorator
91+
print '@callback', jsfunc
7392
self.set_external_function( jsfunc.NAME )
93+
with javascript: arr = jsfunc.args_signature
94+
print 'arr', arr
95+
for i in range(arr.length):
96+
self.add_input_value( arr[i] )
7497
return jsfunc
7598

7699
def set_on_click_callback(self, callback):
77100
self.on_click_callback = callback
78101

79102
def set_external_function(self, func_name):
80103
self.external_function = func_name
81-
if self.title:
82-
self.title = self.title + ': ' + func_name
104+
if not self.title:
105+
self.title = func_name
83106

84107
def set_output(self, output):
85108
if self.stack_input: raise TypeError
@@ -105,13 +128,15 @@ def add_input_value(self, name=None, type=None, title=None):
105128
elif type == 'Number': pass
106129
elif type == 'String': pass
107130
elif type == 'Array': pass
108-
else: raise TypeError
131+
#else: raise TypeError
132+
if title is None: title = name
109133
self.input_values.append(
110134
{'name':name, 'type':type, 'title':title}
111135
)
112136

113137
def add_input_statement(self, name=None, title=None):
114138
if name is None: raise TypeError
139+
if title is None: title = name
115140
self.input_statements.append(
116141
{'name':name, 'title':title}
117142
)
@@ -127,9 +152,9 @@ def bind_block(self):
127152
raise TypeError
128153

129154
title = self.title
130-
input_values = self.input_values
131-
input_statements = self.input_statements
132155
color = self.color
156+
input_values = self.input_values.js_object
157+
input_statements = self.input_statements.js_object
133158

134159
with javascript:
135160
def init():
@@ -144,11 +169,19 @@ def init():
144169
if stack_output:
145170
this.setNextStatement( True )
146171

147-
for input in input_values: # input[...]['name'] for a dict becomes: input.__dict__.js_object['name']
148-
this.appendValueInput( input['name'] ).setCheck( input['type'] ).appendTitle( input['title'] )
149-
150-
for input in input_statements:
172+
i = 0
173+
while i < input_values.length:
174+
input = input_values[i][...]
175+
if input['type']:
176+
this.appendValueInput(input['name'] ).setCheck( input['type'] ).appendTitle( '<'+input['type']+'> '+input['title'] ).setAlign(Blockly.ALIGN_RIGHT)
177+
else:
178+
this.appendValueInput(input['name'] ).appendTitle( input['title'] ).setAlign(Blockly.ALIGN_RIGHT)
179+
i += 1
180+
i = 0
181+
while i < input_statements.length:
182+
input = input_statements[i][...]
151183
this.appendStatementInput( input['name'] ).appendTitle( input['title'] )
184+
i += 1
152185

153186
if output == '*':
154187
this.setOutput( True, null ) ## allows output of any type
@@ -161,22 +194,30 @@ def init():
161194
def bind_generator(self):
162195
block_name = self.name
163196
external_function = self.external_function
164-
input_values = self.input_values
165-
input_statements = self.input_statements
166197
is_statement = self.is_statement
198+
input_values = self.input_values.js_object
199+
input_statements = self.input_statements.js_object
167200

168201
with javascript:
169202
def generator(block):
170203
code = ''
171204

172205
args = []
173-
for input in input_values:
174-
a = Blockly.Python.valueToCode(block, input['name'], Blockly.Python.ORDER_NONE)
175-
args.push( a )
176206

177-
for input in input_statements:
207+
i = 0
208+
while i < input_values.length:
209+
input = input_values[i][...]
210+
a = Blockly.Python.valueToCode(block, input['name'], Blockly.Python.ORDER_NONE)
211+
if a is not null: ## blockly API not correct? is says this will return null when nothing is connected.
212+
args.push( a )
213+
i += 1
214+
i = 0
215+
while i < input_statements.length:
216+
input = input_statements[i][...]
178217
a = Blockly.Python.statementToCode(block, input['name'])
179-
args.push( a )
218+
if a != '': ## blockly API would be better not returning an empty string here, in case we wanted to set an empty string
219+
args.push( a )
220+
i += 1
180221

181222
if external_function:
182223
code += external_function + '(' + ','.join(args) + ')'
@@ -198,15 +239,15 @@ class StatementBlock( BlocklyBlock ):
198239
'''
199240
A statement-block has a previous and/or next statement notch: stack_input and/or stack_output
200241
'''
201-
def __init__(self, name, title=None, stack_input=False, stack_output=False, color=150):
202-
self.setup( name, title=title, color=color )
242+
def __init__(self, name, title=None, stack_input=False, stack_output=False, color=150, category=None):
243+
self.setup( name, title=title, color=color, category=category )
203244
self.make_statement( stack_input=stack_input, stack_output=stack_output)
204245

205246

206247
class ValueBlock( BlocklyBlock ):
207-
def __init__(self, name, title=None, output=None, color=120):
248+
def __init__(self, name, title=None, output=None, color=120, category=None):
208249
if output is None: raise TypeError
209-
self.setup( name, title=title, color=color )
250+
self.setup( name, title=title, color=color, category=category )
210251
self.set_output( output )
211252

212253

pythonjs/python_to_pythonjs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,7 @@ def visit_FunctionDef(self, node):
10501050
## note, in javascript function.name is a non-standard readonly attribute,
10511051
## the compiler creates anonymous functions with name set to an empty string.
10521052
writer.write('%s.NAME = "%s"' %(node.name,node.name))
1053+
writer.write( '%s.args_signature = [%s]' %(node.name, ','.join(['"%s"'%n.id for n in node.args.args])) )
10531054

10541055
if self._with_js and with_js_decorators:
10551056
## these with-js functions are assigned to a some objects prototype,

tests/blockly_custom_blocks.html

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,20 @@
134134
<script type="text/python">
135135
from blockly import *
136136

137-
myblock = StatementBlock('myblock', title='My Block', stack_input=True)
138-
#myblock.set_external_function('testextern')
139-
140-
@myblock.callback
141-
def my_extern_func():
137+
myblock1 = StatementBlock('myblock1', title='My Block1', stack_input=True, category='Statements')
138+
myblock1.set_external_function('func1')
139+
myblock1.add_input_value('a', type='Number')
140+
myblock1.add_input_value('b', type='String')
141+
142+
def func1(a,b):
143+
print 'a', a
144+
print 'b', b
145+
146+
myblock2 = ValueBlock('myblock2', output='Number')
147+
@myblock2.callback
148+
def my_extern_func(x,y,z, w=None):
142149
print 'hello extern func'
150+
return x+y+z
143151

144152
def show_code():
145153
with javascript:

0 commit comments

Comments
 (0)