Maemo 5: Fix window and button layout (Maemo bug 11499)
[gpodder.git] / src / gpodder / gtkui / frmntl / widgets.py
blob0867b6d1dc5744e0561179a20d9db8287615004d
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 import gtk
21 import hildon
22 import gobject
24 class EditToolbarDeluxe(hildon.EditToolbar):
25 """HildonEditToolbar with sensitivity and AppMenu action
27 * Public method to set the button sensitivity
28 * Open the parent window's AppMenu when touching titlebar
30 (Enhancement requests filed as Maemo bugs #5166 and #5167)
31 """
32 def __init__(self, label_text, button_text):
33 hildon.EditToolbar.__init__(self, label_text, button_text)
35 alignment, separator, close_button = self.get_children()
36 hbox = alignment.get_child()
37 label, image, button = hbox.get_children()
38 self._action_button = button
40 expand, fill, padding, pack_type = hbox.query_child_packing(label)
41 event_box = gtk.EventBox()
42 event_box.connect('expose-event', self._on_expose_event)
43 label.reparent(event_box)
44 event_box.connect('button-release-event', self._on_label_clicked)
45 hbox.add(event_box)
46 hbox.reorder_child(event_box, 0)
47 hbox.set_child_packing(event_box, expand, fill, padding, pack_type)
48 self._label = label
50 def set_button_sensitive(self, sensitivity):
51 self._action_button.set_sensitive(sensitivity)
53 def _on_expose_event(self, widget, event):
54 # Based on hildon_edit_toolbar_expose() in hildon-edit-toolbar.c
55 # in order to get the same style background for the EventBox widget
56 style = self.get_style()
57 style.paint_flat_box(widget.window, \
58 gtk.STATE_NORMAL, \
59 gtk.SHADOW_NONE, \
60 event.area, widget, 'edit-toolbar', \
61 0, 0, \
62 widget.allocation.width, widget.allocation.height)
63 # Propagate the expose event to the child (our label)
64 child = widget.get_child()
65 widget.propagate_expose(child, event)
66 return True
68 def _on_label_clicked(self, widget, event):
69 parent = self.get_parent()
70 app_menu = parent.get_app_menu()
71 if app_menu is not None:
72 app_menu.popup(parent)
75 class FancyProgressBar(object):
76 """An animated progress bar with cancel button (bling bling!)
78 This is a helper class coordinating some widgets that are needed for the
79 feed update progress bar. It takes care of hooking up and resizing an event
80 box (to be used in the main window), of creating the progress bar and
81 cancel button widgets and of controlling the show/hide animation as well
82 as reacting to the click on the cancel button (by means of the event box).
84 In short, this provides all the necessary hooks to create a nice, sliding
85 progress bar using hildon.AnimationActor while hiding the plumbing.
87 Usage:
89 Create a new object, where parent is the hildon.StackableWindow on which
90 this progress bar should be shown. The on_cancel should be a callback with
91 one parameter (will be the FancyProgressBar instance from which it is
92 called) or None. It will be called when the cancel button is clicked.
94 The using code should then take the "event_box" attribute and place it at
95 the bottom of the parent window (e.g. as last item in a gtk.VBox). After
96 that, calling "show()" and "hide()" will take care of hiding and showing
97 both the "contents" (progress bar) and the event box. The contents will be
98 slided in and out using a nice animation.
100 You can get the progress bar from the "progress_bar" attribute and use it
101 in your code to update the contents (it's a simple gtk.ProgressBar object).
104 SHOW, HIDE = range(2)
105 FREMANTLE_TITLE_BAR_SIZE = 56
106 STEP = 10
108 def __init__(self, parent, on_cancel=None):
109 self.parent = parent
110 self.on_cancel = on_cancel
111 self.state = FancyProgressBar.HIDE
112 self.offset = float(1)
114 self.progress_bar = gtk.ProgressBar()
115 image = gtk.image_new_from_icon_name('general_stop', \
116 gtk.ICON_SIZE_LARGE_TOOLBAR)
117 self.cancel_button = gtk.ToolButton(image)
118 self.hbox_animation_actor = gtk.HBox()
119 self.hbox_inner = gtk.HBox()
120 self.hbox_animation_actor.pack_start(self.hbox_inner)
121 self.hbox_animation_actor.child_set(self.hbox_inner, 'padding', 12)
122 self.hbox_inner.pack_start(self.progress_bar)
123 self.hbox_inner.pack_start(self.cancel_button, False)
124 self.animation_actor = hildon.AnimationActor()
125 self.animation_actor.set_parent(self.parent)
126 self.animation_actor.add(self.hbox_animation_actor)
127 self.animation_actor.show_all()
128 self.height, self.width = self.cancel_button.size_request()
129 self.event_box = gtk.EventBox()
130 self.event_box.connect('button-release-event', self.on_button_release)
131 self.event_box.set_size_request(-1, self.height)
132 self.offset = float(self.height)
133 self.relayout()
135 def on_button_release(self, widget, event):
136 if event.x > self.cancel_button.get_allocation().x:
137 if self.on_cancel is not None:
138 self.on_cancel(self)
140 def relayout(self):
141 width, height = self.parent.get_size()
142 self.animation_actor.resize(width, self.height)
143 x, y = 0, FancyProgressBar.FREMANTLE_TITLE_BAR_SIZE
144 y += height + int(self.offset)
145 y -= self.height
146 self.animation_actor.set_position(x, y)
147 return False
149 def show(self):
150 if self.state != FancyProgressBar.SHOW:
151 self.state = FancyProgressBar.SHOW
152 self.hbox_animation_actor.show()
153 self.offset = float(self.height)
154 gobject.timeout_add(FancyProgressBar.STEP, self.on_timeout)
156 def hide(self):
157 if self.state != FancyProgressBar.HIDE:
158 self.event_box.hide()
159 self.state = FancyProgressBar.HIDE
160 self.offset = float(1.)
161 gobject.timeout_add(FancyProgressBar.STEP, self.on_timeout)
163 def on_timeout(self):
164 result = True
166 if self.state == FancyProgressBar.SHOW:
167 self.offset *= .9
168 if self.offset < 2:
169 self.event_box.show()
170 self.offset = 0.
171 result = False
172 elif self.state == FancyProgressBar.HIDE:
173 self.offset *= 1.1
174 if self.offset >= self.height:
175 self.offset = float(self.height)
176 self.hbox_animation_actor.hide()
177 result = False
179 self.relayout()
181 return result