############################################################################ # # File: navitrix.icn # # Subject: Procedures to perform file navigation # # Author: Ralph E. Griswold # # Date: July 10, 2002 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This package provides an interface for file navigation. It is # intended for use with another application with a visual interface. # ############################################################################ # # The code is based on Unix but may work in other Unix-like environments. # # Directories are shown with a trailing slash. Clicking on a directory # moves there. Clicking on a file name selects it. The text of the # button used to dismiss the navigator is put in the global variable # nav_state, while the name of the selected file is put in the global # variable nav_file. # # nav_keyboard() processes keyboard shortcuts. A return character is # equivalent to clicking on the Okay button. Other characters cause # the top list entry to be positioned at a name that starts with or is # close to the character. # # The other application needs only to know this: # # The navigator is initialized by calling nav_init(). This opens a # hidden window, assigned to the global variable nav_window, for # the navigator. It also assigns the navigator root vidget to the # global variable nav_root. # # To use the navigator, the other application needs to change the # canvas status nav_window to normal so it can accept user events # and hide it again when it has been "dismissed". The navigator # puts the selected file in nav_file as mentioned above. # # If the application wants to support the navigator's keyboard # shortcuts, it needs to set the shortcut procedure to nav_keyboard # when the navigator window is active. # # A typical event loop for using the navigator is: # # repeat { # event loop # case Active() of { # &window : { # application window # root_cur := root # shortcuts_cur := shortcuts # } # nav_window : { # navigation window # root_cur := nav_root # shortcuts_cur := nav_keyboard # } # } # ProcessEvent(root_cur, , shortcuts_cur) # case nav_state of { # &null : next # "Okay" : load_pattern() # } # nav_state := &null # WAttrib(nav_window, "canvas=hidden") # } # # where process_file() is a procedure that does something with the # file. # # Note that the value of nav_state determines what needs to be done. It is # null when the navigator has not been used since the last event. If # the navigator is dismissed with "Cancel" instead of "Okay", nothing # needs to be done except hide the navigator window and set the nav_state # to null. # # Coupled with this is a procedure (or more than one) that makes the # navigator window visible, as in # # procedure open_cb() # WAttrib(nav_window, "canvas=normal") # ... # return # end # # If there is more than one use of the navigator, the callbacks that # enable it can set process_file to the appropriate companion procedure. # ############################################################################ # # Requires: Version 9 graphics, UNIX # ############################################################################ # # Links: vsetup # ############################################################################ link vsetup $include "keysyms.icn" global directory global dir global file_list global files # Globals used to communicate with the application that uses the navigator global nav_file global nav_root global nav_state global nav_vidgets global nav_window procedure nav_init() local window_save, atts window_save := &window # save current subject window &window := &null # clear for new subject atts := navig_atts() put(atts, "canvas=hidden") (WOpen ! atts) | stop("*** can't open navigation window") nav_vidgets := navig() # initialize interface nav_window := &window # name navigation window &window := window_save # restore previous subject window files := nav_vidgets["files"] nav_root := nav_vidgets["root"] nav_file := &null nav_refresh() return end procedure nav_files_cb(vidget, value) static last_file, last_time initial { last_file := "" last_time := 0 } if /value then { last_time := 0 return } if value ?:= tab(upto('/')) then { chdir(value) nav_refresh() return } nav_file := value if (value == last_file) then { last_file := "" nav_state := "Okay" return } last_time := 0 last_file := value return end procedure nav_refresh() local ls, input static x, y initial { x := nav_vidgets["placeholder"].ax y := nav_vidgets["placeholder"].ay directory := "" } input := open("pwd", "p") WAttrib( nav_window, "drawop=reverse") DrawString(nav_window, x, y, directory) DrawString(nav_window, x, y, directory := !input) WAttrib(nav_window, "drawop=copy") close(input) file_list := [] ls := open("ls -a -p .", "p") every put(file_list, !ls) VSetItems(files, file_list) close(ls) return end procedure nav_okay_cb() if /nav_file then { Notice("No file selected.") fail } nav_state := "Okay" return end procedure nav_keyboard(e) case e of { "\r" : nav_okay_cb() Key_Home : VSetState(files, 1) Key_End : VSetState(files, *file_list) default : if type(e) == "string" then nav_locate(e) } return end procedure nav_locate(e) local i static pos initial pos := list(1) every i := 1 to *file_list do { if file_list[i] >>= e then break } pos[1] := i VSetState(files, pos) return end procedure nav_cancel_cb() nav_state := "Cancel" return end #===<>=== modify using vib; do not remove this marker line procedure navig_atts() return ["size=294,412", "bg=pale gray", "label=Navitrix"] end procedure navig(win, cbk) return vsetup(win, cbk, ["navig:Sizer:::0,0,294,412:Navitrix",], ["cancel:Button:regular::86,378,49,20:Cancel",nav_cancel_cb], ["files:List:w::13,50,273,314:",nav_files_cb], ["okay:Button:regular::21,378,49,20:Okay",nav_okay_cb], ["placeholder:Button:regularno::20,22,65,17: ",], ["refresh:Button:regular::224,378,56,20:Refresh",nav_refresh], ["border:Rect:grooved::18,374,55,28:",nav_okay_cb], ) end #===<>=== end of section maintained by vib