import re
import datetime, dateutil.tz
import gtk, gobject
from threading import RLock
from usercache import AvCache,NameCache
import webbrowser
import config


class TweetPane(gtk.ScrolledWindow):
    '''
    Box that holds all the TweetBoxes for a given feed

    This box will not update itself, the parent should do that.
    
    It will connect num_entries listeners to its parent's on_reply() and on_retweet()

    It also gets some data from its parent, including num_entries
    '''

    def __init__(self, list_name, username, num_entries=20, single_tweet=None, is_user=False, conversation=False, is_dm=False):
        gtk.ScrolledWindow.__init__(self)

        # If the username is encoded in the tweet pane's name, we really want
        # to use it instead, since it may not match the current api's name
        if re.search(r'(^| ).*/', list_name):
            self.username = re.sub(r'(list: | )?(.*?)/.*$', r'\2', list_name)
        else:
            self.username = username

        self.list_name = list_name
        self.single_tweet = single_tweet
        self.conversation = conversation

        self.num_entries = num_entries
        
        self.is_user = is_user
        self.following = False
        self.verified = False
        self.is_dm = is_dm

        self.tab_label = CloseTabLabel(self.list_name)

        self.message = gtk.Label('Loading...')

        # These handle determining which tweets are unread
        self.last_tweet_read = None
        self.latest_tweet = None
        self.num_new_tweets = 0

        self.tweets = []

        self.init_widgets()


    def init_widgets(self):
        self.tab_label.connect('label-clicked', self.set_tweets_read_callback)

        tweet_box = gtk.VBox()
        viewport = gtk.Viewport()

        if self.is_user:
            self.user_box = UserBox()
            tweet_box.pack_start(self.user_box)

        tweet_box.pack_start(self.message)

        # Build us some labels...
        for i in range(0, self.num_entries):
            self.tweets.append(TweetBox(self.conversation, self.is_user, self.is_dm))
            tweet_box.pack_start(self.tweets[i], expand=False)
            self.tweets[i].connect('reply', self.on_tweet_reply)
            self.tweets[i].connect('retweet', self.on_retweet)
            self.tweets[i].connect('in-reply-to', self.on_tweet_reply_to)
            self.tweets[i].connect('conversation', self.on_tweet_conversation)
            self.tweets[i].connect('show-user', self.on_show_user)
            self.tweets[i].connect('show-hashtag', self.on_show_hashtag)
            self.tweets[i].connect('tweet-read', self.set_tweets_read_callback)

        viewport.add(tweet_box)

        # Several different actions should mark the tweets as 'read'
        self.connect('focus', self.set_tweets_read_callback)
        viewport.connect('button-press-event', self.set_tweets_read_callback)
        self.connect('scroll-event', self.set_tweets_read_callback)
        self.connect('scroll-child', self.set_tweets_read_callback)

        self.add(viewport)
        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
        self.show_all()

        for tweet in self.tweets:
            tweet.hide()

        if self.is_user:
            self.user_box.hide_widgets()


    def update_window(self, statuses):
        if statuses is None:
            if self.last_tweet_read is None:
                self.message.set_label('An error occurred while fetching data')
                self.message.show()
                for i in range(0, self.num_entries):
                    self.tweets[i].hide()
            if config.debug:
                print 'Error fetching data for ' + self.tab_label
            return

        self.message.hide()

        # If this is our first load of this list, don't treat anything as new!
        if self.last_tweet_read is None:
            try:
                ids = [status.id for status in statuses]
                ids.sort()
                ids.reverse()
                self.last_tweet_read = ids[0]
            except IndexError:
                self.last_tweet_read = 0

        # Keep count of the new tweets for posting a status message
        self.num_new_tweets = 0

        for i in range(0, self.num_entries):
            read = True
            if i < len(statuses):
                if statuses[i].id > self.last_tweet_read:
                    read = False
                    if statuses[i].user.screen_name != self.username:
                        self.num_new_tweets += 1
                self.tweets[i].set_status(statuses[i], read)
                self.tweets[i].show()
            else:
                self.tweets[i].clear_status()
                self.tweets[i].hide()

        if self.num_new_tweets > 0:
            self.emit('new-tweets')

        if len(statuses) == 0:
            self.message.set_label('There is no data to display')

        try:
            self.latest_tweet = statuses[0].id
        except IndexError:
            self.latest_tweet = 0

        self.update_tab_label()


    # Update the user_box with profile icon, name, etc...
    # Thread calling this should have the gtk lock...
    def update_user_info(self, user):
        if self.is_user:
            self.user_box.update_info(user)


    # Update the label with the number of unread tweets
    def update_tab_label(self):
        pane_text = self.list_name
        if self.num_new_tweets > 0:
            pane_text += ' (' + str(self.num_new_tweets) + ')'
        self.tab_label.set_label_text(pane_text)


    def get_list_name(self):
        return self.list_name


    def set_tweets_read(self):
        num_read = self.num_new_tweets
        self.last_tweet_read = self.latest_tweet
        self.num_new_tweets = 0
        self.update_tab_label()
        self.emit('tweets-read')



    def set_tweets_read_callback(self, event, arg1=None, arg2=None):
        self.set_tweets_read()

    
    def get_tab_label(self):
        return self.tab_label


    def get_single_tweet(self):
        return self.single_tweet


    def get_conversation(self):
        return self.conversation


    def on_tweet_reply(self, widget):
        if self.is_dm:
            self.emit('tweet-reply-dm', widget.screen_name)
        else:
            self.emit('tweet-reply', {'screen_name': widget.screen_name, 'id': widget.id})


    def on_retweet(self, widget):
        self.emit('tweet-retweet', {'id': widget.id})


    def on_tweet_reply_to(self, widget, data):
        self.emit('tweet-in-reply-to', data)


    def on_tweet_conversation(self, widget, data):
        self.emit('tweet-conversation', data)


    def on_show_user(self, widget, data):
        self.emit('show-user', data)


    def on_show_hashtag(self, widget, data):
        self.emit('show-hashtag', data)


    def get_is_user(self):
        return self.is_user


    def set_lists(self, lists):
        if not self.is_user:
            return

        self.user_box.set_lists(lists)

### end class TweetPane

# signals for TweetPane

gobject.signal_new("tweet-reply", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("tweet-reply-dm", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("tweet-retweet", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("tweet-in-reply-to", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("tweet-conversation", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("show-user", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("show-hashtag", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("new-tweets", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())
gobject.signal_new("tweets-read", TweetPane,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())



class TweetBox(gtk.HBox):

    '''
    GUI for displaying one tweet and associated buttons
    
    Also stores the data necessary for replying or retweeting (id, screen name)
    '''

    def __init__(self, conversation=False, is_user=False, is_dm=False):
        gtk.HBox.__init__(self)

        self.screen_name = None
        self.id = None
        self.in_reply_to_id = None
        self.in_reply_to_screen_name = None
        self.app_url = None

        # Lets the tweetbox know if it is part of a conversation or not
        self.conversation = conversation

        self.is_user = is_user
        self.is_dm = is_dm

        self.init_widgets()


    def init_widgets(self):
        # Build the image
        if not self.is_user:
            self.avatar = gtk.Image()
            self.avatar.set_alignment(0.0, 0.0)
            self.avatar.set_padding(5, 5)
            self.pack_start(self.avatar, expand=False, fill=False)
            self.avatar.hide()

        # Everything else goes in a VBox beside the image
        text_box = gtk.VBox()
        self.pack_start(text_box)

        ## Build the header
        self.user_button = gtk.Button(use_underline=False)
        user_button_eb = gtk.EventBox()
        user_button_eb.add(self.user_button)

        self.time_label = gtk.Label()
        time_label_eb = gtk.EventBox()
        time_label_eb.add(self.time_label)

        self.app_button = gtk.Button(use_underline=False)
        app_button_eb = gtk.EventBox()
        app_button_eb.add(self.app_button)

        self.via_label = gtk.Label(' via ')
        via_label_eb = gtk.EventBox()
        via_label_eb.add(self.via_label)
        
        label_box = gtk.HBox()
        label_box.pack_start(user_button_eb, expand=False)
        label_box.pack_start(time_label_eb, expand=False)
        label_box.pack_start(via_label_eb, expand=False)
        label_box.pack_start(app_button_eb, expand=False)
        text_box.pack_start(label_box)

        # Set the header's properties
        self.user_button.set_relief(gtk.RELIEF_NONE)
        self.user_button.set_alignment(0.0, 0.0)
        user_button_eb.modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse("#ffffff"))
        user_button_eb.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#8888ff"))

        self.time_label.set_alignment(0.0, 0.5)
        time_label_eb.modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse("#ffffff"))
        time_label_eb.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#8888ff"))

        self.via_label.set_alignment(0.0, 0.5)
        via_label_eb.modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse("#ffffff"))
        via_label_eb.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#8888ff"))

        self.app_button.set_relief(gtk.RELIEF_NONE)
        self.app_button.set_alignment(0.0, 0.0)
        app_button_eb.modify_text(gtk.STATE_NORMAL,gtk.gdk.color_parse("#ffffff"))
        app_button_eb.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse("#8888ff"))

        # Handle the header buttons being clicked
        if self.is_user:
            self.user_button.set_sensitive(False)
        else:
            self.user_button.connect('clicked', self.on_user_clicked)
            
        self.app_button.connect('clicked', self.on_app_button_clicked)

        ## Build the text
        self.text = gtk.Label()
        text_align = gtk.Alignment()
        text_align.add(self.text)
        self.text_eb = gtk.EventBox()
        self.text_eb.add(text_align)
        text_box.pack_start(self.text_eb)

        # Set the text's properties
        text_align.set_padding(2, 5, 10, 5)
        self.text.set_alignment(0.0, 0.0)
        self.text.set_selectable(True)
        self.text.set_line_wrap(True)
        if gtk.gtk_version[0] > 2 or (gtk.gtk_version[0] == 2 and gtk.gtk_version[1] >= 18):
            self.text.connect('activate-link', self.on_url_clicked)
            self.text.connect('button-press-event', self.on_mouse_clicked)
            self.text_eb.connect('button-press-event', self.on_mouse_clicked)

        # Build the buttons
        button_box_align = gtk.Alignment()
        button_box_align.set_padding(0, 15, 0, 0)
        button_box = gtk.HBox()
        text_box.pack_start(button_box)

        self.reply_to_button = gtk.Button("")
        self.reply_to_button.set_relief(gtk.RELIEF_NONE)
        button_box.pack_start(self.reply_to_button, expand=False)
        self.reply_to_button.connect("clicked", self.on_in_reply_to_clicked)
        self.reply_to_button.hide()

        self.conversation_button = gtk.Button("(conversation)")
        self.conversation_button.set_relief(gtk.RELIEF_NONE)
        button_box.pack_start(self.conversation_button, expand=False)
        self.conversation_button.connect("clicked", self.on_conversation_clicked)
        
        reply_button = gtk.Button("Reply")
        reply_button.set_relief(gtk.RELIEF_HALF)
        button_box.pack_end(reply_button, expand=False)
        reply_button.connect("clicked", self.on_reply_clicked)

        if not self.is_dm:
            retweet_button = gtk.Button("Retweet")
            retweet_button.set_relief(gtk.RELIEF_HALF)
            button_box.pack_end(retweet_button, expand=False)
            retweet_button.connect("clicked", self.on_retweet_clicked)


    def set_status(self, status, read=True):
        # To avoid leftover data when reusing
        self.clear_status()

        # Set avatar
        if not self.is_user:
            try:
                with AvCache().lock:
                    image = AvCache().map[status.user.screen_name]
                self.avatar.set_from_pixbuf(image)
                self.avatar.show()
            except KeyError:
                self.avatar.hide()

            try:
                with NameCache().lock:
                    name = NameCache().map[status.user.screen_name]
            except KeyError:
                name = status.user.name

        self.set_read(read)

        timezone = dateutil.tz.gettz()
        time_format = "%Y.%m.%d %H:%M:%S %Z"

        # Get the user object
        user = status.user

        # Get user's data for retweeting / replying
        self.screen_name = user.screen_name
        self.id = status.id
        self.in_reply_to_id = status.in_reply_to_status_id
        self.in_reply_to_screen_name = status.in_reply_to_screen_name

        # ... and a formatted timestamp
        timestamp = datetime.datetime.strptime(status.created_at, "%a %b %d %H:%M:%S +0000 %Y")
        timestamp = timestamp.replace(tzinfo=dateutil.tz.gettz('UTC'))
        timestring = timestamp.astimezone(timezone).strftime(time_format)

        # Set the header
        if status.source is not None:
            source = status.source
            if re.match(r'&lt;', source):
                metalabel = gtk.Label()
                metalabel.set_markup(status.source)
                source = metalabel.get_text()
            self.app_url = re.sub(r'.*<a href=\"(.*?)\".*', r'\1', source)
            app_name = re.sub(r'.*<a.*?>(.*)</a>.*', r'\1', source)
            self.app_button.set_label(app_name)
            self.app_button.show()
            self.via_label.show()
        else:
            self.app_button.hide()
            self.via_label.hide()
            self.app_url = ''
            

        if re.match('/', self.app_url):
            self.app_url = 'http://twitter.com' + self.app_url
        elif re.match('web', self.app_url):
            self.app_url = None

        self.time_label.set_label(timestring)

        if self.is_user:
            self.user_button.set_label('')
        else:
            self.user_button.set_label(name + " (" + user.screen_name + ") ")

        ### and the text
        new_text = status.text

        # Clean up odd characters in the text
        new_text = re.sub(r'&(?=[^;]*?( |&|$))', r'&amp;', new_text)
        new_text = re.sub(r'"(?=[^;]*?( |"|$))', r'&quot;', new_text)

        if gtk.gtk_version[0] > 2 or (gtk.gtk_version[0] == 2 and gtk.gtk_version[1] >= 18):
            # Make URLs into links
            new_text = re.sub(r"(http://.*?)(?=[^0-9a-zA-Z.~/_?=&;-]|$)", r'<a href="\1">\1</a>', new_text)
            # Make @ or # refs into links, to be used internally
            new_text = re.sub(r'@(.*?)([^0-9a-zA-Z_]|$)', self._make_user_link, new_text)
            new_text = re.sub(r'#(.*?)([ ;,.:*]|$)', self._make_hashtag_link, new_text)

        self.text.set_markup(new_text)

        # If this is in reply to something, set appropriate label
        if not self.conversation and self.in_reply_to_screen_name and self.in_reply_to_id:
            self.reply_to_button.set_label('in reply to ' + self.in_reply_to_screen_name)
            self.reply_to_button.show()
            self.conversation_button.show()


    def clear_status(self):
        self.user_button.set_label('')
        self.time_label.set_label('')
        self.app_button.set_label('')

        self.text.set_markup('')
        self.screen_name = None
        self.id = None
        self.set_read(True)
        self.reply_to_button.set_label('')
        self.reply_to_button.hide()
        self.conversation_button.hide()
        if not self.is_user:
            self.avatar.hide()


    def set_read(self, read=True):
        if read:
            self.text_eb.modify_bg(gtk.STATE_NORMAL,
                                   gtk.gdk.color_parse("#f2f1f0"))
        else:
            self.text_eb.modify_bg(gtk.STATE_NORMAL,
                                   gtk.gdk.color_parse("#dbffdb"))



    def on_reply_clicked(self, widget):
        self.set_read()
        self.emit('reply')
        self.emit('tweet-read')


    def on_retweet_clicked(self, widget):
        self.set_read()
        self.emit('retweet')
        self.emit('tweet-read')


    def on_in_reply_to_clicked(self, widget):
        self.set_read()
        self.emit('in-reply-to', {'id': self.in_reply_to_id, 'name': self.in_reply_to_screen_name})
        self.emit('tweet-read')


    def on_conversation_clicked(self, widget):
        self.set_read()
        self.emit('conversation', {'id': self.id, 'name': 'conversation'})
        self.emit('tweet-read')


    def on_user_clicked(self, widget):
        self.set_read()
        self.emit('show-user', self.screen_name)
        self.emit('tweet-read')


    def on_app_button_clicked(self, widget):
        self.set_read()
        if self.app_url:
            webbrowser.open(self.app_url)


    def on_mouse_clicked(self, widget, event):
        if event.button == 1:
            self.set_read(True)
            self.emit('tweet-read')

    
    def on_url_clicked(self, widget, uri):
        self.set_read()
        self.emit('tweet-read')

        if re.match(r'@', uri):
            self.emit('show-user', re.sub(r'@', '', uri))
            return True
        if re.match(r'#', uri):
            self.emit('show-hashtag', re.sub(r'#', '', uri))
            return True
            

    def _make_user_link(self, matchobj):
        name = matchobj.group(1)
        if name == '':
            return '@' + matchobj.group(2)
        else:
            return '@<a href="@' + name + '">' + name + '</a>' + matchobj.group(2)

    def _make_hashtag_link(self, matchobj):
        name = matchobj.group(1)
        if name == '':
            return '#' + matchobj.group(2)
        else:
            return '<a href="#' + name + '">#' + name + '</a>' + matchobj.group(2)

# end class TweetBox

# signals for TweetBox
gobject.signal_new("reply", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())
gobject.signal_new("retweet", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())
gobject.signal_new("tweet-read", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())
gobject.signal_new("in-reply-to", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("conversation", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("show-user", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("show-hashtag", TweetBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))



class UserBox(gtk.VBox):
    def __init__(self):
        gtk.VBox.__init__(self)

        self.data_lock = RLock()

        self.user_name = None
        self.following = False
        self.verified = False

        self.info_loaded = False

        self.init_widgets()


    def init_widgets(self):
        self.name_label = gtk.Label()
        self.avatar = gtk.Image()
        self.avatar.set_padding(5, 5)
        self.follow_button = gtk.Button()
        self.at_button = gtk.Button('@')
        self.follow_label = gtk.Label('You are following this user')
        self.verified_label = gtk.Label('Verified account')
        self.list_box = gtk.combo_box_entry_new_text()
        self.list_label = gtk.Label('')

        self.list_box.append_text('add to list')
        self.list_box.set_active(0)
        self.list_box.connect('changed', self.on_add_to_list)

        self.name_label.set_alignment(0.0, 0.0)
        self.follow_label.set_alignment(0.0, 0.0)
        self.verified_label.set_alignment(0.0, 0.0)
        self.list_label.set_alignment(0.0, 0.0)
        
        text_col = gtk.VBox()
        text_col.pack_start(self.name_label, expand=False)
        text_col.pack_start(self.verified_label, expand=False)
        text_col.pack_start(self.follow_label, expand=False)
        text_col.pack_start(self.list_label, expand=False)

        info_row = gtk.HBox()
        info_row.pack_start(self.avatar, expand=False)
        info_row.pack_start(text_col, expand=False)

        button_row = gtk.HBox()
        button_row.pack_start(self.follow_button, expand=False)
        button_row.pack_start(self.at_button, expand=False)
        button_row.pack_start(self.list_box, expand=False)

        self.pack_start(info_row, expand=False)
        self.pack_start(button_row, expand=False)

        self.at_button.connect('clicked', self.on_at_clicked)
        self.follow_button.connect('clicked', self.on_follow_clicked)

        self.show_all()


    def update_info(self, user):
        self.user_name = user.screen_name
        name = ''
        
        try:
            with AvCache().lock:
                image = AvCache().map[user.screen_name]
            self.avatar.set_from_pixbuf(image)
            self.avatar.show()
        except KeyError:
            self.avatar.hide()

        try:
            with NameCache().lock:
                name = NameCache().map[user.screen_name]
        except KeyError:
            name = user.name

        self.name_label.set_text(name + ' (' + self.user_name + ')')

        with self.data_lock:
            self.verified = user.verified
            if self.verified:
                self.verified_label.show()
            else:
                self.verified_label.hide()

            if self.following:
                self.follow_label.show()
            else:
                self.follow_label.hide()

        self.name_label.show()
        self.avatar.show()
        self.at_button.show()
        self.follow_button.show()
        self.list_box.show()

        if self.list_label.get_text() != '':
            self.list_label.show()

        self.info_loaded = True


    def on_follow_clicked(self, event):
        if self.following:
            follow = False # destroy the friendship
        else:
            follow = True

        self.emit('follow-clicked', follow)


    def on_at_clicked(self, widget):
        self.emit('at-clicked', self.user_name)


    def get_following(self):
        with self.data_lock:
            return self.following


    def get_verified(self):
        with self.data_lock:
            return self.verified


    def set_following(self, following):
        with self.data_lock:
            self.following = following
        if following:
            self.follow_button.set_label('Unfollow')
            if self.info_loaded:
                self.follow_label.show()
        else:
            self.follow_button.set_label('Follow')
            self.follow_label.hide()

    
    # Hide widgets until update_user_info is done
    def hide_widgets(self):
        self.at_button.hide()
        self.follow_button.hide()
        self.follow_label.hide()
        self.verified_label.hide()
        self.name_label.hide()
        self.avatar.hide()
        self.list_label.hide()
        self.list_box.hide()

    
    def set_lists(self, lists):
        if not lists:
            return

        list_label_text = 'Lists: '

        for l in lists:
            list_label_text += l + ' '
            
        self.list_label.set_text(list_label_text)


    def list_added(self, new_list):
        pass
        # fixme: this should add the list to the text field, and remove it
        # from the combo box


    def on_add_to_list(self, widget):
        if widget.get_active_text() == 'add to list':
            return

        self.emit('add-to-list', widget.get_active_text())

        widget.set_active(0)

# end class UserBox

# signals for UserBox
gobject.signal_new("add-to-list", UserBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("follow-clicked", UserBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
gobject.signal_new("at-clicked", UserBox,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))



class CloseTabLabel(gtk.EventBox):
    '''
    This class holds a label and a button with an 'I' in it.  This button causes the CloseTabLabel
    to emit a clicked signal
    '''

    def __init__(self, name=None):
        gtk.EventBox.__init__(self)
        self.init_widgets(name)


    # This code modified from create_custom_tab in:
    # http://www.daa.com.au/pipermail/pygtk/2006-April/012216.html
    #
    # My version of this code is a little heinous, but at least it is
    # isolated to its own class
    def init_widgets(self, name):
        #create a custom tab for notebook containing a 
        #label and a button with STOCK_ICON
        tabBox = gtk.HBox(False, 2)
        tabButton=gtk.Button(use_underline=False)
        tabButton.connect('clicked', self.on_clicked)

        self.label = gtk.Label(name)

        #Add a picture on a button
        iconBox = gtk.HBox(False, 0)
        image = gtk.Image()
        image.set_from_stock(gtk.STOCK_CLOSE,gtk.ICON_SIZE_MENU)
        gtk.Button.set_relief(tabButton,gtk.RELIEF_NONE)
        settings = gtk.Widget.get_settings(tabButton)
        (w,h) = gtk.icon_size_lookup_for_settings(settings,gtk.ICON_SIZE_MENU)
        gtk.Widget.set_size_request(tabButton, w + 4, h + 4);
        iconBox.pack_start(image, True, False, 0)
        tabButton.add(iconBox)

        tabBox.pack_start(self.label, False)
        tabBox.pack_start(tabButton, False)

        self.connect('button-press-event', self.on_button_press)

        # needed, otherwise even calling show_all on the notebook won't
        # make the hbox contents appear.
        tabBox.show_all()
        self.add(tabBox)


    def set_label_text(self, new_text):
        self.label.set_text(new_text)


    def on_clicked(self, event):
        self.emit('close-clicked')


    def on_button_press(self, event, direction):
        self.emit('label-clicked')


### end class CloseTabLabel

# signals for CloseTabLabel
gobject.signal_new("close-clicked", CloseTabLabel,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())
gobject.signal_new("label-clicked", CloseTabLabel,
                   gobject.SIGNAL_RUN_LAST,
                   gobject.TYPE_NONE, ())