def on_top(self, event):
index, item = self.find_shape()
self.shapes.pop(index)
self.shapes.append(item)
self.populate()
self.list.Select(0)
def on_bottom(self, event):
index, item = self.find_shape()
self.shapes.pop(index)
self.shapes.insert(0, item)
self.populate()
self.list.Select(len(self.shapes) - 1)
def on_up(self, event):
index, item = self.find_shape()
self.shapes.pop(index)
self.shapes.insert(index + 1, item)
x = self.list.GetFirstSelected() - 1
self.populate()
self.list.Select(x)
def on_down(self, event):
index, item = self.find_shape()
self.shapes.pop(index)
self.shapes.insert(index - 1, item)
x = self.list.GetFirstSelected() + 1
self.populate()
self.list.Select(x)
As you can see - a lot of repeated code, with only different things happening in the middle of each function. This is ideal for a decorator. I struggled for a while to get it working as a decorator function inside a class, before reading how you define a wrapper function for creating a closure over the decorated function.
My code now reads,
def move_shape(fn):
"""
Passes the selected shape and its index to the decorated function, which
handles moving the shape. function returns the list's index to select
"""
def wrapper(self, event, index=None, item=None):
index, item = self.find_shape()
self.shapes.pop(index)
x = fn(self, event, index, item)
self.populate()
self.list.Select(x)
return wrapper
@move_shape
def on_top(self, event, index=None, item=None):
self.shapes.append(item)
return 0
@move_shape
def on_bottom(self, event, index=None, item=None):
self.shapes.insert(0, item)
return len(self.shapes) - 1
@move_shape
def on_up(self, event, index=None, item=None):
self.shapes.insert(index + 1, item)
return self.list.GetFirstSelected() - 1
@move_shape
def on_down(self, event, index=None, item=None):
self.shapes.insert(index - 1, item)
return self.list.GetFirstSelected() + 1
Unfortunately the event parameter is there because these are also wxPython event listeners, and I'd have to create delegate functions just to remove the one parameter, which seems pointless.