/* Copyright (C) 2001-2002 Kenichi Suto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "global.h" #include "eb.h" #include "canvas.h" #include "history.h" #include "dump.h" extern GtkWidget *note_tree; extern GtkWidget *tree_viewport; extern CONTENT_AREA *dict_area; static void show_heading(GtkWidget *widget); static GtkWidget *current_node = NULL; GtkWidget *container_child(GtkWidget *container){ GList *p; p = gtk_container_children(GTK_CONTAINER(container)); if(p == NULL){ return(NULL); } else { return((GtkWidget *)(p->data)); } } static void show_location(SEARCH_RESULT *result){ gchar msg[512]; sprintf(msg, "HEADING: page=%08x offset=%03x CONTENT: page=%08x offset=%03x", result->pos_heading.page, result->pos_heading.offset, result->pos_text.page, result->pos_text.offset); status_message(msg); } void ctree_select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *bevent, gpointer user_data) { GtkWidget *node; GtkWidget *last_node; ITEM_DATA *idata; gchar *text; g_return_if_fail (GTK_IS_CLIST (widget)); node = (GtkWidget *)gtk_ctree_node_nth(GTK_CTREE(tree_root), row); idata = gtk_ctree_node_get_row_data(GTK_CTREE(tree_root), GTK_CTREE_NODE(node)); if(idata == NULL) { last_node = current_node; current_row = -1; current_node = NULL; show_heading(last_node); return; } if(current_node != NULL) { last_node = current_node; current_row = row; current_node = node; show_heading(last_node); } else { current_row = row; current_node = node; } show_heading(node); text = ebook_get_text( idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); show_text(idata->result->book_info, text); save_history(dict_area, idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); free(text); show_location(idata->result); current_position.page = idata->result->pos_text.page; current_position.offset = idata->result->pos_text.offset; current_book_info = idata->result->book_info; if(hex_dlg != NULL) dump_hex(); if(text_dlg != NULL) dump_text(); return; } void ctree_unselect_row(GtkWidget *widget, gint row, gint column, GdkEventButton *bevent, gpointer user_data) { GtkWidget *last_node; g_return_if_fail (GTK_IS_CLIST (widget)); last_node = current_node; current_row = -1; current_node = NULL; show_heading(last_node); return; } static void clear_node(GtkCTree *ctree, GtkCTreeNode *list){ ITEM_DATA *data; data = gtk_ctree_node_get_row_data(GTK_CTREE(ctree),list); if(data != NULL){ if(data->pixbuff != NULL){ gdk_pixmap_unref(data->pixbuff); } free(data); } gtk_ctree_remove_node(GTK_CTREE(ctree),list); } void clear_tree(GtkWidget *tree){ GtkCTreeNode *node; if(tree == NULL) { return; } gtk_clist_freeze(GTK_CLIST(tree)); while(1){ node = gtk_ctree_node_nth(GTK_CTREE(tree), 0); if(node == NULL) break; gtk_ctree_post_recursive(GTK_CTREE(tree), node, (GtkCTreeFunc)clear_node, NULL); } gtk_clist_thaw(GTK_CLIST(tree)); current_row = -1; current_node = NULL; gtk_container_check_resize(GTK_CONTAINER(tree_root)); } gint x_max=0; void show_result_tree() { SEARCH_RESULT *rp; GList *l; ITEM_DATA *idata; GtkWidget *node=NULL; GtkWidget *leaf; BOOK_INFO *last_book = NULL; gint result_count=0; char *node_text[1]; gchar *text; gint i; if(search_result == NULL){ // 1件も無かった場合 show_text(0, _("No hit.")); return; } gtk_notebook_set_page(GTK_NOTEBOOK(note_tree), 0); x_max = 0; if(tree_scroll != NULL) gtk_widget_destroy(tree_root); tree_root = gtk_ctree_new(1, 0); gtk_clist_set_row_height(GTK_CLIST(tree_root),font_height+4); gtk_ctree_set_line_style(GTK_CTREE(tree_root),GTK_CTREE_LINES_NONE); gtk_signal_connect (GTK_OBJECT(tree_root), "select_row", GTK_SIGNAL_FUNC(ctree_select_row), tree_root); gtk_signal_connect (GTK_OBJECT(tree_root), "unselect_row", GTK_SIGNAL_FUNC(ctree_unselect_row), tree_root); gtk_widget_set_usize(GTK_WIDGET(tree_root), 200, 350); gtk_container_add (GTK_CONTAINER (tree_scroll), tree_root); gtk_widget_show_all(tree_root); gtk_adjustment_set_value( gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(tree_scroll)), 0); gtk_clist_freeze(GTK_CLIST(tree_root)); for(i=0, l = search_result ; l != NULL; i ++, l = g_list_next(l)){ rp = (SEARCH_RESULT *)(l->data); if(result_count >= max_search) { status_message("Exceeded maximum hits."); break; } // 前の結果と辞書が違う場合 if(last_book != rp->book_info){ //サブツリーを作る //1つ前のサブツリーをexpand状態にする node_text[0] = rp->book_info->subbook_title; node = (GtkWidget *)gtk_ctree_insert_node(GTK_CTREE(tree_root), NULL, //parent NULL, //sibling node_text, //text 0, //spacing book_closed_pixmap, //pixmap closed book_closed_mask, //mask closed book_open_pixmap, //pixmap opened book_open_mask, //mask opened FALSE,//is leaf TRUE);//expanded last_book = rp->book_info; i++; } idata = (ITEM_DATA *)calloc(sizeof(ITEM_DATA), 1); g_assert(idata != NULL); idata->result = rp; node_text[0] = "def"; leaf = (GtkWidget *)gtk_ctree_insert_node(GTK_CTREE(tree_root), GTK_CTREE_NODE(node), //parent NULL, //sibling node_text, //text 2, //spacing item_pixmap, //pixmap closed item_mask, //mask closed item_pixmap, //pixmap opened item_mask, //mask opened TRUE,//is leaf TRUE);//expanded // gtk_widget_set_usize( leaf, x, HEADING_HEIGHT ); if(current_row < 0){ current_row = 1; current_node = leaf; } else if(current_row == i){ current_node = leaf; } gtk_ctree_node_set_row_data(GTK_CTREE(tree_root), GTK_CTREE_NODE(leaf), (gpointer)idata); show_heading(leaf); result_count++; } current_node = (GtkWidget *)gtk_ctree_node_nth(GTK_CTREE(tree_root), current_row); gtk_ctree_select(GTK_CTREE(tree_root), GTK_CTREE_NODE(current_node)); ctree_select_row(tree_root, current_row, 0, NULL, NULL); /* rp = (SEARCH_RESULT *)(search_result->data); text = ebook_get_text(rp->book_info, rp->pos_text.page, rp->pos_text.offset); show_text(rp->book_info, text); free(text); show_location(rp); current_position.page = rp->pos_text.page; current_position.offset = rp->pos_text.offset; current_book_info = rp->book_info; save_history(dict_area, rp->book_info, rp->pos_text.page, rp->pos_text.offset); */ gtk_clist_thaw(GTK_CLIST(tree_root)); gtk_container_resize_children(GTK_CONTAINER(tree_scroll)); gtk_container_check_resize(GTK_CONTAINER(tree_scroll)); gtk_container_check_resize(GTK_CONTAINER(tree_root)); gtk_clist_set_column_width(GTK_CLIST(tree_root), 0, x_max+60); if(hex_dlg != NULL) dump_hex(); if(text_dlg != NULL) dump_text(); } static void show_heading(GtkWidget *item) { ITEM_DATA *idata; gint x,y; gint max_width, max_height; GdkGC *gc; CANVAS *canvas; DRAW_TEXT text; // g_assert(item != NULL); if(item == NULL) return; // idata = gtk_object_get_user_data(GTK_OBJECT(item)); idata = gtk_ctree_node_get_row_data(GTK_CTREE(tree_root), GTK_CTREE_NODE(item)); if(idata == NULL){ return; } if(idata->result->heading == NULL) return; x = 0; // y = HEADING_PIXMAP_HEIGHT; y = font_ascent+2; // Pixmapのサイズを決めるために描画をシミュレートする canvas = create_canvas(window); canvas->x = x; canvas->y = y; canvas->width = HEADING_PIXMAP_WIDTH; // canvas->height = HEADING_PIXMAP_HEIGHT; canvas->height = font_height + 2; text.text = idata->result->heading; text.length = strlen(text.text); draw_content(canvas, &text, idata->result->book_info, NULL); x = canvas->x; y = canvas->y; if(x > HEADING_PIXMAP_WIDTH) x = HEADING_PIXMAP_WIDTH; // if(y > HEADING_PIXMAP_HEIGHT) // y = HEADING_PIXMAP_HEIGHT; if(y > font_height) y = font_height; y += 2; // 最大幅を記憶しておく if(x_max < x) { x_max = x; } gc = gdk_gc_new(window->window); if(idata->pixbuff != NULL){ gdk_pixmap_unref(idata->pixbuff); } idata->pixbuff = gdk_pixmap_new( window->window, x, y, -1 ); if(idata->pixbuff == NULL){ g_assert(idata->pixbuff != NULL); } if(item == current_node){ gdk_gc_set_foreground(gc, &tree_root->style->bg[GTK_STATE_SELECTED]); gdk_draw_rectangle(idata->pixbuff, gc, TRUE, 0,0, // widget->allocation.width, x, y); } else { // gdk_gc_set_foreground(gc, &colors[COLOR_WHITE]); // gdk_gc_set_foreground(gc, &tree_root->style->bg[GTK_STATE_NORMAL]); gdk_gc_set_foreground(gc, &tree_root->style->base[GTK_STATE_NORMAL]); // gdk_gc_set_foreground(gc, &widget->style->bg[GTK_STATE_ACTIVE]); gdk_draw_rectangle(idata->pixbuff, gc, // item->style->white_gc, TRUE, 0,0, x, y); } max_width = HEADING_PIXMAP_WIDTH; // max_height = HEADING_PIXMAP_HEIGHT; // unused max_height = font_height+2; // unused x = 0; // y = HEADING_PIXMAP_HEIGHT;; y = font_ascent+2; // 選択されているかどうかで色を変える if(item == current_node){ gdk_gc_set_foreground(gc, &tree_root->style->fg[GTK_STATE_SELECTED]); gdk_gc_set_background(gc, &tree_root->style->bg[GTK_STATE_SELECTED]); } else { gdk_gc_set_foreground(gc, &tree_root->style->fg[GTK_STATE_NORMAL]); // gdk_gc_set_background(gc, &widget->parent->style->bg[GTK_STATE_NORMAL]); // gdk_gc_set_background(gc, &colors[COLOR_WHITE]); gdk_gc_set_background(gc, &tree_root->style->base[GTK_STATE_NORMAL]); } // 描画する canvas->pixmap = idata->pixbuff; canvas->x = x; canvas->y = y; canvas->width = max_width; canvas->height = max_height; canvas->gc = gc; text.text = idata->result->heading; text.length = strlen(text.text); draw_content(canvas, &text, idata->result->book_info, NULL); gdk_gc_destroy(gc); // このノードとPixmapを関連づける gtk_ctree_node_set_pixmap(GTK_CTREE(tree_root), GTK_CTREE_NODE(item), 0, idata->pixbuff, NULL); // idata->old_width = x; // idata->old_height = y; free(canvas); } void item_next() { ITEM_DATA *idata; gchar *text; gint row; GtkWidget *node, *last_node; row = current_row + 1; while(1){ node = (GtkWidget *)gtk_ctree_node_nth(GTK_CTREE(tree_root), row); if(node == NULL) { return; } if(GTK_CTREE_ROW(node)->is_leaf == 1){ last_node = current_node; if(last_node) gtk_ctree_unselect(GTK_CTREE(tree_root), GTK_CTREE_NODE(last_node)); current_node = node; current_row = row; gtk_ctree_select(GTK_CTREE(tree_root), GTK_CTREE_NODE(current_node)); if(last_node) show_heading(last_node); show_heading(node); idata = gtk_ctree_node_get_row_data(GTK_CTREE(tree_root), GTK_CTREE_NODE(node)); show_location(idata->result); text = ebook_get_text( idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); show_text(idata->result->book_info, text); save_history(dict_area, idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); free(text); current_position.page = idata->result->pos_text.page; current_position.offset = idata->result->pos_text.offset; current_book_info = idata->result->book_info; if(gtk_ctree_node_is_visible(GTK_CTREE(tree_root), GTK_CTREE_NODE(current_node)) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(tree_root), row, 0, 1, 0); if(hex_dlg != NULL) dump_hex(); if(text_dlg != NULL) dump_text(); return; } row ++; } } void item_previous() { ITEM_DATA *idata; gchar *text; gint row; GtkWidget *node, *last_node; row = current_row - 1; while(1){ node = (GtkWidget *)gtk_ctree_node_nth(GTK_CTREE(tree_root), row); if(node == NULL) { gtk_clist_moveto(GTK_CLIST(tree_root), 0, 0, 0, 0); return; } if(GTK_CTREE_ROW(node)->is_leaf == 1){ last_node = current_node; if(last_node) gtk_ctree_unselect(GTK_CTREE(tree_root), GTK_CTREE_NODE(last_node)); current_node = node; current_row = row; gtk_ctree_select(GTK_CTREE(tree_root), GTK_CTREE_NODE(current_node)); if(last_node) show_heading(last_node); show_heading(node); idata = gtk_ctree_node_get_row_data(GTK_CTREE(tree_root), GTK_CTREE_NODE(node)); show_location(idata->result); text = ebook_get_text( idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); show_text(idata->result->book_info, text); save_history(dict_area, idata->result->book_info, idata->result->pos_text.page, idata->result->pos_text.offset); free(text); current_position.page = idata->result->pos_text.page; current_position.offset = idata->result->pos_text.offset; current_book_info = idata->result->book_info; if(gtk_ctree_node_is_visible(GTK_CTREE(tree_root), GTK_CTREE_NODE(current_node)) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(tree_root), row, 0, 0, 0); if(hex_dlg != NULL) dump_hex(); if(text_dlg != NULL) dump_text(); return; } row --; } }