From d45bf8d6f99129e1ca529cfa3b5bbc160e18f2e9 Mon Sep 17 00:00:00 2001 From: clobo Date: Thu, 10 Jul 2014 15:56:29 -0400 Subject: [PATCH 1/8] Can set the position of the drop-down panel by setting the side_panel_positioning property to left, right, top or bottom. --- __init__.py | 103 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/__init__.py b/__init__.py index 212e351..5bd2788 100644 --- a/__init__.py +++ b/__init__.py @@ -155,14 +155,23 @@ def set_anim_type(name): _main_panel: mainpanel _join_image: joinimage side_panel_width: min(dp(250), 0.5*self.width) + _anim_direction: -1 if root.side_panel_positioning in ['top', 'right'] else 1 + _side_panel_offset_x: root.width - sidepanel.width if root.side_panel_positioning == 'right' else 0 + _side_panel_offset_y: root.height - sidepanel.height if root.side_panel_positioning == 'top' else 0 + BoxLayout: id: sidepanel - y: root.y - x: root.x - \ - (1-root._anim_progress)* \ - root.side_panel_init_offset*root.side_panel_width - height: root.height - width: root.side_panel_width + y: root.y + root._side_panel_offset_y - root._anim_direction * (1-root._anim_progress)* \ + root.side_panel_init_offset*root.side_panel_width if root.side_panel_positioning in ['bottom', 'top'] \ + else root.y + + x: root.x + root._side_panel_offset_x - root._anim_direction * (1-root._anim_progress)* \ + root.side_panel_init_offset*root.side_panel_width if root.side_panel_positioning in ['right', 'left'] else \ + root.x + opacity: root.side_panel_opacity + \ + (1-root.side_panel_opacity)*root._anim_progress + height: root.height if root.side_panel_positioning in ['right', 'left'] else root.side_panel_width + width: root.side_panel_width if root.side_panel_positioning in ['right', 'left'] else root.width opacity: root.side_panel_opacity + \ (1-root.side_panel_opacity)*root._anim_progress canvas: @@ -179,11 +188,14 @@ def set_anim_type(name): pos: self.pos BoxLayout: id: mainpanel - x: root.x + \ - root._anim_progress * \ - root.side_panel_width * \ - root.main_panel_final_offset - y: root.y + x: root.x + root._anim_direction *\ + root._anim_progress * \ + root.side_panel_width * \ + root.main_panel_final_offset if root.side_panel_positioning in ['right', 'left'] else root.x + y: root.y + root._anim_direction * root._anim_progress * \ + root.side_panel_width * root.main_panel_final_offset if root.side_panel_positioning in ['bottom', 'top'] \ + else root.y + size: root.size canvas: Color: @@ -203,13 +215,24 @@ def set_anim_type(name): else min(root._anim_progress*40,1)) source: root._choose_image(root._main_above, root.separator_image) mipmap: False + _w: root.width if root.side_panel_positioning == 'right' else 0 + _h: root.height if root.side_panel_positioning == 'top' else 0 width: root.separator_image_width - height: root._side_panel.height - x: (mainpanel.x - self.width + 1) if root._main_above \ - else (sidepanel.x + sidepanel.width - 1) - y: root.y + height: root._side_panel.height if root.side_panel_positioning in ['left', 'right'] else root._side_panel.width + x: mainpanel.x + self._w if root.side_panel_positioning in ['left', 'right'] else \ + root.center_x + y: self._h + mainpanel.y - self.height / 2. if root.side_panel_positioning in ['bottom', 'top'] else \ + 0 allow_stretch: True keep_ratio: False + canvas.before: + PushMatrix + Rotate: + angle: 90 if root.side_panel_positioning in ['bottom', 'top'] else 0 + origin: self.center + canvas: + PopMatrix + ''') @@ -292,6 +315,10 @@ class NavigationDrawer(StencilView): '''Controls the opacity of the side panel in its hidden state. Must be between 0 (fade to transparent) and 1 (no transparency)''' + side_panel_positioning = StringProperty('left') + '''Controlls the screen edge in which the side panel is pulled from. + Must be either 'left', 'right', 'top' or 'bottom' ''' + main_panel_final_offset = NumericProperty(1) '''Final offset (to the right of the normal position) of the main panel, in units of the side panel width.''' @@ -502,11 +529,30 @@ def on_touch_down(self, touch): col_self = self.collide_point(*touch.pos) col_side = self._side_panel.collide_point(*touch.pos) col_main = self._main_panel.collide_point(*touch.pos) - + pan_pos = self.side_panel_positioning + d = 1 + if pan_pos in ['left', 'right']: + edge = self.x + pt = touch.x + if pan_pos == 'right': + edge += self.width + d = -1 + else: + pt = touch.y + edge = self.y + if pan_pos == 'top': + edge += self.height + d = -1 if self._anim_progress < 0.001: # i.e. closed - valid_region = (self.x <= - touch.x <= - (self.x + self.touch_accept_width)) + + if pan_pos in ['top', 'right']: + valid_region = (edge >= + pt >= + (edge + d * self.touch_accept_width)) + else: + valid_region = (edge <= + pt <= + (edge + d * self.touch_accept_width)) if not valid_region: self._main_panel.on_touch_down(touch) return False @@ -541,9 +587,12 @@ def on_touch_down(self, touch): def on_touch_move(self, touch): if touch is self._touch: - dx = touch.x - touch.ox + pan_pos = self.side_panel_positioning + di = touch.x - touch.ox if pan_pos in ['left', 'right'] else touch.y - touch.oy + if pan_pos in ['right', 'top']: + di *= -1 self._anim_progress = max(0, min(self._anim_init_progress + - (dx / self.side_panel_width), 1)) + (di / self.side_panel_width), 1)) if self._anim_progress < 0.975: touch.ud['panels_jiggled'] = True else: @@ -637,6 +686,15 @@ def set_transition(name): navigationdrawer.opening_transition = name navigationdrawer.closing_transition = name + def change_side(*args): + options = ['left', 'top', 'right'] + i = options.index(navigationdrawer.side_panel_positioning) + i += 1 + if i > 2: + i = 0 + navigationdrawer.side_panel_positioning = options[i] + button4.text = options[i].capitalize() + modes_layout = BoxLayout(orientation='horizontal') modes_layout.add_widget(Label(text='preset\nanims:')) slide_an = Button(text='slide_\nabove_\nanim') @@ -686,9 +744,12 @@ def set_transition(name): button2.bind(on_press=lambda j: navigationdrawer.toggle_state(False)) button3 = Button(text='toggle _main_above', size_hint_y=0.2) button3.bind(on_press=navigationdrawer.toggle_main_above) + button4 = Button(text='Panel Side: Left', size_hint_y=0.2) + button4.bind(on_press=change_side) main_panel.add_widget(button) main_panel.add_widget(button2) main_panel.add_widget(button3) + main_panel.add_widget(button4) Window.add_widget(navigationdrawer) From cfcd011669795c170b50dfd9a49b1852e09a698a Mon Sep 17 00:00:00 2001 From: clobo Date: Thu, 10 Jul 2014 16:06:27 -0400 Subject: [PATCH 2/8] fixed issue were buttons in top menu were inaccessible. --- __init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/__init__.py b/__init__.py index 5bd2788..60b1742 100644 --- a/__init__.py +++ b/__init__.py @@ -544,15 +544,10 @@ def on_touch_down(self, touch): edge += self.height d = -1 if self._anim_progress < 0.001: # i.e. closed - if pan_pos in ['top', 'right']: - valid_region = (edge >= - pt >= - (edge + d * self.touch_accept_width)) + valid_region = (edge >= pt >= (edge + d * self.touch_accept_width)) else: - valid_region = (edge <= - pt <= - (edge + d * self.touch_accept_width)) + valid_region = (edge <= pt <= (edge + d * self.touch_accept_width)) if not valid_region: self._main_panel.on_touch_down(touch) return False @@ -560,9 +555,12 @@ def on_touch_down(self, touch): if col_side and not self._main_above: self._side_panel.on_touch_down(touch) return False - valid_region = (self._main_panel.x <= - touch.x <= - (self._main_panel.x + self._main_panel.width)) + if pan_pos in ['left', 'right']: + s = self._main_panel.x, self._main_panel.x + self._main_panel.width + else: + s = self._main_panel.y, self._main_panel.y + self._main_panel.height + + valid_region = (s[0] <= pt <= s[1]) if not valid_region: if self._main_above: if col_main: From 612bc196df318f785a73e47f67d971ac1929e4fd Mon Sep 17 00:00:00 2001 From: clobo Date: Fri, 11 Jul 2014 08:37:48 -0400 Subject: [PATCH 3/8] Exception raised when side_panel_positioning is not one of the four acceptable options. --- __init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/__init__.py b/__init__.py index 60b1742..3e26171 100644 --- a/__init__.py +++ b/__init__.py @@ -355,6 +355,18 @@ def __init__(self, **kwargs): super(NavigationDrawer, self).__init__(**kwargs) Clock.schedule_once(self.on__main_above, 0) + def on_side_panel_positioning(self, *args): + spp = self.side_panel_positioning.lower() + if spp == 'bot': + spp = 'bottom' + if spp in ['left', 'right', 'top', 'bottom']: + self.side_panel_positioning = spp + else: + raise AttributeError("Property side_panel_positioning accepts only 'left', 'right', 'top', 'bottom'") + + + + def on_anim_type(self, *args): anim_type = self.anim_type if anim_type == 'slide_above_anim': From 3b30780baef9bd266e25179f6948f520206d911f Mon Sep 17 00:00:00 2001 From: clobo Date: Mon, 14 Jul 2014 07:49:48 -0400 Subject: [PATCH 4/8] fixed small offset issue with joinimage on top and bottom. --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index 3e26171..e9d754e 100644 --- a/__init__.py +++ b/__init__.py @@ -220,7 +220,7 @@ def set_anim_type(name): width: root.separator_image_width height: root._side_panel.height if root.side_panel_positioning in ['left', 'right'] else root._side_panel.width x: mainpanel.x + self._w if root.side_panel_positioning in ['left', 'right'] else \ - root.center_x + root.center_x - self.width / 2. y: self._h + mainpanel.y - self.height / 2. if root.side_panel_positioning in ['bottom', 'top'] else \ 0 allow_stretch: True From 6a4569b654a72bab42f383cbe8ce17b073ab098a Mon Sep 17 00:00:00 2001 From: clobo Date: Mon, 14 Jul 2014 08:32:47 -0400 Subject: [PATCH 5/8] fixed issue with joinimage gradient facing wrong way on right panel --- __init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/__init__.py b/__init__.py index e9d754e..1b7210c 100644 --- a/__init__.py +++ b/__init__.py @@ -219,8 +219,8 @@ def set_anim_type(name): _h: root.height if root.side_panel_positioning == 'top' else 0 width: root.separator_image_width height: root._side_panel.height if root.side_panel_positioning in ['left', 'right'] else root._side_panel.width - x: mainpanel.x + self._w if root.side_panel_positioning in ['left', 'right'] else \ - root.center_x - self.width / 2. + center_x: sidepanel.center_x + root._anim_direction * (sidepanel.width - self.width) / 2. if root.side_panel_positioning in ['left', 'right'] else \ + root.center_x y: self._h + mainpanel.y - self.height / 2. if root.side_panel_positioning in ['bottom', 'top'] else \ 0 allow_stretch: True @@ -228,7 +228,7 @@ def set_anim_type(name): canvas.before: PushMatrix Rotate: - angle: 90 if root.side_panel_positioning in ['bottom', 'top'] else 0 + angle: 90 * ['left', 'top', 'right', 'bottom'].index(root.side_panel_positioning) #self._r if root.side_panel_positioning in ['bottom', 'top'] else 0 origin: self.center canvas: PopMatrix From 50fcee4dc41410d705dfb2dbaea09745a210962e Mon Sep 17 00:00:00 2001 From: clobo Date: Mon, 14 Jul 2014 13:43:45 -0400 Subject: [PATCH 6/8] fixed issue with joinimage positioning --- __init__.py | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/__init__.py b/__init__.py index 1b7210c..dbaec54 100644 --- a/__init__.py +++ b/__init__.py @@ -219,17 +219,37 @@ def set_anim_type(name): _h: root.height if root.side_panel_positioning == 'top' else 0 width: root.separator_image_width height: root._side_panel.height if root.side_panel_positioning in ['left', 'right'] else root._side_panel.width - center_x: sidepanel.center_x + root._anim_direction * (sidepanel.width - self.width) / 2. if root.side_panel_positioning in ['left', 'right'] else \ - root.center_x - y: self._h + mainpanel.y - self.height / 2. if root.side_panel_positioning in ['bottom', 'top'] else \ - 0 + _left_x: (mainpanel.x - self.width + 1) if root._main_above \ + else (sidepanel.right - 1) + _right_x: (mainpanel.right - self.width - 1 ) if root._main_above \ + else (sidepanel.x - 2 * self.width) + + _top_y: (mainpanel.top + self.width / 2.) if root._main_above \ + else (sidepanel.y - self.width / 2.) + + _bottom_y: (mainpanel.y - self.width / 2.) if root._main_above \ + else (sidepanel.top + self.width / 2.) + x: self._left_x if root.side_panel_positioning == 'left' else self._right_x \ + if root.side_panel_positioning in ['left', 'right'] else root.center_x - self.width / 2. + y: self._top_y if root.side_panel_positioning == 'top' else self._bottom_y \ + if root.side_panel_positioning in ['bottom', 'top'] else root.y allow_stretch: True keep_ratio: False canvas.before: PushMatrix Rotate: - angle: 90 * ['left', 'top', 'right', 'bottom'].index(root.side_panel_positioning) #self._r if root.side_panel_positioning in ['bottom', 'top'] else 0 + angle: 90 * ['left', 'bottom', 'right', 'top'].index(root.side_panel_positioning) #self._r \ + if root.side_panel_positioning in ['bottom', 'top'] else 0 origin: self.center + # Translate to center the width of the image + Translate: + x: -self.width if root.side_panel_positioning == 'right' else 0 + y: self.width if root.side_panel_positioning == 'right' else 0 + # Translate to compensate for the rotation + Translate: + x: self.height / 2. if root.side_panel_positioning == 'top' else -self.height / 2. \ + if root.side_panel_positioning in ['bottom', 'top'] else 0 + canvas: PopMatrix @@ -364,9 +384,6 @@ def on_side_panel_positioning(self, *args): else: raise AttributeError("Property side_panel_positioning accepts only 'left', 'right', 'top', 'bottom'") - - - def on_anim_type(self, *args): anim_type = self.anim_type if anim_type == 'slide_above_anim': @@ -658,7 +675,7 @@ def _choose_image(self, *args): navigationdrawer = NavigationDrawer() side_panel = BoxLayout(orientation='vertical') - side_panel.add_widget(Label(text='Panel label')) + side_panel.add_widget(Button(text='Panel label')) popup = Popup(title='Sidebar popup', content=Label( text='You clicked the sidebar\npopup button'), @@ -697,14 +714,19 @@ def set_transition(name): navigationdrawer.closing_transition = name def change_side(*args): - options = ['left', 'top', 'right'] + options = ['left', 'top', 'right', 'bottom'] i = options.index(navigationdrawer.side_panel_positioning) i += 1 - if i > 2: + if i > 3: i = 0 navigationdrawer.side_panel_positioning = options[i] button4.text = options[i].capitalize() + def toggle_main_above(*args): + navigationdrawer.toggle_main_above() + button3.text = 'Main above: {0}'.format(navigationdrawer._main_above) + + modes_layout = BoxLayout(orientation='horizontal') modes_layout.add_widget(Label(text='preset\nanims:')) slide_an = Button(text='slide_\nabove_\nanim') @@ -753,13 +775,14 @@ def change_side(*args): size_hint_y=0.2) button2.bind(on_press=lambda j: navigationdrawer.toggle_state(False)) button3 = Button(text='toggle _main_above', size_hint_y=0.2) - button3.bind(on_press=navigationdrawer.toggle_main_above) + button3.bind(on_press=toggle_main_above) button4 = Button(text='Panel Side: Left', size_hint_y=0.2) button4.bind(on_press=change_side) main_panel.add_widget(button) main_panel.add_widget(button2) main_panel.add_widget(button3) main_panel.add_widget(button4) + main_panel.add_widget(Label(size_hint_y=0.05)) Window.add_widget(navigationdrawer) From 932602a942609365d76e033f99a231ca329358ca Mon Sep 17 00:00:00 2001 From: clobo Date: Mon, 14 Jul 2014 14:07:05 -0400 Subject: [PATCH 7/8] added main_above state to button text --- __init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index dbaec54..a594011 100644 --- a/__init__.py +++ b/__init__.py @@ -774,7 +774,7 @@ def toggle_main_above(*args): button2 = Button(text='toggle NavigationDrawer state (jump)', size_hint_y=0.2) button2.bind(on_press=lambda j: navigationdrawer.toggle_state(False)) - button3 = Button(text='toggle _main_above', size_hint_y=0.2) + button3 = Button(text='toggle _main_above: {}'.format(navigationdrawer._main_above), size_hint_y=0.2) button3.bind(on_press=toggle_main_above) button4 = Button(text='Panel Side: Left', size_hint_y=0.2) button4.bind(on_press=change_side) From ec63a1991a12d02553785a693963f4a444ff7ebd Mon Sep 17 00:00:00 2001 From: clobo Date: Wed, 16 Jul 2014 09:34:33 -0400 Subject: [PATCH 8/8] fixed side_panel_width to represent min of 250dp and half the panel_positioning dimension --- __init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index a594011..add2335 100644 --- a/__init__.py +++ b/__init__.py @@ -154,7 +154,8 @@ def set_anim_type(name): _side_panel: sidepanel _main_panel: mainpanel _join_image: joinimage - side_panel_width: min(dp(250), 0.5*self.width) + side_panel_width: min(dp(250), 0.5 * self.width) if root.side_panel_positioning in ['left', 'right'] else \ + min(dp(250), 0.5 * self.height) _anim_direction: -1 if root.side_panel_positioning in ['top', 'right'] else 1 _side_panel_offset_x: root.width - sidepanel.width if root.side_panel_positioning == 'right' else 0 _side_panel_offset_y: root.height - sidepanel.height if root.side_panel_positioning == 'top' else 0