1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
|
#-------------------------------------------------------------------------------
# Screenlets - (c) 2007-2009 by RYX (aka Rico Pfaus) <ryx@ryxperience.com>
#
# with contributions by:
# - Whise (Helder Fraga) <helder.fraga@hotmail.com>
#
#-------------------------------------------------------------------------------
==Developers==
===Screenlets API===
You can find online Api documentation [http://screenlets.org//Documentation/index.html here]
===Submit patch/Improve core===
You can easily submit a patch or help improve the Screenlets core by sending a mail to helder.fraga@hotmail.com.
If you want to help but you dont have ideas you can check out our TODO list [http://bazaar.launchpad.net/~screenlets-dev/screenlets/trunk/files here](Click on the TODO file)
===Where/how can I get the development version?===
The screenlets' sourcecode is hosted on [https://launchpad.net/screenlets launchpad]. You can easily download and install the latest development branch using these commands (you need to install [http://bazaar-vcs.org/ 'bzr'] first):
===Some information about Screenlets===
====Builtin controlers====
Screenlets can be controled using builtin variables , for example , if you want to set the scale of the screenlet just do self.scale = 1,2 , or move it self.x = 10 , this will put the screenlet in x = 10 , this also aplys for scale , width , height etc , you can find all this in the api.
====Drawing====
Screenlets are usually drawn using cairo , but you can also use gtk to add gtk widgets to it , however gtk widgets wont resize the way cairo does , so you need to resize the gtk widgets manually , this may be done using a gtk.Box and setting a border width , then in on_scale event set the border you want
====Theming====
Screenlets themes are very costumizable , you can choose to develop a screenlet themes in 3 diferent ways.
1 - Using the builtin theme controls , using funtions like draw_rectangle , draw_triangle , draw_shadow , draw_line , draw_circle and others.
2 - You can use custom images to generate your themes.
3 - You can use both the above
You can also develop themes in a static way , leaving the buttons , text and other stuff also static , or you can change its position , size etc using a theme override .conf file.
You can take a look at the example screenlet for basic theming , and also the radio screenlet (since 0.1.2) that takes the theming to the max.
===Is it easy to create screenlets?===
Screenlets api is relativly easy , but the easiest way to create a screenlet is to edit a screenlet that is already made , for that you can use the example screenlet , included in the core package , or any other screenlet , because Screenlets is an open source project
===Getting Started===
====File structure====
Your screenlet folder should look like this
Clock/ClockScreenlet.py
Clock/icon.png or icon.svg
Clock/themes/defaut/ (containing the default skin)
====Sarting the python file====
=====First we do the basic imports=====
<pre>
import screenlets
from screenlets.options import StringOption , BoolOption , IntOption , FileOption , DirectoryOption , ListOption , AccountOption , TimeOption , FontOption, ColorOption , ImageOption
</pre>
=====We import some more stuff=====
<pre>
import gobject
import gtk
</pre>
=====Lets start the base class =====
<pre>
class ExampleScreenlet (screenlets.Screenlet):
"""A simple example of how to create a Screenlet"""
</pre>
=====Lets set some global vars =====
<pre>
__name__ = 'ExampleScreenlet' #Name of the screenlet followed by "Screenlet"
__version__ = '0.1'
__author__ = 'My name here'
__desc__ = __doc__ # set description to docstring of class
</pre>
=====Lets set some other global vars that we need=====
<pre>
test_text = 'Hi.. im a screenlet'
demo_text = ''
demo_number = ''
int_example = 1
bool_example = True
time_example = (7, 30, 0)
account_example = ('','')
color_example =(0.0, 0.0, 0.0, 1)
font_example = "Sans Medium 5"
image_example = ''
file_example = ''
directory_example = ''
list_example = ('','')
hover = False
</pre>
=====Call super=====
<pre>
def __init__ (self, **keyword_args):
screenlets.Screenlet.__init__(self, width=200, height=200,
uses_theme=True, **keyword_args)
</pre>
=====Set the default theme=====
<pre>
self.theme_name = "default"
</pre>
=====Add menu items or configurable settings=====
<pre>
self.add_options_group('Example', 'This is an example of ' +\
' editable options within an OptionGroup ...')
# add editable option to the group
self.add_option(StringOption('Example','test_text', # attribute-name
self.test_text, # default-value
'Test-Text', # widget-label
'The Test-Text option for this Screenlet ...' # description
))
self.add_option(BoolOption('Example','bool_example',
self.bool_example, 'Option group bool',
'Example options group using bool'))
self.add_option(TimeOption('Example','time_example', self.time_example,
'Option group time', 'Example options group using time'))
self.add_option(IntOption('Example','int_example',
self.int_example, 'Option group integer',
'Example options group using integer',
min=0, max=5000))
self.add_option(FontOption('Example','font_example',
self.font_example, 'Option group font',
'Example options group using font'))
self.add_option(ColorOption('Example','color_example',
self.color_example, 'Option group color',
'Example options group using color'))
self.add_option(AccountOption('Example','account_example',self.account_example,
'Option group account','Using keyring encryption'))
self.add_option(ImageOption('Example','image_example', self.image_example,
'Option group Image', 'Example options group using Image'))
self.add_option(FileOption('Example','file_example', self.file_example,
'Option group file', 'Example options group using file'))
self.add_option(DirectoryOption('Example','directory_example', self.directory_example,
'Option group directory', 'Example options group using directory'))
self.add_option(ListOption('Example','list_example', self.list_example,
'Option group list', 'Example options group using list'))
</pre>
=====The event handlers=====
<pre>
def on_after_set_atribute(self,name, value):
"""Called after setting screenlet atributes"""
print name + ' is going to change from ' + str(value)
pass
def on_before_set_atribute(self,name, value):
"""Called before setting screenlet atributes"""
print name + ' has changed to ' + str(value)
pass
def on_create_drag_icon (self):
"""Called when the screenlet's drag-icon is created. You can supply
your own icon and mask by returning them as a 2-tuple."""
return (None, None)
def on_composite_changed(self):
"""Called when composite state has changed"""
pass
def on_drag_begin (self, drag_context):
"""Called when the Screenlet gets dragged."""
pass
def on_drag_enter (self, drag_context, x, y, timestamp):
"""Called when something gets dragged into the Screenlets area."""
pass
def on_drag_leave (self, drag_context, timestamp):
"""Called when something gets dragged out of the Screenlets area."""
pass
def on_drop (self, x, y, sel_data, timestamp):
"""Called when a selection is dropped on this Screenlet."""
return False
def on_focus (self, event):
"""Called when the Screenlet's window receives focus."""
pass
def on_hide (self):
"""Called when the Screenlet gets hidden."""
pass
def on_init (self):
"""Called when the Screenlet's options have been applied and the
screenlet finished its initialization. If you want to have your
Screenlet do things on startup you should use this handler."""
print 'i just got started'
# add menu items from xml file
self.add_default_menuitems(DefaultMenuItem.XML)
# add menu item
self.add_menuitem("at_runtime", "A")
# add default menu items
self.add_default_menuitems()
def on_key_down(self, keycode, keyvalue, event):
"""Called when a keypress-event occured in Screenlet's window."""
key = gtk.gdk.keyval_name(event.keyval)
if key == "Return" or key == "Tab":
screenlets.show_message(self, 'This is the ' + self.__name__ +'\n' + 'It is installed in ' + self.__path__)
def on_load_theme (self):
"""Called when the theme is reloaded (after loading, before redraw)."""
pass
def on_menuitem_select (self, id):
"""Called when a menuitem is selected."""
if id == "at_runtime":
screenlets.show_message(self, 'This is an example on a menu created at runtime')
if id == "at_xml":
screenlets.show_message(self, 'This is an example on a menu created in the menu.xml')
pass
def on_mouse_down (self, event):
"""Called when a buttonpress-event occured in Screenlet's window.
Returning True causes the event to be not further propagated."""
return False
def on_mouse_enter (self, event):
"""Called when the mouse enters the Screenlet's window."""
self.theme.show_tooltip("this is a tooltip , it is set to shows on mouse hover",self.x+self.mousex,self.y+self.mousey)
self.hover = True
print 'mouse is over me'
def on_mouse_leave (self, event):
"""Called when the mouse leaves the Screenlet's window."""
self.theme.hide_tooltip()
self.hover = False
print 'mouse leave'
def on_mouse_move(self, event):
"""Called when the mouse moves in the Screenlet's window."""
self.redraw_canvas()
pass
def on_mouse_up (self, event):
"""Called when a buttonrelease-event occured in Screenlet's window.
Returning True causes the event to be not further propagated."""
return False
def on_quit (self):
"""Callback for handling destroy-event. Perform your cleanup here!"""
screenlets.show_question(self, 'Do you like screenlets?')
return True
def on_realize (self):
""""Callback for handling the realize-event."""
def on_scale (self):
"""Called when Screenlet.scale is changed."""
pass
def on_scroll_up (self):
"""Called when mousewheel is scrolled up (button4)."""
pass
def on_scroll_down (self):
"""Called when mousewheel is scrolled down (button5)."""
pass
def on_show (self):
"""Called when the Screenlet gets shown after being hidden."""
pass
def on_switch_widget_state (self, state):
"""Called when the Screenlet enters/leaves "Widget"-state."""
pass
def on_unfocus (self, event):
"""Called when the Screenlet's window loses focus."""
pass
def on_draw (self, ctx):
"""In here we load the theme"""
# if theme is loaded
if self.theme:
# set scale rel. to scale-attribute
ctx.scale(self.scale, self.scale)
ctx.set_source_rgba(self.color_example[2], self.color_example[1], self.color_example[0],0.4)
if self.hover:
self.theme.draw_rounded_rectangle(ctx,0,0,20,self.width,self.height)
self.draw_circle(ctx,0,0,self.width,self.height)
# TEST: render example-bg into context (either PNG or SVG)
self.theme.render(ctx, 'example-bg')
ctx.set_source_rgba( self.color_example[0], self.color_example[1], self.color_example[2],self.color_example[3])
self.draw_text(ctx, self.test_text, 0, 0, self.font_example , 10,self.width,pango.ALIGN_LEFT)
self.draw_line(ctx,0,40,self.width,0,1)
self.draw_text(ctx, 'timer - ' + str(self.number), 0, 130, self.font_example , 10, self.width,pango.ALIGN_LEFT)
self.draw_text(ctx, self.theme_name, 0, 50, self.font_example , 10, self.width,pango.ALIGN_LEFT)
self.draw_text(ctx, 'mouse x ' + str(self.mousex ) + ' \n mouse y ' + str(self.mousey ) , 0, 170, self.font_example , 10,self.width,pango.ALIGN_LEFT)
# render svg-file
#self.theme['example-bg.svg'].render_cairo(ctx)
# render png-file
#ctx.set_source_surface(self.theme['example-test.png'], 0, 0)
#ctx.paint()
def on_draw_shape (self, ctx):
self.on_draw(ctx)
</pre>
=====Lets add the screenlet to session=====
<pre>
if __name__ == "__main__":
# create new session
import screenlets.session
screenlets.session.create_session(ExampleScreenlet)
</pre>
=====Builtin drawing funtion=====
<pre>
ctx.scale(self.scale, self.scale)
ctx.set_source_rgba(self.color_example[2], self.color_example[1], self.color_example[0],0.4)
if self.hover:
self.draw_rounded_rectangle(ctx,0,0,20,self.width,self.height)
self.draw_circle(ctx,0,0,self.width,self.height)
# TEST: render example-bg into context (either PNG or SVG)
self.theme.render(ctx, 'example-bg')
ctx.set_source_rgba( self.color_example[0], self.color_example[1], self.color_example[2],self.color_example[3])
self.draw_text(ctx, self.test_text, 0, 0, self.font_example , 10,self.width,pango.ALIGN_LEFT)
self.draw_line(ctx,0,40,self.width,0,1)
self.draw_text(ctx, 'timer - ' + str(self.number), 0, 130, self.font_example , 10, self.width,pango.ALIGN_LEFT)
self.draw_text(ctx, self.theme_name, 0, 50, self.font_example , 10, self.width,pango.ALIGN_LEFT)
self.draw_text(ctx, 'mouse x ' + str(self.mousex ) + ' \n mouse y ' + str(self.mousey ) , 0, 170, self.font_example , 10,self.width,pango.ALIGN_LEFT)
# render svg-file
#self.theme['example-bg.svg'].render_cairo(ctx)
# render png-file
#ctx.set_source_surface(self.theme['example-test.png'], 0, 0)
#ctx.paint()
</pre>
===So where do i start?===
i sugest you get the [http://screenlets.org/images/c/c6/Template.tar.gz template] screenlet and start coding from there
===Codding Rules===
*A Screenlet's classname must end on "Screenlet" (e.g. ClockScreenlet)
*Not more than 80 chars per line (where possible).
*Tabs are 4 char-wide "\t"-characters.
*Classes MUST have a documentation-string.
*After class-headers's documentation, one separating line.
*Internal attributes MUST start with TWO leading underscores.
*Editable options NEVER have leading underscores.
*All functions that are no inherited event-handlers MUST have a documentation-string.
*Constructors of Screenlet-subclasses must implement the **keyword_args parameter as last argument to their __init__-function.
*All screenlet-files MUST have the name of the Screenlet-classes they contain (with a .py-extension).
*All Screenlets MUST have a head-comment containing license/author note,
*Screenlets need to be placed into a directory named like the Screenlet's class (without trailing "Screenlet"). This directory may contain a "themes"-directory where the Screenlet's themes are stored. It may also contain other files (of course).
*Screenlets should supply an icon named "icon.svg" or "icon.png" within their directory.
*When possible set the width and height of the screenlet matching the background theme image , to avoid confusion
*Always call super before anything else ... of course
*Never call exit() or sys.exit().But if you need to check the utils.is_manager_running_me() and only call the exit() if that returns false
===Avoiding memory leaks===
Old versions of screenlets suffered from memory leaks expecilly in the way they draw text , to avoid this use the built in draw_text function.
Also remember to clean all your variables to avoid memory leaks
===Packaging a screenlet===
use the screenlets-packager tool to package your screenlet for release (e.g.):
screenlets-packager ~/.screenlets/Weather
===Finding a host for your package===
One suggestion ,post your screenlet on www.gnome-look.org under the screenlet section , gnome-look provides you to upload your content there , so it will remain in their servers forever , and your screenlet will be safe and backed up, then you can post it on www.screenlets.org and provide the download link from gnome-look
|