<* PRAGMA LL *>A
FileBrowserVBT
displays the files in a directory, and allows
the user to traverse the file system and to select one or more
files. There are two additional widgets that can be associated
with a FileBrowserVBT
. A {\em helper}
\index{FBHelper}\label{FBHelper} is a type-in field that displays
the pathname of the directory and allows the user to type new
pathnames. A {\em directory-menu}\index{FBDirMenu}
\label{FBDirMenu} is a menu containing the names of each level in
the directory tree, with the root at the bottom; you can go to any
level in the tree by selecting the appropriate item in the menu.
There are two user-actions, selecting and activating.
\begin{itemize}
\item The user may {\it select} items, either by single-clicking on
an item to select just that one, or by single-clicking and dragging
to select a range. Shift-clicking adds to the selection. A change
in selection is reported to the client by invoking the
selectItems
method. The client can read the current selection by
calling GetFile
or GetFiles
.
\item The user may {\it activate} an item, either by double-clicking on it, or by typing its name in the helper followed by Return.
Activation of a {\it file} is reported to the client by invoking
the activateFile
method, whose default is a no-op.
Activation of a {\it directory} is reported by invoking the
activateDir
method, whose default behavior is to call Set
to
display the activated directory.
The client can distinguish between a double-click and Return by
looking at the AnyEvent.T
passed to the activation method. A
double-click will be reported as an AnyEvent.Mouse
, and Return
will be reported as an AnyEvent.Key
.
\end{itemize}
Directories are indicated in the display by showing some text
(e.g., ``(dir)'') after the name, but that is not part of the
pathname returned by getValue
, GetFile
, GetFiles
, or the
value passed to activateDir
.
A background thread calls Refresh(v)
for every open filebrowser
v
, once per second, to see whether it needs to be updated
(although a distributed filesystem may cause a substantial delay
before the change is noticed).
FileBrowserVBT
is internally synchronized.
INTERFACEThe callFileBrowserVBT ; IMPORT AnchorSplit, AnyEvent, Font, ListVBT, PaintOp, Pathname, Shadow, TextList, TypeinVBT, VBT; TYPE T <: Public; Public = ListVBT.T OBJECT METHODS <* LL.sup <= VBT.mu *> init (font := Font.BuiltIn; colors: PaintOp.ColorQuad := NIL ): T; <* LL.sup = VBT.mu *> selectItems (event: AnyEvent.T); activateFile (filename: Pathname.T; event: AnyEvent.T); activateDir (dirname : Pathname.T; event: AnyEvent.T); error (err: E); END;
v.init(...)
initializes v
as a FileBrowserVBT
. If
v.painter
is a subtype of ListVBT.TextPainter
, init
calls
v.paint.setFont(font)
. The selector
field must be either NIL
(in which case a new selector is created) or a subtype of
FileBrowserVBT.Selector
. The initial state of the filebrowser is
the current working directory, as returned by
Process.GetWorkingDirectory
.
The implementation calls v.selectItems(event)
when the user
changes the selection using the mouse.
When the user double-clicks on a file in the browser, the
implementation calls v.activateFile(filename, event)
, where
filename
in the absolute pathname corresponding to the first selected
item. If the user types Return in the helper, the implementation
calls v.activateFile(filename, event)
, where filename
is either the pathname in the helper, if that was absolute, or
absolute pathname corresponding to
Pathname.Join (GetDir(v), 'helper text', NIL)Don't forget that if
activateFile
is being called because of a
double-click, multiple files might be selected in the browser, even
though you are given only one in the filename
parameter.
The implementation calls v.activateDir(dir)
when a directory is
activated. The normal action is simply to set v
to view that
directory, relative to GetDir(v)
. If an error occurs during the
activation, the error
method is invoked.
The implementation calls v.error(...)
when an error occurs during
user action in v
, and the Error
exception cannot be raised
(e.g., because it happened in a separate thread). Some examples of
errors are as follows: the user has typed a nonexistent directory
in the path; the current directory has become inaccessible; the
user has no permission to read the directory. The default method
is a no-op. By overriding this method, the client can provide
better information to the user.
The error
method is passed an E
object containing information
about the error that occurred. Here is its definition:
EXCEPTION Error (E); TYPE E = OBJECT v : T; text: TEXT := ""; path: Pathname.T := "" END;
The argument to theError
exception includes theFileBrowserVBT
itself, along with a descriptive message and the pathname in question when the error occurred.
Finally, if you create a subtype of
FileBrowserVBT
(which is a
subtype of ListVBT.T
) and you specify a selector for it, it
must be a subtype of Selector
:
TYPE Selector <: ListVBT.MultiSelector;\subsubsection{The Helper}
The FileBrowser's helper (see page \pageref{FBHelper}) is a
TypeinVBT
. Once the user types in the helper, any selected items
in the browser are unselected. If the user types Return in the
browser, that will activate the name in the Helper.
If an error occurs during the activation, the error
method of the
filebrowser to which the helper is attached will be invoked.
TYPE Helper <: TypeinVBT.T; PROCEDURE SetHelper (v: T; helper: Helper) RAISES {Error}; <* LL.sup = VBT.mu *>
Sets the helper forv
to behelper
, and fills it withGetDir(v)
.
\subsubsection{The Directory-Menu}
The directory menu shows the name of each of the parent directories, going back to the root directory.
TYPE DirMenu <: PublicDirMenu; PublicDirMenu = AnchorSplit.T OBJECT METHODS <* LL.sup <= VBT.mu *> init (font := Font.BuiltIn; shadow: Shadow.T := NIL; n : CARDINAL := 0 ): DirMenu; <* LL.sup = VBT.mu *> setFont (font: Font.T); END;The
font
and shadow
control the appearance of the text
within the menu. As usual, if shadow
is NIL
, then
Shadow.None
is used instead. The parameter n
is used by
AnchorSplit
to determine the ZSplit
in which to install
the menu.
PROCEDURE SetDirMenu (v: T; dm: DirMenu); <* LL.sup = VBT.mu *>
Sets the directory-menu ofv
to bedm
and fill it with the current directory.
\subsubsection{FileBrowser options}
A file browser can be ``read-only'':
PROCEDURE SetReadOnly (v: T; readOnly: BOOLEAN); <* LL.sup = VBT.mu *>
Change the ``read-only'' mode ofv
to bereadOnly
.
If a file browser is ``read-only'' then in subsequent calls to
v.activateFile(filename)
filename is guaranteed to exist. Otherwise, the user can type the
name of a non-existing file into the helper. A newly initialized
FileBrowserVBT
is not read-only.
By default all files in the directory are displayed, but the following procedure can be used to filter which files are shown:
PROCEDURE SetSuffixes (v: T; suffixes: TEXT); <* LL.sup = VBT.mu *>
Specify which suffixes
are to be displayed.
If
suffixes
is not the empty string, only files with the
specified suffixes (and all directories) will be displayed.
The format of suffixes
is a sequence of suffixes (not
including the period) separated by non-alphanumeric characters
(e.g., spaces). The special suffix $
indicates ``files with
no suffix.'' Calling SetSuffixes
procedure does not force
v
to be redisplayed.
\subsubsection{Setting the displayed directory}
PROCEDURE Set (v : T; pathname: Pathname.T; time : VBT.TimeStamp := 0) RAISES {Error}; <* LL.sup = VBT.mu *>
Set the display state of v.
The
pathname
may be absolute or relative; if it's relative, it
is relative to the current displayed directory.
If pathname
refers to a non-existent or inaccessible directory,
Error
will be raised. The exception will also be raised if
pathname
refers to a non-existent file and v
is read-only.
If time
is not zero and there is a helper, then the helper
will take the keyboard focus and will display its new contents
in replace-mode, ready for the user to type something in its
place.
PROCEDURE Unselect (v: T); <* LL.sup = VBT.mu *>
Putv
into the no-selection state, without changing the current directory. Equivalent tov.selectNone()
.
PROCEDURE Refresh (v: T) RAISES {Error}; <* LL.sup = VBT.mu *>
Update the display without changing the directory.
If
v
's domain is not empty, and its directory has been Set
, and
the directory has changed since the last time it was displayed,
then v
will be marked for redisplay. Error
is raised only if
the directory has become inaccessible for some reason; in this
case, the browser goes to the empty state, so that if the client
catches Error
and takes no other action, the browser will be
empty but not broken.
\subsubsection{Retrieving selections from the browser}
PROCEDURE GetFiles (v: T): TextList.T RAISES {Error}; <* LL.sup = VBT.mu *>
Return the current selections ofv
, orNIL
if there are no selections. The list includes ``full'' pathnames; they satisfyPathname.Absolute
, but they may contain symbolic links. UseFS.GetAbsolutePathname
to get a pathname with no symbolic links.
PROCEDURE GetFile (v: T): Pathname.T RAISES {Error}; <* LL.sup = VBT.mu *>
Return the first selection, or the empty string if there are no selections.
PROCEDURE GetDir (v: T): Pathname.T; <* LL.sup = VBT.mu *>
Return the current displayed directory ofv
. Returns an empty string ifv
is in the ``empty'' state.
END FileBrowserVBT.