
-------------------------
namespace fileselector -- Generic file selection dialog;
-------------------------

--# EXPORTS:
/*
    -- functions:
	fileselector:New()
	fileselector:Open()
	fileselector:Save()
	fileselector:SaveAs()
	fileselector:CreateFolder()
	fileselector:SelectFolder()
	
   -- returns: 
	full file path if successful, e.g. "/home/irv/demos/test99.ex"
	or an atom:
	MB_ABORT when dialog is closed
	MB_CANCEL when cancel button is clicked.
*/

include GtkEngine.e

export constant version = "4.12.0"

if not equal(version,gtk:version) then
	Error(,,"GtkFileSelector version mismatch","should be version " & gtk:version)
end if


-- default settings, change before calling the dialog if required;
export boolean 
	create_folders = TRUE,
	local_only = TRUE,
	select_multiple = FALSE,
	show_hidden = FALSE,
	do_overwrite_confirmation = TRUE,
	show_preview = FALSE,
	preview_widget_active = TRUE

export sequence preview_size = {200,200}

export atom preview_max = 150  -- default size 

export object selected_filter=0, filters = {"euphoria","text"}	

-- may change filters before calling the dialog
-- (or every 5,000 miles, whichever comes first)	

-- IOW, to show only .css files, add the line:
-- 	fileselector:filters = {"css"}
-- before calling:
-- 	fileselector:Open("~/demos/*")

-- note that the syntax of the parameter to Open() is important:
-- ~/demos or ~/demos/ will only cause the dialog to highlight the ~/demos folder,
-- ~/demos/* will open the demos folder and display the [filtered] file types
-- ~/demos/*.css will show folders and all *.css files
  
-- combining filters with wildcards:  
--  fileselector:filters = {"images"}
--  fileselector:Open("~/demos/glade/*")
-- the above will show all images in the specified directory,

-- whereas:
--  fileselector:Open("~/demos/glade/*.png")
--  will show only .png images in the specified directory,
--  regardless of how the filters are set.

-- below, only .png images will be shown, but drop-down options to show .html and .c files
-- will be available also:
--  fileselector:filters = {"html","c"}
--  fileselector:Open("~/demos/glade/*.png")

--------------------------------------
function generate_filter(object name)
--------------------------------------
object filter = 0

	switch name do
	
	case "images",".jpg",".gif",".png",".xpm" then filter = create(GtkFileFilter,{
		{"name","Images"},{"add mime type","image/*"}})
		
	case "euphoria",".eu",".e",".exw" then filter = create(GtkFileFilter,{
		{"name","Euphoria files"},{"add pattern","*.e"},
		{"add pattern","*.ex"},{"add pattern","*.cfg"}})
	
	case "text",".text",".txt" then filter = create(GtkFileFilter,{
		{"name","All text"},{"add mime type","text/plain"}})
		
	case "c",".c",".h" then filter = create(GtkFileFilter,{
		{"name","C source code"},{"add mime type","text/x-c"},
		{"add pattern","*.c"},{"add pattern","*.h"}})
		
	case "c++" then filter = create(GtkFileFilter,{
		{"name","C++ source code"},{"add pattern","*.c++"}})
		
	case "css",".css" then filter = create(GtkFileFilter,{
		{"name","css markup"},{"add mime type","text/css"},
		{"add pattern","*.css"}})
		
	case "python",".python",".py" then filter = create(GtkFileFilter,{
		{"name","Python"},{"add mime type","text/x-python"}})
		
	case "html",".htm",".html" then filter = create(GtkFileFilter,{
		{"name","html source"},{"add mime type","text/html"},
		{"add pattern","*.html"}})
		
	case "ini",".ini" then filter = create(GtkFileFilter,{ 
		{"name","ini"},{"add pattern","*.ini"}})
		
	case "all" then filter = create(GtkFileFilter,{
		{"name","All files"},{"add pattern","*"}})
		
	case "dir" then filter = create(GtkFileFilter,{
		{"name","Directories"},{"add mime type","inode/directory"}}) 
		  
	end switch
	
return filter

end function
   
constant update_preview = call_back(routine_id("UpdatePreview"))

----------------------------------------------------------
export function New(object current=0)
----------------------------------------------------------
object result=0
atom dlg = create(GtkFileChooserDialog)

set(dlg,{
	{"name","FileNew"},
	{"title","Create a new file"},
	{"action",GTK_FILE_CHOOSER_ACTION_SAVE}, 
	{"preview widget active",preview_widget_active},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})
		
	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for
	
	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(current) and current > 0 then
		set(dlg,"current name",unpack(current))
	end if

	result = get(dlg,"run")
	if result = MB_OK then
		result = get(dlg,"filename")
	end if

destroy(dlg)

return result
end function
export constant new = call_back(routine_id("New"))

----------------------------------------------------
export function Open(object data=0, atom x=0)
----------------------------------------------------
object result=0
object filter=0

if atom(data) and data > 0 then data = unpack(data) end if
if string(data) and equal("*",filename(data)) then filters &= {"all"} end if

atom dlg = create(GtkFileChooserDialog)

set(dlg,{
	{"name","FileOpen"},
	{"title","Open a file"},
	{"action",GTK_FILE_CHOOSER_ACTION_OPEN},
	{"preview widget active",preview_widget_active},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})
		
	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for
		
	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(data) and data > 0 then
		data = unpack(data) 
	end if

	if string(data) then
		if file_exists(canonical_path(data)) then
			set(dlg,"filename",canonical_path(data))
		else
			if not equal("*",filename(data)) then
				filter = create(GtkFileFilter,{ -- build a custom filter;
				{"name",filename(data) & " files"},
				{"add pattern",filename(data)}})
				set(dlg,"add filter",filter)
				set(dlg,"filter",filter)
			end if
			set(dlg,"filename",canonical_path(data)) -- change to desired folder;
		end if
	end if
	
	result = get(dlg,"run") 
	
	if result = MB_OK then
		result = get(dlg,"filename") 
	end if
	
	destroy(dlg)

return result
end function
export constant open = call_back(routine_id("Open"))

----------------------------------------------------
export function Save(object data, object x=0)
----------------------------------------------------
object result=0
atom dlg = create(GtkFileChooserDialog)
atom f

set(dlg,{
	{"name","FileSave"},
	{"title","Save this file"},
	{"action",GTK_FILE_CHOOSER_ACTION_SAVE},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})
	
	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for

	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(data) and data > 0 then
		set(dlg,"current name",unpack(data))
	end if

	if string(data) then
		set(dlg,"current name",data)
	end if

	result = get(dlg,"run")

	if result = MB_OK then
		result = get(dlg,"filename")
	end if

destroy(dlg)

return result
end function
export constant save = call_back(routine_id("Save"))

-----------------------------------------------------------
export function SaveAs(object data=0, object x=0)
-----------------------------------------------------------
object result=0
atom dlg = create(GtkFileChooserDialog)

set(dlg,{
	{"name=FileSaveAs"},
	{"title","Save this file with a new name"},
	{"action",GTK_FILE_CHOOSER_ACTION_SAVE},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})
	
	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for
	
	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(data) and data > 0 then 
		set(dlg,"current name",unpack(data))
	elsif string(data) then
		set(dlg,"current name",data)
	end if

	result = get(dlg,"run")

	if result = MB_OK then
		result = get(dlg,"filename")
	end if

	destroy(dlg)

return result
end function
export constant save_as = call_back(routine_id("SaveAs"))

---------------------------------------------------------------
export function CreateFolder(object data=0, object x=0)
---------------------------------------------------------------
object result=0
atom dlg = create(GtkFileChooserDialog)

set(dlg,{
	{"name=NewFolder"},
	{"title","Create a new folder"},
	{"action",GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})
	
	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for
		
	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(data) and data > 0 then
		set(dlg,"current name",unpack(data))
	end if

	result = get(dlg,"run")

	if result = MB_OK then
		result = get(dlg,"filename")
	end if

destroy(dlg)

return result
end function
export constant create_folder = call_back(routine_id("CreateFolder"))

---------------------------------------------------------------
export function SelectFolder(object data=0, object x=0)
---------------------------------------------------------------
object result=0
atom dlg = create(GtkFileChooserDialog)

set(dlg,{
	{"name","SelectFolder"},
	{"title","Select a folder"},
	{"action",GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER},
	
	{"add button","gtk-cancel",MB_CANCEL},
	{"add button","gtk-ok",MB_OK},
	{"create folders",create_folders},
	{"local only",local_only},
	{"select multiple",select_multiple},
	{"show hidden",show_hidden},
	{"do overwrite confirmation",do_overwrite_confirmation}})

	for i = 1 to length(filters) do
		set(dlg,"add filter",generate_filter(filters[i]))
	end for
	
	if show_preview = TRUE then
		atom preview = create(GtkImage)
		set(dlg,"preview widget",preview)
		connect(dlg,"update-preview",update_preview,preview) 
	end if

	if atom(data) and data > 0 then
		data = unpack(data)
		if string(data) then
			if file_exists(canonical_path(data)) then
				set(dlg,"filename",canonical_path(data))
			else
				set(dlg,"filename",data)
			end if
		end if
	end if

result = get(dlg,"run")

if result = MB_OK then
	result = get(dlg,"filename")
end if

destroy(dlg)

return result
end function
export constant select_folder = call_back(routine_id("SelectFolder"))

------------------------------------------------------------------------------
function UpdatePreview(atom dlg, atom preview) -- local: follow 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 = get(pix,"scale simple",dimensions[1],dimensions[2],1)
		set(preview,"from pixbuf",pix)
	end if
end if

return 0
end function

