gloss-mc/GlossMgr.py

193 lines
8.5 KiB
Python

import clutter
import copy
from utils.themeMgr import ThemeMgr
from ui_elements.message import Message
from ui_elements.Spinner import Spinner
"""The core control class for Gloss
GlossMgr handles and controls the input. It maintains the status of any modules / plugins
as well as the interface that is to be used. All input goes through GlossMgr, which in turns passes it
to the correct module. It also stores certain global properties (Eg a 'debug' flag). The GlossMgr instance is passed to all modules so that they my reference this data
"""
__author__ = 'Josh Stewart (noisymime)'
__version__= '0.1'"""The core control class for Gloss
GlossMgr handles and controls the input. It maintains the status of any modules / plugins
as well as the interface that is to be used. All input goes through GlossMgr, which in turns passes it
to the correct module. It also stores certain global properties (Eg a 'debug' flag). The GlossMgr instance is passed to all modules so that they my reference this data
"""
__author__ = 'Josh Stewart (noisymime)'
__version__= '0.1'
class GlossMgr:
theme_dir = "themes/"
def __init__ (self, stage, dbMgr, theme=None):
self.stage = stage
self.menus = []
self.menuHistory = [] #A list that contains menus in the order that they've been viewed
self.currentMenu = None
self.debug = False #Debug flag
self.ui_overide = None
self.uiMsg = Message(self)
self.dbMgr = dbMgr
self.themeMgr = ThemeMgr(self, theme)
#Set the menu interface
element = self.themeMgr.search_docs("menu", "main").childNodes
interface_name = self.themeMgr.find_child_value(element, "interface")
self.set_menu_interface(interface_name)
#Set a default menu transition
self.set_menu_transition("slide")
#The background is a bit messy due to the depth issues :(
self.background = self.themeMgr.get_texture("background", None, None)
self.background.set_size(self.stage.get_width(), self.stage.get_height())
self.background.show()
self.stage.add(self.background)
self.currentPlugin = None
def addMenu(self, newMenu):
"""Adds a new menu to the main interface
Arguments:
newMenu -- The new menu to be added to the interface
"""
self.menus.append(newMenu)
#If this is the first menu, make it the active one
if self.currentMenu == None:
self.currentMenu = newMenu
self.menuHistory.append(newMenu)
self.currentMenu.show_all()
self.currentMenu.show()
#This is a bit hacky, but we set the selector bar size based on the font size
tmpLabel = clutter.Label()
tmpLabel.set_text("AAA")
tmpLabel.set_font_name(self.currentMenu.font)
#Selector bar height is 20% larger than the labels
#self.selector_bar.set_height( int(tmpLabel.get_height()*self.selector_bar.height_percent) )
#self.selector_bar.set_menu(self.currentMenu)
tmpLabel = None
def get_stage(self):
return self.stage
def get_themeMgr(self):
return self.themeMgr
def on_key_press_event (self, stage, event):
"""Handles *all* input in Gloss
In 'normal' mode, this will pass the event to the menu item and select it accordingly. If the key is 'Return' then it will start the currently selected module
Exceptions to this:
1) If the UI Overide variable is set, the event is sent to it. This is used for things such as UI prompts (messages) and option dialogs that need to have UI focus above all else
2) If there is a plugin running, the input event gets sent through to its 'on_key_press_event()' method. If this method returns True, GlossMgr assumes the plugin to have terminated.
Arguments:
stage -- The primary stage object
event -- The Clutter event object
"""
#Firstly check whether any messages are currently displayed
if not self.ui_overide is None:
self.ui_overide.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)
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
# If none of these things, the menu needs to do something
if event.keyval == clutter.keysyms.Up: #Up button pressed
self.currentMenu.on_key_press_event(event)
#self.currentMenu.selectPrevious()
if event.keyval == clutter.keysyms.Down: #Down button pressed
self.currentMenu.on_key_press_event(event)
#self.currentMenu.selectNext()
if event.keyval == clutter.keysyms.q:
self.stage.show_cursor()
clutter.main_quit()
if event.keyval == clutter.keysyms.Return:
# Need to decide what action to take
# Options are:
# 1) Switch to a new menu
# 2) Launch a module
action = self.currentMenu.get_current_item().getAction()
if action.__class__.__name__ == "Interface": # Check whether we're a pointing to an interface
self.transition.do_transition(self.currentMenu, action)
self.menuHistory.append(action)
else:
#We have a plugin and need to start it
self.currentPlugin = action
if action is None:
self.display_msg("Error", "Could not start " + self.currentMenu.get_current_item().get_text())
else:
#hide any unnecesary actors
self.currentMenu.hide()
#self.stage.remove(self.currentMenu.getItemGroup())
#And begin the plugin
action.begin( self )
# This is tres bodge
if event.keyval == clutter.keysyms.Escape:
#If there's a plugin running then end it
if not self.currentPlugin == None:
#Plugins on_key_press_event should return true if the plugin is finishing
if self.currentPlugin.on_key_press_event(stage, event):
self.kill_plugin()
#If there's no plugin running, go back one in the menu list (Providing we're not already at the first item.
else:
if len(self.menuHistory)>1:
self.transition.do_transition(self.menuHistory.pop(), self.menuHistory[-1])
self.currentMenu = self.menuHistory[-1]
#print event.hardware_keycode
def kill_plugin(self, kill_plugin=True):
"""Kills any currently running plugin/module"""
if not self.currentPlugin is None:
if kill_plugin: self.currentPlugin.stop()
self.currentPlugin = None
timeline_stop = clutter.Timeline(10,30)
alpha = clutter.Alpha(timeline_stop, clutter.ramp_inc_func)
self.stop_behaviour = clutter.BehaviourOpacity(opacity_start=0, opacity_end=255, alpha=alpha)
self.currentMenu.set_opacity(0)
self.currentMenu.show()
self.stop_behaviour.apply(self.currentMenu)
timeline_stop.start()
def get_current_menu(self):
return self.currentMenu
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]
def display_msg(self, title, msg):
self.uiMsg.display_msg(title, msg)
self.ui_overide = self.uiMsg
def set_menu_interface(self, interface_name):
#Setup the menu interface
interface_path = "interfaces/" + interface_name + "/" + interface_name
self.interface = __import__(interface_path)
def set_menu_transition(self, transition_name):
#Setup the menu transition
transition_path = "transitions/menus/" + transition_name
self.transition = __import__(transition_path).Transition(self)
def create_menu(self):
return self.interface.Interface(self)