eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'FileSelectionList':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: FileSelectionList


Inheritance:

   Object
   |
   +--GraphicsMedium
      |
      +--DisplaySurface
         |
         +--SimpleView
            |
            +--View
               |
               +--ListView
                  |
                  +--SelectionInListView
                     |
                     +--FileSelectionList

Package:
stx:libwidg
Category:
Views-Lists
Version:
rev: 1.63 date: 2019/03/01 14:44:18
user: cg
file: FileSelectionList.st directory: libwidg
module: stx stc-classLibrary: libwidg
Author:
Claus Gittinger

Description:


this class implements file selection lists - its basically a
selection-in-list-view, but adds some right-arrows to directories.
(and will soon remember the previous position when changing directories).
You can specify an optional filename-pattern (such as '*.st') and an
optional matchBlock (such as: [:name | name startsWith:'A']).

Only files (plus directories) matching the pattern (if present) and
for which the matchBlock returns true (if present), are shown.

Except for file-browser like applications, FileSelectionLists are almost 
exclusively used with FileSelectionBoxes (see examples there).

[Instance variables:]
        pattern                 the matchpattern

        directory               the current directory

        timeStamp               the time, when directoryContents was last taken

        directoryId             the directories id (inode-nr) when it was taken

        directoryName           the path when it was taken

        directoryContents       (cached) contents of current directory

        directoryFileTypes      (cached) isDirectory-boolean per entry

        fileTypes               file types as shown in list (i.e only matching ones)

        matchBlock              if non-nil: block evaluated per full filename;
                                only files for which matchBlock returns true are shown.

        realAction              (internal) the action to perform when a file is selected

        quickDirectoryChange    if true, directories can be changed with a single click
                                if false (the default), they need a double click.
                                Makes sense if a directory is what we are interested in,
                                for files its better to leave it as false.

        stayInDirectory         if true, no directoryChanges are allowed.
                                Makes sense to limit the user to choose among certain files.    
                                The default is false.

        ignoreParentDirectory   if true, the parent directory is not shown.
                                Makes sense to limit the user to files below the initial
                                directory. Default is false.

        ignoreDirectories       if true, no directories are shown at all.
                                Makes sense to limit the user to choose among regular files.
                                Default is false.

        ignoreFiles             if true, no regular files are shown at all.
                                Makes sense to limit the user to choose among directories files.
                                Default is false.

        directoryChangeCheckBlock 
                                if nonNil, directoryChanges are only allowed if this block
                                returns true. It is evaluated with one argument, the pathName.
                                Defaults to nil (i.e. no checks).

        directorySelectAction 
                                if nonNil, a directory-select evaluate this block.
                                Possible hook for others (used with Boxes)
                                Defaults to nil.

        fileSelectAction 
                                if nonNil, file-select evaluate this block.
                                Possible hook for others (used with Boxes)
                                Defaults to nil.


Related information:

    DialogBox
    EnterBox2
    YesNoBox
    ListSelectionBox
    FileSelectionBox
    FileSaveBox

Instance protocol:

accessing-behavior
o  action: aBlock
set the action to be performed on a selection

o  directoryChangeAction: aBlock
set the action to be performed on a directory change

o  directoryChangeCheckBlock: aBlock
set the directoryChangeCheckBlock - if non-nil, it controls if
a directory change is legal.

o  directorySelectAction: aBlock
set the action to be performed when a directory is selected.
Useful if someone else wants to show additional information
(readable/owner ...) somewhere.

o  fileSelectAction: aBlock
set the action to be performed when a file is selected.
Useful if someone else wants to show additional information
(readable/owner ...) somewhere.

o  ignoreCaseInPattern: aBoolean
set/clear the flag which controls if the pattern match is caseless.
if it changes, update the list.
The default is true for systems, where filenames are caseless (i.e. msdos-based).

o  ignoreDirectories: aBoolean
set/clear the flag which controls if directories are ignored
(i.e. hidden). The default is false (i.e. dirs are shown)

o  ignoreFiles: aBoolean
set/clear the flag which controls if plain files are ignored
(i.e. hidden). The default is false (i.e. they are shown)

o  ignoreParentDirectory: aBoolean
set/clear the flag which controls if the parent directory (..)
is shown in the list. The default is false (i.e. show it)

o  markDirectories: aBoolean
turn on/off marking of directories with an arrow.
The default is on

o  matchBlock: aBlock
set the matchBlock - if non-nil, it controls which
names are shown in the list.

o  pattern: aPattern
set the pattern - if it changes, update the list.

o  quickDirectoryChange: aBoolean
set/clear quick change (i.e. chdir with single click).
The default is false (i.e. double click is required)

o  stayInDirectory: aBoolean
set/clear the flag which controls if selecting a directory
should locally change (if false) or be handled just like
the selection of a file (if true).
The default is false (i.e. change and do not tell via action)

accessing-channels
o  directoryHolder: aValueHolder

accessing-contents
o  directory
return the shown directory

o  directory: nameOrDirectory
set the lists contents to the filenames in the directory.
This does not validate the change with any directoryChangeBlock.

o  selectedPathname
if there is a selection, return its full pathname.
Of there is no selection, return nil.

drawing
o  redrawFromVisibleLine: startVisLineNr to: endVisLineNr
redefined to look for directory in every line

o  redrawVisibleLine: visLineNr
if the line is one for a directory, draw a right arrow

events
o  directoryHolderChange

o  doubleClicked
(comment from inherited method)
can only happen if claus modifies the selection within

o  keyPress: key x: x y: y
handle cursor-left and cursor-right keys

o  selectionChanged
if the selection changed, check for it being a directory
and possibly go there. If it's not a directory, perform the realAction.

o  sizeChanged: how
redraw marks if any

initialization
o  initialize
nontypical use ...

o  initializeAction
setup action as: selections in list get forwarded to enterfield if not
a directory; otherwise directory is changed

o  reinitialize
(comment from inherited method)
this is called right after snapIn

private
o  changeDirectory
change directory to the selected one

o  changeDirectoryTo: newDirectory
change directory; check if allowed; return true if change was ok

o  changeToParentDirectory
change to the parent directory

o  changeToPreviousDirectory
change to the previous directory

o  selectionIsDirectory
return true, if the current selection is a directory

o  updateList
set the lists contents to the filenames in the directory

o  updateListWithoutScrolling
set the lists contents to the filenames in the directory

o  visibleLineNeedsSpecialCare: visLineNr

o  widthForScrollBetween: firstLine and: lastLine
return the width in pixels for a scroll between firstLine and lastLine
- return full width here since there might be directory marks

realization
o  realize
check if directory is still valid (using timestamp and inode numbers)
- reread if not


Examples:


FileSelectionLists are typically used in FileSelectionBoxes, or file-browser-like applications. Thus, the following examples are a bit untypical. example (plain file-list):
    |list|

    list := FileSelectionList new.
    list open
setting a directory holder:
    |holder list|

    holder := '/etc' asValue.
    list := FileSelectionList new.
    list directoryHolder:holder.
    list open.

    (EditField on:holder) open.
scrolled & some action:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
ignore the parentDirectory:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list ignoreParentDirectory:true.
    top open
ignore all directories (i.e. regular files only):
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list ignoreDirectories:true.
    top open
ignore all regular files (i.e. directories only):
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list ignoreFiles:true.
    top open
don't show the directory arrow-mark:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list markDirectories:false.
    top open
adds a pattern, only showing .st files and directories:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list pattern:'*.st'.
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
a more complicated pattern:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list pattern:'[A-D]*.st'.
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
adds a matchblock to show only writable files:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list matchBlock:[:name | 
                        |fileName|
                        fileName := name asFilename.
                        fileName isWritable or:[fileName isDirectory]
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
adds a matchblock to suppress directories: (this can be done easier with #ignoreDirectories)
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list matchBlock:[:name | 
                        name asFilename isDirectory not
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
the above can be done more convenient:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list ignoreDirectories:true.
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
adds a matchblock to block parent dirs (i.e. only allow files here & below): (can be done easier with #ignoreParentDirectory)
    |top v list currentDir|

    currentDir := '.' asFilename pathName.

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list matchBlock:[:name | 
                        ((name endsWith:'/..') and:[list directory pathName = currentDir]) not
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
do not allow changing up AND show all .rc-files only: (but allow going down)
    |top v list currentDir|

    currentDir := '.' asFilename pathName.

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list pattern:'*.rc'.
    list matchBlock:[:name |  
                        ((name endsWith:'/..') and:[list directory pathName = currentDir]) not
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
show only .rc-files in current directory:
    |top v list currentDir|

    currentDir := '.' asFilename pathName.

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list pattern:'*.rc'.
    list matchBlock:[:name | 
                        name asFilename isDirectory not
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
show only h*-files in /etc; don't allow directory changes:
    |top v list|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list directory:'/etc'.
    list pattern:'h*'.
    list matchBlock:[:name | name printNL.
                        name asFilename isDirectory not
                    ].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
only allow changing into directories below the current one; i.e. not up; but show it
    |top v list here|

    top := StandardSystemView new.
    top extent:(300 @ 200).
    v := ScrollableView for:FileSelectionList in:top.
    v origin:(0.0 @ 0.0) corner:(1.0 @ 1.0).
    list := v scrolledView.
    list directoryChangeCheckBlock:[:dirPath |
                    dirPath asFilename pathName
                        startsWith:Filename currentDirectory pathName].
    list action:[:index | Transcript showCR:'you selected: ' , list selectionValue].
    top open
living in a box:
    |box listView|

    box := Dialog new.
    box addTextLabel:'which file ?'.

    listView := box 
                    addListBoxOn:nil 
                    class:FileSelectionList
                    withNumberOfLines:10 
                    hScrollable:false 
                    vScrollable:true.

    box addAbortButton; addOkButton.
    box stickAtBottomWithVariableHeight:listView.
    box open.
    box accepted ifTrue:[
        Transcript showCR:listView selectedPathname
    ]
living in a box (local files only, no directory change allowed):
    |box listView|

    box := Dialog new.
    box addTextLabel:'which file ?'.

    listView := box 
                    addListBoxOn:nil 
                    class:FileSelectionList
                    withNumberOfLines:10 
                    hScrollable:false 
                    vScrollable:true.

    listView ignoreDirectories:true.
    listView ignoreParentDirectory:true.

    box addAbortButton; addOkButton.
    box stickAtBottomWithVariableHeight:listView.
    box open.
    box accepted ifTrue:[
        Transcript showCR:listView selectedPathname
    ]
living in a box (local files only; immediately show owner in another field):
    |box listView lbl|

    box := Dialog new.
    box addTextLabel:'which file ?'.

    listView := box 
                    addListBoxOn:nil 
                    class:FileSelectionList
                    withNumberOfLines:10 
                    hScrollable:false 
                    vScrollable:true.

    lbl := box addTextLabel:''.
    lbl adjust:#left.

    listView fileSelectAction:[:index |
        |ownerId owner|

        ownerId := listView selectedPathname asFilename info at:#uid.
        ownerId == OperatingSystem getUserID ifTrue:[
            lbl label:('one of yours').
        ] ifFalse:[
            owner := OperatingSystem getUserNameFromID:ownerId.
            lbl label:(owner , '''s property').
        ]
    ].

    listView directorySelectAction:[:index |
        |ownerId owner|

        ownerId := listView selectedPathname asFilename info at:#uid.
        ownerId == OperatingSystem getUserID ifTrue:[
            lbl label:('your files there').
        ] ifFalse:[
            owner := OperatingSystem getUserNameFromID:ownerId.
            lbl label:(owner , '''s files there').
        ]    
    ].

    box addAbortButton; addOkButton.
    box stickAtBottomWithFixHeight:lbl.
    box stickAtBottomWithVariableHeight:listView.
    box open.
    box accepted ifTrue:[
        Transcript showCR:listView selectedPathname
    ]


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Wed, 24 Apr 2024 00:14:25 GMT