
# you really want to read the templates.py files before
# hacking this file

from copy import copy
import sys
if not sys.modules.has_key('gtk'):
    import pygtk
    pygtk.require('1.2')

from gtk import *
import GtkExtra
import string

from specific import *
from templates import *
import log

################### entry widgets

class hbox_with_notnull(entry_widget_template):
    "base class that sets an hbox with an entry for null/notnull (if neeeded)"
    #the hbox
    hbox=None
    #
    is_editable=0
    #the entry widget, that here is virtual
    entry_widget=None
    def __init__(self,columninfo,description):
        entry_widget_template.__init__(self,columninfo,description)
        
        hbox=GtkHBox()
        hbox.show()
        #this is provided outside
        self.hbox=hbox
        #and this is the effective container widget
        self.widget=hbox

        b=GtkCheckButton("NULL")
        self.null_button=b        
        if not self.not_null:
            b.show()
            hbox.pack_start(b,FALSE,TRUE,0)
            b.connect("toggled",self.__null_toggle)
        
    #callback
    def __null_toggle(self,b):
        #self.entry_widget.set_sensitive( self.not_null or not b.get_active())
        if self.not_null or not b.get_active():
            self.entry_widget.show()
            if hasattr(self,'popup_button'):
                self.popup_button.show()
        else:
            self.entry_widget.hide()
            if hasattr(self,'popup_button'):
                self.popup_button.hide()

    #this is enough for all the classes that inherit  this class
    def set_editable(self,v):
        #v=v and not is_primary(self.columninfo,self.description)
        self.is_editable=v
        self.entry_widget.set_sensitive(v)
        self.null_button.set_sensitive(v)
        #self.entry_widget.set_sensitive(v)
        ##also block the "nonnull" toggle
        #self.null_button.set_sensitive(v)

    #two helpers for other classes which use this class
    def set_null(self,data):
        if data != None or self.not_null:
            self.entry_widget.show()
        else:
            self.entry_widget.hide()
        #self.entry_widget.set_sensitive(not not data)        
        self.null_button.set_active(data == None)

    def get_maybe_null(self,text):
        if self.null_button.get_active() and not self.not_null:       
            return None
        else:
            return text














def appropriate_entry_widget(columninfo,description):
    (Field, Type, Null, Key, Default, Extra) = columninfo
    (name, type_code, display_size, internal_size,
     precision, scale, null_ok)=description

    if Type == "text" or Type[:7] == 'varchar' \
           or max(display_size,internal_size)>80:
        x= gtktext_widget(columninfo,description)
    elif Type[:4] == "enum":        
        x= gtkenum_widget(columninfo,description)
    elif Type[:4] == "date":
        x= gtkdatetime_widget(columninfo,description)
    else:    
        x= gtkentry_widget(columninfo,description)
    return x










            
class gtktext_widget(hbox_with_notnull):
    "edit row entry using a GtkText"
    __popup_window=None
    def __init__(self,columninfo,description):
        hbox_with_notnull.__init__(self,columninfo,description)

        entry=GtkText()
        entry.show()
        entry.connect('focus-in-event',self.__focus_in)
        entry.connect('focus-out-event',self.__focus_out)
        #sets the virtual
        self.entry_widget=entry

        entry.set_flags(CAN_FOCUS)
        entry.set_editable(TRUE)
        
        #FIXME. Size is not enforced
        #entry.set_max_length(max(display_size,internal_size))       
        
        vadj = entry.get_vadjustment()
        vscroll = GtkVScrollbar(vadj)
        
        self.hbox.pack_start(entry,TRUE,TRUE,0)
        self.hbox.pack_start(vscroll,FALSE,FALSE,0)
        
        if hasattr(self.entry_widget,'set_size_request'):
            entry.set_size_request(-1,20)
        else:
            entry.set_usize(-1,20)

        arr=GtkArrow(ARROW_UP, SHADOW_OUT)
        arr.show()
        b=GtkButton()
        b.add(arr)
        #FIXME this needs reviewing
        b.show()
        self.popup_button=b
        
        #b.add(self.label_current)
        b.connect("pressed",self.__popup)
        b.connect("released",self.__popdown)
        self.hbox.pack_start(b,FALSE,FALSE,0)
                 
        #hadj = entry.get_hadjustment()
        #hscroll = GtkHScrollbar(hadj)        
        #self.hbox.pack_start(hscroll,FALSE,TRUE,0)
        #hscroll.show()
        
        #FIXME:THIS WOULD BE VERY NICE but sometimes it flashes as crazy...
        self.__vscroll=vscroll
        #self.__vscroll.show()
        #vadj.connect('changed', self.__chk_scroll)

    def __focus_in(self,a,b):
        if hasattr(self.entry_widget,'set_size_request'):
            self.entry_widget.set_size_request(-1,90)
        else:
            self.entry_widget.set_usize(-1,90)
        self.__vscroll.show()
    def __focus_out(self,a,b):
        if hasattr(self.entry_widget,'set_size_request'):
            self.entry_widget.set_size_request(0,0)
        else:
            self.entry_widget.set_usize(-1,20)
        self.__vscroll.hide()
        
    #provides virtual methods
    def set(self,text):
        self.set_null(text)
        if text == None:
            text=""
        self.entry_widget.freeze()
        self.entry_widget.delete_text(0, self.entry_widget.get_length())
        self.entry_widget.insert_defaults(str(text))
        self.entry_widget.thaw()
        self.entry_widget.set_position(0)
        
    def get(self):
        l=self.entry_widget.get_length()
        return self.get_maybe_null(self.entry_widget.get_chars(0,l))

    def __chk_scroll(self, adj):
        if adj.upper - adj.lower <= adj.page_size:
            self.__vscroll.hide()
        else:
            self.__vscroll.show()


    def __popup(self,b):
        if not self.get():
            return
        if not self.__popup_window:
            e=GtkText()
            e.show()
            e.set_editable(TRUE)
            e.insert_defaults(self.get())
            self.__popup_entry=e
            window1=GtkWindow(WINDOW_POPUP)
            window1.set_policy(FALSE, TRUE, FALSE)
            window1.set_usize(480,280)
            window1.add(e)
            window1.set_position(WIN_POS_MOUSE)
            self.__popup_window=window1
        self.__popup_window.show()
        #self.__popup_entry.insert_defaults(self.get())
        #self.__popup_form.set_row(self.__row)
        
    def __popdown(self,b):
        if self.__popup_window:
            self.__popup_window.hide()
            del self.__popup_window
            self.__popup_window=None
            




class gtkentry_widget(hbox_with_notnull):
    "edit row entry using a GtkEntry"
    def __init__(self,columninfo,description):
        hbox_with_notnull.__init__(self,columninfo,description)
        
        (Field, Type, Null, Key, Default, Extra) = columninfo
        (name, type_code, display_size, internal_size,
         precision, scale, null_ok)=description
        
        entry=GtkEntry()
        #sets the virtual
        self.entry_widget=entry        
        
        entry.set_visibility(TRUE)
        if Type == 'date':
            entry.set_max_length(10)
        elif Type[:9] == 'timestamp':
            #FIXME I have to leave some extra size because timestamps
            # are not correctly managed now (are converted to ISO date)        
            entry.set_max_length(19)
        else:
            entry.set_max_length(max(display_size,internal_size) )
        
        self.hbox.pack_start(entry,TRUE,TRUE,0)
        entry.show()
        entry.set_flags(CAN_FOCUS)
        entry.set_editable(TRUE)
            
    def set(self,text):
        self.set_null(text)
        if text != None:           
            self.entry_widget.set_text(str(text))
        else:
            self.entry_widget.set_text("")

    def get(self):
        return self.get_maybe_null(self.entry_widget.get_text())

    


class gtkdatetime_widget(gtkentry_widget):
    "edit row entry using a GtkEntry"

    __popup_window=None
    
    def __init__(self,columninfo,description):
        gtkentry_widget.__init__(self,columninfo,description)
        a=GtkArrow(ARROW_UP, SHADOW_OUT)
        a.show()
        b=GtkButton()
        b.show()
        b.add(a)
        b.connect("pressed",self.__popup)
        b.connect("released",self.__popdown)
        self.hbox.pack_start(b,FALSE,TRUE,0)
        
    def __select(self,c):
        def s(a):
            return ('000'+str(a))[-2:]
        (y,m,d)=c.get_date()
        m=m+1
        r=self.get()
        if r:
            r=r.split(' ')
            while len(r)>1 and r[-1] == '':
                r=r[:-1]
            while len(r)>1 and r[0] == '':
                r=r[1:]
            if len(r)>1:
                r=' '+r[-1]
            else:
                r=''
        else:
            r=''
        self.set( str(y)+'-'+s(m)+'-'+s(d)+r)        
        self.__popup_window.destroy()
        self.__popup_window=None
    def __popup(self,b):
        f=GtkCalendar()
        r=self.get()
        if r:
            r=r.split(' ')
            da=r[0].split('-')
            if len(da) == 3:
                try:
                    y=int(da[0])
                    m=int(da[1])-1
                    d=int(da[2])                
                    f.select_month(m,y)
                    f.select_day(d)
                except ValueError:
                    pass
        f.show()
        f.connect("day-selected-double-click",self.__select)            
        window1=GtkWindow(WINDOW_TOPLEVEL)
        window1.set_policy(FALSE, TRUE, FALSE)
        window1.add(f)
        window1.set_position(WIN_POS_MOUSE)

        self.widget.connect('destroy',window1.destroy)
        
        
        self.__popup_window=window1
        self.__popup_window.show()
    def __popdown(self,b):
        if self.__popup_window and not self.is_editable :
            self.__popup_window.destroy()
            self.__popup_window=None




class gtkenum_widget(hbox_with_notnull):
    "edit enum entry using a GtkOptionMenu"
    def __init__(self,columninfo,description):
        hbox_with_notnull.__init__(self,columninfo,description)
        
        (Field, Type, Null, Key, Default, Extra) = columninfo
        (name, type_code, display_size, internal_size,
         precision, scale, null_ok)=description
        self.field=Field

        options=Type[5:-1]
        options=string.split(options,',')
        self.options=[]
        self.children=[]
        
        m=GtkMenu()
        for o in options:
            o=o[1:-1]
            self.options.append(o)
            item=GtkMenuItem(o)
            item.show()
            self.children.append(item)
            m.append(item)
        m.show()
        self.menu=m
        #m.popup()

        
        entry=GtkOptionMenu()
        entry.show()
        #sets the virtual
        self.entry_widget=entry        
        entry.set_menu(m)
        
        m.connect("deactivate",self.__m_selected)

        self.entry_widget.set_history(2)
        
        #entry.set_visibility(TRUE)
        
        self.hbox.pack_start(entry,TRUE,TRUE,0)
        entry.show()
        #entry.set_flags(CAN_FOCUS)
        #entry.set_editable(TRUE)
        
    def __m_selected(self,menu_shell):
        #damn, it took me an hour to work this out
        item=self.menu.get_active()
        j=self.children.index(item)
        self.__index=j
    
    def set(self,text):
        #print "set "+self.field+" to "+repr(text)
        self.__index=None
        if text != None:
            try:
                j=self.options.index(text)
            except ValueError:
                self.log(log.LOG_WARNING,"Warning:\n "+self.field+" should be set to "+repr(text)+"\n but this is not a valid key in the enumeration")
                #print "cant set "+self.field+" to "+repr(text)
                text=None
            else:
                self.__index=j
                self.entry_widget.set_history(j)
        self.set_null(text)
                
    def get(self):
        if self.__index != None:
            text=self.options[self.__index]
        else:
            text=None
        #print "get "+self.field+" to "+repr(text)
        return self.get_maybe_null(text)
