/* 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 #include "defs.h" #include "global.h" #include "canvas.h" #include "contentarea.h" #include "link.h" #include "select.h" #include "eb.h" #include "popup.h" GtkWidget *popup=NULL; static GtkWidget *popup_scroll=NULL; static GtkWidget *popup_viewport=NULL; static const title_height = 22; static gint align_x = 10; static gint align_y = 10; GList *current_result=NULL; static CONTENT_AREA *popup_area=NULL; static gint close_popup(GtkWidget *widget, gpointer data){ gtk_widget_destroy(popup); gtk_widget_grab_focus(popup); gtk_grab_add(popup); popup = NULL; destroy_canvas(popup_area->canvas); destroy_content_area(popup_area); } static gint popup_click_event (GtkWidget *widget, GdkEventButton *event) { gchar *text = NULL; SEARCH_RESULT *rp; if(event->type == GDK_BUTTON_PRESS){ if (event->button == 1){ gtk_widget_destroy(popup); popup = NULL; destroy_canvas(popup_area->canvas); destroy_content_area(popup_area); } else if ((event->button == 2) || (event->button == 3)){ if(!current_result) return(FALSE); if (event->button == 2) { if(g_list_previous(current_result) == NULL){ return(FALSE); } current_result = g_list_previous(current_result); } else { if(g_list_next(current_result) == NULL){ return(FALSE); } current_result = g_list_next(current_result); } if(current_result == NULL) return(0); rp = (SEARCH_RESULT *)(current_result->data); current_book_info = rp->book_info; if(current_result){ text = ebook_get_text(rp->book_info, rp->pos_text.page, rp->pos_text.offset); show_popup(rp->book_info, text); free(text); } } } return(FALSE); } static void show_in_popup(BOOK_INFO *binfo, gchar *text){ show_popup(binfo, text); } static gint title_click_event (GtkWidget *widget, GdkEventButton *event, gpointer data) { gchar *text = NULL; SEARCH_RESULT *rp; if(event->type == GDK_BUTTON_PRESS){ if ((event->button == 2) || (event->button == 3)){ return(FALSE); } if((strcmp(data, "<") == 0) || (strcmp(data, ">") == 0)){ if(strcmp(data, "<") == 0){ if(g_list_previous(current_result) == NULL){ return(FALSE); } current_result = g_list_previous(current_result); } else { if(g_list_next(current_result) == NULL){ return(FALSE); } current_result = g_list_next(current_result); } if(current_result == NULL) return(0); rp = (SEARCH_RESULT *)(current_result->data); current_book_info = rp->book_info; if(current_result){ text = ebook_get_text(rp->book_info, rp->pos_text.page, rp->pos_text.offset); show_popup(rp->book_info, text); free(text); } } else if(strcmp(data, "X") == 0){ gtk_widget_destroy(popup); popup = NULL; destroy_canvas(popup_area->canvas); destroy_content_area(popup_area); } } else if((event->button == 1) && (event->type == GDK_2BUTTON_PRESS)){ // ダブルクリック } return(TRUE); } void show_popup(BOOK_INFO *binfo, gchar *text) { GdkModifierType mask; gint pos_x, pos_y; gint pointer_x, pointer_y; gint root_x, root_y; GdkWindow *root_win = NULL; gint x, y; gint max_width, max_height; GdkGC *gc=NULL; static gint shadow_width = 4, shadow_height = 4; gint window_width, window_height; CANVAS *canvas; DRAW_TEXT l_text; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *eventbox; GtkWidget *title_label; GtkWidget *pixmapwid; GtkWidget *frame; GtkWidget *separator; gboolean redraw=FALSE; g_return_if_fail(text != NULL); //無駄にウィンドウサイズが大きくなるのを防ぐ if(text[strlen(text)-1] == '\n') text[strlen(text)-1] = '\0'; root_win = gdk_window_foreign_new (GDK_ROOT_WINDOW ()); gdk_window_get_size(root_win, &root_x, &root_y); if(popup != NULL){ // 既に開いているときにはその位置を使うが、 // 画面からはみ出る時には移動する。 gdk_window_get_position(popup->window, &pos_x, &pos_y); gtk_widget_destroy(popup); destroy_canvas(popup_area->canvas); destroy_content_area(popup_area); redraw = TRUE; } // ポップアップウィンドウの位置を決めるにあたり、 // まずキャンバスのサイズを決める popup_area = create_content_area(100, 100); popup_area->show_func = show_in_popup; popup_area->canvas = create_canvas(window); popup_area->canvas->content_area = popup_area; max_width = popup_width - shadow_width - 20; max_height = popup_height - shadow_height; simulate_canvas(popup_area->canvas, binfo, text, max_width, max_height); if(popup_area->canvas->y < max_height) popup_area->canvas->height = popup_area->canvas->y+10; if(popup_area->canvas->height < max_height){ window_width = popup_width; window_height = popup_area->canvas->height + shadow_height; } else { window_width = popup_width; window_height = max_height + shadow_height; } if(!redraw){ // ポップアップウィンドウが開いていないときには // マウスの位置から場所を決定する。 gdk_window_get_pointer(root_win, &pointer_x, &pointer_y, &mask); pos_x = pointer_x + align_x; pos_y = pointer_y + align_y; } if((pos_x + window_width + align_x + shadow_width) > root_x){ pos_x = root_x - window_width; } if(bshow_popup_title) { if((pos_y + window_height + title_height + align_y + shadow_height) > root_y){ pos_y = root_y - window_height - title_height; } } else { if((pos_y + window_height + align_y + shadow_height) > root_y){ pos_y = root_y - window_height; } } popup = gtk_widget_new (GTK_TYPE_WINDOW, "type", GTK_WINDOW_TOPLEVEL, "x", pos_x, "y", pos_y, NULL); gtk_window_set_wmclass(GTK_WINDOW(popup), "Popup", "EBView"); gtk_window_set_policy(GTK_WINDOW(popup),FALSE,FALSE,TRUE); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add (GTK_CONTAINER (popup), vbox); if(bshow_popup_title){ frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_container_add( GTK_CONTAINER(frame), hbox); eventbox = gtk_event_box_new(); gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 2); gtk_signal_connect( GTK_OBJECT(eventbox),"button_press_event", (GtkSignalFunc)title_click_event, (gpointer)"<"); pixmapwid = gtk_pixmap_new (small_left_pixmap, small_left_mask); gtk_container_add( GTK_CONTAINER(eventbox), pixmapwid); separator = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, FALSE, 0); title_label = gtk_label_new("x of x"); gtk_box_pack_start(GTK_BOX(hbox), title_label, TRUE, TRUE, 0); separator = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, FALSE, 0); eventbox = gtk_event_box_new(); gtk_box_pack_end(GTK_BOX(hbox), eventbox, FALSE, FALSE, 2); gtk_signal_connect( GTK_OBJECT(eventbox),"button_press_event", (GtkSignalFunc)title_click_event, (gpointer)"X"); pixmapwid = gtk_pixmap_new (small_close_pixmap, small_close_mask); gtk_container_add( GTK_CONTAINER(eventbox), pixmapwid); separator = gtk_vseparator_new(); gtk_box_pack_end(GTK_BOX(hbox), separator, FALSE, FALSE, 0); eventbox = gtk_event_box_new(); gtk_box_pack_end(GTK_BOX(hbox), eventbox, FALSE, FALSE, 2); gtk_signal_connect( GTK_OBJECT(eventbox),"button_press_event", (GtkSignalFunc)title_click_event, (gpointer)">"); pixmapwid = gtk_pixmap_new (small_right_pixmap, small_right_mask); gtk_container_add( GTK_CONTAINER(eventbox), pixmapwid); } popup_scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (popup_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); popup_viewport = gtk_viewport_new ( gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(popup_scroll)), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW(popup_scroll))); gtk_container_add (GTK_CONTAINER (popup_scroll), popup_viewport); gtk_box_pack_start(GTK_BOX(vbox), popup_scroll, FALSE, FALSE, 0); gtk_signal_connect( GTK_OBJECT(popup_area->area),"button_press_event", (GtkSignalFunc)popup_click_event, NULL); gtk_signal_connect( GTK_OBJECT(popup),"close_popup", (GtkSignalFunc)close_popup, NULL); gtk_viewport_set_shadow_type(GTK_VIEWPORT(popup_viewport), GTK_SHADOW_ETCHED_OUT); gtk_widget_realize(popup); //gdk_window_set_decorations(popup->window, GDK_DECOR_BORDER); gdk_window_set_decorations(popup->window, 0); if(bshow_popup_title){ gchar title[256]; sprintf(title, "%d of %d", g_list_index(search_result, current_result->data) + 1, g_list_length(search_result)); gtk_label_set_text(GTK_LABEL(title_label), title); } clear_content_area(popup_area); resize_content_area(popup_area, popup_area->canvas->max_width, popup_area->canvas->height); create_pixmap(popup_area->canvas); clear_canvas(popup_area->canvas); fill_canvas(popup_area->canvas); draw_canvas(popup_area->canvas, binfo, text); clear_location(popup_area); gtk_widget_set_usize(popup_viewport, window_width, window_height); gtk_container_add(GTK_CONTAINER(popup_viewport), popup_area->area); gtk_widget_show_all(popup); gtk_adjustment_set_value( gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(popup_scroll)), 0); }