--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSelectionBrowser.st Wed Dec 03 22:12:21 1997 +0100
@@ -0,0 +1,575 @@
+SelectionBrowser subclass:#FileSelectionBrowser
+ instanceVariableNames:'selectedFileFilter fileName readTask'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Advanced-Tools'
+!
+
+Object subclass:#Row
+ instanceVariableNames:'fileName size iconKey group owner permissions baseName'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:FileSelectionBrowser
+!
+
+
+!FileSelectionBrowser class methodsFor:'instance creation'!
+
+requestFileName
+
+ ^self new title: 'Select a file'; open
+
+!
+
+requestFileName: aFileName fileFilters: fileFilters
+
+ ^self new
+ fileName: aFileName;
+ listOfFileFilters: fileFilters;
+ open
+! !
+
+!FileSelectionBrowser class methodsFor:'accessing'!
+
+lastFileSelectionDirectory
+ "^ LastFileSelectionDirectory"
+
+! !
+
+!FileSelectionBrowser class methodsFor:'interface specs'!
+
+windowSpec
+ "this window spec was automatically generated by the ST/X UIPainter"
+
+ "do not manually edit this - the painter/builder may not be able to
+ handle the specification if its corrupted."
+
+ "
+ UIPainter new openOnClass:FileSelectionBrowser andSelector:#windowSpec
+ FileSelectionBrowser new openInterface:#windowSpec
+ "
+ "FileSelectionBrowser open"
+
+ <resource: #canvas>
+
+ ^
+
+ #(#FullSpec
+ #'window:'
+ #(#WindowSpec
+ #'name:' 'File Selection Browser'
+ #'layout:' #(#LayoutFrame 410 0 282 0 809 0 581 0)
+ #'label:' 'File Selection Browser'
+ #'min:' #(#Point 10 10)
+ #'max:' #(#Point 1152 900)
+ #'bounds:' #(#Rectangle 410 282 810 582)
+ #'usePreferredExtent:' false
+ )
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#ViewSpec
+ #'name:' 'view'
+ #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -40 1.0)
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#VariableHorizontalPanelSpec
+ #'name:' 'panel'
+ #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -1 1.0)
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#ViewSpec
+ #'name:' 'view1'
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#FileSelectionTreeSpec
+ #'name:' 'directoryTreeView'
+ #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ #'model:' #selectionOfDirectory
+ #'hasHorizontalScrollBar:' true
+ #'hasVerticalScrollBar:' true
+ #'miniScrollerHorizontal:' true
+ #'showRoot:' false
+ #'showDirectoryIndicator:' true
+ #'valueChangeSelector:' #readDirectory
+ #'hierarchicalList:' #rootOfDirectory
+ #'itemClass:' 'Directory'
+ )
+ )
+ )
+ #'level:' -1
+ )
+ #(#ViewSpec
+ #'name:' 'view2'
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#DataSetSpec
+ #'name:' 'filesDataSetView'
+ #'layout:' #(#LayoutFrame 0 0.0 24 0.0 0 1.0 -23 1.0)
+ #'model:' #selectionOfFile
+ #'hasHorizontalScrollBar:' true
+ #'hasVerticalScrollBar:' true
+ #'miniScrollerHorizontal:' true
+ #'dataList:' #listOfFiles
+ #'useIndex:' false
+ #'level:' 1
+ #'doubleClickSelector:' #fileDoubleClicked
+ #'valueChangeSelector:' #fileSelected
+ #'verticalSpacing:' 1
+ #'columns:'
+ #(
+ #(#DataSetColumnSpec
+ #'label:' ''
+ #'width:' 30
+ #'printSelector:' #'iconOn:'
+ #'canSelect:' false
+ )
+ #(#DataSetColumnSpec
+ #'label:' 'file name'
+ #'minWidth:' 100
+ #'model:' #baseName
+ )
+ #(#DataSetColumnSpec
+ #'label:' 'size'
+ #'width:' 50
+ #'model:' #size
+ #'canSelect:' false
+ )
+ #(#DataSetColumnSpec
+ #'label:' 'permissions'
+ #'width:' 85
+ #'model:' #permissions
+ #'canSelect:' false
+ )
+ #(#DataSetColumnSpec
+ #'label:' 'owner'
+ #'width:' 50
+ #'model:' #owner
+ #'canSelect:' false
+ )
+ #(#DataSetColumnSpec
+ #'label:' 'group'
+ #'width:' 50
+ #'model:' #group
+ #'canSelect:' false
+ )
+ )
+ )
+ #(#ComboBoxSpec
+ #'name:' 'formatComboBox'
+ #'layout:' #(#LayoutFrame 0 0.0 2 0 0 1.0 24 0)
+ #'model:' #selectionOfFileFilter
+ #'immediateAccept:' false
+ #'acceptOnTab:' false
+ #'comboList:' #listOfFileFilters
+ )
+ #(#InputFieldSpec
+ #'name:' 'EditField'
+ #'layout:' #(#LayoutFrame 0 0.0 -22 1 0 1.0 0 1)
+ #'model:' #valueOfFileName
+ #'acceptOnReturn:' false
+ #'acceptOnTab:' false
+ )
+ )
+ )
+ #'level:' -1
+ )
+ )
+ )
+ #'handles:' #(#Any 0.5 1.0)
+ )
+ )
+ )
+ )
+ #(#HorizontalPanelViewSpec
+ #'name:' 'horizontalPanelView'
+ #'layout:' #(#LayoutFrame 0 0.0 -40 1 0 1.0 0 1.0)
+ #'component:'
+ #(#SpecCollection
+ #'collection:'
+ #(
+ #(#ActionButtonSpec
+ #'name:' 'cancelButton'
+ #'label:' 'cancel'
+ #'model:' #cancel
+ #'extent:' #(#Point 100 22)
+ )
+ #(#ActionButtonSpec
+ #'name:' 'okButton'
+ #'label:' 'ok'
+ #'model:' #accept
+ #'extent:' #(#Point 100 22)
+ )
+ )
+ )
+ #'level:' 1
+ #'horizontalLayout:' #center
+ #'verticalLayout:' #center
+ #'horizontalSpace:' 3
+ #'verticalSpace:' 3
+ )
+ )
+ )
+ )
+! !
+
+!FileSelectionBrowser methodsFor:'accessing'!
+
+fileName
+
+ (fileName notNil and: [(fileName name ~= self valueOfFileName value and: [self valueOfFileName value notNil])])
+ ifTrue: [^(LastFileSelectionDirectory, Filename separator, self valueOfFileName value) asFilename].
+ ^fileName
+!
+
+fileName: aFileName
+
+ fileName := aFileName
+!
+
+title: aString
+
+ title := aString
+! !
+
+!FileSelectionBrowser methodsFor:'actions'!
+
+closeCancel
+
+ readTask notNil ifTrue: [readTask terminate].
+ fileName := nil.
+ super closeCancel
+!
+
+closeRequest
+
+ readTask notNil ifTrue: [readTask terminate].
+ super closeRequest
+!
+
+closeWindow
+
+ readTask notNil ifTrue: [readTask terminate].
+ super closeWindow
+!
+
+fileDoubleClicked
+
+ self valueOfFileName value: self selectionOfFile value baseName.
+ fileName := self selectionOfFile value fileName.
+ accept value: true.
+ self close
+!
+
+fileSelected
+
+ self valueOfFileName value: self selectionOfFile value baseName.
+ fileName := self selectionOfFile value fileName.
+!
+
+readDirectory
+
+ | file list dir lst|
+ self selectionOfDirectory value isNil ifTrue: [^nil].
+ readTask notNil ifTrue: [readTask terminate].
+ readTask := [
+
+ file := (builder componentAt: #directoryTreeView) selectedPathname asFilename.
+ builder window label: 'Reading: ''', file name, ''''.
+ self class lastSelection: file name.
+ (file isReadable and:[file isExecutable]) ifTrue:[
+ list := self listOfFiles.
+ list removeAll.
+ lst := OrderedCollection new.
+ self listOfFileFilters value
+ do: [:filter|
+ (file filesMatchingWithoutDotDirs: filter) do:
+ [:aFileName|
+ lst add: (Row new fileName: (file name, Filename separator, aFileName) asFilename)
+ ].
+ ].
+ lst := lst asSortedCollection: [:r1 :r2| r1 baseName < r2 baseName].
+ list addAll:lst beforeIndex:1].
+ self selectionOfFile value: (self listOfFiles detect: [:r| r fileName = fileName] ifNone: [nil]).
+ self setLabel.
+ ] forkAt: 4
+! !
+
+!FileSelectionBrowser methodsFor:'aspects'!
+
+listOfFileFilters
+ |holder|
+
+ (holder := builder bindingAt:#listOfFileFilters) isNil ifTrue:[
+ builder aspectAt:#listOfFileFilters put:(holder := List with: '*.*').
+ ].
+ ^ holder
+!
+
+listOfFileFilters: aCollection
+ self listOfFileFilters contents: aCollection.
+!
+
+listOfFiles
+
+ |holder|
+ (holder := builder bindingAt:#listOfFiles) isNil ifTrue:[
+ builder aspectAt:#listOfFiles put:(holder := List new).
+ ].
+ ^ holder
+
+!
+
+rootOfDirectory
+
+ |holder|
+
+ (holder := builder bindingAt:#rootOfDirectory) isNil ifTrue:[
+ builder aspectAt:#rootOfDirectory put: (holder := ValueHolder with: Filename rootDirectory name).
+ ].
+ ^ holder
+
+!
+
+selectionOfDirectory
+
+ |holder|
+ (holder := builder bindingAt:#selectionOfDirectory) isNil ifTrue:[
+ builder aspectAt:#selectionOfDirectory put: (holder := ValueHolder new)
+ ].
+ ^ holder
+
+!
+
+selectionOfFile
+
+ |holder|
+ (holder := builder bindingAt:#selectionOfFile) isNil ifTrue:[
+ builder aspectAt:#selectionOfFile put:(holder := ValueHolder new).
+ ].
+ ^ holder
+
+!
+
+selectionOfFileFilter
+ |holder|
+
+ (holder := builder bindingAt:#selectionOfFileFilter) isNil ifTrue:[
+ builder aspectAt:#selectionOfFileFilter put:
+ (holder := AspectAdaptor new subject:self; forAspect:#selectedFileFilter).
+ selectedFileFilter := '*.*'.
+ ].
+ ^ holder
+!
+
+valueOfFileName
+
+ |holder|
+ (holder := builder bindingAt:#valueOfFileName) isNil ifTrue:[
+ builder aspectAt:#valueOfFileName put:(holder := ValueHolder new).
+ ].
+ ^ holder
+! !
+
+!FileSelectionBrowser methodsFor:'initialization'!
+
+open
+
+ super open.
+ accept value
+ ifTrue:
+ [
+ ^(self selectionOfDirectory value ? '') , Filename separator, (self valueOfFileName value ? '')
+ ].
+ ^nil
+
+
+
+!
+
+postBuildWith:aBuilder
+
+ (fileName notNil and: [fileName asFilename exists])
+ ifTrue:
+ [
+ self class lastSelection: fileName asFilename directoryName.
+ self valueOfFileName value: fileName asFilename baseName
+ ].
+ (builder componentAt: #directoryTreeView) selectPathname: self class lastSelection.
+ self selectionOfFileFilter value: (self listOfFileFilters at: 1 ifAbsent: [nil]).
+ self readDirectory.
+ (builder componentAt: #directoryTreeView) monitoring: true.
+ ^super postBuildWith:aBuilder
+! !
+
+!FileSelectionBrowser methodsFor:'selection'!
+
+selectedFileFilter
+
+ ^selectedFileFilter
+!
+
+selectedFileFilter: aString
+
+ selectedFileFilter := aString.
+
+ self readDirectory
+! !
+
+!FileSelectionBrowser::Row methodsFor:'accessing'!
+
+baseName
+ baseName isNil ifTrue: [baseName := fileName baseName].
+ ^ baseName
+
+
+
+
+
+!
+
+fileName
+ ^ fileName
+
+!
+
+fileName: aFileName
+ fileName := aFileName
+
+!
+
+group
+ group isNil ifTrue:[
+ self validateAttributes
+ ].
+ ^ group
+!
+
+iconOn:aGC
+ |icon|
+
+ iconKey isNil ifTrue:[
+ self validateAttributes.
+ ].
+ (iconKey == #image) | (iconKey == #imageFile)
+ ifTrue:
+ [
+ Object errorSignal handle: [:ex|]
+ do:
+ [
+ ((size < 5000) and: [(icon := Image fromFile: fileName name) notNil])
+ ifTrue: [aGC registerImage: icon key:(iconKey :=fileName name asSymbol).]
+ ].
+ ].
+ (icon := aGC registeredImageAt:iconKey) isNil ifTrue:[
+ self registerIconsOn:aGC.
+ icon := aGC registeredImageAt:iconKey.
+ ].
+ ^ icon
+
+
+
+!
+
+owner
+ owner isNil ifTrue:[
+ self validateAttributes
+ ].
+ ^ owner
+
+
+!
+
+permissions
+ permissions isNil ifTrue:[
+ self validateAttributes
+ ].
+ ^ permissions
+
+
+!
+
+size
+ size isNil ifTrue:[
+ self validateAttributes
+ ].
+ ^ size
+
+! !
+
+!FileSelectionBrowser::Row methodsFor:'private'!
+
+registerIconsOn:aGC
+ "register all file icons on the gc
+ "
+ |directory|
+
+ directory := 'xpmBitmaps/document_images/'.
+
+ #(
+ (#file 'tiny_file_plain.xpm' )
+ (#fileLink 'tiny_file_link.xpm' )
+ (#fileLocked 'tiny_file_lock.xpm' )
+ (#imageFile 'tiny_file_pix.xpm' )
+
+ ) do:[:el|
+ aGC registerImage:(Image fromFile:(directory, el last)) key:(el first)
+ ].
+
+
+
+
+
+!
+
+validateAttributes
+ |info mode|
+
+ permissions := String new:9 withAll:$-.
+
+ (info := fileName info) isNil ifTrue:[
+ iconKey := #fileLocked.
+ size := owner := group := '?'.
+ ^ self
+ ].
+ size := info size.
+ owner := OperatingSystem getUserNameFromID:(info uid).
+ group := OperatingSystem getGroupNameFromID:(info gid).
+ mode := info mode.
+
+ 1 to:9 by:3 do:[:i|
+ (mode bitAt:i ) == 1 ifTrue:[permissions at:10 - i put:$x].
+ (mode bitAt:i + 1) == 1 ifTrue:[permissions at:9 - i put:$w].
+ (mode bitAt:i + 2) == 1 ifTrue:[permissions at:8 - i put:$r].
+ ].
+
+ fileName isReadable ifTrue:[
+ info type == #symbolicLink ifTrue:[
+ iconKey == #fileLink
+ ] ifFalse:[
+ (Image isImageFileSuffix:(fileName suffix)) ifTrue:[
+ iconKey := #imageFile
+ ] ifFalse:[
+ iconKey := #file
+ ]
+ ]
+ ] ifFalse:[
+ iconKey := #fileLocked
+ ].
+
+! !
+
+!FileSelectionBrowser class methodsFor:'documentation'!
+
+version
+ ^ '$Header$'
+! !