DirectoryView.st
author Claus Gittinger <cg@exept.de>
Tue, 14 May 2019 09:46:21 +0200
changeset 3663 9d49ecf8661a
parent 3634 b97f51aaa9ac
child 3669 650468354956
permissions -rw-r--r--
#UI_ENHANCEMENT by cg
class: TabListEditor class
changed:
#canvasSpec
#menu
#windowSpec
     1 "
     2  COPYRIGHT (c) 1997 by eXept Software AG
     3               All Rights Reserved
     4 
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice. This software may not
     8  be provided or otherwise made available to, or used by, any
     9  other person. No title to or ownership of the software is
    10  hereby transferred.
    11 "
    12 "{ Package: 'stx:libtool2' }"
    13 
    14 "{ NameSpace: Smalltalk }"
    15 
    16 ApplicationModel subclass:#DirectoryView
    17 	instanceVariableNames:'directory selectedFileFilter readTask monitoring
    18 		monitoringTimeBlock fileDoubleClickAction fileSelectAction
    19 		fileFilterSelectAction fileAttributes'
    20 	classVariableNames:''
    21 	poolDictionaries:''
    22 	category:'Interface-Dialogs'
    23 !
    24 
    25 Object subclass:#FileRow
    26 	instanceVariableNames:'fileName size modified iconKey imageFromFile group owner
    27 		permissions baseName'
    28 	classVariableNames:'MaxImageFileSize'
    29 	poolDictionaries:''
    30 	privateIn:DirectoryView
    31 !
    32 
    33 !DirectoryView class methodsFor:'documentation'!
    34 
    35 copyright
    36 "
    37  COPYRIGHT (c) 1997 by eXept Software AG
    38               All Rights Reserved
    39 
    40  This software is furnished under a license and may be used
    41  only in accordance with the terms of that license and with the
    42  inclusion of the above copyright notice. This software may not
    43  be provided or otherwise made available to, or used by, any
    44  other person. No title to or ownership of the software is
    45  hereby transferred.
    46 "
    47 
    48 !
    49 
    50 documentation
    51 "
    52     this is somewhat outdated. However, it is still used by the image editor and
    53     some other resource editors.
    54     It has the advantage of showing the file-contents...
    55     ...but the disadvantage of having an ugly layout and user interface.
    56 
    57     [author:]
    58         Thomas Zwick
    59 "
    60 ! !
    61 
    62 !DirectoryView class methodsFor:'instance creation'!
    63 
    64 openOnDirectory: aDirectoryString
    65     "open a DirectoryView for a aDirectoryString"
    66 
    67     ^ (self new directory: aDirectoryString) open
    68 
    69     "
    70      self openOnDirectory: '/etc'
    71     "
    72 
    73     "Modified: / 28.1.1998 / 15:44:53 / stefan"
    74 ! !
    75 
    76 !DirectoryView class methodsFor:'interface specs'!
    77 
    78 windowSpec
    79     "This resource specification was automatically generated
    80      by the UIPainter of ST/X."
    81 
    82     "Do not manually edit this!! If it is corrupted,
    83      the UIPainter may not be able to read the specification."
    84 
    85     "
    86      UIPainter new openOnClass:DirectoryView andSelector:#windowSpec
    87      DirectoryView new openInterface:#windowSpec
    88      DirectoryView open
    89     "
    90 
    91     <resource: #canvas>
    92 
    93     ^ 
    94      #(#FullSpec
    95         #name: #windowSpec
    96         #window: 
    97        #(#WindowSpec
    98           #label: 'Directory View'
    99           #name: 'Directory View'
   100           #min: #(#Point 10 10)
   101           #bounds: #(#Rectangle 13 23 413 323)
   102         )
   103         #component: 
   104        #(#SpecCollection
   105           #collection: #(
   106            #(#DataSetSpec
   107               #name: 'filesDataSetView'
   108               #layout: #(#LayoutFrame 0 0.0 24 0.0 -2 1.0 0 1.0)
   109               #model: #selectionOfFile
   110               #menu: #fileListMenu
   111               #hasHorizontalScrollBar: true
   112               #hasVerticalScrollBar: true
   113               #miniScrollerHorizontal: true
   114               #dataList: #listOfFiles
   115               #useIndex: false
   116               #has3Dsepartors: false
   117               #doubleClickSelector: #fileDoubleClicked
   118               #columnHolder: #fileAttributeColumns
   119               #valueChangeSelector: #fileSelected
   120               #verticalSpacing: 1
   121             )
   122            #(#ComboBoxSpec
   123               #name: 'formatComboBox'
   124               #layout: #(#LayoutFrame 63 0.0 0 0 0 1.0 22 0)
   125               #model: #selectionOfFileFilter
   126               #immediateAccept: false
   127               #acceptOnTab: false
   128               #acceptOnPointerLeave: false
   129               #comboList: #listOfFileFilters
   130             )
   131            #(#LabelSpec
   132               #label: 'Filter: '
   133               #name: 'filterLabel'
   134               #layout: #(#LayoutFrame 0 0 0 0 62 0 22 0)
   135               #adjust: #right
   136             )
   137            )
   138          
   139         )
   140       )
   141 
   142     "Modified: / 11.2.2000 / 00:11:43 / cg"
   143 ! !
   144 
   145 !DirectoryView class methodsFor:'list specs'!
   146 
   147 tableColumnsForFileAttributes
   148     "This resource specification was automatically generated
   149      by the DataSetBuilder of ST/X."
   150 
   151     "Do not manually edit this!! If it is corrupted,
   152      the DataSetBuilder may not be able to read the specification."
   153 
   154     "
   155      DataSetBuilder new openOnClass:DirectoryView andSelector:#tableColumnsForFileAttributes
   156     "
   157 
   158     <resource: #tableColumns>
   159 
   160 
   161     ^ #(
   162         #(#DataSetColumnSpec
   163            #label: ''
   164            #width: 30
   165            #height: 22
   166            #printSelector: #iconOn:
   167            #canSelect: false
   168        )
   169         #(#DataSetColumnSpec
   170            #label: 'File name'
   171            #labelAlignment: #left
   172            #minWidth: 150
   173            #model: #baseName
   174            #canSelect: false
   175        )
   176         #(#DataSetColumnSpec
   177            #label: 'Size'
   178            #labelAlignment: #left
   179            #width: 70
   180            #model: #size
   181            #canSelect: false
   182        )
   183         #(#DataSetColumnSpec
   184            #label: 'Modified'
   185            #labelAlignment: #left
   186            #model: #modified
   187            #canSelect: false
   188        )
   189         #(#DataSetColumnSpec
   190            #label: 'Permissions'
   191            #labelAlignment: #left
   192            #width: 85
   193            #model: #permissions
   194            #canSelect: false
   195        )
   196         #(#DataSetColumnSpec
   197            #label: 'Owner'
   198            #labelAlignment: #left
   199            #width: 50
   200            #model: #owner
   201            #canSelect: false
   202        )
   203         #(#DataSetColumnSpec
   204            #label: 'Group'
   205            #labelAlignment: #left
   206            #width: 50
   207            #model: #group
   208            #canSelect: false
   209        )
   210      )
   211 ! !
   212 
   213 !DirectoryView class methodsFor:'menu specs'!
   214 
   215 fileListMenu
   216     "This resource specification was automatically generated
   217      by the MenuEditor of ST/X."
   218 
   219     "Do not manually edit this!! If it is corrupted,
   220      the MenuEditor may not be able to read the specification."
   221 
   222     "
   223      MenuEditor new openOnClass:DirectoryView andSelector:#fileListMenu
   224      (Menu new fromLiteralArrayEncoding:(DirectoryView fileListMenu)) startUp
   225     "
   226 
   227     <resource: #menu>
   228 
   229     ^ 
   230      #(#Menu
   231         #(
   232          #(#MenuItem
   233             #label: 'Update'
   234             #translateLabel: true
   235             #value: #updateFileList
   236           )
   237          )
   238         nil
   239         nil
   240       )
   241 
   242     "Created: / 11.2.2000 / 00:11:39 / cg"
   243 ! !
   244 
   245 !DirectoryView methodsFor:'accessing'!
   246 
   247 directory: aDirectory
   248 
   249     directory := aDirectory asFilename asAbsoluteFilename name
   250 !
   251 
   252 fileAttributes: anArray
   253 
   254     fileAttributes := anArray
   255 !
   256 
   257 fileDoubleClickAction: anActionBlock
   258 
   259     fileDoubleClickAction := anActionBlock
   260 !
   261 
   262 fileFilterSelectAction: anActionBlock
   263 
   264     fileFilterSelectAction := anActionBlock
   265 !
   266 
   267 fileSelectAction: anActionBlock
   268 
   269     fileSelectAction := anActionBlock
   270 !
   271 
   272 listOfFileFilters: aCollection
   273 
   274     self listOfFileFilters contents: aCollection.
   275     self selectionOfFileFilter value: (self listOfFileFilters at: 1 ifAbsent: [nil]).
   276 !
   277 
   278 monitoring: aBoolean
   279 
   280     aBoolean
   281     ifTrue:
   282     [
   283         monitoringTimeBlock := [self readDirectory].
   284         self readDirectory.
   285     ]
   286     ifFalse:
   287     [
   288         monitoring ifTrue:
   289         [
   290             Processor removeTimedBlock:monitoringTimeBlock.
   291             monitoringTimeBlock := nil
   292         ]
   293     ].
   294 
   295     monitoring := aBoolean.
   296 
   297 ! !
   298 
   299 !DirectoryView methodsFor:'aspects'!
   300 
   301 fileAttributeColumns
   302 
   303     |holder|
   304     (holder := builder bindingAt:#fileAttributeColumns) isNil ifTrue:[
   305         |fileAttributeColumns|
   306         builder aspectAt:#fileAttributeColumns put:(holder := List new).
   307         fileAttributeColumns := self class tableColumnsForFileAttributes collect: [:i| i decodeAsLiteralArray].
   308         holder add: fileAttributeColumns first.
   309         fileAttributeColumns do:
   310         [:col|
   311             (fileAttributes includes: col label) ifTrue: [holder add: col]
   312         ].
   313         holder do: [:col| col label: ' ', col label]
   314     ].
   315     ^ holder
   316 !
   317 
   318 listOfFileFilters
   319 
   320     |holder|          
   321     (holder := builder bindingAt:#listOfFileFilters) isNil ifTrue:[
   322         builder aspectAt:#listOfFileFilters put:(holder :=  List with: '*').
   323     ].
   324     ^ holder
   325 !
   326 
   327 listOfFiles
   328 
   329     |holder|
   330     (holder := builder bindingAt:#listOfFiles) isNil ifTrue:[
   331         builder aspectAt:#listOfFiles put:(holder :=  List new).
   332     ].
   333     ^ holder
   334 !
   335 
   336 selectionOfFile
   337 
   338     |holder|
   339     (holder := builder bindingAt:#selectionOfFile) isNil ifTrue:[
   340         builder aspectAt:#selectionOfFile put:(holder :=  ValueHolder new).
   341     ].
   342     ^ holder
   343 
   344 !
   345 
   346 selectionOfFileFilter
   347 
   348     |holder|
   349     (holder := builder bindingAt:#selectionOfFileFilter) isNil ifTrue:[
   350         builder aspectAt:#selectionOfFileFilter put:
   351         (holder := AspectAdaptor new subject:self; forAspect:#selectedFileFilter).
   352         selectedFileFilter := '*'.
   353     ].
   354     ^ holder
   355 ! !
   356 
   357 !DirectoryView methodsFor:'callbacks'!
   358 
   359 fileDoubleClicked
   360       
   361     (fileDoubleClickAction notNil and: [self selectionOfFile value notNil]) 
   362     ifTrue: 
   363     [
   364         fileDoubleClickAction numArgs = 0
   365         ifTrue:
   366         [
   367             fileDoubleClickAction value
   368         ].
   369         fileDoubleClickAction numArgs = 1
   370         ifTrue:
   371         [                
   372             fileDoubleClickAction value: (directory asFilename construct: self selectionOfFile value baseName) name
   373         ]
   374     ]
   375 !
   376 
   377 fileSelected
   378       
   379     (fileSelectAction notNil and: [self selectionOfFile value notNil]) 
   380     ifTrue: 
   381     [
   382         fileSelectAction numArgs = 0
   383         ifTrue:
   384         [
   385             fileSelectAction value
   386         ].
   387         fileSelectAction numArgs = 1
   388         ifTrue:
   389         [
   390             fileSelectAction value: (directory asFilename construct: self selectionOfFile value baseName) name
   391         ]
   392     ]
   393 ! !
   394 
   395 !DirectoryView methodsFor:'initialization'!
   396 
   397 initialize
   398 
   399     super initialize.
   400     self createBuilder.
   401 
   402     directory :=  (directory ? '.') asFilename asAbsoluteFilename directoryName.
   403     monitoring := false.
   404     fileAttributes := #('File name' 'Size' 'Modified').
   405     self selectionOfFileFilter value: (self listOfFileFilters at: 1 ifAbsent: [nil]).
   406 
   407     "Modified: / 20.6.1998 / 14:46:10 / cg"
   408 ! !
   409 
   410 !DirectoryView methodsFor:'initialize-release'!
   411 
   412 release
   413 
   414     monitoring ifTrue:
   415     [
   416         Processor removeTimedBlock:monitoringTimeBlock.
   417         monitoringTimeBlock := nil
   418     ].
   419 
   420     super release
   421 
   422 ! !
   423 
   424 !DirectoryView methodsFor:'menu actions'!
   425 
   426 updateFileList
   427     DirectoryContents flushCache.
   428     self readDirectory
   429 
   430     "Created: / 11.2.2000 / 00:12:46 / cg"
   431     "Modified: / 11.2.2000 / 00:14:32 / cg"
   432 ! !
   433 
   434 !DirectoryView methodsFor:'private'!
   435 
   436 readDirectory
   437     |allDirectories allFiles foundFiles filterList dir newContents|    
   438 
   439     allFiles := OrderedCollection new.
   440     allDirectories := OrderedCollection new.
   441     foundFiles := OrderedCollection new.
   442     "/ filterList := self listOfFileFilters value.
   443     filterList := self selectedFileFilter asCollectionOfSubstringsSeparatedBy:$;.
   444     filterList := filterList collect:[:pattern | pattern withoutSeparators].
   445 
   446     self withCursor:Cursor read do:[ 
   447         (dir := DirectoryContents directoryNamed: directory) notNil ifTrue:[
   448 "/            dir filesAndBasenamesDo:[:file :name|      
   449 "/                filterList do:[:filter|
   450 "/                    ((filter match:name) and:[(foundFiles includes: name) not])
   451 "/                    ifTrue:[
   452 "/                        foundFiles add: name
   453 "/                    ].
   454 "/                ].
   455 "/            ].
   456             dir filesAndBasenamesDo:[:file :name|      
   457                 allFiles add: name
   458             ].
   459             dir directoriesAndBasenamesDo:[:file :name|      
   460                 allDirectories add: name
   461             ].
   462 
   463             Filename isCaseSensitive ifFalse:[
   464                 filterList do:[:filter|
   465                     |lcFilter|
   466 
   467                     lcFilter := filter asLowercase.
   468                     foundFiles
   469                         addAll:(allFiles 
   470                                     select:[:name | lcFilter match:name asLowercase]
   471                                 ).
   472                 ]
   473             ] ifTrue:[
   474                 filterList do:[:filter|
   475                     foundFiles
   476                         addAll:(allFiles 
   477                                     select:[:name | filter match:name]
   478                                 ).
   479                 ]
   480             ].
   481 
   482             foundFiles sort.
   483             allDirectories sort.
   484 
   485             dir := directory asFilename.
   486 
   487             newContents := OrderedCollection new.
   488             newContents addAll:(allDirectories collect:[:name| FileRow new fileName:(dir construct:name)]).
   489             newContents addAll:(foundFiles collect:[:name| FileRow new fileName:(dir construct:name)]).
   490 
   491             self listOfFiles contents:newContents
   492         ]
   493     ]
   494 
   495     "Modified: / 23.9.1998 / 17:00:42 / cg"
   496 !
   497 
   498 readMonitoringDirectory
   499     <resource: #obsolete>
   500     "this is a very ugly piece of code - 
   501      left in as a bad example of how to make ST look slow...
   502      DO NOT USE IT, but read to learn"
   503      
   504     |readBlock|
   505 
   506     readTask notNil ifTrue: [readTask terminate].
   507     readBlock :=
   508         [
   509             |dir currentFilenames oldListOfFiles listOfFiles|
   510 
   511             dir := directory asFilename.
   512             currentFilenames := OrderedCollection new.
   513             (dir isReadable and:[dir isExecutable]) ifTrue: [
   514                 self listOfFileFilters value do:
   515                 [:filter|
   516                     (dir filesMatchingWithoutDotDirs: filter) do: [:aFileName|
   517                         |file|
   518                         (file := dir construct: aFileName) isDirectory ifFalse: [
   519                             currentFilenames add: file
   520                         ]
   521                     ].
   522                 ].
   523             ].
   524             listOfFiles := self listOfFiles.
   525             
   526             oldListOfFiles := listOfFiles copy.
   527             (currentFilenames asSortedCollection: [:f1 :f2| f1 baseName < f2 baseName]) asSet 
   528                 do: [:fileName| 
   529                     (oldListOfFiles contains:[:fileRow | fileRow fileName = fileName ])
   530                     ifFalse: [
   531                         |nearestFileRow newRow r|
   532                         
   533                         newRow := FileRow new fileName: fileName asFilename.
   534                         "/ cg: how stupid is that?
   535                         nearestFileRow := listOfFiles indexOf: (listOfFiles detect: [:fileRow| fileRow baseName > fileName baseName] ifNone: nil).
   536                         "/ nearestFileRow := listOfFiles findFirst:[:fileRow | fileRow baseName > fileName baseName].
   537                         nearestFileRow = 0
   538                             ifTrue: [listOfFiles add: newRow]
   539                             ifFalse: [listOfFiles add: newRow beforeIndex: nearestFileRow].
   540                         monitoring ifTrue: [self selectionOfFile value: r].
   541                     ]
   542                 ].
   543                 
   544             listOfFiles 
   545                 reverseDo: [:fileRow|
   546                     (currentFilenames includes: fileRow fileName)
   547                     ifFalse: [listOfFiles remove: fileRow]
   548                 ]
   549         ].
   550 
   551     monitoring ifTrue: [
   552         readTask := readBlock forkAt: Processor userBackgroundPriority.
   553         Processor addTimedBlock: monitoringTimeBlock afterSeconds: 1
   554     ] ifFalse: [
   555         Cursor wait showWhile: [readBlock value]
   556     ]
   557 
   558     "Modified: / 19-11-2016 / 20:34:14 / cg"
   559 ! !
   560 
   561 !DirectoryView methodsFor:'selection'!
   562 
   563 selectedFileFilter
   564 
   565     ^selectedFileFilter
   566 
   567 !
   568 
   569 selectedFileFilter:aString
   570     "change the file filter"
   571 
   572     |listOfFileFilters nArgs|
   573 
   574     aString = selectedFileFilter ifTrue:[^ self].
   575 
   576     listOfFileFilters := self listOfFileFilters.
   577 
   578     "/ what is this for ?
   579     aString size == 0 ifTrue: [
   580         listOfFileFilters remove: selectedFileFilter ifAbsent: nil
   581     ].
   582     selectedFileFilter := aString.
   583 
   584     ((listOfFileFilters includes: selectedFileFilter) not
   585     and:[selectedFileFilter notEmpty])
   586     ifTrue: [
   587         listOfFileFilters addFirst: selectedFileFilter
   588     ].
   589     ((listOfFileFilters includes: selectedFileFilter)
   590     and:[fileFilterSelectAction notNil]) 
   591     ifTrue: [
   592         (nArgs := fileFilterSelectAction numArgs) == 0
   593         ifTrue: [
   594             fileFilterSelectAction value
   595         ] ifFalse:[
   596             nArgs == 1 ifTrue:[
   597                 fileFilterSelectAction value: selectedFileFilter
   598             ] ifFalse:[
   599                 self error:'bad numArgs of fileFilter action block'
   600             ]
   601         ]
   602     ].       
   603     self readDirectory.
   604 
   605     "Modified: / 23.9.1998 / 16:53:05 / cg"
   606 ! !
   607 
   608 !DirectoryView methodsFor:'startup & release'!
   609 
   610 closeRequest
   611     "/ is this needed? - I think release is sent anyway by super...
   612     self release.
   613 
   614     super closeRequest
   615 
   616     "Modified (comment): / 28-05-2018 / 09:50:20 / Claus Gittinger"
   617 ! !
   618 
   619 !DirectoryView::FileRow class methodsFor:'resources'!
   620 
   621 HFileIcon
   622 
   623     ^self hFileIcon
   624 !
   625 
   626 MakefileIcon
   627     "This resource specification was automatically generated
   628      by the ImageEditor of ST/X."
   629 
   630     "Do not manually edit this!! If it is corrupted,
   631      the ImageEditor may not be able to read the specification."
   632 
   633     "
   634      self MakefileIcon inspect
   635      ImageEditor openOnClass:self andSelector:#MakefileIcon
   636      Icon flushCachedIcons
   637     "
   638 
   639     <resource: #image>
   640 
   641     ^Icon
   642         constantNamed:'DirectoryView::FileRow MakefileIcon'
   643         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 @@0 @@0 @@0)IV0/U$0)]&0)UT;)UV4 @@0 @@0???0???0')
   644             colorMapFromArray:#[255 255 255 0 0 0]
   645             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   646 !
   647 
   648 binaryFileIcon
   649     "This resource specification was automatically generated
   650      by the ImageEditor of ST/X."
   651 
   652     "Do not manually edit this!! If it is corrupted,
   653      the ImageEditor may not be able to read the specification."
   654 
   655     "
   656      self binaryFileIcon inspect
   657      ImageEditor openOnClass:self andSelector:#binaryFileIcon
   658      Icon flushCachedIcons
   659     "
   660 
   661     <resource: #image>
   662 
   663     ^Icon
   664         constantNamed:'DirectoryView::FileRow binaryFileIcon'
   665         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???3 @_7 @W4#&S0&6Q0&6_3&6O5&6@0#&@9 @@0&\@2&6@0&6@0&6@1&6@8&\@0 @@0???0???1')
   666             colorMapFromArray:#[255 255 255 0 0 0]
   667             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   668 !
   669 
   670 cFileIcon
   671     "This resource specification was automatically generated
   672      by the ImageEditor of ST/X."
   673 
   674     "Do not manually edit this!! If it is corrupted,
   675      the ImageEditor may not be able to read the specification."
   676 
   677     "
   678      self cFileIcon inspect
   679      ImageEditor openOnClass:self andSelector:#cFileIcon
   680      Icon flushCachedIcons
   681     "
   682 
   683     <resource: #image>
   684 
   685     ^Icon
   686         constantNamed:'DirectoryView::FileRow cFileIcon'
   687         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 @@0 @@0 \@0 "@0  @0  @0&"@;&\@4 @@0 @@0???0???0')
   688             colorMapFromArray:#[255 255 255 0 0 0]
   689             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   690 !
   691 
   692 exeFileIcon
   693     "This resource specification was automatically generated
   694      by the ImageEditor of ST/X."
   695 
   696     "Do not manually edit this!! If it is corrupted,
   697      the ImageEditor may not be able to read the specification."
   698 
   699     "
   700      self exeFileIcon inspect
   701      ImageEditor openOnClass:self andSelector:#exeFileIcon
   702      Icon flushCachedIcons
   703     "
   704 
   705     <resource: #image>
   706 
   707     ^Icon
   708         constantNamed:'DirectoryView::FileRow exeFileIcon'
   709         ifAbsentPut:[(Depth2Image width:20 height:19) bits:(ByteArray fromPackedString:'UUUUUUU@@@@UUT@@@AEUP@@@DEU@@@@PET@@@AUUQUUUP@UF**)@ATUUUT@EQ???P@UG??=@AT_??4@EQ???P@UG??=@AT_??4@EQUUUP@U@@@@@AUUUUUUU
   710 UUUUUUTb')
   711             colorMapFromArray:#[255 255 255 0 0 0 0 127 127 170 170 170]
   712             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   713 !
   714 
   715 fileIcon
   716     "Generated by the Image Editor"
   717     "
   718     ImageEditor openOnClass:self andSelector:#fileIcon
   719     "
   720 
   721     <resource: #image>
   722 
   723     ^Icon
   724         constantNamed:#'DirectoryView::FileRow fileIcon'
   725         ifAbsentPut:[(Depth1Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 @@0 @@0 @@0 @@0 @@0 @@0 @@; @@4 @@0 @@0???0???0') ; colorMap:((OrderedCollection new add:(Color white); add:(Color black); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0') ; yourself); yourself]
   726 !
   727 
   728 hFileIcon
   729     "Generated by the Image Editor"
   730     "
   731     ImageEditor openOnClass:self andSelector:#hFileIcon
   732     "
   733 
   734     <resource: #image>
   735 
   736     ^Icon
   737         constantNamed:#'DirectoryView::FileRow hFileIcon'
   738         ifAbsentPut:[(Depth1Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8  @0  @0 ,@0 2@0 "@0 "@0&"@;&"@4 @@0 @@0???0???0'); colorMap:((OrderedCollection new add:(Color white); add:(Color black); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   739 !
   740 
   741 htmlFileIcon
   742     "This resource specification was automatically generated
   743      by the ImageEditor of ST/X."
   744 
   745     "Do not manually edit this!! If it is corrupted,
   746      the ImageEditor may not be able to read the specification."
   747 
   748     "
   749      self htmlFileIcon inspect
   750      ImageEditor openOnClass:self andSelector:#htmlFileIcon
   751      Icon flushCachedIcons
   752     "
   753 
   754     <resource: #image>
   755 
   756     ^Icon
   757         constantNamed:'DirectoryView::FileRow htmlFileIcon'
   758         ifAbsentPut:[(Depth4Image width:20 height:19) bits:(ByteArray fromPackedString:'
   759 DQDQDQDQDQDQDQ????????DQDQD_???????1@QDQG???L3L3<P@QDQ??L3=DL3D@@QD_?3L?P3L1DQDQG?L3MCP3L1DQDQ?3QCQCMCP??1D_<4P4QDL4O?<Q
   760 G?L4QDL3MD??DQ?3L3QCL3S??1D_<3L4QDL4O?<QG?<3QDQCMO??DQ??L4QDP4S??1D_??=D??S???<QG???????????DQ???????????1DQDQDQDQDQDQDQ
   761 DQDQDQDQDQDQDP@a')
   762             colorMapFromArray:#[255 255 255 0 0 0 255 0 0 0 255 0 0 0 255 0 255 255 255 255 0 255 0 255 127 0 0 0 127 0 0 0 127 0 127 127 127 127 0 127 0 127 127 127 127 170 170 170]
   763             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   764 !
   765 
   766 imageFileIcon
   767     "This resource specification was automatically generated
   768      by the ImageEditor of ST/X."
   769 
   770     "Do not manually edit this!! If it is corrupted,
   771      the ImageEditor may not be able to read the specification."
   772 
   773     "
   774      self imageFileIcon inspect
   775      ImageEditor openOnClass:self andSelector:#imageFileIcon
   776      Icon flushCachedIcons
   777     "
   778 
   779     <resource: #image>
   780 
   781     ^Icon
   782         constantNamed:'DirectoryView::FileRow imageFileIcon'
   783         ifAbsentPut:[(Depth4Image width:20 height:19) bits:(ByteArray fromPackedString:'
   784 @@@@@@@@@@@@@@DQDQDQDQ@@@@@ADQDQDQDPD@@@@QDQDQDQDAD@@@DQDQDQDQ@QD@@ADQDQDQDP@@@@@TQG]4)G50@@@@EDQ7^$+W4QDP@AQD]7R$_WDQD@
   785 @SL6Y#$61!!DQ@@D3M&ZS''F0QDP@AL3Y&NS[FDQD@@RH%UR %-QDQ@@D"IUVB"5,QDP@AH"UUJBV5DQD@@QDQDQDQDQDQ@@DQDQDQDQDQDP@@@@@@@@@@@@@@
   786 @@@@@@@@@@@@@@@a')
   787             colorMapFromArray:#[0 0 0 255 255 255 255 0 0 0 255 0 0 0 255 0 255 255 255 255 0 255 0 255 127 0 0 0 127 0 0 0 127 0 127 127 127 127 0 127 0 127]
   788             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   789 !
   790 
   791 imgFileIcon
   792     "Generated by the Image Editor"
   793     "
   794     ImageEditor openOnClass:self andSelector:#imgFileIcon
   795     "
   796 
   797     <resource: #image>
   798 
   799     ^Icon
   800         constantNamed:#'DirectoryView::FileRow imgFileIcon'
   801         ifAbsentPut:[(Depth1Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8  @0 @@0!!-F0 **0 **0 **0&**;&*&4 @B0 @N0???0???0'); colorMap:((OrderedCollection new add:(Color white); add:(Color black); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   802 !
   803 
   804 linkedFileIcon
   805     "Generated by the Image Editor"
   806     "
   807     ImageEditor openOnClass:self andSelector:#linkedFileIcon
   808     "
   809 
   810     <resource: #image>
   811 
   812     ^Icon
   813         constantNamed:#'DirectoryView::FileRow linkedFileIcon'
   814         ifAbsentPut:[(Depth2Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'UUUUUUU@@@@UUT@@@AEUP@@@DEU@@@@PET@@@AUUP@@@AUU@@@@@AT@@@@ EP@@@B U@@@**!!T@@J**EP@B B UB*(@HATJ*@@@EP@@@@@U@@@@@AUUUUUUUUUUUUUTb') ; colorMap:((OrderedCollection new add:(Color white); add:(Color black); add:(Color red:0.0 green:0.0 blue:100.0); add:(Color red:100.0 green:0.0 blue:0.0); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0') ; yourself); yourself]
   815 !
   816 
   817 lockedFileIcon
   818     "Generated by the Image Editor"
   819     "
   820     ImageEditor openOnClass:self andSelector:#lockedFileIcon
   821     "
   822 
   823     <resource: #image>
   824 
   825     ^Icon
   826         constantNamed:#'DirectoryView::FileRow lockedFileIcon'
   827         ifAbsentPut:[(Depth2Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(2 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'UUUUUUU(@@@UUT(@@AEUP(@@DEU@(@@PET@(@IUUP@(B!!UU@@((@AT@@*@@EP@B(@@U@@((@AT@J@(@EPB @(@U@(@@(ATJ@@@(ER @@@(U(@@@@)UUUUUUUUUUUUUTb') ; colorMap:((OrderedCollection new add:(Color white); add:(Color black); add:(Color red:100.0 green:0.0 blue:0.0); add:(Color red:0.0 green:100.0 blue:0.0); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0') ; yourself); yourself]
   828 !
   829 
   830 protoFileIcon
   831 
   832     ^self MakefileIcon
   833 !
   834 
   835 rcFileIcon
   836     "Generated by the Image Editor"
   837     "
   838     ImageEditor openOnClass:self andSelector:#rcFileIcon
   839     "
   840 
   841     <resource: #image>
   842 
   843     ^Icon
   844         constantNamed:#'DirectoryView::FileRow rcFileIcon'
   845         ifAbsentPut:[(Depth1Image new) width: 20; height: 19; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 @@0 @@0 ) 0 2P0 "@0 "@0&"P;&!! 4 @@0 @@0???0???0') ; colorMap:((OrderedCollection new add:(Color white); add:(Color black); yourself)); mask:((ImageMask new) width: 20; height: 19; photometric:(#blackIs0); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0') ; yourself); yourself]
   846 !
   847 
   848 sFileIcon
   849     "This resource specification was automatically generated
   850      by the ImageEditor of ST/X."
   851 
   852     "Do not manually edit this!! If it is corrupted,
   853      the ImageEditor may not be able to read the specification."
   854 
   855     "
   856      self sFileIcon inspect
   857      ImageEditor openOnClass:self andSelector:#sFileIcon
   858      Icon flushCachedIcons
   859     "
   860 
   861     <resource: #image>
   862 
   863     ^Icon
   864         constantNamed:'DirectoryView::FileRow sFileIcon'
   865         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 @@0 @@0 X@0  @0 0@0 X@0&H@;&0@4 @@0 @@0???0???0')
   866             colorMapFromArray:#[255 255 255 0 0 0]
   867             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   868 !
   869 
   870 stFileIcon
   871     "This resource specification was automatically generated
   872      by the ImageEditor of ST/X."
   873 
   874     "Do not manually edit this!! If it is corrupted,
   875      the ImageEditor may not be able to read the specification."
   876 
   877     "
   878      self stFileIcon inspect
   879      ImageEditor openOnClass:self andSelector:#stFileIcon
   880      Icon flushCachedIcons
   881     "
   882 
   883     <resource: #image>
   884 
   885     ^Icon
   886         constantNamed:'DirectoryView::FileRow stFileIcon'
   887         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 A@0 A@0 [00 !!@0 1@0 Y@0&I@;&004 @@0 @@0???0???0')
   888             colorMapFromArray:#[255 255 255 0 0 0]
   889             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   890 !
   891 
   892 stcFileIcon
   893     "This resource specification was automatically generated
   894      by the ImageEditor of ST/X."
   895 
   896     "Do not manually edit this!! If it is corrupted,
   897      the ImageEditor may not be able to read the specification."
   898 
   899     "
   900      self stcFileIcon inspect
   901      ImageEditor openOnClass:self andSelector:#stcFileIcon
   902      Icon flushCachedIcons
   903     "
   904 
   905     <resource: #image>
   906 
   907     ^Icon
   908         constantNamed:'DirectoryView::FileRow stcFileIcon'
   909         ifAbsentPut:[(Depth1Image width:20 height:19) bits:(ByteArray fromPackedString:'???9 @_0 @W2 @S0 @Q0 @_0 @O8 B@0 B@0 _L0 "R0 2P0 ZP0&JR;&3L4 @@0 @@0???0???0')
   910             colorMapFromArray:#[255 255 255 0 0 0]
   911             mask:((ImageMask width:20 height:19) bits:(ByteArray fromPackedString:'??0@??8@??<@??>@???@??? ???0???0???0???0???0???0???0???0???0???0???0???0_??0'); yourself); yourself]
   912 ! !
   913 
   914 !DirectoryView::FileRow methodsFor:'accessing'!
   915 
   916 baseName
   917 
   918     ^baseName ? (baseName := fileName baseName)
   919 
   920 
   921 
   922 
   923 
   924 
   925 
   926 !
   927 
   928 fileName
   929 
   930     ^fileName
   931 !
   932 
   933 fileName: aFileName
   934 
   935     fileName := aFileName
   936 !
   937 
   938 group
   939 
   940     ^group
   941 !
   942 
   943 iconOn:aGC
   944     |icon|
   945     
   946     iconKey isNil ifTrue: [
   947         self validateAttributes.
   948         (imageFromFile isNil and: [iconKey == #imageFileIcon]) ifTrue:  [
   949             icon := self retrieveImageFromFileAndRegisterOn: aGC
   950         ]
   951     ].
   952     imageFromFile == true ifFalse: [
   953         icon := aGC registerImage: (self class perform: iconKey) key: iconKey
   954     ] ifTrue:  [
   955         icon := aGC registeredImageAt: iconKey
   956     ].
   957     ^ icon
   958 
   959     "Modified: / 18-02-1998 / 18:01:52 / cg"
   960     "Modified (format): / 13-09-2017 / 09:57:53 / cg"
   961 !
   962 
   963 modified
   964 
   965     ^modified
   966 !
   967 
   968 owner
   969 
   970     ^owner
   971 !
   972 
   973 permissions
   974 
   975     ^permissions
   976 !
   977 
   978 retrieveImageFromFileAndRegisterOn: aGC
   979     "retrieve a bitmap image - but only if it is smaller than some limit (currently 20k)"
   980 
   981     |image maxImageFileSize|
   982 
   983     maxImageFileSize := MaxImageFileSize ? 20000.
   984 
   985     imageFromFile := false.       
   986     (image := aGC registeredImageAt: fileName name asSymbol) isNil ifTrue:[            
   987         size < maxImageFileSize ifTrue:[     
   988             Error handle: [:ex|]
   989             do:[   
   990                 (image := Image fromFile: fileName name) notNil ifTrue:[
   991                     image extent y > 22 ifTrue:[         
   992                         image := image magnifiedBy: 22/image extent y
   993                     ].
   994                     image := aGC registerImage: image key: fileName name asSymbol.
   995                 ]
   996             ] 
   997         ].
   998     ].
   999     image notNil ifTrue: [imageFromFile := true. iconKey := fileName name asSymbol].
  1000     ^image
  1001 
  1002     "Modified (format): / 13-09-2017 / 09:58:19 / cg"
  1003 !
  1004 
  1005 size
  1006     size isNil ifTrue:[
  1007         self validateAttributes.
  1008     ].
  1009     
  1010     size isNumber ifFalse:[^ size].
  1011 
  1012     "/ ^ UnitConverter fileSizeStringFor:size.
  1013     
  1014     size < 1000        ifTrue: [^ size printString].
  1015     size < (100*1024)  ifTrue: [^(((size/1024) * 10) asInteger/10) asFloat printString, ' Kb'].
  1016     size < (1000*1024) ifTrue: [^(((size/1024)) asInteger) printString, ' Kb'].
  1017     ^(((size/1048576) * 10) asInteger/10) asFloat printString, ' Mb'
  1018 
  1019     "Modified: / 13-09-2017 / 09:58:42 / cg"
  1020 ! !
  1021 
  1022 !DirectoryView::FileRow methodsFor:'private'!
  1023 
  1024 validateAttributes
  1025     |info mode suffix| 
  1026 
  1027     permissions := '---------' copy.
  1028 
  1029     (info := fileName info) isNil ifTrue:[
  1030         iconKey := #lockedFileIcon.
  1031         size    := owner := group := '?'.
  1032         ^ self
  1033     ].        
  1034     size   := info fileSize.
  1035     modified := info modificationTime printString.
  1036     owner  := OperatingSystem getUserNameFromID: info uid.
  1037     group  := OperatingSystem getGroupNameFromID: info gid.
  1038     mode   := info mode.
  1039 
  1040     1 to:9 by:3 do:[:i|
  1041         #((0 $x) (1 $w) (2 $r)) do:
  1042         [:m|
  1043             (mode bitAt:i + m first) == 1 ifTrue:[permissions at: 10 - m first - i put: m last]
  1044         ]
  1045     ].
  1046 
  1047     fileName isReadable ifFalse:[
  1048         ^ iconKey := #lockedFileIcon
  1049     ].
  1050     info type == #symbolicLink ifTrue:[
  1051         ^ iconKey := #linkedFileIcon
  1052     ].
  1053     suffix := fileName suffix.
  1054 
  1055     ((suffix asSingleByteStringIfPossible isSingleByteCollection
  1056      and:[ (self class respondsTo:(iconKey := (suffix, 'FileIcon') asSymbol))])
  1057         or: [fileName baseName asSingleByteStringIfPossible isSingleByteCollection 
  1058              and:[self class respondsTo: (iconKey := (fileName baseName, 'Icon') asSymbol)]]
  1059     ) ifFalse:[
  1060         iconKey := #fileIcon.
  1061         ((suffix = 'o') or:[suffix = 'so']) ifTrue: [
  1062             ^ iconKey := #binaryFileIcon
  1063         ].
  1064         (Image isImageFileSuffix:suffix) ifTrue: [
  1065             ^ iconKey := #imageFileIcon
  1066         ].
  1067 
  1068         fileName isExecutableProgram ifTrue:[
  1069             ^ iconKey := #exeFileIcon
  1070         ]
  1071     ]
  1072 
  1073     "Modified: / 13-09-2017 / 10:00:42 / cg"
  1074     "Modified: / 01-01-2019 / 15:23:11 / Claus Gittinger"
  1075 ! !
  1076 
  1077 !DirectoryView class methodsFor:'documentation'!
  1078 
  1079 version
  1080     ^ '$Header$'
  1081 !
  1082 
  1083 version_CVS
  1084     ^ '$Header$'
  1085 ! !
  1086