summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2010-02-18 00:46:12 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2010-02-18 00:46:12 +0100
commitb13140f726ee9c3c8fbcc870d673dbfa37ffb23e (patch)
tree8b9245ba5bb4aeb3d0454201e75b1435db05ebff
parent956ac944c435a0a116fae2fe664b0af7210802be (diff)
Implemented basic zoom modes (best fit and normal)
This lets the user switch between best fit and normal zoom modes. Zooming in and out is not yet implemented.
-rw-r--r--walls.ui94
-rw-r--r--window_main.c140
2 files changed, 222 insertions, 12 deletions
diff --git a/walls.ui b/walls.ui
index 931b47e..7f3a410 100644
--- a/walls.ui
+++ b/walls.ui
@@ -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));