Add a `Delete` button to the GUI NavBar, and cleanup deletion callbacks.
[hooke.git] / hooke / ui / gui / panel / playlist.py
index e69f248fc2fb4dca943d218827d95c7b60690e77..cf069e804fd5f9e701b64a1b5785e620cfc21518 100644 (file)
@@ -1,21 +1,19 @@
-# Copyright (C) 2010 Massimo Sandal <devicerandom@gmail.com>
-#                    W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2010-2012 W. Trevor King <wking@drexel.edu>
 #
 # This file is part of Hooke.
 #
-# Hooke is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
+# Hooke is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
 #
-# Hooke is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
-# Public License for more details.
+# Hooke is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
 #
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke.  If not, see
-# <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Lesser General Public License
+# along with Hooke.  If not, see <http://www.gnu.org/licenses/>.
 
 """Playlist panel for Hooke.
 
@@ -198,63 +196,57 @@ class Tree (wx.TreeCtrl):
         del(self._hit_id)
         name = self._name_for_id[_id]
         if self._is_curve(name):
-            self.delete_curve(playlist_name=name[0], name=name[1])
+            self._delete_curve(playlist_name=name[0], name=name[1])
         else:
-            self.delete_playlist(name)
+            self._delete_playlist(name)
 
-    def delete_playlist(self, name):
+    def _delete_playlist(self, name):
         """Delete a :class:`hooke.playlist.Playlist` by name.
 
-        Called by the :meth:`_on_delete` handler.
-
-        Removes the playlist and its curves from the tree, then calls
-        :meth:`_delete_playlist`.
+        Called by the :meth:`_on_delete` handler.  Calls the
+        approptiate interface callback.
         """
         _id = self._id_for_name[name]
-        self.Delete(_id)
         playlist = self._playlists[name]
-        self._delete_playlist(playlist)
         in_callback(self, playlist)
 
-    def _delete_playlist(self, playlist):
-        """Adjust name/id caches for the playlist and its curves.
+    def delete_playlist(self, playlist):
+        """Respond to playlist deletion.
 
         Called on *every* playlist deletion.
         """
         self._playlists.pop(playlist.name)
         _id = self._id_for_name.pop(playlist.name)
+        self.Delete(_id)
         del(self._name_for_id[_id])
         for curve in playlist:
             self._delete_curve(playlist, curve)
-        in_callback(self, playlist)
 
-    def delete_curve(self, playlist_name, name):
+    def _delete_curve(self, playlist_name, name):
         """Delete a :class:`hooke.curve.Curve` by name.
 
-        Called by the :meth:`_on_delete` handler.
-
-        Removes the curve from the tree, then calls
-        :meth:`_delete_curve`.
+        Called by the :meth:`_on_delete` handler.  Calls the
+        approptiate interface callback.
         """
         _id = self._id_for_name[(playlist_name, name)]
-        self.Delete(_id)
         playlist = self._playlists[playlist_name]
         curve = None
         for i,c in enumerate(playlist):
             if c.name == name:
                 curve = c
                 break
-        self._delete_curve(playlist, curve)
+        if curve is None:
+            raise ValueError(name)
         in_callback(self, playlist, curve)
 
-    def _delete_curve(self, playlist, curve):
-        """Adjust name/id caches.
+    def delete_curve(self, playlist_name, name):
+        """Respond to curve deletions.
 
-        Called on _every_ curve deletion.
+        Called on *every* curve deletion.
         """
-        _id = self._id_for_name.pop((playlist.name, curve.name))
+        _id = self._id_for_name.pop((playlist_name, name))
+        self.Delete(_id)
         del(self._name_for_id[_id])
-        in_callback(self, playlist, curve)
 
     # Get selection
 
@@ -334,15 +326,11 @@ class Tree (wx.TreeCtrl):
         """Absorb changed `.index()`, etc.
         """
         self._playlists[playlist.name] = playlist
-        cnames = []
+        cnames = set()
         for curve in playlist:
             if (playlist.name, curve.name) not in self._id_for_name:
                 self._add_curve(playlist.name, curve)
-            cnames.append(curve.name)
-        dc = self._callbacks['delete_curve']
-        _dc = self._callbacks['_delete_curve']
-        self._callbacks['delete_curve'] = None
-        self._callbacks['_delete_curve'] = None
+            cnames.add(curve.name)
         for name in self._id_for_name.keys():
             if not self._is_curve(name):
                 continue
@@ -350,9 +338,7 @@ class Tree (wx.TreeCtrl):
             if pname != playlist.name:
                 continue
             if cname not in cnames:
-                self.delete_curve(playlist.name, cname)
-        self._callbacks['delete_curve'] = dc
-        self._callbacks['_delete_curve'] = _dc
+                self.delete_curve(playlist_name=pname, name=cname)
 
     def is_playlist_loaded(self, playlist):
         """Return `True` if `playlist` is loaded, `False` otherwise.