erGtkPageBar.c

Go to the documentation of this file.
00001 /**
00002  * \file erGtkPageBar.c
00003  * \brief ereader gtk library - GtkPageBar widget for ereader system
00004  */
00005  
00006 /*
00007  * This file is part of libergtk.
00008  *
00009  * libergtk is free software: you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation, either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * libergtk is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00021  */
00022 
00023 /**
00024  * Copyright (C) 2008 iRex Technologies B.V.
00025  * All rights reserved.
00026  */
00027 
00028 #include <math.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <gtk/gtk.h>
00033 
00034 #include "erGtkPageBar.h"
00035 #include "erGtkDialogJumpToPage.h"
00036 
00037 /* Default settings */
00038 #define PAGEBAR_DEFAULT_PAGE_COUNT              1
00039 #define PAGEBAR_DEFAULT_CURRENT_PAGE            1
00040 
00041 #define PAGEBAR_INDICATOR_SPACE                 2
00042 #define PAGEBAR_CPI_SPACE                       2
00043 #define PAGEBAR_CPI_ADJACENT_SPACE              1
00044 
00045 #define PAGEBAR_ADJACENT_PAGES_NUM              3
00046 
00047 #define PAGEBAR_HORIZONTAL_LINE_WIDTH           2
00048 #define PAGEBAR_INDICATOR_LINE_WIDTH            1
00049 #define PAGEBAR_INDICATOR_LINE_HEIGHT           12
00050 
00051 #define PAGEBAR_INDICATOR_COLOR                 0xAAAAAA
00052 #define PAGEBAR_NEXT_PAGE_TEXT_COLOR            0x555555
00053 #define PAGEBAR_LAST_PAGE_TEXT_COLOR            0x555555
00054  
00055 #define PAGEBAR_BOOKMARK_SENSOR_RANGE           5
00056 
00057 #define PAGEBAR_HORIZONTAL_MARGIN               4
00058 #define PAGEBAR_VERTICAL_MARGIN                 0
00059 
00060 #define PAGEBAR_MAX_PAGES                       1000000
00061 
00062 /* Bitmap index */
00063 typedef enum
00064 {
00065     BITMAP_CPI = 0,
00066     BITMAP_CPI_BOOKMARK,
00067     BITMAP_PREV_CPI,
00068     BITMAP_PREV_CPI_BOOKMARK,
00069     BITMAP_SUCC_CPI,
00070     BITMAP_SUCC_CPI_BOOKMARK,
00071     BITMAP_BOOKMARK,
00072     BITMAP_COUNT
00073 } BitmapIndex;
00074 
00075 static const char * BITMAP_PATHS[BITMAP_COUNT] =
00076 {
00077     DATADIR "/pagebar_pagefield_black.png",
00078     DATADIR "/pagebar_pagefield_black_bookmark.png",
00079     DATADIR "/pagebar_pagefield_grey.png",
00080     DATADIR "/pagebar_pagefield_grey_bookmark.png",
00081     DATADIR "/pagebar_pagefield_white.png",
00082     DATADIR "/pagebar_pagefield_white_bookmark.png",
00083     DATADIR "/pagebar_bookmark_black.png",
00084 };
00085 
00086 /* Page bar status */
00087 typedef enum
00088 {
00089     STATUS_NORMAL = 0,
00090     STATUS_DETAILS,
00091     STATUS_SHRINK
00092 } PagebarStatus;
00093 
00094 struct _GtkPagebar
00095 {
00096     GtkDrawingArea  drawing_area;
00097     GdkPixmap       *pixmap;                  ///< The backend pixmap always has the same size as the widget.
00098     PangoLayout     *pango_layout;            ///< To display the text.
00099     GdkGC           *own_gc;                  ///< Own gc is used for drawing our lines.
00100 
00101     unsigned int    page_count;               ///< The total page number.
00102     unsigned int    current_page;             ///< Current page.
00103     unsigned int    last_selected_page;       ///< Page last selected.
00104 
00105     PagebarStatus   status;                   ///< Page bar status.
00106 
00107     GdkRectangle    cpi_area;                 ///< the area of current page indicator and adjacent pages
00108                                               ///  it is in pagebar coordination system
00109 
00110     GArray          *bookmarks;
00111 
00112     int             pagebar_width;
00113     int             pagebar_height;
00114 
00115     int             left_indicator_offset;
00116     int             right_indicator_offset;
00117 
00118     unsigned int    max_detailed_items;       ///< Max items can be displayed
00119 };
00120 
00121 struct _GtkPagebarClass
00122 {
00123     GtkDrawingAreaClass parent_class;
00124 
00125     // Signal handlers.
00126     void (*pagebar_page_selected) (GtkPagebar * pagebar, int page);
00127 
00128 };
00129 
00130 static GtkDrawingAreaClass *g_parent_class = NULL;
00131 
00132 typedef struct 
00133 {
00134     GdkPixbuf       *bitmaps[BITMAP_COUNT];   ///< All pixbufs.
00135 
00136     int             cpi_width;
00137     int             cpi_height;
00138     int             page_field_width;
00139     int             page_field_height;
00140     int             bookmark_icon_width;
00141     int             bookmark_icon_height;
00142 } bitmap_data_t;
00143 static const bitmap_data_t g_bitmap_data;
00144 
00145 enum 
00146 {
00147     // signals emitted when the user selects a page, using the page bar
00148     PAGE_SELECTED,
00149     LAST_SIGNAL,
00150 };
00151 
00152 static gint pagebar_signals[LAST_SIGNAL] = { 0 };
00153 
00154 /* gtk widget signal handlers. */
00155 static gboolean on_pagebar_exposed(GtkWidget *, GdkEventExpose *, gpointer);
00156 static gboolean on_pagebar_configured(GtkWidget *, GdkEventConfigure *, gpointer);
00157 static gboolean on_pagebar_button_press_event(GtkWidget *, GdkEventButton *, gpointer);
00158 static gboolean on_pagebar_button_release_event(GtkWidget *, GdkEventButton *, gpointer);
00159 
00160 /* gtk pagebar init functions. */
00161 static void gtk_pagebar_class_init(GtkPagebarClass * klass);
00162 static void gtk_pagebar_init(GtkPagebar * pagebar);
00163 static void gtk_pagebar_finalize(GObject *obj);
00164 
00165 /* gtk pagebar bitmap helper functions */
00166 static void pagebar_load_bitmaps(void);
00167 
00168 /* gtk pagebar bookmark helper functions. */
00169 static int get_bookmark_idx(GtkPagebar * pagebar, const unsigned int page_number);
00170 static gboolean add_bookmark(GtkPagebar * pagebar, const unsigned int page_number);
00171 static gboolean remove_bookmark(GtkPagebar * pagebar, const unsigned int page_number);
00172 
00173 /* gtk pagebar calculation helper functions. */
00174 static void pagebar_calculate_cpi(GtkPagebar * pagebar);
00175 static void pagebar_calculate_cpi_overview(GtkPagebar * pagebar);
00176 static void pagebar_calculate_cpi_shrink(GtkPagebar * pagebar);
00177 static void pagebar_calculate_cpi_details(GtkPagebar * pagebar);
00178 
00179 /* gtk pagebar drawing helper functions. */
00180 static void gtk_pagebar_draw(GtkPagebar * pagebar);
00181 static void pagebar_draw_details(GtkPagebar * pagebar);
00182 static void pagebar_draw_overview(GtkPagebar * pagebar);
00183 
00184 static void pagebar_draw_cpi_overview(GtkPagebar * pagebar);
00185 static void pagebar_draw_cpi_shrink(GtkPagebar * pagebar);
00186 
00187 static void pagebar_draw_markers(GtkPagebar * pagebar,
00188                                  const int bitmap,
00189                                  GArray *data,
00190                                  const int adjacent_pages);
00191 
00192 /* gtk paggbar hit test function. */
00193 static int pagebar_calibrate_x_of_marker(GtkPagebar * pagebar, const int origin_x,
00194                                          const int offset);
00195 static int pagebar_get_x_of_marker(GtkPagebar * pagebar, const int page_number,
00196                                    const int adjacent_pages);
00197 
00198 static gboolean pagebar_hit_test_markers(GtkPagebar * pagebar,
00199                                          int click_x, int click_y);
00200 static void pagebar_hit_test_on_cpi_overview(GtkPagebar * pagebar,
00201                                              int click_x, int click_y,
00202                                              int pagebar_width, int pagebar_height);
00203 static void pagebar_hit_test_on_indicator_overview(GtkPagebar * pagebar,
00204                                                    int click_x, int click_y,
00205                                                    int pagebar_width, int pagebar_height);
00206 static void pagebar_hit_test_details(GtkPagebar * pagebar,
00207                                      int click_x, int click_y);
00208 static void pagebar_hit_test_shrink(GtkPagebar * pagebar,
00209                                     int click_x, int click_y,
00210                                     int pagebar_width, int pagebar_height);
00211 static void pagebar_transfer_position(const int x, const int y,
00212                                       int * click_x, int * click_y,
00213                                       gboolean widget_to_pagebar);
00214 /* gtk pagebar signal emit helper function. */
00215 static int on_current_page_changed(GtkPagebar * pagebar);
00216 
00217 
00218 GType gtk_pagebar_get_type(void)
00219 {
00220     static GType pagebar_type = 0;
00221 
00222     if (!pagebar_type)
00223     {
00224     static const GTypeInfo pagebar_info = {
00225         sizeof(GtkPagebarClass),
00226         NULL,       /* base_init */
00227         NULL,       /* base_finalize */
00228         (GClassInitFunc) gtk_pagebar_class_init,
00229         NULL,       /* class_finalize */
00230         NULL,       /* class_data */
00231         sizeof(GtkPagebar),
00232         0,          /* n_preallocs */
00233         (GInstanceInitFunc) gtk_pagebar_init,
00234         NULL        /* *value_table */
00235     };
00236 
00237     pagebar_type =
00238         g_type_register_static(GTK_TYPE_DRAWING_AREA,
00239                                 "erGtkPagebar",
00240                                 &pagebar_info,
00241                                 (GTypeFlags)(0));
00242     }
00243 
00244     return pagebar_type;
00245 }
00246 
00247 void gtk_pagebar_class_init(GtkPagebarClass * klass)
00248 {
00249     GObjectClass *object_class = (GObjectClass *) klass;
00250 
00251     // remember parent class struct, needed for chaining up to parent class
00252     g_parent_class = g_type_class_peek_parent(klass);
00253 
00254     // overload some virtual methods
00255     object_class->finalize = gtk_pagebar_finalize;
00256 
00257     // event to notify page update 
00258     pagebar_signals[PAGE_SELECTED] = g_signal_new("pagebar_page_selected",
00259                                         G_TYPE_FROM_CLASS(object_class), 
00260                                         G_SIGNAL_RUN_LAST,
00261                                         G_STRUCT_OFFSET(GtkPagebarClass, 
00262                                                    pagebar_page_selected),
00263                                         NULL, 
00264                                         NULL, 
00265                                         gtk_marshal_VOID__INT, 
00266                                         G_TYPE_NONE, 
00267                                         1, 
00268                                         G_TYPE_INT);
00269 
00270     // load bitmap details
00271     pagebar_load_bitmaps();
00272 }
00273 
00274 // init instance (constructor)
00275 void gtk_pagebar_init(GtkPagebar * pagebar)
00276 {
00277     gtk_widget_set_events(GTK_WIDGET(pagebar),
00278                           GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK |
00279                           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
00280 
00281     gtk_signal_connect(GTK_OBJECT(pagebar), 
00282                        "expose-event",
00283                        GTK_SIGNAL_FUNC(on_pagebar_exposed), 
00284                        pagebar);
00285 
00286     gtk_signal_connect(GTK_OBJECT(pagebar), 
00287                        "configure-event",
00288                        GTK_SIGNAL_FUNC(on_pagebar_configured), 
00289                        pagebar);
00290 
00291     g_signal_connect(G_OBJECT(pagebar), 
00292                      "button_press_event",
00293                      G_CALLBACK(on_pagebar_button_press_event), 
00294                      pagebar);
00295 
00296     g_signal_connect(G_OBJECT(pagebar),
00297                      "button_release_event",
00298                      G_CALLBACK(on_pagebar_button_release_event), 
00299                      pagebar);
00300 
00301     gtk_widget_show(GTK_WIDGET(pagebar));
00302 }
00303 
00304 // finalize instance (destructor)
00305 static void gtk_pagebar_finalize (GObject *obj)
00306 {
00307     g_return_if_fail( IS_GTK_PAGEBAR(obj) );
00308     GtkPagebar *pagebar = GTK_PAGEBAR(obj);
00309 
00310     // destroy instance data
00311     gtk_pagebar_reset(pagebar);
00312     //   private
00313     if (pagebar->own_gc)
00314     {
00315         g_object_unref(pagebar->own_gc);
00316         pagebar->own_gc = NULL;
00317     }
00318     if (pagebar->pango_layout)
00319     {
00320         g_object_unref(pagebar->pango_layout);
00321         pagebar->pango_layout = NULL;
00322     }
00323     if (pagebar->pixmap)
00324     {
00325         g_object_unref(pagebar->pixmap);
00326         pagebar->pixmap = NULL;
00327     }
00328     
00329     //   public: none
00330 
00331     // chain to parent class
00332     ((GObjectClass*)g_parent_class)->finalize( obj );
00333 }
00334 
00335 // Implement the public interfaces.
00336 GtkWidget *gtk_pagebar_new()
00337 {
00338     GtkPagebar *pagebar = 0;
00339     PangoFontDescription *fontdesc = 0;
00340 
00341     pagebar = (GtkPagebar *) g_object_new(GTK_PAGEBAR_TYPE, NULL);
00342 
00343     pagebar->bookmarks = NULL;
00344 
00345     // Initiailize with default values.
00346     gtk_pagebar_reset(pagebar);
00347 
00348     // Calculate layout. Hard code the font family here.
00349     // Any other good way to handle that? TODO
00350     pagebar->pango_layout =
00351         gtk_widget_create_pango_layout(GTK_WIDGET(pagebar),
00352                                        "X");
00353     fontdesc = 
00354         pango_font_description_from_string("Bitstream Vera Sans Roman 7.2");
00355 
00356     pango_layout_set_font_description(pagebar->pango_layout, fontdesc);
00357     pango_font_description_free(fontdesc);
00358 
00359     pagebar->pixmap = NULL;
00360     pagebar->own_gc = NULL;
00361 
00362     return GTK_WIDGET(pagebar);
00363 }
00364 
00365 /**
00366  * @brief Load a bitmaps from specified files.
00367  * @brief For simplicity these are loaded only once and never released.
00368  */
00369 void pagebar_load_bitmaps(void)
00370 {
00371     bitmap_data_t *data = (bitmap_data_t*) &g_bitmap_data;  // const_cast
00372 
00373     int i;
00374     GError *error = NULL;
00375     const gchar *filename = NULL;
00376 
00377     // Load the bitmaps.
00378     for(i = 0; i < BITMAP_COUNT; ++i)
00379     {
00380         if (data->bitmaps[i] == NULL)
00381         {
00382             filename = BITMAP_PATHS[i];
00383             data->bitmaps[i] = gdk_pixbuf_new_from_file(filename, &error);
00384             if (error)
00385             {
00386                 g_error("Loading bitmap %s error (%s)\n", filename, error->message);
00387                 g_error_free(error);
00388             }
00389         }
00390     }
00391 
00392     // Update the size values.
00393     if (data->bitmaps[BITMAP_CPI])
00394     {
00395         data->cpi_width  = gdk_pixbuf_get_width(data->bitmaps[BITMAP_CPI]);
00396         data->cpi_height = gdk_pixbuf_get_height(data->bitmaps[BITMAP_CPI]);
00397     }
00398     if (data->bitmaps[BITMAP_SUCC_CPI])
00399     {
00400         data->page_field_width = gdk_pixbuf_get_width(data->bitmaps[BITMAP_SUCC_CPI]);
00401         data->page_field_height = gdk_pixbuf_get_height(data->bitmaps[BITMAP_SUCC_CPI]);
00402     }
00403     if (data->bitmaps[BITMAP_BOOKMARK])
00404     {
00405         data->bookmark_icon_width = gdk_pixbuf_get_width(data->bitmaps[BITMAP_BOOKMARK]);
00406         data->bookmark_icon_height = gdk_pixbuf_get_height(data->bitmaps[BITMAP_BOOKMARK]);
00407     }
00408 }
00409 
00410 /**
00411  * @brief Add to boomark list.
00412  */
00413 static gint compare_bookmark(gconstpointer a, gconstpointer b)
00414 {
00415     gint bm_a = *((gint*)(a));
00416     gint bm_b = *((gint*)(b));
00417     if (bm_a > bm_b)
00418     {
00419         return 1;
00420     }
00421     else if (bm_a == bm_b)
00422     {
00423         return 0;
00424     }
00425     return -1;
00426 }
00427 
00428 int get_bookmark_idx(GtkPagebar * pagebar, const unsigned int page_number)
00429 {
00430     unsigned int i;
00431     for(i=0; i < pagebar->bookmarks->len; ++i)
00432     {
00433         if (g_array_index(pagebar->bookmarks, guint, i) == page_number)
00434         {
00435             return i;
00436         }
00437     }
00438 
00439     return -1;
00440 }
00441 
00442 gboolean add_bookmark(GtkPagebar * pagebar, const unsigned int page_number)
00443 {
00444     if (page_number <= 0 || page_number > pagebar->page_count)
00445     {
00446         return FALSE;
00447     }
00448 
00449     if (pagebar->bookmarks == NULL)
00450     {
00451         pagebar->bookmarks = g_array_new(FALSE, FALSE, sizeof(unsigned int));
00452     }
00453 
00454     if (get_bookmark_idx(pagebar, page_number) >= 0)
00455     {
00456         // the bookmark exists
00457         return TRUE;
00458     }
00459 
00460     g_array_append_val(pagebar->bookmarks, page_number);
00461 
00462     g_array_sort (pagebar->bookmarks, compare_bookmark);
00463 
00464     gtk_pagebar_draw(pagebar);
00465 
00466     return TRUE;
00467 }
00468 
00469 /**
00470  * @brief Remove a page from bookmark list.
00471  */
00472 gboolean remove_bookmark(GtkPagebar * pagebar, const unsigned int page_number)
00473 {
00474     if (pagebar->bookmarks == NULL)
00475     {
00476         return FALSE;
00477     }
00478     if (page_number <= 0 || page_number > pagebar->page_count)
00479     {
00480         return FALSE;
00481     }
00482 
00483     int idx = get_bookmark_idx(pagebar, page_number);
00484     if (idx < 0)
00485     {
00486         return FALSE;
00487     }
00488 
00489     pagebar->bookmarks = g_array_remove_index(pagebar->bookmarks, idx);
00490     gtk_pagebar_draw(pagebar);
00491 
00492     return TRUE;
00493 }
00494 
00495 
00496 /* Create a new backing pixmap of the appropriate size */
00497 gboolean on_pagebar_configured(GtkWidget * widget,
00498                                GdkEventConfigure * event, 
00499                                gpointer user_data)
00500 {
00501     GtkPagebar *pagebar = GTK_PAGEBAR(user_data);
00502 
00503     if (pagebar->own_gc)
00504     {
00505         g_object_unref(pagebar->own_gc);
00506         pagebar->own_gc = NULL;
00507     }
00508     if (pagebar->pixmap)
00509     {
00510         g_object_unref(pagebar->pixmap);
00511         pagebar->pixmap = NULL;
00512     }
00513 
00514     // TODO. If we need the "goto" button, this may be changed.
00515     pagebar->pixmap = gdk_pixmap_new(widget->window,
00516                                      widget->allocation.width, 
00517                                      widget->allocation.height, 
00518                                      -1);
00519 
00520     pagebar->own_gc = gdk_gc_new(pagebar->pixmap);
00521 
00522     gdk_draw_rectangle(pagebar->pixmap,
00523                        widget->style->white_gc,
00524                        TRUE, 
00525                        0, 
00526                        0, 
00527                        widget->allocation.width, 
00528                        widget->allocation.height);
00529 
00530     // reset the max_detailed_items
00531     pagebar->max_detailed_items = (widget->allocation.width - g_bitmap_data.cpi_width) /
00532         (g_bitmap_data.page_field_width + PAGEBAR_CPI_SPACE) + 1;
00533 
00534     if (pagebar->page_count > pagebar->max_detailed_items)
00535     {
00536         pagebar->status = STATUS_NORMAL;
00537         int least_len = (g_bitmap_data.page_field_width << 1) +
00538             (g_bitmap_data.page_field_width + PAGEBAR_CPI_SPACE) * (PAGEBAR_ADJACENT_PAGES_NUM << 1) +
00539             (g_bitmap_data.cpi_width + PAGEBAR_CPI_SPACE);
00540 
00541         if (widget->allocation.width < least_len)
00542         {
00543             pagebar->status = STATUS_SHRINK;
00544         }
00545     }
00546     else
00547     {
00548         pagebar->status = STATUS_DETAILS;
00549     }
00550 
00551     // get the width and height of pagebar
00552     gdk_drawable_get_size(pagebar->pixmap, &pagebar->pagebar_width,
00553         &pagebar->pagebar_height);
00554     pagebar->pagebar_width -= (PAGEBAR_HORIZONTAL_MARGIN << 1);
00555     pagebar->pagebar_height -= (PAGEBAR_VERTICAL_MARGIN << 1);
00556 
00557     gtk_pagebar_draw(pagebar);
00558 
00559     return TRUE;
00560 }
00561 
00562 /* Redraw the screen from the backing pixmap */
00563 gboolean on_pagebar_exposed(GtkWidget * widget,
00564                             GdkEventExpose * event,
00565                             gpointer user_data)
00566 {
00567 
00568     GtkPagebar *pagebar = GTK_PAGEBAR(user_data);
00569 
00570     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), FALSE);
00571     
00572     // Copy damaged region of image from pixmap to output 
00573     gdk_draw_drawable(widget->window,
00574                       widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00575                       pagebar->pixmap,
00576                       event->area.x, event->area.y,
00577                       event->area.x, event->area.y,
00578                       event->area.width, event->area.height);
00579 
00580     return FALSE;
00581 }
00582 
00583 void pagebar_transfer_position(const int x, const int y,
00584                                int * click_x, int * click_y,
00585                                gboolean widget_to_pagebar)
00586 {
00587     if (widget_to_pagebar)
00588     {
00589         *click_x = x - PAGEBAR_HORIZONTAL_MARGIN;
00590         *click_y = y - PAGEBAR_VERTICAL_MARGIN;
00591     }
00592     else
00593     {
00594         // page bar to widget
00595         *click_x = x + PAGEBAR_HORIZONTAL_MARGIN;
00596         *click_y = y + PAGEBAR_VERTICAL_MARGIN;
00597     }
00598 }
00599 
00600 gboolean pagebar_hit_test_markers(GtkPagebar * pagebar,
00601                                   int click_x, int click_y)
00602 {
00603     // it is in page bar coordination system
00604     GArray *markers = pagebar->bookmarks;
00605     if (markers == NULL)
00606     {
00607         return FALSE;
00608     }
00609 
00610     int dst_page = -1;
00611     unsigned int idx = 0;
00612     for (; idx < markers->len; idx++)
00613     {
00614         // get pagenumber by mark
00615         int mark_page = g_array_index(markers, guint, idx);
00616         int marker_x = pagebar_get_x_of_marker(pagebar, mark_page, PAGEBAR_ADJACENT_PAGES_NUM);
00617         if (marker_x < 0)
00618         {
00619             continue;
00620         }
00621         if (click_x < (marker_x + PAGEBAR_BOOKMARK_SENSOR_RANGE +
00622             g_bitmap_data.bookmark_icon_width) &&
00623             click_x > (marker_x - PAGEBAR_BOOKMARK_SENSOR_RANGE))
00624         {
00625             // successfully find the bookmark
00626             dst_page = mark_page;
00627             break;
00628         }
00629     }
00630 
00631     if (dst_page > 0)
00632     {
00633         pagebar->current_page = dst_page;
00634         on_current_page_changed(pagebar);
00635         return TRUE;
00636     }
00637 
00638     return FALSE;
00639 }
00640 
00641 void pagebar_hit_test_on_cpi_overview(GtkPagebar * pagebar,
00642                                       int click_x, int click_y,
00643                                       int pagebar_width, int pagebar_height)
00644 {
00645     // it is in page bar coordination system
00646     int first_page = pagebar->current_page - PAGEBAR_ADJACENT_PAGES_NUM;
00647     if (first_page < 1)
00648     {
00649         first_page = 1;
00650     }
00651     unsigned int last_page = pagebar->current_page + PAGEBAR_ADJACENT_PAGES_NUM;
00652     if (last_page > pagebar->page_count)
00653     {
00654         last_page = pagebar->page_count;
00655     }
00656 
00657     unsigned int idx = first_page;
00658     int cur_x = pagebar->cpi_area.x;
00659     int cur_width = g_bitmap_data.page_field_width;
00660     for (; idx <= last_page; ++idx)
00661     {
00662         if (idx == pagebar->current_page)
00663         {
00664             cur_width = g_bitmap_data.cpi_width + PAGEBAR_CPI_SPACE;
00665         }
00666         else if (idx == (pagebar->current_page - 1))
00667         {
00668             cur_width = g_bitmap_data.page_field_width + PAGEBAR_CPI_SPACE;
00669         }
00670         else
00671         {
00672             cur_width = g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE;
00673         }
00674 
00675         if (click_x >= cur_x && click_x <= cur_x + cur_width)
00676         {
00677             // Test to see if the current page has been clicked
00678             if (idx == pagebar->current_page)
00679             {
00680                 // Show a jump to page dialog and use the result
00681                 GtkWidget* jump_to_page_dialog = ergtk_jump_to_page_dialog_new();
00682                 int response = gtk_dialog_run(GTK_DIALOG(jump_to_page_dialog));
00683                 gtk_widget_destroy(jump_to_page_dialog);
00684 
00685                 if (response > 0)
00686                 {
00687                     if (response <= (int) pagebar->page_count)
00688                     {
00689                         pagebar->current_page = response;
00690                     }
00691                     else
00692                     {
00693                         pagebar->current_page = pagebar->page_count;
00694                     }
00695                 }
00696             }
00697             else
00698             {
00699                 pagebar->current_page = idx;
00700             }
00701             break;
00702         }
00703 
00704         cur_x += cur_width;
00705     }
00706     on_current_page_changed(pagebar);
00707 }
00708 
00709 void pagebar_hit_test_on_indicator_overview(GtkPagebar * pagebar,
00710                                    int click_x, int click_y,
00711                                    int pagebar_width, int pagebar_height)
00712 {
00713     // it is in page bar coordination system
00714     if (pagebar_hit_test_markers(pagebar, click_x, click_y))
00715     {
00716         return;
00717     }
00718 
00719     // calculate the left length and right length
00720     int left_len = 0, right_len = 0;
00721     if (pagebar->cpi_area.x > 0)
00722     {
00723         left_len = pagebar->cpi_area.x - g_bitmap_data.page_field_width;
00724     }
00725     int cpi_right = pagebar->cpi_area.x + pagebar->cpi_area.width;
00726     if (cpi_right < pagebar_width)
00727     {
00728         right_len = pagebar_width - g_bitmap_data.page_field_width - cpi_right;
00729     }
00730 
00731     // coordination transform
00732     int x = click_x;
00733     int first_page = 1;
00734     int pages_left = 0;
00735     int offset_page = 0;
00736     // check x is located in left or right
00737     if (x < pagebar->cpi_area.x)
00738     {
00739         // locate in left
00740         x -= g_bitmap_data.page_field_width;
00741         first_page = 1;
00742         pages_left = (pagebar->current_page - PAGEBAR_ADJACENT_PAGES_NUM) -
00743             first_page;
00744         offset_page = x * pages_left / left_len;
00745     }
00746     else
00747     {
00748         x -= cpi_right;
00749         first_page = pagebar->current_page + PAGEBAR_ADJACENT_PAGES_NUM;
00750         pages_left = (pagebar->page_count - 1) - first_page;
00751         offset_page = x * pages_left / right_len;
00752     }
00753 
00754     if (offset_page <= 0)
00755     {
00756         offset_page = 1;
00757     }
00758     pagebar->current_page = first_page + offset_page;
00759 
00760     on_current_page_changed(pagebar);
00761 }
00762 
00763 // TODO: move duplicate code in a common function; compare this function with pagebar_hit_test_on_cpi_overview()
00764 void pagebar_hit_test_details(GtkPagebar * pagebar,
00765                               int click_x, int click_y)
00766 {
00767     // it is in page bar coordination system
00768     // the detail is drawn
00769     unsigned int idx = 1;
00770     int cur_x = pagebar->cpi_area.x;
00771     int cur_width = g_bitmap_data.page_field_width;
00772     for (; idx <= pagebar->page_count; ++idx)
00773     {
00774         if (idx == pagebar->current_page)
00775         {
00776             cur_width = g_bitmap_data.cpi_width + PAGEBAR_CPI_SPACE;
00777         }
00778         else if (idx == (pagebar->current_page - 1))
00779         {
00780             cur_width = g_bitmap_data.page_field_width + PAGEBAR_CPI_SPACE;
00781         }
00782         else
00783         {
00784             cur_width = g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE;
00785         }
00786 
00787         if (click_x >= cur_x && click_x <= cur_x + cur_width)
00788         {
00789             // Test to see if the current page has been clicked
00790             if (idx == pagebar->current_page)
00791             {
00792                 // Show a jump to page dialog and use the result
00793                 GtkWidget* jump_to_page_dialog = ergtk_jump_to_page_dialog_new();
00794                 int response = gtk_dialog_run(GTK_DIALOG(jump_to_page_dialog));
00795                 gtk_widget_destroy(jump_to_page_dialog);
00796 
00797                 if (response > 0)
00798                 {
00799                     if (response <= (int) pagebar->page_count)
00800                     {
00801                         pagebar->current_page = response;
00802                     }
00803                     else
00804                     {
00805                         pagebar->current_page = pagebar->page_count;
00806                     }
00807                 }
00808             }
00809             else
00810             {
00811                 pagebar->current_page = idx;
00812             }
00813             break;
00814         }
00815 
00816         cur_x += cur_width;
00817     }
00818     on_current_page_changed(pagebar);
00819 }
00820 
00821 void pagebar_hit_test_shrink(GtkPagebar * pagebar,
00822                              int click_x, int click_y,
00823                              int pagebar_width, int pagebar_height)
00824 {
00825     // it is in page bar coordination system
00826     int x = click_x;
00827     if (x >= pagebar->cpi_area.x &&
00828         x <= pagebar->cpi_area.x + pagebar->cpi_area.width)
00829     {
00830         // it is current page
00831         // TODO: do we need to add the call to display the "JumpToPage" dialog here too?
00832         return;
00833     }
00834     else if (x >= 0 && x <= g_bitmap_data.page_field_width)
00835     {
00836         pagebar->current_page = 1;
00837     }
00838     else if (x <= pagebar_width && x >= pagebar_width - g_bitmap_data.page_field_width)
00839     {
00840         pagebar->current_page = pagebar->page_count;
00841     }
00842     else
00843     {
00844         if (pagebar_hit_test_markers(pagebar, click_x, click_y))
00845         {
00846             // hit test the bookmark at first
00847             return;
00848         }
00849 
00850         // calculate the position in overview
00851         int overview_length = pagebar_width - pagebar->cpi_area.width;
00852         if (pagebar->current_page > 1 && pagebar->current_page < pagebar->page_count)
00853         {
00854             overview_length -= g_bitmap_data.page_field_width << 1;
00855         }
00856         else
00857         {
00858             overview_length -= g_bitmap_data.page_field_width;
00859         }
00860 
00861         // coordination transform
00862         int cpi_shrink_x = x;
00863         if (pagebar->cpi_area.x > 0)
00864         {
00865             cpi_shrink_x -= g_bitmap_data.page_field_width;
00866         }
00867 
00868         if (x > pagebar->cpi_area.x)
00869         {
00870             cpi_shrink_x -= pagebar->cpi_area.width;
00871         }
00872 
00873         pagebar->current_page = cpi_shrink_x * pagebar->page_count / overview_length;
00874         if (pagebar->current_page < 1)
00875         {
00876             // current page might be 0
00877             pagebar->current_page = 1;
00878         }
00879     }
00880 
00881     on_current_page_changed(pagebar);
00882 }
00883 
00884 /**
00885  * Event handlers.
00886  */
00887 gboolean on_pagebar_button_release_event(GtkWidget * widget,
00888                                          GdkEventButton * event, 
00889                                          gpointer user_data)
00890 {
00891 
00892     return TRUE;
00893 }
00894 
00895 int on_current_page_changed(GtkPagebar * pagebar)
00896 {
00897     if (pagebar->last_selected_page == pagebar->current_page)
00898     {
00899         return 0;
00900     }
00901 
00902     pagebar->last_selected_page = pagebar->current_page;
00903     gtk_pagebar_draw(pagebar);
00904 
00905     g_signal_emit(pagebar, 
00906                   pagebar_signals[PAGE_SELECTED], 
00907                   0, 
00908                   pagebar->current_page);
00909     return 1;
00910 }
00911 
00912 gboolean on_pagebar_button_press_event(GtkWidget * widget,
00913                                        GdkEventButton * event, 
00914                                        gpointer user_data)
00915 {
00916     GtkPagebar *pagebar = GTK_PAGEBAR(user_data);
00917     int x = (int)(event->x);
00918     int y = (int)(event->y);
00919     pagebar_transfer_position(x, y, &x, &y, TRUE);
00920 
00921     int pagebar_width = pagebar->pagebar_width;
00922     int pagebar_height = pagebar->pagebar_height;
00923 
00924     if (pagebar->status == STATUS_NORMAL)
00925     {
00926         if (x >= pagebar->cpi_area.x &&
00927             x <= pagebar->cpi_area.x + pagebar->cpi_area.width)
00928         {
00929             pagebar_hit_test_on_cpi_overview(pagebar, x, y, pagebar_width, pagebar_height);
00930         }
00931         else if (x > g_bitmap_data.page_field_width && x < (pagebar_width - g_bitmap_data.page_field_width))
00932         {
00933             pagebar_hit_test_on_indicator_overview(pagebar, x, y, pagebar_width, pagebar_height);
00934         }
00935         else if (x <= g_bitmap_data.page_field_width)
00936         {
00937             pagebar->current_page = 1;
00938             on_current_page_changed(pagebar);
00939         }
00940         else if (x >= pagebar_width - g_bitmap_data.page_field_width)
00941         {
00942             pagebar->current_page = pagebar->page_count;
00943             on_current_page_changed(pagebar);
00944         }
00945     }
00946     else if (pagebar->status == STATUS_DETAILS)
00947     {
00948         pagebar_hit_test_details(pagebar, x, y);
00949     }
00950     else
00951     {
00952         pagebar_hit_test_shrink(pagebar, x, y, pagebar_width, pagebar_height);
00953     }
00954 
00955     return TRUE;
00956 }
00957 
00958 void gtk_pagebar_set_number_of_pages(GtkPagebar * pagebar,
00959                                      const unsigned int number)
00960 {
00961     g_return_if_fail(IS_GTK_PAGEBAR(pagebar));
00962     g_return_if_fail((number <= PAGEBAR_MAX_PAGES));
00963 
00964     pagebar->page_count = number;
00965 
00966     if (pagebar->page_count > pagebar->max_detailed_items)
00967     {
00968         pagebar->status = STATUS_NORMAL;
00969     }
00970     else
00971     {
00972         pagebar->status = STATUS_DETAILS;
00973     }
00974 
00975     gtk_pagebar_draw(pagebar);
00976 }
00977 
00978 unsigned int gtk_pagebar_get_number_of_pages(GtkPagebar * pagebar)
00979 {
00980     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), -1);
00981 
00982     return pagebar->page_count;
00983 }
00984 
00985 gboolean gtk_pagebar_set_current_page(GtkPagebar * pagebar,
00986                                       const unsigned int current)
00987 {
00988     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), FALSE);
00989 
00990     if (pagebar->current_page != current)
00991     {
00992         pagebar->current_page = current;
00993         pagebar->last_selected_page = current;
00994         gtk_pagebar_draw(pagebar);
00995     }
00996     return TRUE;
00997 }
00998 
00999 unsigned int gtk_pagebar_get_current_page(GtkPagebar * pagebar)
01000 {
01001     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), -1);
01002 
01003     return pagebar->current_page;
01004 }
01005 
01006 gboolean gtk_pagebar_set_bookmark(GtkPagebar * pagebar,
01007                                   const unsigned int page)
01008 {
01009     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), FALSE);
01010     g_return_val_if_fail((page > 0 && page <= pagebar->page_count), FALSE);
01011 
01012     return add_bookmark(pagebar, page);
01013 }
01014 
01015 gboolean gtk_pagebar_delete_bookmark(GtkPagebar * pagebar,
01016                                      const unsigned int page)
01017 {
01018     return remove_bookmark(pagebar, page);
01019 }
01020 
01021 const GArray* gtk_pagebar_get_bookmarks(GtkPagebar * pagebar)
01022 {
01023     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), NULL);
01024 
01025     return pagebar->bookmarks;
01026 }
01027 
01028 void gtk_pagebar_reset(GtkPagebar * pagebar)
01029 {
01030     g_return_if_fail(IS_GTK_PAGEBAR(pagebar));
01031 
01032     pagebar->page_count = PAGEBAR_DEFAULT_PAGE_COUNT;
01033     pagebar->current_page = PAGEBAR_DEFAULT_CURRENT_PAGE;
01034     pagebar->status = STATUS_NORMAL;
01035 
01036     if (pagebar->bookmarks)
01037     {
01038         g_array_free(pagebar->bookmarks, TRUE);
01039         pagebar->bookmarks = NULL;
01040     }
01041 
01042     // Do not release the bitmap here.
01043 }
01044 
01045 unsigned int gtk_pagebar_get_minimal_height(GtkPagebar * pagebar)
01046 {
01047     g_return_val_if_fail(IS_GTK_PAGEBAR(pagebar), 0);
01048 
01049     return MAX(g_bitmap_data.cpi_height, g_bitmap_data.page_field_height);
01050 }
01051 
01052 gboolean is_page_marked(GArray * markers, int page_number)
01053 {
01054     if (markers == NULL)
01055     {
01056         return FALSE;
01057     }
01058 
01059     unsigned int idx = 0;
01060     int mark_page = 0;
01061     for (; idx < markers->len; idx++)
01062     {
01063         mark_page = g_array_index(markers, guint, idx);
01064         if (mark_page == page_number)
01065         {
01066             return TRUE;
01067         }
01068     }
01069 
01070     return FALSE;
01071 }
01072 
01073 int pagebar_calibrate_x_of_marker(GtkPagebar * pagebar, const int origin_x,
01074                                   const int offset)
01075 {
01076     int x = origin_x;
01077     x -= offset;
01078 
01079     int num_lines = x / (PAGEBAR_INDICATOR_SPACE + PAGEBAR_INDICATOR_LINE_WIDTH);
01080     if (num_lines > 0)
01081     {
01082         num_lines --;
01083     }
01084     x = offset + num_lines * (PAGEBAR_INDICATOR_SPACE + PAGEBAR_INDICATOR_LINE_WIDTH)
01085         - (g_bitmap_data.bookmark_icon_width >> 1);
01086 
01087     return x;
01088 }
01089 
01090 int pagebar_get_x_of_marker(GtkPagebar * pagebar, const int page_number,
01091                             const int adjacent_pages)
01092 {
01093     // it is in page bar coordination system
01094 
01095     int pagebar_width = pagebar->pagebar_width;
01096     // int pagebar_height = pagebar->pagebar_height;
01097 
01098     int x = 0;
01099     int start_x = 0;
01100     int offset = 0;
01101 
01102     if (page_number >= (int) (pagebar->current_page - adjacent_pages) &&
01103         page_number <= (int) (pagebar->current_page + adjacent_pages))
01104     {
01105         return -1;
01106     }
01107     else if (page_number == 1)
01108     {
01109         return -1;
01110     }
01111     else if (page_number == (int) pagebar->page_count)
01112     {
01113         return -1;
01114     }
01115 
01116     if (page_number > (int) pagebar->current_page)
01117     {
01118         // calculate the length of right part
01119         start_x = pagebar->cpi_area.x + pagebar->cpi_area.width;
01120         int right_len = (pagebar_width - g_bitmap_data.page_field_width) - start_x;
01121 
01122         x = (page_number - pagebar->current_page- adjacent_pages) * right_len /
01123             (pagebar->page_count - pagebar->current_page - adjacent_pages - 1);
01124 
01125         offset = pagebar->right_indicator_offset;
01126     }
01127     else
01128     {
01129         // calculate the length of left part
01130         start_x = g_bitmap_data.page_field_width;
01131         int left_len = pagebar->cpi_area.x - start_x;
01132 
01133         x = (page_number - 1) * left_len /
01134             (pagebar->current_page - 1 - adjacent_pages - 1);
01135 
01136         offset = pagebar->left_indicator_offset;
01137     }
01138 
01139     // calibrate the value
01140     return (pagebar_calibrate_x_of_marker(pagebar, x, offset) + start_x);
01141 }
01142 
01143 /**
01144  * @brief Draw the markers for overview mode.
01145  */
01146 void pagebar_draw_markers(GtkPagebar * pagebar,
01147                           const int bitmap,
01148                           GArray * markers,
01149                           const int adjacent_pages)
01150 {
01151     if (markers == NULL)
01152     {
01153         return;
01154     }
01155 
01156     unsigned int idx = 0;
01157     guint mark_page = 0;
01158     int x = 0, y = 0;
01159     int display_x = 0, display_y = 0;
01160     int last_drawn_location = x;
01161 
01162     for (; idx < markers->len; idx++)
01163     {
01164         // get pagenumber by mark
01165         mark_page = g_array_index(markers, guint, idx);
01166 
01167         x = pagebar_get_x_of_marker(pagebar, mark_page, adjacent_pages);
01168         if (x < 0)
01169         {
01170             continue;
01171         }
01172 
01173         // the bookmarks are sorted already
01174         if (x < last_drawn_location + g_bitmap_data.bookmark_icon_width)
01175         {
01176             // if two bookmarks overlap, do not draw the bigger one
01177             continue;
01178         }
01179 
01180         y = pagebar->cpi_area.y + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height);
01181 
01182         // transfer the position to widget position;
01183         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01184         gdk_draw_pixbuf(pagebar->pixmap, NULL,
01185                 g_bitmap_data.bitmaps[bitmap], 0, 0, display_x, display_y, -1, -1,
01186                 GDK_RGB_DITHER_NONE, 0, 0);
01187 
01188         last_drawn_location = x;
01189     }
01190 }
01191 
01192 /**
01193  * @brief Draw the whole pagebar.
01194  * - Draw background.
01195  * - Draw cpi (current page indicator).
01196  * - Draw left and right 
01197  */
01198 void gtk_pagebar_draw(GtkPagebar * pagebar)
01199 {
01200     g_return_if_fail((IS_GTK_PAGEBAR(pagebar)));
01201 
01202     if (!pagebar->pixmap)
01203     {
01204         return;
01205     }
01206 
01207     if (pagebar->pagebar_width <= 1 || pagebar->pagebar_height <= 1)
01208     {
01209         return;
01210     }
01211 
01212     // clear the area.
01213     int width;
01214     int height;
01215     gdk_drawable_get_size(pagebar->pixmap, &width, &height);
01216     gdk_draw_rectangle(pagebar->pixmap,
01217                         GTK_WIDGET(pagebar)->style->white_gc,
01218                         TRUE,
01219                         0,
01220                         0,
01221                         width,
01222                         height);
01223 
01224     pagebar_calculate_cpi(pagebar);
01225 
01226     int line_x1 = 0;
01227     int line_x2 = 0;
01228     int line_y1 = pagebar->cpi_area.y + 1;
01229     int line_y2 = line_y1 + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height);
01230     int line_y_max = MAX(line_y1, line_y2);
01231     int line_y_min = MIN(line_y1, line_y2);
01232 
01233     GdkColor color;
01234     color.pixel = 0;
01235     gdk_gc_set_foreground(pagebar->own_gc, &color);
01236     gdk_gc_set_line_attributes(pagebar->own_gc,
01237                                PAGEBAR_HORIZONTAL_LINE_WIDTH,
01238                                GDK_LINE_SOLID,
01239                                GDK_CAP_PROJECTING,
01240                                GDK_JOIN_MITER);
01241 
01242     // translate the position from page bar to widget
01243     gdk_draw_line(pagebar->pixmap,
01244                   pagebar->own_gc,
01245                   line_x1, line_y_min,
01246                   (line_x1 + width), line_y_min);
01247 
01248     // draw bottom line
01249     pagebar_transfer_position(line_x2, line_y_max, &line_x2, &line_y_max, FALSE);
01250     gdk_draw_line(pagebar->pixmap,
01251                   pagebar->own_gc,
01252                   line_x2 + 1, line_y_max,
01253                   (line_x2 + pagebar->pagebar_width - 1), line_y_max);
01254 
01255     if (pagebar->status == STATUS_DETAILS)
01256     {
01257         // draw the details of each page, highlight the current one
01258         pagebar_draw_details(pagebar);
01259     }
01260     else if (pagebar->status == STATUS_NORMAL)
01261     {
01262         pagebar_draw_overview(pagebar);
01263 
01264         pagebar_draw_cpi_overview(pagebar);
01265 
01266         pagebar_draw_markers(pagebar, BITMAP_BOOKMARK, pagebar->bookmarks,
01267             PAGEBAR_ADJACENT_PAGES_NUM);
01268     }
01269     else
01270     {
01271         pagebar_draw_overview(pagebar);
01272 
01273         pagebar_draw_cpi_shrink(pagebar);
01274 
01275         pagebar_draw_markers(pagebar, BITMAP_BOOKMARK, pagebar->bookmarks, 0);
01276     }
01277 
01278     // draw bookmarks
01279 
01280     // make things appear on the screen 
01281     gtk_widget_queue_draw(GTK_WIDGET(pagebar));
01282 }
01283 
01284 /**
01285  * @brief Calculate the cpi position.
01286  */
01287 void pagebar_calculate_cpi(GtkPagebar * pagebar)
01288 {
01289     switch (pagebar->status)
01290     {
01291     case STATUS_NORMAL:
01292         pagebar_calculate_cpi_overview(pagebar);
01293         break;
01294     case STATUS_DETAILS:
01295         pagebar_calculate_cpi_details(pagebar);
01296         break;
01297     case STATUS_SHRINK:
01298         pagebar_calculate_cpi_shrink(pagebar);
01299         break;
01300     default:
01301         break;
01302     }
01303 }
01304 
01305 void pagebar_calculate_cpi_details(GtkPagebar * pagebar)
01306 {
01307     // only calculate the y position to reduce redundant calculation
01308     // pagebar->cpi_area.y = ((pagebar_height - pagebar->cpi_height) >> 1);
01309     pagebar->cpi_area.y = 0;
01310 }
01311 
01312 // This function will calculate the position of current pages indicators
01313 // including current page and adjacent pages.
01314 void pagebar_calculate_cpi_overview(GtkPagebar * pagebar)
01315 {
01316     // it is in page bar coordination system
01317     int pagebar_width = pagebar->pagebar_width;
01318     // int pagebar_height = pagebar->pagebar_height;
01319 
01320     int cpi_pages_num = 0;
01321     int cpi_width = 0;
01322     int cpi_height = MAX(g_bitmap_data.page_field_height, g_bitmap_data.cpi_height);
01323 
01324     if (pagebar->current_page <= 1 + PAGEBAR_ADJACENT_PAGES_NUM)
01325     {
01326         // cpi = 1 +...+ x + x+1 + x+2
01327         cpi_pages_num = pagebar->current_page + PAGEBAR_ADJACENT_PAGES_NUM;
01328         // width = bitmap length + adjacent cpi spaces length + cpi space length
01329         cpi_width = (g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE) * (cpi_pages_num - 1)+
01330             g_bitmap_data.cpi_width;
01331         if (pagebar->current_page == 1)
01332         {
01333             cpi_width -= (PAGEBAR_CPI_ADJACENT_SPACE - PAGEBAR_CPI_SPACE);
01334         }
01335         else
01336         {
01337             cpi_width -= ((PAGEBAR_CPI_ADJACENT_SPACE - PAGEBAR_CPI_SPACE) << 1);
01338         }
01339 
01340         pagebar->cpi_area.x = 0;
01341     }
01342     else if (pagebar->current_page >= pagebar->page_count - PAGEBAR_ADJACENT_PAGES_NUM)
01343     {
01344         // cpi = x-2 + x-1 + x +...+ last page
01345         cpi_pages_num = pagebar->page_count - pagebar->current_page +
01346             PAGEBAR_ADJACENT_PAGES_NUM + 1;
01347         cpi_width = (g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE) * (cpi_pages_num - 1) +
01348             g_bitmap_data.cpi_width;
01349         if (pagebar->current_page == pagebar->page_count)
01350         {
01351             cpi_width -= (PAGEBAR_CPI_ADJACENT_SPACE - PAGEBAR_CPI_SPACE);
01352         }
01353         else
01354         {
01355             cpi_width -= ((PAGEBAR_CPI_ADJACENT_SPACE - PAGEBAR_CPI_SPACE) << 1);
01356         }
01357 
01358         pagebar->cpi_area.x = pagebar_width - cpi_width;
01359     }
01360     else
01361     {
01362         // cpi = x-2 + x-1 + x + x+1 + x+2
01363         cpi_pages_num = (PAGEBAR_ADJACENT_PAGES_NUM << 1) + 1;
01364         cpi_width = (g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE) * (cpi_pages_num - 1) +
01365             g_bitmap_data.cpi_width;
01366         cpi_width -= ((PAGEBAR_CPI_ADJACENT_SPACE - PAGEBAR_CPI_SPACE) << 1);
01367 
01368         // calculate the position of cpi
01369         int overview_length = pagebar_width - (g_bitmap_data.page_field_width << 1) - cpi_width;
01370 
01371         // calculate the x position in overview
01372         if (pagebar->current_page == (1 + PAGEBAR_ADJACENT_PAGES_NUM + 1))
01373         {
01374             // near the first page
01375             // TODO. we need a better way to solve this problem
01376             pagebar->cpi_area.x = g_bitmap_data.page_field_width + PAGEBAR_CPI_ADJACENT_SPACE;
01377         }
01378         else if (pagebar->current_page == (pagebar->page_count - PAGEBAR_ADJACENT_PAGES_NUM - 1))
01379         {
01380             // near the last page
01381             pagebar->cpi_area.x = pagebar_width - g_bitmap_data.page_field_width -
01382                 PAGEBAR_CPI_ADJACENT_SPACE - cpi_width;
01383         }
01384         else
01385         {
01386             pagebar->cpi_area.x = g_bitmap_data.page_field_width +
01387                 (pagebar->current_page - PAGEBAR_ADJACENT_PAGES_NUM - 2) *
01388                 overview_length / (pagebar->page_count - cpi_pages_num - 2);
01389         }
01390 
01391     }
01392 
01393     pagebar->cpi_area.width = cpi_width;
01394     pagebar->cpi_area.height = cpi_height;
01395     // cpi_area.y is the original coordination for every calculation
01396     // pagebar->cpi_area.y = ((pagebar_height - cpi_height) >> 1);
01397     pagebar->cpi_area.y = 0;
01398 }
01399 
01400 void pagebar_calculate_cpi_shrink(GtkPagebar * pagebar)
01401 {
01402     int pagebar_width = pagebar->pagebar_width;
01403     //int pagebar_height = pagebar->pagebar_height;
01404 
01405     pagebar->cpi_area.width = g_bitmap_data.cpi_width;
01406     pagebar->cpi_area.height = g_bitmap_data.cpi_height;
01407     // pagebar->cpi_area.y = ((pagebar_height - pagebar->cpi_height) >> 1);
01408     pagebar->cpi_area.y = 0;
01409     if (pagebar->current_page == 1)
01410     {
01411         pagebar->cpi_area.x = 0;
01412         return;
01413     }
01414 
01415     if (pagebar->current_page == pagebar->page_count)
01416     {
01417         pagebar->cpi_area.x = pagebar_width - g_bitmap_data.cpi_width;
01418         return;
01419     }
01420 
01421     // calculate the position of cpi
01422     int overview_length = pagebar_width - (g_bitmap_data.page_field_width << 1) - g_bitmap_data.cpi_width;
01423     int cpi_overview_x = pagebar->current_page * overview_length / (pagebar->page_count - 2);
01424     pagebar->cpi_area.x = g_bitmap_data.page_field_width + cpi_overview_x;
01425 
01426 }
01427 
01428 void pagebar_draw_details(GtkPagebar * pagebar)
01429 {
01430     // int pagebar_width = pagebar->pagebar_width;
01431     // int pagebar_height = pagebar->pagebar_height;
01432 
01433     // calculate the display position of "real" page bar
01434     int x = 0;
01435     int y = 0;
01436     int inc_length = 0;
01437     int w = 0, h = 0;
01438     char text[16] = { 0 };
01439 
01440     // borrow cpi area's x to record the position of real page bar
01441     pagebar->cpi_area.x = x;
01442 
01443     // set own gc to draw text of succeed pages after current page
01444     GdkColor color;
01445     color.pixel = PAGEBAR_NEXT_PAGE_TEXT_COLOR;
01446     gdk_gc_set_foreground(pagebar->own_gc, &color);
01447 
01448     // draw each page
01449     int display_x = 0, display_y = 0;
01450 
01451     unsigned int idx = 1;
01452     for (; idx <= pagebar->page_count; ++idx)
01453     {
01454         int bitmap_kind = BITMAP_SUCC_CPI;
01455         GdkGC *gc = GTK_WIDGET(pagebar)->style->black_gc;
01456         int size_x = 0;
01457         int size_y = 0;
01458         if (idx == pagebar->current_page)
01459         {
01460             // draw CPI
01461             y = pagebar->cpi_area.y;
01462 
01463             if (is_page_marked(pagebar->bookmarks, idx))
01464             {
01465                 bitmap_kind = BITMAP_CPI_BOOKMARK;
01466             }
01467             else
01468             {
01469                 bitmap_kind = BITMAP_CPI;
01470             }
01471 
01472             pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01473             gdk_draw_pixbuf(pagebar->pixmap,
01474                             NULL, g_bitmap_data.bitmaps[bitmap_kind],
01475                             0, 0, display_x, display_y,
01476                             g_bitmap_data.cpi_width,
01477                             g_bitmap_data.cpi_height,
01478                             GDK_RGB_DITHER_NONE, 0, 0);
01479 
01480             inc_length = g_bitmap_data.cpi_width;
01481             gc = GTK_WIDGET(pagebar)->style->white_gc;
01482 
01483             size_x = g_bitmap_data.cpi_width;
01484             size_y = g_bitmap_data.cpi_height;
01485         }
01486         else
01487         {
01488             if (idx < pagebar->current_page)
01489             {
01490                 if (is_page_marked(pagebar->bookmarks, idx))
01491                 {
01492                     bitmap_kind = BITMAP_PREV_CPI_BOOKMARK;
01493                 }
01494                 else
01495                 {
01496                     bitmap_kind = BITMAP_PREV_CPI;
01497                 }
01498 
01499                 gc = GTK_WIDGET(pagebar)->style->white_gc;
01500             }
01501             else
01502             {
01503                 if (is_page_marked(pagebar->bookmarks, idx))
01504                 {
01505                     bitmap_kind = BITMAP_SUCC_CPI_BOOKMARK;
01506                 }
01507                 else
01508                 {
01509                     bitmap_kind = BITMAP_SUCC_CPI;
01510                 }
01511 
01512                 gc = pagebar->own_gc;
01513             }
01514 
01515             // draw adjacent page
01516             y = pagebar->cpi_area.y + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height);
01517 
01518             pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01519             gdk_draw_pixbuf(pagebar->pixmap,
01520                             NULL, g_bitmap_data.bitmaps[bitmap_kind],
01521                             0, 0, display_x, display_y,
01522                             -1, -1,
01523                             GDK_RGB_DITHER_NONE, 0, 0);
01524 
01525             inc_length = g_bitmap_data.page_field_width;
01526             size_x = g_bitmap_data.page_field_width;
01527             size_y = g_bitmap_data.page_field_height;
01528         }
01529 
01530         sprintf(text, "%d", idx);
01531         pango_layout_set_text(pagebar->pango_layout, text, -1);
01532         pango_layout_get_pixel_size(pagebar->pango_layout, (int *)&w, (int *)&h);
01533         //pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01534         gdk_draw_layout(pagebar->pixmap,
01535                         gc,
01536                         display_x + (size_x - w) / 2,
01537                         display_y + (size_y - h) / 2,
01538                         pagebar->pango_layout);
01539 
01540         if (idx == pagebar->current_page || idx == (pagebar->current_page - 1))
01541         {
01542             x += (inc_length + PAGEBAR_CPI_SPACE);
01543         }
01544         else
01545         {
01546             x += (inc_length + PAGEBAR_CPI_ADJACENT_SPACE);
01547         }
01548     }
01549 }
01550 
01551 void pagebar_draw_overview(GtkPagebar * pagebar)
01552 {
01553     int pagebar_width = pagebar->pagebar_width;
01554     // int pagebar_height = pagebar->pagebar_height;
01555 
01556     // calculate the left length and right length
01557     int left_length = 0, right_length = 0;
01558     int cpi_right = pagebar->cpi_area.x + pagebar->cpi_area.width;
01559 
01560     int x = 0;
01561     int y = pagebar->cpi_area.y + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height) +
01562         ((g_bitmap_data.page_field_height - PAGEBAR_INDICATOR_LINE_HEIGHT) >> 1) + 2;
01563     int display_x = 0, display_y = 0;
01564 
01565     // reset the offsets of indicators
01566     pagebar->left_indicator_offset = 0;
01567     pagebar->right_indicator_offset = 0;
01568 
01569     char text[16] = { 0 };
01570     unsigned int w = 0, h = 0;
01571 
01572     // draw the first page and last page
01573     gboolean draw_first = TRUE;
01574     gboolean draw_last  = TRUE;
01575     if (pagebar->cpi_area.x == 0)
01576     {
01577         draw_first = FALSE;
01578         right_length = pagebar_width - g_bitmap_data.page_field_width - cpi_right;
01579         x = cpi_right;
01580     }
01581     if (pagebar->cpi_area.x == (pagebar_width - pagebar->cpi_area.width))
01582     {
01583         draw_last = FALSE;
01584         left_length = pagebar->cpi_area.x - g_bitmap_data.page_field_width;
01585         x = g_bitmap_data.page_field_width;
01586     }
01587     else
01588     {
01589         left_length = pagebar->cpi_area.x - g_bitmap_data.page_field_width;
01590         right_length = pagebar_width - cpi_right - g_bitmap_data.page_field_width;
01591         x = g_bitmap_data.page_field_width;
01592     }
01593 
01594     int left_indicators_num = left_length / (PAGEBAR_INDICATOR_LINE_WIDTH +
01595         PAGEBAR_INDICATOR_SPACE);
01596     if (left_indicators_num > 0)
01597     {
01598         int left_indicators_len = left_indicators_num * (PAGEBAR_INDICATOR_LINE_WIDTH +
01599             PAGEBAR_INDICATOR_SPACE);
01600         pagebar->left_indicator_offset = (((PAGEBAR_INDICATOR_SPACE << 1) +
01601                 PAGEBAR_INDICATOR_LINE_WIDTH) >> 1);
01602         if (left_indicators_len != left_length)
01603         {
01604             pagebar->left_indicator_offset += ((left_length - left_indicators_len) >> 1);
01605         }
01606         left_indicators_num--;
01607     }
01608 
01609     int right_indicators_num = right_length / (PAGEBAR_INDICATOR_LINE_WIDTH +
01610         PAGEBAR_INDICATOR_SPACE);
01611     if (right_indicators_num > 0)
01612     {
01613         int right_indicators_len = right_indicators_num * (PAGEBAR_INDICATOR_LINE_WIDTH +
01614             PAGEBAR_INDICATOR_SPACE);
01615         pagebar->right_indicator_offset = (((PAGEBAR_INDICATOR_SPACE << 1) +
01616                 PAGEBAR_INDICATOR_LINE_WIDTH) >> 1);
01617         if (right_indicators_len != right_length)
01618         {
01619             pagebar->right_indicator_offset += ((right_length - right_indicators_len) >> 1);
01620         }
01621         right_indicators_num--;
01622     }
01623 
01624     // draw page indicators
01625     GdkColor color;
01626     color.pixel = PAGEBAR_INDICATOR_COLOR;
01627     gdk_gc_set_foreground(pagebar->own_gc, &color);
01628     gdk_gc_set_line_attributes(pagebar->own_gc,
01629                                PAGEBAR_INDICATOR_LINE_WIDTH,
01630                                GDK_LINE_SOLID,
01631                                GDK_CAP_PROJECTING,
01632                                GDK_JOIN_MITER);
01633 
01634     x += pagebar->left_indicator_offset;
01635     int idx = 0;
01636     while (idx < left_indicators_num)
01637     {
01638         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01639         gdk_draw_line(pagebar->pixmap,
01640                       pagebar->own_gc,
01641                       display_x, display_y,
01642                       display_x, display_y + PAGEBAR_INDICATOR_LINE_HEIGHT);
01643 
01644         idx++;
01645         x += (PAGEBAR_INDICATOR_SPACE + PAGEBAR_INDICATOR_LINE_WIDTH);
01646     }
01647 
01648     color.pixel = 0;
01649     gdk_gc_set_foreground(pagebar->own_gc, &color);
01650     x = cpi_right + pagebar->right_indicator_offset;
01651     idx = 0;
01652     while (idx < right_indicators_num)
01653     {
01654         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01655         gdk_draw_line(pagebar->pixmap,
01656                       pagebar->own_gc,
01657                       display_x, display_y,
01658                       display_x, display_y + PAGEBAR_INDICATOR_LINE_HEIGHT);
01659 
01660         idx++;
01661         x += (PAGEBAR_INDICATOR_SPACE + PAGEBAR_INDICATOR_LINE_WIDTH);
01662     }
01663 
01664     // draw first page and last page field
01665     int bitmap_kind = BITMAP_SUCC_CPI;
01666     // update y to draw the first and last page indicator
01667     y = pagebar->cpi_area.y + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height);
01668     if (draw_first)
01669     {
01670         // draw page 1.
01671         x = 0;
01672 
01673         if (is_page_marked(pagebar->bookmarks, 1))
01674         {
01675             bitmap_kind = BITMAP_PREV_CPI_BOOKMARK;
01676         }
01677         else
01678         {
01679             bitmap_kind = BITMAP_PREV_CPI;
01680         }
01681 
01682         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01683         gdk_draw_pixbuf(pagebar->pixmap, NULL,
01684                         g_bitmap_data.bitmaps[bitmap_kind],
01685                         0, 0, display_x, display_y, -1, -1,
01686                         GDK_RGB_DITHER_NONE, 0, 0);
01687 
01688         sprintf(text, "1");
01689         pango_layout_set_text(pagebar->pango_layout, text, -1);
01690         pango_layout_get_pixel_size(pagebar->pango_layout, (int *)&w,(int*)&h);
01691         // make sure position is transformed before
01692         gdk_draw_layout(pagebar->pixmap,
01693                         GTK_WIDGET(pagebar)->style->white_gc,
01694                         display_x + ((g_bitmap_data.page_field_width - w) >> 1),
01695                         display_y + ((g_bitmap_data.page_field_height - h) >> 1),
01696                         pagebar->pango_layout);
01697     }
01698 
01699     if (draw_last)
01700     {
01701         // draw last page
01702         x = pagebar_width - g_bitmap_data.page_field_width;
01703 
01704         if (is_page_marked(pagebar->bookmarks, pagebar->page_count))
01705         {
01706             bitmap_kind = BITMAP_SUCC_CPI_BOOKMARK;
01707         }
01708         else
01709         {
01710             bitmap_kind = BITMAP_SUCC_CPI;
01711         }
01712 
01713         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01714         gdk_draw_pixbuf(pagebar->pixmap,
01715                         NULL,
01716                         g_bitmap_data.bitmaps[bitmap_kind],
01717                         0, 0, display_x, display_y, -1, -1,
01718                         GDK_RGB_DITHER_NONE, 0, 0);
01719 
01720         // set own gc to draw text of last page
01721         GdkColor color;
01722         color.pixel = PAGEBAR_LAST_PAGE_TEXT_COLOR;
01723         gdk_gc_set_foreground(pagebar->own_gc, &color);
01724 
01725         sprintf(text, "%d", pagebar->page_count);
01726         pango_layout_set_text(pagebar->pango_layout, text, -1);
01727         pango_layout_get_pixel_size(pagebar->pango_layout, (int *)&w, (int *)&h);
01728 
01729         gdk_draw_layout(pagebar->pixmap,
01730                         pagebar->own_gc,
01731                         display_x + ((g_bitmap_data.page_field_width - w) >> 1),
01732                         display_y + ((g_bitmap_data.page_field_height - h) >> 1),
01733                         pagebar->pango_layout);
01734     }
01735 }
01736 
01737 void pagebar_draw_cpi_overview(GtkPagebar * pagebar)
01738 {
01739     unsigned int cpi_pages_count = 0;
01740     unsigned int idx = 0;
01741     int x = pagebar->cpi_area.x;
01742     int y = 0;
01743     char text[16] = { 0 };
01744     int w = 0, h = 0;
01745     int inc_length = 0;
01746     int display_x = 0, display_y = 0;
01747 
01748     // int pagebar_width = pagebar->pagebar_width;
01749     // int pagebar_height = pagebar->pagebar_height;
01750 
01751     if (pagebar->current_page <= 1 + PAGEBAR_ADJACENT_PAGES_NUM)
01752     {
01753         // cpi = 1 +...+ x + x+1 + x+2
01754         idx = 1;
01755         cpi_pages_count = pagebar->current_page + PAGEBAR_ADJACENT_PAGES_NUM;
01756     }
01757     else if (pagebar->current_page >= pagebar->page_count - PAGEBAR_ADJACENT_PAGES_NUM)
01758     {
01759         // cpi = x-2 + x-1 + x +...+ last page
01760         idx = pagebar->current_page - PAGEBAR_ADJACENT_PAGES_NUM;
01761         cpi_pages_count = pagebar->page_count;
01762     }
01763     else
01764     {
01765         idx = pagebar->current_page - PAGEBAR_ADJACENT_PAGES_NUM;
01766         cpi_pages_count = pagebar->current_page + PAGEBAR_ADJACENT_PAGES_NUM;
01767     }
01768 
01769     int bitmap_kind = BITMAP_SUCC_CPI;
01770 
01771     // reset the own gc to draw the text after current page
01772     GdkColor color;
01773     color.pixel = PAGEBAR_NEXT_PAGE_TEXT_COLOR;
01774     gdk_gc_set_foreground(pagebar->own_gc, &color);
01775 
01776     for (; idx <= cpi_pages_count; ++idx)
01777     {
01778         GdkGC *gc = GTK_WIDGET(pagebar)->style->black_gc;
01779         int size_x = 0;
01780         int size_y = 0;
01781         if (idx == pagebar->current_page)
01782         {
01783             // draw CPI
01784             y = pagebar->cpi_area.y;
01785 
01786             if (is_page_marked(pagebar->bookmarks, idx))
01787             {
01788                 bitmap_kind = BITMAP_CPI_BOOKMARK;
01789             }
01790             else
01791             {
01792                 bitmap_kind = BITMAP_CPI;
01793             }
01794 
01795             pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01796             gdk_draw_pixbuf(pagebar->pixmap,
01797                 NULL, g_bitmap_data.bitmaps[bitmap_kind],
01798                 0, 0, display_x, display_y,
01799                 g_bitmap_data.cpi_width,
01800                 g_bitmap_data.cpi_height,
01801                 GDK_RGB_DITHER_NONE, 0, 0);
01802 
01803             inc_length = g_bitmap_data.cpi_width;
01804             gc = GTK_WIDGET(pagebar)->style->white_gc;
01805 
01806             size_x = g_bitmap_data.cpi_width;
01807             size_y = g_bitmap_data.cpi_height;
01808         }
01809         else
01810         {
01811             // draw adjacent page
01812             y = pagebar->cpi_area.y + (g_bitmap_data.cpi_height - g_bitmap_data.page_field_height);
01813 
01814             if (idx < pagebar->current_page)
01815             {
01816                 if (is_page_marked(pagebar->bookmarks, idx))
01817                 {
01818                     bitmap_kind = BITMAP_PREV_CPI_BOOKMARK;
01819                 }
01820                 else
01821                 {
01822                     bitmap_kind = BITMAP_PREV_CPI;
01823                 }
01824 
01825                 gc = GTK_WIDGET(pagebar)->style->white_gc;
01826             }
01827             else
01828             {
01829                 if (is_page_marked(pagebar->bookmarks, idx))
01830                 {
01831                     bitmap_kind = BITMAP_SUCC_CPI_BOOKMARK;
01832                 }
01833                 else
01834                 {
01835                     bitmap_kind = BITMAP_SUCC_CPI;
01836                 }
01837 
01838                 gc = pagebar->own_gc;
01839             }
01840 
01841             pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01842             gdk_draw_pixbuf(pagebar->pixmap,
01843                 NULL, g_bitmap_data.bitmaps[bitmap_kind],
01844                 0, 0, display_x, display_y,
01845                 -1, -1,
01846                 GDK_RGB_DITHER_NONE, 0, 0);
01847 
01848             inc_length = g_bitmap_data.page_field_width;
01849 
01850             size_x = g_bitmap_data.page_field_width;
01851             size_y = g_bitmap_data.page_field_height;
01852         }
01853 
01854         sprintf(text, "%d", idx);
01855         pango_layout_set_text(pagebar->pango_layout, text, -1);
01856         pango_layout_get_pixel_size(pagebar->pango_layout, (int *)&w, (int *)&h);
01857 
01858         pagebar_transfer_position(x, y, &display_x, &display_y, FALSE);
01859         gdk_draw_layout(pagebar->pixmap,
01860                         gc,
01861                         display_x + (size_x - w) / 2,
01862                         display_y + (size_y - h) / 2,
01863                         pagebar->pango_layout);
01864 
01865         if (idx == pagebar->current_page || idx == pagebar->current_page - 1)
01866         {
01867             x += (inc_length + PAGEBAR_CPI_SPACE);
01868         }
01869         else
01870         {
01871             x += (inc_length + PAGEBAR_CPI_ADJACENT_SPACE);
01872         }
01873     }
01874 }
01875 
01876 void pagebar_draw_cpi_shrink(GtkPagebar * pagebar)
01877 {
01878     int x = pagebar->cpi_area.x;
01879     int y = pagebar->cpi_area.y;
01880     char text[16] = { 0 };
01881     int w = 0, h = 0;
01882 
01883     int bitmap_kind = BITMAP_CPI;
01884 
01885     if (is_page_marked(pagebar->bookmarks, pagebar->current_page))
01886     {
01887         bitmap_kind = BITMAP_CPI_BOOKMARK;
01888     }
01889 
01890     pagebar_transfer_position(x, y, &x, &y, FALSE);
01891     gdk_draw_pixbuf(pagebar->pixmap,
01892                     NULL, g_bitmap_data.bitmaps[bitmap_kind],
01893                     0, 0, x, y,
01894                     g_bitmap_data.cpi_width,
01895                     g_bitmap_data.cpi_height,
01896                     GDK_RGB_DITHER_NONE, 0, 0);
01897 
01898     sprintf(text, "%d", pagebar->current_page);
01899     pango_layout_set_text(pagebar->pango_layout, text, -1);
01900     pango_layout_get_pixel_size(pagebar->pango_layout, (int *)&w, (int *)&h);
01901     gdk_draw_layout(pagebar->pixmap,
01902                     GTK_WIDGET(pagebar)->style->white_gc,
01903                     x + (g_bitmap_data.cpi_width - w) / 2,
01904                     y + (g_bitmap_data.cpi_height - h) / 2,
01905                     pagebar->pango_layout);
01906 
01907 }
01908 
01909 void gtk_pagebar_update(GtkPagebar * pagebar)
01910 {
01911     gtk_pagebar_draw(pagebar);
01912 }
Generated by  doxygen 1.6.2-20100208