aboutsummaryrefslogtreecommitdiffstats
path: root/lib/gs/examples/file_dialog.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs/examples/file_dialog.erl')
-rw-r--r--lib/gs/examples/file_dialog.erl255
1 files changed, 255 insertions, 0 deletions
diff --git a/lib/gs/examples/file_dialog.erl b/lib/gs/examples/file_dialog.erl
new file mode 100644
index 0000000000..ff20321374
--- /dev/null
+++ b/lib/gs/examples/file_dialog.erl
@@ -0,0 +1,255 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% File Selection Dialog
+%% ------------------------------------------------------------
+
+-module(file_dialog).
+
+-export([start/0,start/1,start/2,fs_init/3]).
+
+-include_lib("kernel/include/file.hrl").
+
+
+%% ----- File Selection ----
+start() ->
+ {ok,Dir}=file:get_cwd(),
+ start(Dir,[]).
+
+start(Dir) ->
+ start(Dir,[]).
+
+start(Dir,File) ->
+ Dir0 = case lists:last(Dir) of
+ $/ -> Dir;
+ _ -> lists:append(Dir,"/")
+ end,
+ Pid=spawn(file_dialog,fs_init,[Dir0,File,self()]),
+ receive
+ {file_dialog,Pid,Result} -> Result
+ end.
+
+
+%% ------------------------------------------------------------
+fs_init(Dir,File,Owner) ->
+ S=gs:start(),
+ gs:create(window,win,S,[{width,250},{height,265},{title,"File Dialog"},
+ {configure,true}]),
+ gs:create(label,label,win,[{y,0},{width,250},{label, {text,Dir}}]),
+ gs:label(win,[{width,50},{y,30},{x,5},{label, {text,"File:"}}]),
+ gs:create(entry,entry,win,[{y,30},{width,190},{x,55},
+ {keypress,true},{focus,true}]),
+ gs:create(listbox,lb,win,[{x,5},{y,60},{width,160},{height,199},
+ {vscroll,right},{click,true},{doubleclick,true}]),
+ gs:create(button,ok,win,[{label, {text,"OK"}},{width,40},{x,185},{y,170}]),
+ gs:create(button,cancel,win,[{label, {text,"Cancel"}},{x,175},{y,220},{width,65}]),
+ Items=refresh(Dir),
+ %% --- select File if it's given ---
+ case index_member(File,Items) of
+ {ok,Index} ->
+ gs:config(lb,{selection,clear}),
+ gs:config(lb,{selection,Index});
+ _ -> true
+ end,
+ gs:config(win,{map,true}),
+ fs_loop(Dir,Owner).
+
+fs_loop(Dir,Owner) ->
+ receive
+ {gs,ok,click,_,_} ->
+ entered_name(Dir,Owner);
+ {gs,cancel,click,_,_} ->
+ Owner ! {file_dialog,self(),cancel};
+ {gs,entry,keypress,_,['Return'|_]} ->
+ entered_name(Dir,Owner);
+ {gs,entry,keypress,_,[_Keysym|_]} ->
+ fs_loop(Dir,Owner);
+ {gs,lb,click,_,_} ->
+ clicked(Dir,Owner);
+ {gs,lb,doubleclick,_,_} ->
+ double_clicked(Dir,Owner);
+ {gs,win,configure,_,[250,265|_]} -> % already got that size
+ fs_loop(Dir,Owner);
+ {gs,win,configure,_,_} ->
+ gs:config(win,[{geometry,{250,265}}]),
+ fs_loop(Dir,Owner);
+ stop ->
+ exit(normal);
+ {gs,_,destroy,_,_} ->
+ Owner ! {file_dialog,self(),cancel};
+ X ->
+ io:format("file_dialog: got other: ~w.~n",[X]),
+ fs_loop(Dir,Owner)
+ end.
+
+
+
+refresh(Dir) ->
+ gs:config(lb,clear),
+ gs:config(label,{label, {text,Dir}}),
+ gs:config(entry,{text,""}),
+ Items=["../"|get_files(Dir)],
+ gs:config(lb,[{items,Items}]),
+ Items.
+
+
+entered_name(Dir,Owner) ->
+ File=gs:read(entry,text),
+ case check_file(Dir,File) of
+ {file,Dir2,File2} ->
+ Owner ! {file_dialog,self(),{ok,Dir2,File2}};
+ {dir,Dir2} ->
+ refresh(Dir2),
+ fs_loop(Dir2,Owner);
+ {error,no_file} ->
+ double_clicked(Dir,Owner);
+ _ ->
+ fs_loop(Dir,Owner)
+ end.
+
+
+clicked(Dir,Owner) ->
+ [Idx|_]=gs:read(lb,selection),
+ File=gs:read(lb,{get,Idx}),
+ case lists:last(File) of
+ $/ -> %it's a dir
+ true;
+ _ -> % it's a file
+ gs:config(entry,{text,File})
+ end,
+ fs_loop(Dir,Owner).
+
+
+double_clicked(Dir,Owner) ->
+ case gs:read(lb,selection) of
+ [0] -> % up one dir
+ NewDir=up_one_dir(Dir),
+ refresh(NewDir),
+ fs_loop(NewDir,Owner);
+ [] ->
+ fs_loop(Dir,Owner);
+ [Idx] ->
+ File=gs:read(lb,{get,Idx}),
+ case lists:last(File) of
+ $/ -> % down a dir
+ NewDir=lists:append(Dir,File),
+ refresh(NewDir),
+ fs_loop(NewDir,Owner);
+ _ -> % done
+ Owner!{file_dialog,self(),{ok,Dir,File}}
+ end
+ end.
+
+
+%% checks if a file exists
+%% returns {file,Dir,File}
+%% {dir,Dir}
+%% or {error,What}
+check_file(Dir,File) ->
+ case catch lists:last(File) of
+ $/ -> % File is a Dir
+ NewDir = case File of
+ [$/|_] -> %absolute path
+ File;
+ _ -> %relative path
+ lists:append(Dir,File)
+ end,
+ case file:list_dir(NewDir) of
+ {ok,_} -> {dir,NewDir};
+ _ -> {error,bad_dir}
+ end;
+ {'EXIT',_Why} -> {error,no_file};
+ _ ->
+ Words=string:tokens(File,[$/,$\\]),
+ NewFile=lists:last(Words),
+ NewDir = case File of
+ [$/|_] -> %absolute path
+ up_one_dir(File);
+ _ -> %relative path
+ case up_one_dir(File) of
+ [$/] -> Dir;
+ [$/|SubDir] -> lists:flatten([Dir,SubDir,$/])
+ end
+ end,
+ case file:read_file_info(lists:append(NewDir,NewFile)) of
+ {ok,_} ->
+ {file,NewDir,NewFile};
+ _ ->
+ {error,bad_file}
+ end
+ end.
+
+
+get_files(Dir) ->
+ {ok,Files} = file:list_dir(Dir),
+ add_slash(Dir,lists:sort(Files)).
+
+add_slash(_,[]) -> [];
+add_slash(Dir,[H|T]) ->
+ case file:read_file_info(lists:append(Dir,[$/|H])) of
+ {ok,FI} when FI#file_info.type==directory ->
+ [lists:append(H,"/")|add_slash(Dir,T)];
+ _ ->
+ [H|add_slash(Dir,T)]
+ end.
+
+
+%filter([H|T]) ->
+% case lists:last(H) of
+% $/ -> [H|filter(T)];
+% _ ->
+% Len =length(H),
+% if Len>4 ->
+% case lists:nthtail(Len-4,H) of
+% ".erl" -> [H|filter(T)];
+% _ -> filter(T)
+% end;
+% true -> filter(T)
+% end
+% end;
+%filter([]) ->
+% [].
+
+
+%% like member but also returns index
+index_member(Item,List) ->
+ i_m(0,Item,List).
+
+i_m(N,Item,[Item|_List]) ->
+ {ok,N};
+i_m(N,Item,[_|List]) ->
+ i_m(N+1,Item,List);
+i_m(_N,_Item,[]) ->
+ false.
+
+up_one_dir(Dir) ->
+ L =string:tokens(Dir,[$/,$\\]),
+ lists:flatten(rem_last(L)).
+
+rem_last([_Last]) ->
+ [$/];
+rem_last([Head|Tail]) ->
+ [$/,Head|rem_last(Tail)];
+rem_last([]) ->
+ [$/].
+
+%% ----------------------------------------
+%% done