#  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: JournalEditWidget.py 82 2004-07-11 13:01:44Z henning $

from Tkinter import *
import Pmw
import string
import debug
import IconImages
import broadcaster
import broker
from AbstractJournalView import AbstractJournalView
import ToolTip

PADX = PADY = 1

# stores the handle of the journal under edit:
affectedJournal = None
def _broadcast_journal_modify():
    broadcaster.Broadcast('Journal', 'Modified',
        {'handle':affectedJournal}, onceonly=1)
    
currentEditControl = None
def _setcurrentEditControl(event):
    global currentEditControl
    currentEditControl = event.widget

import InputWidgets
from InputWidgets import MultiRecordEdit
class DateEdit(InputWidgets.DateEdit):
    def __init__(self, master, **kws):
        InputWidgets.DateEdit.__init__(self, master, **kws)
        self.add_save_hook(_broadcast_journal_modify)
        self.component('entry').bind('<FocusIn>', _setcurrentEditControl)
class TimeWrapperVar:
    "Wraps a vC_datetime var"
    def __init__(self, datetime):
        self.datetime = datetime
    def set(self, time):
        self.datetime.setTime(time)
    def get(self):
        return self.datetime.getTime()
class DateWrapperVar:
    "Wraps a vC_datetime var"
    def __init__(self, datetime):
        self.datetime = datetime
    def set(self, date):
        self.datetime.setDate(date)
    def get(self):
        return self.datetime.getDate()
class TimeEdit(InputWidgets.TimeEdit):
    def __init__(self, master, **kws):
        InputWidgets.TimeEdit.__init__(self, master, **kws)
        self.add_save_hook(_broadcast_journal_modify)
class MemoEdit(InputWidgets.MemoEdit):
    def __init__(self, master):
        InputWidgets.MemoEdit.__init__(self, master)
        self.add_save_hook(_broadcast_journal_modify)
        self.bind('<FocusIn>', _setcurrentEditControl)
class TextEdit(InputWidgets.TextEdit):
    def __init__(self, master, **kws):
        InputWidgets.TextEdit.__init__(self, master, **kws)
        self.add_save_hook(_broadcast_journal_modify)
        self.bind('<FocusIn>', _setcurrentEditControl)
class TextComboEdit(InputWidgets.TextComboEdit):
    def __init__(self, master, **kws):
        InputWidgets.TextComboEdit.__init__(self, master, **kws)
        self.add_save_hook(_broadcast_journal_modify)
        self.component('entry').bind('<FocusIn>', _setcurrentEditControl)
class MultiSelectButtons(InputWidgets.MultiSelectButtons):
    def __init__(self, master, buttondefs, icons, iconsgrey):
        InputWidgets.MultiSelectButtons.__init__(self, master, buttondefs, icons, iconsgrey)
        self.add_save_hook(_broadcast_journal_modify)
        
class UTCOffsetPropEdit(InputWidgets.AbstractSingleVarEdit, Pmw.EntryField):
    import re
    _utcoffsetregex = re.compile('[-+][0-2][0-9]:[0-5][0-9]')
    def __init__(self, master, title, descr):
        InputWidgets.AbstractSingleVarEdit.__init__(self)
        Pmw.EntryField.__init__(self, master, 
            entry_width = 10,
            entry_justify = LEFT,
            value = "+00:00",
            validate = {'validator' : self.validate},
            modifiedcommand=self.save)
        ToolTip.ToolTip(self, descr)
    def validate(self, str):
        if str:
            if not str[0] in "0123456789+-:":
                return 0 #ERROR
            elif self._utcoffsetregex.match(str) is None:
                return -1 #PARTIAL
            else: return 1 #OK   
        else: return -1 #PARTIAL   
    def get(self):
        return self.getvalue() # inherited from Pmw.EntryField
    def set(self, val):
        self.setvalue(val)

class LatLongPropEdit(InputWidgets.AbstractSingleVarEdit, Frame):
    def __init__(self, master, title, descr):
        InputWidgets.AbstractSingleVarEdit.__init__(self)
        Frame.__init__(self, master)
        self.edtLat = Pmw.EntryField(self, 
            entry_width = 8,
            entry_justify = LEFT,
            value = "0.0",
            validate = {'validator' : 'real',
            'min':-90.0,'max':90.0},
            modifiedcommand=self.save)
        ToolTip.ToolTip(self.edtLat,
            "Latitude as Float (53.5)")
        self.edtLat.grid(row=0, column=0)       
        self.edtLon = Pmw.EntryField(self, 
            entry_width = 8,
            entry_justify = LEFT,
            value = "0.0",
            validate = {'validator' : 'real',
            'min':-90.0,'max':90.0},
            modifiedcommand=self.save)
        ToolTip.ToolTip(self.edtLon,
            "Longitude as Float (10.0)")
        self.edtLon.grid(row=0, column=1)
    def clear(self):
        self.edtLat.clear()
        self.edtLon.clear()
    def get(self):
        ret= str(self.edtLat.getvalue())+";"+str(self.edtLon.getvalue())
        if ret==";": ret = ""
        return ret
    def set(self, val):
        parts = val.split(";")
        if len(parts)<2: parts = ["",""]
        self.edtLat.setvalue(parts[0])
        self.edtLon.setvalue(parts[1])

class URLEdit(Pmw.Group):
    def __init__(self, master):
        Pmw.Group.__init__(self, master, tag_text = "URL")
        master = self.interior()
        self.edtURL = TextEdit(master)
        self.edtURL.add_save_hook(self.updatestate)
        self.btnGotoURL = Button(master, command=self.gotoURL,
            image=IconImages.IconImages["webbrowser"], state=DISABLED)
        self.btnGotoURL.bind("<Enter>", self.updatestate)
        master.columnconfigure(0, weight=1)
        master.rowconfigure(0, weight=1)
        self.edtURL.grid(sticky=W+E+S+N, padx=PADX, pady=PADY)
        self.btnGotoURL.grid(row=0, column=1, padx=PADX, pady=PADY)
    def gotoURL(self):
        import webbrowser
        webbrowser.open(self.edtURL.get(), 1)
    def updatestate(self, event=None):
        if self.edtURL.get():
            self.btnGotoURL["state"] = NORMAL
        else:
            self.btnGotoURL["state"] = DISABLED
    def bindto(self, var):
        self.edtURL.bindto(var)
        self.updatestate()
                
class AttendeeEdit(MultiRecordEdit):
    from vcalendar import vC_attendee
    def __init__(self, master):
        MultiRecordEdit.__init__(self, master, 
            self.vC_attendee, "Attendees", "Attendee")
    defaultlabel = "*Click here to add current contact as attendee*"
    def createBody(self):
        master = self.body

        self.__lblContact = Label(master, cursor='hand2',
            text=self.defaultlabel)
        self.__lblContact.grid(column=0,row=1,sticky=W+E)
        self.__lblContact.bind('<1>', self.onMouseClick)

    def onRecordAdd(self, rec):
        contact = broker.Request('Current Contact')
        # Assign Attendee's Values from vCard:
        rec.assignFromCard(contact)
        if not contact.uid.is_empty():
            uid = "[%s]" % (contact.uid.get())
        else:
            uid = ''    
        self.__lblContact["text"] = "%s <%s> %s" % (contact.fn.get(), rec.get(), uid)
        _broadcast_journal_modify()
    def onRecordDel(self):
        if self.state == DISABLED:
            self.bindtorec(None)
        _broadcast_journal_modify()
        
    def onMouseClick(self, event=None):
        if self.state == DISABLED:
            self._AddRecord()   
        elif self._attendee_uid or self._attendee_fn:
            broadcaster.Broadcast('Journal', 'Attendee Clicked',
                data={'uid':self._attendee_uid,
                      'fn':self._attendee_fn})
        
    _attendee_uid = None        
    _attendee_fn = None 
    def bindtorec(self, rec):
        if rec is None:
            self._attendee_uid = None
            self.__lblContact["text"] = self.defaultlabel
        else:
            fn = rec.params.get('cn')
            if fn is None: fn = ""
            else: fn = fn[0]
            uid = rec.getUID()
            if not uid:
                uidstr = ""
            else:
                uidstr = "[%s]" % uid
            self._attendee_uid = uid
            self._attendee_fn = fn
            self.__lblContact["text"] = "%s <%s> %s" % (fn, rec.get(), uidstr)
            
                
class JournalEditWidget(AbstractJournalView, Frame):
    def __init__(self, master, **kws):
        AbstractJournalView.__init__(self, **kws)
        Frame.__init__(self, master, class_="JournalEdit")
        self.__createWidgets()
        # Catch every Mouse-Click:
        self.bind_all('<1>', self.__EditControlSave)
        self.bind_all('<2>', self.__EditControlSave)
        self.bind_all('<3>', self.__EditControlSave)
    def __EditControlSave(self, event=None):
        if currentEditControl:
            try:
                currentEditControl.save()
            except:
                pass
    def bind_journal(self, journal):
        global affectedJournal
        if journal:
            affectedJournal = journal.handle()
        else:
            affectedJournal = None
        AbstractJournalView.bind_journal(self, journal)
        self.rebindWidgets()
    def rebindWidgets(self):
        self.edtDateStart.bindto(DateWrapperVar(self._journal.dtstart))
        self.edtTimeStart.bindto(TimeWrapperVar(self._journal.dtstart))
        self.edtTimeEnd.bindto(TimeWrapperVar(self._journal.dtend))
        self.edtSummary.bindto(self._journal.summary)
        self.edtCategories.bindto(self._journal.categories)
        self.edtLocation.bindto(self._journal.location)
        self.edtDescr.bindto(self._journal.description)
        self.edtAttendee.bindto(self._journal.attendee)
        self.lblRev["text"] = "Created: %s   Last-Modification: %s" % (self._journal.created.get(), self._journal.last_mod.get())
    def _onTimeEndSave(self):
        if self._journal.dtend.getTime():
            # If End-Time is set:
            # Set End-Date to Start-Date:
            self._journal.dtend.setDate(self._journal.dtstart.getDate())
        else:
            self._journal.dtend.set(None)
    def __createWidgets(self):
        self.columnconfigure(1, weight=1)
        self.rowconfigure(1, weight=1)
        
        # Row 0:
        self.edtDateStart = DateEdit(self)
        ToolTip.ToolTip(self.edtDateStart, 'Date')
        self.edtDateStart.grid(padx=PADX, pady=PADY)
        self.edtSummary = TextEdit(self)
        ToolTip.ToolTip(self.edtSummary, 'Summary')
        self.edtSummary.grid(row=0, column=1, sticky=W+E, padx=PADX, pady=PADY)

        # Row 1:
        self.edtCategories = TextComboEdit(self, entry_width=10)
        ToolTip.ToolTip(self.edtCategories, 'Categories (separate with \',\')')
        self.edtCategories.grid(row=1, column=0, sticky=W+E, padx=PADX, pady=PADY)
        self.edtCategories.setlist(['Appointment','Birthday','Business',
            'Charge','Education','Holiday','Invoice','Meeting',
            'Miscellaneous','Personal',
            'Phone Call','Special Occasion','Travel','Vacation'])
        self.edtDescr = MemoEdit(self)
        ToolTip.ToolTip(self.edtDescr, 'Description')
        # MemoEdit is Pmw.ScrolledText:
        self.edtDescr["text_height"] = 2
        self.edtDescr.grid(row=1, rowspan=2, column=1, sticky=W+E+S+N, padx=PADX, pady=PADY)

        # Row 2:
        self.edtLocation = TextEdit(self, entry_width=10)
        ToolTip.ToolTip(self.edtLocation, 'Location')
        self.edtLocation.grid(row=2, column=0, sticky=W+E, padx=PADX, pady=PADY)

        # Row 3:
        timeframe = Pmw.Group(self, tag_text='Start/End Time')
        self.edtTimeStart = TimeEdit(timeframe.interior(), increment=900) # increment by 15 min
        ToolTip.ToolTip(self.edtTimeStart, 'Time Start')
        self.edtTimeStart.grid(row=0, column=0, padx=PADX, pady=PADY)
        self.edtTimeEnd = TimeEdit(timeframe.interior(), increment=900) # increment by 15 min
        self.edtTimeEnd.add_save_hook(self._onTimeEndSave)
        ToolTip.ToolTip(self.edtTimeEnd, 'Time End')
        self.edtTimeEnd.grid(row=1, column=0, padx=PADX, pady=PADY)
        timeframe.grid(row=3, column=0, sticky=W+E+S+N, padx=PADX, pady=PADY)
        self.edtAttendee = AttendeeEdit(self)
        self.edtAttendee.grid(row=3, column=1, sticky=W+E+S+N, padx=PADX, pady=PADY)
        
        # Row 4:
        self.lblRev = Label(self, anchor=W)
        self.lblRev.grid(row=4, column=0, columnspan=2, sticky=W+E, padx=PADX, pady=PADY)
        
    def focus_set(self):
        self.edtSummary.selection_range(0,END)
        self.edtSummary.focus_set()

if __name__ == "__main__":
    tk = Tk()
    wdgt = JournalEditWidget(tk)
    wdgt.pack(fill=BOTH)
    tk.mainloop()
