00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <glib.h>
00029 #include <gtk/gtk.h>
00030 #include <gdk/gdkkeysyms.h>
00031
00032 #include "text_config.h"
00033 #include "text_model.h"
00034 #include "text_view.h"
00035
00036 using namespace text;
00037
00038
00039 GdkPixbuf *pix_buf = NULL;
00040 GtkWidget *top_level_window = NULL;
00041
00042 static int page_index = 0;
00043 static int total_pages = 0;
00044
00045 struct RenderData
00046 {
00047 RenderData(const PluginBitmapAttributes& _ba, const Position& _pos)
00048 : ba(_ba), pos(_pos)
00049 {
00050 }
00051
00052 public:
00053 PluginBitmapAttributes ba;
00054 Position pos;
00055 };
00056
00057 struct SearchResult
00058 {
00059 int matches;
00060 Range* ranges;
00061 };
00062
00063 struct Event
00064 {
00065 public:
00066 Event()
00067 {
00068 }
00069 Event(TextEvent e, void *_data)
00070 : event(e), data(_data)
00071 {
00072 }
00073
00074 public:
00075 TextEvent event;
00076 void *data;
00077 };
00078
00079 class EventQueue
00080 {
00081 public:
00082 EventQueue()
00083 {
00084 mutex = g_mutex_new();
00085 }
00086 ~EventQueue()
00087 {
00088 g_mutex_free(mutex);
00089 }
00090
00091 void append_event(const Event& ev)
00092 {
00093 g_mutex_lock(mutex);
00094 event_queue.push_back(ev);
00095 g_mutex_unlock(mutex);
00096 }
00097
00098 bool get_event(Event& ev)
00099 {
00100 bool ret = false;
00101 g_mutex_lock(mutex);
00102 if (!event_queue.empty())
00103 {
00104 ev = event_queue.front();
00105 event_queue.pop_front();
00106 ret = true;
00107 }
00108 g_mutex_unlock(mutex);
00109 return ret;
00110 }
00111
00112 private:
00113 std::list<Event> event_queue;
00114 GMutex* mutex;
00115 };
00116
00117 class EventHandler
00118 {
00119 public:
00120 EventHandler(EventQueue *_eq)
00121 : eq(_eq)
00122 {
00123 }
00124 ~EventHandler()
00125 {
00126 }
00127 public:
00128 void handle_paginate_start(unsigned int page_count)
00129 {
00130 Event e(PAGINATE_STARTED, (void *)1);
00131 eq->append_event(e);
00132 }
00133
00134 void handle_paginate_end(unsigned int page_count)
00135 {
00136 Event e(PAGINATE_ENDED, (void *)page_count);
00137 eq->append_event(e);
00138 }
00139
00140 void handle_render_done(const PluginBitmapAttributes& ba, const Position& start_pos)
00141 {
00142 RenderData *rd = new RenderData(ba, start_pos);
00143 Event e(RENDER_DONE, (void *)rd);
00144 eq->append_event(e);
00145 }
00146
00147 void handle_search_done(const std::vector<Range>& result_ranges, const SearchContext& search_context)
00148 {
00149 SearchResult *p = new SearchResult;
00150 p->matches = result_ranges.size();
00151 p->ranges = new Range[p->matches];
00152
00153 for (unsigned int i=0; i<result_ranges.size(); i++)
00154 {
00155 p->ranges[i] = result_ranges[i];
00156 }
00157
00158 Event e(SEARCH_DONE, (void *)p);
00159 eq->append_event(e);
00160 }
00161
00162 private:
00163 EventQueue *eq;
00164 };
00165
00166 void fill_pix_buf(const unsigned char *bmp, const int width, const int height)
00167 {
00168 if (pix_buf != NULL)
00169 {
00170 g_object_unref(pix_buf);
00171 pix_buf = NULL;
00172 }
00173
00174 pix_buf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
00175 FALSE,
00176 8,
00177 width,
00178 height);
00179
00180 guchar *pixels = gdk_pixbuf_get_pixels(pix_buf);
00181 int rowstride = gdk_pixbuf_get_rowstride(pix_buf);
00182 int channels = gdk_pixbuf_get_n_channels(pix_buf);
00183
00184 guchar *p = NULL;
00185 for (int y=0; y<height; y++)
00186 {
00187 for (int x=0; x<width; x++)
00188 {
00189 p = pixels + y*rowstride + x*channels;
00190 p[0] = p[1] = p[2] = bmp[y*width+x];
00191 }
00192 }
00193 }
00194
00195 void handle_event(const Event& ev)
00196 {
00197 const unsigned char *bmp = 0;
00198 RenderData *rd = 0;
00199 Position pos;
00200 SearchResult *sr = 0;
00201
00202 switch (ev.event)
00203 {
00204 case PAGINATE_STARTED:
00205 printf("Pagination starts...\n");
00206 break;
00207
00208 case PAGINATE_ENDED:
00209 total_pages = (unsigned int)ev.data;
00210 printf("Pagination end, total_pages = %d.\n", total_pages);
00211 break;
00212
00213 case RENDER_DONE:
00214 rd = (RenderData *)ev.data;
00215 pos = rd->pos;
00216 bmp = rd->ba.data;
00217 fill_pix_buf(bmp, rd->ba.width, rd->ba.height);
00218 delete[] bmp;
00219 delete rd;
00220 rd = 0;
00221 printf("Render done for pos (%d, %d).\n", pos.paragraph, pos.offset);
00222 gdk_window_invalidate_rect(top_level_window->window, NULL, TRUE);
00223 break;
00224
00225 case SEARCH_DONE:
00226 printf("Search done.\n");
00227 sr = (SearchResult *)ev.data;
00228 for (int i=0; i<sr->matches; i++)
00229 {
00230 printf("Match %3d: (%d, %d)~(%d, %d)\n",
00231 i+1,
00232 sr->ranges[i].start.paragraph,
00233 sr->ranges[i].start.offset,
00234 sr->ranges[i].end.paragraph,
00235 sr->ranges[i].end.offset);
00236 }
00237 delete[] sr->ranges;
00238 delete sr;
00239 break;
00240
00241 default:
00242 break;
00243 }
00244 }
00245
00246 static gboolean widget_event_handler(GtkWidget *widget, GdkEvent *event, gpointer user_data)
00247 {
00248 guint key_code;
00249 TextController *ctrl = (TextController *)user_data;
00250
00251 switch (event->type)
00252 {
00253 case GDK_KEY_PRESS:
00254 key_code = ((GdkEventKey*)event)->keyval;
00255 if (key_code == GDK_Page_Up)
00256 {
00257 if (page_index == 0)
00258 {
00259 return FALSE;
00260 }
00261 --page_index;
00262 }
00263 else if (key_code == GDK_Page_Down)
00264 {
00265 if (page_index == total_pages-1)
00266 {
00267 return FALSE;
00268 }
00269 ++page_index;
00270 }
00271 ctrl->render(page_index);
00272 break;
00273
00274 default:
00275 break;
00276 }
00277
00278 return TRUE;
00279 }
00280 gboolean timeout_handler(gpointer data)
00281 {
00282 Event ev;
00283 EventQueue *eq = (EventQueue *)data;
00284 while (eq->get_event(ev))
00285 {
00286 handle_event(ev);
00287 }
00288
00289 return TRUE;
00290 }
00291
00292 static gboolean my_expose(GtkWidget *da, GdkEventExpose *event, gpointer data)
00293 {
00294 GdkGC *gc = gdk_gc_new(da->window);
00295 GdkPixbuf** pix_buf = (GdkPixbuf**)data;
00296 if (*pix_buf != NULL)
00297 {
00298 gdk_draw_pixbuf(da->window,
00299 gc,
00300 *pix_buf,
00301 0,
00302 0,
00303 0,
00304 0,
00305 -1,
00306 -1,
00307 GDK_RGB_DITHER_NORMAL,
00308 0,
00309 0);
00310 }
00311
00312 return TRUE;
00313 }
00314
00315 static void destroy(GtkWidget *widget, gpointer data)
00316 {
00317 gtk_main_quit ();
00318 }
00319
00320 int main(int argc, char* argv[])
00321 {
00322 gtk_init(&argc, &argv);
00323
00324 if (argc != 2)
00325 {
00326 fprintf(stderr, "Usage: %s <file_name>.\n", argv[0]);
00327 return -1;
00328 }
00329
00330
00331 TextModel model(argv[1]);
00332 model.open();
00333
00334
00335 TextView view(&model);
00336 g_thread_init(NULL);
00337 TextController ctrl(&model, &view);
00338
00339
00340 EventQueue eq;
00341 EventHandler event_handler(&eq);
00342 model.search_done_signal.add_slot<EventHandler>(&event_handler, &EventHandler::handle_search_done);
00343 view.pagination_start_signal.add_slot<EventHandler>(&event_handler, &EventHandler::handle_paginate_start);
00344 view.pagination_end_signal.add_slot<EventHandler>(&event_handler, &EventHandler::handle_paginate_end);
00345 view.render_done_signal.add_slot<EventHandler>(&event_handler, &EventHandler::handle_render_done);
00346
00347
00348 top_level_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00349 gtk_widget_set_size_request(top_level_window, DEFAULT_SURFACE_WIDTH, DEFAULT_SURFACE_HEIGHT);
00350
00351
00352 g_signal_connect(G_OBJECT(top_level_window), "destroy", G_CALLBACK(destroy), NULL);
00353 g_signal_connect(G_OBJECT(top_level_window), "expose_event", G_CALLBACK(my_expose), &pix_buf);
00354 gtk_signal_connect(GTK_OBJECT(top_level_window), "key_press_event", GTK_SIGNAL_FUNC(widget_event_handler), &ctrl);
00355 g_timeout_add(10, timeout_handler, &eq);
00356
00357
00358 gtk_widget_show_all(top_level_window);
00359
00360
00361 ctrl.render(page_index);
00362 ctrl.search(SearchContext(SEARCH_ALL, Position(0, 0), "render", true, true, false));
00363 gtk_main();
00364
00365 g_object_unref(pix_buf);
00366 return 0;
00367 }
00368