DirectoryDifferenceViewApplication.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Sun, 29 Jan 2012 15:33:37 +0000
branchjv
changeset 12125 0c49a3b13e43
child 12128 a7ff7d66ee85
permissions -rw-r--r--
Merged with /trunk

"{ Package: 'stx:libtool' }"

AbstractFileFinderApplicationComponent subclass:#DirectoryDifferenceViewApplication
	instanceVariableNames:'directory1Holder directory2Holder directory1 directory2
		filesOnlyInDirectory1 filesOnlyInDirectory2
		filesWhichAreDifferent directoriesOnlyInDirectory1
		directoriesOnlyInDirectory2 namePatternHolder
		excludedNamePatternHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Tools-File'
!


!DirectoryDifferenceViewApplication class methodsFor:'help specs'!

flyByHelpSpec
    "This resource specification was automatically generated
     by the UIHelpTool of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIHelpTool may not be able to read the specification."

    "
     UIHelpTool openOnClass:FindFileApplication    
    "

    <resource: #help>

    ^ super flyByHelpSpec addPairsFrom:#(

#namePattern
'Filename(s) to search for. Can be matchPatterns, separated by ";"'

#excludedNamePattern
'Filename(s) to skip. Can be matchPatterns, separated by ";"'

#searchDirectory1
'The first folder, to be compared against folder2'

#searchDirectory2
'The second folder, to be compared against folder1'

)

    "Modified: / 13-01-2012 / 14:41:36 / cg"
! !

!DirectoryDifferenceViewApplication class methodsFor:'interface specs'!

windowSpec
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the UIPainter may not be able to read the specification."

    "
     UIPainter new openOnClass:DirectoryDifferenceViewApplication andSelector:#windowSpec
     DirectoryDifferenceViewApplication new openInterface:#windowSpec
     DirectoryDifferenceViewApplication open
    "

    <resource: #canvas>

    ^ 
     #(FullSpec
        name: windowSpec
        window: 
       (WindowSpec
          label: 'Directory Diff'
          name: 'Directory Diff'
          min: (Point 377 131)
          bounds: (Rectangle 0 0 758 512)
        )
        component: 
       (SpecCollection
          collection: (
           (MenuPanelSpec
              name: 'ToolBar1'
              layout: (LayoutFrame 0 0.0 0 0 0 1.0 32 0)
              level: 0
              menu: searchMenu
              textDefault: true
            )
           (ProgressIndicatorSpec
              name: 'ProgressIndicator1'
              layout: (LayoutFrame 125 0 11 0 231 0 21 0)
              visibilityChannel: enableStop
              backgroundColor: (Color 0.0 66.9993133440146 66.9993133440146)
              showPercentage: false
              isActivityIndicator: true
            )
           (ViewSpec
              name: 'Box1'
              layout: (LayoutFrame 0 0.0 32 0 0 1.0 130 0)
              component: 
             (SpecCollection
                collection: (
                 (LabelSpec
                    label: 'Directory1:'
                    name: 'DirectoryLabel'
                    layout: (LayoutFrame 2 0 7 0 154 0 24 0)
                    activeHelpKey: searchDirectory1
                    translateLabel: true
                    adjust: right
                  )
                 (FilenameInputFieldSpec
                    name: 'DirectoryEntryField'
                    layout: (LayoutFrame 156 0 4 0 0 1 24 0)
                    activeHelpKey: searchDirectory1
                    model: directory1Holder
                    immediateAccept: true
                    acceptOnPointerLeave: false
                  )
                 (LabelSpec
                    label: 'Directory2:'
                    name: 'Label2'
                    layout: (LayoutFrame 2 0 31 0 154 0 48 0)
                    activeHelpKey: searchDirectory2
                    translateLabel: true
                    adjust: right
                  )
                 (FilenameInputFieldSpec
                    name: 'FilenameEntryField1'
                    layout: (LayoutFrame 156 0 28 0 0 1 48 0)
                    activeHelpKey: searchDirectory2
                    model: directory2Holder
                    immediateAccept: true
                    acceptOnPointerLeave: false
                  )
                 (LabelSpec
                    label: 'Compare Files Named:'
                    name: 'FileNameLabel'
                    layout: (LayoutFrame 2 0 55 0 154 0 72 0)
                    activeHelpKey: namePattern
                    translateLabel: true
                    adjust: right
                  )
                 (InputFieldSpec
                    name: 'FileNameEntryField'
                    layout: (LayoutFrame 156 0 52 0 -315 1 72 0)
                    activeHelpKey: namePattern
                    tabable: true
                    model: namePatternHolder
                    immediateAccept: true
                    acceptOnLeave: false
                    acceptOnPointerLeave: false
                  )
                 (CheckBoxSpec
                    label: 'Ignore Case'
                    name: 'IgnoreCaseInNameCheckBox'
                    layout: (LayoutFrame -169 1 53 0 -4 1 76 0)
                    activeHelpKey: ignoreCase
                    tabable: true
                    model: ignoreCaseInName
                    translateLabel: true
                  )
                 (LabelSpec
                    label: 'But Not Named:'
                    name: 'Label1'
                    layout: (LayoutFrame 2 0 79 0 154 0 96 0)
                    activeHelpKey: excludedNamePattern
                    translateLabel: true
                    adjust: right
                  )
                 (InputFieldSpec
                    name: 'EntryField1'
                    layout: (LayoutFrame 156 0 76 0 -315 1 96 0)
                    activeHelpKey: excludedNamePattern
                    tabable: true
                    model: excludedNamePatternHolder
                    immediateAccept: true
                    acceptOnLeave: false
                    acceptOnPointerLeave: false
                  )
                 (CheckBoxSpec
                    label: 'Ignore Case'
                    name: 'CheckBox1'
                    layout: (LayoutFrame -169 1 77 0 -4 1 100 0)
                    activeHelpKey: ignoreCase
                    tabable: true
                    model: ignoreCaseInExcludedName
                    translateLabel: true
                  )
                 )
               
              )
            )
           (VariableVerticalPanelSpec
              name: 'VariableVerticalPanel1'
              layout: (LayoutFrame 0 0.0 140 0 0 1.0 0 1)
              component: 
             (SpecCollection
                collection: (
                 (DataSetSpec
                    name: 'Table1'
                    model: selectionHolder
                    hasHorizontalScrollBar: true
                    hasVerticalScrollBar: true
                    dataList: matchedFilesList
                    doubleClickSelector: fileDoubleClick:
                    columnHolder: searchResultTable
                    valueChangeSelector: fileSelected:
                    multipleSelectOk: true
                  )
                 (ArbitraryComponentSpec
                    name: 'DiffTextView'
                    hasHorizontalScrollBar: true
                    hasVerticalScrollBar: true
                    component: DiffTextView
                  )
                 )
               
              )
              handles: (Any 0.5 1.0)
            )
           )
         
        )
      )

    "Modified: / 13-01-2012 / 14:41:56 / cg"
! !

!DirectoryDifferenceViewApplication class methodsFor:'menu specs'!

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

    <resource: #menu>

    ^ 
     #(Menu
        (
         (MenuItem
            label: 'Search'
            itemValue: doSearch
            translateLabel: true
            isButton: true
            labelImage: (ResourceRetriever ToolbarIconLibrary searchFileIcon)
          )
         (MenuItem
            enabled: enableStop
            label: 'Stop'
            itemValue: stop
            translateLabel: true
            isButton: true
            isVisible: enableStop
            labelImage: (ResourceRetriever XPToolbarIconLibrary stop22x22Icon)
          )
         (MenuItem
            label: 'Close'
            itemValue: doClose
            translateLabel: true
            isButton: true
            startGroup: right
            isVisible: false
            labelImage: (ResourceRetriever ToolbarIconLibrary removeTabIcon)
          )
         )
        nil
        nil
      )
! !

!DirectoryDifferenceViewApplication class methodsFor:'tableColumns specs'!

searchResultTable
    "This resource specification was automatically generated
     by the DataSetBuilder of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the DataSetBuilder may not be able to read the specification."

    "
     DataSetBuilder new openOnClass:DirectoryDifferenceViewApplication andSelector:#searchResultTable
    "

    <resource: #tableColumns>

    ^#(
      (DataSetColumnSpec
         label: 'Filename'
         id: 'FileName'
         labelButtonType: Button
         model: at:
         menuFromApplication: false
         writeSelector: at:put:
         showRowSeparator: false
         showColSeparator: false
       )
      (DataSetColumnSpec
         label: 'Diff'
         id: 'Diff'
         labelButtonType: Button
         model: at:
         menuFromApplication: false
         writeSelector: at:put:
         showRowSeparator: false
         showColSeparator: false
       )
      )
    
! !

!DirectoryDifferenceViewApplication methodsFor:'accessing'!

directory1:directory1Arg directory2:directory2Arg 
    self directory1Holder value:directory1Arg.
    self directory2Holder value:directory2Arg.

"/    self namePatternHolder value:newPattern.
    self enableStop value:false.
    self enableSearch value:true.
    ^ true.

    "Modified: / 12-01-2012 / 01:36:54 / cg"
!

directory1Holder
    directory1Holder isNil ifTrue:[
        directory1Holder := nil asValue
    ].
    ^ directory1Holder

    "Created: / 12-01-2012 / 01:37:31 / cg"
!

directory2Holder
    directory2Holder isNil ifTrue:[
        directory2Holder := nil asValue
    ].
    ^ directory2Holder

    "Created: / 12-01-2012 / 01:37:41 / cg"
! !

!DirectoryDifferenceViewApplication methodsFor:'actions'!

fileSelected:entries
    |entry file fn1 fn2 text1 text2 differ|

    entries isEmptyOrNil ifTrue:[^ self].

    entry := self shownList at:entries first.
    file := entry first.

    fn1 := self directory1Holder value asFilename construct:file.
    fn2 := self directory2Holder value asFilename construct:file.
    fn1 exists ifTrue:[
        text1 := fn1 contentsOfEntireFile.
    ].
    fn2 exists ifTrue:[
        text2 := fn2 contentsOfEntireFile.
    ].
    differ := builder componentAt:'DiffTextView'.
    differ text1:(text1 ? '') text2:(text2 ? '').

    "Created: / 12-01-2012 / 03:21:52 / cg"
! !

!DirectoryDifferenceViewApplication methodsFor:'aspects'!

excludedNamePatternHolder
    excludedNamePatternHolder isNil ifTrue:[
        excludedNamePatternHolder := '' asValue.
    ].
    ^ excludedNamePatternHolder.

    "Created: / 13-01-2012 / 14:42:47 / cg"
!

namePatternHolder

    namePatternHolder isNil ifTrue:[
        namePatternHolder := '*' asValue.
    ].
    ^ namePatternHolder.

    "Created: / 13-01-2012 / 14:37:28 / cg"
! !

!DirectoryDifferenceViewApplication methodsFor:'comparing'!

doSearch
    |dir1 dir2 namePattern namePatterns excludedNamePattern excludedNamePatterns|

    filesOnlyInDirectory1 := OrderedCollection new.
    filesOnlyInDirectory2 := OrderedCollection new.
    directoriesOnlyInDirectory1 := OrderedCollection new.
    directoriesOnlyInDirectory2 := OrderedCollection new.
    filesWhichAreDifferent := OrderedCollection new.

    dir1 := self directory1Holder value.
    dir1 isNil ifTrue:[^ self].

    dir2 := self directory2Holder value.
    dir2 isNil ifTrue:[^ self].

    dir1 := dir1 asFilename.
    dir2 := dir2 asFilename.

    dir1 pathName = dir2 pathName ifTrue:[
        self notify:('Same folder.' allBold).
        ^ self.
    ].

    namePattern := self namePatternHolder value.
    namePattern notEmptyOrNil ifTrue:[
        namePatterns := namePattern asCollectionOfSubstringsSeparatedByAny:',;'.
        namePatterns := namePatterns collect:[:p | p withoutSeparators ].
    ].
    excludedNamePattern := self excludedNamePatternHolder value.
    excludedNamePattern notEmptyOrNil ifTrue:[
        excludedNamePatterns := excludedNamePattern asCollectionOfSubstringsSeparatedByAny:',;'.
        excludedNamePatterns := excludedNamePatterns collect:[:p | p withoutSeparators ].
    ].

    self 
        startSearchTask:[
            self changeInformationTo:'Directory Diff - searching ' toTab:true.

            self shownListHolder valueHolder:(self matchedFilesList).

            dir1 recursiveDirectoryContentsDo:[:relFn1 |
                |fn1 fn2|

                fn1 := dir1 construct:relFn1.
                (namePatterns isNil or:[namePatterns contains:[:p | p match:fn1 baseName]]) ifTrue:[
                    (excludedNamePatterns notNil and:[excludedNamePatterns contains:[:p | p match:fn1 baseName]]) ifFalse:[
                        fn2 := dir2 construct:relFn1.
                        fn1 isDirectory ifTrue:[
                            self notify:('Comparing %1...' bindWith:relFn1 asString allBold).
                            fn2 exists ifFalse:[
                                directoriesOnlyInDirectory1 add:fn1.
                                self matchedFilesList add:{ relFn1 . 'Directory only in directory1' }.
                            ].
                        ] ifFalse:[
                            fn2 exists ifTrue:[
                                (fn1 sameContentsAs:fn2) ifFalse:[
                                    filesWhichAreDifferent add:fn1.
                                    self matchedFilesList add:{ relFn1 . 'Different' }.
                                ].
                            ] ifFalse:[
                                filesOnlyInDirectory1 add:fn1.
                                self matchedFilesList add:{ relFn1 . 'File only in directory1' }.
                            ].
                        ].
                    ]
                ]
            ].
            dir2 recursiveDirectoryContentsDo:[:relFn2 |
                |fn1 fn2|

                fn2 := dir2 construct:relFn2.
                (namePatterns isNil or:[namePatterns contains:[:p | p match:fn2 baseName]]) ifTrue:[
                    (excludedNamePatterns notNil and:[excludedNamePatterns contains:[:p | p match:fn2 baseName]]) ifFalse:[
                        fn1 := dir1 construct:relFn2.
                        fn1 exists ifFalse:[
                            fn1 isDirectory ifTrue:[
                                directoriesOnlyInDirectory1 add:fn1.
                                self matchedFilesList add:{ relFn2 . 'Directory only in directory2' }.
                            ] ifFalse:[
                                filesOnlyInDirectory2 add:fn2.
                                self matchedFilesList add:{ relFn2 . 'File only in directory2' }.
                            ]
                        ].
                    ].
                ]
            ].
            filesOnlyInDirectory1 notEmpty ifTrue:[
                Transcript showCR:('%1 files only in directory1' bindWith:filesOnlyInDirectory1 size).
            ].
            filesOnlyInDirectory2 notEmpty ifTrue:[
                Transcript showCR:('%1 files only in directory2' bindWith:filesOnlyInDirectory2 size).
            ].
            directoriesOnlyInDirectory1 notEmpty ifTrue:[
                Transcript showCR:('%1 directories only in directory1' bindWith:directoriesOnlyInDirectory1 size).
            ].
            directoriesOnlyInDirectory2 notEmpty ifTrue:[
                Transcript showCR:('%1 directories only in directory2' bindWith:directoriesOnlyInDirectory2 size).
            ].
            filesWhichAreDifferent notEmpty ifTrue:[
                Transcript showCR:('%1 files are different' bindWith:filesWhichAreDifferent size).
            ]
        ]
        name:'Directory Diff'.

    "Created: / 12-01-2012 / 01:07:20 / cg"
! !

!DirectoryDifferenceViewApplication methodsFor:'startup & release'!

postOpenWith:aBuilder
    super postOpenWith:aBuilder.
    self doSearch

    "Created: / 12-01-2012 / 01:41:18 / cg"
! !

!DirectoryDifferenceViewApplication class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/DirectoryDifferenceViewApplication.st,v 1.4 2012/01/13 14:14:02 cg Exp $'
!

version_CVS
    ^ '§Header: /cvs/stx/stx/libtool/DirectoryDifferenceViewApplication.st,v 1.4 2012/01/13 14:14:02 cg Exp §'
! !