]>
Commit | Line | Data |
---|---|---|
1 | #---------------------------------------------------------------------- | |
2 | # Name: wx.lib.ticker | |
3 | # Purpose: A news-ticker style scrolling text control | |
4 | # | |
5 | # Author: Chris Mellon | |
6 | # | |
7 | # Created: 29-Aug-2004 | |
8 | # RCS-ID: $Id$ | |
9 | # Copyright: (c) 2004 by Chris Mellon | |
10 | # Licence: wxWindows license | |
11 | #---------------------------------------------------------------------- | |
12 | ||
13 | """News-ticker style scrolling text control | |
14 | ||
15 | Can scroll from right to left or left to right. | |
16 | Speed of the ticking is controlled by two parameters: | |
17 | Frames per Second(FPS): How many times per second the ticker updates | |
18 | Pixels per Frame(PPF): How many pixels the text moves each update | |
19 | Low FPS with high PPF will result in "jumpy" text, lower PPF with higher FPS | |
20 | is smoother (but blurrier and more CPU intensive) text. | |
21 | """ | |
22 | ||
23 | import wx | |
24 | ||
25 | #---------------------------------------------------------------------- | |
26 | ||
27 | class Ticker(wx.PyControl): | |
28 | def __init__(self, | |
29 | parent, | |
30 | id=-1, | |
31 | text=wx.EmptyString, #text in the ticker | |
32 | fgcolor = wx.BLACK, #text/foreground color | |
33 | bgcolor = wx.WHITE, #background color | |
34 | start=True, #if True, the ticker starts immediately | |
35 | ppf=2, #pixels per frame | |
36 | fps=20, #frames per second | |
37 | direction="rtl", #direction of ticking, rtl or ltr | |
38 | pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_BORDER, | |
39 | name="Ticker" | |
40 | ): | |
41 | wx.PyControl.__init__(self, parent, id=id, pos=pos, size=size, style=style, name=name) | |
42 | self.timer = wx.Timer(owner=self) | |
43 | self._extent = (-1, -1) #cache value for the GetTextExtent call | |
44 | self._offset = 0 | |
45 | self._fps = fps #frames per second | |
46 | self._ppf = ppf #pixels per frame | |
47 | self.SetDirection(direction) | |
48 | self.SetText(text) | |
49 | self.SetBestFittingSize(size) | |
50 | self.SetForegroundColour(fgcolor) | |
51 | self.SetBackgroundColour(bgcolor) | |
52 | wx.EVT_TIMER(self, -1, self.OnTick) | |
53 | wx.EVT_PAINT(self, self.OnPaint) | |
54 | wx.EVT_ERASE_BACKGROUND(self, self.OnErase) | |
55 | if start: | |
56 | self.Start() | |
57 | ||
58 | ||
59 | def Stop(self): | |
60 | """Stop moving the text""" | |
61 | self.timer.Stop() | |
62 | ||
63 | ||
64 | def Start(self): | |
65 | """Starts the text moving""" | |
66 | if not self.timer.IsRunning(): | |
67 | self.timer.Start(1000 / self._fps) | |
68 | ||
69 | ||
70 | def IsTicking(self): | |
71 | """Is the ticker ticking? ie, is the text moving?""" | |
72 | return self.timer.IsRunning() | |
73 | ||
74 | ||
75 | def SetFPS(self, fps): | |
76 | """Adjust the update speed of the ticker""" | |
77 | self._fps = fps | |
78 | self.Stop() | |
79 | self.Start() | |
80 | ||
81 | ||
82 | def GetFPS(self): | |
83 | """Update speed of the ticker""" | |
84 | return self._fps | |
85 | ||
86 | ||
87 | def SetPPF(self, ppf): | |
88 | """Set the number of pixels per frame the ticker moves - ie, how "jumpy" it is""" | |
89 | self._ppf = ppf | |
90 | ||
91 | ||
92 | def GetPPF(self): | |
93 | """Pixels per frame""" | |
94 | return self._ppf | |
95 | ||
96 | ||
97 | def SetFont(self, font): | |
98 | self._extent = (-1, -1) | |
99 | wx.Control.SetFont(self, font) | |
100 | ||
101 | ||
102 | def SetDirection(self, dir): | |
103 | """Sets the direction of the ticker: right to left(rtl) or left to right (ltr)""" | |
104 | if dir == "ltr" or dir == "rtl": | |
105 | if self._offset <> 0: | |
106 | #Change the offset so it's correct for the new direction | |
107 | self._offset = self._extent[0] + self.GetSize()[0] - self._offset | |
108 | self._dir = dir | |
109 | else: | |
110 | raise TypeError | |
111 | ||
112 | ||
113 | def GetDirection(self): | |
114 | return self._dir | |
115 | ||
116 | ||
117 | def SetText(self, text): | |
118 | """Set the ticker text.""" | |
119 | self._text = text | |
120 | self._extent = (-1, -1) | |
121 | if not self._text: | |
122 | self.Refresh() #Refresh here to clear away the old text. | |
123 | ||
124 | ||
125 | def GetText(self): | |
126 | return self._text | |
127 | ||
128 | ||
129 | def UpdateExtent(self, dc): | |
130 | """Updates the cached text extent if needed""" | |
131 | if not self._text: | |
132 | self._extent = (-1, -1) | |
133 | return | |
134 | if self._extent == (-1, -1): | |
135 | self._extent = dc.GetTextExtent(self.GetText()) | |
136 | ||
137 | ||
138 | def DrawText(self, dc): | |
139 | """Draws the ticker text at the current offset using the provided DC""" | |
140 | dc.SetTextForeground(self.GetForegroundColour()) | |
141 | dc.SetFont(self.GetFont()) | |
142 | self.UpdateExtent(dc) | |
143 | if self._dir == "ltr": | |
144 | offx = self._offset - self._extent[0] | |
145 | else: | |
146 | offx = self.GetSize()[0] - self._offset | |
147 | offy = (self.GetSize()[1] - self._extent[1]) / 2 #centered vertically | |
148 | dc.DrawText(self._text, offx, offy) | |
149 | ||
150 | ||
151 | def OnTick(self, evt): | |
152 | self._offset += self._ppf | |
153 | w1 = self.GetSize()[0] | |
154 | w2 = self._extent[0] | |
155 | if self._offset >= w1+w2: | |
156 | self._offset = 0 | |
157 | self.Refresh() | |
158 | ||
159 | ||
160 | def OnPaint(self, evt): | |
161 | dc = wx.BufferedPaintDC(self) | |
162 | brush = wx.Brush(self.GetBackgroundColour()) | |
163 | dc.SetBackground(brush) | |
164 | dc.Clear() | |
165 | self.DrawText(dc) | |
166 | ||
167 | ||
168 | def OnErase(self, evt): | |
169 | """Noop because of double buffering""" | |
170 | pass | |
171 | ||
172 | ||
173 | def AcceptsFocus(self): | |
174 | """Non-interactive, so don't accept focus""" | |
175 | return False | |
176 | ||
177 | ||
178 | def DoGetBestSize(self): | |
179 | """Width we don't care about, height is either -1, or the character | |
180 | height of our text with a little extra padding | |
181 | """ | |
182 | if self._extent == (-1, -1): | |
183 | if not self._text: | |
184 | h = self.GetCharHeight() | |
185 | else: | |
186 | h = self.GetTextExtent(self.GetText())[1] | |
187 | else: | |
188 | h = self._extent[1] | |
189 | return (100, h+5) | |
190 | ||
191 | ||
192 | def ShouldInheritColours(self): | |
193 | """Don't get colours from our parent...""" | |
194 | return False | |
195 | ||
196 | ||
197 | ||
198 | #testcase/demo | |
199 | if __name__ == '__main__': | |
200 | app = wx.PySimpleApp() | |
201 | f = wx.Frame(None) | |
202 | p = wx.Panel(f) | |
203 | t = Ticker(p, text="Some sample ticker text") | |
204 | #set ticker properties here if you want | |
205 | s = wx.BoxSizer(wx.VERTICAL) | |
206 | s.Add(t, flag=wx.GROW, proportion=0) | |
207 | p.SetSizer(s) | |
208 | f.Show() | |
209 | app.MainLoop() | |
210 | ||
211 |