2007-08-14 18:10:53 -07:00
|
|
|
import clutter
|
|
|
|
from SkinMgr import SkinMgr
|
|
|
|
from Spinner import Spinner
|
|
|
|
import pygtk
|
|
|
|
import gtk
|
2007-11-22 02:41:29 -08:00
|
|
|
import pango
|
2007-08-14 18:10:53 -07:00
|
|
|
|
2007-08-14 19:08:46 -07:00
|
|
|
class MenuMgr:
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
def __init__ (self, stage):
|
|
|
|
self.stage = stage
|
|
|
|
self.menus = []
|
2007-08-19 05:29:56 -07:00
|
|
|
self.menuHistory = [] #A list that contains menus in the order that they've been viewed
|
2007-08-14 18:10:53 -07:00
|
|
|
self.currentMenu = None
|
2007-11-22 02:41:29 -08:00
|
|
|
self.uiMsg = message(stage)
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
self.skinMgr = SkinMgr(self.stage)
|
|
|
|
background = self.skinMgr.get_Background()
|
|
|
|
self.stage.add(background)
|
|
|
|
|
|
|
|
self.selector_bar = MenuSelector(self)
|
|
|
|
self.stage.add(self.selector_bar)
|
|
|
|
self.selector_bar.show_all()
|
|
|
|
self.currentPlugin = None
|
|
|
|
|
|
|
|
def addMenu(self, newMenu):
|
|
|
|
self.menus.append(newMenu)
|
|
|
|
|
|
|
|
#If this is the first menu, make it the active one
|
|
|
|
if self.currentMenu == None:
|
|
|
|
self.currentMenu = newMenu
|
2007-08-19 05:29:56 -07:00
|
|
|
self.menuHistory.append(newMenu)
|
2007-08-14 18:10:53 -07:00
|
|
|
self.currentMenu.getItemGroup().show_all()
|
|
|
|
self.currentMenu.getMenuGroup().show_all()
|
|
|
|
self.selector_bar.set_menu(self.currentMenu)
|
|
|
|
|
|
|
|
def get_selector_bar(self):
|
|
|
|
return self.selector_bar
|
|
|
|
|
|
|
|
def get_stage(self):
|
|
|
|
return self.stage
|
|
|
|
|
|
|
|
def get_skinMgr(self):
|
|
|
|
return self.skinMgr
|
|
|
|
|
|
|
|
def transition_fade_zoom(self, fromMenu, toMenu):
|
|
|
|
oldGroup = fromMenu.getItemGroup()
|
|
|
|
oldMenuGroup = fromMenu.getMenuGroup()
|
|
|
|
newGroup = toMenu.getItemGroup()
|
|
|
|
newMenuGroup = toMenu.getMenuGroup()
|
|
|
|
|
|
|
|
oldGroup.set_opacity(255)
|
|
|
|
|
|
|
|
self.timeline = clutter.Timeline(25, 50)
|
|
|
|
self.alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
|
|
|
#self.exit_behaviour_scale = clutter.BehaviourScale(self.alpha, 1, 0.5, clutter.GRAVITY_CENTER)
|
|
|
|
self.exit_behaviour_opacity = clutter.BehaviourOpacity(self.alpha, 150, 0)
|
|
|
|
|
|
|
|
#Setup some knots
|
|
|
|
knots_exiting = (\
|
|
|
|
(oldGroup.get_x(), oldGroup.get_y()),\
|
|
|
|
#(-oldGroup.get_x(), int(fromMenu.getStage().get_height()/2))
|
|
|
|
(-oldGroup.get_x(), oldGroup.get_y())\
|
|
|
|
)
|
|
|
|
self.exit_behaviour_path = clutter.BehaviourPath(self.alpha, knots_exiting)
|
|
|
|
|
|
|
|
#self.exit_behaviour_scale.apply(oldGroup)
|
|
|
|
self.exit_behaviour_opacity.apply(oldGroup)
|
|
|
|
self.exit_behaviour_opacity.apply(oldMenuGroup)
|
|
|
|
self.exit_behaviour_path.apply(oldGroup)
|
|
|
|
|
|
|
|
|
|
|
|
##################################################################
|
|
|
|
#Start incoming menu
|
|
|
|
#self.exit_behaviour_scale = clutter.BehaviourScale(self.alpha, 1, 0.5, clutter.GRAVITY_CENTER)
|
|
|
|
self.entrance_behaviour_opacity = clutter.BehaviourOpacity(self.alpha, 0, 255)
|
|
|
|
|
|
|
|
#Setup some knots
|
|
|
|
start_y = int(self.stage.get_height()/2 - newGroup.get_height()/2)
|
|
|
|
start_x = int(self.stage.get_width())
|
|
|
|
newGroup.set_position(start_x, start_y)
|
|
|
|
#end_x = int(self.stage.get_width() - newGroup.get_width())/2
|
|
|
|
(end_x, end_y) = toMenu.get_display_position()
|
|
|
|
end_x = oldGroup.get_x() #int(end_x)
|
|
|
|
end_y = oldGroup.get_y() #int(end_y)
|
|
|
|
knots_entering = (\
|
|
|
|
(newGroup.get_x(), newGroup.get_y()),\
|
|
|
|
#(-oldGroup.get_x(), int(fromMenu.getStage().get_height()/2))
|
|
|
|
(end_x, end_y) \
|
|
|
|
#toMenu.get_display_position()
|
|
|
|
)
|
|
|
|
|
|
|
|
self.entrance_behaviour_path = clutter.BehaviourPath(self.alpha, knots_entering)
|
|
|
|
|
|
|
|
self.entrance_behaviour_opacity.apply(newGroup)
|
|
|
|
self.entrance_behaviour_opacity.apply(newMenuGroup)
|
2007-08-17 16:18:17 -07:00
|
|
|
self.entrance_behaviour_path.apply(newGroup)
|
2007-08-17 03:45:09 -07:00
|
|
|
#newGroup.show_all()
|
|
|
|
#newMenuGroup.show_all()
|
|
|
|
toMenu.display()
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
#Finally, move the selector bar
|
|
|
|
self.selector_bar.selectItem(fromMenu.getItem(0), self.timeline)
|
|
|
|
#(to_x, to_y) = toMenu.get_display_position() #fromMenu.getItem(0).get_abs_position()
|
|
|
|
#self.selector_bar.move_to(int(to_x), int(to_y), self.timeline)
|
|
|
|
toMenu.selectFirst(False)
|
|
|
|
|
|
|
|
#self.timeline.connect('completed', self.on_transition_complete)
|
|
|
|
self.timeline.start()
|
|
|
|
self.currentMenu = toMenu
|
|
|
|
|
|
|
|
def on_key_press_event (self, stage, event):
|
2007-11-22 02:41:29 -08:00
|
|
|
#Firstly check whether any messages are currently displayed
|
|
|
|
if self.uiMsg.active:
|
|
|
|
self.uiMsg.on_key_press_event(stage, event)
|
|
|
|
return
|
|
|
|
|
|
|
|
#Secondly, checking whether we are in the process of running a plugin (And that the key isn't escape)
|
2007-08-14 18:10:53 -07:00
|
|
|
if (not self.currentPlugin == None) and (not event.keyval == clutter.keysyms.Escape):
|
|
|
|
#If it is, simply pass the event details along to the plugin
|
|
|
|
self.currentPlugin.on_key_press_event(stage, event)
|
|
|
|
return None
|
|
|
|
|
2007-11-22 02:41:29 -08:00
|
|
|
|
|
|
|
# If none of these things, the menu needs to do something
|
2007-08-14 18:10:53 -07:00
|
|
|
if event.keyval == clutter.keysyms.Up: #Up button pressed
|
|
|
|
self.currentMenu.selectPrevious()
|
|
|
|
if event.keyval == clutter.keysyms.Down: #Down button pressed
|
|
|
|
self.currentMenu.selectNext()
|
|
|
|
if event.keyval == clutter.keysyms.q:
|
|
|
|
clutter.main_quit()
|
2007-11-22 02:41:29 -08:00
|
|
|
if event.keyval == clutter.keysyms.Return: #return button pressed
|
|
|
|
# Need to decide what action to take
|
|
|
|
# Options are:
|
|
|
|
# 1) Switch to a new menu
|
|
|
|
# 2) Launch a module
|
2007-08-14 18:10:53 -07:00
|
|
|
action = self.currentMenu.get_current_item().getAction()
|
|
|
|
if action.__class__.__name__ == "Menu": # Check whether we're a pointing to a menu object
|
|
|
|
self.transition_fade_zoom(self.currentMenu, action)
|
2007-08-19 05:29:56 -07:00
|
|
|
self.menuHistory.append(action)
|
2007-08-14 18:10:53 -07:00
|
|
|
else:
|
|
|
|
#We have a plugin and need to start it
|
|
|
|
self.currentPlugin = action
|
2007-08-21 14:49:29 -07:00
|
|
|
action.begin( self )
|
2007-11-22 02:41:29 -08:00
|
|
|
# This is tres bodge
|
2007-08-14 18:10:53 -07:00
|
|
|
if event.keyval == clutter.keysyms.Escape:
|
2007-08-19 05:29:56 -07:00
|
|
|
#If there's a plugin running then end it
|
2007-08-14 18:10:53 -07:00
|
|
|
if not self.currentPlugin == None:
|
2007-09-05 03:16:17 -07:00
|
|
|
#Plugins on_key_press_event should return true if the plugin is finishing
|
|
|
|
if self.currentPlugin.on_key_press_event(stage, event):
|
|
|
|
self.currentPlugin.stop()
|
|
|
|
self.currentPlugin = None
|
2007-08-19 05:29:56 -07:00
|
|
|
#If there's no plugin running, go back one in the menu list (Providing we're not already at the first item.
|
|
|
|
else:
|
2007-08-28 14:55:50 -07:00
|
|
|
if len(self.menuHistory)>1:
|
2007-08-19 05:29:56 -07:00
|
|
|
self.transition_fade_zoom(self.menuHistory.pop(), self.menuHistory[-1])
|
|
|
|
self.currentMenu = self.menuHistory[-1]
|
2007-08-14 18:10:53 -07:00
|
|
|
#print event.hardware_keycode
|
|
|
|
|
|
|
|
def get_current_menu(self):
|
|
|
|
return self.currentMenu
|
2007-11-19 03:38:15 -08:00
|
|
|
|
|
|
|
def go_up_x_levels(self, num_levels):
|
|
|
|
for i in range(1, num_levels):
|
|
|
|
if len(self.menuHistory)>1:
|
|
|
|
self.transition_fade_zoom(self.menuHistory.pop(), self.menuHistory[-1])
|
|
|
|
self.currentMenu = self.menuHistory[-1]
|
2007-11-22 02:41:29 -08:00
|
|
|
|
|
|
|
def display_msg(self, title, msg):
|
|
|
|
self.uiMsg.display_msg(title, msg)
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
class MenuSelector(clutter.Texture):
|
|
|
|
x_offset = -50
|
2007-09-01 16:28:47 -07:00
|
|
|
width = 400
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
def __init__ (self, menuMgr):
|
|
|
|
clutter.Texture.__init__ (self)
|
|
|
|
self.menuMgr = menuMgr
|
|
|
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/active_bar.png")
|
|
|
|
self.set_pixbuf(pixbuf)
|
2007-09-01 16:28:47 -07:00
|
|
|
self.set_width(self.width)
|
2007-08-14 18:10:53 -07:00
|
|
|
|
2007-11-08 03:41:12 -08:00
|
|
|
#pixbuf = gtk.gdk.pixbuf_new_from_file("ui/spinner1.gif")
|
|
|
|
#self.spinner = clutter.Texture()
|
|
|
|
#self.spinner.set_pixbuf(pixbuf)
|
|
|
|
#self.spinner.hide()
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
|
|
|
|
def selectItem(self, selectee, timeline):
|
|
|
|
(x, y) = selectee.get_abs_position()
|
|
|
|
|
|
|
|
x = x + self.x_offset
|
|
|
|
|
|
|
|
#Check if we're going up or down
|
|
|
|
if y > self.get_y():
|
|
|
|
#Going down
|
|
|
|
y = int(y - selectee.get_menu().get_item_gap()/2)
|
|
|
|
else:
|
|
|
|
#Going up
|
|
|
|
y = int(y - selectee.get_menu().get_item_gap()/2)
|
|
|
|
|
2007-08-26 06:15:05 -07:00
|
|
|
self.move_to(x, y, timeline)
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
def move_to(self, x, y, timeline):
|
|
|
|
knots = (\
|
|
|
|
(self.get_x(), self.get_y()),\
|
|
|
|
(x, y)\
|
|
|
|
)
|
|
|
|
|
2007-08-26 06:15:05 -07:00
|
|
|
self.alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
2007-08-14 18:10:53 -07:00
|
|
|
self.behaviour = clutter.BehaviourPath(self.alpha, knots)
|
|
|
|
|
|
|
|
self.behaviour.apply(self)
|
|
|
|
|
|
|
|
def set_menu(self, menu):
|
|
|
|
self.menu = menu
|
|
|
|
|
|
|
|
def set_spinner(self, state):
|
2007-08-23 04:50:05 -07:00
|
|
|
self.timeline = clutter.Timeline(25, 25)
|
|
|
|
self.alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
|
|
|
self.behaviour = clutter.BehaviourOpacity(self.alpha, 0,255)
|
2007-08-14 18:10:53 -07:00
|
|
|
if state:
|
|
|
|
self.spinner = Spinner()
|
2007-08-23 04:50:05 -07:00
|
|
|
|
|
|
|
height = self.get_height() - int(self.get_height() * 0.11)
|
|
|
|
#Height has to be even otherwise spinner rotates on a slightly off axis
|
|
|
|
if (height % 2) == 1:
|
|
|
|
height = height -1
|
|
|
|
|
|
|
|
width = height
|
|
|
|
self.spinner.set_size(width, height)
|
|
|
|
|
|
|
|
(x, y) = self.get_abs_position()
|
2007-08-26 06:15:05 -07:00
|
|
|
x = x + self.get_width() - int(self.get_width() * 0.13)
|
|
|
|
y = y + int(self.get_height() * 0.03)
|
2007-08-23 04:50:05 -07:00
|
|
|
self.spinner.set_position(x, y)
|
|
|
|
|
|
|
|
self.spinner.set_opacity(0)
|
2007-08-14 18:10:53 -07:00
|
|
|
self.spinner.show()
|
|
|
|
self.menuMgr.get_stage().add(self.spinner)
|
2007-08-23 04:50:05 -07:00
|
|
|
self.behaviour = clutter.BehaviourOpacity(self.alpha, 0,255)
|
|
|
|
self.spinner.start()
|
2007-08-14 18:10:53 -07:00
|
|
|
else:
|
2007-08-23 04:50:05 -07:00
|
|
|
self.behaviour = clutter.BehaviourOpacity(self.alpha, 255,0)
|
|
|
|
self.timeline.connect('completed', self.spinner_end_event)
|
|
|
|
#self.menuMgr.get_stage().remove(self.spinner)
|
|
|
|
#self.spinner = None
|
|
|
|
|
|
|
|
self.behaviour.apply(self.spinner)
|
|
|
|
self.timeline.start()
|
2007-08-14 18:10:53 -07:00
|
|
|
|
2007-08-23 04:50:05 -07:00
|
|
|
def spinner_end_event(self, data):
|
|
|
|
self.menuMgr.get_stage().remove(self.spinner)
|
|
|
|
self.spinner = None
|
2007-08-14 18:10:53 -07:00
|
|
|
|
|
|
|
def get_x_offset(self):
|
|
|
|
return self.x_offset
|
2007-09-01 16:28:47 -07:00
|
|
|
def get_width(self):
|
|
|
|
return self.width
|
2007-08-14 19:08:46 -07:00
|
|
|
|
2007-11-22 02:41:29 -08:00
|
|
|
class message():
|
|
|
|
font = "Lucida Grande "
|
|
|
|
message_font_size = 30
|
|
|
|
detail_font_size = 22
|
|
|
|
|
|
|
|
def __init__(self, stage):
|
|
|
|
self.stage = stage
|
|
|
|
self.active = False
|
|
|
|
|
|
|
|
self.backdrop = clutter.Rectangle()
|
|
|
|
self.backdrop.set_color(clutter.color_parse('Black'))
|
|
|
|
#self.backdrop.set_opacity(240)
|
|
|
|
self.backdrop.set_width(self.stage.get_width())
|
|
|
|
self.backdrop.set_height(self.stage.get_height())
|
|
|
|
|
|
|
|
self.main_group = clutter.Group()
|
|
|
|
|
|
|
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/splash_box.png")
|
|
|
|
self.box = clutter.Texture()
|
|
|
|
self.box.set_pixbuf(pixbuf)
|
|
|
|
self.box.set_opacity(int(255 * 0.75))
|
|
|
|
self.box.set_height(int(self.stage.get_height()* 0.3))
|
|
|
|
self.main_group.add(self.box)
|
|
|
|
|
|
|
|
self.message = clutter.Label()
|
|
|
|
self.message.set_font_name(self.font + str(self.message_font_size))
|
|
|
|
self.message.set_color(clutter.color_parse('White'))
|
|
|
|
pos_x = int(self.box.get_width() * 0.10)
|
|
|
|
pos_y = int(self.box.get_height() * 0.10)
|
|
|
|
self.message.set_position(pos_x, pos_y)
|
|
|
|
width = int(self.box.get_width() * 0.80) #Width is 80% of the box, giving 10% gap each side
|
|
|
|
self.message.set_width(width)
|
|
|
|
self.message.set_ellipsize(pango.ELLIPSIZE_END)
|
|
|
|
self.message.set_text("")
|
|
|
|
self.main_group.add(self.message)
|
|
|
|
|
|
|
|
self.detail = clutter.Label()
|
|
|
|
self.detail.set_font_name(self.font + str(self.detail_font_size))
|
|
|
|
self.detail.set_color(clutter.color_parse('White'))
|
|
|
|
pos_x = self.message.get_x()
|
|
|
|
pos_y = self.message.get_y() + self.message.get_height()
|
|
|
|
self.detail.set_position(pos_x, pos_y)
|
|
|
|
height = self.box.get_height() - pos_y
|
|
|
|
self.detail.set_height(height)
|
|
|
|
#self.detail.set_ellipsize(pango.ELLIPSIZE_END)
|
|
|
|
self.main_group.add(self.detail)
|
|
|
|
self.detail.set_line_wrap(True)
|
|
|
|
|
|
|
|
group_x = (self.stage.get_width()/2) - (self.box.get_width()/2)
|
|
|
|
group_y = (self.stage.get_height()/2) - (self.box.get_height()/2)
|
|
|
|
self.main_group.set_position(group_x, group_y)
|
|
|
|
|
|
|
|
def display_msg(self, title, text):
|
|
|
|
self.active = True
|
|
|
|
|
|
|
|
self.message.set_text(title)
|
|
|
|
self.detail.set_text(text)
|
|
|
|
width = int(self.box.get_width() * 0.80) #Width is 80% of the box, giving 10% gap each side
|
|
|
|
self.detail.set_width(width)
|
|
|
|
self.message.set_width(width)
|
|
|
|
|
|
|
|
|
|
|
|
self.main_group.set_opacity(0)
|
|
|
|
self.backdrop.set_opacity(0)
|
|
|
|
self.stage.add(self.backdrop)
|
|
|
|
self.stage.add(self.main_group)
|
|
|
|
self.main_group.show_all()
|
|
|
|
self.backdrop.show()
|
|
|
|
|
|
|
|
self.timeline = clutter.Timeline(10,30)
|
|
|
|
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
|
|
|
self.behaviour_group = clutter.BehaviourOpacity(alpha, 0, 255)
|
|
|
|
self.behaviour_backdrop = clutter.BehaviourOpacity(alpha, 0, 180)
|
|
|
|
self.behaviour_group.apply(self.main_group)
|
|
|
|
self.behaviour_backdrop.apply(self.backdrop)
|
|
|
|
self.timeline.start()
|
|
|
|
|
|
|
|
def hide_msg(self):
|
|
|
|
self.active = False
|
|
|
|
|
|
|
|
self.timeline = clutter.Timeline(10,30)
|
|
|
|
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
|
|
|
self.behaviour_group = clutter.BehaviourOpacity(alpha, 255, 0)
|
|
|
|
self.behaviour_backdrop = clutter.BehaviourOpacity(alpha, 180, 0)
|
|
|
|
self.behaviour_group.apply(self.main_group)
|
|
|
|
self.behaviour_backdrop.apply(self.backdrop)
|
|
|
|
self.timeline.start()
|
|
|
|
|
|
|
|
def on_key_press_event (self, stage, event):
|
|
|
|
self.hide_msg()
|