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

from Tkinter import *
import Pmw
import InputWidgets
import ToolTip
import string
import Set
import broadcaster
from MultiColumnTextList import MultiColumnTextList

class JournalListWidget(Frame):
    def __init__(self, master, model, selcommand):
        Frame.__init__(self, master)
        self.model = model
        self.selcommand = selcommand
        self.textlist = MultiColumnTextList(self,
            selectcommand=self._textlistClick,
            autocolresize=1,
            text_height=10)
        self.textlist.pack(fill=BOTH,expand=TRUE)
        self.textlist.setcolwidthsfromstr(["0000-00-00", "Appointment", "Summary"])
        self.registerAtBroadcaster()

    def textwidget(self):
        return self.textlist.text

    def registerAtBroadcaster(self):
        "Register our Widget's Callback Handlers"
        broadcaster.Register(self.updateList,
            source='Journals', title='Opened')
        broadcaster.Register(self.updateList,
            source='Journals', title='Closed')
        # Import Hook not needed because New and Save will do the job:    
        #broadcaster.Register(self.updateList,
        #    source='Journals', title='Imported')
        broadcaster.Register(self.onJournalSave,
            source='Journal', title='Saved')
        broadcaster.Register(self.onJournalNew,
            source='Journal', title='Added')
        broadcaster.Register(self.onJournalDel,
            source='Journal', title='Deleted')

    def getUpdatedJournalData(self):
        """Returns handle, AttendeeIds of the modified journal
        Call only from a broadcaster callback function"""
        handle = broadcaster.CurrentData()['handle']
        if broadcaster.CurrentTitle() != "Deleted":
            attr = self.model.QueryJournalAttributes([handle], 'AttendeeIds')
            return (handle, attr[0]) 
        else:
            return (handle, None)
                
    def onJournalNew(self):
        handle, attr = self.getUpdatedJournalData()
        self._journalhandles.append(handle)
        self._journalattendees.append(attr)
        #self.textlist.append(attr)
        idx = len(self._journalhandles)-1
        srvidx = self.model.ListJournalHandles().index(handle)
        if idx != srvidx:
            def move(list, x, y):
                temp = list[x]; del list[x]
                list.insert(y, temp)
            # and move our new journal to it's sorted place:    
            move(self._journalhandles, idx, srvidx)
            move(self._journalattendees, idx, srvidx)
            #self.textlist.remove(idx)
            #self.textlist.insert(srvidx, attr)
        self.applyFilter()   
        
    def onJournalDel(self):
        handle, attr = self.getUpdatedJournalData()
        idx = self._journalhandles.index(handle)
        del self._journalhandles[idx]
        del self._journalattendees[idx]
        try:
            idx = self._filteredhandles.index(handle)
            del self._filteredhandles[idx]
        except: 
            self._updateTextList()
        else:    
            self.textlist.remove(idx)    
                
    def onJournalSave(self):
        handle, attr = self.getUpdatedJournalData()
        idx = self._journalhandles.index(handle)
        self._journalattendees[idx] = attr
        # Now get the sorted list from the server:
        srvidx = self.model.ListJournalHandles().index(handle)
        if idx != srvidx:
            def move(list, x, y):
                temp = list[x]; del list[x]
                list.insert(y, temp)
            # and move our saved journal to it's sorted place:    
            move(self._journalhandles, idx, srvidx)
            move(self._journalattendees, idx, srvidx)
        self.applyFilter()
        #self.textlist.remove(idx)
        #self.textlist.insert(srvidx, attr)
        self.selectJournal(handle)

    def _textlistClick(self):
        "Event triggered by clicking on the listbox"
        sel = self.textlist.selected()
        if sel is not None:
            self.selcommand(self._filteredhandles[sel])

    currentFilter = 'All'
    def applyFilter(self, filter=None):
        "If called with no arguments the filter will be unchanged"
        if filter is None:
            filter = self.currentFilter
        else:    
            self.currentFilter = filter
        if filter == "All":
            self._filteredhandles[:] = self._journalhandles
        else:
            self._filteredhandles = []
            for str, handle in zip(self._journalattendees, 
                                   self._journalhandles):
                if str.find(filter) != -1:
                    self._filteredhandles.append(handle)
        self._updateTextList()

    def _updateTextList(self):
        rows = self.model.QueryJournalAttributes(self._filteredhandles,
            ('DateStart','Categories','Summary'))
        self.textlist.clear()
        for row in rows:
            self.textlist.append(row)

    _journalhandles = []
    _journalattendees = []
    _filteredhandles = []
    def updateList(self):
        "Completely update our list"
        self._journalhandles[:] = self._filteredhandles[:] = self.model.ListJournalHandles()
        self._journalattendees = self.model.QueryJournalAttributes(self._journalhandles, 'AttendeeIds')
        self._updateTextList()

    def listFilteredHandles(self):
        return self._filteredhandles

    def selectJournal(self, handle): 
        "Set the listbox selection"
        try:
            idx = self._filteredhandles.index(handle)
            self.textlist.select(idx)
        except ValueError:
            # The Journal does not appear in our filtered list!
            # => We can't select it => Do nothing
            return
        self.textlist.see(idx)
        
