%% %% %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% %% -module(toolbar_toolconfig). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Erlang Toolbar % %%% Description %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Tool configuration tool, edit and creates .tool files % This tool works separately from the toolbar. % %%% External data types %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % toolinfo() -- Tool configuration information -include("toolbar.hrl"). % %%% Internal data types %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % tfwindow() -- Toolfile configuration window -record(tfwindow, {window, fileentry, toolentry,moduleentry,functionentry, iconentry,messageentry,htmlentry, label}). % %%% Exports %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -export([start/0]). % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([init/0]). % spawn %%% Exported functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %---------------------------------------- % start() => pid() %---------------------------------------- start() -> spawn(toolbar_toolconfig,init,[]). %%% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %============================================================================= % Main loop %============================================================================= %---------------------------------------- % init() %---------------------------------------- init() -> %% Start GS (or get the pid if it is already running) S = gs:start(), %% Draw the window Window = draw_window(S), loop(S,Window). %---------------------------------------- % loop(S,Window) % S - pid() GS % Window - tfwindow() %---------------------------------------- loop(S,Window) -> receive %% 'Return' pressed in the 'File' entry {gs,_Obj,keypress,file,['Return'|_]} -> %% Check if a file name is specified case string:strip(gs:read(Window#tfwindow.fileentry,text)) of %% No file name specified, move focus to next entry "" -> move_focus(Window,file); %% A name is specified String -> %% Add a .tool suffix to the file name if necessary FileName = tool_file(String), %% Write the complete file name to the file entry gs:config(Window#tfwindow.fileentry,{text,FileName}), %% Try to open the file case file:consult(FileName) of %% File exists and seems ok {ok,[{version,Vsn},T]} -> %% Check the syntax of the file contents %% (All mandatory information specified, %% correct types, etc) case toolbar_lib:tool_info_syntax(Vsn,T) of %% Ok -- Show the file contents in the window %% and move focus to the next entry {ok,Info} -> display(Window,"File: "++FileName++ " opened"), clear_info(Window), show_info(Window,Info), move_focus(Window,file); %% Erronous version number -- Notify user {error,version} -> Win = Window#tfwindow.window, tool_utils:notify(Win,[FileName, "File has wrong version number"]); %% Other error -- Notify user _Error -> Win = Window#tfwindow.window, tool_utils:notify(Win,[FileName, "File is on erronous format"]) end; %% The file can not be read, show default values %% according to the file name in the window and %% move focus to the next entry _ -> display(Window,"File: "++FileName ++ " could not be read, new file"), Tool = filename:basename(FileName,".tool"), clear_info(Window), show_info(Window,[{tool,Tool}, {start,{list_to_atom(Tool), start,[]}}, {icon,Tool++".gif"}, {html,Tool++".html"}]), move_focus(Window,file) end end, loop(S,Window); %% 'Return' pressed in another entry, move focus to next entry {gs,_Obj,keypress,Focus,['Return'|_]} -> move_focus(Window,Focus), loop(S,Window); %% Any oher keypress, clear the display {gs,_Obj,keypress,_Data,_Args} -> display_clear(Window), loop(S,Window); %% 'Clear' button pressed, clear the window {gs,_Obj,click,_Data,["Clear"|_]} -> clear_info(Window), loop(S,Window); %% 'Save' button pressed, save the given information to file {gs,_Obj,click,_Data,["Save"|_]} -> %% Check if a file name is specified case string:strip(gs:read(Window#tfwindow.fileentry,text)) of %% No file name specified, notify user "" -> Win = Window#tfwindow.window, tool_utils:notify(Win, "A file name must be specified"); %% A name is specified String -> %% Add a .tool suffix to the file name if necessary FileName = tool_file(String), %% Write the complete file name to the file entry gs:config(Window#tfwindow.fileentry,{text,FileName}), %% Check the other information given case check_info(Window) of %% If given info is correct, try to save %% it to the file {ok,ToolInfo} -> Win = Window#tfwindow.window, case save_info(Win,FileName,ToolInfo) of %% Ok, display confirmation ok -> display(Window, "Tool information saved to "++ FileName); %% Cancel, do nothing cancel -> ignore; %% Error, display error message {error,Reason} -> display(Window, toolbar_lib:error_string(Reason)++ FileName) end; %% Given info incorrect, notify user {error,Reason} -> Win = Window#tfwindow.window, Str = toolbar_lib:error_string(Reason), tool_utils:notify(Win,Str) end end, loop(S,Window); %% 'Stop' button, close window and exit {gs,_Obj,click,_Data,["Stop"|_]} -> gs:destroy(Window#tfwindow.window), finished; %% Window closed, exit {gs,_Obj,destroy,_Data,_Args} -> finished; Other -> io:format("toolbar_toolconfig: unexp msg: ~p~n",[Other]), loop(S,Window) end. %============================================================================= % Graphics %============================================================================= %---------------------------------------- % draw_window(S) % S - pid() GS % Draw the main window. %---------------------------------------- draw_window(S) -> %% ----- Open a new window ----- Win = gs:create(window,S,[{width,400},{height,390}, {title,"Create Tool File"}]), %% ----- Top frame containing a 'File name' label and entry ----- Top = gs:create(frame,Win,[{x,0},{y,0},{width,400},{height,60},{bw,2}, {keypress,true}]), %% File name gs:create(label,Top,[{x,10},{y,10},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"File name:"}}]), File = gs:create(entry,Top,[{x,110},{y,10},{width,280},{height,30}, {keypress,true},{data,file}]), %% ----- Middle frame containing other labels and entries ----- Mid = gs:create(frame,Win,[{x,0},{y,60},{width,400},{height,250},{bw,2}, {keypress,true}]), %% Tool name gs:create(label,Mid,[{x,10},{y,10},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"Tool name:"}}]), Tool = gs:create(entry,Mid,[{x,110},{y,10},{width,280},{height,30}, {keypress,true},{data,tool}]), %% Start function gs:create(label,Mid,[{x,10},{y,60},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"Start:"}}]), Mod = gs:create(entry,Mid,[{x,110},{y,60},{width,135},{height,30}, {keypress,true},{data,module}]), Fun = gs:create(entry,Mid,[{x,245},{y,60},{width,135},{height,30}, {keypress,true},{data,function}]), %% Icon file gs:create(label,Mid,[{x,10},{y,110},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"Icon file:"}}]), Icon = gs:create(entry,Mid,[{x,110},{y,110},{width,280},{height,30}, {keypress,true},{data,icon}]), %% Message gs:create(label,Mid,[{x,10},{y,160},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"Message:"}}]), Msg = gs:create(entry,Mid,[{x,110},{y,160},{width,280},{height,30}, {keypress,true},{data,message}]), %% HTML file gs:create(label,Mid,[{x,10},{y,210},{width,80},{height,30},{align,e}, {keypress,true}, {label,{text,"HTML:"}}]), Html = gs:create(entry,Mid,[{x,110},{y,210},{width,280},{height,30}, {keypress,true},{data,html}]), %% ----- Bottom frame containing the buttons ----- Bot = gs:create(frame,Win,[{x,0},{y,310},{width,400},{height,50}, {bw,2},{keypress,true}]), gs:create(button,Bot,[{x,75},{y,10},{width,50},{height,30}, {keypress,true}, {label,{text,"Clear"}}]), gs:create(button,Bot,[{x,175},{y,10},{width,50},{height,30}, {keypress,true}, {label,{text,"Save"}}]), gs:create(button,Bot,[{x,275},{y,10},{width,50},{height,30}, {keypress,true}, {label,{text,"Stop"}}]), %% ----- Label for displaying help messages ----- Lbl = gs:create(label,Win,[{x,0},{y,360},{width,400},{height,30},{bw,2}, {relief,raised}, {keypress,true}, {align,c},{label,{text,""}}]), gs:config(Win,{map,true}), gs:config(File,{setfocus,true}), #tfwindow{window=Win, fileentry=File, toolentry=Tool, moduleentry=Mod, functionentry=Fun, iconentry=Icon, messageentry=Msg, htmlentry=Html, label=Lbl}. %---------------------------------------- % move_focus(Window,Focus) % Window - tfwindow() % Focus - file | tool | module | function | icon | message | html | none % Move the input focus to the entry following Focus %---------------------------------------- move_focus(Window,file) -> gs:config(Window#tfwindow.toolentry,{setfocus,true}); move_focus(Window,tool) -> gs:config(Window#tfwindow.moduleentry,{setfocus,true}); move_focus(Window,module) -> gs:config(Window#tfwindow.functionentry,{setfocus,true}); move_focus(Window,function) -> gs:config(Window#tfwindow.iconentry,{setfocus,true}); move_focus(Window,icon) -> gs:config(Window#tfwindow.messageentry,{setfocus,true}); move_focus(Window,message) -> gs:config(Window#tfwindow.htmlentry,{setfocus,true}); move_focus(Window,html) -> gs:config(Window#tfwindow.htmlentry,{setfocus,false}); move_focus(_Window,none) -> true. %---------------------------------------- % display(Window,Text) % Window - tfwindow() % Text - string() % Display a help message in the window %---------------------------------------- display(Window,Text) -> gs:config(Window#tfwindow.label,{label,{text,Text}}). %---------------------------------------- % display_clear(Window) % Window - tfwindow() % Clear the help message display %---------------------------------------- display_clear(Window) -> display(Window,""). %---------------------------------------- % clear_info(Window) % Window - tfwindow() % Clear the entries of Window (except the file entry) %---------------------------------------- clear_info(Window) -> gs:config(Window#tfwindow.toolentry,{text,""}), gs:config(Window#tfwindow.moduleentry,{text,""}), gs:config(Window#tfwindow.functionentry,{text,""}), gs:config(Window#tfwindow.iconentry,{text,""}), gs:config(Window#tfwindow.messageentry,{text,""}), gs:config(Window#tfwindow.htmlentry,{text,""}). %---------------------------------------- % show_info(Window,List) % Window - tfwindow() % List - [{Key,Val}] % Key - tool, Val - string() % Key - start, Val - {atom(),atom(),_} % Key - icon, Val - string() % Key - message, Val - string() % Key - html, Val - string() % Display the different Val's in the appropriate entries of Window %---------------------------------------- show_info(_Window,[]) -> ok; show_info(Window,[{tool,Tool}|Rest]) -> gs:config(Window#tfwindow.toolentry,{text,Tool}), show_info(Window,Rest); show_info(Window,[{start,{M,F,_}}|Rest]) -> gs:config(Window#tfwindow.moduleentry,{text,M}), gs:config(Window#tfwindow.functionentry,{text,F}), show_info(Window,Rest); show_info(Window,[{icon,Icon}|Rest]) -> gs:config(Window#tfwindow.iconentry,{text,Icon}), show_info(Window,Rest); show_info(Window,[{message,Message}|Rest]) -> gs:config(Window#tfwindow.messageentry,{text,Message}), show_info(Window,Rest); show_info(Window,[{html,Html}|Rest]) -> gs:config(Window#tfwindow.htmlentry,{text,Html}), show_info(Window,Rest). %============================================================================= % Retrieve user specified information %============================================================================= %---------------------------------------- % check_info(Window) => {ok,ToolInfo} | {error,Reason} % Window - tfwindow() % ToolInfo - toolinfo() % Reason - noname | nostart % Check the information given in the entries and insert it into ToolInfo % if all mandatory information is given. %---------------------------------------- check_info(Window) -> %% First check mandatory elements: name and start function Tool = gs:read(Window#tfwindow.toolentry,text), M = gs:read(Window#tfwindow.moduleentry,text), F = gs:read(Window#tfwindow.functionentry,text), if Tool/="",M/="",F/="" -> ToolInfo = #toolinfo{tool=Tool, start={list_to_atom(M),list_to_atom(F),[]}, icon=gs:read(Window#tfwindow.iconentry,text), message=gs:read(Window#tfwindow.messageentry,text), html=gs:read(Window#tfwindow.htmlentry,text)}, {ok,ToolInfo}; Tool=="" -> {error,noname}; true -> {error,nostart} end. %============================================================================= % Save information to file %============================================================================= %---------------------------------------- % save_info(Win,File,ToolInfo) => ok | cancel | {error,waccess} % Win - GS object % File - string() % ToolInfo - toolinfo() % Saves the information in ToolInfo to File on a predefined format. %---------------------------------------- save_info(Win,File,ToolInfo) -> %% First check if file already exists case file:read_file_info(File) of {ok,_FileInfo} -> %% Request the user to confirm that the file should %% be overwritten case tool_utils:confirm(Win,[File, "exists, will be overwritten"]) of ok -> save_info2(File,ToolInfo); cancel -> cancel end; {error,_Reason} -> % _Reason = "No such file or directory" save_info2(File,ToolInfo) end. %---------------------------------------- % save_info2(File,ToolInfo) => ok | {error,waccess} % File - string() File name % ToolInfo - toolinfo record % Called by save_info/3 %---------------------------------------- save_info2(File,ToolInfo) -> case file:open(File, [write]) of {ok,Fd} -> io:format(Fd,"{version,\"~s\"}.~n",[toolbar:version()]), io:format(Fd,"{{tool,\"~s\"},~n",[ToolInfo#toolinfo.tool]), io:format(Fd," {start,~w}",[ToolInfo#toolinfo.start]), case ToolInfo#toolinfo.icon of "" -> ignore; Icon -> io:format(Fd,",~n {icon,\"~s\"}",[Icon]) end, case ToolInfo#toolinfo.message of "" -> ignore; Message -> io:format(Fd,",~n {message,\"~s\"}",[Message]) end, case ToolInfo#toolinfo.html of "" -> ignore; Html -> io:format(Fd,",~n {html,\"~s\"}",[Html]) end, io:format(Fd,"}.~n",[]), file:close(Fd), ok; _Error -> {error,waccess} end. %============================================================================= % Auxiliary functions %============================================================================= %---------------------------------------- % tool_file(File) => string() % File - string() % Return a file name consisting of File with the suffix .tool added, % if File does not already have this suffix. %---------------------------------------- tool_file(File) -> case filename:extension(File) of ".tool" -> File; _ -> File ++ ".tool" end.