diff options
-rw-r--r-- | walls.ui | 94 | ||||
-rw-r--r-- | window_main.c | 140 |
2 files changed, 222 insertions, 12 deletions
@@ -55,6 +55,19 @@ <property name="visible">True</property> <property name="label" translatable="yes">_View</property> <property name="use_underline">True</property> + <signal name="activate" handler="on_view_activate"/> + <child type="submenu"> + <object class="GtkMenu" id="viewmenu"> + <property name="visible">True</property> + <child> + <object class="GtkCheckMenuItem" id="view_toolbar"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Toolbar</property> + <property name="use_underline">True</property> + </object> + </child> + </object> + </child> </object> </child> <child> @@ -84,6 +97,67 @@ </packing> </child> <child> + <object class="GtkToolbar" id="zoom_toolbar"> + <property name="visible">True</property> + <child> + <object class="GtkRadioToolButton" id="zoom_bestfit"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Best fit</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-fit</property> + <property name="active">True</property> + <signal name="toggled" handler="on_zoom_mode_toggled"/> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkRadioToolButton" id="zoom_normal"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Normal</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-100</property> + <property name="group">zoom_bestfit</property> + <signal name="toggled" handler="on_zoom_mode_toggled"/> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkToolButton" id="zoom_in"> + <property name="visible">True</property> + <property name="label" translatable="yes">Zoom _In</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-in</property> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkToolButton" id="zoom_out"> + <property name="visible">True</property> + <property name="label" translatable="yes">Zoom _Out</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-out</property> + </object> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> <object class="GtkHPaned" id="window_hpane"> <property name="visible">True</property> <child> @@ -106,6 +180,7 @@ <object class="GtkTreeView" id="foldtree"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="has_focus">True</property> <signal name="button_press_event" handler="on_foldtree_button_press_event"/> <signal name="popup_menu" handler="on_foldtree_popup_menu"/> </object> @@ -186,11 +261,22 @@ </packing> </child> <child> - <object class="GtkLayout" id="layout"> + <object class="GtkScrolledWindow" id="layout_scroller"> <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> <child> - <object class="GtkImage" id="image"> + <object class="GtkLayout" id="layout"> <property name="visible">True</property> + <signal name="button_press_event" handler="on_layout_button_press_event"/> + <signal name="motion_notify_event" handler="on_layout_motion_notify_event"/> + <signal name="button_release_event" handler="on_layout_button_release_event"/> + <child> + <object class="GtkImage" id="image"> + <property name="visible">True</property> + </object> + </child> </object> </child> </object> @@ -201,7 +287,7 @@ </child> </object> <packing> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child> @@ -211,7 +297,7 @@ </object> <packing> <property name="expand">False</property> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> </object> diff --git a/window_main.c b/window_main.c index fe2c68d..ff5200f 100644 --- a/window_main.c +++ b/window_main.c @@ -11,19 +11,30 @@ #include "window_tag.h" #include "preload.h" +enum zoom_mode_t { + ZOOM_BESTFIT, + ZOOM_NORMAL, + ZOOM_CUSTOM, +}; + struct wallpaper_t *cur_wall = NULL; GdkPixbuf *orig_pixbuf = NULL; gint last_width = 0, last_height = 0, hpane_last_pos = 0; guint hpane_source_id = 0; +gboolean layout_dragging = FALSE; +gdouble layout_dragx, layout_dragy; + +enum zoom_mode_t zoom_mode = ZOOM_BESTFIT; GtkWindow *window; GtkImage *image = NULL; GtkWidget *layout = NULL; GtkStatusbar *statusbar; GtkIconView *thumbview; -GtkWidget *window_hpane, *window_vpane, *foldtree, *tagview; +GtkWidget *window_hpane, *window_vpane, *foldtree, *tagview, *view_toolbar, + *zoom_toolbar, *zoom_bestfit, *zoom_normal; GThread *wallpaper_thread = NULL; @@ -109,7 +120,11 @@ static void set_resize_msg(gdouble scale) { gchar *msg; gtk_statusbar_pop(statusbar, image_context); - msg = g_strdup_printf("%s (%d %%)", cur_wall_msg, (gint)(scale * 100.0)); + if(scale == 0) { + msg = g_strdup(cur_wall_msg); + } else { + msg = g_strdup_printf("%s (%d %%)", cur_wall_msg, (gint)(scale * 100.0)); + } gtk_statusbar_push(statusbar, image_context, msg); g_free(msg); } @@ -125,6 +140,33 @@ static void set_image_pixbuf_resized(GdkPixbuf *pb, gint win_width, gint win_hei gtk_layout_set_size(GTK_LAYOUT(layout), win_width, win_height); } +static void layout_center(gint width, gint height) { + GtkAdjustment *hadj, *vadj; + gdouble hupper, hpagesize, vupper, vpagesize; + + hadj = gtk_layout_get_hadjustment(GTK_LAYOUT(layout)); + vadj = gtk_layout_get_vadjustment(GTK_LAYOUT(layout)); + + hupper = gtk_adjustment_get_upper(GTK_ADJUSTMENT(hadj)); + hpagesize = gtk_adjustment_get_page_size(GTK_ADJUSTMENT(hadj)); + vupper = gtk_adjustment_get_upper(GTK_ADJUSTMENT(vadj)); + vpagesize = gtk_adjustment_get_page_size(GTK_ADJUSTMENT(vadj)); + + gtk_adjustment_set_value(GTK_ADJUSTMENT(hadj), hupper / 2 - hpagesize / 2); + gtk_adjustment_set_value(GTK_ADJUSTMENT(vadj), vupper / 2 - vpagesize / 2); +} + +static void set_image_pixbuf_normal(GdkPixbuf *pb, gint win_width, gint win_height, gint width, gint height) { + set_resize_msg(0.0); + + gtk_widget_set_size_request(GTK_WIDGET(image), width, height); + gtk_widget_set_uposition(GTK_WIDGET(image), (width < win_width ? win_width / 2 - width / 2 : 0), + (height < win_height ? win_height / 2 - height / 2 : 0)); + gtk_image_set_from_pixbuf(image, pb); + gtk_layout_set_size(GTK_LAYOUT(layout), width, height); + layout_center(width, height); +} + static void set_image_pixbuf() { GdkWindow *window; GdkPixbuf *pb; @@ -137,12 +179,16 @@ static void set_image_pixbuf() { window = gtk_widget_get_window(layout); gdk_drawable_get_size(window, &win_width, &win_height); - pb = resize_pixbuf(orig_pixbuf, win_width, win_height, &width, &height, &ratio); - if(!pb) - return; + if(zoom_mode == ZOOM_BESTFIT) { + pb = resize_pixbuf(orig_pixbuf, win_width, win_height, &width, &height, &ratio); + if(!pb) + return; - set_image_pixbuf_resized(pb, win_width, win_height, width, height, ratio); - g_object_unref(pb); + set_image_pixbuf_resized(pb, win_width, win_height, width, height, ratio); + g_object_unref(pb); + } else if(zoom_mode == ZOOM_NORMAL || zoom_mode == ZOOM_CUSTOM) { + set_image_pixbuf_normal(orig_pixbuf, win_width, win_height, gdk_pixbuf_get_width(orig_pixbuf), gdk_pixbuf_get_height(orig_pixbuf)); + } } void on_window_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) { @@ -247,7 +293,11 @@ static void load_pixbuf(const gchar *filepath) { window = gtk_widget_get_window(layout); gdk_drawable_get_size(window, &win_width, &win_height); - set_image_pixbuf_resized(pt->pb, win_width, win_height, pt->width, pt->height, pt->ratio); + if(zoom_mode == ZOOM_BESTFIT) { + set_image_pixbuf_resized(pt->pb, win_width, win_height, pt->width, pt->height, pt->ratio); + } else { + set_image_pixbuf_normal(pt->pb_orig, win_width, win_height, gdk_pixbuf_get_width(pt->pb_orig), gdk_pixbuf_get_height(pt->pb_orig)); + } } else set_image_pixbuf(); } @@ -855,6 +905,74 @@ gboolean on_left_pages_switch_page(GtkNotebook *notebook, GtkNotebookTab page, g return TRUE; } +void on_view_activate(GtkMenuItem *menuitem, gpointer user_data) { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(view_toolbar), gtk_widget_get_visible(zoom_toolbar)); +} + +void on_zoom_mode_toggled(GtkToggleToolButton *toolbutton, gpointer user_data) { + if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(zoom_bestfit))) { + zoom_mode = ZOOM_BESTFIT; + } else if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(zoom_normal))) { + zoom_mode = ZOOM_NORMAL; + } + + if(zoom_mode != ZOOM_CUSTOM) { + set_image_pixbuf(); + } +} + +gboolean on_layout_button_press_event(GtkWindow *widget, GdkEventButton *event, gpointer user_data) { + GtkAdjustment *hadj, *vadj; + + if(event->button == 1 && zoom_mode != ZOOM_BESTFIT) { + hadj = gtk_layout_get_hadjustment(GTK_LAYOUT(layout)); + vadj = gtk_layout_get_vadjustment(GTK_LAYOUT(layout)); + + layout_dragging = TRUE; + layout_dragx = event->x; + layout_dragy = event->y; + } + + return FALSE; +} + +gboolean on_layout_button_release_event(GtkWindow *widget, GdkEventButton *event, gpointer user_data) { + if(event->button == 1) { + layout_dragging = FALSE; + } + + return FALSE; +} + +gboolean on_layout_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { + GtkAdjustment *hadj, *vadj; + gdouble adjx, adjy; + gdouble hupper, hpagesize, vupper, vpagesize; + + if(layout_dragging) { + hadj = gtk_layout_get_hadjustment(GTK_LAYOUT(layout)); + vadj = gtk_layout_get_vadjustment(GTK_LAYOUT(layout)); + + hupper = gtk_adjustment_get_upper(GTK_ADJUSTMENT(hadj)); + hpagesize = gtk_adjustment_get_page_size(GTK_ADJUSTMENT(hadj)); + vupper = gtk_adjustment_get_upper(GTK_ADJUSTMENT(vadj)); + vpagesize = gtk_adjustment_get_page_size(GTK_ADJUSTMENT(vadj)); + + adjx = gtk_adjustment_get_value(GTK_ADJUSTMENT(hadj)) + (layout_dragx - event->x); + adjy = gtk_adjustment_get_value(GTK_ADJUSTMENT(vadj)) + (layout_dragy - event->y); + + if(adjx > hupper - hpagesize) + adjx = hupper - hpagesize; + if(adjy > vupper - vpagesize) + adjy = vupper - vpagesize; + + gtk_adjustment_set_value(GTK_ADJUSTMENT(hadj), adjx); + gtk_adjustment_set_value(GTK_ADJUSTMENT(vadj), adjy); + } + + return FALSE; +} + static void save_window() { gint width, height; @@ -924,6 +1042,7 @@ int gui_main(int argc, char **argv) { layout = GTK_WIDGET(gtk_builder_get_object(builder, "layout")); if(gdk_color_parse("#000", &color)) gtk_widget_modify_bg(GTK_WIDGET(layout), GTK_STATE_NORMAL, &color); + gtk_widget_add_events(layout, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); window_hpane = GTK_WIDGET(gtk_builder_get_object(builder, "window_hpane")); g_signal_connect(window_hpane, "notify::position", G_CALLBACK(on_window_hpane_resized), window_hpane); @@ -932,6 +1051,11 @@ int gui_main(int argc, char **argv) { statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar")); image_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "Image display"); + view_toolbar = GTK_WIDGET(gtk_builder_get_object(builder, "view_toolbar")); + zoom_toolbar = GTK_WIDGET(gtk_builder_get_object(builder, "zoom_toolbar")); + zoom_bestfit = GTK_WIDGET(gtk_builder_get_object(builder, "zoom_bestfit")); + zoom_normal = GTK_WIDGET(gtk_builder_get_object(builder, "zoom_normal")); + gtk_builder_connect_signals(builder, NULL); g_object_unref(G_OBJECT(builder)); |