Skip to content

Commit 9a3329d

Browse files
committed
Timeline: Fix slow drag operations
1 parent 8017c4d commit 9a3329d

File tree

1 file changed

+74
-59
lines changed

1 file changed

+74
-59
lines changed

lglpy/timeline/drawable/timeline_base.py

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -196,23 +196,35 @@ def add_to_active_objects(self, new_object):
196196
Args:
197197
new_object: the object to add.
198198
'''
199+
# If this object is already active then do nothing
200+
if new_object in self.active_objects:
201+
return
202+
199203
# If this is the first selection then fade all the 'other' objects
200204
if not self.active_objects:
201205
for drawable in self.drawable_trace.each_object():
202206
style_set = drawable.style.style_set
203207
drawable.style = style_set.get_style('fade')
204208

205-
# Update the style if this is a new user data
206-
user_data = [x.user_data for x in self.active_objects if x.user_data]
209+
# If no user data then highlight by raw object
210+
if not new_object.user_data:
211+
style_set = new_object.style.style_set
212+
new_object.style = style_set.get_style('highlight')
207213

208-
if new_object.user_data and (new_object.user_data not in user_data):
209-
for drawable in self.drawable_trace.each_object():
210-
if drawable.user_data == new_object.user_data:
214+
# If new user data then highlight all events with matching user data
215+
else:
216+
user_data = {
217+
x.user_data for x in self.active_objects if x.user_data
218+
}
219+
220+
if new_object.user_data not in user_data:
221+
def obj_filter(x):
222+
return x.user_data == new_object.user_data
223+
224+
for drawable in self.drawable_trace.each_object(
225+
obj_filter=obj_filter):
211226
style_set = drawable.style.style_set
212227
drawable.style = style_set.get_style('highlight')
213-
else:
214-
style_set = new_object.style.style_set
215-
new_object.style = style_set.get_style('highlight')
216228

217229
self.active_objects.add(new_object)
218230

@@ -223,61 +235,67 @@ def add_multiple_to_active_objects(self, new_objects):
223235
Args:
224236
new_objects: sequence of objects to add.
225237
'''
238+
# If no new objects then do nothing
239+
if not new_objects:
240+
return
241+
226242
# If this is the first selection then fade all the 'other' objects
227243
if not self.active_objects:
228244
for drawable in self.drawable_trace.each_object():
229245
style_set = drawable.style.style_set
230246
drawable.style = style_set.get_style('fade')
231247

248+
# Add object to the active objects if we don't have it already
249+
added_user_data = set()
232250
for new_object in new_objects:
251+
if new_object in self.active_objects:
252+
continue
253+
233254
self.active_objects.add(new_object)
255+
256+
# If no user data then highlight by raw object
234257
if not new_object.user_data:
235258
style_set = new_object.style.style_set
236259
new_object.style = style_set.get_style('highlight')
260+
# Else track user data so we can use it later
261+
else:
262+
added_user_data.add(new_object.user_data)
237263

238-
# TODO: What's the point in this?
239-
user_data = {x.user_data for x in self.active_objects if x.user_data}
240-
for drawable in self.drawable_trace.each_object():
241-
if drawable.user_data in user_data:
242-
style_set = drawable.style.style_set
243-
drawable.style = style_set.get_style('highlight')
264+
# If new user data then highlight all events with matching it
265+
def obj_filter(x):
266+
return x.user_data in added_user_data
267+
268+
for drawable in self.drawable_trace.each_object(obj_filter=obj_filter):
269+
style_set = drawable.style.style_set
270+
drawable.style = style_set.get_style('highlight')
244271

245272
def remove_from_active_objects(self, old_object):
246273
'''
247274
Remove an object from the set of active objects.
248275
249276
Args:
250-
old_object: WorldDrawable`
251-
The object to remove.
252-
'''
253-
removed_objects = set()
254-
user_data = old_object.user_data
255-
256-
if user_data:
257-
for drawable in self.active_objects:
258-
if drawable.user_data == user_data:
259-
removed_objects.add(drawable)
260-
for drawable in removed_objects:
261-
self.active_objects.remove(drawable)
262-
else:
263-
self.active_objects.remove(old_object)
264-
removed_objects.add(old_object)
277+
old_object: the object to remove.
278+
'''
279+
self.remove_multiple_from_active_objects(set([old_object]))
280+
281+
def remove_multiple_from_active_objects(self, old_objects):
282+
'''
283+
Remove an sequence of objects from the set of active objects.
284+
285+
Args:
286+
old_objects: the sequence of objects to remove.
287+
'''
288+
removed_objects = {x for x in old_objects}
289+
new_active_objects = self.active_objects - removed_objects
265290

266291
# If nothing left then reset the active state
267-
if not self.active_objects:
292+
if not new_active_objects:
268293
self.clear_active_objects()
269294
return
270295

271-
# Update the style if this is a new user data
272-
user_data = {x.user_data for x in self.active_objects if x.user_data}
273-
274-
# Update the style
275-
if old_object.user_data and (old_object.user_data not in user_data):
276-
for drawable in self.drawable_trace.each_object():
277-
if drawable.user_data == old_object.user_data:
278-
drawable.style = drawable.style.style_set.get_style('fade')
279-
else:
280-
old_object.style = old_object.style.style_set.get_style('fade')
296+
# Else rebuild with the remaining active_objects
297+
self.active_objects.clear()
298+
self.add_multiple_to_active_objects(new_active_objects)
281299

282300
def clear_active_objects(self):
283301
'''
@@ -495,6 +513,7 @@ def on_mouse_drag_release(self, button, drag):
495513

496514
# Find the clicked objects
497515
dt = self.drawable_trace
516+
498517
clicked_objects = dt.get_boxed_objects(min_x, min_y, max_x, max_y)
499518
if not clicked_objects:
500519
# Force a redraw if we were dragging, even if the click itself
@@ -504,20 +523,15 @@ def on_mouse_drag_release(self, button, drag):
504523
# If no modifier then create selection from highlighted region
505524
if drag.mod == '':
506525
self.active_objects.clear()
507-
for clicked_object in clicked_objects:
508-
self.add_to_active_objects(clicked_object)
526+
self.add_multiple_to_active_objects(clicked_objects)
509527

510528
# If 'c' modifier then append selection to highlighted region
511529
elif drag.mod == 'c':
512-
for clicked_object in clicked_objects:
513-
if clicked_object not in self.active_objects:
514-
self.add_to_active_objects(clicked_object)
530+
self.add_multiple_to_active_objects(clicked_objects)
515531

516-
# If 's' modifier then append selection to highlighted region
532+
# If 's' modifier then subtract selection to highlighted region
517533
elif drag.mod == 's':
518-
for clicked_object in clicked_objects:
519-
if clicked_object in self.active_objects:
520-
self.remove_from_active_objects(clicked_object)
534+
self.remove_multiple_from_active_objects(clicked_objects)
521535

522536
return True
523537

@@ -554,19 +568,20 @@ def on_mouse_single_click(self, button, x, y, mod):
554568
clicked_object = self.drawable_trace.get_clicked_object(ws_x, ws_y)
555569

556570
if (button == 'left') and clicked_object:
571+
# If no modifier then create selection from highlighted region
557572
if mod == '':
558-
if clicked_object in self.active_objects:
559-
self.remove_from_active_objects(clicked_object)
560-
else:
561-
self.active_objects.clear()
562-
self.add_to_active_objects(clicked_object)
573+
self.active_objects.clear()
574+
self.add_to_active_objects(clicked_object)
563575
return True
564576

565-
if mod == 'c':
566-
if clicked_object in self.active_objects:
567-
self.remove_from_active_objects(clicked_object)
568-
else:
569-
self.add_to_active_objects(clicked_object)
577+
# If 'c' modifier then append selection to highlighted region
578+
elif mod == 'c':
579+
self.add_to_active_objects(clicked_object)
580+
return True
581+
582+
# If 's' modifier then subtract selection to highlighted region
583+
elif mod == 's':
584+
self.remove_from_active_objects(clicked_object)
570585
return True
571586

572587
return False

0 commit comments

Comments
 (0)