~ubuntu-branches/ubuntu/raring/wxwidgets2.8/raring

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/src/style_editor.py

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-01-07 13:59:25 UTC
  • mfrom: (1.1.9) (5.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120107135925-2601miy9ullcon9j
Tags: 2.8.12.1-6ubuntu1
* Resync from Debian, changes that were kept:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control: Build-dep on libxt-dev for mediactrl.
  - Patches
    + fix-bashism-in-example
* Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to python-wxversion
  to guarantee upgrade ordering when moving from pycentral to dh_python2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
# Name: style_editor.py                                                       #
3
3
# Purpose: Syntax Highlighting configuration dialog                           #
4
4
# Author: Cody Precord <cprecord@editra.org>                                  #
5
 
# Copyright: (c) 2008 Cody Precord <staff@editra.org>                         #
 
5
# Copyright: (c) 2008-2011 Cody Precord <staff@editra.org>                    #
6
6
# License: wxWindows License                                                  #
7
7
###############################################################################
8
8
 
17
17
"""
18
18
 
19
19
__author__ = "Cody Precord <cprecord@editra.org>"
20
 
__svnid__ = "$Id: style_editor.py 63520 2010-02-19 03:27:26Z CJP $"
21
 
__revision__ = "$Revision: 63520 $"
 
20
__svnid__ = "$Id: style_editor.py 67139 2011-03-07 02:44:26Z CJP $"
 
21
__revision__ = "$Revision: 67139 $"
22
22
 
23
23
#--------------------------------------------------------------------------#
24
24
# Imports
34
34
import util
35
35
import syntax.syntax as syntax
36
36
import eclib
 
37
import ed_basewin
37
38
 
38
39
# Function Aliases
39
40
_ = wx.GetTranslation
40
41
 
41
42
# Global Values
42
 
ID_STYLES = wx.NewId()
43
43
ID_FORE_COLOR = wx.NewId()
44
44
ID_BACK_COLOR = wx.NewId()
45
45
ID_BOLD = wx.NewId()
51
51
 
52
52
SETTINGS_IDS = [ ID_FORE_COLOR, ID_BACK_COLOR, ID_BOLD, ID_ITALIC,
53
53
                 ID_EOL, ID_ULINE, ID_FONT, ID_FONT_SIZE ]
 
54
 
 
55
# Modification Flags
 
56
MOD_NONE           = 0
 
57
MOD_DOESNT_EXIST   = 1
 
58
MOD_CHANGE_PRESENT = 2
 
59
 
54
60
#--------------------------------------------------------------------------#
55
61
 
56
 
class StyleEditor(wx.Dialog):
 
62
class StyleEditor(ed_basewin.EdBaseDialog):
57
63
    """This class creates the window that contains the controls
58
64
    for editing/configuring the syntax highlighting styles it acts
59
65
    as a graphical way to interact with the L{ed_style.StyleMgr}.
61
67
    @see: ed_style.StyleMgr
62
68
    """
63
69
    def __init__(self, parent, id_=wx.ID_ANY, title=_("Style Editor"),
64
 
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RAISED_BORDER):
65
 
        """Initializes the Dialog
66
 
        @todo: rework the layout
67
 
 
68
 
        """
69
 
        wx.Dialog.__init__(self, parent, id_, title, style=style)
 
70
                 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
 
71
        super(StyleEditor, self).__init__(parent, id_, title, style=style)
70
72
 
71
73
        # Attributes
72
74
        self.LOG = wx.GetApp().GetLog()
73
 
        self.preview = ed_basestc.EditraBaseStc(self, wx.ID_ANY, size=(-1, 200),
74
 
                                                style=wx.SUNKEN_BORDER)
75
 
        self.styles_orig = self.preview.GetStyleSet()
76
 
        self.preview.SetCaretLineVisible(True)
77
 
        self.styles_new = DuplicateStyleDict(self.styles_orig)
78
 
        self.preview.SetStyles('preview', self.styles_new, True)
79
 
        self.OpenPreviewFile('cpp')
80
 
        # XXX On Windows the settings pane must be made before the
81
 
        #     sizer it is to be put in or it becomes unable to recieve
82
 
        #     focus. But is the exact opposite on mac/gtk. This is really
83
 
        #     a pain or possibly a bug?
84
 
        if wx.Platform == '__WXMSW__':
85
 
            self._settings = SettingsPanel(self)
 
75
        self._panel = StyleEditorBox(self) #TODO
86
76
 
87
 
        # Main Sizer
 
77
        # Layout
88
78
        sizer = wx.BoxSizer(wx.VERTICAL)
89
 
 
90
 
        # Control Panel
91
 
        self.ctrl_pane = wx.Panel(self, wx.ID_ANY)
92
 
        ctrl_sizer = wx.BoxSizer(wx.HORIZONTAL)  # Main Control Sizer
93
 
        left_colum = wx.BoxSizer(wx.VERTICAL)    # Left Column
94
 
        right_colum = wx.BoxSizer(wx.VERTICAL)   # Right Column
95
 
 
96
 
        # XXX On Mac/GTK if panel is created before sizer all controls in
97
 
        #     it become unable to recieve focus from clicks, but it is the
98
 
        #     exact opposite on windows!
99
 
        if wx.Platform != '__WXMSW__':
100
 
            self._settings = SettingsPanel(self)
101
 
 
102
 
        # Control Panel Left Column
103
 
        left_colum.AddMany([((10, 10), 0),
104
 
                            (self.__StyleSheets(), 0, wx.ALIGN_LEFT),
105
 
                            ((10, 10), 0),
106
 
                            (self.__LexerChoice(), 0, wx.ALIGN_LEFT),
107
 
                            ((10, 10), 0),
108
 
                            (self.__StyleTags(), 1, wx.ALIGN_LEFT|wx.EXPAND),
109
 
                            ((10, 10), 0)])
110
 
        ctrl_sizer.Add(left_colum, 0, wx.ALIGN_LEFT)
111
 
 
112
 
        # Divider
113
 
        ctrl_sizer.Add(wx.StaticLine(self.ctrl_pane, size=(-1, 2),
114
 
                                     style=wx.LI_VERTICAL),
115
 
                       0, wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND)
116
 
        ctrl_sizer.Add((5, 5), 0)
117
 
 
118
 
        # Control Panel Right Column
119
 
        right_colum.Add(self._settings, 1, wx.ALIGN_LEFT | wx.EXPAND)
120
 
        ctrl_sizer.AddMany([(right_colum, 1, wx.ALIGN_RIGHT | wx.EXPAND),
121
 
                            ((5, 5), 0)])
122
 
 
123
 
        # Finish Control Panel Setup
124
 
        self.ctrl_pane.SetSizer(ctrl_sizer)
125
 
        sizer.AddMany([((10, 10)), (self.ctrl_pane, 0, wx.ALIGN_CENTER)])
126
 
 
127
 
        # Preview Area
128
 
        pre_sizer = wx.BoxSizer(wx.HORIZONTAL)
129
 
        pre_sizer.AddMany([((10, 10), 0),
130
 
                           (wx.StaticText(self, label=_("Preview") + u": "),
131
 
                            0, wx.ALIGN_LEFT)])
132
 
        sizer.AddMany([((10, 10), 0), (pre_sizer, 0, wx.ALIGN_LEFT),
133
 
                       (self.preview, 0, wx.EXPAND | wx.BOTTOM)])
 
79
        sizer.Add(self._panel, 1, wx.EXPAND)
134
80
 
135
81
        # Create Buttons
136
82
        b_sizer = wx.BoxSizer(wx.HORIZONTAL)
138
84
        ok_b.SetDefault()
139
85
        b_sizer.AddMany([(wx.Button(self, wx.ID_CANCEL, _("Cancel")), 0),
140
86
                         ((5, 5), 0),
141
 
                         (wx.Button(self, wx.ID_SAVE, _("Export")), 0),
 
87
                         (wx.Button(self, wx.ID_SAVE, _("Save")), 0),
142
88
                         ((5, 5), 0), (ok_b, 0)])
143
89
        sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT |
144
90
                  wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
145
91
 
146
92
        # Finish the Layout
147
93
        self.SetSizer(sizer)
148
 
        self.SetAutoLayout(True)
149
 
        sizer.Fit(self)
150
 
        self.EnableSettings(False)
 
94
        self.SetInitialSize()
151
95
 
152
96
        # Event Handlers
153
97
        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
154
98
        self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK)
155
 
        self.Bind(wx.EVT_BUTTON, self.OnExport, id=wx.ID_SAVE)
156
 
        self.Bind(wx.EVT_CHOICE, self.OnChoice)
157
 
        self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
 
99
        self.Bind(wx.EVT_BUTTON, self.OnSave, id=wx.ID_SAVE)
158
100
        self.Bind(wx.EVT_CLOSE, self.OnClose)
 
101
 
 
102
    #--- End Init ---#
 
103
 
 
104
    def ExportStyleSheet(self):
 
105
        """Writes the style sheet data out to a style sheet
 
106
        @return: bool
 
107
 
 
108
        """
 
109
        saved = self._panel.SaveStyleSheet()
 
110
        return saved
 
111
 
 
112
    def OnCancel(self, evt):
 
113
        """Catches the cancel button clicks and checks if anything
 
114
        needs to be done before closing the window.
 
115
        @param evt: event that called this handler
 
116
 
 
117
        """
 
118
        self.LOG('[style_editor][evt] Cancel Clicked Closing Window')
 
119
        evt.Skip()
 
120
 
 
121
    def OnClose(self, evt):
 
122
        """Handles the window closer event
 
123
        @param evt: event that called this handler
 
124
 
 
125
        """
 
126
        self.LOG("[style_editor][evt] Dialog closing...")
 
127
        self.OnOk(evt)
 
128
 
 
129
    def OnOk(self, evt):
 
130
        """Catches the OK button click and checks if any changes need to be
 
131
        saved before the window closes.
 
132
        @param evt: event that called this handler
 
133
 
 
134
        """
 
135
        self.LOG('[style_editor][evt] Ok Clicked Closing Window')
 
136
        modtype = self._panel.CheckForModifications()
 
137
        result = wx.ID_NO
 
138
        msg = None
 
139
        if modtype == MOD_CHANGE_PRESENT:
 
140
            msg = _("Some styles have been changed would "
 
141
                    "you like to save before exiting?")
 
142
        elif modtype == MOD_DOESNT_EXIST:
 
143
            msg = _("The new style sheet '%s' has not been saved "
 
144
                    "would you like to save before exiting?") % self._panel.StyleTheme
 
145
        if msg is not None:
 
146
            dlg = wx.MessageDialog(self, msg, _("Save Styles"),
 
147
                                   style=wx.YES_NO | wx.YES_DEFAULT | \
 
148
                                         wx.CANCEL | wx.ICON_INFORMATION)
 
149
            dlg.CenterOnParent()
 
150
            result = dlg.ShowModal()
 
151
            dlg.Destroy()
 
152
 
 
153
        if result == wx.ID_NO:
 
154
            # Get Current Selection to update buffers
 
155
            sheet = self._panel.StyleTheme
 
156
            path = self._panel.GetStyleSheetPath(sheet)
 
157
            if os.path.exists(path):
 
158
                UpdateBufferStyles(sheet)
 
159
            evt.Skip()
 
160
        elif result == wx.ID_CANCEL:
 
161
            self.LOG('[style_editor][info] canceled closing')
 
162
        else:
 
163
            result = self.ExportStyleSheet()
 
164
            if result != wx.ID_CANCEL:
 
165
                evt.Skip()
 
166
 
 
167
    def OnSave(self, evt):
 
168
        """Catches save button event
 
169
        @param evt: event that called this handler
 
170
 
 
171
        """
 
172
        self.LOG('[style_editor][evt] Export Clicked')
 
173
        self.ExportStyleSheet()
 
174
 
 
175
#-----------------------------------------------------------------------------#
 
176
 
 
177
class StyleEditorBox(eclib.ControlBox):
 
178
    """StyleEditor main Panel"""
 
179
    def __init__(self, parent):
 
180
        super(StyleEditorBox, self).__init__(parent)
 
181
 
 
182
        # Attributes
 
183
        self._prevTheme = None
 
184
        ctrlbar = self.CreateControlBar(wx.TOP)
 
185
        ss_lst = util.GetResourceFiles(u'styles', get_all=True)
 
186
        ss_lst = [sheet for sheet in ss_lst if not sheet.startswith('.')]
 
187
        self._style_ch = wx.Choice(ctrlbar, ed_glob.ID_PREF_SYNTHEME,
 
188
                                   choices=sorted(ss_lst))
 
189
        bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD), wx.ART_MENU)
 
190
        if not bmp.IsOk():
 
191
            bmp = None
 
192
        self._addbtn = eclib.PlateButton(ctrlbar, label=_("New"),
 
193
                                         bmp=bmp, style=eclib.PB_STYLE_NOBG)
 
194
        bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_REMOVE), wx.ART_MENU)
 
195
        if not bmp.IsOk():
 
196
            bmp = None
 
197
        self._delbtn = eclib.PlateButton(ctrlbar, label=_("Remove"),
 
198
                                         bmp=bmp, style=eclib.PB_STYLE_NOBG)
 
199
 
 
200
        # Setup
 
201
        ss_lbl = wx.StaticText(ctrlbar, label=_("Style Theme") + u": ")
 
202
        ctrlbar.AddControl(ss_lbl, wx.ALIGN_LEFT)
 
203
        self.StyleTheme = Profile_Get('SYNTHEME', 'str')
 
204
        ctrlbar.AddControl(self._style_ch, wx.ALIGN_LEFT)
 
205
        ctrlbar.AddControl(self._addbtn, wx.ALIGN_LEFT)
 
206
        self._addbtn.SetToolTipString(_("Create a new style theme"))
 
207
        ctrlbar.AddControl(self._delbtn, wx.ALIGN_LEFT)
 
208
        self._delbtn.SetToolTipString(_("Remove Style"))
 
209
        self.SetWindow(StyleEditorPanel(self))
 
210
 
 
211
        # Events
 
212
        self.Bind(wx.EVT_CHOICE, self.OnThemeChoice, self._style_ch)
 
213
        self.Bind(wx.EVT_BUTTON, self.OnButton)
 
214
        self.Bind(wx.EVT_UPDATE_UI,
 
215
                  lambda evt: evt.Enable(not self.IsSystemStyleSheet()),
 
216
                  self._delbtn)
 
217
 
 
218
    #--- Properties ----#
 
219
    def __setStyleTheme(self, theme):
 
220
        self._prevTheme = theme # Tracking for choice change
 
221
        self._style_ch.SetStringSelection(theme)
 
222
    StyleTheme = property(lambda self: self._style_ch.GetStringSelection(),
 
223
                          lambda self, val: self.__setStyleTheme(val))
 
224
    SyntaxSheets = property(lambda self: self._style_ch.GetItems(),
 
225
                            lambda self, val: self._style_ch.SetItems(sorted(val)))
 
226
 
 
227
    #---- Public Api ----#
 
228
    def CheckForModifications(self, sheet_name=None):
 
229
        """Check for any unsaved modifications to the styling information
 
230
        @return: modification type
 
231
 
 
232
        """
 
233
        if sheet_name is None:
 
234
            sheet_name = self.StyleTheme # currently selected
 
235
        modtype = MOD_NONE
 
236
        if self.Window.DiffStyles():
 
237
            modtype = MOD_CHANGE_PRESENT
 
238
        elif not self.SheetExistOnDisk(sheet_name):
 
239
            modtype = MOD_DOESNT_EXIST
 
240
        return modtype
 
241
 
 
242
    def DoChangeStyleSheet(self, sheet_name):
 
243
        """Change the StyleEditor for the given style sheet"""
 
244
        if not self.SheetExistOnDisk(sheet_name):
 
245
            # Changing to a fully transient style sheet that has
 
246
            # not yet been written to disk.
 
247
            self.SetDisplayForTransientSheet(sheet_name)
 
248
        else:
 
249
            self.Window.ChangeStyleSheet(sheet_name)
 
250
            self.StyleTheme = sheet_name
 
251
 
 
252
    def GetStyleSheetPath(self, sheet, syspath=False):
 
253
        """Get the on disk path to where the style sheet should
 
254
        be written to.
 
255
        @param sheet: sheet name
 
256
 
 
257
        """
 
258
        cfgdir = ed_glob.CONFIG['STYLES_DIR']
 
259
        if syspath:
 
260
            cfgdir = ed_glob.CONFIG['SYS_STYLES_DIR']
 
261
        sheet_path = os.path.join(cfgdir, sheet)
 
262
        if not sheet_path.endswith(u"ess"):
 
263
            sheet_path += u".ess"
 
264
        return sheet_path
 
265
 
 
266
    def IsSystemStyleSheet(self):
 
267
        """Is the given style sheet a system provided one
 
268
        @return: bool
 
269
 
 
270
        """
 
271
        # If it exists in user space it is not a system one
 
272
        path = self.GetStyleSheetPath(self.StyleTheme)
 
273
        return not os.path.exists(path)
 
274
 
 
275
    def RefreshStyleSheets(self):
 
276
        """Update the list of style sheets"""
 
277
        ss_lst = util.GetResourceFiles(u'styles', get_all=True)
 
278
        ss_lst = [sname for sname in ss_lst if not sname.startswith('.')]
 
279
        self.SyntaxSheets = ss_lst
 
280
 
 
281
    def SaveStyleSheet(self, sheetname=None):
 
282
        """Save the changes to the currently selected StyleSheet
 
283
        @return: bool
 
284
 
 
285
        """
 
286
        # Ensure user styles directory exists to save style sheet to
 
287
        if ed_glob.CONFIG['STYLES_DIR'] == ed_glob.CONFIG['SYS_STYLES_DIR']:
 
288
            path = util.GetUserConfigBase()
 
289
            user_config = os.path.join(path, 'styles')
 
290
            if not os.path.exists(user_config):
 
291
                try:
 
292
                    os.mkdir(user_config)
 
293
                except (OSError, IOError), msg:
 
294
                    util.Log("[style_editor][err] %s" % msg)
 
295
                else:
 
296
                    ed_glob.CONFIG['STYLES_DIR'] = user_config
 
297
 
 
298
        rval = False
 
299
        if sheetname is None:
 
300
            sheetname = self.StyleTheme
 
301
        sheet_path = self.GetStyleSheetPath(sheetname)
 
302
        if self.WriteStyleSheet(sheet_path):
 
303
            # Update Style Sheet Control
 
304
            self.RefreshStyleSheets()
 
305
            sheet = u".".join(os.path.basename(sheet_path).split(u'.')[:-1])
 
306
            self.StyleTheme = sheet
 
307
            self.Window.ResetTransientStyleData()
 
308
            util.Log("[style_editor][info] Successfully exported: %s" % sheet)
 
309
 
 
310
            if sheet_path.startswith(ed_glob.CONFIG['STYLES_DIR']) or \
 
311
               sheet_path.startswith(ed_glob.CONFIG['SYS_STYLES_DIR']):
 
312
                # Update editor windows/buffer to use new style sheet
 
313
                UpdateBufferStyles(sheet)
 
314
            rval = True
 
315
        return rval
 
316
 
 
317
    def SetDisplayForTransientSheet(self, sheet_name):
 
318
        """Setup the display and editor data for a transient style sheet"""
 
319
        self.Window.SetBlankStyle()
 
320
        themes = self.SyntaxSheets
 
321
        if sheet_name not in themes:
 
322
            themes.append(sheet_name)
 
323
            self.SyntaxSheets = themes
 
324
        self.StyleTheme = sheet_name
 
325
 
 
326
    def SheetExistOnDisk(self, sheet_name):
 
327
        """Check if the given style sheet exists on disk
 
328
        @param sheet_name: style sheet name
 
329
        @return: bool
 
330
 
 
331
        """
 
332
        path = self.GetStyleSheetPath(sheet_name) # User path
 
333
        syspath = self.GetStyleSheetPath(sheet_name, True) # System path
 
334
        exists = os.path.exists(path) or os.path.exists(syspath)
 
335
        return exists
 
336
 
 
337
    def WriteStyleSheet(self, path):
 
338
        """Write the current style data to the given path
 
339
        @param path: string
 
340
        @return: bool
 
341
 
 
342
        """
 
343
        bOk = True
 
344
        try:
 
345
            writer = util.GetFileWriter(path)
 
346
            writer.write(self.Window.GenerateStyleSheet())
 
347
            writer.close()
 
348
        except (AttributeError, IOError), msg:
 
349
            util.Log('[style_editor][err] Failed to export style sheet')
 
350
            util.Log('[style_editor][err] %s' % msg)
 
351
            bOk = False
 
352
        return bOk
 
353
 
 
354
    #---- Event Handlers ----#
 
355
 
 
356
    def OnButton(self, evt):
 
357
        """Handle the Add/Remove Buttons"""
 
358
        e_obj = evt.GetEventObject()
 
359
        if e_obj is self._addbtn:
 
360
            # TODO: warn about unsaved changes
 
361
            fname = wx.GetTextFromUser(_("Enter style sheet name"),
 
362
                                       _("New Style Sheet"),
 
363
                                       parent=self)
 
364
            if fname:
 
365
                # Case insensitive check
 
366
                if fname.lower() in [name.lower() for name in self.SyntaxSheets]:
 
367
                    # Already exists
 
368
                    wx.MessageBox(_("The style %s already exists. Please choose a different name.") % fname,
 
369
                                  style=wx.OK|wx.CENTER|wx.ICON_INFORMATION)
 
370
                else:
 
371
                    # Create it
 
372
                    self.SetDisplayForTransientSheet(fname)
 
373
        elif e_obj is self._delbtn:
 
374
            path = self.GetStyleSheetPath(self.StyleTheme)
 
375
            try:
 
376
                os.remove(path)
 
377
            except OSError, msg:
 
378
                wx.MessageBox(_("Failed to delete style sheet:\nError:\n%s") % msg,
 
379
                              style=wx.OK|wx.CENTER|wx.ICON_ERROR)
 
380
            else:
 
381
                self.RefreshStyleSheets()
 
382
                self.StyleTheme = u"Default" # select the default style
 
383
                self.DoChangeStyleSheet(self.StyleTheme)
 
384
        else:
 
385
            evt.Skip()
 
386
 
 
387
    def OnThemeChoice(self, evt):
 
388
        """Check if current style sheet has been saved when switching sheets"""
 
389
        oldTheme = self._prevTheme
 
390
        newTheme = self.StyleTheme # newly selected theme
 
391
        msg = None
 
392
        modtype = self.CheckForModifications(self._prevTheme)
 
393
        if modtype == MOD_CHANGE_PRESENT:
 
394
            # prompt to save before changing
 
395
            msg = _("Would you like to save the changes to '%s' before changing themes?\n\n"
 
396
                    "Selecting No will result in all changes being lost.")
 
397
            msg = msg % oldTheme
 
398
        elif modtype == MOD_DOESNT_EXIST:
 
399
            # prompt to save unsaved sheet
 
400
            msg = _("The new style theme '%s' has not been saved.\n\n"
 
401
                    "Would you like to save it before changing themes?")
 
402
            msg = msg % oldTheme
 
403
 
 
404
        if msg is not None:
 
405
            dlg = wx.MessageDialog(self, msg, _("Save Styles"),
 
406
                                   style=wx.YES_NO | wx.YES_DEFAULT | \
 
407
                                         wx.ICON_INFORMATION)
 
408
            dlg.CenterOnParent()
 
409
            result = dlg.ShowModal()
 
410
            dlg.Destroy()
 
411
            if result == wx.YES:
 
412
                # Save the style sheet
 
413
                self.SaveStyleSheet(oldTheme)
 
414
 
 
415
        # Change the style sheet to the newly selected one
 
416
        self.DoChangeStyleSheet(newTheme)
 
417
 
 
418
#-----------------------------------------------------------------------------#
 
419
 
 
420
class StyleEditorPanel(wx.Panel):
 
421
    """Main panel for the editor portion of the StyleEditor"""
 
422
    def __init__(self, parent):
 
423
        super(StyleEditorPanel, self).__init__(parent)
 
424
 
 
425
        # Attributes
 
426
        self._settings = SettingsPanel(self)
 
427
        self.preview = PreviewPanel(self)
 
428
        self.prebuff = self.preview.GetPreviewBuffer() # TEMP HACK
 
429
        self.styles_orig = DuplicateStyleDict(self.prebuff.GetStyleSet())
 
430
        self.styles_new = DuplicateStyleDict(self.styles_orig)
 
431
        self.prebuff.SetStyles('preview', self.styles_new, True)
 
432
        self.preview.OpenPreviewFile('cpp')
 
433
 
 
434
        # Setup
 
435
        self.StyleTags = self.styles_orig.keys()
 
436
        self.__DoLayout()
 
437
        self.EnableSettings(False)
 
438
 
 
439
        # Event Handlers
159
440
        self.Bind(wx.EVT_LISTBOX, self.OnListBox)
 
441
        self.Bind(wx.EVT_CHOICE, self.OnChoice)
 
442
        self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
160
443
        self.Bind(eclib.EVT_COLORSETTER, self.OnColor)
161
 
        self.preview.Bind(wx.EVT_LEFT_UP, self.OnTextRegion)
162
 
        self.preview.Bind(wx.EVT_KEY_UP, self.OnTextRegion)
163
 
    #--- End Init ---#
164
 
 
165
 
    def __LexerChoice(self):
166
 
        """Returns a sizer object containing a choice control with all
167
 
        available lexers listed in it.
168
 
        @return: sizer item containing a choice control with all available
169
 
                 syntax test files available
170
 
 
171
 
        """
172
 
        lex_sizer = wx.BoxSizer(wx.HORIZONTAL)
173
 
        lexer_lbl = wx.StaticText(self.ctrl_pane, wx.ID_ANY,
174
 
                                  _("Syntax Files") + u": ")
175
 
        lexer_lst = wx.Choice(self.ctrl_pane, ed_glob.ID_LEXER,
176
 
                              choices=syntax.GetLexerList())
177
 
        lexer_lst.SetToolTip(wx.ToolTip(_("Set the preview file type")))
178
 
        lexer_lst.SetStringSelection(u"CPP")
179
 
        lex_sizer.AddMany([((10, 10)), (lexer_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
180
 
                           ((5, 0)), (lexer_lst, 1, wx.ALIGN_CENTER_VERTICAL),
181
 
                           ((10, 10))])
182
 
        return lex_sizer
183
 
 
184
 
    def __StyleSheets(self):
185
 
        """Returns a sizer item that contains a choice control with
186
 
        all the available style sheets listed in it.
187
 
        @return: sizer item holding all installed style sheets
188
 
 
189
 
        """
190
 
        ss_sizer = wx.BoxSizer(wx.HORIZONTAL)
191
 
        ss_lbl = wx.StaticText(self.ctrl_pane, wx.ID_ANY,
192
 
                               _("Style Theme") + u": ")
193
 
        ss_lst = util.GetResourceFiles(u'styles', get_all=True)
194
 
        ss_choice = wx.Choice(self.ctrl_pane, ed_glob.ID_PREF_SYNTHEME,
195
 
                              choices=sorted(ss_lst))
196
 
        ss_choice.SetToolTip(wx.ToolTip(_("Base new theme on existing one")))
197
 
        ss_choice.SetStringSelection(Profile_Get('SYNTHEME', 'str'))
198
 
        ss_new = wx.CheckBox(self.ctrl_pane, wx.ID_NEW, _("New"))
199
 
        ss_new.SetToolTip(wx.ToolTip(_("Start a blank new style")))
200
 
        ss_sizer.AddMany([((10, 10)), (ss_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
201
 
                          ((5, 0)),
202
 
                          (ss_choice, 0, wx.ALIGN_CENTER_VERTICAL), ((10, 0)),
203
 
                          (ss_new, 0, wx.ALIGN_CENTER_VERTICAL), ((10, 10))])
204
 
        return ss_sizer
205
 
 
206
 
    def __StyleTags(self):
207
 
        """Returns a sizer object containing a choice control with all
208
 
        current style tags in it.
209
 
        @return: sizer item containing list of all available style tags
210
 
 
211
 
        """
212
 
        style_sizer = wx.BoxSizer(wx.HORIZONTAL)
213
 
        style_sizer2 = wx.BoxSizer(wx.VERTICAL)
214
 
 
215
 
        style_lbl = wx.StaticText(self.ctrl_pane, wx.ID_ANY,
216
 
                                  _("Style Tags") + u": ")
217
 
 
218
 
        style_tags = self.styles_orig.keys()
219
 
        lsize = (-1, 100)
220
 
        if wx.Platform == '__WXMAC__':
221
 
            lsize = (-1, 120)
222
 
 
223
 
        style_lst = wx.ListBox(self.ctrl_pane, ID_STYLES, size=lsize,
224
 
                               choices=sorted(style_tags), style=wx.LB_SINGLE)
225
 
        style_sizer2.AddMany([(style_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
226
 
                             (style_lst, 1, wx.EXPAND)])
227
 
        style_sizer.AddMany([((10, 10), 0),
228
 
                             (style_sizer2, 1,
229
 
                              wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND),
230
 
                             ((10, 10), 0)])
231
 
        return style_sizer
 
444
        self.prebuff.Bind(wx.EVT_LEFT_UP, self.OnTextRegion)
 
445
        self.prebuff.Bind(wx.EVT_KEY_UP, self.OnTextRegion)
 
446
 
 
447
    def __DoLayout(self):
 
448
        """Layout the window"""
 
449
        vsizer = wx.BoxSizer(wx.VERTICAL)
 
450
        vsizer.Add(self._settings, 0, wx.EXPAND|wx.ALL, 5)
 
451
        vsizer.Add(self.preview, 1, wx.EXPAND)
 
452
        self.SetSizer(vsizer)
 
453
 
 
454
    #---- Properties ----#
 
455
 
 
456
    StyleTags = property(lambda self: self._settings.TagList.GetItems(),
 
457
                         lambda self, val: self._settings.TagList.SetItems(sorted(val)))
 
458
    SettingsPanel = property(lambda self: self._settings)
 
459
 
 
460
    #---- Public API ----#
 
461
 
 
462
    def ChangeStyleSheet(self, sheet_name):
 
463
        """Change the style sheet that is being edited
 
464
        @param sheet_name: style sheet name (without extension)
 
465
 
 
466
        """
 
467
        self.prebuff.UpdateAllStyles(sheet_name)
 
468
        self.ResetTransientStyleData()
 
469
        tag = self._settings.TagList.GetStringSelection()
 
470
        if tag != wx.EmptyString:
 
471
            self.UpdateSettingsPane(self.styles_new[tag])
232
472
 
233
473
    def DiffStyles(self):
234
474
        """Checks if the current style set is different from the
240
480
        """
241
481
        diff = False
242
482
        for key in self.styles_orig:
243
 
            if unicode(self.styles_orig[key]) != unicode(self.styles_new[key]):
 
483
            if self.styles_orig[key] != self.styles_new[key]:
244
484
                diff = True
245
485
                break
246
 
 
247
 
        result = wx.ID_NO
248
 
        if diff:
249
 
            dlg = wx.MessageDialog(self,
250
 
                                    _("Some styles have been changed would "
251
 
                                      "you like to save before exiting?"),
252
 
                                   _("Save Styles"),
253
 
                                   style=wx.YES_NO | wx.YES_DEFAULT | \
254
 
                                         wx.CANCEL | wx.ICON_INFORMATION)
255
 
            dlg.CenterOnParent()
256
 
            result = dlg.ShowModal()
257
 
            dlg.Destroy()
258
 
        return result
 
486
        return diff
259
487
 
260
488
    def EnableSettings(self, enable=True):
261
489
        """Enables/Disables all settings controls
262
490
        @keyword enable: whether to enable/disable settings controls
263
491
 
264
492
        """
265
 
        for child in self._settings.GetChildren():
266
 
            child.Enable(enable)
267
 
 
268
 
    def ExportStyleSheet(self):
269
 
        """Writes the style sheet data out to a style sheet
270
 
        @return: whether style sheet was exported properly or not
271
 
 
272
 
        """
273
 
        if ed_glob.CONFIG['STYLES_DIR'] == ed_glob.CONFIG['SYS_STYLES_DIR']:
274
 
            stdpath = wx.StandardPaths_Get()
275
 
            user_config = os.path.join(stdpath.GetUserDataDir(), 'styles')
276
 
            if not os.path.exists(user_config):
277
 
                try:
278
 
                    os.mkdir(user_config)
279
 
                except (OSError, IOError), msg:
280
 
                    self.LOG("[style_editor][err] %s" % msg)
281
 
                else:
282
 
                    ed_glob.CONFIG['STYLES_DIR'] = user_config
283
 
 
284
 
        result = wx.ID_CANCEL
285
 
        ss_c = self.FindWindowById(ed_glob.ID_PREF_SYNTHEME)
286
 
        new_cb = self.FindWindowById(wx.ID_NEW)
287
 
        if new_cb.GetValue():
288
 
            name = ''
289
 
        else:
290
 
            name = ss_c.GetStringSelection()
291
 
 
292
 
        fname = wx.GetTextFromUser(_("Enter style sheet name"),
293
 
                                   _("Export Style Sheet"),
294
 
                                   name, self)
295
 
 
296
 
        if len(fname):
297
 
            sheet_path = os.path.join(ed_glob.CONFIG['STYLES_DIR'], fname)
298
 
            if sheet_path.split(u'.')[-1] != u'ess':
299
 
                sheet_path += u".ess"
300
 
 
301
 
            try:
302
 
                writer = util.GetFileWriter(sheet_path)
303
 
                writer.write(self.GenerateStyleSheet())
304
 
                writer.close()
305
 
            except (AttributeError, IOError), msg:
306
 
                self.LOG('[style_editor][err] Failed to export style sheet')
307
 
                self.LOG('[style_editor][err] %s' % str(msg))
308
 
            else:
309
 
                # Update Style Sheet Control
310
 
                sheet = ".".join(os.path.basename(sheet_path).split(u'.')[:-1])
311
 
                ss_c.SetItems(util.GetResourceFiles(u'styles', get_all=True))
312
 
                ss_c.SetStringSelection(sheet)
313
 
                ss_c.Enable()
314
 
                self.FindWindowById(wx.ID_NEW).SetValue(False)
315
 
                self.styles_orig = self.styles_new
316
 
                self.styles_new = DuplicateStyleDict(self.styles_orig)
317
 
                result = wx.ID_OK
318
 
 
319
 
                if sheet_path.startswith(ed_glob.CONFIG['STYLES_DIR']) or \
320
 
                   sheet_path.startswith(ed_glob.CONFIG['SYS_STYLES_DIR']):
321
 
                    # Update editor windows/buffer to use new style sheet
322
 
                    UpdateBufferStyles(sheet)
323
 
 
324
 
        return result
 
493
        for child in self.SettingsPanel.GetChildren():
 
494
            if not isinstance(child, wx.ListBox):
 
495
                child.Enable(enable)
325
496
 
326
497
    def GenerateStyleSheet(self):
327
498
        """Generates a style sheet from the dialogs style data
367
538
 
368
539
        return u"".join(sty_sheet)
369
540
 
370
 
    def OnCancel(self, evt):
371
 
        """Catches the cancel button clicks and checks if anything
372
 
        needs to be done before closing the window.
373
 
        @param evt: event that called this handler
374
 
 
375
 
        """
376
 
        self.LOG('[style_editor][evt] Cancel Clicked Closing Window')
377
 
        evt.Skip()
378
 
 
379
 
    def OnCheck(self, evt):
380
 
        """Handles Checkbox events
381
 
        @param evt: event that called this handler
382
 
 
383
 
        """
384
 
        e_id = evt.GetId()
385
 
        e_obj = evt.GetEventObject()
386
 
        if e_id == wx.ID_NEW:
387
 
            val = e_obj.GetValue()
388
 
            choice = self.ctrl_pane.FindWindowById(ed_glob.ID_PREF_SYNTHEME)
389
 
            choice.Enable(not val)
390
 
            if val:
391
 
                self.styles_orig = self.preview.BlankStyleDictionary()
392
 
                self.styles_new = DuplicateStyleDict(self.styles_orig)
393
 
                self.preview.SetStyles('preview', self.styles_new, nomerge=True)
394
 
                self.preview.UpdateAllStyles('preview')
395
 
 
396
 
                # For some reason this causes the text display to refresh
397
 
                # properly when nothing else would work.
398
 
                self.OnTextRegion()
399
 
            else:
400
 
                scheme = choice.GetStringSelection().lower()
401
 
                self.preview.UpdateAllStyles(scheme)
402
 
                self.styles_orig = self.preview.GetStyleSet()
403
 
                self.styles_new = DuplicateStyleDict(self.styles_orig)
404
 
        elif e_id in [ID_BOLD, ID_EOL, ID_ULINE, ID_ITALIC]:
405
 
            self.UpdateStyleSet(e_id)
406
 
        else:
407
 
            evt.Skip()
408
 
 
409
 
    def OnChoice(self, evt):
410
 
        """Handles the events generated from the choice controls
411
 
        @param evt: event that called this handler
412
 
 
413
 
        """
414
 
        e_id = evt.GetId()
415
 
        e_obj = evt.GetEventObject()
416
 
        val = e_obj.GetStringSelection()
417
 
        if e_id == ed_glob.ID_LEXER:
418
 
            self.OpenPreviewFile(val)
419
 
        elif e_id == ed_glob.ID_PREF_SYNTHEME:
420
 
            # TODO Need to check for style changes before switching this
421
 
            self.preview.UpdateAllStyles(val)
422
 
            self.styles_new = self.preview.GetStyleSet()
423
 
            self.styles_orig = DuplicateStyleDict(self.styles_new)
424
 
            ctrl = self.FindWindowById(ID_STYLES)
425
 
            tag = ctrl.GetStringSelection()
426
 
            if tag != wx.EmptyString:
427
 
                self.UpdateSettingsPane(self.styles_new[tag])
428
 
        elif e_id in [ID_FONT, ID_FONT_SIZE]:
429
 
            self.UpdateStyleSet(e_id)
430
 
        else:
431
 
            evt.Skip()
432
 
 
433
 
    def OnClose(self, evt):
434
 
        """Handles the window closer event
435
 
        @param evt: event that called this handler
436
 
 
437
 
        """
438
 
        self.LOG("[style_editor][evt] Dialog closing...")
439
 
        self.OnOk(evt)
440
 
 
441
 
    def OnColor(self, evt):
442
 
        """Handles color selection events
443
 
        @param evt: event that called this handler
444
 
 
445
 
        """
446
 
        # Update The Style data for current tag
447
 
        self.UpdateStyleSet(evt.GetId())
448
 
 
449
 
    def OnTextRegion(self, evt=None):
450
 
        """Processes clicks in the preview control and sets the style
451
 
        selection in the style tags list to the style tag of the area
452
 
        the cursor has moved into.
453
 
        @param evt: event that called this handler
454
 
 
455
 
        """
456
 
        if evt is not None:
457
 
            evt.Skip()
458
 
 
459
 
        style_id = self.preview.GetStyleAt(self.preview.GetCurrentPos())
460
 
        tag_lst = self.FindWindowById(ID_STYLES)
461
 
        data = self.preview.FindTagById(style_id)
462
 
        if data != wx.EmptyString and data in self.styles_new:
463
 
            tag_lst.SetStringSelection(data)
464
 
            if wx.Platform == '__WXGTK__':
465
 
                tag_lst.SetFirstItemStr(data)
466
 
            self.UpdateSettingsPane(self.styles_new[data])
467
 
            self.EnableSettings()
468
 
 
469
 
    def OnListBox(self, evt):
470
 
        """Catches the selection of a style tag in the listbox
471
 
        and updates the style window appropriately.
472
 
        @param evt: event that called this handler
473
 
 
474
 
        """
475
 
        tag = evt.GetEventObject().GetStringSelection()
476
 
        if tag != wx.EmptyString and tag in self.styles_new:
477
 
            self.UpdateSettingsPane(self.styles_new[tag])
478
 
            self.EnableSettings()
479
 
        else:
480
 
            self.EnableSettings(False)
481
 
 
482
 
    def OnOk(self, evt):
483
 
        """Catches the OK button click and checks if any changes need to be
484
 
        saved before the window closes.
485
 
        @param evt: event that called this handler
486
 
 
487
 
        """
488
 
        self.LOG('[style_editor][evt] Ok Clicked Closing Window')
489
 
 
490
 
 
491
 
        result = self.DiffStyles()
492
 
        if result == wx.ID_NO:
493
 
            # Get Current Selection to update buffers
494
 
            csheet = self.FindWindowById(ed_glob.ID_PREF_SYNTHEME).GetStringSelection()
495
 
            UpdateBufferStyles(csheet)
496
 
            evt.Skip()
497
 
        elif result == wx.ID_CANCEL:
498
 
            self.LOG('[style_editor][info] canceled closing')
499
 
        else:
500
 
            result = self.ExportStyleSheet()
501
 
            if result != wx.ID_CANCEL:
502
 
                evt.Skip()
503
 
 
504
 
    def OnExport(self, evt):
505
 
        """Catches save button event
506
 
        @param evt: event that called this handler
507
 
 
508
 
        """
509
 
        self.LOG('[style_editor][evt] Export Clicked')
510
 
        self.ExportStyleSheet()
511
 
 
512
 
    def OpenPreviewFile(self, file_lbl):
513
 
        """Opens a file using the names in the Syntax Files choice
514
 
        control as a search query.
515
 
        @param file_lbl: name of file to open in test data directory
516
 
 
517
 
        """
518
 
        fname = file_lbl.replace(u" ", u"_").replace(u"/", u"_").lower()
519
 
        fname = fname.replace('#', 'sharp')
520
 
        try:
521
 
            fname = glob.glob(ed_glob.CONFIG['TEST_DIR'] + fname + ".*")[0]
522
 
        except IndexError:
523
 
            self.LOG('[style_editor][err] File %s Does not exist' % fname)
524
 
            return False
525
 
 
526
 
        self.preview.SetFileName(fname)
527
 
        self.preview.ClearAll()
528
 
        self.preview.LoadFile(fname)
529
 
        self.preview.FindLexer()
530
 
        self.preview.EmptyUndoBuffer()
531
 
        return True
 
541
    def ResetTransientStyleData(self):
 
542
        """Reset the transient style data to mark the changes as not dirty"""
 
543
        self.styles_new = DuplicateStyleDict(self.prebuff.GetStyleSet())
 
544
        self.styles_orig = DuplicateStyleDict(self.styles_new)
 
545
 
 
546
    def SetBlankStyle(self):
 
547
        """Clear all the transient style data to a blank style set"""
 
548
        self.styles_orig = self.prebuff.BlankStyleDictionary()
 
549
        self.styles_new = DuplicateStyleDict(self.styles_orig)
 
550
        self.prebuff.SetStyles('preview', self.styles_new, nomerge=True)
 
551
        self.prebuff.UpdateAllStyles('preview')
 
552
 
 
553
        # For some reason this causes the text display to refresh
 
554
        # properly when nothing else would work.
 
555
        self.OnTextRegion()
532
556
 
533
557
    def UpdateSettingsPane(self, syntax_data):
534
558
        """Updates all the settings controls to hold the
550
574
        # Fall back to defaults for color values
551
575
        # that we may not be able to understand
552
576
        if u"#" not in val_map[ID_FORE_COLOR]:
553
 
            val_map[ID_FORE_COLOR] = self.preview.GetDefaultForeColour(as_hex=True)
 
577
            val_map[ID_FORE_COLOR] = self.prebuff.GetDefaultForeColour(as_hex=True)
554
578
        if u"#" not in val_map[ID_BACK_COLOR]:
555
 
            val_map[ID_BACK_COLOR] = self.preview.GetDefaultBackColour(as_hex=True)
 
579
            val_map[ID_BACK_COLOR] = self.prebuff.GetDefaultBackColour(as_hex=True)
556
580
 
557
581
        for sid in SETTINGS_IDS:
558
582
            ctrl = self.FindWindowById(sid)
559
 
            c_type = ctrl.GetClassName()
560
 
            if c_type == 'wxCheckBox':
 
583
            if isinstance(ctrl, wx.CheckBox):
561
584
                ctrl.SetValue(val_map[sid])
562
 
            elif c_type == "wxChoice":
 
585
            elif isinstance(ctrl, wx.Choice):
563
586
                ctrl.SetStringSelection(val_map[sid])
564
587
            elif isinstance(ctrl, eclib.ColorSetter):
565
588
                ctrl.SetLabel(val_map[sid][:7])
572
595
 
573
596
        """
574
597
        # Get the tag that has been modified
575
 
        tag = self.FindWindowById(ID_STYLES)
576
 
        tag = tag.GetStringSelection()
577
 
        if tag == None or tag == wx.EmptyString:
 
598
        tag = self._settings.TagList.GetStringSelection()
 
599
        if not tag:
578
600
            return False
579
601
 
580
602
        # Get the modified value
581
603
        ctrl = self.FindWindowById(id_)
582
 
        ctrl_t = ctrl.GetClassName()
583
 
        if ctrl_t == 'wxCheckBox':
 
604
        if isinstance(ctrl, wx.CheckBox):
584
605
            val = ctrl.GetValue()
585
 
        elif ctrl_t == 'wxChoice':
 
606
        elif isinstance(ctrl, wx.Choice):
586
607
            val = ctrl.GetStringSelection()
587
608
        elif isinstance(ctrl, eclib.ColorSetter):
588
609
            val = ctrl.GetLabel()
590
611
            return False
591
612
 
592
613
        # Update the value of the modified tag
593
 
        val_map = { ID_FONT       : u'face',
594
 
                    ID_FONT_SIZE  : u'size',
 
614
        val_map = { ID_FONT       : u"face",
 
615
                    ID_FONT_SIZE  : u"size",
595
616
                    ID_BOLD       : u"bold",
596
617
                    ID_EOL        : u"eol",
597
618
                    ID_ITALIC     : u"italic",
608
629
            return False
609
630
 
610
631
        # Update the Preview Area
611
 
        self.preview.SetStyleTag(tag, self.styles_new[tag])
612
 
        self.preview.RefreshStyles()
 
632
        self.prebuff.SetStyleTag(tag, self.styles_new[tag])
 
633
        self.prebuff.RefreshStyles()
 
634
 
 
635
    #---- Event Handlers ----#
 
636
 
 
637
    def OnCheck(self, evt):
 
638
        """Update Model for changes to styling settings"""
 
639
        e_id = evt.GetId()
 
640
        if e_id in [ID_BOLD, ID_EOL, ID_ULINE, ID_ITALIC]:
 
641
            self.UpdateStyleSet(e_id)
 
642
        else:
 
643
            evt.Skip()
 
644
 
 
645
    def OnChoice(self, evt):
 
646
        """Update Model for changes to styling settings"""
 
647
        e_id = evt.GetId()
 
648
        if e_id in [ID_FONT, ID_FONT_SIZE]:
 
649
            self.UpdateStyleSet(e_id)
 
650
        else:
 
651
            evt.Skip()
 
652
 
 
653
    def OnColor(self, evt):
 
654
        """Handles color selection events
 
655
        @param evt: event that called this handler
 
656
 
 
657
        """
 
658
        # Update The Style data for current tag
 
659
        self.UpdateStyleSet(evt.GetId())
 
660
 
 
661
    def OnListBox(self, evt):
 
662
        """Catches the selection of a style tag in the listbox
 
663
        and updates the style window appropriately.
 
664
        @param evt: event that called this handler
 
665
 
 
666
        """
 
667
        tag = evt.GetEventObject().GetStringSelection()
 
668
        if tag != u"" and tag in self.styles_new:
 
669
            self.UpdateSettingsPane(self.styles_new[tag])
 
670
            self.EnableSettings()
 
671
        else:
 
672
            self.EnableSettings(False)
 
673
 
 
674
    def OnTextRegion(self, evt=None):
 
675
        """Processes clicks in the preview control and sets the style
 
676
        selection in the style tags list to the style tag of the area
 
677
        the cursor has moved into.
 
678
        @param evt: event that called this handler
 
679
 
 
680
        """
 
681
        if evt is not None:
 
682
            evt.Skip()
 
683
 
 
684
        style_id = self.prebuff.GetStyleAt(self.prebuff.GetCurrentPos())
 
685
        data = self.prebuff.FindTagById(style_id)
 
686
        if data != wx.EmptyString and data in self.styles_new:
 
687
            self._settings.TagList.SetStringSelection(data)
 
688
            if wx.Platform == '__WXGTK__':
 
689
                self._settings.TagList.SetFirstItemStr(data)
 
690
            self.UpdateSettingsPane(self.styles_new[data])
 
691
            self.EnableSettings()
613
692
 
614
693
#-----------------------------------------------------------------------------#
615
694
 
620
699
    """
621
700
    def __init__(self, parent):
622
701
        """Create the settings panel"""
623
 
        wx.Panel.__init__(self, parent)
 
702
        super(SettingsPanel, self).__init__(parent)
624
703
 
625
704
        # Attributes
 
705
        self._tag_list = wx.ListBox(self,
 
706
                                    size=(-1, 150),
 
707
                                    style=wx.LB_SINGLE)
626
708
 
627
709
        # Layout
628
710
        self.__DoLayout()
629
711
 
 
712
    TagList = property(lambda self: self._tag_list)
 
713
 
630
714
    def __DoLayout(self):
631
715
        """Layout the controls in the panel"""
 
716
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
 
717
 
 
718
        # Setup Left hand side with Style Tag List
 
719
        ss_v = wx.BoxSizer(wx.VERTICAL)
 
720
        style_lbl = wx.StaticText(self, label=_("Style Tags") + u": ")
 
721
        ss_v.AddMany([(style_lbl, 0, wx.ALIGN_LEFT),
 
722
                      (self._tag_list, 1, wx.EXPAND)])
 
723
        hsizer.Add(ss_v, 0, wx.EXPAND|wx.ALL, 5)
 
724
 
 
725
        # Add divider line
 
726
        hsizer.Add(wx.StaticLine(self, size=(-1, 2), style=wx.LI_VERTICAL),
 
727
                   0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 
728
        
 
729
        # Setup the Right side
632
730
        setting_sizer = wx.BoxSizer(wx.VERTICAL)
633
731
        setting_top = wx.BoxSizer(wx.HORIZONTAL)
634
732
 
635
733
        # Settings top
636
 
        setting_sizer.Add((10, 10))
637
 
        cbox_sizer = wx.StaticBoxSizer(wx.StaticBox(self,
638
 
                                          label=_("Color") + u":"), wx.VERTICAL)
 
734
        sbox = wx.StaticBox(self, label=_("Color"))
 
735
        cbox_sizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)
639
736
 
640
737
        # Foreground
641
738
        fground_sizer = wx.BoxSizer(wx.HORIZONTAL)
643
740
        fground_sel = eclib.ColorSetter(self, ID_FORE_COLOR, wx.BLACK)
644
741
        fground_sizer.AddMany([((5, 5)),
645
742
                               (fground_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
646
 
                               ((2, 2), 1, wx.EXPAND),
 
743
                               ((2, 2), 0),
647
744
                               (fground_sel, 0, wx.ALIGN_CENTER_VERTICAL),
648
745
                               ((5, 5))])
649
746
        cbox_sizer.AddMany([(fground_sizer, 0, wx.ALIGN_LEFT | wx.EXPAND),
655
752
        bground_sel = eclib.ColorSetter(self, ID_BACK_COLOR, wx.WHITE)
656
753
        bground_sizer.AddMany([((5, 5)),
657
754
                               (bground_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
658
 
                               ((2, 2), 1, wx.EXPAND),
 
755
                               ((2, 2), 0),
659
756
                               (bground_sel, 0, wx.ALIGN_CENTER_VERTICAL),
660
757
                               ((5, 5))])
661
 
        cbox_sizer.Add(bground_sizer, 0, wx.ALIGN_LEFT | wx.EXPAND)
662
 
        setting_top.AddMany([(cbox_sizer, 0, wx.ALIGN_TOP), ((10, 10))])
 
758
        cbox_sizer.Add(bground_sizer, 0, wx.EXPAND)
 
759
        setting_top.AddMany([(cbox_sizer, 0, wx.ALIGN_TOP), ((10, 10), 0)])
663
760
 
664
761
        # Attrib Box
665
 
        attrib_box = wx.StaticBox(self, label=_("Attributes") + u":")
 
762
        attrib_box = wx.StaticBox(self, label=_("Attributes"))
666
763
        abox_sizer = wx.StaticBoxSizer(attrib_box, wx.VERTICAL)
667
764
 
668
765
        # Attributes
670
767
        eol_cb = wx.CheckBox(self, ID_EOL, _("eol"))
671
768
        ital_cb = wx.CheckBox(self, ID_ITALIC, _("italic"))
672
769
        uline_cb = wx.CheckBox(self, ID_ULINE, _("underline"))
673
 
        abox_sizer.AddMany([(bold_cb, 0, wx.ALIGN_CENTER_VERTICAL),
674
 
                            (eol_cb, 0, wx.ALIGN_CENTER_VERTICAL),
675
 
                            (ital_cb, 0, wx.ALIGN_CENTER_VERTICAL),
676
 
                            (uline_cb, 0, wx.ALIGN_CENTER_VERTICAL)])
 
770
        abox_sizer.AddMany([(bold_cb, 0),
 
771
                            (eol_cb, 0),
 
772
                            (ital_cb, 0),
 
773
                            (uline_cb, 0)])
677
774
        setting_top.Add(abox_sizer, 0, wx.ALIGN_TOP)
678
775
 
679
776
        # Font
680
777
        fh_sizer = wx.BoxSizer(wx.HORIZONTAL)
681
 
        font_box = wx.StaticBox(self, label=_("Font Settings") + u":")
 
778
        font_box = wx.StaticBox(self, label=_("Font Settings"))
682
779
        fbox_sizer = wx.StaticBoxSizer(font_box, wx.VERTICAL)
683
780
 
684
781
        # Font Face Name
690
787
            fontenum.EnumerateFacenames(fixedWidthOnly=False)
691
788
        else:
692
789
            fontenum.EnumerateFacenames(fixedWidthOnly=True)
693
 
        font_lst = ["%(primary)s", "%(secondary)s"]
 
790
        font_lst = [u"%(primary)s", u"%(secondary)s"]
694
791
        font_lst.extend(sorted(fontenum.GetFacenames()))
695
792
        fchoice = wx.Choice(self, ID_FONT, choices=font_lst)
696
793
        fsizer.AddMany([((5, 5), 0), (flbl, 0, wx.ALIGN_CENTER_VERTICAL),
697
 
                        (fchoice, 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5))])
698
 
        fbox_sizer.Add(fsizer, 0, wx.ALIGN_LEFT)
 
794
                        (fchoice, 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5),0)])
 
795
        fbox_sizer.Add(fsizer, 0)
699
796
 
700
797
        # Font Size
701
798
        fsize_sizer = wx.BoxSizer(wx.HORIZONTAL)
702
799
        fsize_lbl = wx.StaticText(self, label=_("Size") + u": ")
703
 
        fsizes = ['%(size)d', '%(size2)d']
704
 
        fsizes.extend([ str(x) for x in xrange(4, 21) ])
 
800
        fsizes = [u"%(size)d", u"%(size2)d"]
 
801
        fsizes.extend([ unicode(x) for x in range(4, 21) ])
705
802
        fs_choice = wx.Choice(self, ID_FONT_SIZE, choices=fsizes)
706
803
        fsize_sizer.AddMany([((5, 5), 0),
707
804
                             (fsize_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
708
 
                             (fs_choice, 1, wx.EXPAND | wx.ALIGN_RIGHT),
 
805
                             (fs_choice, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL),
709
806
                             ((5, 5), 0)])
710
 
        fbox_sizer.AddMany([((5, 5)),
711
 
                            (fsize_sizer, 0, wx.ALIGN_LEFT | wx.EXPAND)])
712
 
        fh_sizer.AddMany([(fbox_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL),
713
 
                          ((10, 10))])
 
807
        fbox_sizer.AddMany([((5, 5), 0), (fsize_sizer, 0, wx.EXPAND)])
 
808
        fh_sizer.AddMany([(fbox_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL), ((10, 10), 0)])
714
809
 
715
810
        # Build Section
716
811
        setting_sizer.AddMany([(setting_top, 0, wx.ALIGN_CENTER_HORIZONTAL),
717
 
                               ((10, 10), 1, wx.EXPAND),
 
812
                               ((10, 10), 0),
718
813
                               (fh_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
719
 
        self.SetSizer(setting_sizer)
720
 
        self.SetAutoLayout(True)
721
 
 
722
 
#-----------------------------------------------------------------------------#
723
 
# Utility funtcions
 
814
 
 
815
        # Setup Right hand side with the settings controls
 
816
        hsizer.AddStretchSpacer()
 
817
        hsizer.Add(setting_sizer, 0, wx.EXPAND|wx.ALL, 5)
 
818
        hsizer.AddStretchSpacer()
 
819
 
 
820
        self.SetSizer(hsizer)
 
821
 
 
822
#-----------------------------------------------------------------------------#
 
823
 
 
824
class PreviewPanel(ed_basewin.EdBaseCtrlBox):
 
825
    """Panel to hold the preview window and selector"""
 
826
    def __init__(self, parent):
 
827
        super(PreviewPanel, self).__init__(parent)
 
828
 
 
829
        # Attributes
 
830
        self.LOG = wx.GetApp().GetLog()
 
831
        self.preview = ed_basestc.EditraBaseStc(self, size=(-1, 200),
 
832
                                                style=wx.SUNKEN_BORDER)
 
833
 
 
834
        # Setup
 
835
        self.preview.SetEdgeColumn(80)
 
836
        self.preview.SetEdgeMode(wx.stc.STC_EDGE_LINE)
 
837
        self.preview.SetCaretLineVisible(True)
 
838
        self.__DoLayout()
 
839
 
 
840
        # Event Handlers
 
841
        self.Bind(wx.EVT_CHOICE, self.OnChoice)
 
842
 
 
843
    def __DoLayout(self):
 
844
        """Layout the Panel"""
 
845
        # Create the ControlBar
 
846
        cbar = self.CreateControlBar(wx.TOP)
 
847
 
 
848
        # Setup the ControlBar's controls
 
849
        lexer_lbl = wx.StaticText(cbar, label=_("Preview File") + u": ")
 
850
        lexer_lst = wx.Choice(cbar, ed_glob.ID_LEXER,
 
851
                              choices=syntax.GetLexerList())
 
852
        lexer_lst.SetToolTip(wx.ToolTip(_("Set the preview file type")))
 
853
        lexer_lst.SetStringSelection(u"CPP")
 
854
        cbar.AddControl(lexer_lbl)
 
855
        cbar.AddControl(lexer_lst)
 
856
 
 
857
        self.SetWindow(self.preview)
 
858
 
 
859
    def GetPreviewBuffer(self):
 
860
        """Get the STC instance"""
 
861
        return self.preview
 
862
 
 
863
    def OnChoice(self, evt):
 
864
        """Update the preview file"""
 
865
        if evt.GetId() == ed_glob.ID_LEXER:
 
866
            e_obj = evt.GetEventObject()
 
867
            val = e_obj.GetStringSelection()
 
868
            self.OpenPreviewFile(val)
 
869
        else:
 
870
            evt.Skip()
 
871
 
 
872
    def OpenPreviewFile(self, file_lbl):
 
873
        """Opens a file using the names in the Syntax Files choice
 
874
        control as a search query.
 
875
        @param file_lbl: name of file to open in test data directory
 
876
 
 
877
        """
 
878
        fname = file_lbl.replace(u" ", u"_").replace(u"/", u"_").lower()
 
879
        fname = fname.replace('#', 'sharp')
 
880
        try:
 
881
            fname = glob.glob(ed_glob.CONFIG['TEST_DIR'] + fname + ".*")[0]
 
882
        except IndexError:
 
883
            self.LOG('[style_editor][err] File %s Does not exist' % fname)
 
884
            return False
 
885
 
 
886
        self.preview.SetFileName(fname)
 
887
        self.preview.ClearAll()
 
888
        self.preview.LoadFile(fname)
 
889
        self.preview.FindLexer()
 
890
        self.preview.EmptyUndoBuffer()
 
891
        return True
 
892
 
 
893
#-----------------------------------------------------------------------------#
 
894
# Utility functions
724
895
def DuplicateStyleDict(style_dict):
725
896
    """Duplicates the style dictionary to make a true copy of
726
897
    it, as simply assigning the dictionary to two different variables
732
903
    """
733
904
    new_dict = dict()
734
905
    for tag in style_dict:
735
 
        new_dict[tag] = StyleItem()
736
 
        is_ok = new_dict[tag].SetAttrFromStr(unicode(style_dict[tag]))
737
 
        if not is_ok:
738
 
            new_dict[tag].null = True
 
906
        new_dict[tag] = style_dict[tag].Clone()
739
907
    return new_dict
740
908
 
741
909
def UpdateBufferStyles(sheet):
744
912
 
745
913
    """
746
914
    # Only update if the sheet has changed
747
 
    if sheet is None or sheet == Profile_Get('SYNTHEME'):
748
 
        return
749
 
    Profile_Set('SYNTHEME', sheet)
 
915
    if sheet is not None:
 
916
        Profile_Set('SYNTHEME', sheet)