"""
Property Editor Dialog
"""
#  Copyright (C) 2004  Henning Jacobs <henning@srcco.de>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  $Id: PropertyEditor.py 93 2004-11-28 16:05:34Z henning $

from Tkinter import *
import Pmw
import ToolTip
from InputWidgets import AbstractSingleVarEdit, TextEdit, MemoEdit, CheckboxEdit

PADX = PADY = 2

class MemoPropEdit(Pmw.Group):
    def __init__(self, master, title, descr):
        Pmw.Group.__init__(self, master, tag_text = title)
        master = self.interior()
        self.edtMemo = MemoEdit(master)
        master.columnconfigure(0, weight=1)
        master.rowconfigure(0, weight=1)
        self.edtMemo.grid(sticky=W+E+S+N, padx=PADX, pady=PADY)
        ToolTip.ToolTip(self.edtMemo, descr)
    def bindto(self, var):
        self.edtMemo.bindto(var)
    def add_save_hook(self, save_hook):
        self.edtMemo.add_save_hook(save_hook)

class TextPropEdit(TextEdit):
    def __init__(self, master, title, descr):
        TextEdit.__init__(self, master)
        ToolTip.ToolTip(self, descr)

class CheckboxPropEdit(CheckboxEdit):
    def __init__(self, master, title, descr):
        CheckboxEdit.__init__(self, master)
        ToolTip.ToolTip(self, descr)
        
class ImagePropEdit(Pmw.Group, AbstractSingleVarEdit):
    def __init__(self, master, title, descr):
        Pmw.Group.__init__(self, master, tag_text = title)
        AbstractSingleVarEdit.__init__(self)
        # imagedata is base64 encoded!
        self._imagedata = ""
        self._imageformat = ""
        master = self.interior()
        ToolTip.ToolTip(master, descr)
        self.btnLoad = Button(master, text='Load...', command=self.loadImageFromFile)
        self.btnLoad.grid(column=0, columnspan=2, row=0, sticky=W+E+S+N, padx=PADX, pady=PADY)
        ToolTip.ToolTip(self.btnLoad, "Load Image from file")
        self.btnSave = Button(master, text='Save...', command=self.saveImageToFile)
        self.btnSave.grid(column=2, columnspan=2, row=0, sticky=W+E+S+N, padx=PADX, pady=PADY)
        ToolTip.ToolTip(self.btnSave, "Save Image to file")
        self.lblSize = Label(master)
        self.lblSize.grid(columnspan=3, row=1, sticky=W+E, padx=PADX, pady=PADY)
        self.btnClear = Button(master, text="Clear", command=self.clearImage,
            padx=0, pady=0)
        self.btnClear.grid(column=3, row=1, padx=PADX, pady=PADY)
        ToolTip.ToolTip(self.btnClear, "Clear Image (remove)")
        self.updateLabel()
    def clearImage(self):
        self.clear()
        self.save()
        self.updateLabel()
    def updateLabel(self):
        if not self._imageformat and hasattr(self._var, 'params'):
            # get vCard specific parameters
            tempset = self._var.params.get('type')
            if tempset and len(tempset) > 0:
                self._imageformat = tempset[0]
            else:
                self._imageformat = "UNKNOWN"
        size = len(self._imagedata)
        if size > 0:
            self.lblSize["text"] = "%d Bytes (base64 encoded %s)" % (size, self._imageformat)
        else:
            self.lblSize["text"] = "<no image>" 
    def get(self):
        return self._imagedata
    def clear(self):
        self._imagedata = ""
        self._imageformat = ""
    def set(self, data):
        self._imagedata = data
        self.updateLabel()
    def loadImageFromFile(self):
        import tkFileDialog, base64
        dlg = tkFileDialog.Open(self.interior(), 
            filetypes=[("Image Files", "*.jpg *.jpeg *.png *.gif"), 
            ("All Files", "*")])
        fname = dlg.show()
        if fname:
            # determine image format
            import os
            fbase, fext = os.path.splitext(fname)
            fext = fext.lower()
            if fext == '.jpg' or fext == '.jpeg':
                self._imageformat = 'JPEG'
            elif fext == '.png':
                self._imageformat = 'PNG'
            elif fext == '.gif':
                self._imageformat = 'GIF'
            else:
                self._imageformat = 'UNKNOWN'
            self.set(base64.encodestring(open(fname, "rb").read()))
            if hasattr(self._var, 'params'):
                # set vCard specific parameters
                import Set
                self._var.params.set('encoding', Set.Set('b'))
                self._var.params.set('type', Set.Set(self._imageformat))
            self.save()
    def saveImageToFile(self):
        import tkFileDialog, base64
        dlg = tkFileDialog.SaveAs(self.interior(), 
            filetypes=[("Image Files", "*.jpg *.jpeg *.png *.gif"), 
            ("All Files", "*")])
        fname = dlg.show()
        if fname:
            fd = open(fname, "wb")
            fd.write(base64.decodestring(self.get()))
            fd.close()

class PropertyEditor(Pmw.Dialog):
    # propdefs = [(type, title, descr)]
    def __init__(self, master, propdefs, **kws):
        Pmw.Dialog.__init__(self, master=master, title=kws.get('title', ''),
            buttons=('Close',), defaultbutton='Close')
        
        self.master = master    
        self.propdefs = propdefs
        self._save_hook = kws.get('save_hook')
        self._editclasses = kws.get('editclasses', {})
        self._addcolon = kws.get('addcolon', ':')
        self.notebook = None
        self.createWidgets()

    def createWidgets(self):
        self.propwidgets = []
        row = 1
        page = self.interior()
        self.interior().columnconfigure(0, weight=1)
        for type, title, descr in self.propdefs:
            if type == "Page":
                row = 0
                if not self.notebook:
                    self.interior().rowconfigure(row, weight=1)
                    self.notebook = Pmw.NoteBook(self.interior())
                    self.notebook.grid(row=row, columnspan=2, sticky=W+E+S+N, padx=PADX, pady=PADY)
                page = self.notebook.add(title)
                page.columnconfigure(0, weight=1)
                page.columnconfigure(1, weight=2)
                continue
            elif type == "Label":
                lbl = Label(page, text=descr)
                lbl.grid(row=row, column=0, columnspan=2, padx=PADX, pady=PADY)
            else:
                if type == "Memo":
                    page.rowconfigure(row, weight=1)
                    widget = MemoPropEdit(page, title, descr)
                    widget.grid(row=row, columnspan=2, sticky=W+E+N+S,
                                padx=PADX, pady=PADY)
                elif type == "Image":
                    page.rowconfigure(row, weight=1)
                    widget = ImagePropEdit(page, title, descr)
                    widget.grid(row=row, columnspan=2, sticky=W+E+N+S,
                                padx=PADX, pady=PADY)
                else:
                    lbl = Label(page, text=title+self._addcolon)
                    lbl.grid(row=row, column=0, padx=PADX, pady=PADY)
                    if type == "Text":
                        widget = TextPropEdit(page, title, descr)
                    elif type == "Checkbox":
                        widget = CheckboxPropEdit(page, title, descr)
                    else:
                        widget = self._editclasses[type](page, title, descr)
                    widget.grid(row=row, column=1, sticky=W+E,
                                padx=PADX, pady=PADY)
                if self._save_hook:
                    widget.add_save_hook(self._save_hook)
                self.propwidgets.append(widget)
            row += 1
            
        if self.notebook:
            self.notebook.setnaturalsize()

    def bindto(self, varlist):
        for var, widget in zip(varlist, self.propwidgets):
            widget.bindto(var)

    _firstshow = 1
    def show(self):
        if self._firstshow:
            self.centerWindow()
        else:
            self.deiconify()
        self._firstshow = 0
            
    def centerWindow(self, relx=0.5, rely=0.3):
        "Center the Window on Screen"
        widget = self
        master = self.master
        widget.update_idletasks() # Actualize geometry information
        if master.winfo_ismapped():
            m_width = master.winfo_width()
            m_height = master.winfo_height()
            m_x = master.winfo_rootx()
            m_y = master.winfo_rooty()
        else:
            m_width = master.winfo_screenwidth()
            m_height = master.winfo_screenheight()
            m_x = m_y = 0
        w_width = widget.winfo_reqwidth()
        w_height = widget.winfo_reqheight()
        x = m_x + (m_width - w_width) * relx
        y = m_y + (m_height - w_height) * rely
        if x+w_width > master.winfo_screenwidth():
            x = master.winfo_screenwidth() - w_width
        elif x < 0:
            x = 0
        if y+w_height > master.winfo_screenheight():
            y = master.winfo_screenheight() - w_height
        elif y < 0:
            y = 0
        widget.geometry("+%d+%d" % (x, y))
        widget.deiconify() # Become visible at the desired location



if __name__ == "__main__":
    import InputWidgets
    propdefs = [
        ("Text", "Test", "Test Descr"),
        ("Text", "Color", "Choose Color"),
        ("Label", "", "Here comes a DateEdit:"),
        ("Date", "Date", "My Date Edit"),
        ("Memo", "Your Ideas", "Please enter your Ideas")]
    class MyDateEdit(InputWidgets.DateEdit):
        def __init__(self, master, title, descr):
            InputWidgets.DateEdit.__init__(self, master)
    tk = Tk()
    dlg = PropertyEditor(tk, propdefs, 
                         title="Property Editor Test",
                         editclasses={"Date":MyDateEdit})
    dlg.show()
    tk.mainloop()
