Samuel- This is a very large patch, which makes it difficult to truly review well. I've asked lots of questions, and hope that through those questions, you might be able to evaluate the implementation from another viewpoint, and discover issues on your own. I'm not going to vote just yet, as I'm curious to hear your response to my review. > === modified file 'entertainerlib/frontend/gui/screens/main.py' > --- entertainerlib/frontend/gui/screens/main.py 2009-04-17 21:02:35 +0000 > +++ entertainerlib/frontend/gui/screens/main.py 2009-04-25 23:30:15 +0000 > @@ -47,16 +47,55 @@ class Main(Screen): > self.preview.set_opacity(0x00) > self.add(self.preview) > > - self.active_menu = "main" > self.rss_preview_menu = self._create_rss_preview_menu() > self.preview.add(self.rss_preview_menu) > > - self.menu = None > - self.playing_item = None > - self.create_main_menu() > + self.menu = self._create_main_menu() > + self.add(self.menu) > + self.menu.connect('selected', self._on_menu_selected) > + self.menu.connect('moved', self._on_menu_moved) > + self.menu.connect('activated', self._main_menu_activation) > + self.menu.active = True > + > + self.add(ClockLabel(0.13, "screentitle", 0, 0.87)) > + This makes me a bit queesy. Why are you creating an instance variable, and then calling an instance method on that instance variable. What does self.add do? Why are we calling it? If it is required (and I'm concerned it isn't), self._create_main_menu should be calling self.add(). Also, _create_main_menu should be doing all the self.menu.connect type stuff. Also, I see the clock got moved here instead of the _create_main_menu code. Why? > + def get_type(self): > + """Return screen type.""" > + return Screen.NORMAL > + > + def get_name(self): > + """Return screen name (human readble)""" > + return "Main" > + I've seen this convention a few times. What are we using get_name for? Is there a better way to handle this than using a string? I'd like some answers about this, because I thought Joshua had eliminated the need for this code. Also, it seems that type and name would be better as properties. They never change dynamically, so making them instance properties is a good idea. If type or name had the ability to change within the life of the instance, we would use accessors, but that's more for convention than anything. In this case though, there isn't even a need for defining a function. This code could be simplified to: type = Screen.NORMAL name = "Main" > @@ -206,42 +200,23 @@ class Main(Screen): > > return preview > > - def get_type(self): > - """Return screen type.""" > - return Screen.NORMAL > - > - def get_name(self): > - """Return screen name (human readble)""" > - return "Main" > - > - def update(self): > - """ > - Update screen widgets. This is called always when screen is poped from > - the screen history. Updates main menu widget. > - """ > - selected_name = self.menu.get_selected().get_name() > - > - self.remove(self.menu) > - self.create_main_menu() > - > - index = self.menu.get_index(selected_name) > - if not index == -1: > - self.menu.select(index) > - > - self.menu.update() > - > - self._update_preview_area(self.menu.get_selected()) > - > - def _update_preview_area(self, item): > + def _update_preview_area(self): > '''Update the preview area to display the current menu item.''' > self.preview.remove_all() > + item = self.menu.get_selected() > + > self.preview.set_opacity(0x00) > > update = True > + > if item.get_name() == "playing": > self.preview.add(self._create_playing_preview()) > elif item.get_name() == "rss": > self.preview.add(self._create_rss_preview()) > + # when we update the rss preview menu, we must set it active if > + # main menu is not > + if not self.menu.active: > + self.rss_preview_menu.set_active(True) > else: > update = False > The comment here needs to start with a capital letter and end with a full stop. > @@ -253,61 +228,51 @@ class Main(Screen): > self.behaviour.apply(self.preview) > fade_in.start() > > - def _move_menu(self, menu_direction): > - '''Move the menu in the given direction.''' > - > - if menu_direction == self.UP: > - scroll_direction = self.menu.scroll_down > - preview_direction = TextMenu.UP > - elif menu_direction == self.DOWN: > - scroll_direction = self.menu.scroll_up > - preview_direction = TextMenu.DOWN > - > - if self.active_menu == "main": > - scroll_direction() > - selected = self.menu.get_selected() > - if selected.get_name() == None: > - scroll_direction() > - selected = self.menu.get_selected() > - self._update_preview_area(selected) > + def _can_move_horizontally(self): > + '''Return a boolean indicating if horizontal movement is allowed.''' > + item = self.menu.get_selected() > + if self.feed_library.is_empty() or item.get_name() != 'rss': > + return False > else: > - self.rss_preview_menu.move(preview_direction) > + return True > + > + def update(self): > + """ > + Update screen widgets. This is called always when screen is poped from > + the screen history. Updates main menu widget. > + """ > + if self.media_player.is_playing() and \ > + (self.menu.get_index("playing") == -1): > + self.menu.add_item(_("Playing now..."), "playing") > + elif not self.media_player.is_playing() and \ > + (self.menu.get_index("playing") != -1): > + self.menu.remove_item("playing") > + > + self.menu.refresh() > + self._update_preview_area() > This docstring needs to be consistent with the rest of our new docstrings. It needs to read like this: """Single line that describes the function. Optional details on how the method works. """ > === added file 'entertainerlib/frontend/gui/widgets/motion_buffer.py' > --- entertainerlib/frontend/gui/widgets/motion_buffer.py 1970-01-01 00:00:00 +0000 > +++ entertainerlib/frontend/gui/widgets/motion_buffer.py 2009-04-25 23:30:15 +0000 > @@ -0,0 +1,137 @@ > +"""Tools for pointer motion calculations""" > + > +__licence__ = "GPLv2" > +__copyright__ = "2009, Samuel Buffet" > +__author__ = "Samuel Buffet