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

from copy import copy
from gtk import *
import string

from specific import *
from templates import *

################### 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
    #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,FALSE,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()
        else:
            self.entry_widget.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.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
    #FIXME. Should support dates through GtkCalendar
    if Type == "text" or max(display_size,internal_size)>80:
        x= gtktext_widget(columninfo,description)
    elif Type[:4] == "enum":
        x= gtkenum_widget(columninfo,description)
    else:    
        x= gtkentry_widget(columninfo,description)
    return x










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

        entry=GtkText()
        entry.show()
        #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))
        entry.set_usize(2,40)
        vadj = entry.get_vadjustment()
        vscroll = GtkVScrollbar(vadj)
        self.hbox.pack_start(entry,TRUE,TRUE,0)
        self.hbox.pack_start(vscroll,FALSE,TRUE,0)
        #vscroll.show()
        self.__vscroll=vscroll        
        vadj.connect('changed', self.__chk_scroll)
        
    #provides virtual methods
    def set(self,text):
        self.set_null(text)
        if text == None:
            text=""
        self.entry_widget.delete_text(0, self.entry_widget.get_length())
        self.entry_widget.insert_defaults(str(text))
        self.entry_widget.thaw()
        
    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:
            #FIXME:THIS WOULD BE VERY NICE but sometimes it flashes as crazy...
            self.__vscroll.show()
        else:
            self.__vscroll.show()





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 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(1,"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)

    ##this is enough for all the classes that hinerith this class
    #def set_editable(self,v):
    #    self.entry_widget.set_sensitive(v and self.key != "PRI")
    #    #also block the "nonnull" toggle
    #    self.null_button.set_sensitive(v and self.key != "PRI")
    
