AbstractFileBrowser.st
author Claus Gittinger <cg@exept.de>
Mon, 11 Nov 2002 10:37:33 +0100
changeset 4230 805e8d4b4ec7
parent 4213 b8e7d4276a33
child 4250 5637f9e6c683
permissions -rw-r--r--
added make.

"{ Package: 'stx:libtool' }"

ApplicationModel subclass:#AbstractFileBrowser
	instanceVariableNames:'aspects'
	classVariableNames:'DirectoryHistory DefaultCommandPerMIME RuntimeAspects
		DirectoryBookmarks LastEnforcedNameSpace CommandHistory
		DefaultCommandPerSuffix CommandHistorySize LastFileDiffFile
		DefaultFilters'
	poolDictionaries:''
	category:'Interface-Tools-File'
!

AbstractFileBrowser class instanceVariableNames:'DisabledCursorImage EnabledCursorImage'

"
 The following class instance variables are inherited by this class:

	ApplicationModel - ClassResources
	Model - 
	Object - 
"
!

Object subclass:#Clipboard
	instanceVariableNames:'method files'
	classVariableNames:''
	poolDictionaries:''
	privateIn:AbstractFileBrowser
!

Object subclass:#CodeExecutionLock
	instanceVariableNames:'locked'
	classVariableNames:''
	poolDictionaries:''
	privateIn:AbstractFileBrowser
!

OrderedCollection subclass:#DirectoryHistory
	instanceVariableNames:'forwardList backList lastWasForwardPath lastBackPath lastAddPath'
	classVariableNames:'HistorySize'
	poolDictionaries:''
	privateIn:AbstractFileBrowser
!

Object subclass:#DirectoryHistoryItem
	instanceVariableNames:'path position'
	classVariableNames:''
	poolDictionaries:''
	privateIn:AbstractFileBrowser::DirectoryHistory
!

OrderedSet subclass:#FilenameHistory
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:AbstractFileBrowser
!

Object subclass:#SaveAspectItem
	instanceVariableNames:'value isHolder'
	classVariableNames:''
	poolDictionaries:''
	privateIn:AbstractFileBrowser
!


!AbstractFileBrowser class methodsFor:'classAccess'!

directoryHistoryClass

    ^ AbstractFileBrowser::DirectoryHistory
!

filenameHistoryClass

    ^ FilenameHistory
! !

!AbstractFileBrowser class methodsFor:'classVarAccess'!

directoryHistory

    DirectoryHistory isNil ifTrue:[
	DirectoryHistory := self directoryHistoryClass new.
"/        DirectoryHistory inspect.
    ].
    ^ DirectoryHistory
!

resetClassVars

    DirectoryHistory := nil.

"
    AbstractFileBrowser resetClassVars
"
! !

!AbstractFileBrowser class methodsFor:'defaults'!

commandHistory

    CommandHistory isNil ifTrue:[
	CommandHistory := OrderedCollection new.
    ].
    ^ CommandHistory
!

commandHistorySize

    "max no of entries in the HistoryList "
    CommandHistorySize isNil ifTrue:[
	CommandHistorySize := 50
    ].
    ^ CommandHistorySize
!

defaultCommandPerMIME

    DefaultCommandPerMIME isNil ifTrue:[
	self initializeDefaultCommands
    ].
    ^ DefaultCommandPerMIME
!

defaultFilterList

    DefaultFilters isNil ifTrue:[
	DefaultFilters := #(        '*'
				    '*.st' 
				    '*.htm*' 
				    '*.txt' 
				    '*.gif' 
				    '*.xpm' 
				    '*.jpg' 
				    '*.[h,c]*' 
				)
    ].
    ^ DefaultFilters.
!

directoryBookmarks

    DirectoryBookmarks isNil ifTrue:[                     
	DirectoryBookmarks := OrderedCollection new.
	DirectoryBookmarks add:Filename homeDirectory asAbsoluteFilename.
	DirectoryBookmarks add:Filename tempDirectory.
	DirectoryBookmarks add:Filename currentDirectory asAbsoluteFilename.
	Smalltalk systemPath do:[:path |
	    ((path ~= '.') and:[path asFilename exists]) ifTrue:[
		DirectoryBookmarks add:path asFilename.
	    ]
	]
    ].
    ^ DirectoryBookmarks

"/    DirectoryBookmarks := nil
!

initializeDefaultCommands
    DefaultCommandPerMIME := Dictionary new.

    DefaultCommandPerMIME at:'application/x-tar-compressed' put:'gunzip < %1 | tar tvf -'.
    DefaultCommandPerMIME at:'application/pdf'              put:'acroread -display %2 %1'.

    "
     self initializeDefaultCommands
    "
!

listOfRuntimeValuesToRemark

    " list of all aspects that will be saved after close of FileBrowserV2"

    ^ #(
           #rootHolder
           #filterModel
           #enableFileHistory
           #fileHistory
           #currentFileNameHolder
           #currentSortOrder
           #sortBlockProperty
      )
!

resetAspects

    RuntimeAspects := nil.

"
    self resetAspects
"
!

runtimeAspects

    RuntimeAspects isNil ifTrue:[
	RuntimeAspects := Dictionary new.
    ].
    ^ RuntimeAspects
!

userPreferencesAspectList

    " list of all aspects that will be saved with save settings
      that aspects will be image consistent if the settings are saved in Launcher
      dont forget to add a access methos in Userpreferences if you add a aspect here
    "

    ^ #(
           #viewDirsInContentsBrowser
           #showDirectoryTree  
           #showHiddenFiles          
           #viewDescription        
           #viewDetails              
           #viewDirectoryDescription
           #viewFilesInDirectoryTree
           #viewGroup                
           #viewOwner                
           #viewPermissions          
           #viewPreview              
           #viewSize                
           #viewTime                 
           #viewType  
           #openMultipleApplicationsForType
           #filenameEntryFieldVisibleHolder
           #toolBarVisibleHolder
           #sortDirectoriesBeforeFiles
           #openAlwaysInTextEditor
           #sortCaseless
      )
! !

!AbstractFileBrowser class methodsFor:'image'!

DisabledCursorImage

    DisabledCursorImage isNil ifTrue:[
	DisabledCursorImage := Image fromFile:'xpmBitmaps/cursors/no_entry.xpm'
    ].
    ^ DisabledCursorImage
!

EnabledCursorImage

    EnabledCursorImage isNil ifTrue:[
	EnabledCursorImage := Image fromFile:'xpmBitmaps/cursors/double_crossHair.xpm'
    ].
    ^ EnabledCursorImage
! !

!AbstractFileBrowser class methodsFor:'image specs'!

clearHistoryIcon
    ^ Icon deleteIcon
!

closeIcon
    "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 closeIcon inspect
     ImageEditor openOnClass:self andSelector:#closeIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class closeIcon'
	ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ H@@@@@@@@@@@@B@ @@@@@@@@@@@@HB@ @@@@@@@@@B@ H@@@@@@@@@@@@@@ HB@@@@@@@B@ H@@@@@@@@@
@@@@@@@B@ H@@@@B@ H@@@@@@@@@@@@@@@@@@@HB@ @B@ H@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@B@ H@@@@@@@@@@@@@@@@@
@@@@@@@B@ HB@ @@@@@@@@@@@@@@@@@@@@@B@ H@@ HB@@@@@@@@@@@@@@@@@@@B@ H@@@@B@ H@@@@@@@@A@@@@@@@B@ H@@@@@@@HB@ @@@@@@@@@@@@@B
@ H@@@@@@@@@@ HB@@@@@@@@@@@@@ H@@@@@@@@@@@@B@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@PD@@P@@
@@DA@@@@@PD@@@DA@@@@@P@@@@D@@@D@@@D@@P@@@@D@@@D@@@D@@@@A@@@A@@@A@@@A@@@A@PDA@@@A@@@@@P@@@P@@@P@@@@D@@P@@@@@@@@DA@@DA@@@A
@P@@@PD@@@@A@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[255 255 255 0 0 0 255 0 0]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@A C@A0G@@8N@@\\@@N8@@G0@@C @@G0@@N8@@\\B@8N@A0G@A C@@@@@A@@@MFL0QIQHQII8QIE@M&X0@@@@') ; yourself); yourself]
!

copyIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary copy20x20Icon "copy28x28Icon"
!

cutIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary cut20x20Icon2 "cut28x28Icon"
!

deleteIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary erase20x20Icon "/ delete28x28Icon
!

diffIcon
    "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 diffIcon inspect
     ImageEditor openOnClass:self andSelector:#diffIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class diffIcon'
	ifAbsentPut:[(Depth8Image new) width: 26; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@A@PDA@PDA@PD@@@@@@@@@@@@@@@@@@@@@@@DA XFA XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA XF@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@XFA @F
A XD@@@@@@@@@@@@@@@@@@@@@@@DA X@A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA @FA XFA@@@@@@@@@@@@@@@@@@@@@@@A@XF@@XFA XD@@@@@@@@@@@@
@@@@@@@@@@@DA X@A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA X@A XFA@@@@@@@@@@@@@@@@@@@@@@@A@XFA X@@@@@@@@@@@@@@@@@@@@@@@@@@@@DA XF
A XFA P@@@@@@@@@@@@@@@@@@@@@@@PFA XFA XFA@@@@@@@@@@@@@@@@@@@@@@@A@PDA@PDA@PD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 129 129 129 0 0 0 194 194 194 132 132 132 198 198 198 255 255 255]; mask:((Depth1Image new) width: 26; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@?8@@@O>@@@C? @@@?<@@@O> @@C?(@@@?:@@@O> @@C?8@@@??@@@O>8@@C?''@@@?80@@@@@@@@T[@@@DI@@@GSX@@BT$@@@%I@@@IRP@@A4$@@@@@@@@@@a') ; yourself); yourself]
!

fileInIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary fileIn20x20Icon3
!

goHomeIcon
    "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 goHomeIcon inspect
     ImageEditor openOnClass:self andSelector:#goHomeIcon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class goHomeIcon'
	ifAbsentPut:[(Depth4Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(4 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@DQ@@@@@@@@@@@@DQDP@@@@@@@@@@DQ@QD@@@@@@@@@DQH2DQ@@@@@@@@DQH4L!!DP@@@@@@DQH4QCHQD@@@@@
DQH4QDP2DQ@@@@DQH4QDQDL!!DP@@DQH4QDQDQCHQD@D"H4QBH"ADP0@A@RH#QBH"H QC@@D@@@MDIUUUADL@@@@@@4P%UUTDP0@@@@@CQBUUUPQC@@@@@@MD
IUUUADL@@@@@@4P%UUTDP0@@@@@CQBUUUPQC@@@@@@MDIUUUADL@@@@@@4P%UUTDP0@@@@@@@@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 192 0 0 64 0 0 128 128 128 192 192 192 100 128 255]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@A@@@C @A''0@A/8@A?<@A?>@A??@C?? G??0O??8_??<_??<_??<C?? C?? C?? C?? C?? C?? C?? C?? C?? ') ; yourself); yourself]
!

hexToggle22x22Icon
    "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 hexToggle22x22Icon inspect
     ImageEditor openOnClass:self andSelector:#hexToggle22x22Icon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class hexToggle22x22Icon'
	ifAbsentPut:[(Depth8Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@AP@@@@T@@@@EAP@@@@@@@@@@
@@@@@@TEAP@E@@TEAPT@@@@@@@@@@@@@@@@EAP@@AP@@APTE@@@@@@@@@@@@@@@@APTE@@T@APTEAP@@@@@@@@@@@@@@@@T@@@@E@@TEAPT@@@@@@@@@@@@@
@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@AP@@@@T@@@@EAP@@@@@@@@@@@@@@@@T@AP@E@@T@APT@@@@@@@@@@@@@@@@E@@@@AP@@@@TE@@@@@@@@@@@@@@@@
AP@E@@T@AP@EAP@@@@@@@@@@@@@@@@T@AP@E@@@@APT@@@@@@@@@@@@@@@@EAPTEAPTEAPTE@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 105 133 190 129 129 129 194 194 194 255 0 0 255 255 255]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@A?>@@@@@B''Q@B$J@C&D@B$J@B''Q@') ; yourself); yourself]
!

historyIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary history20x20Icon "/ history28x28Icon
!

homeIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary home28x28Icon
!

htmlReloadIcon
    "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 htmlReloadIcon inspect
     ImageEditor openOnClass:self andSelector:#htmlReloadIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class htmlReloadIcon'
	ifAbsentPut:[(Depth2Image new) width: 22; height: 22; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@UT@@@@@EU@D@@@@UT@@@H@AUP@@@@@EU@@@@@@EU@@@@E@EU@@@@@@EU@@@@@AUUT@@@@@UUP@@@@@EU@@@@@@AT@@@@@@@P@@@@H@@@@@@@@
@@@@@@@@@@@@@@@H@@@@@@@@@@@@@@@G@@@@@@@J@@@@@@@I@@@@@@@@') ; colorMapFromArray:#[0 0 0 0 129 0]; mask:((Depth1Image new) width: 22; height: 22; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@G<C@_?C@??#A?C3C>@;G<@KG<@CG<@C??$C_?NCO>_CG<?#C9?3A3?;@''??@@?#P@?C\A?COC>CG?<CC?8C@? C') ; yourself); yourself]
!

leftArrow
    "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 leftArrow inspect
     ImageEditor openOnClass:self andSelector:#leftArrow
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftArrow'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@A@0D@@@@@@@@@@@@@@@@@@@@@@@@@@@DDAPH@@@@@@@@@@@@@@@@@@@@@@@@@@PX@A0D@@@@@@@@@@@@@@@@@@@@@@@@AB@@IB HK
@0LA@PDK@@@@@@@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@@@@@@@PX@@ALTEP8PDQDVE0\R@@@@@@@@@@@AAADQD1PUEQTNF@$SFP(R@@@@@@@@@@@KB!!P[
GAPUEQT]GQ4]GP(R@@@@@@@@@@@@D (TG!!0TEA,_G1<[H@(R@@@@@@@@@@@@@AHJC!!< GQ4JB (JB"DK@@@@@@@@@@@@@@@RB 8^B DRD!!HRD!!HK@@@@@@@@
@@@@@@@@D (]H H@@@@@@@@@@@@@@@@@@@@@@@@@@AHJHPD@@@@@@@@@@@@@@@@@@@@@@@@@@@@K@PH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B0D@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@,@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@B@@@F@@@N@@@^@@@>@@A??@C??@G??@O??@O??@G??@C??@A??@@>@@@^@@@N@@@F@@@B@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
!

leftArrow20x20Icon
    "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 leftArrow20x20Icon inspect
     ImageEditor openOnClass:self andSelector:#leftArrow20x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftArrow20x20Icon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@@HB@ HB@ HB@ HB@ HB@ HB@ @@@ HB@ HB@ HB@ HB@ HB@ H@@ @B@ HB@ HB@ HB@ HB@ HB@@HA
@@HB@ HB@ HB@ HB@ HB@ @B@PD@@ HB@ HB@ HB@ HB@ H@@ DA@P@@@@@@@@@@@ HB@ HB@@HA@PDA@ HB@ HB@ @B@ HB@ @B@PDA@PDA@PDA@PDB@@HB
@ H@@ DA@PDA@PDA@PDA@PH@@ HB@ @B@PDA@PDA@PDA@PDA@ @B@ HB@ @B@PDA@PDA@PDA@PDB@@HB@ HB@ @B@PDA@PHB@ HB@ H@@ HB@ HB@ @B@PDA
@@@@@@@@@@@B@ HB@ HB@ @B@PD@@ HB@ HB@ HB@ HB@ HB@ @B@P@B@ HB@ HB@ HB@ HB@ HB@ @B@@HB@ HB@ HB@ HB@ HB@ HB@ @@@ HB@ HB@ HB
@ HB@ HB@ HB@ @B@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ @a') ; colorMapFromArray:#[0 0 0 100 128 255 128 128 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@M@B@@@F@J@N@@@^@J@>@@A??@C??@G??OO??@O??@G??@C??@A??E@>@H@^@@@N@@@F@N@B@A@@@@') ; yourself); yourself]
!

leftArrow20x20PlusMenuIcon
    "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 leftArrow20x20PlusMenuIcon inspect
     ImageEditor openOnClass:self andSelector:#leftArrow20x20PlusMenuIcon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftArrow20x20PlusMenuIcon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@A@ @@@@@@@@@@@@@@@@@@@@@@@PLA@@@@@@@@@@@@@@@@@@@@@@DD
APH@@@@@@@@@@@@@@@@@@@@AA @G@P@@@@@@@@@@@@@@@@@@@P @BP(BB0LC@PDAB0@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@AA @@D1PUC!!@QDQXWA1H@
@@@@@PPQDQLTEQTUC!! ID1$JD @@@@@KB!!P[GAPUEQT]GQ4]GP(R@@@@@@@RB!!P^GAPTF1<_G1, B!!H@@@@@@@@RB 8_HA4]B (JB (!!B0@@@@@@@@@RB 8^
B DRD!!HRD!!HK@@@@@@@@@@@RB!!4"@ @@@@@@@@@@@@@@@@@@@@@RB"DA@@@@@@@@@@@KB0,KB0,K@@@K@PH@@@@@@@@@@@@KB0,KB0@@@@@K@P@@@@@@@@@@
@@@KB0,@@@@@@@@K@@@@@@@@@@@@@@@K@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A@@@C@@@G@@@O@@@_@@@?? A?? C?? G?? G?? C?? A?? @?? @_@@@O@@?''@@_C@@NA@@D@@@') ; yourself); yourself]
!

leftArrowIcon
    ^ self leftArrow20x20Icon
!

leftArrowPlusMenu
    "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 leftArrowPlusMenu inspect
     ImageEditor openOnClass:self andSelector:#leftArrowPlusMenu
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftArrowPlusMenu'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@A@0D@@@@@@@@@@@@@@@@@@@@@@@@@@@DDAPH@@@@@@@@@@@@@@@@@@@@@@@@@@PX@A0D@@@@@@@@@@@@@@@@@@@@@@@@AB@@IB HK
@0LA@PDK@@@@@@@@@@@@@@DL@@@MC <P@@@@DPLR@@@@@@@@@@@@@PX@@ALTEP8PDQDVE0\R@@@@@@@@@@@AAADQD1PUEQTNF@$SFP(R@@@@@@@@@@@KB!!P[
GAPUEQT]GQ4]GP(R@@@@@@@@@@@@D (TG!!0TEA,_G1<[H@(R@@@@@@@@@@@@@AHJC!!< GQ4JB (JB"DK@@@@@@@@@@@@@@@RB 8^B DRD!!HRD!!HK@@@@@@@@
@@@@@@@@D (]H H@@@@@@@@@@@@@@@@@@@@@@@@@@AHJHPD@@@@@@@@@@@@@@@@@@@@@@@@@@@@K@PH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B0D@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@,@@@@@@@@KB0,KB0,K@@@@@@@@@@@@@@@@@@@@@@@@B0,KB0,@@@@@@@@@@@@@@@@@@@@@@@@@@@,KB0@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@K@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 32 96 32 64 96 96 128 160 64 96 128 128 160 192 32 96 128 128 160 160 160 192 224 0 96 128 0 0 0 128 128 160 64 192 192 32 160 192 64 128 192 128 192 224 192 224 224 0 0 32 96 192 224 0 160 192 0 128 192 160 224 224 96 160 192 128 192 192 64 160 192 192 192 192 32 192 192 0 192 224 0 128 160 32 192 224 64 192 224 0 192 192 0 64 96 0 64 128]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@B@@@F@@@N@@@^@@@>@@A??@C??@G??@O??@O??@G??@C??@A??@@>@@@^@@@N@@@F@@@BA?@@@>@@@\@@@H@@@@') ; yourself); yourself]
!

leftDownIcon
    "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 leftDownIcon inspect
     ImageEditor openOnClass:self andSelector:#leftDownIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftDownIcon'
	ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
UUUUUUUUUUUPAUUUUUUUP@UUUUUUUPB!!UUUUUU@B*AUUUUU@B*(UUUUUPB** UUUUPB***AUUUTB***(EUUUB****%UUUR*****UUUUU@*%UUUUUUPJ)UUUU
UUTB*UUUUUUU@*%UUUUUUPJ)UUUUUUTB*UUUUUUU@*%UUUUUUPJ)UUUUUUTB*UUUUUUU@*$@@@@AUPJ*****)UTB******UU@******%UPJ*****)UTAUUUU
UUUU@@@@@@@AUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 40 40 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@ @@@@\@@@@O @@@G<@@@C? @@A?<@@@?? @@_?<@@G?? @@C<@@@@?@@@@O0@@@C<@@@@?@@@@O0@@@C<@@@@?@@@@O0@@@C??? @???8@O?
?>@C??? @???8@O??>@@@@@@@@@@@@@a') ; yourself); yourself]
!

leftIcon
    "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 leftIcon inspect
     ImageEditor openOnClass:self andSelector:#leftIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class leftIcon'
	ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPUUUUUUUUPUUUUUUUUP%UUUUUUUP)UUUUUUUP*P@@@@@AP*$@@@@@@P*******
*P********$********)J********U********%V*%UUUUUUUZ)UUUUUUUP*UUUUUUUUV%UUUUUUUUYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 40 40 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@H@@@@F@@@@C @@@A8@@@@>@@@@_???0O???<G????C????0_???<C????@_???0C8@@@@^@@@@C @@@@X@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
!

makeIcon
    "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 makeIcon inspect
     ImageEditor openOnClass:self andSelector:#makeIcon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
        constantNamed:#'AbstractFileBrowser class makeIcon'
        ifAbsentPut:[(Depth8Image new) width: 22; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@XF@@@@@@@@@@@@@@@@@@@FA X@@@XJB X@@@@FA @@@@@@@@@FB (JA XJB (JA XEB \F@@@@@@@@A (JB (JB (JB (JB (GA @@@@@@
@@DAB (JB (JB (JB (GAPT@@@@@A XFA XJB (GAPDAB (JAPTFA X@A \JB (JB (GAPD@@@DJB (JB (JA XJB (JB (JA0DEA0DAB (JB (JB TAA XF
B (JB (EAPTEA0(JB TEAPTA@PDA@PXJB (JB (JB (JB TE@PDA@PDA@PXJB (JB (JB (JB (JA0TA@PD@@PXJB (JB (JB (JB (JB (JA D@@@HDB (J
@ HJB (JB PDA@(JB X@@@@@@P\G@PDAA (JB XA@PDFA XA@@@@@@DA@PDA@PXJB (F@PDA@PDA@P@@@@@A@PDA@PDFA0(GA D@@PDA@PD@@@@@@@DA@P@@
@PXFA D@@@@A@PD@@@@@@@@@@@@@@@DA@PDA@@@@@@@@@@@@@@@@@@@@@@@A@PDA@P@@@@@@@@@@@@@@@@@@@@@@@@DA@P@@@@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 48 48 48 56 59 56 64 68 64 88 92 88 128 128 128 160 160 160 192 192 192 216 219 216 239 244 239 248 252 248]; mask:((Depth1Image new) width: 22; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@C@@C''#@G?? G?? G?? _??8???<???<???<???<???<_??8_??0O??0O??0O?70GO# @O @@O @@G@@') ; yourself); yourself]
!

menuHistoryList9x20Icon
    "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 menuHistoryList9x20Icon inspect
     ImageEditor openOnClass:self andSelector:#menuHistoryList9x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class menuHistoryList9x20Icon'
	ifAbsentPut:[(Depth1Image new) width: 9; height: 20; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A0@G@@\@A0@G@@\@A0@G@@\@A0@G@A?@C8@G@@H@G<@@@@@@@@a') ; colorMapFromArray:#[255 255 255 0 0 0]; mask:((Depth1Image new) width: 9; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@A0@G@@\@A0@G@@\@A0@G@@\@A0@G@A?@C8@G@@H@G<@@@@@@@@a') ; yourself); yourself]
!

menuHistoryListIcon
    "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 menuHistoryListIcon inspect
     ImageEditor openOnClass:self andSelector:#menuHistoryListIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class menuHistoryListIcon'
	ifAbsentPut:[(Depth1Image new) width: 12; height: 12; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??S?<O?0??C?<O?0??/?=_?0??C?<O?0') ; colorMapFromArray:#[255 255 255 0 0 0]; mask:((Depth1Image new) width: 12; height: 12; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@O@@<@C0A?8C?@G8@O@@X@@@A?8@@@') ; yourself); yourself]
!

newDirectory20x20Icon
    "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 newDirectory20x20Icon inspect
     ImageEditor openOnClass:self andSelector:#newDirectory20x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class newDirectory20x20Icon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PDA@PDA@P@@@@@@@@@@@@@@@@@A@ HB@ HA@@@@@@@@@@@@@@@@@PHB@ HB@ HA
@@@@@@@@@@@@@@DA@PDA@PDA@P@@@@@@@@@@@@D@@PHB@ HB@ HB@ HB@@@@@ HB@P@A@ HB@ HB@ HB@ @B@@H@@ HA@@DB@ HB@ HB@ H@@ H@@ H@@ D@
@PHB@ HB@ HB@@HB@ @B@ H@@P@A@ HB@ HB@ HB@ HB@ HB@ HA@@DB@ HB@ HB@ HB@ HB@ HB@ D@@PHB@ HB@ HB@ HB@ HB@ HB@P@A@ HB@ HB@ HB
@ HB@ HB@ HA@@DB@ HB@ HB@ HB@ HB@ HB@ D@@PHB@ HB@ HB@ HB@ HB@ HB@P@A@ HB@ HB@ HB@ HB@ HB@ HA@@DA@PDA@PDA@PDA@PDA@PDA@PD@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[255 0 0 0 0 0 255 255 0]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@DQ@O:R@O9T@_<8@??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? @@@@@@@@') ; yourself); yourself]
!

pasteIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary paste20x20Icon "/ paste28x28Icon
!

rightArrow
    "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 rightArrow inspect
     ImageEditor openOnClass:self andSelector:#rightArrow
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class rightArrow'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@0PB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PTF@ @@@@@@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@@@@@@A@PDA@PDH@P\I
@@XB@@@@@@@@@@@@@@@AA0(@@@@@B ,LB @D@ @@@@@@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@@@@@@@@M@@TTEQLQE!!\WD 0K@@PB@@@@@@@@@@@MB <W
E1\WD!!\WD!!LYDQ(B@@@@@@@@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@@@@@@AA!!(ZF!!(ZE1H^FQDZ@ @@@@@@@@@@@@@A@ HB@ HB@1DYDQ(B@@@@@@@@@@@@
@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@@@@@@@0PZ@ @@@@@@@@@@@@@@@@@@@@@@@@@@@Q(B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0H@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@D@@@F@@@G@@@G @@G0@O?8@O?<@O?>@O??@O??@O?>@O?<@O?8@@G0@@G @@G@@@F@@@D@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
!

rightArrow20x20Icon
    "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 rightArrow20x20Icon inspect
     ImageEditor openOnClass:self andSelector:#rightArrow20x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class rightArrow20x20Icon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ H@@ HB@ HB@ HB@ HB@ HB@ HB@ @@@ HB@ HB@ HB@ HB@ HB@ HB@@H@@ HB@ HB@ HB@ HB@ HB@ H@
@PH@@ HB@ HB@ HB@ HB@ HB@ @A@PH@@ HB@ HB@ H@@@@@@@@@@@DA@PH@@ HB@ HB@ @B@ HB@ HB@PDA@PH@@ HB@ HB@@HA@PDA@PDA@PDA@PH@@ HB
@ H@@ DA@PDA@PDA@PDA@PH@@ HB@ @B@PDA@PDA@PDA@PDA@ @B@ HB@@HA@PDA@PDA@PDA@PH@@ HB@ H@@ HB@ HB@ DA@PDB@@HB@ HB@ @@@@@@@@@@
@PDA@ @B@ HB@ HB@ HB@ HB@ @A@PH@@ HB@ HB@ HB@ HB@ HB@@DB@@HB@ HB@ HB@ HB@ HB@ H@@ @B@ HB@ HB@ HB@ HB@ HB@ @@@ HB@ HB@ HB
@ HB@ HB@ HB@@HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ @a') ; colorMapFromArray:#[0 0 0 100 128 255 128 128 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@D@@@F@H@G@@@G @@G0@O?8AO?<@O?>@O??@O??DO?>DO?<@O?8@@G0@@G @@G@@@F@@@D@J@@@@') ; yourself); yourself]
!

rightArrowIcon
    ^ self rightArrow20x20Icon
!

rightArrowPlusMenu
    "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 rightArrowPlusMenu inspect
     ImageEditor openOnClass:self andSelector:#rightArrowPlusMenu
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class rightArrowPlusMenu'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@0PB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PTF@ @@@@@@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@@@@@@A@PDA@PDH@P\I
@@XB@@@@@@@@@@@@@@@AA0(@@@@@B ,LB @D@ @@@@@@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@@@@@@@@M@@TTEQLQE!!\WD 0K@@PB@@@@@@@@@@@MB <W
E1\WD!!\WD!!LYDQ(B@@@@@@@@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@@@@@@AA!!(ZF!!(ZE1H^FQDZ@ @@@@@@@@@@@@@A@ HB@ HB@1DYDQ(B@@@@@@@@@@@@
@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@@@@@@@0PZ@ @@@@@@@@@@@@@@@@@@@@@@@@@@@Q(B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0H@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@P@@@@@@@@@B@ HB@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@@@@HB@ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@D@@@F@@@G@@@G @@G0@O?8@O?<@O?>@O??@O??@O?>@O?<@O?8@@G0@@G @@G@@@F@@@DA?@@@>@@@\@@@H@@@@') ; yourself); yourself]
!

rightArrowPlusMenu20x20Icon
    "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 rightArrowPlusMenu20x20Icon inspect
     ImageEditor openOnClass:self andSelector:#rightArrowPlusMenu20x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class rightArrowPlusMenu20x20Icon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@@@@@@@@@@@@@@@@CA@H@@@@@@@@@@@@@@@@@@@@@@@DE
A H@@@@@@@@@@@@@@@@@@@@@@0\@A@H@@@@@@@@@@@DA@PDA@P AA0$@A H@@@@@@@@@@P\J@@@@@@(KC@(@A@H@@@@@@@@MB \NB ,ODADRD0(@A H@@@@@
@@4@AQPUD1DVE1\RC@,@A@H@@@@@CP(OE1\WE1HWE1HSFQDZ@ @@@@@AB <[D10[GQ8QG!!$QF H@@@@@@@DFF!!(ZF!!(WD!!8YDQ(B@@@@@@@@@PHB@ HB@ LQ
FQDZ@ @@@@@@@@@@@@@@@@@@@QXQF H@@@@@@@@@@@@@@@@@@@@CAA(B@@@@@@@@@@@@@@@@@@@@@@DZ@ @@@ HB@ HB@ @@@@@@@@@@@0H@@@@@@ HB@ H@
@@@@@@@@@@@A@@@@@@@@@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 0 64 96 32 128 160 128 160 192 32 96 128 128 192 192 0 64 64 160 192 192 192 224 224 160 192 224 96 192 224 32 64 96 160 224 224 128 192 224 96 160 192 0 160 192 0 128 192 64 192 192 64 160 192 96 192 192 32 160 192 0 128 160 192 192 192 64 224 224 0 96 128 32 192 192 64 192 224 0 192 224 0 192 192]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@H@@@L@@@N@@@O@@@O @_?0@_?8@_?<@_?>@_?>@_?<@_?8@_?0@@O @@O@@@N_0@LO @HG@@@B@') ; yourself); yourself]
!

rightIcon
    "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 rightIcon inspect
     ImageEditor openOnClass:self andSelector:#rightIcon
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class rightIcon'
	ifAbsentPut:[(Depth2Image new) width: 28; height: 28; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTIUUUUUUUUB%UEUUUUUP*EP@@@@@@J)T@@@@@@B*%B*******
*P********(J********B********P********PEUUUUUV*QEUUUUUP*PUUUUUUTJQUUUUUUUBQUUUUUUUPQUUUUUUUPAUUUUUUUTUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUP@a') ; colorMapFromArray:#[255 255 255 0 0 0 50 50 100 255 0 0]; mask:((Depth1Image new) width: 28; height: 28; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@C@@@@@8@@@@O@@@@C8A????@_???8G????A????0_???<G???>A????@@@@O @@@C0@@@@8@@@@L@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; yourself); yourself]
!

searchIcon
    <resource: #programImage>

    ^ ToolbarIconLibrary search20x20Icon "/ search28x28Icon
    "/ ^ ToolbarIconLibrary search16x16Icon "/ search28x28Icon
!

shellIcon
    <resource: #programImage>

    OperatingSystem isMSDOSlike ifTrue:[
	^ ToolbarIconLibrary dos20x20Icon
    ].
    ^ ToolbarIconLibrary shell20x20Icon
!

shellWithoutTextIcon
    <resource: #programImage>

    OperatingSystem isMSDOSlike ifTrue:[
	^ ToolbarIconLibrary dosWithoutText20x20Icon
    ].
    ^ ToolbarIconLibrary shellWithoutText20x20Icon
!

upArrow
    "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 upArrow inspect
     ImageEditor openOnClass:self andSelector:#upArrow
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class upArrow'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@@@@@@DFA0 DAP@@@@@@@@@@@@@@@@@@@@@@@P$@A0(HA@T@@@@@@@@@@@@@@@@@@@@AB0@@C@4N
C0PE@@@@@@@@@@@@@@@@@@DF@@@LB@ MD@<DAP@@@@@@@@@@@@@@@PLGDQHHD1LHE@8UA@H@@@@@@@@@@@@AE!!\XA@<SD1LHEPPYF DB@@@@@@@@@@D\@Q0A
GA4OD1LJEPD\@Q0A@ @@@@@@@@@@@@@@@!!8^C1T_A@T@@@@@@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@@@@@@E @GDQT_A@T@@@@@@@@@@@@@
@@@@@@@@@P@!!H!!TJA@T@@@@@@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@@@@@@@QXXFPPDF H@@@@@@@@@@@@@@@@@@@@@@ TEAPTE@ H@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@@@@@@@@@@@@@@@@@@@') ; yourself); yourself]
!

upArrow20x20Icon
    "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 upArrow20x20Icon inspect
     ImageEditor openOnClass:self andSelector:#upArrow20x20Icon
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class upArrow20x20Icon'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ @@@ HB@ HB@ HB@ HB@ HB@ H@@ H@@ HB@ HB@ HB@ HB@ HB@@HA
@PH@@ HB@ HB@ HB@ HB@ @B@PDA@PH@@ HB@ HB@ HB@ H@@ DA@PDA@PH@@ HB@ HB@ HB@@HA@PDA@PDA@PH@@ HB@ HB@ @B@PDA@PDA@PDA@PH@@ HB
@ H@@ DA@PDA@PDA@PDA@PH@@ HB@@@@@@@@@ DA@PDB@@@@@@@@@ HB@ HB@ @B@PDA@PH@@ HB@ HB@ HB@ HB@@HA@PDA@ @B@ HB@ HB@ HB@ H@@ DA
@PDB@@HB@ HB@ HB@ HB@ @B@PDA@PH@@ HB@ HB@ HB@ HB@@HA@PDA@ @B@ HB@ HB@ HB@ H@@ HB@ HB@@HB@ HB@ HB@ HB@ @@@@@@@@@@@ HB@ HB
@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ HB@ @a') ; colorMapFromArray:#[0 0 0 100 128 255 128 128 128]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@J@@@@@F@@@O@@@_ O@?0@A?8@C?<@G?>@O??E_??(@?0@@?0@@?0N@?0A@?0@@?0@@?0K@@@A@@@@') ; yourself); yourself]
!

upArrow20x20IconOld
    "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 upArrow20x20IconOld inspect
     ImageEditor openOnClass:self andSelector:#upArrow20x20IconOld
     Icon flushCachedIcons
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class upArrow20x20IconOld'
	ifAbsentPut:[(Depth8Image new) width: 20; height: 20; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DB@@@@@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@PXG
B@PE@@@@@@@@@@@@@@@@@@DI@@\JB@PE@@@@@@@@@@@@@@@AB0@@C@4NC0PE@@@@@@@@@@@@@PX@@@0HB@4PC0PE@@@@@@@@@@DCA1DRBALSBAPNEPPB@@@@
@@@AE!!\XA@<SD1LHEPPYF DB@@@@@Q0AG@D\GP<SD0(U@Q0AG@DB@@@@@@@@@@H^G <UG0PE@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@V@@\Q
EQ<DAP@@@@@@@@@@@@@@@@D@HRHUB PE@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@AE!! YA@PZ@ @@@@@@@@@@@@@@@@HEAPTEAPHB@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 20; height: 20; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@@@@@@@') ; yourself); yourself]
!

upArrowIcon
    ^ self upArrow20x20Icon
!

upArrowPlusMenu
    "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 upArrowPlusMenu inspect
     ImageEditor openOnClass:self andSelector:#upArrowPlusMenu
    "

    <resource: #image>

    ^Icon
	constantNamed:#'AbstractFileBrowser class upArrowPlusMenu'
	ifAbsentPut:[(Depth8Image new) width: 24; height: 24; photometric:(#palette); bitsPerSample:(#(8 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PH@@@@@@@@@
@@@@@@@@@@@@@@@@@@@A@0PE@@@@@@@@@@@@@@@@@@@@@@@@@@DFA0 DAP@@@@@@@@@@@@@@@@@@@@@@@P$@A0(HA@T@@@@@@@@@@@@@@@@@@@@AB0@@C@4N
C0PE@@@@@@@@@@@@@@@@@@DF@@@LB@ MD@<DAP@@@@@@@@@@@@@@@PLGDQHHD1LHE@8UA@H@@@@@@@@@@@@AE!!\XA@<SD1LHEPPYF DB@@@@@@@@@@D\@Q0A
GA4OD1LJEPD\@Q0A@ @@@@@@@@@@@@@@@!!8^C1T_A@T@@@@@@@@@@@@@@@@@@@@@E @GHATRA@T@@@@@@@@@@@@@@@@@@@@@E @GDQT_A@T@@@@@@@@@@@@@
@@@@@@@@@P@!!H!!TJA@T@@@@@@@@@@@@@@@@@@@@@@P\#IATTA@T@@@@@@@@@@@@@@@@@@@@@@QXXFPPDF H@@@@@@@@@@@@@@@@@@@@@@ TEAPTE@ H@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@ HB@ HB@@@@@@@@@@@@@@@@@@@@@@@@@ HB@ H@@@@@@@@@@@@@@@@@@@@@@@@@@@HB@ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') ; colorMapFromArray:#[224 224 224 0 32 64 0 0 0 96 128 160 0 96 128 0 0 32 128 160 192 192 224 224 0 160 192 128 128 160 32 192 192 128 160 160 96 192 224 0 192 224 32 192 224 32 160 192 64 224 224 160 192 224 64 192 192 0 128 192 0 192 192 0 128 160 32 64 96 64 96 128 32 96 128 0 64 128 0 64 96 192 192 192 0 32 96 32 128 192 128 192 224 64 192 224 128 192 192 160 224 224 96 192 192 96 160 192 64 160 192]; mask:((Depth1Image new) width: 24; height: 24; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@F@@@O@@@_ @@?0@A?8@C?<@G?>@O??@_?? @?0@@?0@@?0@@?0@@?0@@?0@@?0@@@A?@@@>@@@\@@@H@@@@') ; yourself); yourself]
!

vt100Terminal
    <resource: #programImage>

    ^ ToolbarIconLibrary shell20x20Icon
! !

!AbstractFileBrowser class methodsFor:'menu specs'!

baseBookmarksMenuSpec
    "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:AbstractFileBrowser andSelector:#baseBookmarksMenuSpec
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser baseBookmarksMenuSpec)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'Add Bookmark'
	    #translateLabel: true
	    #value: #addBookmark
	    #enabled: #currentFilesHasDirectories
	  )
	 #(#MenuItem
	    #label: 'Remove Bookmark'
	    #translateLabel: true
	    #value: #removeBookmark
	    #enabled: #hasBookmarksToRemove
	  )
	 )
	nil
	nil
      )
!

browserMenu
    "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:AbstractFileBrowser andSelector:#browserMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser browserMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Spawn'
            #itemValue: #doSpawn
            #translateLabel: true
          )
         #(#MenuItem
            #label: 'Settings'
            #translateLabel: true
            #submenu: 
           #(#Menu
              #(
               #(#MenuItem
                  #label: 'Show'
                  #translateLabel: true
                  #submenuChannel: #showMenuSpec
                )
               #(#MenuItem
                  #label: 'Sort'
                  #translateLabel: true
                  #submenuChannel: #sortMenu
                )
               #(#MenuItem
                  #label: 'Details'
                  #translateLabel: true
                  #submenuChannel: #viewInContentsBrowserMenu
                )
               #(#MenuItem
                  #label: '-'
                )
               #(#MenuItem
                  #label: 'Toolbar'
                  #translateLabel: true
                  #hideMenuOnActivated: false
                  #indication: #toolBarVisibleHolder
                )
               #(#MenuItem
                  #label: 'Path Entry && Filter'
                  #translateLabel: true
                  #hideMenuOnActivated: false
                  #indication: #filenameEntryFieldVisibleHolder
                )
               #(#MenuItem
                  #label: '-'
                )
               #(#MenuItem
                  #label: 'Open Multiple Applications'
                  #translateLabel: true
                  #hideMenuOnActivated: false
                  #indication: #openMultipleApplicationsForType
                )
               #(#MenuItem
                  #label: 'Open Always in Text Editor'
                  #translateLabel: true
                  #hideMenuOnActivated: false
                  #indication: #openAlwaysInTextEditor
                )
               #(#MenuItem
                  #label: 'Auto Open Directory Description'
                  #translateLabel: true
                  #hideMenuOnActivated: false
                  #indication: #viewDirectoryDescription
                )
               #(#MenuItem
                  #label: '-'
                )
               #(#MenuItem
                  #label: 'Save Settings'
                  #itemValue: #saveAspectValues
                  #translateLabel: true
                )
               )
              nil
              nil
            )
          )
         #(#MenuItem
            #label: '-'
          )
         #(#MenuItem
            #label: 'Search Files'
            #itemValue: #doOpenSearchFile
            #translateLabel: true
          )
         #(#MenuItem
            #label: 'Shell Terminal'
            #itemValue: #doAddTerminal
            #translateLabel: true
          )
         #(#MenuItem
            #label: '-'
          )
         #(#MenuItem
            #label: 'Exit'
            #itemValue: #closeRequest
            #translateLabel: true
          )
         )
        nil
        nil
      )
!

cvsMenu
    "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:AbstractFileBrowser andSelector:#cvsMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser cvsMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #enabled: #hasSelection
	    #label: 'Update selected Files/Directories'
	    #itemValue: #cvsUpdateSelection
	    #translateLabel: true
	  )
	 #(#MenuItem
	    #label: 'Update Directory Local'
	    #itemValue: #cvsUpdateAll
	    #translateLabel: true
	  )
	 #(#MenuItem
	    #label: 'Update Directory Recursive'
	    #itemValue: #cvsUpdateAllRecursive
	    #translateLabel: true
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Commit...'
	    #itemValue: #cvsCommit
	    #translateLabel: true
	  )
	 #(#MenuItem
	    #enabled: #canCvsAddAndCommit
	    #label: 'Add && Commit...'
	    #itemValue: #cvsAddAndCommit
	    #translateLabel: true
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #enabled: #canRemoveCVSContainer
	    #label: 'Remove File && CVS Container...'
	    #itemValue: #cvsRemoveFileAndCVSContainer
	    #translateLabel: true
	  )
	 )
	nil
	nil
      )
!

directoryMenu
    "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:AbstractFileBrowser andSelector:#directoryMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser directoryMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'Up'
	    #translateLabel: true
	    #value: #doGoDirectoryUp
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Back'
	    #translateLabel: true
	    #value: #doBack
	    #activeHelpKey: #directoryBack
	    #enabled: #enableBack
	  )
	 #(#MenuItem
	    #label: 'Forward'
	    #translateLabel: true
	    #value: #doForward
	    #activeHelpKey: #directoryBack
	    #enabled: #enableForward
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Default'
	    #translateLabel: true
	    #value: #doGotoDefaultDirectory
	  )
	 #(#MenuItem
	    #label: 'Home'
	    #translateLabel: true
	    #value: #doGotoHomeDirectory
	  )
	 #(#MenuItem
	    #label: 'Visited Directories'
	    #translateLabel: true
	    #submenuChannel: #visitedDirectoriesMenu
	  )
	 #(#MenuItem
	    #label: 'Bookmarks'
	    #translateLabel: true
	    #submenuChannel: #bookmarksMenuSpec
	  )
	 )
	nil
	nil
      )
!

editMenu
    "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:AbstractFileBrowser andSelector:#editMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser editMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'Copy'
	    #translateLabel: true
	    #value: #copyInDirContentsBrowser
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: 'Cut'
	    #translateLabel: true
	    #value: #cutInDirContentsBrowser
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: 'Paste'
	    #translateLabel: true
	    #value: #pasteFiles
	    #enabled: #canPaste
	  )
	 #(#MenuItem
	    #label: 'Delete'
	    #translateLabel: true
	    #value: #deleteInDirContentsBrowser
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Copy All Filenames'
	    #translateLabel: true
	    #value: #copyFileList
	    #enabled: #fileListIsNotEmpty
	  )
	 #(#MenuItem
	    #label: 'Copy Selected Filenames'
	    #translateLabel: true
	    #value: #copySelectedFilenames
	    #enabled: #hasSelection
	  )
	 )
	nil
	nil
      )
!

fileMenu
    "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:AbstractFileBrowser andSelector:#fileMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser fileMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'New'
	    #translateLabel: true
	    #submenuChannel: #newMenu
	  )
	 #(#MenuItem
	    #label: 'Rename'
	    #translateLabel: true
	    #value: #renameSelection
	    #enabled: #hasSelection
	    #shortcutKeyCharacter: #Replace
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Open in Text Editor'
	    #translateLabel: true
	    #value: #doShowFileContents
	  )
	 #(#MenuItem
	    #label: 'Properties...'
	    #translateLabel: true
	    #value: #doShowProperties
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: '-'
	    #isVisible: #javaSupportLoaded
	  )
	 #(#MenuItem
	    #label: 'File in'
	    #translateLabel: true
	    #value: #fileFileIn
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: 'File in to Namespace...'
	    #translateLabel: true
	    #value: #fileFileInToNameSpace
	    #enabled: #hasSelection
	  )
	 #(#MenuItem
	    #label: '-'
	    #isVisible: #javaSupportLoaded
	  )
	 #(#MenuItem
	    #label: 'Add to Java Class Path'
	    #translateLabel: true
	    #isVisible: #javaSupportLoaded
	    #enabled: #canAddToClassPath
	  )
	 #(#MenuItem
	    #label: 'Remove from Java Class Path'
	    #translateLabel: true
	    #isVisible: #javaSupportLoaded
	    #enabled: #canRemoveFromClassPath
	  )
	 #(#MenuItem
	    #label: 'Add to Java Source Path'
	    #translateLabel: true
	    #isVisible: #javaSupportLoaded
	    #enabled: #canAddToSourcePath
	  )
	 #(#MenuItem
	    #label: 'Remove from Java Source Path'
	    #translateLabel: true
	    #isVisible: #javaSupportLoaded
	    #enabled: #canRemoveFromSourcePath
	  )
	 )
	nil
	nil
      )
!

newMenu
    "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:DirectoryTreeBrowser andSelector:#newMenu
     (Menu new fromLiteralArrayEncoding:(DirectoryTreeBrowser newMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'Directory...'
	    #translateLabel: true
	    #value: #newDirectory
	  )
	 #(#MenuItem
	    #label: 'File...'
	    #translateLabel: true
	    #value: #newFile
	  )                                     
	 #(#MenuItem
	    #label: 'Hard Link...'
	    #translateLabel: true
	    #isVisible: #systemIsUnix
	    #value: #newHardLink
	  )
	 #(#MenuItem
	    #label: 'Symbolic Link...'
	    #translateLabel: true
	    #isVisible: #systemIsUnix
	    #value: #newSoftLink
	  )
	 )
	nil
	nil
      )
!

showMenuSpec
    "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:AbstractFileBrowser andSelector:#showMenuSpec
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser showMenuSpec)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Hidden Files'
            #translateLabel: true
            #indication: #showHiddenFiles
          )
         #(#MenuItem
            #label: '-'
          )
         #(#MenuItem
            #label: 'Directory Tree'
            #translateLabel: true
            #indication: #showDirectoryTree
          )
         #(#MenuItem
            #label: 'Regular Files in TreeView (Left)'
            #translateLabel: true
            #indication: #viewFilesInDirectoryTree
          )
         #(#MenuItem
            #label: 'Directories in ContentsView (Right)'
            #translateLabel: true
            #indication: #viewDirsInContentsBrowser
          )
         #(#MenuItem
            #enabled: #enableViewNoteBookApplication
            #label: 'File Applications'
            #translateLabel: true
            #indication: #viewNoteBookApplicationHolder
          )
         )
        nil
        nil
      )
!

sortMenu
    "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:AbstractFileBrowser andSelector:#sortMenu
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser sortMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
	#(
	 #(#MenuItem
	    #label: 'By Filename'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #baseName
	  )
	 #(#MenuItem
	    #label: 'By Type'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #suffix
	  )
	 #(#MenuItem
	    #label: 'By Permissions'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #permissions
	  )
	 #(#MenuItem
	    #label: 'By Owner'
	    #translateLabel: true
	    #isVisible: #viewOwner
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #owner
	  )
	 #(#MenuItem
	    #label: 'By Group'
	    #translateLabel: true
	    #isVisible: #viewOwner
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #group
	  )
	 #(#MenuItem
	    #label: 'By Size'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #fileSize
	  )
	 #(#MenuItem
	    #label: 'By Date && Time'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #choice: #sortBlockProperty
	    #choiceValue: #modificationTime
	  )
	 #(#MenuItem
	    #label: '-'
	  )
	 #(#MenuItem
	    #label: 'Ignore Case in Sort'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #indication: #sortCaseless
	  )
	 #(#MenuItem
	    #label: 'Directories before Files'
	    #translateLabel: true
	    #hideMenuOnActivated: false
	    #indication: #sortDirectoriesBeforeFiles
	  )
	 )
	nil
	nil
      )
!

toolsMenuSpec
    "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:FileBrowserV2 andSelector:#toolsMenuSpec
     (Menu new fromLiteralArrayEncoding:(FileBrowserV2 toolsMenuSpec)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Execute Command...'
            #translateLabel: true
            #value: #doExecuteCommand
          )
         #(#MenuItem
            #label: 'Shell Terminal'
            #translateLabel: true
            #isVisible: #canDoTerminalAndSystemIsUnix
            #value: #openTerminal
            #enabled: #canDoTerminal
          )
         #(#MenuItem
            #label: 'DOS Terminal'
            #translateLabel: true
            #isVisible: #canDoTerminalAndSystemIsDOS
            #value: #openTerminal
            #enabled: #canDoTerminal
          )
         #(#MenuItem
            #label: '-'
          )
         #(#MenuItem
            #label: 'Changes Browser'
            #translateLabel: true
            #value: #openChangesBrowser
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'ChangeSet Browser'
            #translateLabel: true
            #value: #openChangeSetBrowser
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'Snapshot Image Browser'
            #translateLabel: true
            #value: #openSnapshotImageBrowser
            #enabled: #hasSnapshotSelection
          )
         #(#MenuItem
            #label: 'Create Smalltalk Project'
            #translateLabel: true
            #value: #createProjectAndOpenProjectBrowser
            #enabled: #canCreateNewProject
          )
         #(#MenuItem
            #label: 'Install Autoloaded'
            #translateLabel: true
            #value: #readAbbrevFile
            #enabled: #canReadAbbrevFile
          )
         #(#MenuItem
            #label: 'Install all as Autoloaded'
            #translateLabel: true
            #value: #installAllAsAutoloaded
            #enabled: #anySTFilesPresent
          )
         #(#MenuItem
            #label: 'Editor'
            #translateLabel: true
            #value: #openEditor
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'HTML Reader'
            #translateLabel: true
            #value: #openHTMLReader
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'ASN1 Browser'
            #translateLabel: true
            #isVisible: #hasASN1
            #value: #openASN1Browser
            #enabled: #hasASN1AndSelection
          )
         #(#MenuItem
            #label: 'C Browser'
            #translateLabel: true
            #isVisible: #hasCBrowser
            #value: #openCBrowser
            #enabled: #hasCBrowser
          )
         #(#MenuItem
            #label: 'Applet Viewer'
            #translateLabel: true
            #isVisible: #hasJava
            #value: #openAppletViewer
            #enabled: #hasJavaAndSelection
          )
         #(#MenuItem
            #label: 'Image Inspector'
            #translateLabel: true
            #value: #openImageInspector
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'Image Preview'
            #translateLabel: true
            #value: #openImagePreview
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'Image Editor'
            #translateLabel: true
            #value: #openImageEditor
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'MP3 Player'
            #translateLabel: true
            #isVisible: #hasMP3Player
            #value: #openMP3Player
            #enabled: #hasMP3PlayerAndSelection
          )
         #(#MenuItem
            #label: 'ZipFile Tool'
            #translateLabel: true
            #value: #openZipTool
            #enabled: #hasZipFileSelected
          )
         #(#MenuItem
            #label: 'Slide Show'
            #translateLabel: true
            #isVisible: #hasSlideShow
            #value: #openSlideShow
            #enabled: #currentFilesAreInSameDirectory
          )
         #(#MenuItem
            #label: 'File Differences...'
            #translateLabel: true
            #value: #openDiffView
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'Find Duplicate Files'
            #translateLabel: true
            #value: #fileFindDuplicates
          )
         #(#MenuItem
            #label: 'Find All Duplicate Files (Recursive)'
            #translateLabel: true
            #value: #fileFindAllDuplicates
            #enabled: #hasSelection
          )
         #(#MenuItem
            #label: 'Find a File...'
            #translateLabel: true
            #value: #fileFindFile
          )
         #(#MenuItem
            #label: 'Hex Dump'
            #translateLabel: true
            #value: #fileHexDump
            #enabled: #hasSelection
          )
         )
        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
      )
! !

!AbstractFileBrowser class methodsFor:'misc'!

newLock
    ^ CodeExecutionLock new
! !

!AbstractFileBrowser methodsFor:'actions'!

askForCommandFor:fileName thenDo:aBlock
    "setup and launch a querybox to ask for unix command.
     Then evaluate aBlock passing the command-string as argument."

    |box osName|

    osName := OperatingSystem platformName.

    box := FilenameEnterBox 
		title:(resources string:'Execute %1 command:' with:osName)
	       okText:(resources string:'Execute')
	       action:aBlock.

    fileName notNil ifTrue:[
	self initialCommandFor:fileName into:box.
    ].
    box directory:(self getDirWithoutFileName:fileName).
    box showAtPointer.
    box destroy.

    "Modified: / 7.9.1995 / 10:31:54 / claus"
    "Modified: / 16.9.1997 / 15:35:10 / stefan"
    "Modified: / 14.8.1998 / 14:12:52 / cg"
!

changeFileBrowserTitleTo:aString

    self application:#FileBrowserV2
	 do:#changeFileBrowserTitleTo:                            
	 withArg:aString
!

copyFileList

    | fileList stream|
    fileList := self application:#DirectoryContentsBrowser do:#descriptions.
    stream := WriteStream on:''.
    fileList do:[: item |
	stream nextPutAll:(item fileName asString).
	stream cr.
    ].
    self window setTextSelection:stream contents.
    stream close.
!

copySelectedFilenames

    | fileList stream|
    fileList := self application:#DirectoryContentsBrowser do:#selectedFiles.
    fileList isEmpty ifTrue:[^ self].
    stream := WriteStream on:''.
    fileList do:[: file |
	stream nextPutAll:(file asString).
	stream cr.
    ].
    self window setTextSelection:stream contents.
    stream close.
!

doAddTerminal

    | item dir directories|

    directories := self currentDirectories value.
    
    directories isEmpty ifTrue:[
	dir :=  Filename homeDirectory
    ] ifFalse:[
	dir :=  directories first.
    ].
    
    item := (DirectoryContentsBrowser itemClass fileName:dir).
    self fileApplicationDo:#openTerminalApplication: withArg:item.
!

doExecuteCommand

    | action  fileName|
    fileName := self firstSelectedFile.
    action := [:command | 
		self addToCommandHistory:command for:fileName.
		self executeCommand:command.
	      ].
    self askForCommandFor:fileName thenDo:action
!

doGoDirectoryUp
    | upDir directories rootInTreeView|

    self enableDirectoryUp value ifFalse:[ ^ self].
    self currentFilesAreInSameDirectory ifTrue:[
	directories := self currentDirectories value.
	upDir := directories first directory.
    ] ifFalse:[
	rootInTreeView := self application:#DirectoryTreeBrowser do:#rootHolder.
	upDir := rootInTreeView value asFilename directory.
    ].
    self currentFileNameHolder value:(OrderedCollection with:upDir).
!

doGotoDefaultDirectory
    self gotoFile:(Filename defaultDirectory).
!

doGotoHomeDirectory

    | home |

    home := Filename homeDirectory.
    self gotoFile:home.
!

doOpenSearchFile

    |item files|

    files := self currentFileNameHolder value.
    files notEmpty ifTrue:[
	item := DirectoryContentsBrowser itemClass fileName:(files first).
    ] ifFalse:[
	item := DirectoryContentsBrowser itemClass fileName:(Filename homeDirectory asAbsoluteFilename).
    ].
    self openSearchFileOn:item.
!

doShowFileContents

    ^ self application:#DirectoryContentsBrowser do:#doShowFileContents.
!

doShowProperties

    "show long stat (file)-info"

    self fileGetInfo:true
!

fileApplicationDo:selector

    ^ self application:#FileApplicationNoteBook do:selector
!

fileApplicationDo:selector withArg:arg
    ^ self application:#FileApplicationNoteBook do:selector withArg:arg 
!

fileGetInfo:longInfo 
    "get info on selected file - show it in a box"

    |string box updater|

    string := self getFileInfoStringForFirstSelectedFile:longInfo.
    string notNil ifTrue:[
	box := InfoBox title:string.
	updater := [
		    [true] whileTrue:[
			Delay waitForSeconds:2.
			string := self getFileInfoStringForFirstSelectedFile:longInfo.
			string isNil ifTrue:[ ^ self].
			box title:string
		    ]
		] fork.
	box showAtPointer.
	updater terminate.
	box destroy
    ]
!

gotoFile:aFilename

    " select only if the file is not already in selection"
    | currentSel |

    currentSel := self currentFileNameHolder value.
    ((currentSel findFirst:[:aFile| aFile = aFilename]) == 0) ifTrue:[
	self currentFileNameHolder value:(OrderedCollection with:(aFilename asAbsoluteFilename)).
    ].
!

openApplByFileItem:aItem

    ^ self fileApplicationDo:#openApplByFileItem: withArg:aItem
!

openCommandResultApplication

    ^ self fileApplicationDo:#openCommandResultApplication
!

openSearchFileOn:aItem

    ^ self fileApplicationDo:#openSearchFileOn: withArg:aItem
!

openTextEditorOn:aItem

    ^ self fileApplicationDo:#openTextEditorOn: withArg:aItem 
!

updateAndSelect:aColOfFiles

    self application:#DirectoryContentsBrowser do:#doUpdate.
    self application:#DirectoryTreeBrowser do:#doUpdate.
    
    aColOfFiles notNil ifTrue:[ self currentFileNameHolder value:aColOfFiles ].
!

updateCurrentDirectory

    self updateAndSelect:nil
! !

!AbstractFileBrowser methodsFor:'actions bookmarks'!

addBookmark

    |directories|

    self currentFilesAreInSameDirectory ifFalse:[^ self].
    directories := self currentDirectories value.
    self addBookmark:directories.
!

addBookmark:aColOfDirectories
    |idx bookmarks|

    aColOfDirectories do:[ : path |
	bookmarks := self class directoryBookmarks.
	idx := bookmarks indexOf:path.
	idx == 0 ifTrue:[
	    bookmarks addLast:path.
	].
    ].
!

hasBookmarks
    ^ self class directoryBookmarks size > 0
!

hasBookmarksToRemove

    |bookmarks directories|

    directories := self currentSelectedDirectories.
    bookmarks := self class directoryBookmarks.
    ^ (bookmarks size > 0 and:[directories notEmpty])
!

removeBookmark

    |bookmarks directories|

    bookmarks := self class directoryBookmarks.
    bookmarks isNil ifTrue:[ ^ self].
    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[^ self].
    directories do:[:dir|
	bookmarks remove:dir ifAbsent:nil.
    ].
! !

!AbstractFileBrowser methodsFor:'actions history'!

addToCommandHistory:aCommandString for:aFilename
    |cmd suffix cmdHist|

    cmdHist := self class commandHistory.
    (aCommandString notNil and:[aCommandString notEmpty]) ifTrue:[
	cmdHist notNil ifTrue:[
	    cmdHist addFirst:aCommandString.
	    cmdHist size > self class commandHistorySize ifTrue:[
		cmdHist removeLast
	    ]
	].
	aFilename notNil ifTrue:[
	    cmd := aCommandString copyTo:(aCommandString indexOf:Character space ifAbsent:[aCommandString size + 1])-1.
	    DefaultCommandPerSuffix isNil ifTrue:[
		DefaultCommandPerSuffix := Dictionary new.
	    ].
	    suffix := aFilename asFilename suffix.
	    suffix notNil ifTrue:[
		DefaultCommandPerSuffix at:suffix put:cmd.
	    ]
	]
    ]
!

doBack

    | fileName|

    fileName := self dirHistory goBack.
    fileName notNil ifTrue:[
	self gotoFile:(fileName asFilename).
    ]
!

doForward

    | fileName|

    fileName := self dirHistory goForward.
    fileName notNil ifTrue:[
	self gotoFile:(fileName asFilename).
    ] ifFalse:[
	self enableForward value:false.

    ].
! !

!AbstractFileBrowser methodsFor:'actions-app-common'!

openApplForFile:aFilename
    ^ self openApplByFileItem:(DirectoryContentsBrowser itemClass fileName:aFilename).
! !

!AbstractFileBrowser methodsFor:'applications'!

application:aApplication do:aMethod 

    " perform a Method for a application "
    |appl|

    appl := self applications at:aApplication ifAbsent:nil.
    appl notNil ifTrue:[
	^ appl perform:aMethod.
    ].
    ^ nil.
!

application:aApplication do:aMethod withArg:arg 
    |appl|

    appl := self applications at:aApplication ifAbsent:nil.
    appl notNil ifTrue:[
	^ appl perform:aMethod with:arg
    ].
    ^ nil
!

application:aApplication do:aMethod withArg:arg1 withArg:arg2
    |appl|

    appl := self applications at:aApplication ifAbsent:nil.
    appl notNil ifTrue:[
	(arg1 notNil and:[arg2 notNil]) ifTrue:[
	    ^ appl perform:aMethod with:arg1 with:arg2
	]
    ].
    ^ nil
!

directoryContentsBrowser
    ^ self applications at:#DirectoryContentsBrowser ifAbsent:nil.
! !

!AbstractFileBrowser methodsFor:'aspects'!

applications
    "returns the list of registered applications
    "
    ^ aspects at:#applications
!

backgroundProcesses

    ^ self aspectFor:#backgroundProcesses ifAbsent:[List new]
!

canMake

    ^ self aspectFor:#hasSelection ifAbsent:[ false asValue ].
!

currentDirectories

    " returns a Ordered Collection of all directories currently selected 
      if only a file is selected currentDirectories holds the directory of the file
    "

    ^ self aspectFor:#currentDirectories ifAbsent:[ (OrderedCollection new) asValue ].
!

currentFileNameHolder

    " returns a OrderedCollection of all files that are selected
      if no file but a directory is selected it contains the directories 
      in contrast to currentDirectories wich have only the directories 
    "
    ^ self aspectFor:#currentFileNameHolder ifAbsent:[
        (OrderedCollection with:(Filename currentDirectory asAbsoluteFilename)) asValue
        ] notPresentDo:[:holder|
            | filenames newFilenames|
            filenames := holder value.
            newFilenames := Set new.
            filenames do:[ : filename |  | fn |
                fn := filename.
                [fn exists not] whileTrue:[
                    fn := fn directory.
                ].
                newFilenames add:fn.
            ].
            newFilenames asOrderedCollection.
        ]
!

enableDirectoryUp

    ^ self aspectFor:#enableDirectoryUp ifAbsent:[false asValue]
!

enableHome

    ^ self aspectFor:#enableHome ifAbsent:[ true asValue ].
!

enableViewNoteBookApplication

    ^ self aspectFor:#enableViewNoteBookApplication ifAbsent:[false asValue]
!

hasSelection

    ^ self aspectFor:#hasSelection ifAbsent:[ false asValue ].
!

notifyChannel

    ^ self aspectFor:#notifyChannel ifAbsent:['' asValue]
!

rootHolder
    "holder, which keeps the rootHolder of the treeView
    "

    ^ self aspectFor:#rootHolder ifAbsent:[ValueHolder new].
! !

!AbstractFileBrowser methodsFor:'aspects handling'!

aspectFor:something ifAbsent:aBlock
    "returns the model for an aspect
    "
    |holder saveAspectItem aspect|

    holder := aspects at:something ifAbsent:[
        saveAspectItem := self runtimeAspectValueFor:something.
        saveAspectItem notNil ifTrue:[
            saveAspectItem isHolder ifTrue:[
                holder := ValueHolder with:saveAspectItem value 
            ] ifFalse:[
                holder := saveAspectItem value 
            ].
        ] ifFalse:[
            aspect := self userPreferencesAspectValueFor:something.
            aspect notNil ifTrue:[ 
                holder := aspect asValue
            ] ifFalse:[
                holder := aBlock value.
            ]
        ].
        holder notNil ifTrue:[        
            aspects at:something put:holder
        ]
    ].
    ^ holder
!

aspectFor:something ifAbsent:aBlock notPresentDo:notPresentBlock
    "returns the model for an aspect
    "
    |holder saveAspectItem aspect|

    holder := aspects at:something ifAbsent:[
        saveAspectItem := self runtimeAspectValueFor:something.
        saveAspectItem notNil ifTrue:[
            saveAspectItem isHolder ifTrue:[
                holder := ValueHolder with:saveAspectItem value 
            ] ifFalse:[
                holder := saveAspectItem value 
            ].
        ] ifFalse:[
            aspect := self userPreferencesAspectValueFor:something.
            aspect notNil ifTrue:[ 
                holder := aspect asValue
            ] ifFalse:[
                holder := aBlock value.
            ]
        ].
        holder notNil ifTrue:[  
            holder value:(notPresentBlock value:holder).
            aspects at:something put:holder
        ]
    ].
    ^ holder
!

aspects
    ^ aspects
!

runtimeAspectValueFor:something
    "returns the default aspect item from the class variable RuntimeAspects
    "
    ^ self class runtimeAspects at:something ifAbsent:nil.
!

saveAspectValues
    |saveAspects aspectValue|


    saveAspects := self class userPreferencesAspectList.
    saveAspects do:[ : aspectKey |
        aspectValue := (self perform:aspectKey) value.
        UserPreferences current perform:((aspectKey asString, ':') asSymbol) with:aspectValue.
    ].
!

saveRuntimeAspectValues
    |savedAspects dictionary value isHolder aspect|

    savedAspects := self class listOfRuntimeValuesToRemark.
    dictionary := Dictionary new.
    savedAspects do:[ : aspectKey |
	aspect := self perform:aspectKey.
	isHolder := aspect isValueModel.
	isHolder ifTrue:[value:= aspect value] ifFalse:[ value := aspect].
	dictionary at:aspectKey 
		   put:(SaveAspectItem withValue:value isHolder:isHolder)
    ].
        
    RuntimeAspects := dictionary. 
!

userPreferencesAspectValueFor:something
    "returns the default aspect from the Userpreferences
    "

    (self class userPreferencesAspectList includes:something) not ifTrue:[ ^ nil].
    ^ UserPreferences current perform:something.
! !

!AbstractFileBrowser methodsFor:'aspects-filter'!

filterBackgroundColor

    ^ self aspectFor:#filterBackgroundColor ifAbsent:[Color white asValue]
!

filterBlockHolder

    ^ self aspectFor:#filterBlockHolder ifAbsent:[self getFilter asValue]
!

filterListModel

    ^ self aspectFor:#filterListModel ifAbsent:[self class defaultFilterList]
!

filterModel

    ^ self aspectFor:#filterModel ifAbsent:[(self filterListModel at:1) asValue]
!

filterValueBox

    ^ self aspectFor:#filterValueBox ifAbsent:[ValueHolder new]
!

getFilter
    | filter showHidden|

    filter := self filterModel value.
    filter = '' ifTrue:[filter := '*'].
    showHidden := self showHiddenFiles value.
    showHidden ifTrue:[
	^ [: el | filter match:el].
    ] ifFalse:[
	^ [: el | ((el asString startsWith:'.') not) and:[filter match:el]].
    ]
!

shownFiles

    ^ self aspectFor:#shownFiles ifAbsent:['-/-' asValue]
! !

!AbstractFileBrowser methodsFor:'aspects-history'!

dirHistory

    ^ self class directoryHistory
!

enableBack

    ^ self aspectFor:#enableBack ifAbsent:[false asValue]
!

enableFileHistory

    ^ self aspectFor:#enableFileHistory ifAbsent:[false asValue]
!

enableForward

    ^ self aspectFor:#enableForward ifAbsent:[false asValue]
!

fileHistory

    ^ self aspectFor:#fileHistory ifAbsent:[FilenameHistory new]
! !

!AbstractFileBrowser methodsFor:'aspects-visibility'!

filenameEntryFieldVisibleHolder
    " aspect for show FileEntryField "

    ^ self aspectFor:#filenameEntryFieldVisibleHolder ifAbsent:[true asValue]
!

openAlwaysInTextEditor
    " aspect for open every file in TextEditor dont use e.g. HtmlEditor for *.html'"

    ^ self aspectFor:#openAlwaysInTextEditor ifAbsent:[ false asValue ].
!

openMultipleApplicationsForType

    " aspect for open more applications for e.g. TextEditor and not change the contents of already 
      open TextEditor "

    ^ self aspectFor:#openMultipleApplicationsForType ifAbsent:[ false asValue ].
!

showDirectoryTree

    ^ self aspectFor:#showDirectoryTree ifAbsent:[ true asValue ]
!

showHiddenFiles

    ^ self aspectFor:#showHiddenFiles ifAbsent:[ true asValue ].
!

toolBarVisibleHolder
    " aspect for show toolbar in FileBrowserV2"

    ^ self aspectFor:#toolBarVisibleHolder ifAbsent:[true asValue]
!

viewDescription
    "get the user preferences for show file description row in DirectoryContentsBrowser"

    ^ self aspectFor:#viewDescription ifAbsent:[ false asValue ].
!

viewDetails
    "get the user preferences for view more file properties in rows in DirectoryContentsBrowser 
    "

    ^ self aspectFor:#viewDetails ifAbsent:[ false asValue ].
!

viewDirectoryDescription

    " aspect for auto open a TextView for Readme and other see getInfoItem Method files 
      on change directory "

    ^ self aspectFor:#viewDirectoryDescription ifAbsent:[ true asValue ].
!

viewDirsInContentsBrowser

    ^ self aspectFor:#viewDirsInContentsBrowser ifAbsent:[ false asValue ].
!

viewFilesInDirectoryTree

    " aspect for view files in tree view (not only directories) "

    ^ self aspectFor:#viewFilesInDirectoryTree ifAbsent:[ false asValue ].
!

viewGroup

    " aspect for show group information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewGroup ifAbsent:[ false asValue ].
!

viewNoteBookApplicationHolder

    ^ self aspectFor:#viewNoteBookApplicationHolder ifAbsent:[ false asValue].
!

viewOwner

    " aspect for show owner information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewOwner ifAbsent:[ false asValue ].
!

viewPermissions

    " aspect for show permission information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewPermissions ifAbsent:[ false asValue ].
!

viewPreview

    " aspect for show image previev row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewPreview ifAbsent:[ false asValue ].
!

viewSize

    " aspect for show size information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewSize ifAbsent:[ false asValue ].
!

viewTime

    " aspect for show time information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewTime ifAbsent:[ false asValue ].
!

viewType
    " aspect for show suffix (type) information row in DirectoryContentsBrowser "

    ^ self aspectFor:#viewType ifAbsent:[ false asValue ].
! !

!AbstractFileBrowser methodsFor:'background processing'!

executeCommand:cmd

    self executeCommand:cmd inDirectory:nil
!

executeCommand:cmd inDirectory:aDir

    | nameString executionBlock|

    executionBlock := self getExecutionBlockForCommand:cmd inDirectory:aDir.
    nameString := 'Command> ', cmd.
    self makeExecutionResultProcessFor:executionBlock withName:nameString.
!

getExecutionBlockForCommand:cmd

    ^ self getExecutionBlockForCommand:cmd inDirectory:nil
!

getExecutionBlockForCommand:cmd inDirectory:aDir

    | dir dirs|

    dir := aDir.
    aDir isNil ifTrue:[
	dirs := self currentSelectedDirectories.
	dirs size ~= 1 ifTrue:[ ^ self].
	dir := dirs anElement.
    ].
    ^ [:stream| stream notNil ifTrue:[
	    OperatingSystem 
		executeCommand:cmd
		inputFrom:nil 
		outputTo:stream 
		errorTo:stream 
		inDirectory:dir
		onError:[:status| false].
	]
    ].
!

killAllRunningBackgroundProcesses

    self backgroundProcesses do:[ : process |
	self notifyChannel value:'kill ', process name.
	process terminate.    
    ].
!

makeExecutionResultProcessFor:aBlock withName:aString
    | stream process appl nameString|

    appl := self openCommandResultApplication.
    stream := appl resultStream.
    nameString := aString ? 'Execution Result'.
    appl changeTabTo:nameString.
    process := [ [aBlock value:stream] valueNowOrOnUnwindDo:[
	self backgroundProcesses remove:process ifAbsent:[].
	appl process value:nil.
    ]] newProcess.
    process priority:(Processor userBackgroundPriority).
    process name:nameString.
    self backgroundProcesses add:process.
    appl process value:process.
    process resume.
! !

!AbstractFileBrowser methodsFor:'change & update'!

abstractCurrentFileNameHolderChanged
    " do here all the things that have to be done for every part of the FileBrowserV2
      and the things that have to be done if it runs standalone "

    | newDirectories oldDirectories size rootInTreeView holder|

    holder := self currentFileNameHolder value.
    self hasSelection value:(holder value notEmpty).
    newDirectories := self directoriesForFiles:(holder value).
    oldDirectories := self currentDirectories value.
    oldDirectories ~= newDirectories ifTrue:[
	self currentDirectories value:newDirectories.
	size := newDirectories size.
	rootInTreeView := self application:#DirectoryTreeBrowser do:#rootHolder.
	rootInTreeView := rootInTreeView notNil ifTrue:[rootInTreeView value].
	self enableDirectoryUp value:(((size == 1) and:[newDirectories first isRootDirectory not]) or:[(rootInTreeView notNil and:[rootInTreeView value asFilename isRootDirectory not])]).
	newDirectories notEmpty ifTrue:[
	    newDirectories do:[: dir |
		self dirHistory addToHistory:(dir asString).
	    ].
	].
	self enableHome value:((newDirectories includes:(Filename homeDirectory))not).
    ].
    self enableForward value:self canForward.
    self enableBack value:self canBack.
    ^ self
!

filterModelChanged

    self filterBlockHolder value:(self getFilter).
!

update:something with:aParameter from:changedObject

    " do here all the things that have to be done for every part of the FileBrowserV2
      and the things that have to be done if it runs standalone "

    changedObject == self currentFileNameHolder ifTrue:[
	self abstractCurrentFileNameHolderChanged.
	^ self
    ].
    changedObject == self sortCaseless ifTrue:[
	self sortFileListsBy:#baseName withReverse:false.
	^ self
    ].             
    (changedObject == self filterModel or:[changedObject == self showHiddenFiles]) ifTrue:[
	self filterModelChanged.
	^ self
    ].

    super update:something with:aParameter from:changedObject
! !

!AbstractFileBrowser methodsFor:'clipboard'!

canPaste

    ^ self aspectFor:#canPaste ifAbsent:[ false asValue ].
!

clipboard

    ^ self aspectFor:#clipboard ifAbsent:[Clipboard new]
!

copyFilesToClipBoard:colOfFiles
    "defete current selected files/directories
    "
    self putInClipBoard:colOfFiles as:#copy.
!

cutFilesToClipBoard:colOfFiles
    "defete current selected files/directories
    "
    self putInClipBoard:colOfFiles as:#cut.
!

emptyClipBoard

    self clipboard files:nil.
    self canPaste value:false.
!

putInClipBoard:colOfFiles as:aSymbol

    | stream clp|

    colOfFiles isEmpty ifTrue:[ ^ self].
    clp := self clipboard.
    clp files:nil.
    clp method:aSymbol.
    stream := WriteStream on:''.
    stream nextPutAll:aSymbol asString.
    stream nextPutAll:' <'.
    stream nextPutAll:colOfFiles first asString.
    colOfFiles size > 1 ifTrue:[
	stream nextPutAll:' ...'.
    ].
    stream nextPutAll:'> to clipboard'.

    self notifyChannel value:stream contents.
    stream close.
    clp files:colOfFiles.
    self canPaste value:true.
! !

!AbstractFileBrowser methodsFor:'drag & drop'!

canDropArchiv:dropedObjects for:filename 

    (filename isDirectory 
    and:[filename isWritable and:[dropedObjects notEmpty]])  ifTrue:[
	^ true
    ].
    ^ false
!

canDropFiles:dropedObjects for:filename 
    | checkObject filenameDirString checkObjectString filenameDir|

    dropedObjects isEmpty ifTrue:[^ false].
    filenameDir := self getDirWithoutFileName:filename.
    filenameDir isWritable not ifTrue:[^ false].
    filenameDirString := filenameDir asString.
    dropedObjects do:[:aObject | 
	checkObject := aObject theObject.
	checkObjectString := checkObject asString.
	checkObject isDirectory ifTrue:[
	    (self fileName:filenameDirString startsWith:checkObjectString) ifTrue:[
		" can not drop a directory in his parents "
		^ false
	    ]
	] ifFalse:[
	    (filenameDirString = checkObject directory asString 
	    or:[ filenameDirString = checkObject physicalPathName asFilename directory asString ]) ifTrue:[
		" can not drop a file in same directory "
		^ false
	    ]
	]
    ].
    ^ true
!

doStartDrag:aDropSource in:aView
    "set the cursors before starting the drag & drop operation
    "
    |hdl|


    hdl := DragAndDropManager new.

    hdl disabledCursor:self class DisabledCursorImage.
    hdl enabledCursor:self class EnabledCursorImage.
    hdl alienCursor:nil.

    hdl startDragFrom:aView dropSource:aDropSource offset:#topLeft
! !

!AbstractFileBrowser methodsFor:'file operations'!

copyFile:aSourceFile to:aDestFile
    "copy to
    "
    |copy|

    copy := FileOperation copy copyFile:aSourceFile to:aDestFile withOverWriteWarning:true copyFileIfSame:true.
    copy result ifTrue:[
	self notifyChannel value:('copy ', aSourceFile baseName, ' to:,', aDestFile baseName).
    ] ifFalse:[
	self notifyChannel value:copy errorString.
    ].
    ^ copy result
!

copyFiles:aColOfSourceFiles to:aDirectory 
   "copy aColOfSourceFiles to aDirectory
   "
    |copy|

    copy := FileOperation copy copyFiles:aColOfSourceFiles to:aDirectory.
    copy result ifFalse:[
	self notifyChannel value:copy errorString.
    ].
    self updateCurrentDirectory.
    ^ copy colOfCopiedFiles
!

copyOrMoveDialog:aCol

    | size stream dialog|

    size := aCol size.
    stream := WriteStream on:''.
    stream nextPutAll:'copy or move file'.
    size == 1 ifFalse:[
	stream nextPutAll:'s'.
    ].
    stream nextPutAll:': '.
    stream nextPutAll:aCol first baseName asString.
    size == 1 ifFalse:[
	stream nextPutAll:' ... '.
	stream nextPutAll:aCol last baseName asString.
    ].

    dialog := OptionBox 
		  request:stream contents 
		  label:'move or copy'
		  form:(WarningBox iconBitmap)
		  buttonLabels:#('cancel' 'move' 'copy')
		  values:#(#cancel #move #copy)
		  default:#copy.
    dialog isNil ifTrue:[dialog := #cancel].
    ^ dialog.
!

copyOrMoveFiles:aColOfSourceFiles to:aDirectory 
   "copy aColOfSourceFiles to aDirectory
   "
    |dialog|

    dialog := self copyOrMoveDialog:aColOfSourceFiles.
    dialog == #copy ifTrue:[
	self copyFiles:aColOfSourceFiles to:aDirectory.
	^ self.
    ].
    dialog == #move ifTrue:[
	self moveFiles:aColOfSourceFiles to:aDirectory.
	^ self.
    ].
!

deleteFile:aFile
    "delete current selected files/directories
    "

    ^ self deleteFiles:(OrderedCollection with:aFile).
!

deleteFiles:colOfFiles
    "delete current selected files/directories
    "
    |delete|

    delete := FileOperation delete deleteFiles:colOfFiles.
    delete result ifFalse:[
	self notifyChannel value:delete errorString.
    ].
    self updateCurrentDirectory.
    ^ delete result.
!

moveFile:aSourceFile to:aDestFile
    "defete current selected files/directories
    "

    |move|

    move := FileOperation move moveFile:aSourceFile to:aDestFile.
    move result ifTrue:[
	self notifyChannel value:('move ', aSourceFile asString, ' to ', aDestFile asString).
    ] ifFalse:[
	self notifyChannel value:move errorString.
    ].
    self updateCurrentDirectory.
    ^ move result
!

moveFiles:aColOfSourceFiles to:aDirectory 
   "move aColOfSourceFiles to aDirectory
   "
    |move|

    move := FileOperation move moveFiles:aColOfSourceFiles to:aDirectory.
    move result ifFalse:[
	self notifyChannel value:move errorString.
    ].
    self updateCurrentDirectory.
    ^ move colOfMovedFiles
!

newDirectory
    "ask for and create a new directory"

    | directories directory create newFile|

    directories := self currentDirectories value.
    (directories size ~= 1) ifTrue:[^ self].
    directory := directories first.
    create := FileOperation create createDirectoryIn:directory.
    create result ifFalse:[ ^ self].
    newFile := create createdFile.
    newFile notNil ifTrue:[
	self updateCurrentDirectory.
    ]
!

newFile
    "ask for and create a new file"

    | curFile directories directory create file|

    directories := self currentDirectories value.
    (directories size ~= 1) ifTrue:[^ self].
    directory := directories first.
    curFile := self firstSelectedFile.
    curFile notNil ifTrue:[
	file := curFile.
    ] ifFalse:[
	file := directory.
    ].
    create := FileOperation create createFileIn:file.
    create result ifFalse:[ ^ self].
    self updateAndSelect:(OrderedCollection with:(create createdFile)).
!

newHardLink
    "ask for and create a hard link (unix only)"

    self newLink:false.
!

newLink:symbolic

    "ask for and create a symbolic if symbolic is true otherwise a hard link (unix only)"

    | sel create createdFile|

    sel := self currentFileNameHolder value.
    (sel size ~= 1) ifTrue:[^ self].
    symbolic ifTrue:[
	create := FileOperation create createSoftLinkIn:(sel first).
    ] ifFalse:[
	create := FileOperation create createHardLinkIn:(sel first).
    ].
    create result ifFalse:[ ^ self].
    createdFile := create createdFile.
    createdFile notNil ifTrue:[
	self updateAndSelect:(OrderedCollection with:createdFile).
    ].
!

newSoftLink
    "ask for and create a soft link (unix only)"

    self newLink:true.
!

pasteFiles
    "defete current selected files/directories
    "
    | buffer destination files directories copiedFiles|

    files := self clipboard files.
    (files isNil or:[files isEmpty]) ifTrue:[ ^ self ].
    buffer := self clipboard copy.
    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[
	|box dirStringCol|
	dirStringCol := directories collect:[:aDir| aDir asString].
	box := ListSelectionBox new.
	box title:'In which directory you want to paste ?'.
	box list:dirStringCol.
	box okAction:[:sel | destination := sel asFilename].
	box showAtPointer
    ] ifFalse:[
	destination := directories first.
    ].
    copiedFiles := self copyFiles:(buffer files) to:destination.
    
    (self clipboard method == #cut) ifTrue:[
	self deleteFiles:copiedFiles.
    ] 
!

renameFile:aFile 
    "rename the selected file(s)"

    ^ self renameFiles:(OrderedCollection with:aFile).
!

renameFile:filename to:newFileString update:aBoolean
    "rename filename to newFileString"

    |rename|

    rename := FileOperation rename renameFile:filename to:newFileString.
    rename result ifTrue:[
        aBoolean ifTrue:[
            self updateAndSelect:(rename renamedFiles).
        ].
    ] ifFalse:[
        self notifyChannel value:rename errorString.
    ].
    ^ rename result
!

renameFiles:aColOfFiles 
    "rename the selected file(s)"

    |rename|

    rename := FileOperation rename renameFiles:aColOfFiles.
    rename result ifFalse:[
        self notifyChannel value:rename errorString
    ] ifTrue:[
        "/ self updateAndSelect:(rename renamedFiles)
    ].
    ^ rename result
!

renameSelection
    "rename the selected file(s)"

    self renameFiles:self currentFileNameHolder value
! !

!AbstractFileBrowser methodsFor:'menu accessing'!

bookmarksMenuSpec
    "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:FileBrowser andSelector:#bookmarksMenuSpec
     (Menu new fromLiteralArrayEncoding:(AbstractFileBrowser bookmarksMenuSpec)) startUp
    "
    <resource: #programMenu>

    |menuSpec menu bookmarks|

    menuSpec := self class baseBookmarksMenuSpec.
    menu := menuSpec decodeAsLiteralArray.
    menu findGuiResourcesIn:self.
    menu receiver:self.
    bookmarks := self class directoryBookmarks.
    "/ add the history items ...

    bookmarks size > 0 ifTrue:[
	menu addItem:(MenuItem labeled:'-').
	bookmarks do:[:dirName |
	    menu addItem:((MenuItem label:dirName asString value:[
		(self currentDirectories value includes:dirName) ifFalse:[
		    self currentFileNameHolder value:(OrderedCollection with:dirName).
		].
	    ])).
	].
    ].
    ^ menu

    "Modified: / 17.8.1998 / 10:13:05 / cg"
!

canBack


    ^ self dirHistory canBack.
!

canForward

"/    | currentSelection |
"/
"/    currentSelection := self currentDirectories value.
"/    currentSelection size ~~ 1 ifTrue:[ ^ false].
    
    ^ self dirHistory canForward.
!

menuDirHistory:backOrForward
    "initialize the directory menu
    "
    <resource: #programMenu >

    |menu pathList currentSel currentPath|

    menu := Menu new.
    menu receiver:self.

    self dirHistory isEmpty ifTrue:[^ nil].
    backOrForward == #back ifTrue:[
	currentSel := self currentDirectories value.
	currentSel size == 1 ifTrue:[
	    currentPath := currentSel first asString.
	] ifFalse:[
	    currentPath := nil.
	].
	pathList := self dirHistory getBackCollectionFrom:currentPath.
    ] ifFalse:[
	pathList := self dirHistory getForwardCollection.
    ].
    pathList isEmpty ifTrue:[ ^ nil].
    pathList do:[:aPath| 
	| menuItem |
	menuItem := MenuItem new.
	menuItem label:aPath.
	menuItem value:[
	    self currentFileNameHolder value:(OrderedCollection with:(aPath asFilename)).
	].
	menu addItem:menuItem.
    ].
    ^ menu
!

menuDirHistoryBack
    "initialize the directory menu
    "
    <resource: #programMenu >

    ^ self menuDirHistory:#back.
!

menuDirHistoryForward
    "initialize the directory menu
    "
    <resource: #programMenu >

    ^ self menuDirHistory:#forward.
!

menuFileHistory
    "initialize the file history menu
    "
    <resource: #programMenu >

    |menu hist text removeItem removeCol|

    menu := Menu new.
    menu findGuiResourcesIn:self.
    menu receiver:self.

    hist := self fileHistory.
    hist isEmpty ifTrue:[^ nil].
    text := LabelAndIcon icon:(self class clearHistoryIcon) string:(resources string:'Clear File History').
    removeCol := OrderedCollection new.
    hist do:[:aFileItem|
	aFileItem fileName exists ifTrue:[
	    menu addItem:(MenuItem label: aFileItem fileName asString value:[
		self currentFileNameHolder value:(OrderedCollection with:(aFileItem fileName)).
		self openApplByFileItem:aFileItem
	    ]).
	] ifFalse:[
	    removeCol add:aFileItem.
	]
    ].
    "/ remove all not existing history entries
    removeCol do:[ : el |
	hist remove:el.
    ].
    removeItem := MenuItem new.
    removeItem translateLabel:true.
    removeItem label:text.
    removeItem value:[
	self fileHistory removeAll.
	self enableFileHistory value:false.
    ].
    menu addItem:(MenuItem label:'-').
    menu addItem:removeItem.
    ^ menu
!

sortMenu

    <resource: #programMenu >

    |menu|

    menu :=  Menu new fromLiteralArrayEncoding:self class sortMenu.
    menu ifNil:[ ^ nil ].
    menu findGuiResourcesIn:self.
    menu receiver:self.
    ^ menu
!

viewDetailsMenuSpec
    ^self class viewDetailsMenuSpec
!

viewInContentsBrowserMenu

    ^ self application:#DirectoryContentsBrowser do:#viewBrowserMenu
!

visitedDirectoriesMenu

    <resource: #programMenu >

    |menu histCopy text removeItem|

    menu := Menu new.
    menu receiver:self.

    self dirHistory isEmpty ifTrue:[^ nil].
    text := LabelAndIcon icon:(self class clearHistoryIcon) string:(resources string:'Clear History').
    removeItem := MenuItem new.
    removeItem translateLabel:true.
    removeItem label:text.
    removeItem value:[
	self dirHistory removeAll.
	self enableForward value:self canForward.
	self enableBack value:self canBack.
    ].
    histCopy := self dirHistory.
    histCopy do:[:aFile| 
	menu addItem:(MenuItem label:aFile asString value:[
	    self currentFileNameHolder value:(OrderedCollection with:(aFile path asFilename)).
	]).
    ].
    menu addItem:(MenuItem label:'-').
    menu addItem:removeItem.
    ^ menu
! !

!AbstractFileBrowser methodsFor:'menu actions cvs'!

cvsAddAndCommit

    |sel log cmd dir executionBlock nameString block|

    log := Dialog
	requestText:(resources string:'enter initial log message')
	lines:10
	columns:70
	initialAnswer:nil.

    sel := self currentSelectedFiles.
    executionBlock := [ : stream |
	log notNil ifTrue:[
	    sel size > 0 ifTrue:[
		sel do:[:fn |
		    dir := self getDirWithoutFileName:fn.
		    cmd := ('cvs add -m ''' , log , ''' ' , fn baseName).
		    block := self getExecutionBlockForCommand:cmd inDirectory:dir.
		    block value:stream.
		    cmd := ('cvs commit -l -m ''' , log , ''' ' , fn baseName).
		    block := self getExecutionBlockForCommand:cmd inDirectory:dir.
		    block value:stream.
		]
	    ] 
	]
    ].
    nameString := 'Command> cvs add and commit'.
    self makeExecutionResultProcessFor:executionBlock withName:nameString.
!

cvsCommit

    |nSel log msg cmd selectedFiles sel executionBlock nameString|

    selectedFiles:= self currentSelectedFiles.
    nSel := selectedFiles size.

    nSel == 1 ifTrue:[
	msg := resources string:'enter log message for checkIn of ''%1''' with:(selectedFiles first baseName)
    ] ifFalse:[
	nSel > 1 ifTrue:[
	    msg := resources string:'enter log message for %1 files to checkIn' with:nSel printString
	] ifFalse:[
	    msg := resources string:'enter log message for checkIn'
	]
    ].

    log := Dialog
	requestText:msg
	lines:10
	columns:70
	initialAnswer:nil.

    log notNil ifTrue:[
	sel := self currentFileNameHolder value.
	sel isEmpty ifTrue:[ ^ self ].
	executionBlock := [ : stream |
	    log notNil ifTrue:[
		sel size > 0 ifTrue:[
		    sel do:[:fn |
			| dir block |
			dir := fn directory.
			cmd := ('cvs commit -m ''' , log , ''' ' , fn baseName).
			block := self getExecutionBlockForCommand:cmd inDirectory:dir.
			block value:stream.
		    ]
		] 
	    ]
	].
    ].
    nameString := 'Command> cvs commit'.
    self makeExecutionResultProcessFor:executionBlock withName:nameString.
!

cvsRemoveAndRemoveFromCVS:filesToRemove
    "remove the selected file(s) and their CVS containers - no questions asked"

    |msg toRemove updateRunning cmd executionBlock nameString|

    updateRunning := self backgroundProcesses value notEmpty.
    self killAllRunningBackgroundProcesses.
    toRemove := OrderedCollection new.

    executionBlock := [ : stream |
	| block |
	filesToRemove do:[:fileName |
	    OperatingSystem accessDeniedErrorSignal handle:[:ex|
		"was not able to remove it"
		| lastError |
		lastError := OperatingSystem lastErrorString.
		msg := (resources string:'cannot remove ''%1'' !!' with:fileName).
		lastError isNil ifFalse:[
		    msg := msg , '\\(' , lastError , ')'
		].
		Dialog warn:msg withCRs
	    ] do:[
		|answer contents|

		(fileName isSymbolicLink not) ifTrue:[
		    fileName remove.
		    cmd := ('cvs remove -f ' , fileName baseName).
		    block := self getExecutionBlockForCommand:cmd.
		    block value:stream.
		]
	    ].
	].

	cmd := ('cvs commit -m ''removed via FileBrowser''').
	block := self getExecutionBlockForCommand:cmd. 
	block value:stream.
    ].
    nameString := 'Command> cvs remove and commit ', filesToRemove first baseName.
    filesToRemove size > 1 ifTrue:[
	nameString := nameString, ' ...'.
    ].
    self makeExecutionResultProcessFor:executionBlock withName:nameString.
!

cvsRemoveFileAndCVSContainer

    |sel question aswer|

    sel := self currentSelectedFiles.

    sel size > 0 ifTrue:[
	sel size > 1 ifTrue:[
	    question := resources string:'Remove %1 selected files and their CVS containers ?' with:(sel size)
	] ifFalse:[
	    question := resources string:'Remove ''%1'' and its CVS container ?' with:(sel first baseName allBold)
	].

	aswer := Dialog 
		confirm:question withCRs
		yesLabel:(resources at:'Remove')
		noLabel:(resources at:'Cancel').
	aswer ifTrue:[
	    self withCursor:(Cursor wait) do:[
		self cvsRemoveAndRemoveFromCVS:sel
	    ]
	]
    ]
!

cvsUpdateAll

    | cmd |

    cmd := 'cvs upd -l'.
    self executeCommand:cmd.
!

cvsUpdateAllRecursive

    | cmd |

    cmd := 'cvs upd -d'.
    self executeCommand:cmd.
!

cvsUpdateSelection

    | selectedFiles stream|


    selectedFiles:= self currentSelectedFiles.
    stream := WriteStream on:''.
    stream nextPutAll:'cvs upd '.
    selectedFiles do:[: file |
	stream nextPutAll:file baseName.
	stream space.
    ].
    self executeCommand:stream contents.
    stream close.
! !

!AbstractFileBrowser methodsFor:'menu actions edit'!

copyInDirContentsBrowser

    ^ self application:#DirectoryContentsBrowser do:#doCopy.
!

cutInDirContentsBrowser

    ^ self application:#DirectoryContentsBrowser do:#doCut.
!

deleteInDirContentsBrowser

    ^ self application:#DirectoryContentsBrowser do:#doDelete.
! !

!AbstractFileBrowser methodsFor:'menu actions tools'!

createProjectAndOpenProjectBrowser
    |nm f s directory|

    self currentFilesAreInSameDirectory ifFalse:[^ self].
    directory := self currentDirectories value first.
    nm := directory baseName.
    f := (directory  construct:nm) withSuffix:'prj'.
    f exists ifTrue:[
	Dialog warn:'A file named ' , f baseName , ' already exists.'.
	^ self.
    ].
    s := f writeStream.
    s nextPutAll:'
name            ''' , nm , '''
type            #classLibrary
package         #''private:' , nm , '''
prerequisites   nil

classes      #( )
'.
    s close.
    ProjectBrowser openOnFile:f.
!

doMake

    | cmd |

    cmd := 'make'.
    self executeCommand:cmd.
!

fileFileIn
    "fileIn the selected file(s)"

    self fileFileInLazy:false 
!

fileFileInLazy
    "fileIn the selected file(s). Do a quick load (no compilation)"

    self fileFileInLazy:true 
!

fileFileInLazy:lazy
    "fileIn the selected file(s)"

    | selectedFiles|

    self withWaitCursorDo:[
	selectedFiles:= self currentSelectedFiles.
	selectedFiles do:[:fileName |
	    self singleFileFileIn:fileName lazy:lazy
	].
    ].
!

fileFileInToNameSpace
    "fileIn the selected file(s)<into a nameSpace"

    |ns listOfKnownNameSpaces|

    listOfKnownNameSpaces := Set new.
    NameSpace 
	allNamespaces 
	    do:[:eachNameSpace | 
		listOfKnownNameSpaces add:eachNameSpace name
	    ].
    listOfKnownNameSpaces := listOfKnownNameSpaces asOrderedCollection sort.

    ns := Dialog 
		request:'During fileIn, new classes are created in nameSpace:'
		initialAnswer:(LastEnforcedNameSpace ? Class nameSpaceQuerySignal query name)
		list:listOfKnownNameSpaces.
    ns isEmptyOrNil ifTrue:[^ self].

    LastEnforcedNameSpace := ns.
    ns := NameSpace name:ns.

    Class nameSpaceQuerySignal 
	answer:ns
	do:[ 
	    self fileFileInLazy:false 
	] 
!

fileFindAllDuplicates
    "scan directory and all subdirs for duplicate files"

    |fileNames dir infoDir filesBySize
     result info dirPrefix myName stream textBox maxLength directories|


    self withWaitCursorDo:[
	result := Dictionary new.
	myName := self class name asString.
	directories := self currentSelectedDirectories.
	directories isEmpty ifTrue:[^ self].
        
	dir := directories first.
"/        self label: myName, '- gathering file names ...'.
	fileNames := dir recursiveDirectoryContents.
	fileNames := fileNames collect:[:fn | dir construct:fn].
	fileNames := fileNames select:[:fn | fn isDirectory not].

"/        self label:myName , '- gathering sizes ...'.
	infoDir := Dictionary new.
	fileNames do:[:fn |
	    infoDir at:fn put:(fn fileSize)
	].

	"/ for each, get the files size.
	"/ in a first pass, look for files of the same size and
	"/ compare them ...

"/        self label:myName , '- preselect possible duplicates ...'.
	filesBySize := Dictionary new.
	infoDir keysAndValuesDo:[:fn :sz |
	    |entry|

	    entry := filesBySize at:sz ifAbsentPut:[Set new].
	    entry add:fn.
	].

	"/ any of same size ?

"/        self label:myName , '- checking for duplicates ...'.
	filesBySize do:[:entry |
	    |files|

	    entry size > 1 ifTrue:[
		files := entry asArray.
		1 to:files size-1 do:[:idx1 |
		    idx1+1 to:files size do:[:idx2 |
			|fn1 fn2|

			fn1 := files at:idx1.
			fn2 := files at:idx2.

"/                        self label:myName , '- checking ' , fn1 baseName , ' vs. ' , fn2 baseName , ' ...'.
			(result at:fn2 ifAbsent:nil) ~= fn1 ifTrue:[
			    "/ compare the files
			    (fn1 sameContentsAs:fn2) ifTrue:[
"/                                Transcript show:'Same: '; show:fn1 baseName; show:' and '; showCR:fn2 baseName.
				result at:fn1 put:fn2.
			    ]
			]
		    ]
		]
	    ]
	].

"/        self label:myName , '- sorting ...'.
	dirPrefix := dir pathName.
	result := result associations.
	result := result collect:[:assoc |
					|f1 f2|

					f1 := assoc key name.
					f2 := assoc value name.
					(f1 startsWith:dirPrefix) ifTrue:[
					    f1 := f1 copyFrom:dirPrefix size + 2.
					].
					(f2 startsWith:dirPrefix) ifTrue:[
					    f2 := f2 copyFrom:dirPrefix size + 2.
					].
					f1 < f2 ifTrue:[
					    f2 -> f1
					] ifFalse:[
					    f1 -> f2
					]
				].
	result sort:[:f1 :f2 | f2 value < f1 value].

	info := OrderedCollection new.
	result do:[:assoc |
	    info add:(assoc key , ' same as ' , assoc value)
	].
	info isEmpty ifTrue:[
	    info := 'No duplicate files found.'
	].
    ].

    stream := WriteStream on:''.
    info do:[:el|
	stream nextPutAll:el.
	stream cr.
    ].
    textBox := TextBox new.
    textBox initialText:(stream contents).
    textBox title:'File dublicates in directory: ', dir asString.
    textBox readOnly:true.
    textBox noCancel.
    textBox label:'Dublicates in ', dir asString.
    maxLength := 10.
    info do:[: el |
	maxLength := maxLength max:(el size).
    ].
    textBox extent:((maxLength * 5)@(info size * 20)); sizeFixed:false.
    textBox showAtPointer.
    stream close.
"/    subView contents:info.
"/    self label:myName.
!

fileFindDuplicates
    "scan directory for duplicate files"

    |fileNames infoDir filesBySize
     result info stream textBox maxLength directories allFiles titleStream size|

"/    (self askIfModified:'contents has not been saved.\\Modifications will be lost when you proceed.'
"/              yesButton:'proceed') ifFalse:[^ self].

    self withWaitCursorDo:[
	result := Dictionary new.

	directories := self currentSelectedDirectories.
	directories isEmpty ifTrue:[^ self].

	allFiles := OrderedCollection new.
	directories do:[ : dir|
	    fileNames := dir directoryContents.
	    fileNames := fileNames collect:[:fn | dir construct:fn].
	    fileNames := fileNames select:[:fn | fn isDirectory not].
	    allFiles addAll:fileNames.
	].

	infoDir := Dictionary new.
	allFiles do:[:fn |
	    infoDir at:fn put:(fn info)
	].

	"/ for each, get the files size.
	"/ in a first pass, look for files of the same size and
	"/ compare them ...

	filesBySize := Dictionary new.
	infoDir keysAndValuesDo:[:fn :info |
	    |sz entry|

	    sz := info size.
	    entry := filesBySize at:sz ifAbsentPut:[Set new].
	    entry add:fn.
	].

	"/ any of same size ?

	filesBySize do:[:entry |
	    |files|

	    entry size > 1 ifTrue:[
		files := entry asArray.
		1 to:files size-1 do:[:idx1 |
		    idx1+1 to:files size do:[:idx2 |
			|fn1 fn2|

			fn1 := files at:idx1.
			fn2 := files at:idx2.

			(result at:fn2 ifAbsent:nil) ~= fn1 ifTrue:[
			    "/ compare the files
			    (fn1 sameContentsAs:fn2) ifTrue:[
"/                                Transcript show:'Same: '; show:fn1 baseName; show:' and '; showCR:fn2 baseName.
				result at:fn1 put:fn2.
			    ]
			]
		    ]
		]
	    ]
	].

	result := result associations.
	result := result collect:[:assoc |
					|f1 f2|

					f1 := assoc key asString.
					f2 := assoc value asString.
					f1 < f2 ifTrue:[
					    f2 -> f1
					] ifFalse:[
					    f1 -> f2
					]
				].
	result sort:[:f1 :f2 | f2 value < f1 value].

	info := OrderedCollection new.
	size := self getBestDirectory asString size.
	result do:[:assoc |
	    |fn1 fn2|

	    fn1 := assoc key.
	    fn2 := assoc value.
	    size > 1 ifTrue:[
		fn1 := ('..', (fn1 copyFrom:(size + 1))).
		fn2 := ('..', (fn2 copyFrom:(size + 1))).
	    ].
	    (fn1 includes:Character space) ifTrue:[
		fn1 := '"' , fn1 , '"'
	    ].
	    (fn2 includes:Character space) ifTrue:[
		fn2 := '"' , fn2 , '"'
	    ].
	    info add:(fn1 , ' same as ' , fn2)
	].
	info isEmpty ifTrue:[
	    info add:'No duplicate files found.'
	].
    ].
    stream := WriteStream on:''.
    info do:[:el|
	stream nextPutAll:el.
	stream cr.
    ].
    titleStream := WriteStream on:''.
    titleStream nextPutAll:'File dublicates in director'.
    directories size == 1 ifTrue:[
	titleStream nextPutAll:'y: ', directories first asString.
    ] ifFalse:[
	titleStream nextPutAll:'ies: '.
	titleStream cr.
	directories do:[:dir|
	    size > 1 ifTrue:[
		titleStream nextPutAll:'..'.
		titleStream nextPutAll:((dir asString) copyFrom:(size + 1)).
	    ] ifFalse:[
		titleStream nextPutAll:(dir asString).
	    ].
	    titleStream cr.
	]
    ].
    
    textBox := TextBox new.
    textBox initialText:(stream contents).
    textBox title:(titleStream contents).
    textBox readOnly:true.
    textBox noCancel.
    stream := WriteStream on:'Dublicates in '.
    directories do:[ :aDirectory |
	stream nextPutAll:aDirectory baseName
	stream space
    ].
    textBox label:stream contents.
    maxLength := 10.
    info do:[: el |
	maxLength := maxLength max:(el size).
    ].
    textBox extent:((maxLength * 5)@(info size * 10)); sizeFixed:false.
    textBox showAtPointer.
    titleStream close.
    stream close.
!

fileFindFile
    |filename files|

    files := self currentFileNameHolder value.
    files notEmpty ifTrue:[
	filename := files first.
    ] ifFalse:[
	filename := (Filename homeDirectory).
    ].
    FindFileApplication openOnFileName:filename for:self.
!

installAllAsAutoloaded
    "install all classes found here as autoloaded classes"

    self allItemsOfCurrentDirectory do:[:fileItem |
	(fileItem hasMimeType and:[fileItem mimeType isSmalltalkSource]) ifTrue:[
	    self installAsAutoloaded:(fileItem fileName).
	]
    ].
!

installAsAutoloaded:aFilename
    "install aFilename as autoloaded class"

    |chunks s|

    chunks := ChangeSet fromStream:(s := aFilename asFilename readStream). s close.
    chunks 
	select:[:eachChunk | eachChunk isClassDefinitionChange]
	thenDo:[:eachClassChunk | eachClassChunk installAsAutoloadedClassIfNotPrivate].
!

loadImageAndPerform:aSelectorOrBlock

    |img path files|

    files := self currentSelectedFiles.
    files isEmpty ifTrue:[ ^ self].
    files do:[:fileName |
	path := fileName.
	path isDirectory ifFalse:[
	    img := Image fromFile:(path pathName).
	    img notNil ifTrue:[
		aSelectorOrBlock isSymbol ifTrue:[
		    img perform:aSelectorOrBlock
		] ifFalse:[
		    aSelectorOrBlock value:img
		]
	    ] ifFalse:[
		Dialog warn:'unknown format: ' , fileName asString
	    ]
	]
    ].
!

openASN1Browser

    self openTool:OSI::ASN1Browser 
!

openAppletViewer
    |numItems files|

    files := self currentSelectedFiles.
    (numItems := files size) > 2 ifTrue:[
	(self 
	    confirm:(resources string:'open for each of the %1 items ?' 
				 with:numItems)) ifFalse:[^ self].
    ].

    Java startupJavaSystem.
"/    Java markAllClassesUninitialized.
"/    Java initAllStaticFields.
"/    Java initAllClasses.

    files do:[:fileName |
	|p path|

	path := fileName.
	path isDirectory ifFalse:[
	    p := Java 
		    javaProcessForMainOf:(Java classForName:'sun.applet.AppletViewer')
		    argumentString:path pathName.
	    p resume.
	]
    ].
!

openCBrowser

    |directories|

    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[ ^ self].
    self withWaitCursorDo:[
	CBrowser::Browser openIn:directories first.
    ]
!

openChangeSetBrowser
    self
        openTool:ChangeSetBrowser 
        with:#openOnFile: 
        ignoreDirectories:true
!

openChangesBrowser
    "open a change browser on the selected file(s)"

    self openTool:(UserPreferences current changesBrowserClass)
!

openDiffView
    "open a diff-view"

    | name1 name2 text1 text2 d err nm l1 files title defaultName lastFile|

    files := self currentSelectedFiles.
    files isEmpty ifTrue:[
	Dialog warn:'you have to select a file first'.
	^ self.
    ].
    (files size == 2) ifTrue:[
	name1 := files last.
	name2 := files first.
    ] ifFalse:[
	LastFileDiffFile notNil ifTrue:[
	    | directories |
	    directories := self currentDirectories value.
	    directories notEmpty ifTrue:[
		lastFile := directories first asFilename construct:(LastFileDiffFile baseName).
		(lastFile exists and:[lastFile isReadable]) ifTrue:[
		    name1 := lastFile.
		]
	    ]
	].
	name2 := files first.
	title := 'show difference between ', name2 baseName, ' and:'.
	defaultName := name1 notNil ifTrue:[name1 baseName] ifFalse:[nil].
	name1 := DialogBox 
		    requestFileName:title 
		    default:defaultName 
		    ok:'OK' 
		    abort:'Use File List' 
		    pattern:'*' 
		    fromDirectory:(name2 asFilename directory).



    ].

    (name1 isNil or:[name1 asString isEmpty]) ifTrue:[
	text1 := self getAllFilesAsStringCollection asStringCollection withTabs.
	text1 := text1 collect:[:l | l isNil ifTrue:[' '] ifFalse:[l]].
	name1 := nil.
	l1 := 'browser contents'
    ] ifFalse:[
	name1 := name1 asFilename.
	LastFileDiffFile := name1.
	name1 asFilename isReadable ifFalse:[
	    nm := name1.
	    name1 asFilename exists ifFalse:[
		err := '%1 does not exist'.
	    ] ifTrue:[
		err := '%1 is not readable'
	    ].
	].
	l1 := name1
    ].

    err isNil ifTrue:[
	name2 isReadable ifFalse:[
	    nm := name2.
	    name2 exists ifFalse:[
		err := '%1 does not exist'.
	    ] ifTrue:[
		err := '%1 is not readable'
	    ].
	].
    ].
    err notNil ifTrue:[
	Dialog warn:(resources string:err with:nm pathName).
	^ self
    ].

    self withWaitCursorDo:[
	name1 notNil ifTrue:[
	    text1 := name1 contents.
	].
	text2 := name2 contents.
	text1 = text2 ifTrue:[
	    self information:'same contents'
	] ifFalse:[
	    d := DiffTextView 
		    openOn:text1 label:l1
		    and:text2 label:name2 pathName.
	    d topView label:'file differences'.
	]
    ]
!

openEditor
    self openTool:EditTextView
!

openHTMLReader

    self openTool:HTMLDocumentView ignoreDirectories:false
!

openImageEditor

    [self loadImageAndPerform:#edit] fork
!

openImageInspector
    [self loadImageAndPerform:#inspect] fork
!

openImagePreview

    [self loadImageAndPerform:[:img |
				|i top viewer|

				top := StandardSystemView new.

				viewer := ImageView origin:0.0@0.0 corner:1.0@1.0 in:top.
				i := img.
				top extent:200@200.
				top label:(img fileName asFilename directoryName asFilename baseName , '/' , img fileName asFilename baseName).
				top openAndWait.

				(i width > 200 or:[i height > 200]) ifTrue:[
				    i := i magnifiedPreservingRatioTo:200@200.
				].
				viewer image:i.
			      ].
    ] fork
!

openMP3Player
    |file|

    file := self currentSelectedFiles.
    (file isEmpty) ifTrue:[
	^ self.
    ].
    file := file first.
    (MP3PlayerApplication ? SaugFix::MP3PlayerApplication) playSong:file.
!

openSlideShow

    |directories dir|

    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[^ self].

    dir := directories first.
    CodingExamples_GUI::SlideShow openIn:dir.
!

openSnapshotImageBrowser
    ^ self openTool:SystemBrowser with:#openOnSnapShotImage: ignoreDirectories:true
!

openTerminal

    |directories dir|

    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[
	dir := Filename homeDirectory.
    ] ifFalse:[
	dir := directories first.
    ].

    VT100TerminalView openShellIn:dir.
!

openTool:aToolClass
    "open a tool on the selected file(s)"

    ^ self openTool:aToolClass ignoreDirectories:true
!

openTool:aToolClass ignoreDirectories:ignoreDirs
    "open a tool on the selected file(s)"

    ^ self
	openTool:aToolClass 
	with:#openOn: 
	ignoreDirectories:ignoreDirs
!

openTool:aToolClass with:aSelector ignoreDirectories:ignoreDirs
    "open a tool on the selected file(s)"

    |numItems path tool files|

    aToolClass isNil ifTrue:[
	Dialog warn:'Sorry, that tool seems to be not available'.
	^ nil.
    ].
    files := self currentSelectedFiles.
    
    (numItems := files size) > 2 ifTrue:[
	(self 
	    confirm:(resources string:'open for each of the %1 items ?' 
				 with:numItems)) ifFalse:[^ self].
    ].

    self withWaitCursorDo:[
	files do:[:fileName |
	    (ignoreDirs not or:[fileName isDirectory not]) ifTrue:[
		fileName isAbsolute ifTrue:[
		    path := fileName getName.
		] ifFalse:[
		    path := fileName pathName.
		].
		tool := aToolClass perform:aSelector with:path.
	    ]
	].
    ].
    ^ tool
!

openZipTool
    |zipTool directories dir|

    (zipTool := self openTool:ZipTool) notNil ifTrue:[
	directories := self currentSelectedDirectories.
	directories isEmpty ifTrue:[
	    dir := directories first.
	] ifFalse:[
	    dir := Filename homeDirectory.
	].

	zipTool initialExtractDirectory:dir.
    ].
!

readAbbrevFile
    "read the abbrev file and install classes found there as autoloaded classes"

    | directories dir|

    directories := self currentSelectedDirectories.
    directories isEmpty ifTrue:[^ self].

    dir := directories first.
    Smalltalk installAutoloadedClassesFrom:(dir construct:'abbrev.stc').
!

singleFileFileIn:fileName lazy:lazy
    "fileIn the selected file(s)"

    |aStream wasLazy|

    fileName type == #regular ifTrue:[

	(ObjectFileLoader notNil
	and:[ObjectFileLoader hasValidBinaryExtension:fileName]) ifTrue:[
	    AbortOperationRequest catch:[
		|p|

		"/
		"/ look if already loaded ...  then unload first
		"/
		p := fileName pathName.
		(ObjectFileLoader loadedObjectFiles includes:p) ifTrue:[
		    (Dialog confirm:(resources 
					string:'%1 is already loaded; load anyway ?'
					with:p)) ifFalse:[
			^ self
		    ].
		    Transcript showCR:'unloading old ' , p , ' ...'.
		    ObjectFileLoader unloadObjectFile:p. 
		].

		Transcript showCR:'loading ' , p , ' ...'.
		ObjectFileLoader loadObjectFile:p.
		Class addInfoRecord:('fileIn ' , fileName asFilename pathName) 
	    ]
	] ifFalse:[ ((fileName hasSuffix:'cls') 
		     and:[((fileName mimeTypeOfContents ? '') startsWith:'application/x-smalltalk-source') not ]) ifTrue:[
	    "/ loading a binary class file
	    aStream := fileName readStream.
	    aStream notNil ifTrue:[
		aStream fileInBinary.
	    ]
	] ifFalse:[
	    ((fileName hasSuffix:'class')
	    or:[(fileName hasSuffix:'cla')]) ifTrue:[
		"/ loading a java class file
		JavaClassReader notNil ifTrue:[
		    JavaClassReader loadFile:(fileName pathName)
		]
	    ] ifFalse:[ (fileName hasSuffix:'sif') ifTrue:[
		"/ loading a sif (smalltalk interchange format) file
		SmalltalkInterchangeSTXFileInManager autoload.    
		SmalltalkInterchangeFileManager newForFileIn
		    fileName: fileName pathName;
		    fileIn.
	    ] ifFalse:[ (fileName hasSuffix:'pcl') ifTrue:[
		Parcel isNil ifTrue:[
		    Dialog warn:'Parcel support not loaded.'
		] ifFalse:[
		    Parcel loadParcelFrom: fileName pathName
		]
	    ] ifFalse:[
		"/ loading a regular (chunk) or xml source file
		aStream := fileName readStream.
		aStream notNil ifTrue:[
		    Error handle:[ : ex |
			Dialog warn:'Error on file in: ', ex errorString.
		    ] do:[
			[
			    Class withoutUpdatingChangesDo:[
				wasLazy := Compiler compileLazy:lazy.
				aStream fileIn.
			    ].
			    Class addInfoRecord:('fileIn ' , fileName asString) 
			] ensure:[
			    Compiler compileLazy:wasLazy.
			    aStream close
			]
		    ]
		]
	    ]]]
	]]
    ].
! !

!AbstractFileBrowser methodsFor:'menu queries cvs'!

canCvsAddAndCommit

    |selectedFiles|

    selectedFiles := self currentSelectedFiles.
    ^ (selectedFiles notEmpty and:[self currentFilesAreInSameDirectory]).
!

canRemoveCVSContainer

    |selectedFiles dirOfFile cvsDir|

    selectedFiles := self currentSelectedFiles.
    selectedFiles isEmpty ifTrue:[^ false].
    ^ ((selectedFiles detect:[:fileName|
	dirOfFile := self getDirWithoutFileName:fileName.
	cvsDir := dirOfFile construct:'CVS'.
	(cvsDir isDirectory and:[cvsDir exists])
    ] ifNone:[nil]) notNil).
! !

!AbstractFileBrowser methodsFor:'menu queries tools'!

anySTFilesPresent

    ^ self anyFilesPresentWithSuffix:'st'
!

canCreateNewProject

    | selectedFiles |

    self currentFilesAreInSameDirectory ifFalse:[^ false].
    selectedFiles := self currentSelectedFiles.
    ^ [ 
	((selectedFiles detect:[:fileName| | suffix|
	    suffix := fileName suffix asLowercase.
	    (suffix = 'prj' or:[suffix = 'st'])
	] ifNone:[nil]) notNil)
      ]
!

canDoTerminal

    ^ OperatingSystem isUNIXlike
      or:[OperatingSystem isMSWINDOWSlike]
!

canDoTerminalAndSystemIsDOS

    ^ self canDoTerminal and:[OperatingSystem isMSWINDOWSlike]
!

canDoTerminalAndSystemIsUnix

    ^ self canDoTerminal and:[OperatingSystem isUNIXlike]
!

canReadAbbrevFile


    self currentFilesAreInSameDirectory ifFalse:[^ false].
    ^ (self currentDirectories value first construct:'abbrev.stc') exists
!

canRemoveFromSourcePath

    ^ false
!

hasASN1
    ^ [ OSI::ASN1Parser notNil 
	and:[OSI::ASN1Parser isLoaded]]

!

hasASN1AndSelection
    ^ [ self hasSelection value 
	and:[self currentSelectedFiles size > 0
	and:[OSI::ASN1Parser notNil 
	and:[OSI::ASN1Parser isLoaded]]]]
!

hasCBrowser
    ^ [ CBrowser::Browser notNil ]
!

hasJava

    ^ [ JavaClassReader notNil 
	and:[JavaClassReader isLoaded]]
!

hasJavaAndSelection

    ^ [ self currentSelectedFiles size > 0
	and:[JavaClassReader notNil 
	and:[JavaClassReader isLoaded]]]
!

hasMP3Player

    ^ [ MP3PlayerApplication notNil
	or:[SaugFix::MP3PlayerApplication notNil ]]
!

hasMP3PlayerAndSelection

    ^ [ self currentSelectedFiles size > 0
	and:[ self hasMP3Player value]]
!

hasSlideShow

    ^ [CodingExamples_GUI::SlideShow notNil]
!

hasSnapshotSelection

    ^ [ 
	| files |
	files := self currentSelectedFiles.
	((files size == 1)
	and:[ files first hasSuffix:'img' ])
      ]
!

hasZipFileSelected

    ^ [|sel fileName fn suff|

	sel := self currentSelectedFiles.
	sel size == 1 ifTrue:[
	    fileName := sel first.
	    fileName notNil ifTrue:[
		suff := fileName suffix asLowercase.
		suff = 'zip' or:[suff = 'jar']
	    ] ifFalse:[
		false
	    ]
	] ifFalse:[
	    false
	]
      ]
!

javaSupportLoaded

    ^ false
! !

!AbstractFileBrowser methodsFor:'presentation'!

getModeString:modeBits
    "convert file-mode bits into a more user-friendly string.
     This is wrong here - should be moved into OperatingSystem."

    ^ self getModeString:modeBits 
		    with:#( 'owner:' $r $w $x 
			    ' group:' $r $w $x 
			    ' others:' $r $w $x )
!

getModeString:modeBits with:texts
    "convert file-mode bits into a more user-friendly string.
     This is wrong here - should be moved into OperatingSystem."

    |bits modeString|

    bits := modeBits bitAnd:8r777.
    modeString := ''.

    #( nil 8r400 8r200 8r100 nil 8r040 8r020 8r010 nil 8r004 8r002 8r001 ) 
    with: texts do:[:bitMask :access |
	|ch|

	bitMask isNil ifTrue:[
	    modeString := modeString , access
	] ifFalse:[
	    (bits bitAnd:bitMask) == 0 ifTrue:[
		ch := $-
	    ] ifFalse:[
		ch := access
	    ].
	    modeString := modeString copyWith:ch 
	]
    ].
    ^ modeString
! !

!AbstractFileBrowser methodsFor:'queries'!

getFileInfoStringForFirstSelectedFile:longInfo
    "get stat info on selected file - return a string which can be
     shown in a box"

    | selFiles filename text fileOutput type modeBits modeString s ts isLink info|

    selFiles := self currentFileNameHolder value.
    ((selFiles size == 1) not) ifTrue:[ ^ nil].
    filename := selFiles first.

    text := StringCollection new.

    text add:('filename: ', filename asString).
    isLink := filename isSymbolicLink.
    isLink ifTrue:[
	text add:('symbolic link to: ', (filename linkInfo path))
    ].

    info := filename info.
    type := info type.
    (longInfo and:[type == #regular]) ifTrue:[
	fileOutput := filename fileType.
    ].

    s := ('type:   ').
    fileOutput isNil ifTrue:[
	s := s ,  type asString
    ] ifFalse:[
	s := s , 'regular (' , fileOutput , ')'
    ].
    text add:s.
    isLink = true ifTrue:[
	info := filename linkInfo
    ] ifFalse:[
	info := filename info
    ].
    
    text add:('size:   ', (info fileSize) printString).

    modeBits := info mode.
    modeString := self getModeString:modeBits.
    longInfo ifTrue:[
	text add:('access: ', modeString,' ', (modeBits printStringRadix:8)).
    ] ifFalse:[
	text add:('access: ', modeString)
    ].
    text add:('owner:  ',
	       (OperatingSystem getUserNameFromID:(info uid))).
    longInfo ifTrue:[
	text add:('group:  ',
		   (OperatingSystem getGroupNameFromID:(info gid))).

	ts := info accessTime.
	text add:('last access:       ',ts asTime printString ,' ', ts asDate printString). 

	ts := info modificationTime.
	text add:('last modification: ', ts asTime printString, ' ', ts asDate printString).
    ].
    ^ text asString
!

initialCommandFor:fileName into:aBox
    "set a useful initial command for execute box."

    |mime cmd select path suffix|

    path := self getDirWithoutFileName:fileName.
    suffix := fileName asFilename suffix.
    DefaultCommandPerSuffix notNil ifTrue:[
	cmd := DefaultCommandPerSuffix at:suffix ifAbsent:nil.
	cmd notNil ifTrue:[
	    aBox initialText:(cmd , ' ' , fileName baseName) selectFrom:1 to:cmd size.
	    ^ self
	].
    ].
    mime := MIMETypes mimeTypeForSuffix:suffix.
"/    mime notNil ifTrue:[
"/        cmd := self initialCommandForMIME:mime file:path
"/    ].

    "/ XXX should be changed to take stuff from a config file
    "/ XXX or from resources.

    (path type == #regular) ifTrue:[
	path isExecutableProgram ifTrue:[
	    aBox initialText:(fileName , ' <arguments>').
	    ^ self
	].

	select := true.

	"some heuristics - my personal preferences ...
	 (actually this should come from a configfile)"

	(fileName endsWith:'akefile') ifTrue:[
	    aBox initialText:'make target' selectFrom:6 to:11.
	    ^ self
	].

	cmd := self class defaultCommandPerMIME at:mime ifAbsent:nil.
	cmd notNil ifTrue:[
	    select := false
	].

	cmd isNil ifTrue:[

	    suffix := path suffix.
	    (suffix = 'C') ifTrue:[
		cmd := 'g++ -c %1'.
		select := 6.
	    ] ifFalse:[
		suffix := suffix asLowercase.

		(suffix = 'taz') ifTrue:[
		    aBox initialText:'zcat %1 | tar tvf -'.
		    select := false.
		].
		(suffix = 'tar') ifTrue:[
		    cmd := 'tar tvf %1'.
		    select := 7.
		].
		(suffix = 'zoo') ifTrue:[
		    cmd := 'zoo -list %1'.
		    select := 9.
		].
		(suffix = 'zip') ifTrue:[
		    cmd := 'unzip -l %1'.
		    select := 8.
		].
		(suffix = 'jar') ifTrue:[
		    cmd := 'unzip -l %1'.
		    select := 8.
		].
		(suffix = 'z') ifTrue:[
		    (fileName asLowercase endsWith:'tar.z') ifTrue:[
			cmd := 'zcat %1 | tar tvf -'.
			select := false.
		    ] ifFalse:[
			cmd := 'uncompress %1'
		    ].
		].
		(suffix = 'gz') ifTrue:[
		    (fileName asLowercase endsWith:'tar.gz') ifTrue:[
			cmd := ('gunzip < %1 | tar tvf -' ).
			select := false.
		    ] ifFalse:[
			cmd := 'gunzip %1'.
		    ].
		].
		(suffix = 'html') ifTrue:[
		    cmd := 'netscape %1'
		].
		(suffix = 'htm') ifTrue:[
		    cmd := 'netscape %1'
		].
		(suffix = 'uue') ifTrue:[
		    cmd := 'uudecode %1'
		].
		(suffix = 'c') ifTrue:[
		    cmd := 'cc -c %1'.
		    select := 5.
		].
		(suffix = 'cc') ifTrue:[
		    cmd := 'g++ -c %1'.
		    select := 6.
		].
		(suffix = 'xbm') ifTrue:[
		    cmd := 'bitmap %1'
		].
		(suffix = 'ps') ifTrue:[
		    cmd := 'ghostview %1'
		].
		((suffix = '1') or:[suffix = 'man']) ifTrue:[
		    cmd := 'nroff -man %1'.
		    select := 10.
		].
	    ].
	].

	cmd isNil ifTrue:[
	    DefaultCommandPerSuffix isNil ifTrue:[
		cmd := '<cmd>'
	    ] ifFalse:[
		cmd := DefaultCommandPerSuffix 
			at:suffix
			ifAbsent:'<cmd>'.
	    ].
	    cmd := cmd , ' %1'.
	].

	cmd := cmd bindWith:fileName.
	select == false ifTrue:[
	    aBox initialText:cmd
	] ifFalse:[
	    select class == Interval ifTrue:[
		aBox initialText:cmd selectFrom:select start to:select stop
	    ] ifFalse:[
		select isInteger ifFalse:[
		    select := (cmd indexOf:Character space ifAbsent:[cmd size + 1]) - 1.
		].
		aBox initialText:cmd selectFrom:1 to:select
	    ].
	]
    ]
!

isAbstractFileBrowser

    ^ true
!

systemIsDOS

    ^ OperatingSystem isMSDOSlike
!

systemIsUnix
    ^ OperatingSystem isUNIXlike
! !

!AbstractFileBrowser methodsFor:'queries-file'!

allItemsOfCurrentDirectory

    ^ self application:#DirectoryContentsBrowser do:#allItemsOfCurrentDirectory.
!

anyFilesPresentWithSuffix:suffix

    | directories |

    directories := self currentDirectories value.
    directories do:[ : dir|
	(dir directoryContents do:[:f| (f asFilename suffix = suffix) ifTrue:[ ^ true]])
    ].
    ^ false.
!

currentFilesAreInSameDirectory

    ^ (self currentDirectories value size == 1).
!

currentFilesHasDirectories

    ^ self currentDirectories value notEmpty.
!

directoriesForFiles:aFileCol

    ^ ((aFileCol collect:[:file| self getDirWithoutFileName:file]) asSet).
!

fileListIsEmpty

    ^ self application:#DirectoryContentsBrowser do:#fileListIsEmpty.
!

fileListIsNotEmpty

    ^ self fileListIsEmpty not.   
!

fileName:aFilename1 startsWith:aFilename2

" check if aFilename2 starts with the same directories like aFilename1 "

    | file1 file2 |

    aFilename2 isNil ifTrue:[ ^ false].
    aFilename1 isNil ifTrue:[ ^ false].
    file1 := aFilename1 asFilename.
    file2 := aFilename2 asFilename.
    file2 isRootDirectory ifTrue:[ ^ true].
    ((file1 isDirectory) 
    and:[(file2 isDirectory)
    and:[file1 directory = file2 directory]]) ifTrue:[
	^ file1 baseName = file2 baseName
    ].
    ^ (file1 pathName) startsWith:(file2 pathName)
!

getAllFilesAsStringCollection

    ^ self application:#DirectoryContentsBrowser do:#getAllFilesAsStringCollection.
!

getBestDirectory

    |selFiles stringCol firstPre|

    selFiles := self currentDirectories value.
    selFiles isEmpty ifTrue:[^ nil].
    selFiles size == 1 ifTrue:[^ selFiles first].
    stringCol := (selFiles collect:[: file| file asString]) asOrderedCollection.
    firstPre := stringCol at:1.
    stringCol from:2 do:[:el|
	 firstPre :=  firstPre commonPrefixWith:el.
    ].
    (firstPre endsWith:(OperatingSystem fileSeparator)) ifTrue:[
	firstPre removeLast.
    ].
    ^ firstPre asFilename
!

getCommonForCurrentFiles

    |selFiles stringCol firtsPre|

    selFiles := self currentFileNameHolder value.
    selFiles isEmpty ifTrue:[^ nil].
    stringCol := selFiles collect:[: file| file asString].
    firtsPre := stringCol at:1.
    stringCol from:2 do:[:el|
	 firtsPre :=  firtsPre commonPrefixWith:el.
    ].
    ^ firtsPre asFilename
!

getDirWithoutFileName:aFileName

    | dir |
    aFileName isNil ifTrue:[
	^ aFileName.    
    ].
    dir := aFileName asFilename.
    dir isDirectory ifFalse:[
	dir := dir directory.
    ].
    ^ dir.
!

getInfoItem
    "get filename of a description-file (.dir.info, README etc.);
     This file is automatically shown when a directory is enterred.
     You can add more names below if you like."

    |directories|

    directories := self currentSelectedDirectories.
    (directories size ~= 1) ifTrue:[ ^ nil].

    #( 
       '.dir.info'
       'README'
       'ReadMe'
       'Readme'
       'readme'
       'read.me'
       'Read.me'
       'READ.ME'
       'README.TXT'
       'readme.txt'
       'Readme.txt'
       'Info.txt'
       'info.txt'
       'INFO.TXT'
    ) do:[:f | 
	|n dir|

	n := (directories first) construct:f.
	(n isReadable and:[n isDirectory not]) ifTrue:[
	    ^ DirectoryContentsBrowser itemClass fileName:n
	]
    ].
    ^ nil
! !

!AbstractFileBrowser methodsFor:'selection'!

currentSelectedDirectories

    ^ self currentDirectories value.
!

currentSelectedFiles

    | files |
    files := self currentFileNameHolder value.
    ^ (files select:[: file | file isDirectory not]).
!

firstSelectedFile

    | files |
    files := self currentFileNameHolder value.
    ^ (files detect:[: file | file isDirectory not] ifNone:[nil]).
! !

!AbstractFileBrowser methodsFor:'sorting'!

currentSortOrder

    " returns a Ordered Collection of all directories currently selected 
      if only a file is selected currentDirectories holds the directory of the file
    "

    ^ self aspectFor:#currentSortOrder ifAbsent:[ Dictionary new asValue ].
!

makeDirectorySortBlockFor:aSortBlock

    self sortDirectoriesBeforeFiles value ifTrue:[
	^ [:a :b|
	    |aIsDir bIsDir res|

	    aIsDir := a isDirectory.
	    bIsDir := b isDirectory.
	    (aIsDir ~~ bIsDir) ifTrue:[
		res := aIsDir 
	    ] ifFalse:[
		res := aSortBlock value:a value:b.
	    ].
	    res
	  ].
    ] ifFalse:[
	^ aSortBlock
    ].
!

sortBlockHolder
    |nameSortBlock|

    ^ self aspectFor:#sortBlockHolder ifAbsent:[
	self sortCaseless value ifTrue:[
	    nameSortBlock := [ :a :b | a asString asLowercase < b asString asLowercase.].
	] ifFalse:[
	    nameSortBlock := [ :a :b | a asString < b asString.].
	].
	(self makeDirectorySortBlockFor:nameSortBlock) asValue.
    ].
!

sortBlockProperty

    
    ^ self aspectFor:#sortBlockProperty ifAbsent:[ #baseName asValue ].
!

sortCaseless
    " aspect for sort caseless "

    ^ self aspectFor:#sortCaseless ifAbsent:[
        | holder |
        holder := (Filename isCaseSensitive not) asValue.
        holder
    ]
!

sortDirectoriesBeforeFiles

    " aspect for sort directories always before files"
    ^ self aspectFor:#sortDirectoriesBeforeFiles ifAbsent:[ true asValue ].
!

sortFileListsBy:instanceName 

    self sortFileListsBy:instanceName withReverse:true
!

sortFileListsBy:instanceName withReverse:aBoolean

    | aSymbol sortCaselessLocal currentSortOrder cmpOp instanceSortBlock sortReverse|

    aSymbol := instanceName asSymbol.
    self sortBlockProperty setValue:instanceName asSymbol.
    sortCaselessLocal := self sortCaseless value.
    currentSortOrder := self currentSortOrder value.
    currentSortOrder isEmpty ifTrue:[
	currentSortOrder at:#column put:aSymbol.
	currentSortOrder at:#reverse put:false.
	currentSortOrder at:#sortCaseless put:sortCaselessLocal.
    ] ifFalse:[
	(currentSortOrder at:#sortCaseless) ~= sortCaselessLocal ifTrue:[
	    "/ sort caseless changed
	    currentSortOrder at:#sortCaseless put:sortCaselessLocal.
	] ifFalse:[
	    (currentSortOrder at:#column) = aSymbol ifTrue:[
		"/ same column like before - change sort order ifReverse is true
		aBoolean ifTrue:[
		    | isReverse |
		    isReverse := currentSortOrder at:#reverse.
		    currentSortOrder at:#reverse put:(isReverse not).
		].
	    ] ifFalse:[
		"/ another column - remark column
		currentSortOrder at:#column put:aSymbol.
	    ]
	]
    ].
    self currentSortOrder changed.
    (currentSortOrder at:#reverse) ifTrue:[
	cmpOp := #'>'
    ] ifFalse:[
	cmpOp := #'<'
    ].
    sortReverse := currentSortOrder at:#reverse.
    instanceSortBlock := [:a :b | 
	|entry1 entry2|

	((a respondsTo:aSymbol) not) ifTrue:[
	    true
	] ifFalse:[
	    entry1 := (a perform:aSymbol).
	    entry2 := (b perform:aSymbol).
	    ((entry1 isNil) or:[entry2 isNil]) ifTrue:[
		((entry1 isNil) and:[entry2 isNil]) ifTrue:[true] ifFalse:[
		    ((entry1 notNil) and:[entry2 isNil]) ifTrue:[
		       sortReverse
		    ] ifFalse:[
			sortReverse not
		    ]
		]
	    ] ifFalse:[
		(aSymbol = #baseName) ifTrue:[
		    sortCaselessLocal ifTrue:[
			entry1 := entry1 asString asLowercase.
			entry2 := entry2 asString asLowercase.
		    ] ifFalse:[
			entry1 := entry1 asString.
			entry2 := entry2 asString.
		    ].
		].
		entry1 perform:cmpOp with:entry2
	    ]
	]
    ].
    self sortBlockHolder value:(self makeDirectorySortBlockFor:instanceSortBlock).
! !

!AbstractFileBrowser methodsFor:'startup & release'!

makeDependent
    self filterModel addDependent:self.            
    self currentFileNameHolder addDependent:self.
    self sortDirectoriesBeforeFiles addDependent:self.
    self sortCaseless addDependent:self.
    self showHiddenFiles addDependent:self.
!

masterApplication:anApplication

    masterApplication isNil ifTrue:[
	(anApplication notNil and:[anApplication askFor:#isAbstractFileBrowser]) ifTrue:[
	    aspects := anApplication aspects
	] ifFalse:[
	    aspects isNil ifTrue:[
		aspects := IdentityDictionary new.
		aspects at:#applications put:(IdentityDictionary new).
	    ]
	].
	self applications at:(self className) put:self.
	self makeDependent.
    ].
    ^ super masterApplication:anApplication.
!

postOpenWith:aBuilder

    super postOpenWith:aBuilder.
! !

!AbstractFileBrowser::Clipboard methodsFor:'accessing'!

files
    "return the value of the instance variable 'files' (automatically generated)"

    ^ files
!

files:something
    "set the value of the instance variable 'files' (automatically generated)"

    files := something.
!

method
    "return the value of the instance variable 'method' (automatically generated)"

    ^ method
!

method:something
    "set the value of the instance variable 'method' (automatically generated)"

    method := something.
! !

!AbstractFileBrowser::CodeExecutionLock methodsFor:'accessing'!

locked
    "return the value of the instance variable 'locked' (automatically generated)"

    locked isNil ifTrue:[
	locked := false.
    ].
    ^ locked
! !

!AbstractFileBrowser::CodeExecutionLock methodsFor:'actions'!

doIfUnLocked:aBlock

    self locked ifFalse:[
	aBlock value.
    ].
!

doLocked:aBlock

    locked  := true.
    aBlock ensure:[
	locked := false.
    ]
! !

!AbstractFileBrowser::DirectoryHistory class methodsFor:'defaults'!

historySize

    ^ 20
! !

!AbstractFileBrowser::DirectoryHistory class methodsFor:'new'!

new

    ^ super new initialize.
! !

!AbstractFileBrowser::DirectoryHistory methodsFor:'accessing'!

forwardList
    "return the value of the instance variable 'forwardList' (automatically generated)"

    forwardList isNil ifTrue:[
	forwardList := OrderedCollection new.
    ].
    ^ forwardList
! !

!AbstractFileBrowser::DirectoryHistory methodsFor:'actions'!

addToHistory:aPath
    | item|

    item := self getItemFor:aPath.
    (lastBackPath notNil and:[lastAddPath notNil and:[lastBackPath = aPath]]) ifTrue:[
	lastAddPath := nil.
    ].
    lastAddPath notNil ifTrue:[
	self backListAdd:lastAddPath.
    ].
    lastAddPath := aPath.
    item isNil ifTrue:[
	" not already in history"
	self size >= self class historySize ifTrue:[
	    self removeLast.
	].
	item := DirectoryHistoryItem path:aPath.
	self addFirst:item
    ] ifFalse:[
	"already been there before; move the entry to
	 the beginning, so it will fall out later."
	self remove:item.
	self addFirst:item
    ].
!

backListAdd:aPath

    backList size >= self class historySize ifTrue:[
	backList removeLast.
    ].
    backList addFirst:aPath.
!

forwardListAdd:aPath

    forwardList size >= self class historySize ifTrue:[
	forwardList removeLast.
    ].
    forwardList addFirst:aPath.
!

goBack

" search the item in the list and give back the next in the list"

    | retPath|

    backList isEmpty ifTrue:[ ^ nil].
    retPath := backList first.
    self forwardListAdd:(self first path).
    lastBackPath := retPath.
    backList removeFirst.
    ^ retPath.
!

goForward

" return first path of forward list"

    | retPath|
    self forwardList isEmpty ifTrue:[ ^ nil].
    retPath := self forwardList first.
    self forwardList removeFirst.
    ^ retPath.
!

resetForwardBackward

    backList := self collect:[:item| item path].
    forwardList := OrderedCollection new.
!

setPosition:aPosition for:aPath

    self do:[:item| 
	item path = aPath ifTrue:[
	    item position:aPosition.
	]
    ].
!

xxgoBackFrom:aPath

" search the item in the list and give back the next in the list"

    | index retVal|

    self isEmpty ifTrue:[ ^ nil].

    aPath isNil ifTrue:[
	retVal := self first path
    ] ifFalse:[
	index := self findFirst:[:item| item path = aPath].
	index == 0 ifTrue:[
	    retVal := self first path
	] ifFalse:[
	    index < self size ifTrue:[
		retVal := ((self at:index + 1) path).
	    ]
	].
    ].
    retVal := retVal ? self first path.
    self forwardListAdd:aPath.
    ^ retVal.
! !

!AbstractFileBrowser::DirectoryHistory methodsFor:'initialize'!

initialize

    backList := OrderedCollection new.
    forwardList := OrderedCollection new.
! !

!AbstractFileBrowser::DirectoryHistory methodsFor:'queries'!

canBack

    ^ backList notEmpty
!

canForward

    ^ self forwardList notEmpty.
!

getBackCollectionFrom:aPath

"/    | backCol index |
"/    
"/    backCol := OrderedCollection new.
"/    aPath isNil ifTrue:[
"/        index := 0.
"/    ] ifFalse:[
"/        index := self findFirst:[:item| item path = aPath].
"/    ].
"/    "/ if aPath is not in collection starts from 1 with collect af path
"/    index < self size ifTrue:[ 
"/        self from:(index + 1) to:(self size) do:[:item |
"/            backCol add:(item path).
"/        ].
"/    ].
    ^ backList.
!

getForwardCollection

    ^ self forwardList.
!

getItemFor:aPath

    self do:[:item| item path = aPath ifTrue:[^ item]].
    ^ nil.
!

getPositionFor:aPath

    |item|

    item := self getItemFor:aPath.

    item notNil ifTrue:[
	^ item position.
    ].
    ^ nil
!

includesPath:aPath

    self do:[:item| item path = aPath ifTrue:[^ true]].
    ^ false.
! !

!AbstractFileBrowser::DirectoryHistory::DirectoryHistoryItem class methodsFor:'instance creation'!

path:aPath

    ^ self new path:aPath
! !

!AbstractFileBrowser::DirectoryHistory::DirectoryHistoryItem methodsFor:'accessing'!

path
    "return the value of the instance variable 'path' (automatically generated)"

    ^ path
!

path:something
    "set the value of the instance variable 'path' (automatically generated)"

    path := something.
!

position
    "return the value of the instance variable 'position' (automatically generated)"

    ^ position
!

position:something
    "set the value of the instance variable 'position' (automatically generated)"

    position := something.
!

printString

    ^ self path asString
! !

!AbstractFileBrowser::FilenameHistory class methodsFor:'attributes access'!

FilenameHistorySize

    ^ 20
!

HistorySize

    ^ 20
! !

!AbstractFileBrowser::FilenameHistory methodsFor:'adding & removing'!

add:aApplItem

    super add:aApplItem.
    (self size > self class FilenameHistorySize) ifTrue:[
	self removeLast.
    ]
! !

!AbstractFileBrowser::SaveAspectItem class methodsFor:'instance creation'!

withValue:aValue isHolder:aBoolean

    | instance |

    instance := self basicNew.
    instance value:aValue.
    instance isHolder:aBoolean.
    ^ instance
! !

!AbstractFileBrowser::SaveAspectItem methodsFor:'accessing'!

isHolder
    "return the value of the instance variable 'isHolder' (automatically generated)"

    ^ isHolder
!

isHolder:something
    "set the value of the instance variable 'isHolder' (automatically generated)"

    isHolder := something.
!

value
    "return the value of the instance variable 'value' (automatically generated)"

    ^ value
!

value:something
    "set the value of the instance variable 'value' (automatically generated)"

    value := something.
! !

!AbstractFileBrowser class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/AbstractFileBrowser.st,v 1.58 2002-11-11 09:37:33 cg Exp $'
! !