#include "window.h" #include "ui.h" #include "edit.h" #include "draw.h" #include "geometry.h" #include "level.h" #include static GtkWidget *drawingArea = NULL; static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL; static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { return FALSE; } static gboolean scrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) { const gdouble x = event->x/widget->allocation.width, y = event->y/widget->allocation.height; switch(event->direction) { case GDK_SCROLL_UP: zoomIn(1.1, x, y); break; case GDK_SCROLL_DOWN: zoomOut(1.1, x, y); } } static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { VERTEX v = {event->x, event->y}; int i; switch(event->type) { case GDK_BUTTON_PRESS: switch(event->button) { case 1: viewToImage(&v); setActiveRoom(NULL); for(i = 0; i < getLevel()->nRooms; i++) { if(vertexInPolygon(&v, &getLevel()->rooms[i])) { setActiveRoom(&getLevel()->rooms[i]); break; } } redraw(); gtk_widget_queue_draw(drawingArea); } } return FALSE; } gboolean crossingNotifyEvent(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) { int i; VERTEX v; setHoveredRoom(NULL); if(event->type == GDK_ENTER_NOTIFY) { v.x = event->x; v.y = event->y; viewToImage(&v); for(i = 0; i < getLevel()->nRooms; i++) { if(vertexInPolygon(&v, &getLevel()->rooms[i])) { setHoveredRoom(&getLevel()->rooms[i]); break; } } } gtk_widget_queue_draw(drawingArea); } gboolean motionNotifyEvent(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { int i; static VERTEX v, v_last = {0, 0}; LINE line; gboolean changed = FALSE; v.x = event->x; v.y = event->y; viewToImage(&v); line.v1 = v_last; line.v2 = v; for(i = 0; i < getLevel()->nRooms; i++) { if(linePolygonIntersection(&line, &getLevel()->rooms[i])) { if(vertexInPolygon(&v, &getLevel()->rooms[i])) { setHoveredRoom(&getLevel()->rooms[i]); changed = TRUE; break; } else { setHoveredRoom(NULL); changed = TRUE; } } } if(changed) gtk_widget_queue_draw(drawingArea); v_last = v; } static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } static void refreshScrolling() { if(getImageWidth() < drawingArea->allocation.width) setXTranslate((getImageWidth()-drawingArea->allocation.width)/2); else setXTranslate(gtk_adjustment_get_value(hAdjustment)); if(getImageHeight() < drawingArea->allocation.height) setYTranslate((getImageHeight()-drawingArea->allocation.height)/2); else setYTranslate(gtk_adjustment_get_value(vAdjustment)); gtk_widget_queue_draw(drawingArea); } static void updateScrollbars(double x, double y) { const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight(); const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height; gdouble upper, pageSize, value; gdk_window_freeze_updates(drawingArea->window); g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL); g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL); gtk_adjustment_changed(hAdjustment); if((pageSize > upper && width < imageWidth) || upper == 0) value = (imageWidth-width)/2; else value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x; gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, imageWidth-width), 0)); g_object_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL); g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL); gtk_adjustment_changed(vAdjustment); if((pageSize > upper && height < imageHeight) || upper == 0) value = (imageHeight-height)/2; else value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y; gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0)); gdk_window_thaw_updates(drawingArea->window); refreshScrolling(); } static void updateScrollbarsCentered() { updateScrollbars(0.5, 0.5); } GtkWidget* createMainWindow() { GtkWidget *window, *vbox, *menubar, *toolbar, *hPaned, *table, *vScroll, *hScroll, *sidebar; GdkColor color = {0, 0, 0, 0}; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 640, 480); g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(deleteEvent), NULL); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); menubar = getMenu(); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); toolbar = getToolbar(); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); gtk_window_add_accel_group(GTK_WINDOW(window), getAccels()); hPaned = gtk_hpaned_new(); gtk_box_pack_end(GTK_BOX(vbox), hPaned, TRUE, TRUE, 0); table = gtk_table_new(2, 2, FALSE); gtk_paned_pack1(GTK_PANED(hPaned), table, TRUE, TRUE); drawingArea = gtk_drawing_area_new(); gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color); g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(updateScrollbarsCentered), NULL); g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(drawTopView), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-press-event", G_CALLBACK(buttonEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-release-event", G_CALLBACK(buttonEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "enter-notify-event", G_CALLBACK(crossingNotifyEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "leave-notify-event", G_CALLBACK(crossingNotifyEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "motion-notify-event", G_CALLBACK(motionNotifyEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(scrollEvent), NULL); gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_double_buffered(drawingArea, FALSE); gtk_table_attach(GTK_TABLE(table), drawingArea, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND|GTK_SHRINK, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100)); hScroll = gtk_hscrollbar_new(hAdjustment); g_signal_connect(G_OBJECT(hScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL); gtk_table_attach(GTK_TABLE(table), hScroll, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0, 0); vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100)); vScroll = gtk_vscrollbar_new(vAdjustment); g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL); gtk_table_attach(GTK_TABLE(table), vScroll, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); sidebar = gtk_vbox_new(FALSE, 0); gtk_paned_pack2(GTK_PANED(hPaned), sidebar, FALSE, TRUE); gtk_widget_show_all(vbox); return window; } void zoomIn(double factor, double x, double y) { setScale(getScale()*factor); updateScrollbars(x, y); } void zoomOut(double factor, double x, double y) { setScale(getScale()/factor); updateScrollbars(x, y); } void zoomInCentered(double factor) { zoomIn(factor, 0.5, 0.5); } void zoomOutCentered(double factor) { zoomOut(factor, 0.5, 0.5); }