Welcome, guest | Sign In | My Account | Store | Cart
# Author: Miguel Martinez Lopez
# Version: 0.4

try:
    import Tkinter as tk
    import ttk

    import tkFont
    from Tkconstants import *
except ImportError:
    import tkinter as tk
    import tkinter.ttk as ttk

    from tkinter import font as tkFont
    from tkinter.constants import *

# Page label states
NOT_SELECTED = 0
SELECTED = 1

NORMAL_STATE = 0
ACTIVE_STATE = 1


class PageLabel(tk.Label, object):
    def __init__(self, master, is_selected, is_active, is_displayed=True, **kwargs):
        tk.Label.__init__(self, master, **kwargs)
        
        self._page_number = int(kwargs["text"])
        
        self.is_selected = is_selected
        self.is_active = is_active
        
        self.is_displayed = is_displayed

    @property
    def page_number(self):
        return self._page_number
        
    @page_number.setter
    def page_number(self, value):
        self._page_number = value
        self.configure(text=value)

class Pagination(tk.Frame):

    def __init__(self, master, displayed_pages, total_pages, ID=None, background=None, current_page=None, start_page=1, prev_button= "Prev", next_button="Next", first_button="First", last_button="Last", hide_at_edge=False, command =None, pagination_style=None):
        if pagination_style is None:
            raise Exception("No pagination style defined")
        
        self._start_page = start_page
        self._end_page = min(total_pages, start_page + displayed_pages - 1)

        if current_page is None:
            current_page = start_page
        else:
            if not self._start_page <= current_page <= self._end_page:
                raise ValueError("Not valid selected page")

        tk.Frame.__init__(self, master, ID=None, background=background)

        self._command = command
        
        self._hide_at_edge = hide_at_edge

        self._list_of_page_labels = []

        self._total_pages = total_pages        
        self._displayed_pages = displayed_pages

        self._left_controls = None
        self._right_controls = None

        self._previous_label = None
        self._first_label = None        
        self._next_label = None
        self._last_label = None

        self._current_page = current_page
        
        self._button_spacing = pagination_style.get("button_spacing", 0)

        self._config = {}

        for selected_state in (NOT_SELECTED, SELECTED):
            for active_state in (NORMAL_STATE, ACTIVE_STATE):
                self._config[selected_state, active_state] = self._get_configuration_of_state(pagination_style, selected_state, active_state)

        self._render_pagination(current_page, prev_button, next_button, first_button, last_button)

    def _render_pagination(self, current_page, prev_button, next_button, first_button, last_button):
        if self._hide_at_edge:
            if self._start_page == 1:
                self._are_left_controls_displayed = False
            else:
                self._are_left_controls_displayed 

            if self._end_page == self._total_pages:
                self._are_right_controls_displayed = False
            else:
                self._are_right_controls_displayed = True
        else:
            self._are_left_controls_displayed = True
            self._are_right_controls_displayed = True
        
        if first_button is None:
            if prev_button is not None:
                self._left_controls = tk.Frame(self)
                self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing))
                
                self._previous_label = self._navigation_control(self._left_controls, "prev", prev_button)
                self._previous_label.pack(side=LEFT)
        else:
            self._left_controls = tk.Frame(self)
            if self._are_left_controls_displayed:
                self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing))
            
            self._first_label = self._navigation_control(self._left_controls, "first", first_button)
            self._first_label.pack(side=LEFT)

            if prev_button is not None:
                self._previous_label = self._navigation_control(self._left_controls, "prev", prev_button)
                self._previous_label.pack(side=LEFT, padx=(self._button_spacing,0))

        self._page_frame = tk.Frame(self)
        self._page_frame.pack(side=LEFT)
        
        first_page = True
        for page_number in range(self._start_page,self._start_page + self._displayed_pages):
            is_selected = (page_number == self._current_page)

            if page_number <= self._end_page:
                page_label = self._page_label(page_number, is_selected)

                if first_page:
                    first_page = False
                    page_label.pack(side=LEFT)
                else:
                    page_label.pack(side=LEFT, padx=(self._button_spacing, 0))
                    
            else:
                page_label = self._page_label(page_number, is_selected, False)
            self._list_of_page_labels.append(page_label)

        if last_button is None:
            if prev_button is not None:
                self._right_controls = tk.Frame(self)
                self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0))
                
                self._next_label = self._navigation_control(self._right_controls, "next", next_button)               
                self._next_label.pack(side=RIGHT)

        else:
            self._right_controls = tk.Frame(self)
            if self._are_right_controls_displayed:
                self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0))

            self._last_label = self._navigation_control(self._right_controls, "last", last_button)
            self._last_label.pack(side=RIGHT)

            if next_button is not None:
                self._next_label = self._navigation_control(self._right_controls, "next", next_button)
                self._next_label.pack(side=RIGHT, padx=(0,self._button_spacing))

    def _update_labels(self):

        if self._hide_at_edge:
            if self._start_page == 1:
                if self._are_left_controls_displayed:
                    self._are_left_controls_displayed = False
                    self._left_controls.pack_forget()
            else:
                if not self._are_left_controls_displayed:
                    self._are_left_controls_displayed = True
                    self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing), before=self._page_frame)

            if self._end_page == self._total_pages:
                if self._are_right_controls_displayed:
                    self._are_right_controls_displayed = False
                    self._right_controls.pack_forget()
            else:                
                if not self._are_right_controls_displayed:
                    self._are_right_controls_displayed = True
                    self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0), after=self._page_frame)

        first_page_label = True
        for i, page_number in enumerate(xrange(self._start_page, self._end_page+1)):
            page_label = self._list_of_page_labels[i]
            
            if self._current_page == page_number:
                if not page_label.is_selected:
                    self._config_label(page_label, SELECTED, NORMAL_STATE)
                    page_label.is_selected = True
            else:
                if page_label.is_selected:
                    self._config_label(page_label, NOT_SELECTED, NORMAL_STATE)
                    page_label.is_selected = False
            
            if not page_label.is_displayed:
                page_label.is_displayed = True
                
                if first_page_label:
                    page_label.pack(side=LEFT)
                else:
                    page_label.pack(side=LEFT, padx=(self._button_spacing, 0))

            page_label.page_number = page_number
            first_page_label = False

        for i in range(self._end_page-self._start_page+1, self._displayed_pages):
            page_label = self._list_of_page_labels[i]
            
            if page_label.is_displayed:
                page_label.pack_forget()
                page_label.is_displayed = False
    
    def _navigation_control(self, master, control_name, text):
        onclick_control = getattr(self, "%s_page"%control_name)
        
        label = tk.Label(master, text=text, width=0)
        
        self._config_label(label, NOT_SELECTED, NORMAL_STATE)
        label.bind("<1>", lambda event: onclick_control())
        
        label.bind("<Enter>", lambda event, label=label: self._config_label(label, NOT_SELECTED, ACTIVE_STATE))
        label.bind("<Leave>", lambda event, label=label: self._config_label(label, NOT_SELECTED, NORMAL_STATE))

        return label

    def _page_label(self, page_number, is_selected):
        label = PageLabel(self._page_frame, text=page_number, is_selected=is_selected, is_active=False, width=0)
        
        if is_selected:
            self._config_label(label, SELECTED, NORMAL_STATE)
        else:
            self._config_label(label, NOT_SELECTED, NORMAL_STATE)

        label.bind("<1>", lambda event, label=label: self._on_click_page(label))
        
        label.bind("<Enter>", lambda event, label=label: self._on_mouse_enter_page(label))
        label.bind("<Leave>", lambda event, label=label: self._on_mouse_leave_page(label))

        return label

    def _on_mouse_enter_page(self, label):
        label.is_active = True

        if label.is_selected:
            self._config_label(label, SELECTED, ACTIVE_STATE)
        else:
            self._config_label(label, NOT_SELECTED, ACTIVE_STATE)

    def _on_mouse_leave_page(self, label):
        label.is_active = False
        if label.is_selected:
            self._config_label(label, SELECTED, NORMAL_STATE)
        else:
            self._config_label(label, NOT_SELECTED, NORMAL_STATE)

    def _on_click_page(self, new_page):
        if new_page.page_number == self._current_page:
            return

        old_page = self._list_of_page_labels[self._current_page - self._start_page]
        old_page.is_selected = False
        self._config_label(old_page, NOT_SELECTED, NORMAL_STATE)

        new_page.is_selected = True

        self._current_page = new_page.page_number
        self._config_label(new_page, SELECTED, ACTIVE_STATE)

        if self._command is not None:
            self._command(self._current_page)

    def _config_label(self, label, selected_state, active_state):
        label.configure(**self._config[selected_state, active_state])

    def _get_configuration_of_state(self, pagination_style, selected_state, active_state):
        config = {}

        if "font" in pagination_style:
            config["font"] = pagination_style["font"]

        if "font_family" in pagination_style:
            font_family = pagination_style["font_family"]
        else:
            font_family = None

        if "font_size" in pagination_style:
            font_size = pagination_style["font_size"]
        else:
            font_size = None

        if "font_weight" in pagination_style:
            font_weight = pagination_style["font_weight"]
        else:
            font_weight = None

        if "button_padx" in pagination_style:
            config["padx"] = pagination_style["button_padx"]

        if "button_pady" in pagination_style:
            config["pady"] = pagination_style["button_pady"]

        if selected_state == SELECTED:
            state_style = pagination_style["selected_button"]
        else:
            state_style = pagination_style["normal_button"]
        
        if active_state == ACTIVE_STATE:
            if "activebackground" in state_style:
                config["background"] = state_style["activebackground"]
            if "activeforeground" in state_style:
                config["foreground"] = state_style["activeforeground"]
        else:
            if "background" in state_style:
                config["background"] = state_style["background"]
            if "foreground" in state_style:
                config["foreground"] = state_style["foreground"]

        if "padx" in state_style:
            config["padx"] = state_style["padx"]

        if "pady" in state_style:
            config["pady"] = state_style["pady"]

        if "font" in state_style:
            config["font"] = state_style["font"]
        else:
            font_family = state_style.get("font_family", font_family)
            font_size = state_style.get("font_size", font_size)
            font_weight = state_style.get("font_weight", font_weight)
            
            kw = {}
            if font_family is not None:
                kw["family"] = font_family

            if font_size is not None:
                kw["size"] = font_size
                
            if font_family is not None:
                kw["weight"] = font_weight
            
            config["font"] = tkFont.Font(**kw)

        return config

    def select_page(self, page_number, start_page=None):
        self._current_page = page_number
        if start_page is None:
            if page_number < self._start_page:
                self._start_page = page_number
                self._end_page = self._start_page + self._displayed_pages - 1
        else:
            end_page = start_page + self._displayed_pages - 1

            if not start_page <= page_number <= end_page:
                raise ValueError("Page_number not visible")
                
            self._start_page = start_page
            self._end_page = end_page
            
        self._update_labels()

    def prev_page(self):
        if self._current_page == 1: return

        if self._current_page == self._start_page:
            self._start_page -= 1
            self._end_page -= 1

        self._current_page -= 1
        
        if self._command is not None:
            self._command(self._current_page)

        self._update_labels()
        
    def next_page(self):
        if self._current_page == self._total_pages: return

        if self._current_page == self._end_page:
            self._start_page += 1
            self._end_page += 1
            
        self._current_page += 1
        
        if self._command is not None:
            self._command(self._current_page)

        self._update_labels()
        
    def first_page(self):
        if self._current_page == 1: return

        self._start_page = 1
        self._end_page = min(self._total_pages, self._displayed_pages)
        
        self._current_page = 1
        
        if self._command is not None:
            self._command(self._current_page)
        
        self._update_labels()
        
    def last_page(self):
        if self._current_page == self._total_pages: return

        self._end_page = self._total_pages
        self._start_page = max(self._end_page- self._displayed_pages + 1, 1)

        self._current_page = self._total_pages
        
        if self._command is not None:
            self._command(self._current_page)

        self._update_labels()

    @property
    def current_page(self):
        return self._current_page
    
    page = current_page

    @property
    def total_pages(self):
        return self._total_pages

    def update(self, total_pages, current_page, start_page=1):
        end_page = min(total_pages, start_page + self._displayed_pages - 1)

        if not start_page <= current_page <= end_page:
                raise ValueError("Not valid selected page")

        self._start_page = start_page
        self._end_page = end_page
        
        self._total_pages = total_pages
        self._current_page = current_page

        self._update_labels()
    
pagination_style1 = {
    "button_spacing": 3,
    "button_padx":12,
    "button_pady": 6,
    "normal_button": {
        "font": ("Verdana", 10),
        "foreground": "#337ab7", 
        "activeforeground":"#23527c",
        "background": "white",
        "activebackground": "#eee"
    }, 
    "selected_button": {
        "font":("Verdana", 10, "bold"),
        "foreground":"#fff",
        "activeforeground":"#fff", 
        "background":"#337ab7", 
        "activebackground":"#337ab7"
    }
}

pagination_style2 = {
    "button_spacing": 3,
    "button_padx":12,
    "button_pady":6,
    "normal_button": {
        "font": ("Verdana", 10),
        "foreground": "black", 
        "activeforeground":"black",
        "background": "white", 
        "activebackground": "#ccc"
    }, 
    "selected_button": {
        "font":("Verdana", 10, "bold"),
        "foreground":"white",
        "activeforeground":"#fff", 
        "background":"#f44336", 
        "activebackground":"#f44336"
    }
}

pagination_style3 = {
    "button_spacing": 3,
    "button_padx":12,
    "button_pady":6,
    "normal_button": {
        "font": ("Verdana", 10),
        "foreground": "#717171", 
        "activeforeground":"#717171",
        "background": "#e9e9e9", 
        "activebackground": "#fefefe"
    }, 
    "selected_button": {
        "font":("Verdana", 10, "bold"),
        "foreground":"#f0f0f0",
        "activeforeground":"#f0f0f0", 
        "background":"#616161", 
        "activebackground":"#616161"
    }
}

pagination_style4 = {
    "button_spacing": 3,
    "button_padx":12,
    "button_pady":6,
    "normal_button": {
        "font": ("Verdana", 10),
        "foreground": "#feffff", 
        "activeforeground":"#feffff",
        "background": "#3e4347", 
        "activebackground": "#3d4f5d"
    }, 
    "selected_button": {
        "font":("Verdana", 10, "bold"),
        "foreground":"#feffff",
        "activeforeground":"#feffff", 
        "background":"#2f3237", 
        "activebackground":"#2f3237"
    }
}

pagination_style5 = {
    "button_spacing": 3,
    "button_padx":12,
    "button_pady":6,
    "normal_button": {
        "font": ("Verdana", 10),
        "foreground": "#2E4057", 
        "activeforeground":"#2E4057",
        "background": "white", 
        "activebackground": "white"
    }, 
    "selected_button": {
        "font":("Verdana", 10, "bold"),
        "foreground":"white",
        "activeforeground":"white", 
        "background":"#64a281", 
        "activebackground":"#64a281"
    }
}

if __name__ == "__main__":
    
    try:
        from Tkinter import Tk
        from tkMessageBox import showinfo
    except ImportError:
        from tkinter import Tk
        from tkinter.messagebox import showinfo
        
    root = Tk()

    page = tk.Frame()
    page.pack()

    def print_page(page_number):
        print("page number %s"%page_number)

    row = tk.Frame(page)
    row.pack(padx=10, pady=4, fill=X)

    tk.Label(row, text="Pagination").pack(anchor=W)
    
    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style1)
    pagination.pack(pady=10, anchor=W)

    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style2)
    pagination.pack(pady=10, anchor=W)

    pagination = Pagination(row, 5, 50, command=print_page,  pagination_style=pagination_style3)
    pagination.pack(pady=10, anchor=W)

    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style4)
    pagination.pack(pady=10, anchor=W)

    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style5)
    pagination.pack(pady=10, anchor=W)
    
    
    root.mainloop()

Diff to Previous Revision

--- revision 15 2017-01-28 00:29:48
+++ revision 16 2017-04-21 23:13:29
@@ -1,35 +1,30 @@
 # Author: Miguel Martinez Lopez
-# Version: 0.3
-#
-# Uncomment the next line to see my email
-# print("Author's email: %s"%"61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))
+# Version: 0.4
 
 try:
-    from Tkinter import Label
-    from ttk import Frame
-    from Tkconstants import LEFT, RIGHT
+    import Tkinter as tk
+    import ttk
+
+    import tkFont
+    from Tkconstants import *
 except ImportError:
-    from tkinter import Label
-    from tkinter.ttk import Frame
-    from tkinter.constants import LEFT, RIGHT
-
-# Support for Python 3
-try:
-    xrange
-except NameError:
-    xrange = range
-
-
+    import tkinter as tk
+    import tkinter.ttk as ttk
+
+    from tkinter import font as tkFont
+    from tkinter.constants import *
+
+# Page label states
 NOT_SELECTED = 0
 SELECTED = 1
 
-NORMAL = 0
-ACTIVE = 1
-
-
-class PageLabel(Label, object):
+NORMAL_STATE = 0
+ACTIVE_STATE = 1
+
+
+class PageLabel(tk.Label, object):
     def __init__(self, master, is_selected, is_active, is_displayed=True, **kwargs):
-        Label.__init__(self, master, **kwargs)
+        tk.Label.__init__(self, master, **kwargs)
         
         self._page_number = int(kwargs["text"])
         
@@ -47,9 +42,9 @@
         self._page_number = value
         self.configure(text=value)
 
-class Pagination(Frame):
-
-    def __init__(self, master, displayed_pages, total_pages, current_page=None, start_page=1, prev_button= "Prev", next_button="Next", first_button="First", last_button="Last", hide_at_edge=False, command =None, pagination_style=None):
+class Pagination(tk.Frame):
+
+    def __init__(self, master, displayed_pages, total_pages, ID=None, background=None, current_page=None, start_page=1, prev_button= "Prev", next_button="Next", first_button="First", last_button="Last", hide_at_edge=False, command =None, pagination_style=None):
         if pagination_style is None:
             raise Exception("No pagination style defined")
         
@@ -62,7 +57,7 @@
             if not self._start_page <= current_page <= self._end_page:
                 raise ValueError("Not valid selected page")
 
-        Frame.__init__(self, master)
+        tk.Frame.__init__(self, master, ID=None, background=background)
 
         self._command = command
         
@@ -83,7 +78,13 @@
 
         self._current_page = current_page
         
-        self._pagination_style = pagination_style
+        self._button_spacing = pagination_style.get("button_spacing", 0)
+
+        self._config = {}
+
+        for selected_state in (NOT_SELECTED, SELECTED):
+            for active_state in (NORMAL_STATE, ACTIVE_STATE):
+                self._config[selected_state, active_state] = self._get_configuration_of_state(pagination_style, selected_state, active_state)
 
         self._render_pagination(current_page, prev_button, next_button, first_button, last_button)
 
@@ -101,29 +102,27 @@
         else:
             self._are_left_controls_displayed = True
             self._are_right_controls_displayed = True
-
-        button_spacing = self._pagination_style.get("button_spacing", 0)
         
         if first_button is None:
             if prev_button is not None:
-                self._left_controls = Frame(self)
-                self._left_controls.pack(side=LEFT, padx=(0, button_spacing))
+                self._left_controls = tk.Frame(self)
+                self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing))
                 
                 self._previous_label = self._navigation_control(self._left_controls, "prev", prev_button)
                 self._previous_label.pack(side=LEFT)
         else:
-            self._left_controls = Frame(self)
+            self._left_controls = tk.Frame(self)
             if self._are_left_controls_displayed:
-                self._left_controls.pack(side=LEFT, padx=(0, button_spacing))
+                self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing))
             
             self._first_label = self._navigation_control(self._left_controls, "first", first_button)
             self._first_label.pack(side=LEFT)
 
             if prev_button is not None:
                 self._previous_label = self._navigation_control(self._left_controls, "prev", prev_button)
-                self._previous_label.pack(side=LEFT, padx=(button_spacing,0))
-
-        self._page_frame = Frame(self)
+                self._previous_label.pack(side=LEFT, padx=(self._button_spacing,0))
+
+        self._page_frame = tk.Frame(self)
         self._page_frame.pack(side=LEFT)
         
         first_page = True
@@ -137,7 +136,7 @@
                     first_page = False
                     page_label.pack(side=LEFT)
                 else:
-                    page_label.pack(side=LEFT, padx=(button_spacing, 0))
+                    page_label.pack(side=LEFT, padx=(self._button_spacing, 0))
                     
             else:
                 page_label = self._page_label(page_number, is_selected, False)
@@ -145,29 +144,27 @@
 
         if last_button is None:
             if prev_button is not None:
-                self._right_controls = Frame(self)
-                self._right_controls.pack(side=LEFT, padx=(button_spacing, 0))
+                self._right_controls = tk.Frame(self)
+                self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0))
                 
                 self._next_label = self._navigation_control(self._right_controls, "next", next_button)               
                 self._next_label.pack(side=RIGHT)
 
         else:
-            self._right_controls = Frame(self)
+            self._right_controls = tk.Frame(self)
             if self._are_right_controls_displayed:
-                self._right_controls.pack(side=LEFT, padx=(button_spacing, 0))
+                self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0))
 
             self._last_label = self._navigation_control(self._right_controls, "last", last_button)
             self._last_label.pack(side=RIGHT)
 
             if next_button is not None:
                 self._next_label = self._navigation_control(self._right_controls, "next", next_button)
-                self._next_label.pack(side=RIGHT, padx=(0,button_spacing))
+                self._next_label.pack(side=RIGHT, padx=(0,self._button_spacing))
 
     def _update_labels(self):
 
         if self._hide_at_edge:
-            button_spacing = self._pagination_style.get("button_spacing", 0)
-
             if self._start_page == 1:
                 if self._are_left_controls_displayed:
                     self._are_left_controls_displayed = False
@@ -175,7 +172,7 @@
             else:
                 if not self._are_left_controls_displayed:
                     self._are_left_controls_displayed = True
-                    self._left_controls.pack(side=LEFT, padx=(0, button_spacing), before=self._page_frame)
+                    self._left_controls.pack(side=LEFT, padx=(0, self._button_spacing), before=self._page_frame)
 
             if self._end_page == self._total_pages:
                 if self._are_right_controls_displayed:
@@ -184,7 +181,7 @@
             else:                
                 if not self._are_right_controls_displayed:
                     self._are_right_controls_displayed = True
-                    self._right_controls.pack(side=LEFT, padx=(button_spacing, 0), after=self._page_frame)
+                    self._right_controls.pack(side=LEFT, padx=(self._button_spacing, 0), after=self._page_frame)
 
         first_page_label = True
         for i, page_number in enumerate(xrange(self._start_page, self._end_page+1)):
@@ -192,11 +189,11 @@
             
             if self._current_page == page_number:
                 if not page_label.is_selected:
-                    self._config_style(page_label, SELECTED, NORMAL)
+                    self._config_label(page_label, SELECTED, NORMAL_STATE)
                     page_label.is_selected = True
             else:
                 if page_label.is_selected:
-                    self._config_style(page_label, NOT_SELECTED, NORMAL)
+                    self._config_label(page_label, NOT_SELECTED, NORMAL_STATE)
                     page_label.is_selected = False
             
             if not page_label.is_displayed:
@@ -205,7 +202,7 @@
                 if first_page_label:
                     page_label.pack(side=LEFT)
                 else:
-                    page_label.pack(side=LEFT, padx=(button_spacing, 0))
+                    page_label.pack(side=LEFT, padx=(self._button_spacing, 0))
 
             page_label.page_number = page_number
             first_page_label = False
@@ -220,13 +217,13 @@
     def _navigation_control(self, master, control_name, text):
         onclick_control = getattr(self, "%s_page"%control_name)
         
-        label = Label(master, text=text, width=0)
-        
-        self._config_style(label, NOT_SELECTED, NORMAL)
+        label = tk.Label(master, text=text, width=0)
+        
+        self._config_label(label, NOT_SELECTED, NORMAL_STATE)
         label.bind("<1>", lambda event: onclick_control())
         
-        label.bind("<Enter>", lambda event, label=label: self._config_style(label, NOT_SELECTED, ACTIVE))
-        label.bind("<Leave>", lambda event, label=label: self._config_style(label, NOT_SELECTED, NORMAL))
+        label.bind("<Enter>", lambda event, label=label: self._config_label(label, NOT_SELECTED, ACTIVE_STATE))
+        label.bind("<Leave>", lambda event, label=label: self._config_label(label, NOT_SELECTED, NORMAL_STATE))
 
         return label
 
@@ -234,9 +231,9 @@
         label = PageLabel(self._page_frame, text=page_number, is_selected=is_selected, is_active=False, width=0)
         
         if is_selected:
-            self._config_style(label, SELECTED, NORMAL)
-        else:
-            self._config_style(label, NOT_SELECTED, NORMAL)
+            self._config_label(label, SELECTED, NORMAL_STATE)
+        else:
+            self._config_label(label, NOT_SELECTED, NORMAL_STATE)
 
         label.bind("<1>", lambda event, label=label: self._on_click_page(label))
         
@@ -249,16 +246,16 @@
         label.is_active = True
 
         if label.is_selected:
-            self._config_style(label, SELECTED, ACTIVE)
-        else:
-            self._config_style(label, NOT_SELECTED, ACTIVE)
+            self._config_label(label, SELECTED, ACTIVE_STATE)
+        else:
+            self._config_label(label, NOT_SELECTED, ACTIVE_STATE)
 
     def _on_mouse_leave_page(self, label):
         label.is_active = False
         if label.is_selected:
-            self._config_style(label, SELECTED, NORMAL)
-        else:
-            self._config_style(label, NOT_SELECTED, NORMAL)
+            self._config_label(label, SELECTED, NORMAL_STATE)
+        else:
+            self._config_label(label, NOT_SELECTED, NORMAL_STATE)
 
     def _on_click_page(self, new_page):
         if new_page.page_number == self._current_page:
@@ -266,58 +263,88 @@
 
         old_page = self._list_of_page_labels[self._current_page - self._start_page]
         old_page.is_selected = False
-        self._config_style(old_page, NOT_SELECTED, NORMAL)
+        self._config_label(old_page, NOT_SELECTED, NORMAL_STATE)
 
         new_page.is_selected = True
 
         self._current_page = new_page.page_number
-        self._config_style(new_page, SELECTED, ACTIVE)
+        self._config_label(new_page, SELECTED, ACTIVE_STATE)
 
         if self._command is not None:
             self._command(self._current_page)
 
-    def _config_style(self, label, selected_style, active_style):
-        font = self._pagination_style.get("font")
-        button_padx = self._pagination_style.get("button_padx")
-        button_pady = self._pagination_style.get("button_pady")
-
-        if selected_style == SELECTED:
-            style_config = self._pagination_style["selected_button"]
-        else:
-            style_config = self._pagination_style["normal_button"]
-            
+    def _config_label(self, label, selected_state, active_state):
+        label.configure(**self._config[selected_state, active_state])
+
+    def _get_configuration_of_state(self, pagination_style, selected_state, active_state):
         config = {}
-        
-        if active_style == ACTIVE:
-            if "activebackground" in style_config:
-                config["background"] = style_config["activebackground"]
-            if "activeforeground" in style_config:
-                config["foreground"] = style_config["activeforeground"]
-        else:
-            if "background" in style_config:
-                config["background"] = style_config["background"]
-            if "foreground" in style_config:
-                config["foreground"] = style_config["foreground"]
-
-        if "padx" in style_config:
-            config["padx"] = style_config["padx"]
-        else:
-            if button_padx is not None:
-                config["padx"] = button_padx
-
-        if "pady" in style_config:
-            config["pady"] = style_config["pady"]
-        else:
-            if button_pady is not None:
-                config["pady"] = button_pady
-        
-        if "font" in style_config:
-            config["font"] = style_config["font"]
-        else:
-            if font is not None:
-                config["font"] = font
-
-        label.configure(**config)
+
+        if "font" in pagination_style:
+            config["font"] = pagination_style["font"]
+
+        if "font_family" in pagination_style:
+            font_family = pagination_style["font_family"]
+        else:
+            font_family = None
+
+        if "font_size" in pagination_style:
+            font_size = pagination_style["font_size"]
+        else:
+            font_size = None
+
+        if "font_weight" in pagination_style:
+            font_weight = pagination_style["font_weight"]
+        else:
+            font_weight = None
+
+        if "button_padx" in pagination_style:
+            config["padx"] = pagination_style["button_padx"]
+
+        if "button_pady" in pagination_style:
+            config["pady"] = pagination_style["button_pady"]
+
+        if selected_state == SELECTED:
+            state_style = pagination_style["selected_button"]
+        else:
+            state_style = pagination_style["normal_button"]
+        
+        if active_state == ACTIVE_STATE:
+            if "activebackground" in state_style:
+                config["background"] = state_style["activebackground"]
+            if "activeforeground" in state_style:
+                config["foreground"] = state_style["activeforeground"]
+        else:
+            if "background" in state_style:
+                config["background"] = state_style["background"]
+            if "foreground" in state_style:
+                config["foreground"] = state_style["foreground"]
+
+        if "padx" in state_style:
+            config["padx"] = state_style["padx"]
+
+        if "pady" in state_style:
+            config["pady"] = state_style["pady"]
+
+        if "font" in state_style:
+            config["font"] = state_style["font"]
+        else:
+            font_family = state_style.get("font_family", font_family)
+            font_size = state_style.get("font_size", font_size)
+            font_weight = state_style.get("font_weight", font_weight)
+            
+            kw = {}
+            if font_family is not None:
+                kw["family"] = font_family
+
+            if font_size is not None:
+                kw["size"] = font_size
+                
+            if font_family is not None:
+                kw["weight"] = font_weight
+            
+            config["font"] = tkFont.Font(**kw)
+
+        return config
 
     def select_page(self, page_number, start_page=None):
         self._current_page = page_number
@@ -413,143 +440,143 @@
         self._current_page = current_page
 
         self._update_labels()
-
+    
+pagination_style1 = {
+    "button_spacing": 3,
+    "button_padx":12,
+    "button_pady": 6,
+    "normal_button": {
+        "font": ("Verdana", 10),
+        "foreground": "#337ab7", 
+        "activeforeground":"#23527c",
+        "background": "white",
+        "activebackground": "#eee"
+    }, 
+    "selected_button": {
+        "font":("Verdana", 10, "bold"),
+        "foreground":"#fff",
+        "activeforeground":"#fff", 
+        "background":"#337ab7", 
+        "activebackground":"#337ab7"
+    }
+}
+
+pagination_style2 = {
+    "button_spacing": 3,
+    "button_padx":12,
+    "button_pady":6,
+    "normal_button": {
+        "font": ("Verdana", 10),
+        "foreground": "black", 
+        "activeforeground":"black",
+        "background": "white", 
+        "activebackground": "#ccc"
+    }, 
+    "selected_button": {
+        "font":("Verdana", 10, "bold"),
+        "foreground":"white",
+        "activeforeground":"#fff", 
+        "background":"#f44336", 
+        "activebackground":"#f44336"
+    }
+}
+
+pagination_style3 = {
+    "button_spacing": 3,
+    "button_padx":12,
+    "button_pady":6,
+    "normal_button": {
+        "font": ("Verdana", 10),
+        "foreground": "#717171", 
+        "activeforeground":"#717171",
+        "background": "#e9e9e9", 
+        "activebackground": "#fefefe"
+    }, 
+    "selected_button": {
+        "font":("Verdana", 10, "bold"),
+        "foreground":"#f0f0f0",
+        "activeforeground":"#f0f0f0", 
+        "background":"#616161", 
+        "activebackground":"#616161"
+    }
+}
+
+pagination_style4 = {
+    "button_spacing": 3,
+    "button_padx":12,
+    "button_pady":6,
+    "normal_button": {
+        "font": ("Verdana", 10),
+        "foreground": "#feffff", 
+        "activeforeground":"#feffff",
+        "background": "#3e4347", 
+        "activebackground": "#3d4f5d"
+    }, 
+    "selected_button": {
+        "font":("Verdana", 10, "bold"),
+        "foreground":"#feffff",
+        "activeforeground":"#feffff", 
+        "background":"#2f3237", 
+        "activebackground":"#2f3237"
+    }
+}
+
+pagination_style5 = {
+    "button_spacing": 3,
+    "button_padx":12,
+    "button_pady":6,
+    "normal_button": {
+        "font": ("Verdana", 10),
+        "foreground": "#2E4057", 
+        "activeforeground":"#2E4057",
+        "background": "white", 
+        "activebackground": "white"
+    }, 
+    "selected_button": {
+        "font":("Verdana", 10, "bold"),
+        "foreground":"white",
+        "activeforeground":"white", 
+        "background":"#64a281", 
+        "activebackground":"#64a281"
+    }
+}
 
 if __name__ == "__main__":
+    
     try:
         from Tkinter import Tk
-        from Tkconstants import W
+        from tkMessageBox import showinfo
     except ImportError:
         from tkinter import Tk
-        from tkinter.constants import W
-
-    pagination_style1 = {
-        "button_spacing": 3,
-        "button_padx":12,
-        "button_pady": 6,
-        "normal_button": {
-            "font": ("Verdana", 12),
-            "foreground": "#337ab7", 
-            "activeforeground":"#23527c",
-            "background": "white",
-            "activebackground": "#eee"
-        }, 
-        "selected_button": {
-            "font":("Verdana", 12, "bold"),
-            "foreground":"#fff",
-            "activeforeground":"#fff", 
-            "background":"#337ab7", 
-            "activebackground":"#337ab7"
-        }
-    }
-
-    pagination_style2 = {
-        "button_spacing": 3,
-        "button_padx":12,
-        "button_pady":6,
-        "normal_button": {
-            "font": ("Verdana", 12),
-            "foreground": "black", 
-            "activeforeground":"black",
-            "background": "white", 
-            "activebackground": "#ccc"
-        }, 
-        "selected_button": {
-            "font":("Verdana", 12, "bold"),
-            "foreground":"white",
-            "activeforeground":"#fff", 
-            "background":"#f44336", 
-            "activebackground":"#f44336"
-        }
-    }
-
-    pagination_style3 = {
-        "button_spacing": 3,
-        "button_padx":12,
-        "button_pady":6,
-        "normal_button": {
-            "font": ("Verdana", 12),
-            "foreground": "#717171", 
-            "activeforeground":"#717171",
-            "background": "#e9e9e9", 
-            "activebackground": "#fefefe"
-        }, 
-        "selected_button": {
-            "font":("Verdana", 12, "bold"),
-            "foreground":"#f0f0f0",
-            "activeforeground":"#f0f0f0", 
-            "background":"#616161", 
-            "activebackground":"#616161"
-        }
-    }
-
-    pagination_style4 = {
-        "button_spacing": 3,
-        "button_padx":12,
-        "button_pady":6,
-        "normal_button": {
-            "font": ("Verdana", 12),
-            "foreground": "#feffff", 
-            "activeforeground":"#feffff",
-            "background": "#3e4347", 
-            "activebackground": "#3d4f5d"
-        }, 
-        "selected_button": {
-            "font":("Verdana", 12, "bold"),
-            "foreground":"#feffff",
-            "activeforeground":"#feffff", 
-            "background":"#2f3237", 
-            "activebackground":"#2f3237"
-        }
-    }
-
-    pagination_style5 = {
-        "button_spacing": 3,
-        "button_padx":12,
-        "button_pady":6,
-        "normal_button": {
-            "font": ("Verdana", 12),
-            "foreground": "#2E4057", 
-            "activeforeground":"#2E4057",
-            "background": "white", 
-            "activebackground": "white"
-        }, 
-        "selected_button": {
-            "font":("Verdana", 12, "bold"),
-            "foreground":"white",
-            "activeforeground":"white", 
-            "background":"#64a281", 
-            "activebackground":"#64a281"
-        }
-    }
+        from tkinter.messagebox import showinfo
+        
+    root = Tk()
+
+    page = tk.Frame()
+    page.pack()
 
     def print_page(page_number):
         print("page number %s"%page_number)
 
-    root = Tk()
-
-    Label(root, text="Style 1:").pack(padx=20, anchor=W)
-        
-    pagination = Pagination(root, 5, 100, command=print_page, pagination_style=pagination_style1)
-    pagination.pack(pady=(5,20), padx=20)
-    
-    Label(root, text="Style 2:").pack(padx=20, anchor=W)
-    pagination = Pagination(root, 5, 100, command=print_page, pagination_style=pagination_style2)
-    pagination.pack(pady=(5,20), padx=20)
-    
-    Label(root, text="Style 3:").pack(padx=20, anchor=W)
-    pagination = Pagination(root, 5, 50, command=print_page, hide_at_edge=True, pagination_style=pagination_style3)
-    pagination.pack(pady=(5,20), padx=20)
-    
-    Label(root, text="Style 4:").pack(padx=20, anchor=W)
-    pagination = Pagination(root, 5, 100, command=print_page, hide_at_edge=True, pagination_style=pagination_style4)
-    pagination.pack(pady=(5,20), padx=20)
-    
-    pagination.update(total_pages=50, current_page=20, start_page=18)
-    
-    Label(root, text="Style 5:").pack(padx=20, anchor=W)
-    pagination = Pagination(root, 5, 100, command=print_page, hide_at_edge=True, pagination_style=pagination_style5)
-    pagination.pack(pady=(5,20), padx=20)
-
-    pagination.update(total_pages=50, current_page=48, start_page=46)
+    row = tk.Frame(page)
+    row.pack(padx=10, pady=4, fill=X)
+
+    tk.Label(row, text="Pagination").pack(anchor=W)
+    
+    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style1)
+    pagination.pack(pady=10, anchor=W)
+
+    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style2)
+    pagination.pack(pady=10, anchor=W)
+
+    pagination = Pagination(row, 5, 50, command=print_page,  pagination_style=pagination_style3)
+    pagination.pack(pady=10, anchor=W)
+
+    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style4)
+    pagination.pack(pady=10, anchor=W)
+
+    pagination = Pagination(row, 5, 100, command=print_page, pagination_style=pagination_style5)
+    pagination.pack(pady=10, anchor=W)
+    
+    
     root.mainloop()

History