# code_property.py: Property class for the 'code' property of toplevel widgets
#
# Copyright (c) 2002-2007 Alberto Griggio <agriggio@users.sourceforge.net>
# License: MIT (see license.txt)
# THIS PROGRAM COMES WITH NO WARRANTY

import wx, wx.grid
import widget_properties
from widget_properties import GridProperty
from xml.sax.saxutils import escape, quoteattr


class CodeProperty(widget_properties.TextProperty):
    def __init__(self, owner, name='extracode'):
        setattr(owner, name, "")
        def get(): return getattr(owner, name)
        def set(val): return setattr(owner, name, val)
        owner.access_functions[name] = (get, set)
        widget_properties.TextProperty.__init__(self, owner, name, None,
                                                True, multiline=True)

    def _show(self, notebook, label=_('Code')):
        panel, new = _find_or_create_page(notebook, label)
        self.display(panel)
        szr = wx.BoxSizer(wx.VERTICAL)
        szr.Add(self.panel, 1, wx.EXPAND)
        if new:
            panel.SetSizerAndFit(szr)
            notebook.AddPage(panel, label)
        else:
            sizer = panel.GetSizer()
            sizer.Add(szr, 1, wx.EXPAND)
            panel.Layout()

    def display(self, parent):
        self.id = wx.NewId()
        val = self.get_value()
        val = val.replace('\\n', '\n')

        sb = wx.StaticBox(parent, -1, "")
        
        label = widget_properties.wxGenStaticText(parent, -1,
                                                  _('Extra code for this widget'))
        self._enabler = wx.CheckBox(parent, self.id+1, '')
        tooltip = """\
You can use this property to add some extra code to that generated by wxGlade.

Please note that you should use this ability only if you have the \
"Overwrite existing sources" option set.

NOTE: at the moment, this property is supported only by the following code \
generators:
    Python C++ XRC"""
        style = wx.TE_MULTILINE|wx.HSCROLL
        self.text = wx.TextCtrl(parent, self.id, val, style=style, size=(1, -1))
        font = wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_NORMAL)
        self.text.SetFont(font)

        label.SetToolTip(wx.ToolTip(tooltip))
        wx.EVT_CHECKBOX(self._enabler, self.id+1,
                        lambda event: self.toggle_active(event.IsChecked()))
        self.text.Enable(self.is_active())
        self._enabler.SetValue(self.is_active())
        self._target = self.text
        szr = wx.BoxSizer(wx.HORIZONTAL)
        szr.Add(label, 1, wx.ALL|wx.EXPAND, 3)
        szr.Add(self._enabler, 0, wx.ALL|wx.EXPAND, 3)        
        sizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
        sizer.Add(szr, 0, wx.EXPAND)
        sizer.Add(self.text, 1, wx.ALL|wx.EXPAND, 3)
        h = self.text.GetCharHeight()
        sizer.SetItemMinSize(self.text, -1, h*3)
        self.panel = sizer
        self.bind_event(self.on_change_val)
        wx.EVT_CHAR(self.text, self.on_char)

# end of class CodeProperty


class ExtraPropertiesProperty(GridProperty):
    def __init__(self, owner):
        setattr(owner, 'extraproperties', [])
        def get(): return getattr(owner, 'extraproperties')
        def set(val): return setattr(owner, 'extraproperties', val)
        owner.access_functions['extraproperties'] = (get, set)

        cols = [(_('Property'), GridProperty.STRING),
                (_('Value'), GridProperty.STRING)]
        self.label = _('Extra properties for this widget')
        GridProperty.__init__(self, owner, 'extraproperties', None, cols,
                              can_insert=False)

    def write(self, outfile, tabs):
        if self.getter:
            props = self.getter()
        else:
            props = self.owner[self.name][0]()
        if props:
            written = False
            write = outfile.write
            stab = '    ' * (tabs+1)
            for name, value in props:
                if value:
                    if not written:
                        written = True
                        write('    ' * tabs + '<extraproperties>\n')
                    write('%s<property name=%s>%s</property>\n' %
                          (stab, quoteattr(name), escape(value.strip())))
            if written:
                write('    ' * tabs + '</extraproperties>\n')

    def display(self, panel):
        GridProperty.display(self, panel)
        self.btn.Hide()
        wx.grid.EVT_GRID_CELL_CHANGE(self.grid, self.on_change_val)
        tooltip = """\
You can use this property to add some extra custom properties to this widget.

For each property "prop" with value "val", wxGlade will generate a \
"widget.SetProp(val)" line (or a "<prop>val</prop>" line for XRC).

NOTE: at the moment, this property is supported only by the following code \
generators:
    Python C++ XRC Perl"""
        self.grid.SetToolTip(wx.ToolTip(tooltip))

    def add_row(self, event):
        GridProperty.add_row(self, event)
        self.on_change_val(event)

    def remove_row(self, event):
        GridProperty.remove_row(self, event)
        self.on_change_val(event)

    def set_value(self, val):
        if isinstance(val, dict):
            val = [[k, val[k]] for k in sorted(val.keys())]
        GridProperty.set_value(self, val)

    def _show(self, notebook, label=_('Code')):
        panel, new = _find_or_create_page(notebook, label)
        self.display(panel)
        szr = wx.BoxSizer(wx.VERTICAL)
        szr.Add(self.panel, 1, wx.EXPAND)
        if new:
            panel.SetSizerAndFit(szr)
            notebook.AddPage(panel, _('Code'))
        else:
            sizer = panel.GetSizer()
            sizer.Add(szr, 1, wx.EXPAND)
            sizer.Layout()

# end of class ExtraPropertiesProperty


class ExtraPropertiesPropertyHandler(object):
    def __init__(self, owner):
        self.owner = owner
        self.props = {}
        self.prop_name = None
        self.curr_prop = []
        
    def start_elem(self, name, attrs):
        if name == 'property':
            self.prop_name = attrs['name']

    def end_elem(self, name):
        if name == 'property':
            if self.prop_name and self.curr_prop:
                self.props[self.prop_name] = ''.join(self.curr_prop)
            self.prop_name = None
            self.curr_prop = []
        elif name == 'extraproperties':
            self.owner.properties['extraproperties'].set_value(self.props)
            val = [[k, self.props[k]] for k in sorted(self.props.keys())]
            self.owner.extraproperties = val
            return True # to remove this handler

    def char_data(self, data):
        data = data.strip()
        if data:
            self.curr_prop.append(data)

# end of class ExtraPropertiesPropertyHandler


def _find_or_create_page(notebook, label):
    """\
    Searches the given notebook for a page whose label is "label". 
    """
    for i in xrange(notebook.GetPageCount()):
        if notebook.GetPageText(i) == label:
            return notebook.GetPage(i), False
    return wx.Panel(notebook, -1, style=wx.TAB_TRAVERSAL), True
