zoomedit: Improved scrolling, added zoom
This commit is contained in:
parent
84361f7a9e
commit
2a3c0deaa5
3 changed files with 63 additions and 29 deletions
13
ui.c
13
ui.c
|
@ -26,7 +26,14 @@ static const gchar *uiData =
|
||||||
"</ui>";
|
"</ui>";
|
||||||
|
|
||||||
|
|
||||||
|
static void handleAction(GtkAction *action, gpointer user_data) {
|
||||||
|
const gchar* name = gtk_action_get_name(action);
|
||||||
|
|
||||||
|
if(!strcmp(name, "zoomIn"))
|
||||||
|
zoomInCentered(1.2);
|
||||||
|
else if(!strcmp(name, "zoomOut"))
|
||||||
|
zoomOutCentered(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
static GtkActionGroup *createActions() {
|
static GtkActionGroup *createActions() {
|
||||||
GtkActionGroup *actionGroup = gtk_action_group_new("actions");
|
GtkActionGroup *actionGroup = gtk_action_group_new("actions");
|
||||||
|
@ -51,11 +58,11 @@ static GtkActionGroup *createActions() {
|
||||||
gtk_action_group_add_action(actionGroup, action);
|
gtk_action_group_add_action(actionGroup, action);
|
||||||
|
|
||||||
action = gtk_action_new("zoomIn", "Zoom _in", NULL, GTK_STOCK_ZOOM_IN);
|
action = gtk_action_new("zoomIn", "Zoom _in", NULL, GTK_STOCK_ZOOM_IN);
|
||||||
g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(zoomIn), NULL);
|
g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(handleAction), NULL);
|
||||||
gtk_action_group_add_action_with_accel(actionGroup, action, NULL);
|
gtk_action_group_add_action_with_accel(actionGroup, action, NULL);
|
||||||
|
|
||||||
action = gtk_action_new("zoomOut", "Zoom _out", NULL, GTK_STOCK_ZOOM_OUT);
|
action = gtk_action_new("zoomOut", "Zoom _out", NULL, GTK_STOCK_ZOOM_OUT);
|
||||||
g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(zoomOut), NULL);
|
g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(handleAction), NULL);
|
||||||
gtk_action_group_add_action_with_accel(actionGroup, action, NULL);
|
gtk_action_group_add_action_with_accel(actionGroup, action, NULL);
|
||||||
|
|
||||||
action = gtk_action_new("quit", "_Quit", NULL, GTK_STOCK_QUIT);
|
action = gtk_action_new("quit", "_Quit", NULL, GTK_STOCK_QUIT);
|
||||||
|
|
72
window.c
72
window.c
|
@ -8,10 +8,22 @@ static GtkWidget *drawingArea = NULL;
|
||||||
static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL;
|
static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL;
|
||||||
|
|
||||||
|
|
||||||
static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
|
static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) {
|
||||||
return FALSE;
|
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 void destroy(GtkWidget *widget, gpointer data) {
|
static void destroy(GtkWidget *widget, gpointer data) {
|
||||||
gtk_main_quit();
|
gtk_main_quit();
|
||||||
}
|
}
|
||||||
|
@ -27,36 +39,44 @@ static void refreshScrolling() {
|
||||||
else
|
else
|
||||||
setYTranslate(gtk_adjustment_get_value(vAdjustment));
|
setYTranslate(gtk_adjustment_get_value(vAdjustment));
|
||||||
|
|
||||||
gdk_window_invalidate_rect(drawingArea->window, NULL, FALSE);
|
gtk_widget_queue_draw(drawingArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateScrollbars() {
|
static void updateScrollbars(double x, double y) {
|
||||||
const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight();
|
const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight();
|
||||||
const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height;
|
const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height;
|
||||||
gdouble upper, pageSize, value;
|
gdouble upper, pageSize, value;
|
||||||
|
|
||||||
|
gdk_window_freeze_updates(drawingArea->window);
|
||||||
|
|
||||||
g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL);
|
g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL);
|
||||||
g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL);
|
g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL);
|
||||||
gtk_adjustment_changed(hAdjustment);
|
gtk_adjustment_changed(hAdjustment);
|
||||||
|
|
||||||
if(pageSize > upper && width < imageWidth)
|
if((pageSize > upper && width < imageWidth) || upper == 0)
|
||||||
value = (imageWidth-width)/2;
|
value = (imageWidth-width)/2;
|
||||||
else
|
else
|
||||||
value = MAX(MIN(gtk_adjustment_get_value(hAdjustment) - (width-pageSize)/2 + (imageWidth-upper)/2, imageWidth-width), 0);
|
value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x;
|
||||||
gtk_adjustment_set_value(hAdjustment, value);
|
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_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL);
|
||||||
g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL);
|
g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL);
|
||||||
|
|
||||||
if(pageSize > upper && height < imageHeight)
|
if((pageSize > upper && height < imageHeight) || upper == 0)
|
||||||
value = (imageHeight-height)/2;
|
value = (imageHeight-height)/2;
|
||||||
else
|
else
|
||||||
value = MAX(MIN(gtk_adjustment_get_value(vAdjustment) - (height-pageSize)/2 + (imageHeight-upper)/2, imageHeight-height), 0);
|
value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y;
|
||||||
gtk_adjustment_set_value(vAdjustment, value);
|
gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0));
|
||||||
|
|
||||||
|
gdk_window_thaw_updates(drawingArea->window);
|
||||||
|
|
||||||
refreshScrolling();
|
refreshScrolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateScrollbarsCentered() {
|
||||||
|
updateScrollbars(0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
GtkWidget* createMainWindow() {
|
GtkWidget* createMainWindow() {
|
||||||
GtkWidget *window, *vbox, *menubar, *toolbar, *table, *vScroll, *hScroll;
|
GtkWidget *window, *vbox, *menubar, *toolbar, *table, *vScroll, *hScroll;
|
||||||
GdkColor color = {0, 0, 0, 0};
|
GdkColor color = {0, 0, 0, 0};
|
||||||
|
@ -64,7 +84,7 @@ GtkWidget* createMainWindow() {
|
||||||
|
|
||||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
|
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
|
||||||
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), NULL);
|
g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(deleteEvent), NULL);
|
||||||
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
|
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
|
||||||
|
|
||||||
vbox = gtk_vbox_new(FALSE, 0);
|
vbox = gtk_vbox_new(FALSE, 0);
|
||||||
|
@ -72,11 +92,9 @@ GtkWidget* createMainWindow() {
|
||||||
|
|
||||||
menubar = getMenu();
|
menubar = getMenu();
|
||||||
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
|
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
|
||||||
gtk_widget_show(menubar);
|
|
||||||
|
|
||||||
toolbar = getToolbar();
|
toolbar = getToolbar();
|
||||||
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
|
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
|
||||||
gtk_widget_show(toolbar);
|
|
||||||
|
|
||||||
gtk_window_add_accel_group(GTK_WINDOW(window), getAccels());
|
gtk_window_add_accel_group(GTK_WINDOW(window), getAccels());
|
||||||
|
|
||||||
|
@ -85,35 +103,41 @@ GtkWidget* createMainWindow() {
|
||||||
|
|
||||||
drawingArea = gtk_drawing_area_new();
|
drawingArea = gtk_drawing_area_new();
|
||||||
gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color);
|
gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color);
|
||||||
g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(updateScrollbars), NULL);
|
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), "expose-event", G_CALLBACK(drawTopView), NULL);
|
||||||
|
g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(scrollEvent), NULL);
|
||||||
|
gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK);
|
||||||
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);
|
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);
|
||||||
gtk_widget_show(drawingArea);
|
|
||||||
|
|
||||||
hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
||||||
hScroll = gtk_hscrollbar_new(hAdjustment);
|
hScroll = gtk_hscrollbar_new(hAdjustment);
|
||||||
g_signal_connect(G_OBJECT(hScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL);
|
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);
|
gtk_table_attach(GTK_TABLE(table), hScroll, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0, 0);
|
||||||
gtk_widget_show(hScroll);
|
|
||||||
|
|
||||||
vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
||||||
vScroll = gtk_vscrollbar_new(vAdjustment);
|
vScroll = gtk_vscrollbar_new(vAdjustment);
|
||||||
g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL);
|
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);
|
gtk_table_attach(GTK_TABLE(table), vScroll, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0);
|
||||||
gtk_widget_show(vScroll);
|
|
||||||
|
|
||||||
gtk_widget_show(table);
|
gtk_widget_show_all(vbox);
|
||||||
gtk_widget_show(vbox);
|
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoomIn() {
|
void zoomIn(double factor, double x, double y) {
|
||||||
setScale(getScale()*1.5);
|
setScale(getScale()*factor);
|
||||||
updateScrollbars();
|
updateScrollbars(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoomOut() {
|
void zoomOut(double factor, double x, double y) {
|
||||||
setScale(getScale()/1.5);
|
setScale(getScale()/factor);
|
||||||
updateScrollbars();
|
updateScrollbars(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zoomInCentered(double factor) {
|
||||||
|
zoomIn(factor, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zoomOutCentered(double factor) {
|
||||||
|
zoomOut(factor, 0.5, 0.5);
|
||||||
}
|
}
|
||||||
|
|
7
window.h
7
window.h
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
|
|
||||||
GtkWidget* createMainWindow();
|
GtkWidget* createMainWindow();
|
||||||
void zoomIn();
|
|
||||||
void zoomOut();
|
void zoomIn(double factor, double x, double y);
|
||||||
|
void zoomOut(double factor, double x, double y);
|
||||||
|
void zoomInCentered(double factor);
|
||||||
|
void zoomOutCentered(double factor);
|
||||||
|
|
||||||
#endif /*WINDOW_H_*/
|
#endif /*WINDOW_H_*/
|
||||||
|
|
Reference in a new issue