1
###############################################################################
3
# Purpose: Icon theme management for Editra #
4
# Author: Cody Precord <cprecord@editra.org> #
5
# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
6
# License: wxWindows License #
7
###############################################################################
10
Provide an interface for creating icon themes for Editra. This will allow for
11
themes to be created, installed, and managed as plugins, which means that they
12
can be installed as single file instead of dozens of individual image files.
14
@summary: Editra's theme interface and implementation
18
__author__ = "Cody Precord <cprecord@editra.org>"
19
__svnid__ = "$Id: ed_theme.py 69346 2011-10-09 17:22:09Z CJP $"
20
__revision__ = "$Revision: 69346 $"
22
#--------------------------------------------------------------------------#
31
from profiler import Profile_Get, Profile_Set
32
import syntax.synglob as synglob
33
from syntax.syntax import SYNTAX_IDS
35
#--------------------------------------------------------------------------#
37
class ThemeI(plugin.Interface):
38
"""Interface for defining an icon theme in Editra
39
When a icon theme is active Editra's ArtProvider will ask the active
40
theme that implements this interface to give it a bitmap. The requests
41
for bitmaps will be numerical ID values that come from ed_glob. These
42
ID's are associated with different objects in the interface. The names
43
are descriptive of the object they represent, for reference however
44
see the implementation of the two main themes (Tango and Nuovo).
47
@see: L{syntax.synglob}
51
"""Return the name of this theme. This is used to identify the
52
theme when the provider looks for resources based on user preferences
58
def GetMenuBitmap(self, bmp_id):
59
"""Get the menu bitmap associated with the object id
60
If this theme does not have a resource to provide for this
61
object return a wx.NullBitmap.
63
@return: 16x16 pixel bitmap
68
def GetFileBitmap(self, bmp_id):
69
"""Get the filetype bitmap associated with the object id, the
70
valid object ids are defined in the module syntax.synglob and
71
are used to request images for menu's and page tabs. The theme
72
implimenting this interface should at least be able to
73
provide an image for plain text files and return that for any
76
If this theme does not have a resource to provide for this
77
object return a wx.NullBitmap.
79
@return: 16x16 pixel bitmap
84
def GetOtherBitmap(self, bmp_id):
85
"""Get the bitmap from the 'other' icon resources. Valid id's are
86
identified by a mapping in the ART dictionary.
88
If this theme does not have a resource to provide for this
89
object return a wx.NullBitmap.
96
def GetToolbarBitmap(self, bmp_id):
97
"""Get the toolbar bitmap associated with the object id. The
98
toolbar icons must be returned as a 32x32 pixel bitmap any
99
scaling that is needed will be handled by the art provider that
100
requests the resource.
102
If this theme does not have a resource to provide for this
103
object return a wx.NullBitmap.
105
@return: 32x32 pixel bitmap
110
#-----------------------------------------------------------------------------#
112
class BitmapProvider(plugin.Plugin):
113
"""Plugin that fetches requested icons from the current active theme.
116
observers = plugin.ExtensionPoint(ThemeI)
118
def __GetCurrentProvider(self):
119
"""Gets the provider of the current theme resources
120
@return: ThemeI object
123
theme = Profile_Get('ICONS', 'str', u'')
124
for prov in self.observers:
125
if theme == prov.GetName():
128
# Case if a theme was deleted while it was the active theme
129
if theme.lower() != u'default':
130
Profile_Set('ICONS', u'Default')
134
def _GetTango(self, bmp_id, client):
135
"""Try to get the icon from the default tango theme"""
138
for prov in self.observers:
139
if prov.GetName() == TangoTheme.name:
145
if client == wx.ART_TOOLBAR:
146
bmp = theme.GetToolbarBitmap(bmp_id)
147
elif client == wx.ART_MENU:
148
bmp = theme.GetMenuBitmap(bmp_id)
149
elif client == wx.ART_OTHER:
150
bmp = theme.GetOtherBitmap(bmp_id)
157
"""Gets a list of the installed and activated themes
158
@return: list of strings
161
return [ name.GetName() for name in self.observers ]
163
def GetBitmap(self, bmp_id, client):
164
"""Gets a 16x16 or 32x32 pixel bitmap depending on client value.
165
May return a NullBitmap if no suitable bitmap can be
168
@param bmp_id: id of bitmap to lookup
169
@param client: wxART_MENU, wxART_TOOLBAR
173
prov = self.__GetCurrentProvider()
175
if client == wx.ART_MENU:
176
bmp = prov.GetMenuBitmap(bmp_id)
177
elif client == wx.ART_OTHER:
178
# Backwards compatibility for older interface
179
if hasattr(prov, 'GetOtherBitmap'):
180
bmp = prov.GetOtherBitmap(bmp_id)
184
bmp = prov.GetToolbarBitmap(bmp_id)
189
# Try to fallback to tango theme when icon lookup fails
190
bmp = self._GetTango(bmp_id, client)
196
#-----------------------------------------------------------------------------#
197
# Default theme data maps
198
ART = { ed_glob.ID_ABOUT : u'about.png',
199
ed_glob.ID_ADD : u'add.png',
200
ed_glob.ID_ADD_BM : u'bmark_add.png',
201
ed_glob.ID_ADVANCED : u'advanced.png',
202
ed_glob.ID_BACKWARD : u'backward.png',
203
ed_glob.ID_BIN_FILE : u'bin_file.png',
204
ed_glob.ID_CDROM : u'cdrom.png',
205
ed_glob.ID_CONTACT : u'mail.png',
206
ed_glob.ID_COPY : u'copy.png',
207
ed_glob.ID_COMPUTER : u'computer.png',
208
ed_glob.ID_CUT : u'cut.png',
209
ed_glob.ID_DELETE : u'delete.png',
210
ed_glob.ID_DELETE_ALL : u'delete_all.png',
211
ed_glob.ID_DOCPROP : u'doc_props.png',
212
ed_glob.ID_DOCUMENTATION : u'docs.png',
213
ed_glob.ID_DOWN : u'down.png',
214
ed_glob.ID_EXIT : u'quit.png',
215
ed_glob.ID_FILE : u'file.png',
216
ed_glob.ID_FIND : u'find.png',
217
ed_glob.ID_FIND_REPLACE : u'findr.png',
218
ed_glob.ID_FIND_RESULTS : u'find.png',
219
ed_glob.ID_FLOPPY : u'floppy.png',
220
ed_glob.ID_FOLDER : u'folder.png',
221
ed_glob.ID_FONT : u'font.png',
222
ed_glob.ID_FORWARD : u'forward.png',
223
ed_glob.ID_HARDDISK : u'harddisk.png',
224
ed_glob.ID_HOMEPAGE : u'web.png',
225
ed_glob.ID_HTML_GEN : u'html_gen.png',
226
ed_glob.ID_INDENT : u'indent.png',
227
ed_glob.ID_LOGGER : u'log.png',
228
ed_glob.ID_NEW : u'new.png',
229
ed_glob.ID_NEW_FOLDER : u'newfolder.png',
230
ed_glob.ID_NEW_WINDOW: u'newwin.png',
231
ed_glob.ID_NEXT_MARK : u'bmark_next.png',
232
ed_glob.ID_NEXT_POS : u'forward.png',
233
ed_glob.ID_OPEN : u'open.png',
234
ed_glob.ID_PACKAGE : u'package.png',
235
ed_glob.ID_PASTE : u'paste.png',
236
ed_glob.ID_PLUGMGR : u'plugin.png',
237
ed_glob.ID_PRE_MARK : u'bmark_pre.png',
238
ed_glob.ID_PRE_POS : u'backward.png',
239
ed_glob.ID_PREF : u'pref.png',
240
ed_glob.ID_PRINT : u'print.png',
241
ed_glob.ID_PRINT_PRE : u'printpre.png',
242
ed_glob.ID_PYSHELL : u'pyshell.png',
243
ed_glob.ID_REDO : u'redo.png',
244
ed_glob.ID_REFRESH : u'refresh.png',
245
ed_glob.ID_REMOVE : u'remove.png',
246
ed_glob.ID_RTF_GEN : u'rtf_gen.png',
247
ed_glob.ID_SAVE : u'save.png',
248
ed_glob.ID_SAVEALL : u'saveall.png',
249
ed_glob.ID_SAVEAS : u'saveas.png',
250
ed_glob.ID_SELECTALL : u'selectall.png',
251
ed_glob.ID_STOP : u'stop.png',
252
ed_glob.ID_STYLE_EDIT : u'style_edit.png',
253
ed_glob.ID_TEX_GEN : u'tex_gen.png',
254
ed_glob.ID_THEME : u'theme.png',
255
ed_glob.ID_UNDO : u'undo.png',
256
ed_glob.ID_UNINDENT : u'outdent.png',
257
ed_glob.ID_UP : u'up.png',
258
ed_glob.ID_USB : u'usb.png',
259
ed_glob.ID_WEB : u'web.png',
260
ed_glob.ID_ZOOM_IN : u'zoomi.png',
261
ed_glob.ID_ZOOM_OUT : u'zoomo.png',
262
ed_glob.ID_ZOOM_NORMAL : u'zoomd.png',
263
ed_glob.ID_READONLY : u'readonly.png',
266
ed_glob.ID_CLASS_TYPE : u'class.png',
267
ed_glob.ID_FUNCT_TYPE : u'function.png',
268
ed_glob.ID_ELEM_TYPE : u'element.png',
269
ed_glob.ID_VARIABLE_TYPE : u'variable.png',
270
ed_glob.ID_ATTR_TYPE : u'attribute.png',
271
ed_glob.ID_PROPERTY_TYPE : u'property.png',
272
ed_glob.ID_METHOD_TYPE : u'method.png'
276
MIME_ART = { synglob.ID_LANG_ADA : u'ada.png',
277
synglob.ID_LANG_BASH : u'shell.png',
278
synglob.ID_LANG_BOO : u'boo.png',
279
synglob.ID_LANG_BOURNE : u'shell.png',
280
synglob.ID_LANG_C : u'c.png',
281
synglob.ID_LANG_CPP : u'cpp.png',
282
synglob.ID_LANG_CSH : u'shell.png',
283
synglob.ID_LANG_CSS : u'css.png',
284
synglob.ID_LANG_DIFF : u'diff.png',
285
synglob.ID_LANG_HTML : u'html.png',
286
synglob.ID_LANG_JAVA : u'java.png',
287
synglob.ID_LANG_KSH : u'shell.png',
288
synglob.ID_LANG_LATEX : u'tex.png',
289
synglob.ID_LANG_MAKE : u'makefile.png',
290
synglob.ID_LANG_PASCAL : u'pascal.png',
291
synglob.ID_LANG_PERL : u'perl.png',
292
synglob.ID_LANG_PHP : u'php.png',
293
synglob.ID_LANG_PS : u'postscript.png',
294
synglob.ID_LANG_PYTHON : u'python.png',
295
synglob.ID_LANG_RUBY : u'ruby.png',
296
synglob.ID_LANG_TCL : u'tcl.png',
297
synglob.ID_LANG_TEX : u'tex.png',
298
synglob.ID_LANG_TXT : u'text.png',
299
synglob.ID_LANG_XML : u'xml.png'
302
#-----------------------------------------------------------------------------#
304
class TangoTheme(plugin.Plugin):
305
"""Represents the Tango Icon theme for Editra"""
306
plugin.Implements(ThemeI)
310
def __GetArtPath(self, client, mime=False):
311
"""Gets the path of the resource directory to get
313
@param client: wx.ART_MENU/wx.ART_TOOLBAR
314
@keyword mime: is this a filetype icon lookup
315
@return: path of art resource
319
clients = { wx.ART_MENU : u"menu",
320
wx.ART_TOOLBAR : u"toolbar",
321
wx.ART_OTHER : u"other" }
324
if ed_glob.CONFIG['THEME_DIR'] == u'':
325
theme = util.ResolvConfigDir(os.path.join(u"pixmaps", u"theme"))
326
ed_glob.CONFIG['THEME_DIR'] = theme
329
path = os.path.join(ed_glob.CONFIG['THEME_DIR'],
330
Profile_Get('ICONS'), u'mime')
332
path = os.path.join(ed_glob.CONFIG['THEME_DIR'],
334
clients.get(client, u"menu"))
337
if os.path.exists(path):
343
"""Get the name of this theme
347
return TangoTheme.name
349
def GetMenuBitmap(self, bmp_id):
351
@param bmp_id: Id of bitmap to look for
355
path = self.__GetArtPath(wx.ART_MENU, mime=False)
357
path = path + ART[bmp_id]
358
if os.path.exists(path):
359
return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
361
return self.GetFileBitmap(bmp_id)
365
def GetFileBitmap(self, bmp_id):
366
"""Get a mime type bitmap from the theme
367
@param bmp_id: Id of filetype bitmap to look up
368
@see: L{syntax.synglob}
371
path = self.__GetArtPath(wx.ART_MENU, mime=True)
372
if path is not None and bmp_id in SYNTAX_IDS:
373
if bmp_id in MIME_ART:
374
req = path + MIME_ART[bmp_id]
375
if os.path.exists(req):
376
return wx.Bitmap(req, wx.BITMAP_TYPE_PNG)
378
# Try to fall back to bmp for plain text when above is not found
379
bkup = path + MIME_ART[synglob.ID_LANG_TXT]
380
if os.path.exists(bkup):
381
return wx.Bitmap(bkup, wx.BITMAP_TYPE_PNG)
385
def GetOtherBitmap(self, bmp_id):
386
"""Get a other catagory bitmap.
387
@param bmp_id: Id of art resource
391
path = self.__GetArtPath(wx.ART_OTHER, mime=False)
393
path = path + ART[bmp_id]
394
if os.path.exists(path):
395
return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
399
def GetToolbarBitmap(self, bmp_id):
400
"""Get a toolbar bitmap
401
@param bmp_id: Id of bitmap to look for
402
@return: wx.NullBitmap or a 32x32 bitmap
406
# size = Profile_Get('ICON_SZ', default=(24, 24))
407
path = self.__GetArtPath(wx.ART_TOOLBAR, mime=False)
409
# tpath = os.path.join(path, '24', ART[bmp_id])
410
# if size[0] == 24 and os.path.exists(tpath):
413
path = path + ART[bmp_id]
415
if os.path.exists(path):
416
return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)