Merge branch 'bug_387_small_spinner_fix' into experimental
[enigma2.git] / lib / python / Screens / Screen.py
1 from Tools.Profile import profile
2
3 profile("LOAD:GUISkin")
4 from Components.GUISkin import GUISkin
5 profile("LOAD:Source")
6 from Components.Sources.Source import Source
7 profile("LOAD:GUIComponent")
8 from Components.GUIComponent import GUIComponent
9
10 class Screen(dict, GUISkin):
11
12         False, SUSPEND_STOPS, SUSPEND_PAUSES = range(3)
13         ALLOW_SUSPEND = False
14
15         global_screen = None
16
17         def __init__(self, session, parent = None):
18                 dict.__init__(self)
19                 self.skinName = self.__class__.__name__
20                 self.session = session
21                 self.parent = parent
22                 GUISkin.__init__(self)
23
24                 self.onClose = [ ]
25                 self.onFirstExecBegin = [ ]
26                 self.onExecBegin = [ ]
27                 self.onShown = [ ]
28
29                 self.onShow = [ ]
30                 self.onHide = [ ]
31
32                 self.execing = False
33                 
34                 self.shown = True
35                 # already shown is false until the screen is really shown (after creation)
36                 self.already_shown = False
37
38                 self.renderer = [ ]
39
40                 # in order to support screens *without* a help,
41                 # we need the list in every screen. how ironic.
42                 self.helpList = [ ]
43
44                 self.close_on_next_exec = None
45
46                 # stand alone screens (for example web screens)
47                 # don't care about having or not having focus.
48                 self.stand_alone = False
49
50         def execBegin(self):
51                 self.active_components = [ ]
52                 if self.close_on_next_exec is not None:
53                         tmp = self.close_on_next_exec
54                         self.close_on_next_exec = None
55                         self.execing = True
56                         self.close(*tmp)
57                 else:
58                         single = self.onFirstExecBegin
59                         self.onFirstExecBegin = []
60                         for x in self.onExecBegin + single:
61                                 x()
62                                 if not self.stand_alone and self.session.current_dialog != self:
63                                         return
64
65 #                       assert self.session == None, "a screen can only exec once per time"
66 #                       self.session = session
67
68                         for val in self.values() + self.renderer:
69                                 val.execBegin()
70                                 if not self.stand_alone and self.session.current_dialog != self:
71                                         return
72                                 self.active_components.append(val)
73
74                         self.execing = True
75         
76                         for x in self.onShown:
77                                 x()
78         
79         def execEnd(self):
80                 active_components = self.active_components
81 #               for (name, val) in self.items():
82                 self.active_components = None
83                 for val in active_components:
84                         val.execEnd()
85 #               assert self.session != None, "execEnd on non-execing screen!"
86 #               self.session = None
87                 self.execing = False
88         
89         # never call this directly - it will be called from the session!
90         def doClose(self):
91                 self.hide()
92                 for x in self.onClose:
93                         x()
94                 
95                 # fixup circular references
96                 del self.helpList
97                 GUISkin.close(self)
98
99                 # first disconnect all render from their sources.
100                 # we might split this out into a "unskin"-call,
101                 # but currently we destroy the screen afterwards
102                 # anyway.
103                 for val in self.renderer:
104                         val.disconnectAll()  # disconnected converter/sources and probably destroy them. Sources will not be destroyed.
105
106                 del self.session
107                 for (name, val) in self.items():
108                         val.destroy()
109                         del self[name]
110
111                 self.renderer = [ ]
112
113                 # really delete all elements now
114                 self.__dict__.clear()
115         
116         def close(self, *retval):
117                 if not self.execing:
118                         self.close_on_next_exec = retval
119                 else:
120                         self.session.close(self, *retval)
121
122         def setFocus(self, o):
123                 self.instance.setFocus(o.instance)
124
125         def show(self):
126                 if (self.shown and self.already_shown) or not self.instance:
127                         return
128                 self.shown = True
129                 self.already_shown = True
130                 self.instance.show()
131                 for x in self.onShow:
132                         x()
133                 for val in self.values() + self.renderer:
134                         if isinstance(val, GUIComponent) or isinstance(val, Source):
135                                 val.onShow()
136
137         def hide(self):
138                 if not self.shown or not self.instance:
139                         return
140                 self.shown = False
141                 self.instance.hide()
142                 for x in self.onHide:
143                         x()
144                 for val in self.values() + self.renderer:
145                         if isinstance(val, GUIComponent) or isinstance(val, Source):
146                                 val.onHide()
147
148         def __repr__(self):
149                 return str(type(self))
150
151         def getRelatedScreen(self, name):
152                 if name == "session":
153                         return self.session.screen
154                 elif name == "parent":
155                         return self.parent
156                 elif name == "global":
157                         return self.global_screen
158                 else:
159                         return None