|
1 SelectionBrowser subclass:#FileSelectionBrowser |
|
2 instanceVariableNames:'selectedFileFilter fileName readTask' |
|
3 classVariableNames:'' |
|
4 poolDictionaries:'' |
|
5 category:'Interface-Advanced-Tools' |
|
6 ! |
|
7 |
|
8 Object subclass:#Row |
|
9 instanceVariableNames:'fileName size iconKey group owner permissions baseName' |
|
10 classVariableNames:'' |
|
11 poolDictionaries:'' |
|
12 privateIn:FileSelectionBrowser |
|
13 ! |
|
14 |
|
15 |
|
16 !FileSelectionBrowser class methodsFor:'instance creation'! |
|
17 |
|
18 requestFileName |
|
19 |
|
20 ^self new title: 'Select a file'; open |
|
21 |
|
22 ! |
|
23 |
|
24 requestFileName: aFileName fileFilters: fileFilters |
|
25 |
|
26 ^self new |
|
27 fileName: aFileName; |
|
28 listOfFileFilters: fileFilters; |
|
29 open |
|
30 ! ! |
|
31 |
|
32 !FileSelectionBrowser class methodsFor:'accessing'! |
|
33 |
|
34 lastFileSelectionDirectory |
|
35 "^ LastFileSelectionDirectory" |
|
36 |
|
37 ! ! |
|
38 |
|
39 !FileSelectionBrowser class methodsFor:'interface specs'! |
|
40 |
|
41 windowSpec |
|
42 "this window spec was automatically generated by the ST/X UIPainter" |
|
43 |
|
44 "do not manually edit this - the painter/builder may not be able to |
|
45 handle the specification if its corrupted." |
|
46 |
|
47 " |
|
48 UIPainter new openOnClass:FileSelectionBrowser andSelector:#windowSpec |
|
49 FileSelectionBrowser new openInterface:#windowSpec |
|
50 " |
|
51 "FileSelectionBrowser open" |
|
52 |
|
53 <resource: #canvas> |
|
54 |
|
55 ^ |
|
56 |
|
57 #(#FullSpec |
|
58 #'window:' |
|
59 #(#WindowSpec |
|
60 #'name:' 'File Selection Browser' |
|
61 #'layout:' #(#LayoutFrame 410 0 282 0 809 0 581 0) |
|
62 #'label:' 'File Selection Browser' |
|
63 #'min:' #(#Point 10 10) |
|
64 #'max:' #(#Point 1152 900) |
|
65 #'bounds:' #(#Rectangle 410 282 810 582) |
|
66 #'usePreferredExtent:' false |
|
67 ) |
|
68 #'component:' |
|
69 #(#SpecCollection |
|
70 #'collection:' |
|
71 #( |
|
72 #(#ViewSpec |
|
73 #'name:' 'view' |
|
74 #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -40 1.0) |
|
75 #'component:' |
|
76 #(#SpecCollection |
|
77 #'collection:' |
|
78 #( |
|
79 #(#VariableHorizontalPanelSpec |
|
80 #'name:' 'panel' |
|
81 #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 -1 1.0) |
|
82 #'component:' |
|
83 #(#SpecCollection |
|
84 #'collection:' |
|
85 #( |
|
86 #(#ViewSpec |
|
87 #'name:' 'view1' |
|
88 #'component:' |
|
89 #(#SpecCollection |
|
90 #'collection:' |
|
91 #( |
|
92 #(#FileSelectionTreeSpec |
|
93 #'name:' 'directoryTreeView' |
|
94 #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0) |
|
95 #'model:' #selectionOfDirectory |
|
96 #'hasHorizontalScrollBar:' true |
|
97 #'hasVerticalScrollBar:' true |
|
98 #'miniScrollerHorizontal:' true |
|
99 #'showRoot:' false |
|
100 #'showDirectoryIndicator:' true |
|
101 #'valueChangeSelector:' #readDirectory |
|
102 #'hierarchicalList:' #rootOfDirectory |
|
103 #'itemClass:' 'Directory' |
|
104 ) |
|
105 ) |
|
106 ) |
|
107 #'level:' -1 |
|
108 ) |
|
109 #(#ViewSpec |
|
110 #'name:' 'view2' |
|
111 #'component:' |
|
112 #(#SpecCollection |
|
113 #'collection:' |
|
114 #( |
|
115 #(#DataSetSpec |
|
116 #'name:' 'filesDataSetView' |
|
117 #'layout:' #(#LayoutFrame 0 0.0 24 0.0 0 1.0 -23 1.0) |
|
118 #'model:' #selectionOfFile |
|
119 #'hasHorizontalScrollBar:' true |
|
120 #'hasVerticalScrollBar:' true |
|
121 #'miniScrollerHorizontal:' true |
|
122 #'dataList:' #listOfFiles |
|
123 #'useIndex:' false |
|
124 #'level:' 1 |
|
125 #'doubleClickSelector:' #fileDoubleClicked |
|
126 #'valueChangeSelector:' #fileSelected |
|
127 #'verticalSpacing:' 1 |
|
128 #'columns:' |
|
129 #( |
|
130 #(#DataSetColumnSpec |
|
131 #'label:' '' |
|
132 #'width:' 30 |
|
133 #'printSelector:' #'iconOn:' |
|
134 #'canSelect:' false |
|
135 ) |
|
136 #(#DataSetColumnSpec |
|
137 #'label:' 'file name' |
|
138 #'minWidth:' 100 |
|
139 #'model:' #baseName |
|
140 ) |
|
141 #(#DataSetColumnSpec |
|
142 #'label:' 'size' |
|
143 #'width:' 50 |
|
144 #'model:' #size |
|
145 #'canSelect:' false |
|
146 ) |
|
147 #(#DataSetColumnSpec |
|
148 #'label:' 'permissions' |
|
149 #'width:' 85 |
|
150 #'model:' #permissions |
|
151 #'canSelect:' false |
|
152 ) |
|
153 #(#DataSetColumnSpec |
|
154 #'label:' 'owner' |
|
155 #'width:' 50 |
|
156 #'model:' #owner |
|
157 #'canSelect:' false |
|
158 ) |
|
159 #(#DataSetColumnSpec |
|
160 #'label:' 'group' |
|
161 #'width:' 50 |
|
162 #'model:' #group |
|
163 #'canSelect:' false |
|
164 ) |
|
165 ) |
|
166 ) |
|
167 #(#ComboBoxSpec |
|
168 #'name:' 'formatComboBox' |
|
169 #'layout:' #(#LayoutFrame 0 0.0 2 0 0 1.0 24 0) |
|
170 #'model:' #selectionOfFileFilter |
|
171 #'immediateAccept:' false |
|
172 #'acceptOnTab:' false |
|
173 #'comboList:' #listOfFileFilters |
|
174 ) |
|
175 #(#InputFieldSpec |
|
176 #'name:' 'EditField' |
|
177 #'layout:' #(#LayoutFrame 0 0.0 -22 1 0 1.0 0 1) |
|
178 #'model:' #valueOfFileName |
|
179 #'acceptOnReturn:' false |
|
180 #'acceptOnTab:' false |
|
181 ) |
|
182 ) |
|
183 ) |
|
184 #'level:' -1 |
|
185 ) |
|
186 ) |
|
187 ) |
|
188 #'handles:' #(#Any 0.5 1.0) |
|
189 ) |
|
190 ) |
|
191 ) |
|
192 ) |
|
193 #(#HorizontalPanelViewSpec |
|
194 #'name:' 'horizontalPanelView' |
|
195 #'layout:' #(#LayoutFrame 0 0.0 -40 1 0 1.0 0 1.0) |
|
196 #'component:' |
|
197 #(#SpecCollection |
|
198 #'collection:' |
|
199 #( |
|
200 #(#ActionButtonSpec |
|
201 #'name:' 'cancelButton' |
|
202 #'label:' 'cancel' |
|
203 #'model:' #cancel |
|
204 #'extent:' #(#Point 100 22) |
|
205 ) |
|
206 #(#ActionButtonSpec |
|
207 #'name:' 'okButton' |
|
208 #'label:' 'ok' |
|
209 #'model:' #accept |
|
210 #'extent:' #(#Point 100 22) |
|
211 ) |
|
212 ) |
|
213 ) |
|
214 #'level:' 1 |
|
215 #'horizontalLayout:' #center |
|
216 #'verticalLayout:' #center |
|
217 #'horizontalSpace:' 3 |
|
218 #'verticalSpace:' 3 |
|
219 ) |
|
220 ) |
|
221 ) |
|
222 ) |
|
223 ! ! |
|
224 |
|
225 !FileSelectionBrowser methodsFor:'accessing'! |
|
226 |
|
227 fileName |
|
228 |
|
229 (fileName notNil and: [(fileName name ~= self valueOfFileName value and: [self valueOfFileName value notNil])]) |
|
230 ifTrue: [^(LastFileSelectionDirectory, Filename separator, self valueOfFileName value) asFilename]. |
|
231 ^fileName |
|
232 ! |
|
233 |
|
234 fileName: aFileName |
|
235 |
|
236 fileName := aFileName |
|
237 ! |
|
238 |
|
239 title: aString |
|
240 |
|
241 title := aString |
|
242 ! ! |
|
243 |
|
244 !FileSelectionBrowser methodsFor:'actions'! |
|
245 |
|
246 closeCancel |
|
247 |
|
248 readTask notNil ifTrue: [readTask terminate]. |
|
249 fileName := nil. |
|
250 super closeCancel |
|
251 ! |
|
252 |
|
253 closeRequest |
|
254 |
|
255 readTask notNil ifTrue: [readTask terminate]. |
|
256 super closeRequest |
|
257 ! |
|
258 |
|
259 closeWindow |
|
260 |
|
261 readTask notNil ifTrue: [readTask terminate]. |
|
262 super closeWindow |
|
263 ! |
|
264 |
|
265 fileDoubleClicked |
|
266 |
|
267 self valueOfFileName value: self selectionOfFile value baseName. |
|
268 fileName := self selectionOfFile value fileName. |
|
269 accept value: true. |
|
270 self close |
|
271 ! |
|
272 |
|
273 fileSelected |
|
274 |
|
275 self valueOfFileName value: self selectionOfFile value baseName. |
|
276 fileName := self selectionOfFile value fileName. |
|
277 ! |
|
278 |
|
279 readDirectory |
|
280 |
|
281 | file list dir lst| |
|
282 self selectionOfDirectory value isNil ifTrue: [^nil]. |
|
283 readTask notNil ifTrue: [readTask terminate]. |
|
284 readTask := [ |
|
285 |
|
286 file := (builder componentAt: #directoryTreeView) selectedPathname asFilename. |
|
287 builder window label: 'Reading: ''', file name, ''''. |
|
288 self class lastSelection: file name. |
|
289 (file isReadable and:[file isExecutable]) ifTrue:[ |
|
290 list := self listOfFiles. |
|
291 list removeAll. |
|
292 lst := OrderedCollection new. |
|
293 self listOfFileFilters value |
|
294 do: [:filter| |
|
295 (file filesMatchingWithoutDotDirs: filter) do: |
|
296 [:aFileName| |
|
297 lst add: (Row new fileName: (file name, Filename separator, aFileName) asFilename) |
|
298 ]. |
|
299 ]. |
|
300 lst := lst asSortedCollection: [:r1 :r2| r1 baseName < r2 baseName]. |
|
301 list addAll:lst beforeIndex:1]. |
|
302 self selectionOfFile value: (self listOfFiles detect: [:r| r fileName = fileName] ifNone: [nil]). |
|
303 self setLabel. |
|
304 ] forkAt: 4 |
|
305 ! ! |
|
306 |
|
307 !FileSelectionBrowser methodsFor:'aspects'! |
|
308 |
|
309 listOfFileFilters |
|
310 |holder| |
|
311 |
|
312 (holder := builder bindingAt:#listOfFileFilters) isNil ifTrue:[ |
|
313 builder aspectAt:#listOfFileFilters put:(holder := List with: '*.*'). |
|
314 ]. |
|
315 ^ holder |
|
316 ! |
|
317 |
|
318 listOfFileFilters: aCollection |
|
319 self listOfFileFilters contents: aCollection. |
|
320 ! |
|
321 |
|
322 listOfFiles |
|
323 |
|
324 |holder| |
|
325 (holder := builder bindingAt:#listOfFiles) isNil ifTrue:[ |
|
326 builder aspectAt:#listOfFiles put:(holder := List new). |
|
327 ]. |
|
328 ^ holder |
|
329 |
|
330 ! |
|
331 |
|
332 rootOfDirectory |
|
333 |
|
334 |holder| |
|
335 |
|
336 (holder := builder bindingAt:#rootOfDirectory) isNil ifTrue:[ |
|
337 builder aspectAt:#rootOfDirectory put: (holder := ValueHolder with: Filename rootDirectory name). |
|
338 ]. |
|
339 ^ holder |
|
340 |
|
341 ! |
|
342 |
|
343 selectionOfDirectory |
|
344 |
|
345 |holder| |
|
346 (holder := builder bindingAt:#selectionOfDirectory) isNil ifTrue:[ |
|
347 builder aspectAt:#selectionOfDirectory put: (holder := ValueHolder new) |
|
348 ]. |
|
349 ^ holder |
|
350 |
|
351 ! |
|
352 |
|
353 selectionOfFile |
|
354 |
|
355 |holder| |
|
356 (holder := builder bindingAt:#selectionOfFile) isNil ifTrue:[ |
|
357 builder aspectAt:#selectionOfFile put:(holder := ValueHolder new). |
|
358 ]. |
|
359 ^ holder |
|
360 |
|
361 ! |
|
362 |
|
363 selectionOfFileFilter |
|
364 |holder| |
|
365 |
|
366 (holder := builder bindingAt:#selectionOfFileFilter) isNil ifTrue:[ |
|
367 builder aspectAt:#selectionOfFileFilter put: |
|
368 (holder := AspectAdaptor new subject:self; forAspect:#selectedFileFilter). |
|
369 selectedFileFilter := '*.*'. |
|
370 ]. |
|
371 ^ holder |
|
372 ! |
|
373 |
|
374 valueOfFileName |
|
375 |
|
376 |holder| |
|
377 (holder := builder bindingAt:#valueOfFileName) isNil ifTrue:[ |
|
378 builder aspectAt:#valueOfFileName put:(holder := ValueHolder new). |
|
379 ]. |
|
380 ^ holder |
|
381 ! ! |
|
382 |
|
383 !FileSelectionBrowser methodsFor:'initialization'! |
|
384 |
|
385 open |
|
386 |
|
387 super open. |
|
388 accept value |
|
389 ifTrue: |
|
390 [ |
|
391 ^(self selectionOfDirectory value ? '') , Filename separator, (self valueOfFileName value ? '') |
|
392 ]. |
|
393 ^nil |
|
394 |
|
395 |
|
396 |
|
397 ! |
|
398 |
|
399 postBuildWith:aBuilder |
|
400 |
|
401 (fileName notNil and: [fileName asFilename exists]) |
|
402 ifTrue: |
|
403 [ |
|
404 self class lastSelection: fileName asFilename directoryName. |
|
405 self valueOfFileName value: fileName asFilename baseName |
|
406 ]. |
|
407 (builder componentAt: #directoryTreeView) selectPathname: self class lastSelection. |
|
408 self selectionOfFileFilter value: (self listOfFileFilters at: 1 ifAbsent: [nil]). |
|
409 self readDirectory. |
|
410 (builder componentAt: #directoryTreeView) monitoring: true. |
|
411 ^super postBuildWith:aBuilder |
|
412 ! ! |
|
413 |
|
414 !FileSelectionBrowser methodsFor:'selection'! |
|
415 |
|
416 selectedFileFilter |
|
417 |
|
418 ^selectedFileFilter |
|
419 ! |
|
420 |
|
421 selectedFileFilter: aString |
|
422 |
|
423 selectedFileFilter := aString. |
|
424 |
|
425 self readDirectory |
|
426 ! ! |
|
427 |
|
428 !FileSelectionBrowser::Row methodsFor:'accessing'! |
|
429 |
|
430 baseName |
|
431 baseName isNil ifTrue: [baseName := fileName baseName]. |
|
432 ^ baseName |
|
433 |
|
434 |
|
435 |
|
436 |
|
437 |
|
438 ! |
|
439 |
|
440 fileName |
|
441 ^ fileName |
|
442 |
|
443 ! |
|
444 |
|
445 fileName: aFileName |
|
446 fileName := aFileName |
|
447 |
|
448 ! |
|
449 |
|
450 group |
|
451 group isNil ifTrue:[ |
|
452 self validateAttributes |
|
453 ]. |
|
454 ^ group |
|
455 ! |
|
456 |
|
457 iconOn:aGC |
|
458 |icon| |
|
459 |
|
460 iconKey isNil ifTrue:[ |
|
461 self validateAttributes. |
|
462 ]. |
|
463 (iconKey == #image) | (iconKey == #imageFile) |
|
464 ifTrue: |
|
465 [ |
|
466 Object errorSignal handle: [:ex|] |
|
467 do: |
|
468 [ |
|
469 ((size < 5000) and: [(icon := Image fromFile: fileName name) notNil]) |
|
470 ifTrue: [aGC registerImage: icon key:(iconKey :=fileName name asSymbol).] |
|
471 ]. |
|
472 ]. |
|
473 (icon := aGC registeredImageAt:iconKey) isNil ifTrue:[ |
|
474 self registerIconsOn:aGC. |
|
475 icon := aGC registeredImageAt:iconKey. |
|
476 ]. |
|
477 ^ icon |
|
478 |
|
479 |
|
480 |
|
481 ! |
|
482 |
|
483 owner |
|
484 owner isNil ifTrue:[ |
|
485 self validateAttributes |
|
486 ]. |
|
487 ^ owner |
|
488 |
|
489 |
|
490 ! |
|
491 |
|
492 permissions |
|
493 permissions isNil ifTrue:[ |
|
494 self validateAttributes |
|
495 ]. |
|
496 ^ permissions |
|
497 |
|
498 |
|
499 ! |
|
500 |
|
501 size |
|
502 size isNil ifTrue:[ |
|
503 self validateAttributes |
|
504 ]. |
|
505 ^ size |
|
506 |
|
507 ! ! |
|
508 |
|
509 !FileSelectionBrowser::Row methodsFor:'private'! |
|
510 |
|
511 registerIconsOn:aGC |
|
512 "register all file icons on the gc |
|
513 " |
|
514 |directory| |
|
515 |
|
516 directory := 'xpmBitmaps/document_images/'. |
|
517 |
|
518 #( |
|
519 (#file 'tiny_file_plain.xpm' ) |
|
520 (#fileLink 'tiny_file_link.xpm' ) |
|
521 (#fileLocked 'tiny_file_lock.xpm' ) |
|
522 (#imageFile 'tiny_file_pix.xpm' ) |
|
523 |
|
524 ) do:[:el| |
|
525 aGC registerImage:(Image fromFile:(directory, el last)) key:(el first) |
|
526 ]. |
|
527 |
|
528 |
|
529 |
|
530 |
|
531 |
|
532 ! |
|
533 |
|
534 validateAttributes |
|
535 |info mode| |
|
536 |
|
537 permissions := String new:9 withAll:$-. |
|
538 |
|
539 (info := fileName info) isNil ifTrue:[ |
|
540 iconKey := #fileLocked. |
|
541 size := owner := group := '?'. |
|
542 ^ self |
|
543 ]. |
|
544 size := info size. |
|
545 owner := OperatingSystem getUserNameFromID:(info uid). |
|
546 group := OperatingSystem getGroupNameFromID:(info gid). |
|
547 mode := info mode. |
|
548 |
|
549 1 to:9 by:3 do:[:i| |
|
550 (mode bitAt:i ) == 1 ifTrue:[permissions at:10 - i put:$x]. |
|
551 (mode bitAt:i + 1) == 1 ifTrue:[permissions at:9 - i put:$w]. |
|
552 (mode bitAt:i + 2) == 1 ifTrue:[permissions at:8 - i put:$r]. |
|
553 ]. |
|
554 |
|
555 fileName isReadable ifTrue:[ |
|
556 info type == #symbolicLink ifTrue:[ |
|
557 iconKey == #fileLink |
|
558 ] ifFalse:[ |
|
559 (Image isImageFileSuffix:(fileName suffix)) ifTrue:[ |
|
560 iconKey := #imageFile |
|
561 ] ifFalse:[ |
|
562 iconKey := #file |
|
563 ] |
|
564 ] |
|
565 ] ifFalse:[ |
|
566 iconKey := #fileLocked |
|
567 ]. |
|
568 |
|
569 ! ! |
|
570 |
|
571 !FileSelectionBrowser class methodsFor:'documentation'! |
|
572 |
|
573 version |
|
574 ^ '$Header$' |
|
575 ! ! |