summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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));