eumandy/eugtk/examples/test23.ex
2016-11-25 00:33:18 -07:00

268 lines
8.6 KiB
Elixir

------------------------------------------------------------------------
--# A simple, but fairly complete, image viewer.
-- Demonstrates Menus, FileChooser, FileFilters, Previews, etc.
-- Resizes images to fit the current window, shows statistics for
-- selected image, with variable preview sizes available.
-- There's quite a bit of functionality here for only around 250
-- lines of code!
------------------------------------------------------------------------
include GtkEngine.e
include GtkEvents.e
include std/filesys.e
include std/datetime.e
atom preview_max = 150 -- default size
object fn = 0 -- current filename
sequence name, path
constant win = create(GtkWindow,
"name=Main,title=`Simple Image Viewer`,size=500x400,position=1," &
"$configure-event=ResizeWindow,$destroy=Quit")
constant group = create(GtkAccelGroup) -- for CTL-O, CTL-C, CTL-Q menu options
set(win,"add accel group",group)
constant panel = create(GtkBox,"name=box,orientation=VERTICAL")
gtk:add(win,panel)
constant menubar = create(GtkMenuBar)
pack(panel,menubar)
constant menu1 = create(GtkMenuItem,"_File"),
filemenu = create(GtkMenu),
fileopen = create(GtkMenuItem,"gtk-open",_("FileOpen"),0,{group,"<Ctl>o"}),
fileclose = create(GtkMenuItem,"gtk-close",_("FileClose"),0,{group,"<Ctl>c"}),
sep1 = create(GtkSeparatorMenuItem),
fileexit = create(GtkMenuItem,"gtk-quit","Quit",0,{group,"<Ctl>q"})
set(fileclose,"sensitive",FALSE)
gtk:add(filemenu,{fileopen,fileclose,sep1,fileexit})
set(menu1,"submenu",filemenu)
gtk:add(menubar,menu1)
constant menu2 = create(GtkMenuItem,"_Help"),
helpmenu = create(GtkMenu),
helpabout = create(GtkMenuItem,"gtk-about#About",_("ShowAbout"),0,{group,"F1"}),
helpinfo = create(GtkMenuItem,"gtk-info#Photo _Info",_("PixInfo"),0,{group,"F2"})
set(helpabout,"add accelerator",{group,"<ctl>a"})
set(helpinfo,"add accelerator",{group,"<ctl>i"})
set(helpinfo,"sensitive",FALSE)
set(helpabout,"tooltip text","About this program...")
set(helpinfo,"tooltip text","About current photo")
gtk:add(helpmenu,{helpabout,helpinfo})
set(menu2,"submenu",helpmenu)
gtk:add(menubar,menu2)
constant scrolwin = create(GtkScrolledWindow)
pack(panel,scrolwin,1,1)
constant scroller = create(GtkViewport)
gtk:add(scrolwin,scroller)
constant img = create(GtkImage)
gtk:add(scroller,img)
set(scroller,"border width",10)
-----------------------------------------------------------------
-- filters determine which types of files will be shown in the
-- file chooser dialog. No filter = show all files.
-----------------------------------------------------------------
constant imagetypes = {"gif","jpg","png","ico"}
constant filter1 = create(GtkFileFilter,{{"name","All Images"}})
ifdef UNIX then
set(filter1,"add mime type","image/*")
elsedef -- windows doesn't know mime types?
for i = 1 to length(imagetypes) do
set(filter1,"add pattern",sprintf("*.%s",{imagetypes[i]}))
end for
end ifdef
constant
filter2 = create(GtkFileFilter,"name=`JPEG images`,add_pattern=*.jpg"),
filter3 = create(GtkFileFilter,"name=`GIF images`,add_pattern=*.gif"),
filter4 = create(GtkFileFilter,"name=`PNG images`,add_pattern=*.png"),
filter5 = create(GtkFileFilter,"name=`All files`,add_pattern=*")
constant dlg = create(GtkFileChooserDialog,{
{"title","Select an image"},
{"transient for",win},
{"action",GTK_FILE_CHOOSER_ACTION_OPEN},
{"local only",FALSE},
{"select multiple",FALSE}})
gtk:add(dlg,{filter1,filter2,filter3,filter4,filter5})
constant sizer = create(GtkScale,{
{"orientation",HORIZONTAL},
{"range",64,512},
{"increments",1},
{"value",preview_max},
{"draw value",FALSE},
{"tooltip text",sprintf("Preview width %d px",preview_max)},
{"connect","change-value",call_back(routine_id("ChangePreviewSize"))}})
constant action_area = get(dlg,"action area")
gtk:add(action_area,sizer) show(sizer)
set(dlg,"add button","gtk-cancel",MB_CANCEL)
set(dlg,"add button","gtk-ok",MB_APPLY)
constant preview = create(GtkImage)
set(dlg,"preview widget",preview)
-- call UpdatePreview whenever selection, filter, or folder changes.
connect(dlg,"update-preview",_("UpdatePreview"))
show_all(win)
-- try to find user's pictures folder via a call to a glib func:
ifdef WINDOWS then
path = canonical_path("~\\Pictures")
end ifdef
ifdef OSX then
-- FIXME OSX
end ifdef
ifdef LINUX then -- this function doesn't exist on Windows;
path = gtk_str_func("g_get_user_special_dir",{S},
{G_USER_DIRECTORY_PICTURES})
end ifdef
main()
------------------------------------------------------------------------
function FileOpen()
------------------------------------------------------------------------
object tmp
integer result
set(dlg,"current folder",path)
result = get(dlg,"run")
switch result do
case GTK_RESPONSE_APPLY then
tmp = get(dlg,"filename")
path = dirname(tmp)
-- note: important to check to see that an actual file is selected,
if not atom(tmp) then -- if atom, no file was selected
fn = locate_file(tmp)
if file_type(fn) = 1 then
set(win,"title",filename(fn))
set(fileclose,"sensitive",TRUE)
ResizeWindow()
end if
end if
case GTK_RESPONSE_CANCEL then
path = current_dir()
end switch
set(dlg,"hide")
set(helpinfo,"sensitive",TRUE)
return 1
end function
------------------------------------------------------------------------
function FileClose() -- remove image from view;
------------------------------------------------------------------------
fn = 0
set(img,"clear")
set(win,"title","Image Viewer")
set(fileopen,"sensitive",TRUE)
set(fileclose,"sensitive",FALSE)
set(helpinfo,"sensitive",FALSE)
return 1
end function
------------------------------------------------------------------------
global function UpdatePreview(atom ctl=0, atom event=0) -- as focus changes;
------------------------------------------------------------------------
object pix
atom ratio
object dimensions
object fn = get(dlg,"filename")
if string(fn) then -- avoid trying to preview a directory!
pix = create(GdkPixbuf,fn)
if pix > 0 then
dimensions = get(pix,"size")
ratio = preview_max / dimensions[1]
dimensions *= {ratio,ratio}
pix = set(pix,"scale simple",dimensions[1],dimensions[2],1)
set(preview,"from pixbuf",pix)
set(dlg,"preview widget active",TRUE)
end if
end if
return 0
end function
------------------------------------------------------------------------
global function ResizeWindow() -- tries to fit the image into the window!
------------------------------------------------------------------------
object pix
object ratio
sequence size
size = get(win,"size") - {30,50} -- allow for window border & header
pix = create(GdkPixbuf,fn,size[1],size[2],1)
set(img,"from pixbuf",pix)
return 0
end function
------------------------------------------------------------------------
function ChangePreviewSize(atom ctl)
------------------------------------------------------------------------
preview_max = to_integer(get(ctl,"value"))
set(sizer,"tooltip text",sprintf("Preview width %d px",preview_max))
UpdatePreview()
return 0
end function
------------------------------------------------------------------------
function ShowAbout()
------------------------------------------------------------------------
return Info(win," About ","Simple Image Viewer",
`Resize the main window,
the image is expanded to fit.`,,"emblem-photos")
end function
------------------------------------------------------------------------
function PixInfo()
------------------------------------------------------------------------
atom w = allocate(8), h = allocate(8)
-- obtain size of the current image;
integer flen = file_length(fn)
-- obtain time & date file saved;
object tstamp = file_timestamp(fn)
-- get more info by obtaining a a file_info structure from the filename;
object info = gtk_func("gdk_pixbuf_get_file_info",{P,I,I},{allocate_string(fn,1),w,h})
w = peek4u(w) h = peek4u(h)
-- get image format (jpg, gif, etc...) from the info structure;
object fmt = peek_string(peek4u(info))
-- create an icon for the Info box using the current image;
Pixbuf pix = create(GdkPixbuf,fn,90,0,1)
Info(win,"File Info", -- show as much info about the selected image as possible;
text:format("File: []\n",{filename(fn)}),
text:format("Folder: []\nFormat: []\nWidth: []px, Height: []px\nSize: [,,] bytes",
{path,fmt,w,h,flen}) &
datetime:format(tstamp,"\nDate: %a, %d %b %Y"),,pix,128)
return 1
end function