5
5
from sage_widget_adapters .graphs .graph_grid_view_adapter import GraphGridViewAdapter
6
6
from sage_combinat_widgets .grid_view_widget import GridViewWidget , ButtonCell , BlankButton , styled_button_cell
7
7
from ipywidgets import Layout
8
- from traitlets import dlink , HasTraits , Bool
8
+ from traitlets import dlink , HasTraits , Bool , observe , All
9
9
from contextlib import contextmanager
10
+ from sage_combinat_widgets .grid_view_editor import extract_coordinates
10
11
11
12
smallblyt = Layout (width = '12px' ,height = '12px' , margin = '0' , padding = '0' )
12
13
@@ -26,7 +27,7 @@ def set_cell(self, obj, pos, val, dirty={}):
26
27
if dirty : # if i'm a neighbor, then flip and return a new obj ; else return an error
27
28
# Consider the relevant matching(s)
28
29
for p in dirty :
29
- if not dirty [p ]: # check this position is pressed
30
+ if not dirty [p ]: # check this position was pressed
30
31
continue
31
32
d2 = obj .domino_for_position (p )
32
33
if d2 == d1 or not d2 in d1 .neighbors ():
@@ -98,8 +99,8 @@ def _busy_updating(self):
98
99
self .updating = False
99
100
100
101
def _update (self , change ):
101
- if self .updating :
102
- return
102
+ # if self.updating or self.target[0].donottrack :
103
+ # return
103
104
with self ._busy_updating ():
104
105
if self .logic == 'and' :
105
106
if self .intermediate_value == False : # aucun bouton pressé avant
@@ -155,23 +156,25 @@ def __init__(self, parent, b1, b2):
155
156
self .link = None
156
157
self .direction = None
157
158
self .orientation = None
158
- self .compute (None )
159
+ self .compute ()
160
+ self .donottrack = False
159
161
160
162
def __repr__ (self ):
161
163
if self .value :
162
164
return repr (self .first ) + ' -> ' + repr (self .second ) + " PRESSED"
163
165
return repr (self .first ) + ' -> ' + repr (self .second )
164
166
165
- def compute (self , css_classes = None ):
167
+ def compute (self , css_classes = [ 'b0' , 'b1' , 'b2' , 'b3' , 'b4' ] ):
166
168
"""Compute buttons relative positions.
167
169
Create double directional link from both buttons"""
168
170
self .geometry .compute ()
171
+ #print(self.geometry.__dict__)
169
172
if css_classes :
170
173
for cl in css_classes :
171
174
self .first .remove_class (cl )
172
175
self .second .remove_class (cl )
173
- self .first .add_class (css_classes [self .geometry .index_for_display - 1 ])
174
- self .second .add_class (css_classes [self .geometry .index_for_display - 1 ])
176
+ self .first .add_class (css_classes [self .geometry .index_for_display ])
177
+ self .second .add_class (css_classes [self .geometry .index_for_display ])
175
178
if self .geometry .orientation == 1 :
176
179
self .key = self .first .position
177
180
else :
@@ -199,19 +202,19 @@ def is_pressed(self):
199
202
"""Is the domino pressed?"""
200
203
return self .value
201
204
202
- def set_value (self , value ):
203
- """Set domino value
204
- As we have a directional link,
205
- the domino value will also be set.
206
- """
207
- self .link .unlink ()
208
- self .first .value = value
209
- self .second .value = value
210
- self .link = ddlink (((self .first , 'value' ), (self .second , 'value' )), (self , 'value' ), logic = 'and' , set_at_init = False ) # Fresh ddlink
205
+ # def set_value(self, value):
206
+ # """Set domino value
207
+ # As we have a directional link,
208
+ # the domino value will also be set.
209
+ # """
210
+ # self.link.unlink()
211
+ # self.first.value = value
212
+ # self.second.value = value
213
+ # self.link = ddlink(((self.first, 'value'), (self.second, 'value')), (self, 'value'), logic='and', set_at_init=False) # Fresh ddlink
211
214
212
215
def reset (self ):
213
216
"""Full domino reset"""
214
- self .set_value (False )
217
+ # self.set_value(False)
215
218
self .link .unlink ()
216
219
217
220
def flip (self , other ):
@@ -237,11 +240,12 @@ def cell_widget_class_index(pos):
237
240
class FlippingDominosWidget (GridViewWidget ):
238
241
"""A widget with dominos"""
239
242
240
- def __init__ (self , g ):
243
+ def __init__ (self , g , css_classes = [ 'b0' , 'b1' , 'b2' , 'b3' , 'b4' ] ):
241
244
r"""
242
245
Init a flipping dominos widget
243
246
with flipping aztec diamond graph `g`
244
247
"""
248
+ self .css_classes = css_classes
245
249
super (FlippingDominosWidget , self ).__init__ (g , adapter = FlippingDominosAdapter (),
246
250
cell_layout = smallblyt ,
247
251
cell_widget_classes = [styled_button_cell (),
@@ -252,19 +256,11 @@ def __init__(self, g):
252
256
],
253
257
cell_widget_class_index = make_cell_widget_class_index (g ),
254
258
blank_widget_class = BlankButton )
255
- self .css_classes = ['b1' , 'b2' , 'b3' , 'b4' ]
256
-
257
259
def draw (self ):
258
260
self .dominos = {}
259
261
super (FlippingDominosWidget , self ).draw ()
260
262
self .apply_matching (self .value .matching )
261
263
262
- def update (self ):
263
- self .apply_matching (self .value .matching )
264
- for k ,d in self .dominos .items ():
265
- d .compute (self .css_classes )
266
- d .set_value (False ) # unpress buttons
267
-
268
264
def match (self , b1 , b2 ):
269
265
"""Match buttons b1 and b2, that is: create a domino"""
270
266
try :
@@ -286,7 +282,64 @@ def apply_matching(self, matching):
286
282
self .match (self .children [d .first [0 ]].children [d .first [1 ]],
287
283
self .children [d .second [0 ]].children [d .second [1 ]])
288
284
289
- def set_value (self , value ):
290
- """Need to call self.update() manually, as the change is not obvious to the observer!"""
285
+ def update (self ):
286
+ self .apply_matching (self .value .matching )
287
+ for k ,d in self .dominos .items ():
288
+ d .compute (self .css_classes )
289
+ #d.set_value(False) # unpress buttons
290
+
291
+ def domino_for_position (self , pos ):
292
+ geometry = self .value .domino_for_position (pos )
293
+ for t in (geometry .first , geometry .second ):
294
+ if t in self .dominos :
295
+ print ("domino for position" , t , ":" , self .dominos [t ].geometry , self .dominos [t ].value )
296
+ return self .dominos [t ]
297
+
298
+ def not_tracking (self , value ):
299
+ self .donottrack = value
300
+ for d in self .dominos .values ():
301
+ d .donottrack = value
302
+
303
+ @observe (All )
304
+ def set_cell (self , change ):
305
+ if self .donottrack :
306
+ return
307
+ if change .name .startswith ('cell_' ):
308
+ print ("set_cell()" , change .name , change .old , change .new )
309
+ else :
310
+ print ("set_cell()" , change .name )
311
+ # Try to reset everything right now to avoid unwanted propagations
312
+ domino = self .domino_for_position (extract_coordinates (change .name ))
313
+ # First, we want to make the pressed domino visible to the user
314
+ self .not_tracking (True )
315
+ domino .first .value = True
316
+ domino .second .value = True
317
+ # Any pressed neighbor?
318
+ other = None
319
+ if self .dirty :
320
+ for pos in self .dirty :
321
+ other = self .domino_for_position (pos )
322
+ if other and not other .geometry in domino .geometry .neighbors ():
323
+ other = None
324
+ continue # we don't have to reset everything, I guess(hope)
325
+ if not other :
326
+ self .dirty [domino .geometry .first ] = True
327
+ self .dirty [domino .geometry .second ] = True
328
+ self .not_tracking (False )
329
+ return
330
+ if domino .link :
331
+ domino .link .unlink ()
332
+ if other .link :
333
+ other .link .unlink ()
334
+ self .not_tracking (False )
335
+ super (FlippingDominosWidget , self ).set_cell (change )
336
+ self .not_tracking (True )
337
+ # And now, we want to reset everything before the flip
338
+ domino .first .value = False
339
+ domino .second .value = False
340
+ other .first .value = False
341
+ other .second .value = False
342
+ # Now, recreate the 2 dominos and compute style
291
343
self .reset_dirty ()
292
344
self .update ()
345
+ self .not_tracking (False )
0 commit comments