"{ Package: 'stx:libtool' }"
AbstractFileBrowser subclass:#DirectoryContentsBrowser
instanceVariableNames:'readDirectoryTask updateDirectoryContentsTask updateColumnsTask
updateFromSensorTask modificationTime directory columnDescriptors
filterBlock iconIndex fileDescriptionIndex iconExtent
tableColumns currentSortOrder previewIndex allItemsList
currentItemList wantSelectFiles updateToExternFileHolderLock
updateTaskSema inDropMode draggedItem canDropItem viewBrowserMenu
updateContentsSelection selectionInFileList contentsBrowser
browserItemList sel'
classVariableNames:''
poolDictionaries:''
category:'Interface-Tools-File'
!
Object subclass:#DirectoryContentsItem
instanceVariableNames:'fileName fileInfo icon fileType
contentsBrowserChangeModificationTime suffix preview group owner
timeAndDate mimeType iconKey mimeTypeForContents'
classVariableNames:'LastUIDToUserNameMapping LastGIDToGroupNameMapping'
poolDictionaries:''
privateIn:DirectoryContentsBrowser
!
!DirectoryContentsBrowser class methodsFor:'documentation'!
documentation
"
DirectoryContentsBrowser openIn:'/home/ca/work/stx/goodies/bitmaps/xpmBitmaps'
DirectoryContentsBrowser openIn:'/home/ca/TEST'
"
! !
!DirectoryContentsBrowser class methodsFor:'instance creation'!
openIn:aDirectory
"opens a directory (standalone) for a directory
"
self openIn:aDirectory withDirectories:false
"
self openIn:(Filename currentDirectory construct:'.cvsignore')
"
!
openIn:aDirectory withDirectories:withDirectoriesBoolean
"opens a directory (standalone) for a directory
"
|browser|
browser := DirectoryContentsBrowser new.
browser open.
aDirectory notNil ifTrue:[
browser currentFileNameHolder value:(OrderedCollection with:(aDirectory asFilename))
].
browser viewDirectoriesInDirectoryContentsBrowser value:withDirectoriesBoolean.
^ browser
"
self openIn:(Filename currentDirectory asAbsoluteFilename) withDirectories:false
"
! !
!DirectoryContentsBrowser class methodsFor:'classAccess'!
itemClass
^ DirectoryContentsItem
"
self itemClass
"
! !
!DirectoryContentsBrowser class methodsFor:'constant'!
updateTaskPriority
"returns the priority of the update task
"
^ 8
! !
!DirectoryContentsBrowser class methodsFor:'image specs'!
detailsMenuIcon2
"This resource specification was automatically generated
by the ImageEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the ImageEditor may not be able to read the specification."
"
self detailsMenuIcon2 inspect
ImageEditor openOnClass:self andSelector:#detailsMenuIcon2
Icon flushCachedIcons
"
<resource: #image>
^Icon
constantNamed:#'DirectoryContentsBrowser class detailsMenuIcon2'
ifAbsentPut:[(Depth1Image new) width: 11; height: 5; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 255 255 255]; mask:((Depth1Image new) width: 11; height: 5; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'* AT@B @D@@@@@@a') ; yourself); yourself]
!
detailsMenuIconR
"This resource specification was automatically generated
by the ImageEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the ImageEditor may not be able to read the specification."
"
self detailsMenuIconR inspect
ImageEditor openOnClass:self andSelector:#detailsMenuIconR
Icon flushCachedIcons
"
<resource: #image>
^Icon
constantNamed:#'DirectoryContentsBrowser class detailsMenuIconR'
ifAbsentPut:[(Depth1Image new) width: 5; height: 7; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 255 255 255]; mask:((Depth1Image new) width: 5; height: 7; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:' DB TJA@ @@a') ; yourself); yourself]
! !
!DirectoryContentsBrowser class methodsFor:'interface specs'!
detailsMenuIcon
"This resource specification was automatically generated
by the ImageEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the ImageEditor may not be able to read the specification."
"
self detailsMenuIcon inspect
ImageEditor openOnClass:self andSelector:#detailsMenuIcon
Icon flushCachedIcons
"
<resource: #image>
^Icon
constantNamed:#'DirectoryContentsBrowser class detailsMenuIcon'
ifAbsentPut:[(Depth1Image new) width: 7; height: 5; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@b') ; colorMapFromArray:#[0 0 0 255 255 255]; mask:((Depth1Image new) width: 7; height: 5; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@W49DPDb') ; yourself); yourself]
!
tableColumns
"This resource specification was automatically generated
by the DataSetBuilder of ST/X."
"Do not manually edit this!! If it is corrupted,
the DataSetBuilder may not be able to read the specification."
"
DataSetBuilder new openOnClass:DirectoryContentsBrowser andSelector:#tableColumns
"
<resource: #tableColumns>
^#(
#(#DataSetColumnSpec
#label: #detailsMenuIconR
#labelIsImage: true
#labelButtonType: #Group
#labelActionSelector: #showDetailMenu
#width: 22
#minWidth: 22
#height: 16
#model: #icon
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Filename'
#id: #filename
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'baseName'
#minWidth: 150
#model: #baseName
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Suffix'
#id: #suffix
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'suffix'
#width: 40
#model: #suffix
#canSelect: false
#isResizeable: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Perm'
#id: #perm
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'permissions'
#width: 75
#model: #permissions
#canSelect: false
#isResizeable: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Owner'
#id: #owner
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'owner'
#usePreferredWidth: true
#width: 50
#model: #owner
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Group'
#id: #group
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'group'
#usePreferredWidth: true
#width: 40
#model: #group
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Size'
#id: #size
#translateLabel: true
#labelAlignment: #right
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'fileSize'
#columnAlignment: #right
#usePreferredWidth: true
#model: #sizeString
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Date & Time'
#id: #time
#labelAlignment: #right
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'modificationTime'
#columnAlignment: #right
#usePreferredWidth: true
#width: 140
#model: #timeAndDate
#writeSelector: #date:
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'File Info'
#id: #fileInfo
#labelAlignment: #left
#labelButtonType: #Button
#labelActionSelector: #sortFileListsBy:
#labelActionArgument: 'fileType'
#width: 250
#model: #fileInfoString
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'Pre +/-'
#id: #preview
#labelButtonType: #Button
#labelActionSelector: #doResizeImage
#labelActionArgument: ''
#columnAlignment: #center
#width: 45
#height: 16
#model: #preview
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
)
!
windowSpec
"This resource specification was automatically generated
by the UIPainter of ST/X."
"Do not manually edit this!! If it is corrupted,
the UIPainter may not be able to read the specification."
"
UIPainter new openOnClass:DirectoryContentsBrowser andSelector:#windowSpec
DirectoryContentsBrowser new openInterface:#windowSpec
DirectoryContentsBrowser open
"
<resource: #canvas>
^
#(#FullSpec
#name: #windowSpec
#window:
#(#WindowSpec
#label: 'Directory ContentsBrowser'
#name: 'Directory ContentsBrowser'
#min: #(#Point 10 10)
#max: #(#Point 1152 900)
#bounds: #(#Rectangle 16 42 604 520)
#menu: #menu
)
#component:
#(#SpecCollection
#collection: #(
#(#DataSetSpec
#name: 'browser'
#layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
#model: #selectionInFileList
#menu: #directoryContentsBrowserMenu
#hasHorizontalScrollBar: true
#hasVerticalScrollBar: true
#miniScrollerHorizontal: false
#miniScrollerVertical: false
#dataList: #browserItemList
#useIndex: false
#has3Dsepartors: false
#doubleClickSelector: #doubleClickedAt:
#columnHolder: #tableColumns
#multipleSelectOk: true
#verticalSpacing: 0
#columns:
#(#OrderedCollection
#(#DataSetColumnSpec
#labelButtonType: #Group
#width: 22
#minWidth: 22
#height: 16
#model: #icon
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: 'file name'
#labelAlignment: #left
#labelButtonType: #Button
#model: #baseName
#canSelect: false
#showRowSeparator: false
#showColSeparator: false
)
#(#DataSetColumnSpec
#label: '+/-'
#labelButtonType: #Button
#labelActionSelector: #doResizeImage
#labelActionArgument: ''
#columnAlignment: #center
#width: 30
#height: 16
#model: #preview
#canSelect: false
#showRowSeparator: false
#showSelectionHighLighted: false
#showColSeparator: false
)
)
#viewClassName: 'DirectoryContentsBrowser::Widget'
#postBuildCallback: #postBuildBrowser:
#properties:
#(#PropertyListDictionary
#dropSelector: #doDrop:
#dragArgument: #contentsbrowser
#startDragSelector: #doStartDrag:in:
#displayObjectSelector: #getDisplayObjects:
#dropObjectSelector: #getDropObjects:
#dropArgument: #browser
#canDropSelector: #canDrop:
#leaveSelector: #dropLeave:
#enterSelector: #dropEnter:
#overSelector: #dropOver:
)
)
)
)
)
! !
!DirectoryContentsBrowser class methodsFor:'menu specs'!
directoryContentsBrowserMenu
"This resource specification was automatically generated
by the MenuEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:DirectoryContentsBrowser andSelector:#directoryContentsBrowserMenu
(Menu new fromLiteralArrayEncoding:(DirectoryContentsBrowser directoryContentsBrowserMenu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#label: 'Copy'
#translateLabel: true
#value: #doCopy
#shortcutKeyCharacter: #Copy
)
#(#MenuItem
#label: 'Cut'
#translateLabel: true
#value: #doCut
#shortcutKeyCharacter: #Cut
)
#(#MenuItem
#label: 'Paste'
#translateLabel: true
#value: #pasteFiles
#enabled: #canPaste
#shortcutKeyCharacter: #Paste
)
#(#MenuItem
#label: 'Delete'
#translateLabel: true
#nameKey: #delete
#value: #doDelete
#shortcutKeyCharacter: #Delete
)
#(#MenuItem
#label: 'Rename...'
#translateLabel: true
#value: #renameSelection
#enabled: #hasSelection
#shortcutKeyCharacter: #Replace
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'View'
#translateLabel: true
#nameKey: #View
#submenuChannel: #viewBrowserMenu
)
#(#MenuItem
#label: 'Sort'
#translateLabel: true
#nameKey: #Sort
#submenuChannel: #sortMenu
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'New'
#translateLabel: true
#submenuChannel: #newMenu
)
#(#MenuItem
#label: 'Properties...'
#translateLabel: true
#value: #doShowProperties
#enabled: #hasSelection
)
#(#MenuItem
#label: 'More'
#submenu:
#(#Menu
#(
#(#MenuItem
#label: 'File In'
#translateLabel: true
#value: #fileFileIn
#enabled: #hasSelection
#shortcutKeyCharacter: #Accept
)
#(#MenuItem
#label: 'File in to NameSpace...'
#translateLabel: true
#value: #fileFileInToNameSpace
#enabled: #hasSelection
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Open in TextEditor'
#translateLabel: true
#value: #doShowFileContents
#enabled: #hasSelection
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Select All'
#translateLabel: true
#value: #selectAll
)
#(#MenuItem
#label: 'Copy File List'
#translateLabel: true
#value: #copyFileList
#enabled: #fileListIsNotEmpty
)
)
nil
nil
)
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Update'
#translateLabel: true
#value: #doUpdate
)
)
nil
nil
)
!
viewBrowserMenu
"This resource specification was automatically generated
by the MenuEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:DirectoryContentsBrowser andSelector:#viewBrowserMenu
(Menu new fromLiteralArrayEncoding:(DirectoryContentsBrowser viewBrowserMenu)) startUp
"
<resource: #menu>
^ Menu new fromLiteralArrayEncoding:self viewBrowserMenuSpec
!
viewBrowserMenuSpec
"This resource specification was automatically generated
by the MenuEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:DirectoryContentsBrowser andSelector:#viewBrowserMenu
(Menu new fromLiteralArrayEncoding:(DirectoryContentsBrowser viewBrowserMenu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#label: 'View Details'
#translateLabel: true
#hideMenuOnActivated: false
#indication: #viewDetails
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'View Suffix'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewType
)
#(#MenuItem
#label: 'View Permissions'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewPermissions
)
#(#MenuItem
#label: 'View Owner'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewOwner
)
#(#MenuItem
#label: 'View Group'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewGroup
)
#(#MenuItem
#label: 'View Size'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewSize
)
#(#MenuItem
#label: 'View Date && Time'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewTime
)
#(#MenuItem
#label: 'View File Info'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewDescription
)
#(#MenuItem
#label: 'View Preview'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewPreview
)
#(#MenuItem
#label: '-'
#isVisible: false
)
#(#MenuItem
#label: 'Show Hidden Files'
#translateLabel: true
#indication: #showHiddenFiles
#isVisible: false
)
#(#MenuItem
#label: 'Update'
#translateLabel: true
#value: #doUpdate
#isVisible: false
)
)
nil
nil
)
!
viewDetailsMenuSpec
"This resource specification was automatically generated
by the MenuEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:DirectoryContentsBrowser andSelector:#viewBrowserMenu
(Menu new fromLiteralArrayEncoding:(DirectoryContentsBrowser viewBrowserMenu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#label: 'Suffix'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewType
)
#(#MenuItem
#label: 'Permissions'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewPermissions
)
#(#MenuItem
#label: 'Owner'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewOwner
)
#(#MenuItem
#label: 'Group'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewGroup
)
#(#MenuItem
#label: 'Size'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewSize
)
#(#MenuItem
#label: 'Date && Time'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewTime
)
#(#MenuItem
#label: 'File Info'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewDescription
)
#(#MenuItem
#label: 'Preview'
#translateLabel: true
#hideMenuOnActivated: false
#enabled: #viewDetails
#indication: #viewPreview
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Hidden Files'
#translateLabel: true
#indication: #showHiddenFiles
)
)
nil
nil
)
! !
!DirectoryContentsBrowser methodsFor:'accessing'!
columnDescriptors
"get the column description
"
^ columnDescriptors
!
columnDescriptors:aListOfColumns
"set the column description
"
columnDescriptors = aListOfColumns ifTrue:[
^ self
].
columnDescriptors := OrderedCollection new.
previewIndex := 0.
iconIndex := 0.
fileDescriptionIndex := 0.
iconExtent := nil.
aListOfColumns keysAndValuesDo:[:anIndex :aDesc| |col|
col := aDesc isSequenceable ifTrue:[DataSetColumnSpec new fromLiteralArrayEncoding:aDesc]
ifFalse:[aDesc].
columnDescriptors add:col.
col readSelector == #preview ifTrue:[
previewIndex := anIndex.
iconExtent := Point x:(col width) y:(col height).
] ifFalse:[
col readSelector == #fileInfoString ifTrue:[
fileDescriptionIndex := anIndex.
] ifFalse:[
col readSelector == #icon ifTrue:[
iconIndex := anIndex.
]
]
]
].
!
directory
"returns the current directory or nil
"
^ directory
!
directory:aDirectory
"change the current directory and read the items
"
self readDirectoryTaskStop.
self updateDirectoryContentsTaskStop.
self updateColumnsTaskStop.
directory := aDirectory.
allItemsList := nil.
currentItemList := nil.
self readDirectoryTaskStart.
!
filterBlock
"return the value of the instance variable 'filterBlock' (automatically generated)"
^ filterBlock
!
filterBlock:something
"set the value of the instance variable 'filterBlock' (automatically generated)"
filterBlock := something.
!
updateColumnsTask
"return the value of the instance variable 'updateColumnsTask' (automatically generated)"
^ updateColumnsTask
!
updateColumnsTask:something
"set the value of the instance variable 'updateColumnsTask' (automatically generated)"
updateColumnsTask := something.
!
updateContentsSelection
"return the value of the instance variable 'updateToExternFileHolder' (automatically generated)"
updateContentsSelection isNil ifTrue:[
updateContentsSelection := self class newLock.
].
^ updateContentsSelection
!
updateDirectoryContentsTask
"return the value of the instance variable 'updateDirectoryContentsTask' (automatically generated)"
^ updateDirectoryContentsTask
!
updateDirectoryContentsTask:something
"set the value of the instance variable 'updateDirectoryContentsTask' (automatically generated)"
updateDirectoryContentsTask := something.
!
updateToExternFileHolderLock
"return the value of the instance variable 'updateToExternFileHolder' (automatically generated)"
updateToExternFileHolderLock isNil ifTrue:[
updateToExternFileHolderLock := self class newLock.
].
^ updateToExternFileHolderLock
! !
!DirectoryContentsBrowser methodsFor:'actions'!
doResizeImage
|column w h|
previewIndex == 0 ifTrue:[^ self].
column := columnDescriptors at:previewIndex.
w := iconExtent x.
h := iconExtent y.
w == column width ifTrue:[
w := w * 2.
h := h * 2.
].
column width:w.
column height:h.
"/Processor activeProcess ~~ self windowGroup process ifTrue:[self halt].
self updateColumnsTaskStop.
browserItemList do:[:el| el resetImageFile ].
contentsBrowser columnDescriptors:columnDescriptors.
self updateColumnsTaskStart.
!
doUpdate
modificationTime := nil.
self updateDirectoryContentsTaskRestart.
!
doubleClickedAt:anItemIndex
self withWaitCursorDo:[
self enterActionFor:(self selectedItems first). "/ anItemIndex.
]
!
enterActionFor:anItem
| filename|
filename := anItem fileName.
filename = '..' asFilename ifTrue:[
self currentFileNameHolder value:(OrderedCollection with:(self directory directory)).
^ self.
].
(anItem isRemoteDirectory
or:[filename isDirectory]) ifTrue:[
self currentFileNameHolder value:(OrderedCollection with:filename).
^ self.
].
self openApplByFileItem:anItem.
! !
!DirectoryContentsBrowser methodsFor:'aspects'!
browserItemList
browserItemList isNil ifTrue:[
browserItemList := List new.
].
^ browserItemList
!
descriptions:anItemCollection
| showDir directoryUpItem|
self updateColumnsTaskStop. "/ dont access rows while rows changed
self updateToExternFileHolderLock doLocked:[
showDir := self viewDirectoriesInDirectoryContentsBrowser value.
(showDir and:[self directory notNil and:[self directory isRootDirectory not]]) ifTrue:[
directoryUpItem := DirectoryContentsItem fileName:('..' asFilename).
directoryUpItem icon:(FileBrowser iconForKeyMatching:#directory).
anItemCollection addFirst:directoryUpItem.
].
"/ because this can be invoked by a background task,
"/ ensure that we syncronize this operation with the main browsers GUI
"/ (i.e. avoid changing the list, while the main process loops over it in
"/ a redraw, select etc.)
self
enqueueMessage:#value
for:[
self updateColumnsTaskStop.
browserItemList contents:anItemCollection.
self updateColumnsTaskStart.
wantSelectFiles notNil ifTrue:[
self selectFiles:wantSelectFiles.
].
]
arguments:nil.
].
"/ self updateColumnsTaskStart.
"/ wantSelectFiles notNil ifTrue:[
"/ self selectFileName:wantSelectFiles.
"/ ].
!
selectionInFileList
selectionInFileList isNil ifTrue:[
selectionInFileList := ValueHolder new.
selectionInFileList addDependent:self.
].
^ selectionInFileList
!
tableColumns
"automatically generated by UIPainter ..."
"*** the code below creates a default model when invoked."
"*** (which may not be the one you wanted)"
"*** Please change as required and accept it in the browser."
"*** (and replace this comment by something more useful ;-)"
tableColumns isNil ifTrue:[
tableColumns := self class tableColumns asValue.
"/ if your app needs to be notified of changes, uncomment one of the lines below:
"/ tableColumns addDependent:self.
"/ tableColumns onChangeSend:#tableColumnsChanged to:self.
].
^ tableColumns.
! !
!DirectoryContentsBrowser methodsFor:'change & update'!
currentFileNameHolderChanged
"filename changed
"
| newDir currentDir aColOfFiles|
aColOfFiles := self currentFileNameHolder value.
(aColOfFiles isEmpty or:[self currentFilesAreInSameDirectory not]) ifTrue:[
self directory:nil.
^ self
].
wantSelectFiles := aColOfFiles. "/ set the file to the current filename to change selection if update process have added the list
newDir := self currentDirectories value first.
currentDir := self directory.
newDir = currentDir ifTrue:[
self selectFiles:aColOfFiles.
^ self.
] ifFalse:[
"/ change of the directory filename
self directory:newDir.
].
!
filterChanged
self setDefaultFilter.
self evaluateFilter.
!
selectionChanged
| selection newCurrentFilename |
self directory isNil ifTrue:[^ self].
selection := self selectedFiles.
selection remove:('..' asFilename) ifAbsent:[nil].
selection isEmpty ifTrue:[
newCurrentFilename := OrderedCollection with:self directory.
] ifFalse:[
wantSelectFiles := selection.
newCurrentFilename := selection.
].
self currentFileNameHolder value ~= newCurrentFilename ifTrue:[
self currentFileNameHolder value:newCurrentFilename withoutNotifying:self
]
!
setDefaultFilter
| filter |
filter := self filterModel value.
filter = '' ifTrue:[filter := '*'].
self filterBlock: [: el |
(self showHiddenFiles value
ifFalse:[
(el asString startsWith:'.') not
]
ifTrue:[
true
]
)
and:[filter match:el]].
!
update:something with:aParameter from:aModel
"one of my models changed
"
aModel == self currentFileNameHolder ifTrue:[
self updateContentsSelection doIfUnLocked:[
self updateToExternFileHolderLock doLocked:[
self currentFileNameHolderChanged.
].
].
" do not return here because the AbstractFileBrowser have to do something
for every application "
"/ ^ self.
].
aModel == self selectionInFileList ifTrue:[
self updateToExternFileHolderLock doIfUnLocked:[
self updateContentsSelection doLocked:[
self selectionChanged.
]
].
^ self.
].
aModel == self filterModel ifTrue:[
self updateToExternFileHolderLock doLocked:[
self filterChanged.
].
^ self.
].
aModel == self sortBlockHolder ifTrue:[
self evaluateSortBlock.
^ self.
].
aModel == self viewDirectoriesInDirectoryContentsBrowser ifTrue:[
self evaluateFilter.
^ self
].
super update:something with:aParameter from:aModel
!
viewedColumnsChanged
| columns buffer |
columns := OrderedCollection new.
self class tableColumns do:[:el|
columns add:(DataSetColumnSpec new fromLiteralArrayEncoding:el).
].
buffer := columns copy.
self viewDetails value = false ifTrue:[
contentsBrowser showLabels:false.
buffer do:[:col |
(col readSelector = #baseName or:[col readSelector = #icon]) ifFalse:[
columns remove:col.
]
]
] ifFalse:[
contentsBrowser showLabels:true.
buffer do:[:col |
| id |
id := col id.
id notNil ifTrue:[
(id == #filename) ifTrue:[
self viewType value ifTrue:[
col readSelector:#baseNameWithOutSuffix
] ifFalse:[
col readSelector:#baseName
].
] ifFalse:[
(id == #suffix and:[self viewType value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #group and:[self viewGroup value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #owner and:[self viewOwner value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #perm and:[self viewPermissions value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #preview and:[self viewPreview value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #size and:[self viewSize value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #time and:[self viewTime value not]) ifTrue:[
columns remove:col.
] ifFalse:[
(id == #fileInfo and:[self viewDescription value not]) ifTrue:[
columns remove:col.
]
]
]
]
]
]
]
]
]
]
]
].
self tableColumns value:columns.
self columnDescriptors:(self tableColumns value).
! !
!DirectoryContentsBrowser methodsFor:'directory contents'!
evaluateFilter
|filterBlock showDir|
showDir := self viewDirectoriesInDirectoryContentsBrowser value.
currentItemList := OrderedCollection new.
allItemsList size ~~ 0 ifTrue:[
filterBlock := self filterBlock.
allItemsList do:[:aItem |
(showDir or:[aItem isDirectory not]) ifTrue:[
(filterBlock isNil
or:[filterBlock value:aItem baseName]) ifTrue:[
currentItemList add:aItem
]
]
].
].
self evaluateSortBlock.
!
evaluateSortBlock
| newList|
newList := currentItemList.
newList sort:self sortBlockHolder value.
self descriptions:newList asList.
!
readDirectoryItems
|dir list mountPoints contents|
mountPoints := OperatingSystem mountPoints.
dir := self directory.
list := OrderedCollection new.
dir notNil ifTrue:[
modificationTime := dir modificationTime.
contents := DirectoryContents directoryNamed:dir.
contents itemsDo:[:aItem|
list add:(DirectoryContentsItem forInfoItem:aItem).
].
].
^ list
! !
!DirectoryContentsBrowser methodsFor:'drag & drop'!
canDrop:aContext
^ canDropItem
!
doDrop:aContext
|col destinationPath receiver|
draggedItem isNil ifTrue:[
destinationPath := self directory.
] ifFalse:[
destinationPath := self getDirWithoutFileName:(draggedItem fileName).
destinationPath = '..' asFilename ifTrue:[
destinationPath := self directory directory.
]
].
self dropLeave:aContext.
aContext dropSource argument == #archivApplication ifTrue:[
receiver := aContext dropSource receiver.
receiver extractSelectedFilesTo:destinationPath askForExtractOptions:true.
^ true.
].
col := OrderedCollection new.
aContext dropObjects do:[:obj|
col add:(obj theObject).
].
self copyOrMoveFiles:col to:destinationPath.
^ true.
!
doStartDrag:aDropSource in:aView
"set the cursors before starting the drag & drop operation
"
|selectedFiles|
selectedFiles := self selectedFiles.
(selectedFiles size == 1 and:[selectedFiles first baseName = '..']) ifTrue:[
^ self.
].
^ super doStartDrag:aDropSource in:aView
!
dropEnter:aContext
|dropedObjects|
self dropTargetItemChangedTo:nil in:aContext.
inDropMode := false.
self directory isNil ifTrue:[^ self].
dropedObjects := aContext dropObjects.
dropedObjects do:[:aObject|
|checkObject checkObjectString|
aObject isFileObject ifFalse:[^ self].
checkObject := aObject theObject.
checkObject isFilename not ifTrue:[^ self].
((aContext dropSource argument == #archivApplication) not) ifTrue:[
checkObject isSpecialFile ifTrue:[^ self].
checkObject isReadable ifFalse:[^ self].
].
].
inDropMode := true.
!
dropLeave:aDropContext
inDropMode ifTrue:[
self dropTargetItemChangedTo:nil in:aDropContext.
inDropMode := false.
].
!
dropOver:aContext
"send the last time, when leaving the widget
"
|lineNr newDest destinationFile|
inDropMode ifFalse:[^ self].
lineNr := self getLineNumberFor:aContext.
lineNr notNil ifTrue:[
newDest := browserItemList at:lineNr.
(newDest notNil and:[newDest isDirectory]) ifTrue:[
destinationFile := newDest fileName.
destinationFile = '..' asFilename ifTrue:[
destinationFile := self directory directory.
]
].
].
newDest == draggedItem ifTrue:[^ self].
destinationFile isNil ifTrue:[
destinationFile := self directory.
].
newDest ~~ draggedItem ifTrue:[
aContext dropSource argument == #archivApplication ifTrue:[
canDropItem := true.
] ifFalse:[
canDropItem := self canDropFiles:(aContext dropObjects) for:destinationFile.
].
].
self dropTargetItemChangedTo:newDest in:aContext.
!
dropTargetItemChangedTo:anItem in:aDropContext
| current |
"/ (anItem notNil and:[anItem isDirectory]) ifTrue:[ self halt].
current := draggedItem.
"/ Transcript showCR:'current:', (current isNil ifTrue:['nil'] ifFalse:[current fileName baseName]).
"/ Transcript showCR:'anItem:', (anItem isNil ifTrue:['nil'] ifFalse:[anItem fileName baseName]).
current == anItem ifTrue:[^ self].
draggedItem := anItem.
aDropContext contentsWillChange.
current ifNotNil:[
current isDirectory ifTrue:[
current icon:(self getIconFor:current).
].
].
anItem ifNotNil:[
anItem isDirectory ifTrue:[
anItem icon:(FileBrowser iconForKeyMatching:#directoryOpenGray).
].
].
contentsBrowser shown ifTrue:[
contentsBrowser invalidateVisibleRow:current colAt:iconIndex.
contentsBrowser invalidateVisibleRow:anItem colAt:iconIndex.
contentsBrowser repairDamage.
].
!
getDisplayObjects:anArgument
| selectedFiles string fnName stream|
selectedFiles := self selectedFiles.
selectedFiles isEmpty ifTrue:[ ^ ''].
selectedFiles remove:('..' asFilename) ifAbsent:[nil].
stream := WriteStream on:''.
stream nextPutAll:(selectedFiles first baseName).
selectedFiles size == 1 ifTrue:[
fnName := 'ui_menuitem.xpm'.
] ifFalse:[
fnName := 'ui_submenu_open.xpm'.
stream nextPutAll:' ... '.
stream nextPutAll:(selectedFiles last baseName).
].
string := stream contents.
stream close.
^ Array with:(LabelAndIcon icon:(Image fromFile:fnName)
string:(Text string:string emphasis:#bold)
)
!
getDropObjects:anArgument
^ self selectedFiles collect:[:file| DropObject newFile:file].
!
getLineNumberFor:aDropContext
| yVisible|
yVisible := (aDropContext targetPoint y).
^ contentsBrowser yVisibleToRowNr:yVisible.
! !
!DirectoryContentsBrowser methodsFor:'event handling'!
processEvent:anEvent
"filter keyboard events.
Return true, if I have eaten the event"
|focusView key rawKey|
anEvent isKeyPressEvent ifTrue:[
focusView := anEvent targetView.
key := anEvent key.
rawKey := anEvent rawKey.
(focusView == contentsBrowser) ifTrue:[
"/ (key ~= #'Alt_L') ifTrue:[self halt.].
key == #Paste ifTrue:[
self pasteFiles.
^ true.
].
(key == #CursorLeft) ifTrue:[
self doGoDirectoryUp.
^ true
].
(key == #CursorRight) ifTrue:[
self doBack.
^ true
].
browserItemList size == 0 ifTrue:[
^ false
].
key == #Copy ifTrue:[
self doCopy.
^ true.
].
(key == #Return) ifTrue:[
self doOpenSelectedFile.
^ true.
].
key == #Delete ifTrue:[
self doDelete.
^ true.
].
key == #Cut ifTrue:[
self doCut.
^ true.
].
]
].
^ false
! !
!DirectoryContentsBrowser methodsFor:'file actions'!
doCopy
"copy current selected files/directories
"
self copyFilesToClipBoard:(self selectedFiles).
!
doCut
"cut current selected files/directories
"
self cutFilesToClipBoard:(self selectedFiles).
!
doDelete
"delete current selected files/directories
"
self deleteFiles:(self selectedFiles).
! !
!DirectoryContentsBrowser methodsFor:'menu accessing'!
viewBrowserMenu
<resource: #programMenu >
|menu|
viewBrowserMenu isNil ifTrue:[
viewBrowserMenu := self class viewBrowserMenu.
].
viewBrowserMenu ifNil:[ ^ nil ].
menu := viewBrowserMenu.
menu receiver:self.
^ menu
!
viewDetailsMenuSpec
^self class viewDetailsMenuSpec
! !
!DirectoryContentsBrowser methodsFor:'menu actions'!
doOpenSelectedFile
| selectedFileItems|
selectedFileItems := self selectedFileItems.
(selectedFileItems size == 1) ifTrue:[
self enterActionFor:(selectedFileItems first).
].
!
doShowFileContents
| selectedFileItems|
selectedFileItems := self selectedFileItems.
(selectedFileItems size == 1) ifTrue:[
self openTextEditorOn:(selectedFileItems first).
].
! !
!DirectoryContentsBrowser methodsFor:'queries'!
allItemsOfCurrentDirectory
| list |
list := browserItemList copy.
self viewDirectoriesInDirectoryContentsBrowser value ifTrue:[
list removeIdentical:(browserItemList first) ifAbsent:[nil]
].
^ list.
!
fileListIsEmpty
^ browserItemList isEmpty
!
getAllFilesAsStringCollection
|files items|
items := browserItemList.
files := OrderedCollection new.
items isEmpty ifTrue:[
^ files
].
items do:[:aItem |
aItem isDirectory not ifTrue:[
files add:aItem fileName asString
].
].
^ files.
!
hasFilesFiltered
^ allItemsList size ~~ currentItemList size
! !
!DirectoryContentsBrowser methodsFor:'selection'!
firstSelectedItem
^ self selectedItems first.
!
selectAll
| sel|
sel := browserItemList copy.
sel notEmpty ifTrue:[
sel first fileName baseName = '..' ifTrue:[
sel removeFirst.
]
].
self selectionInFileList value:sel.
!
selectFiles:aColOfFilenames
| curSel newSel|
curSel := self selectedFiles.
aColOfFilenames size = curSel size ifTrue:[
| index |
index := curSel findFirst:[:file| (aColOfFilenames includes:file) not].
index == 0 ifTrue:[ ^ self].
].
newSel := OrderedCollection new.
browserItemList do:[: item|
(aColOfFilenames includes:(item fileName)) ifTrue:[
newSel add:item.
].
].
self selectionInFileList value:newSel.
!
selectedFileItems
| sel |
sel := self selectedItems select:[:item | item isDirectory not].
^ sel
!
selectedFileNames
^ self selectedFileItems collect:[:item| item fileName].
!
selectedFiles
^ self selectedItems collect:[: item| item fileName].
!
selectedItems
| sel |
sel := self selectionInFileList value copy.
sel isNil ifTrue:[ ^ #()].
self viewDirectoriesInDirectoryContentsBrowser value ifTrue:[
sel removeIdentical:(browserItemList first) ifAbsent:[nil]
].
^ self selectionInFileList value.
! !
!DirectoryContentsBrowser methodsFor:'startup / release'!
makeDependent
self currentFileNameHolder addDependent:self.
self viewDirectoriesInDirectoryContentsBrowser addDependent:self.
self filterModel addDependent:self.
self sortBlockHolder addDependent:self.
self sortBlockProperty addDependent:self.
self viewDescription onChangeSend:#viewedColumnsChanged to:self.
self viewDetails onChangeSend:#viewedColumnsChanged to:self.
self viewGroup onChangeSend:#viewedColumnsChanged to:self.
self viewOwner onChangeSend:#viewedColumnsChanged to:self.
self viewPermissions onChangeSend:#viewedColumnsChanged to:self.
self viewPreview onChangeSend:#viewedColumnsChanged to:self.
self viewSize onChangeSend:#viewedColumnsChanged to:self.
self viewTime onChangeSend:#viewedColumnsChanged to:self.
self viewType onChangeSend:#viewedColumnsChanged to:self.
self showHiddenFiles onChangeSend:#filterChanged to:self.
!
postBuildBrowser:aWidget
contentsBrowser := aWidget scrolledView.
contentsBrowser wantsFocusWithPointerEnter.
"/ dont register icons anymore
"/ FileBrowser icons keysAndValuesDo:[:aKey :anIcon|
"/ browser registerImage:anIcon key:aKey.
"/ ].
self columnDescriptors:(self class tableColumns).
!
postBuildWith:aBuilder
self viewedColumnsChanged.
self setDefaultFilter. "/ filterChanged.
^ super postBuildWith:aBuilder.
!
postOpenAsSubcanvasWith:aBuilder
self windowGroup addPreEventHook:self.
^ super postOpenAsSubcanvasWith:aBuilder.
!
postOpenWith:aBuilder
"
only invoked if the application not started from a master
"
self currentFileNameHolder changed.
self windowGroup addPreEventHook:self.
^ super postOpenWith:aBuilder.
!
preBuildWith:aBuilder
self masterApplication isNil ifTrue:[
self masterApplication:nil.
].
^ super preBuildWith:aBuilder.
!
release
"release my resources
"
self updateColumnsTaskStop.
self updateDirectoryContentsTaskStop.
super release.
!
releaseAsSubCanvas
self updateColumnsTaskStop.
self updateDirectoryContentsTaskStop.
^ super releaseAsSubCanvas.
! !
!DirectoryContentsBrowser methodsFor:'task update columns'!
findNextBuildInDescFor:aConditionBlock
|vis idx stillSearching |
vis := contentsBrowser indexOfFirstRowShown.
vis = 0 ifTrue:[vis := 1].
idx := vis.
stillSearching := true.
[ stillSearching ] whileTrue:[
((idx <= browserItemList size) and:[ (contentsBrowser isRowVisible:idx) ]) ifFalse:[
stillSearching := false.
idx := nil.
] ifTrue:[
(aConditionBlock value:(browserItemList at:idx)) ifTrue:[
"/ found a one
stillSearching := false.
] ifFalse:[
idx := idx + 1.
]
].
].
idx isNil ifTrue:[^ nil].
^ browserItemList at:idx ifAbsent:nil
!
findNextItemFor:aBlock
^ allItemsList detect:aBlock ifNone:[nil].
!
getFileInfoFor:aItem
| type|
type := aItem fileName fileType.
aItem fileType:type.
^ type
!
getIconFor:aItem
| key icon|
key := aItem iconKey.
icon := FileBrowser iconForKeyMatching:key.
aItem isRemoteDirectory ifTrue:[
^ icon "/ do not query attributes
].
^ FileBrowser addOnIconsFor:(aItem fileName) to:icon.
!
getIconForMimeTypeByContents:aItem
| currentIcon newIcon icon|
newIcon := FileBrowser iconForKeyMatching:(aItem mimeTypeForContents).
currentIcon := aItem icon.
(currentIcon class == MultiImage) ifTrue:[
| images |
images := currentIcon images.
images removeFirst.
images addFirst:newIcon.
icon := currentIcon.
] ifFalse:[
icon := newIcon.
].
^ icon
!
getPreviewFor:aItem
| column icon|
column := contentsBrowser columnAt:previewIndex.
column isNil ifTrue:[
previewIndex := 0.
] ifFalse:[
(aItem hasMimeType and:[aItem mimeType isImage]) ifTrue:[
Exception handle:[:ex|
icon := nil.
] do:[ |scale extent w h |
icon := Image fromFile:(aItem fileName pathName).
icon notNil ifTrue:[
extent := icon extent.
w := column width - 4.
h := column height.
(extent x > w or:[extent y > h]) ifTrue:[
scale := extent / (w@h).
scale := scale x max:(scale y).
icon := icon magnifiedTo:((extent / scale max:8.0) asInteger).
].
icon := icon onDevice:(contentsBrowser device).
icon clearMaskedPixels.
]
]
] ifFalse:[ icon := nil].
aItem preview:(icon ? '').
].
^ icon
!
updateChangesFor:aItem
aItem resetItemForChanges.
!
updateColumnsTaskCycle
" update items in the foolowing order
- update item if item properties are changed
- update icon for visible items by suffix
- update icon for visible items by contents
- update file info for visible items if file info column is shown
- update preview for visible items if preview column is shown
- update icon for invisible items by suffix
- update icon for invisible items by contents
- update file info for invisible items if file info column is shown
- update preview for invisible items if preview column is shown
- update file info for invisible items if file info column is not shown
"
|desc icon type preview|
currentItemList notEmpty ifTrue:[
"/ update item if item properties are changed
desc := self findNextBuildInDescFor:[:n| n hasBeenModified ].
desc notNil ifTrue:[
contentsBrowser invalidateVisibleRow:desc.
self updateChangesFor:desc.
^ true.
].
"/ update icon for visible items by suffix
desc := self findNextBuildInDescFor:[:n| n icon isNil ].
desc notNil ifTrue:[
icon := self getIconFor:desc.
desc icon:icon.
(icon notNil and:[iconIndex ~~ 0]) ifTrue:[
contentsBrowser invalidateVisibleRow:desc colAt:iconIndex
].
^ true
].
"/ update icon for visible items by contents
desc := self findNextBuildInDescFor:[:n|
(n iconKey == #file
and:[n mimeTypeForContents asSymbol ~= #unknown])
].
desc notNil ifTrue:[
icon := self getIconForMimeTypeByContents:desc.
desc icon:icon.
(icon notNil and:[iconIndex ~~ 0]) ifTrue:[
contentsBrowser invalidateVisibleRow:desc colAt:iconIndex
].
^ true
].
"/ update file info for visible items if file info column is shown
fileDescriptionIndex ~~ 0 ifTrue:[
desc := self findNextBuildInDescFor:[:n| n fileType isNil ].
desc notNil ifTrue:[
type := self getFileInfoFor:desc.
type notNil ifTrue:[contentsBrowser invalidateVisibleRow:desc colAt:fileDescriptionIndex].
^ true
]
].
"/ update preview for visible items if preview column is shown
previewIndex ~~ 0 ifTrue:[
desc := self findNextBuildInDescFor:[:n| n preview isNil ].
desc notNil ifTrue:[
preview := self getPreviewFor:desc.
preview notNil ifTrue:[
contentsBrowser invalidateVisibleRow:desc colAt:previewIndex
].
^ true
]
].
].
"/ may we want to see the other items later make this items to
allItemsList notEmpty ifTrue:[
"/ update icon for invisible items by suffix
desc := self findNextItemFor:[:n| n icon isNil ].
desc notNil ifTrue:[
icon := self getIconFor:desc.
desc icon:icon.
^ true
].
"/ update icon for invisible items by contents
desc := self findNextItemFor:[:n| (n iconKey == #file and:[n mimeTypeForContents ~= #unknown])].
desc notNil ifTrue:[
icon := self getIconForMimeTypeByContents:desc.
desc icon:icon.
^ true
].
"/ update file info for invisible items if file info column is shown
fileDescriptionIndex ~~ 0 ifTrue:[
desc := self findNextItemFor:[:n| n fileType isNil ].
desc notNil ifTrue:[
self getFileInfoFor:desc.
^ true
].
].
"/ update preview for invisible items if preview column is shown
previewIndex ~~ 0 ifTrue:[
desc := self findNextItemFor:[:n| n preview isNil ].
desc notNil ifTrue:[
self getPreviewFor:desc.
^ true
].
].
"/ update file info for invisible items if file info column is not shown
desc := self findNextItemFor:[:n| n fileType isNil ].
desc notNil ifTrue:[
self getFileInfoFor:desc.
^ true
].
].
^ false
!
updateColumnsTaskRestart
"/Processor activeProcess ~~ self windowGroup process ifTrue:[self halt].
self updateColumnsTaskStop.
self updateColumnsTaskStart.
!
updateColumnsTaskStart
| somethigToDo p |
somethigToDo := true.
self directory notNil ifTrue:[
p := [
[
[true] whileTrue:[
somethigToDo := false.
(contentsBrowser shown and:[self directory notNil]) ifTrue:[
somethigToDo := self updateColumnsTaskCycle.
Processor yield.
].
somethigToDo ifFalse:[
Delay waitForSeconds:1.0
]
]
] valueNowOrOnUnwindDo:[
self updateColumnsTask:nil.
]
] newProcess.
"/ p priority:(Processor systemBackgroundPriority).
p priorityRange:(Processor userBackgroundPriority to:Processor activePriority).
self updateColumnsTask: p.
self updateColumnsTask name:('DirectoryContentsBrowser update columns[', self directory baseName, ']').
self updateColumnsTask resume.
]
!
updateColumnsTaskStop
|task|
(task := self updateColumnsTask) notNil ifTrue:[
self updateColumnsTask:nil.
Object errorSignal handle:[:ex|
Dialog warn:ex description.
]do:[
task isDead ifFalse:[
task terminateWithAllSubprocessesInGroup.
task waitUntilTerminated.
]
]
].
! !
!DirectoryContentsBrowser methodsFor:'task update dir contents'!
readDirectoryTaskStart
|p|
p := [
allItemsList := self readDirectoryItems.
self evaluateFilter. "/ filter makes a sort anyway
self updateDirectoryContentsTaskStart.
] newProcess.
"/ p priorityRange:(Processor userBackgroundPriority to:Processor activePriority).
readDirectoryTask := p.
p name:('DirectoryContentsBrowser readDir').
p resume.
!
readDirectoryTaskStop
|task|
(task := readDirectoryTask) notNil ifTrue:[
readDirectoryTask := nil.
Object errorSignal handle:[:ex|
Dialog warn:ex description.
] do:[
task isDead ifFalse:[
task terminateWithAllSubprocessesInGroup.
task waitUntilTerminated.
]
]
].
!
updateDirectoryContentsTaskCycle
| contents|
"/ DIRECTORY CONTNETS HAVE CHANGED
(modificationTime ~= self directory modificationTime) ifTrue:[
modificationTime := self directory modificationTime.
contents := self directory directoryContentsAsFilenames.
contents size == 0 ifTrue:[
allItemsList removeAll.
] ifFalse:[
"/ MERGE WITH CURRENT CONTENTS
allItemsList reverseDo:[:aDesc|
"/ remove no longer valid files
(contents detect:[:f| aDesc fileName = f] ifNone:nil) isNil ifTrue:[
allItemsList removeIdentical:aDesc
]
].
allItemsList size ~~ contents size ifTrue:[
"/ add new files
| addedFiles |
addedFiles := OrderedCollection new.
contents reverseDo:[:aFile|
(allItemsList contains:[:item| item fileName = aFile]) ifTrue:[
addedFiles add:(DirectoryContentsItem fileName:aFile)
]
].
allItemsList addAll:addedFiles.
]
].
self evaluateFilter.
].
!
updateDirectoryContentsTaskRestart
self updateDirectoryContentsTaskStop.
self updateDirectoryContentsTaskStart.
!
updateDirectoryContentsTaskStart
|p|
self directory notNil ifTrue:[
p := [
[
[true] whileTrue:[
(contentsBrowser shown and:[self directory notNil]) ifTrue:[
self updateDirectoryContentsTaskCycle.
Processor yield.
].
Delay waitForSeconds:1.0
]
] valueNowOrOnUnwindDo:[
self updateDirectoryContentsTask:nil.
self updateColumnsTaskStop.
]
] newProcess.
"/ p priority:(Processor systemBackgroundPriority).
p priorityRange:(Processor userBackgroundPriority to:Processor activePriority).
self updateDirectoryContentsTask:p.
p name:('DirectoryContentsBrowser update contents[', self directory baseName, ']').
p resume.
]
!
updateDirectoryContentsTaskStop
|task|
(task := self updateDirectoryContentsTask) notNil ifTrue:[
self updateDirectoryContentsTask:nil.
Object errorSignal handle:[:ex|
Dialog warn:ex description.
]do:[
task isDead ifFalse:[
task terminateWithAllSubprocessesInGroup.
task waitUntilTerminated.
]
]
].
! !
!DirectoryContentsBrowser::DirectoryContentsItem class methodsFor:'instance creation'!
fileName:aFilename
| instance fileItem|
instance := self new.
aFilename asString = '..' ifTrue:[
instance fileName:aFilename.
^ instance.
].
fileItem := DirectoryContents contentsItemForFileName:aFilename.
fileItem notNil ifTrue:[^ self forInfoItem:fileItem].
^ nil
"
DirectoryContentsItem fileName:'..'
"
!
forInfoItem:anItem
| instance |
instance := self new.
instance fileName:anItem fileName.
anItem isRemoteDirectory ifTrue:[
instance beRemoteDirectory.
] ifFalse:[
instance fileInfo:anItem info.
].
^ instance
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'accessing'!
fileInfo:something
"set the value of the instance variable 'fileInfo' (automatically generated)"
fileInfo := something.
!
fileName
"returns the fileName
"
^ fileName
!
fileName:aFilename
"set fileName for instance
"
fileName := aFilename.
!
fileType
"returns the type of the file
"
^ fileType
!
fileType:aType
"returns the type of the file
"
fileType := aType.
!
icon
"returns the icon assigned to the file
"
^ icon
!
icon:anIcon
icon := anIcon.
!
iconKey
"return the value of the instance variable 'iconKey' (automatically generated)"
iconKey isNil ifTrue:[
self isRemoteDirectory ifTrue:[
iconKey := FileBrowser iconKeyForRemoteDirectory:fileName.
] ifFalse:[
iconKey := FileBrowser iconKeyForFile:fileName.
]
].
^ iconKey
!
isDirectory
self isRemoteDirectory ifTrue:[^ true].
self getFileInfo.
fileInfo isNil ifTrue:[^ false].
^ fileInfo isDirectory
!
isSymbolicLink
self isRemoteDirectory ifTrue:[^ false].
self getFileInfo.
fileInfo isNil ifTrue:[^ false].
^ fileInfo isSymbolicLink
!
lastButOneSuffix
"returns the suffix of the file
"
^ self suffixes at:2
!
lastSuffix
"returns the suffix of the file
"
^ self suffixes at:1
!
mimeType
"return the value of the instance variable 'mimeType' (automatically generated)"
mimeType isNil ifTrue:[
mimeType := MIMETypes mimeTypeForFilename:(self fileName).
mimeType isNil ifTrue:[
mimeType := #unknown
]
].
^ mimeType
!
preview
^ preview
!
preview:aLabel
preview := aLabel.
!
suffix
"returns the suffix of the file
"
suffix isNil ifTrue:[
(OperatingSystem isUNIXlike and:[(self baseName at:1) == $.]) ifTrue:[
suffix := ''.
] ifFalse:[
suffix := fileName suffix.
]
].
^ suffix
!
suffixes
| lastSuff lastButOneSuff|
(fileName name occurrencesOf:$.) <= 1 ifTrue:[
^ Array with:(self suffix) with:nil.
].
(fileName baseName occurrencesOf:$.) <= 1 ifTrue:[
^ Array with:(self suffix) with:nil.
].
((lastSuff := self suffix) isEmpty) ifTrue:[
lastSuff := nil.
] ifFalse:[
lastSuff := lastSuff asLowercase.
].
((lastButOneSuff := fileName withoutSuffix suffix) isEmpty) ifTrue:[
lastButOneSuff := nil.
] ifFalse:[
lastButOneSuff := lastButOneSuff asLowercase.
].
(lastSuff notNil and:[lastButOneSuff notNil]) ifTrue:[
(lastSuff = 'bak' or:[lastSuff = 'sav']) ifTrue:[
lastSuff := lastButOneSuff.
lastButOneSuff := nil.
]
].
^ Array with:lastSuff with:lastButOneSuff
!
type
"returns the type of the file
"
^ self valueAt:#type
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'actions'!
resetImageFile
" if the image preview extent is changed the icon will set to nil to force the update task to reload the image "
(mimeType notNil and:[ mimeType isImage]) ifTrue:[
preview := nil
]
!
resetItemForChanges
" dont know what someone else is doing with the file - read all item properties new "
fileInfo := nil.
icon := nil.
fileType := nil.
preview := nil.
owner := nil.
group := nil.
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'change queries'!
hasBeenModified
"check if item modification time is changed
"
| time info|
self isRemoteDirectory ifTrue:[^ false].
info := fileName info.
info isNil ifTrue:[ ^ false].
time := info modificationTime.
contentsBrowserChangeModificationTime isNil ifTrue:[
contentsBrowserChangeModificationTime := time.
fileInfo := nil.
^ false.
].
((contentsBrowserChangeModificationTime = time) not) ifTrue:[
contentsBrowserChangeModificationTime := time.
fileInfo := nil.
^ true
].
^ false
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'compare'!
= aItem
"/ Transcript showCR:(aItem species == self species).
aItem species == self species ifFalse:[ ^ false].
aItem isNil ifTrue:[ ^ false].
^ (self fileName = aItem fileName)
!
hash
^ fileName hash
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'presentation'!
baseName
"returns the baseName of the file
"
^ fileName baseName.
!
baseName:aName
"rename the file
"
^ self
!
baseNameWithOutSuffix
"returns the baseName of the file
"
| baseNameWithOutSuff |
baseNameWithOutSuff := self baseName asFilename withoutSuffix asString.
baseNameWithOutSuff isEmpty ifTrue:[
^ self baseName
].
^ baseNameWithOutSuff.
!
date
"returns the modTimeString
"
| modTime |
modTime := self modificationTime.
modTime isNil ifTrue:[
^ '???'
].
^ modTime asDate printString.
!
fileInfoString
"get stat info on selected file - return a string which can be
shown in a box"
| afileType |
fileName isNil ifTrue:[^ nil].
afileType := self fileType.
afileType isNil ifTrue:[
^ ''.
].
^ afileType
!
fileSize
"returns the fileSize
"
self getFileInfo.
fileInfo isNil ifTrue:[^ nil].
^ fileInfo fileSize
!
group
"returns the printable group
"
|gid|
group isNil ifTrue:[
self getFileInfo.
fileInfo isNil ifTrue:[^ '???'].
gid := fileInfo gid.
(LastGIDToGroupNameMapping notNil and:[gid == LastGIDToGroupNameMapping key]) ifTrue:[
group := LastGIDToGroupNameMapping value
] ifFalse:[
group := OperatingSystem getGroupNameFromID:gid.
LastGIDToGroupNameMapping := gid -> group.
]
].
^ group
!
modificationTime
"returns the absolute time of modification
"
self getFileInfo.
fileInfo isNil ifTrue:[^ nil].
^ fileInfo modificationTime
!
owner
"returns the printable owner
"
|uid|
owner isNil ifTrue:[
self getFileInfo.
fileInfo isNil ifTrue:[^ '???'].
uid := fileInfo uid.
(LastUIDToUserNameMapping notNil and:[uid == LastUIDToUserNameMapping key]) ifTrue:[
owner := LastUIDToUserNameMapping value
] ifFalse:[
owner := OperatingSystem getUserNameFromID:uid.
LastUIDToUserNameMapping := uid -> owner.
]
].
^ owner
!
permissions
"returns the permissions as printable string
"
|mode permissionString|
self getFileInfo.
fileInfo isNil ifTrue:[^ '???'.].
mode := fileInfo mode.
permissionString := String new:9 withAll:$-.
1 to:9 by:3 do:[:i|
(mode bitAt:i ) == 1 ifTrue:[permissionString at:10 - i put:$x].
(mode bitAt:i + 1) == 1 ifTrue:[permissionString at:9 - i put:$w].
(mode bitAt:i + 2) == 1 ifTrue:[permissionString at:8 - i put:$r].
].
^ permissionString
!
printString
^ 'a DirectoryContentsItem [', fileName asString, ']'
!
sizeString
"returns the size of the file
"
| unitString n locSize|
unitString := ''.
locSize := self fileSize.
locSize isNil ifTrue:[^ '???'].
locSize < (500 * 1024) ifTrue:[
locSize < 1024 ifTrue:[
n := locSize
] ifFalse:[
n := (locSize * 10 // 1024 / 10.0).
unitString := ' Kb'
]
] ifFalse:[
n := (locSize * 10 // 1024 // 1024 / 10.0).
unitString := ' Mb'
].
^ (n printStringLeftPaddedTo:5) , unitString.
!
timeAndDate
"returns the date
"
|modTime|
modTime := self modificationTime.
modTime isNil ifTrue:[
^ '???'
].
Smalltalk languageTerritory == #us ifTrue:[
^ modTime printStringFormat:'%(ShortMonthName), %(dayPadded) %(yearOrTime)'.
].
^ modTime printStringFormat:'%(day)-%(ShortMonthName) %(yearOrTime)'.
"/ ^ modTime printStringFormat:'%(year)-%(mon)-%(day) %h:%m:%s'.
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'private'!
getFileInfo
fileInfo isNil ifTrue:[
self isRemoteDirectory ifTrue:[
"/ do not access, to avoid automount
] ifFalse:[
fileInfo := fileName linkInfo.
fileInfo isNil ifTrue:[
fileInfo := fileName info.
].
].
].
^ fileInfo
! !
!DirectoryContentsBrowser::DirectoryContentsItem methodsFor:'queries'!
beRemoteDirectory
fileType := #remoteDirectory.
!
exists
"returns the fileName
"
^ fileName exists
!
hasMimeType
^ (self mimeType ~= #unknown)
!
isRemoteDirectory
^ fileType == #remoteDirectory
!
mimeTypeForContents
mimeTypeForContents isNil ifTrue:[
mimeTypeForContents := MIMETypes mimeTypeOfContents:(self fileName).
mimeTypeForContents isNil ifTrue:[
mimeTypeForContents := #unknown
] ifFalse:[
" set mimeType to mimeType of contents if a better mimeType is found "
mimeType := mimeTypeForContents.
iconKey := mimeTypeForContents.
]
].
^ mimeTypeForContents
! !
!DirectoryContentsBrowser class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libtool/DirectoryContentsBrowser.st,v 1.24 2002-10-15 16:43:04 cg Exp $'
! !