Skip to content

Commit

Permalink
Pho 0.7, 2002-08-13:
Browse files Browse the repository at this point in the history
  Put image name in titlebar; prompt after last image before quitting;
  add fullscreen mode.
  • Loading branch information
akkana committed Jan 12, 2010
1 parent e6f55db commit 0b5457a
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 135 deletions.
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Makefile for pho

CFLAGS = -g -O2 -Wall -I/usr/include/gdk-pixbuf-1.0 -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include
# Locate the gtk/gdk libraries (thanks to nev for this!)
CFLAGS = -g -O2 -Wall
CFLAGS := $(CFLAGS) $(shell gdk-pixbuf-config --cflags)

XLIBS = -L/usr/X11R6/lib -lgdk_pixbuf -lgdk_pixbuf_xlib -lX11
XLIBS := $(shell gdk-pixbuf-config --libs) -lgdk_pixbuf_xlib -lX11

GLIBS = -L/usr/X11R6/lib -lgdk_pixbuf -lgtk -lgdk -lX11
GLIBS := $(shell gdk-pixbuf-config --libs)

INSTALL = /usr/bin/install -D

Expand Down
14 changes: 12 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@ Ideas for improving pho (in no particular order).
If you have more ideas, or want to contribute to the project,
let me know!

Should be relatively easy:

- Go back to the first image (especially from the last-image dialog).

- In fullscreen mode, show image at full screen (no titlebar or frame).

Slightly harder:
- Save notes to EXIF, display current exif.

- Save images at the proper rotation.
(Should preserve EXIF, though!)

- Prompt at end rather than exiting.
Difficult:

- Left mouse button pans image on screen (if image is larger than screen).

- Save notes to EXIF, display current exif.

181 changes: 125 additions & 56 deletions dialogs.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <stdio.h>
#include <string.h>

#include "pho.h"

static GtkWidget* InfoDialog = 0;
static GtkWidget* InfoDEntry = 0;
static GtkWidget* InfoDImgName = 0;
static GtkWidget* InfoDImgSize = 0;
static GtkWidget* InfoDOrigSize = 0;
static GtkWidget* InfoDImgRotation = 0;
static GtkWidget* InfoFlag[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

Expand Down Expand Up @@ -53,7 +55,9 @@ void UpdateInfoDialog()
gtk_entry_set_text(GTK_ENTRY(InfoDEntry), s ? s : "");

gtk_label_set_text(GTK_LABEL(InfoDImgName), ArgV[ArgP]);
sprintf(buffer, "Size: %d x %d", XSize, YSize);
sprintf(buffer, "Actual Size: %d x %d", realXSize, realYSize);
gtk_label_set_text(GTK_LABEL(InfoDOrigSize), buffer);
sprintf(buffer, "Displayed Size: %d x %d", XSize, YSize);
gtk_label_set_text(GTK_LABEL(InfoDImgSize), buffer);
switch (GetRotation(ArgP))
{
Expand Down Expand Up @@ -135,8 +139,12 @@ void ToggleInfo()
InfoDImgSize = gtk_label_new("imgSize");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(InfoDialog)->vbox),
InfoDImgSize, TRUE, TRUE, 0);
InfoDOrigSize = gtk_label_new("origSize");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(InfoDialog)->vbox),
InfoDOrigSize, TRUE, TRUE, 0);
gtk_widget_show(InfoDImgName);
gtk_widget_show(InfoDImgSize);
gtk_widget_show(InfoDOrigSize);

box = gtk_hbox_new(FALSE, 0);
label = gtk_label_new("Rotation:");
Expand Down Expand Up @@ -178,79 +186,140 @@ void ToggleInfo()
gtk_widget_show(InfoDialog);
}

static GtkWidget* deleteDialog = 0;
/*
* A generic Prompt dialog.
*/

static GtkWidget* promptDialog = 0;
static int qYesNo = -1;

static char* defaultYesChars = "yY\n";
static char* defaultNoChars = "nN"; /* ESC always works to cancel */
static char* gYesChars = 0;
static char* gNoChars = 0;

static void
deleteCB(GtkWidget *widget, gpointer data)
promptCB(GtkWidget *widget, gpointer data)
{
if (data)
ReallyDelete();

gtk_widget_hide(deleteDialog);
qYesNo = (int)data;
}

static gint
HandleDeleteKeyPress(GtkWidget* widget, GdkEventKey* event)
HandlePromptKeyPress(GtkWidget* widget, GdkEventKey* event)
{
switch (event->keyval)
char c;

if (event->keyval == GDK_Escape)
{
case GDK_d:
case GDK_Return:
case GDK_KP_Enter:
deleteCB(widget, (gpointer)1);
return TRUE;
case GDK_Escape:
case GDK_q:
case GDK_n:
deleteCB(widget, (gpointer)0);
return TRUE;
default:
return FALSE;
qYesNo = 0;
return TRUE;
}

/* For anything else, map it to a printable and search in the strings */
if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
c = '\n';

else if (event->keyval == GDK_space)
c = ' ';

else if (event->keyval >= GDK_A && event->keyval <= GDK_Z)
c = event->keyval - GDK_A + 'A';

else if (event->keyval >= GDK_a && event->keyval <= GDK_z)
c = event->keyval - GDK_a + 'a';

else if (event->keyval >= GDK_0 && event->keyval <= GDK_9)
c = event->keyval - GDK_0 + '0';

else {
qYesNo = -1;
gdk_beep();
return FALSE;
}

/* Now we have a c: see if it's in the yes or no char lists */
if (strchr(gYesChars, c))
{
qYesNo = 1;
return TRUE;
}
else if (strchr(gNoChars, c))
{
qYesNo = 0;
return TRUE;
}

qYesNo = -1;
return FALSE;
}

void ShowDeleteDialog()
int PromptDialog(char* msg, char* yesStr, char* noStr,
char* yesChars, char* noChars)
{
GtkWidget* deleteBtn;
GtkWidget* cancelBtn;
static GtkWidget* label = 0;
char buf[512];
static GtkWidget* question = 0;
static GtkWidget* yesBtn = 0;
static GtkWidget* noBtn = 0;

if (!yesStr)
yesStr = "Yes";
if (!noStr)
noStr = "Cancel";

sprintf(buf, "Okay to delete '%s'?", ArgV[ArgP]);
gYesChars = yesChars ? yesChars : defaultYesChars;
gNoChars = noChars ? noChars : defaultNoChars;

if (deleteDialog && label)
if (promptDialog && question && yesBtn && noBtn)
{
gtk_label_set_text(GTK_LABEL(label), buf);
gtk_widget_show(deleteDialog);
return;
gtk_label_set_text(GTK_LABEL(question), msg);
gtk_label_set_text(GTK_LABEL(GTK_BIN(yesBtn)->child), yesStr);
gtk_label_set_text(GTK_LABEL(GTK_BIN(noBtn)->child), noStr);
}
else
{
/* First time through: make the dialog */

promptDialog = gtk_dialog_new();

// This is stupid: to make the dialog modal we have to use
// new_with_buttons, but that doesn't let us get to to the buttons
// to change their labels later!
// Figure out how to add modality some other time.
//promptDialog = gtk_dialog_new_with_buttons("Prompt",

gtk_signal_connect(GTK_OBJECT(promptDialog), "key_press_event",
(GtkSignalFunc)HandlePromptKeyPress, 0);

// Make the buttons:
yesBtn = gtk_button_new_with_label(yesStr);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(promptDialog)->action_area),
yesBtn, TRUE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(yesBtn), "clicked",
(GtkSignalFunc)promptCB, (gpointer)1);

noBtn = gtk_button_new_with_label(noStr);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(promptDialog)->action_area),
noBtn, TRUE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(noBtn), "clicked",
(GtkSignalFunc)promptCB, (gpointer)0);
gtk_widget_show(yesBtn);
gtk_widget_show(noBtn);

// Make the label:
question = gtk_label_new(msg);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(promptDialog)->vbox),
question, TRUE, TRUE, 15);
gtk_widget_show(question);
}

deleteDialog = gtk_dialog_new();
gtk_signal_connect(GTK_OBJECT(deleteDialog), "key_press_event",
(GtkSignalFunc)HandleDeleteKeyPress, 0);

// Make the buttons:
deleteBtn = gtk_button_new_with_label("Delete");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(deleteDialog)->action_area),
deleteBtn, TRUE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(deleteBtn), "clicked",
(GtkSignalFunc)deleteCB, (gpointer)1);

cancelBtn = gtk_button_new_with_label("Cancel");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(deleteDialog)->action_area),
cancelBtn, TRUE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(cancelBtn), "clicked",
(GtkSignalFunc)deleteCB, (gpointer)0);
gtk_widget_show(deleteBtn);
gtk_widget_show(cancelBtn);

// Make the label:
label = gtk_label_new(buf);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(deleteDialog)->vbox),
label, TRUE, TRUE, 0);
gtk_widget_show(label);
gtk_widget_show(promptDialog);

qYesNo = -1;
while (qYesNo < 0)
gtk_main_iteration();

gtk_widget_show(deleteDialog);
gtk_widget_hide(promptDialog);
return qYesNo;
}



67 changes: 52 additions & 15 deletions gmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,76 @@ extern void UpdateInfoDialog();
static GtkWidget *win = 0;
static GtkWidget *drawingArea = 0;

void InitWin();
static int gFullScreenMode = 0;

/* ShowImage assumes image already contains the right GdkPixbuf.
/* ShowImage assumes gImage already contains the right GdkPixbuf.
*/
void ShowImage()
{
char title[160];

if (drawingArea->window == 0)
return;
if (image == 0)
if (gImage == 0)
return;

XSize = gdk_pixbuf_get_width(image);
YSize = gdk_pixbuf_get_height(image);
// If we're coming back to normal from fullscreen mode,
// we need to restore sizes.
if (!gFullScreenMode && (XSize > realXSize || YSize > realYSize))
{
GdkPixbuf* newimage;
XSize = realXSize;
YSize = realYSize;
newimage = gdk_pixbuf_scale_simple(gImage, XSize, YSize,
GDK_INTERP_NEAREST);
if (gImage)
gdk_pixbuf_unref(gImage);
gImage = newimage;
resized = 0;
}

// Now scale it if needed.
if (XSize > MonitorWidth || YSize > MonitorHeight)
// Scale it down if needed.
else if (XSize > MonitorWidth || YSize > MonitorHeight
|| (gFullScreenMode
&& XSize < MonitorWidth && YSize < MonitorWidth))
{
GdkPixbuf* newimage;
double xratio = (double)XSize / MonitorWidth;
double yratio = (double)YSize / MonitorHeight;
double ratio = (xratio > yratio ? xratio : yratio);
GdkPixbuf* newimage;

XSize = (double)XSize / ratio;
YSize = (double)YSize / ratio;

newimage = gdk_pixbuf_scale_simple(image, XSize, YSize,
newimage = gdk_pixbuf_scale_simple(gImage, XSize, YSize,
GDK_INTERP_NEAREST);
gdk_pixbuf_unref(image);
image = newimage;
if (gImage)
gdk_pixbuf_unref(gImage);
gImage = newimage;
resized = 1;
}

gdk_window_resize(win->window, XSize, YSize);

gdk_pixbuf_render_to_drawable(image, drawingArea->window,
gdk_pixbuf_render_to_drawable(gImage, drawingArea->window,
drawingArea->style->fg_gc[GTK_WIDGET_STATE(drawingArea)],
0, 0, 0, 0, XSize, YSize,
GDK_RGB_DITHER_NONE, 0, 0);

// Update the titlebar
sprintf(title, "pho%s: %s",
gFullScreenMode ? " (fullscreen)" : "", ArgV[ArgP]);
gtk_window_set_title(GTK_WINDOW(win), title);

UpdateInfoDialog();
}

static void ToggleFullScreenMode()
{
gFullScreenMode = !gFullScreenMode;
ShowImage();
}

static gint HandleDelete(GtkWidget* widget, GdkEventKey* event, gpointer data)
{
/* If you return FALSE in the "delete_event" signal handler,
Expand Down Expand Up @@ -116,15 +144,22 @@ static gint HandleKeyPress(GtkWidget* widget, GdkEventKey* event)
DeleteImage();
break;
case GDK_space:
if (NextImage() != 0)
EndSession();
ShowImage();
if (NextImage() != 0) {
if (PromptDialog("Quit pho?", "Quit", "Continue",
"qx \n", "c ") != 0)
EndSession();
}
else
ShowImage();
return TRUE;
case GDK_BackSpace:
case GDK_minus:
if (PrevImage() == 0)
ShowImage();
return TRUE;
case GDK_f:
ToggleFullScreenMode();
break;
case GDK_0:
case GDK_1:
case GDK_2:
Expand All @@ -145,6 +180,8 @@ static gint HandleKeyPress(GtkWidget* widget, GdkEventKey* event)
return TRUE;
case GDK_T: // make life easier for xv users
case GDK_R:
case GDK_l:
case GDK_L:
case GDK_Left:
case GDK_KP_Left:
RotateImage(-90);
Expand Down
Loading

0 comments on commit 0b5457a

Please sign in to comment.