Tools__ChangeList.st
author Claus Gittinger <cg@exept.de>
Sun, 14 Apr 2013 21:55:58 +0200
changeset 12666 c90e266fc135
parent 12657 3debb799f72d
child 12680 4e2f5b0d4cb2
child 13473 d8e9ed472e9f
child 13498 b8d845e42988
permissions -rw-r--r--
class: Tools::ChangeList added: #iconExcla #iconSelectorForChange: changed: #hasSingleChangeSelectedAndCanBrowse #listMenuApply #listMenuBrowseChanges:

"
 COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
              All Rights Reserved

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the 'Software'), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"
"{ Package: 'stx:libtool' }"

"{ NameSpace: Tools }"

BrowserListWithFilter subclass:#ChangeList
	instanceVariableNames:'listHolder showRemovedHolder showSameHolder
		showConflictsOnlyHolder allowRemoveHolder allowAcceptHolder
		applyAction'
	classVariableNames:'LastSelectionConditionString'
	poolDictionaries:''
	category:'Interface-Browsers-ChangeSet'
!

HierarchicalItem subclass:#ListEntry
	instanceVariableNames:'change application x'
	classVariableNames:''
	poolDictionaries:''
	privateIn:ChangeList
!

!ChangeList class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
              All Rights Reserved

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the 'Software'), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"
! !

!ChangeList class methodsFor:'image specs'!

iconEqual
    ^ ToolbarIconLibrary iconEqual12x12

    "Modified: / 31-08-2011 / 10:52:34 / cg"
!

iconEqualGrayed
    ^ ToolbarIconLibrary iconEqualGray12x12

    "Modified: / 31-08-2011 / 10:54:00 / cg"
!

iconExcla
    ^ ToolbarIconLibrary iconExclaRed12x12
!

iconMinus
    ^ ToolbarIconLibrary iconMinusRed12x12

    "Modified: / 24-07-2012 / 16:43:36 / cg"
!

iconMinusGrayed
    ^ ToolbarIconLibrary iconMinusGray12x12

    "Modified: / 31-08-2011 / 10:54:40 / cg"
!

iconPlus
    ^ ToolbarIconLibrary iconPlusBlue12x12

    "Modified: / 24-07-2012 / 16:43:31 / cg"
!

iconPlusGrayed
    ^ ToolbarIconLibrary iconPlusGray12x12

    "Modified: / 31-08-2011 / 10:54:46 / cg"
! !

!ChangeList 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:Tools::ChangeList andSelector:#windowSpec
     Tools::ChangeList new openInterface:#windowSpec
     Tools::ChangeList open
    "

    <resource: #canvas>

    ^ 
     #(FullSpec
        name: windowSpec
        window: 
       (WindowSpec
          label: 'Change List'
          name: 'Change List'
          min: (Point 10 10)
          bounds: (Rectangle 0 0 300 300)
        )
        component: 
       (SpecCollection
          collection: (
           (SelectionInListModelViewSpec
              name: 'List'
              layout: (LayoutFrame 0 0 0 0 0 1 0 1)
              model: selectionHolder
              menu: menuHolderWithShowFilter
              hasHorizontalScrollBar: true
              hasVerticalScrollBar: true
              listModel: listHolder
              multipleSelectOk: true
              useIndex: false
              highlightMode: line
              doubleClickSelector: selectionDoubleclicked
              postBuildCallback: postBuildListView:
            )
           (InputFieldSpec
              name: 'Filter'
              layout: (LayoutFrame 0 0 0 0 0 1 26 0)
              initiallyInvisible: true
              model: filterPatternHolder
              immediateAccept: true
              acceptOnLeave: false
              acceptOnReturn: false
              acceptOnTab: false
              acceptOnPointerLeave: false
              emptyFieldReplacementText: 'Search Filter...'
              usePreferredHeight: true
              useDynamicPreferredHeight: true
              postBuildCallback: postBuildFilterView:
            )
           )
         
        )
      )

    "Modified: / 29-11-2011 / 15:52:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList class methodsFor:'menu specs'!

listMenu
    "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:Tools::ChangeList andSelector:#listMenu
     (Menu new fromLiteralArrayEncoding:(Tools::ChangeList listMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu
        (
         (MenuItem
            enabled: hasChangeSelectedAndNotRemoved
            label: 'Apply'
            itemValue: listMenuApply
            translateLabel: true
            isVisible: allowAcceptHolder
            shortcutKey: Accept
          )
         (MenuItem
            label: 'Apply all'
            itemValue: listMenuApplyAll
            translateLabel: true
            isVisible: allowAcceptHolder
          )
         (MenuItem
            enabled: hasSingleChangeSelectedAndCanBrowse
            label: 'Browse'
            itemValue: listMenuBrowse
            translateLabel: true
          )
         (MenuItem
            label: '-'
          )
         (MenuItem
            label: 'Delete'
            itemValue: listMenuDeleteSelection
            nameKey: Delete
            translateLabel: true
            isVisible: allowRemoveHolder
            shortcutKey: Delete
          )
         (MenuItem
            label: '-'
            isVisible: allowRemoveHolder
          )
         (MenuItem
            label: 'Select...'
            translateLabel: true
            submenu: 
           (Menu
              (
               (MenuItem
                  label: 'Select same'
                  itemValue: listMenuSelectSame
                  translateLabel: true
                )
               (MenuItem
                  label: 'Select conflicts (redefined classes/methods)'
                  itemValue: listMenuSelectConflicts
                  translateLabel: true
                )
               (MenuItem
                  label: 'Select additions (new classes/methods)'
                  itemValue: listMenuSelectAdditions
                  translateLabel: true
                )
               (MenuItem
                  label: 'Select removals'
                  itemValue: listMenuSelectRemovals
                  translateLabel: true
                )
               (MenuItem
                  label: '-'
                )
               (MenuItem
                  label: 'Select all'
                  itemValue: listMenuSelectAll
                  translateLabel: true
                )
               (MenuItem
                  label: 'Select none'
                  itemValue: listMenuSelectNone
                  translateLabel: true
                )
               (MenuItem
                  label: '-'
                )
               (MenuItem
                  label: 'Select using block'
                  itemValue: listMenuSelectUsingBlock
                  translateLabel: true
                )
               )
              nil
              nil
            )
          )
         (MenuItem
            label: '-'
          )
         (MenuItem
            label: 'Show Deleted'
            translateLabel: true
            isVisible: allowRemoveHolder
            indication: showRemovedHolder
          )
         (MenuItem
            label: 'Inspect change'
            itemValue: listMenuInspect
            translateLabel: true
          )
         )
        nil
        nil
      )
! !

!ChangeList class methodsFor:'plugIn spec'!

aspectSelectors
    "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."

    "Return a description of exported aspects;
     these can be connected to aspects of an embedding application
     (if this app is embedded in a subCanvas)."

    ^ #(
        #allowAcceptHolder
        #allowRemoveHolder

        #inGeneratorHolder
        #menuHolder
        #outGeneratorHolder
        #selectionHolder
        #showRemovedHolder
        #showSameHolder
        #showConflictsOnlyHolder
      ).

    "Modified: / 24-01-2012 / 19:54:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList methodsFor:'accessing'!

acceptEnabled
    ^ self allowAccept

    "Created: / 08-02-2012 / 14:45:12 / cg"
!

allowAccept
    ^ self allowAcceptHolder value

    "Created: / 24-01-2012 / 19:52:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

allowAccept: aBoolean
    ^ self allowAcceptHolder value: aBoolean

    "Created: / 24-01-2012 / 19:52:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

allowRemoved
    ^ self allowRemoveHolder value ? true

    "Created: / 05-12-2009 / 14:28:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

applyAction:aBlock
    applyAction := aBlock.

    "Modified (format): / 10-09-2012 / 14:15:30 / cg"
!

list
    ^ listHolder value

    "Created: / 05-12-2009 / 14:48:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 27-12-2011 / 14:18:25 / cg"
!

selection

    ^self selectionHolder value

    "Created: / 05-12-2009 / 14:48:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

selectionIndices
    |sel|

    (sel := self selectionHolder value) isEmptyOrNil ifTrue:[^ #()].
    ^ sel collect:[:each | self list identityIndexOf:each].

    "Created: / 05-12-2009 / 14:48:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 27-12-2011 / 10:56:20 / cg"
!

showRemoved

    ^self showRemovedHolder value ? true

    "Created: / 05-12-2009 / 14:28:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList methodsFor:'actions'!

selectionDoubleclicked

    self listMenuBrowse
"/    | app |
"/
"/    self selection do:
"/        [:e|e removed: e removed not].
"/    ((app := self masterApplication) respondsTo: #redrawChangeListViews)
"/        ifTrue:[app redrawChangeListViews].

    "Modified: / 24-01-2012 / 22:01:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList methodsFor:'aspects'!

allowAcceptHolder
    "return/create the valueHolder 'acceptEnabledHolder'"

    allowAcceptHolder isNil ifTrue:[
        allowAcceptHolder := ValueHolder with:nil "defaultValue here".
    ].
    ^ allowAcceptHolder

    "Created: / 24-01-2012 / 19:53:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

allowAcceptHolder:something
    "set the 'allowAcceptHolder' value holder (automatically generated)"

    allowAcceptHolder := something.
!

allowRemoveHolder
    "return/create the 'allowRemoveHolder' value holder (automatically generated)"
    
    allowRemoveHolder isNil ifTrue:[
        allowRemoveHolder := ValueHolder with:true.
        allowRemoveHolder addDependent:self.
    ].
    ^ allowRemoveHolder

    "Modified (comment): / 24-01-2012 / 19:44:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

allowRemoveHolder:something 
    "set the 'showRemovedHolder' value holder (automatically generated)"
    
    |oldValue newValue|

    allowRemoveHolder notNil ifTrue:[
        oldValue := allowRemoveHolder value.
        allowRemoveHolder removeDependent:self.
    ].
    allowRemoveHolder := something.
    allowRemoveHolder notNil ifTrue:[
        allowRemoveHolder addDependent:self.
    ].
    newValue := allowRemoveHolder value.
    oldValue ~~ newValue ifTrue:[
        self 
            update:#value
            with:newValue
            from:allowRemoveHolder.
    ].
!

listHolder
    listHolder isNil ifTrue:[
        listHolder := ValueHolder new.
    ].
    ^ listHolder
!

showConflictsOnlyHolder
    "return/create the 'showConflictsOnlyHolder' value holder (automatically generated)"

    showConflictsOnlyHolder isNil ifTrue:[
        showConflictsOnlyHolder := ValueHolder with: true.
        showConflictsOnlyHolder addDependent: self.
    ].
    ^ showConflictsOnlyHolder
!

showConflictsOnlyHolder:something
    "set the 'showConflictsOnlyHolder' value holder (automatically generated)"

    |oldValue newValue|

    showConflictsOnlyHolder notNil ifTrue:[
        oldValue := showConflictsOnlyHolder value.
        showConflictsOnlyHolder removeDependent:self.
    ].
    showConflictsOnlyHolder := something.
    showConflictsOnlyHolder notNil ifTrue:[
        showConflictsOnlyHolder addDependent:self.
    ].
    newValue := showConflictsOnlyHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:showConflictsOnlyHolder.
    ].
!

showRemovedHolder
    "return/create the 'showRemovedHolder' value holder (automatically generated)"

    showRemovedHolder isNil ifTrue:[
        showRemovedHolder := ValueHolder with: true.
        showRemovedHolder addDependent: self.
    ].
    ^ showRemovedHolder
!

showRemovedHolder:something
    "set the 'showRemovedHolder' value holder (automatically generated)"

    |oldValue newValue|

    showRemovedHolder notNil ifTrue:[
        oldValue := showRemovedHolder value.
        showRemovedHolder removeDependent:self.
    ].
    showRemovedHolder := something.
    showRemovedHolder notNil ifTrue:[
        showRemovedHolder addDependent:self.
    ].
    newValue := showRemovedHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:showRemovedHolder.
    ].
!

showSameHolder
    "return/create the 'showSameHolder' value holder (automatically generated)"

    showSameHolder isNil ifTrue:[
        showSameHolder := ValueHolder with: true.
        showSameHolder addDependent:self.
    ].
    ^ showSameHolder

    "Modified: / 04-08-2011 / 18:39:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

showSameHolder:something
    "set the 'showSameHolder' value holder (automatically generated)"

    |oldValue newValue|

    showSameHolder notNil ifTrue:[
        oldValue := showSameHolder value.
        showSameHolder removeDependent:self.
    ].
    showSameHolder := something.
    showSameHolder notNil ifTrue:[
        showSameHolder addDependent:self.
    ].
    newValue := showSameHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:showSameHolder.
    ].
! !

!ChangeList methodsFor:'change & update'!

selectionChanged
   super selectionChanged
!

update: aspect with: param from: sender

    sender == selectionHolder ifTrue:[
        self selectionChanged.
        ^ self
    ].
    sender == showSameHolder ifTrue:[
        self updateList
    ].
    sender == showRemovedHolder ifTrue:[
        self updateList
    ].
    sender == showConflictsOnlyHolder ifTrue:[
        self updateList
    ].

    ^super update: aspect with: param from: sender

    "Created: / 24-10-2009 / 19:47:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 27-12-2011 / 14:20:30 / cg"
! !

!ChangeList methodsFor:'event processing'!

buttonPress:button x:x y:y view:aView

    | itemIndex item |

    button ~= 1 ifTrue:[^aView buttonPress:button x:x y:y].

    itemIndex := aView yVisibleToLineNr:y.
    itemIndex isNil ifTrue:[^self].
    itemIndex == 0 ifTrue:[^self].
    itemIndex > aView list size ifTrue:[^self].
    item := aView list at: itemIndex.

    ((aView left + x) between: (item x) and: (item x + 16))
        ifFalse:[^aView buttonPress:button x:x y:y].

    item removed: item removed not.
    aView invalidate

    "Created: / 08-12-2009 / 14:12:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 18-11-2011 / 14:55:41 / cg"
!

handlesButtonPress:button inView:aView

    ^listView scrolledView == aView

    "Created: / 08-12-2009 / 14:08:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

handlesKeyPress:key inView:aView
    <resource: #keyboard (#Accept #Ctrls)>

    ^(key == #Accept or:[ key == #Ctrls]) 
        and:[ listView scrolledView == aView ]

    "Created: / 08-02-2012 / 14:43:11 / cg"
!

keyPress:key x:x y:y view:aView
    <resource: #keyboard (#Ctrls #Accept)>

    (key == #Accept or:[ key == #Ctrls]) ifTrue:[
        self listMenuApply.
        ^ self
    ].

    "Created: / 08-02-2012 / 14:42:18 / cg"
! !

!ChangeList methodsFor:'generators'!

makeGenerator
    "Superclass Tools::BrowserList says that I am responsible to implement this method"

    ^Iterator on:
        [:whatToDo|

        selectionHolder value do:
            [:changeListItem| | change |
            change := changeListItem change.
            change isCompositeChange ifTrue:
                [change changes do: whatToDo]]].

    "Modified: / 24-07-2009 / 23:00:41 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 24-10-2009 / 20:00:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList methodsFor:'hooks'!

postBuildListView: aView

    super postBuildListView: aView.
    listView scrolledView delegate: self.

    "Created: / 29-11-2011 / 14:56:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ChangeList methodsFor:'initialization'!

initialize
    super initialize.

    menuHolder := [self menuFor: #listMenu].
    applyAction isNil ifTrue:[
        applyAction := [:change | change apply ].
    ].

    "Created: / 29-10-2010 / 12:50:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 10-09-2012 / 13:57:20 / cg"
! !

!ChangeList methodsFor:'menu actions'!

listMenuApply
    |sel list idx selectionHolder|

    self acceptEnabled ifFalse:[^self].
    selectionHolder := self selectionHolder.

    (sel := selectionHolder value) do:[:e| applyAction value:e change].
    sel size == 1 ifTrue:[
        list := self listHolder value. 
        idx := list indexOf:(sel first). 
        idx < list size ifTrue:[
            selectionHolder value:(Array with:(list at:idx+1))
        ] ifFalse:[
            selectionHolder value:#()
        ].
    ].

    "Modified: / 24-10-2009 / 22:02:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 10-09-2012 / 13:57:46 / cg"
!

listMenuApplyAll

    self acceptEnabled ifFalse:[^self].

    self selection value do:
        [:e|e removed ifFalse:[applyAction value:e change]].

    "Created: / 05-12-2009 / 14:53:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 10-09-2012 / 13:57:58 / cg"
!

listMenuBrowse

    self listMenuBrowseChanges:
        ((self selectionHolder value ? #()) collect:[:e|e change])

    "Modified: / 24-01-2012 / 22:00:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

listMenuBrowseChanges: changes
    | classes methods methodsOnly browserClass|

    classes := Set new.
    methods := Set new.
    methodsOnly := true.
    changes do: [:each |
        each isClassChange ifTrue:[
            each changeClass ifNotNil:[
                classes add: each  changeClass.
                each isMethodCodeChange 
                    ifTrue:
                        [each changeMethod ifNotNil:
                            [methods add:each changeMethod]]
                    ifFalse:
                        [methodsOnly := false]
            ]
        ]
    ].

    browserClass := Smalltalk browserClass.
    methodsOnly 
        ifTrue:
            [methods size = 1 
                ifTrue:[ browserClass openInMethod: methods anyOne]
                ifFalse:[ browserClass browseMethods: methods asArray title: 'Selected methods from changeset' sort: true]]
        ifFalse:
            [classes size = 1
                ifTrue:[ browserClass browseClass: classes anyOne]
                ifFalse:[ browserClass browseClasses: classes]]

    "Modified: / 24-10-2009 / 22:02:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 24-01-2012 / 22:00:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

listMenuDeleteSelection

    self selectionHolder value do:
        [:each|each removed: true].
    self updateList
!

listMenuInspect

    | selection |

    selection := self selectionHolder value collect:[:e|e change].
    selection size = 1
        ifTrue:[selection anyOne inspect]
        ifFalse:[selection inspect].

    "Modified: / 24-10-2009 / 22:02:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

listMenuSelectAdditions

    self listMenuSelectAllSuchThat:[:change|change delta = #+]
!

listMenuSelectAll

    self listMenuSelectAllSuchThat:[:change|true]
!

listMenuSelectAllSuchThat:conditionBlock 
    |newSelection|

    newSelection := self listHolder value 
                select:[:entry | conditionBlock value:entry change ].
    self selectionHolder value:newSelection
!

listMenuSelectNone

    self listMenuSelectAllSuchThat:[:change|false]
!

listMenuSelectRemovals

    self listMenuSelectAllSuchThat:[:change|change delta = #-]
!

listMenuSelectSame

    self listMenuSelectAllSuchThat:[:change|change delta = #=]
!

listMenuSelectUsingBlock

    |conditionBlockString conditionBlock dialog textHolder template|

    template :=
'[:change|
     "/ Define condition for selection below:
     "/ change is an instance of Change
     "/ change will be selected if and only if block returns true

    
     true"/always select the change
]
'.

    LastSelectionConditionString isNil ifTrue:[
        LastSelectionConditionString := template.
    ].


    textHolder := ValueHolder new.
    dialog := Dialog
                 forRequestText:(resources string:'Enter condition for selection')
                 lines:20
                 columns:70
                 initialAnswer:LastSelectionConditionString
                 model:textHolder.
    dialog addButton:(Button label:'Template' action:[textHolder value:template. textHolder changed:#value.]).
    dialog open.
    dialog accepted ifFalse:[^ self].

    conditionBlockString := textHolder value.
    LastSelectionConditionString := conditionBlockString.

    conditionBlock := Parser evaluate:conditionBlockString.
    conditionBlock isBlock ifFalse:[
        self error:'Bad selection block (syntax error?)'.
        ^ self
    ].

    self listMenuSelectAllSuchThat: conditionBlock
!

listMenuUndeleteSelection

    self selectionHolder value do:
        [:each|each removed: false].
    self updateList
! !

!ChangeList methodsFor:'private'!

application

    ^self

    "Created: / 05-12-2009 / 14:10:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

browserNameList

    ^'Change list'

    "Modified: / 24-07-2009 / 22:06:53 / Jan Vrany <vranyj1@fel.cvut.cz>"
!

iconSelectorForChange:change
    | delta sym selectorOrNil |

    masterApplication notNil ifTrue:[
        selectorOrNil := masterApplication iconSelectorForChange:change.
        selectorOrNil notNil ifTrue:[ ^ selectorOrNil ].
    ].
    delta := change deltaDetail.
    sym := delta shortDeltaSymbol.
    sym = #+ ifTrue:[^#iconPlus].
    sym = #- ifTrue:[^#iconMinus].
    sym = #= ifTrue:[^#iconEqual].
    "/ different.
    ^ nil.
!

listEntryFor:chg 
    ^ListEntry change:chg application: self

    "Modified: / 05-12-2009 / 14:39:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

makeDependent

    "Modified: / 24-07-2009 / 22:06:32 / Jan Vrany <vranyj1@fel.cvut.cz>"
!

makeIndependent

    "Modified: / 24-07-2009 / 22:06:37 / Jan Vrany <vranyj1@fel.cvut.cz>"
!

parentOrModel

    ^self

    "Created: / 05-12-2009 / 14:14:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateList
    |inGenerator changeset newList|

    self withWaitCursorDo:[
        inGenerator := self inGeneratorHolder value.
        changeset := inGenerator ifNil:[ #() ] ifNotNil:[ inGenerator ].
        self showConflictsOnlyHolder value ifTrue:[
            newList := changeset select: [:chg | 
                           chg isConflict
                       ].
        ] ifFalse:[
            | showRemoved showSame |

            showRemoved := self showRemovedHolder value.
            showSame := self showSameHolder value.

            newList := changeset select: [:chg | 
                           (showRemoved or:[ chg removed not ])
                               and:[showSame or:[chg delta ~~ #=]]
                       ].
        ].
        newList := self filterList: newList.
        newList := newList collect:[:chg | self listEntryFor:chg ].
        self listHolder value ~= newList ifTrue:[
            self listHolder value: newList.
        ]
    ]

    "Modified: / 29-11-2011 / 15:38:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 28-12-2011 / 15:46:15 / cg"
! !

!ChangeList methodsFor:'queries'!

hasChangeSelected

    ^self selectionHolder value size > 0
!

hasChangeSelectedAndNotRemoved

    | selection |
    selection := self selectionHolder value ? #().
    ^selection size > 0 and:
        [selection allSatisfy:[:e|e removed not]].
!

hasSingleChangeSelected

    ^self selectionHolder value size = 1
!

hasSingleChangeSelectedAndCanBrowse
    self selectionHolder value ? #() do: [:each |
        |chg|

        chg := each change.
        chg isClassChange ifTrue:[
            (chg isMethodChange not or:[chg isMethodCodeChange]) ifFalse:[^ false]
        ].
    ].
    ^ true
! !

!ChangeList::ListEntry class methodsFor:'instance creation'!

change: aChange

    ^self new change: aChange

    "Created: / 24-07-2009 / 22:43:41 / Jan Vrany <vranyj1@fel.cvut.cz>"
!

change: aChange application: anApplicationModel

    ^self new change: aChange; application: anApplicationModel

    "Created: / 05-12-2009 / 14:16:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

change: aChange parent: aChangeList

    ^self new change: aChange; parent: aChangeList

    "Created: / 25-07-2009 / 23:33:00 / Jan Vrany <vranyj1@fel.cvut.cz>"
! !

!ChangeList::ListEntry methodsFor:'accessing'!

application
    ^ application ifNil:[super application]

    "Modified: / 05-12-2009 / 14:16:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

application:anApplicationModel
    application := anApplicationModel.

    "Modified: / 05-12-2009 / 14:15:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

change
    ^ change
!

change:aChange
    self assert: ((aChange isKindOf: Change) or:[aChange isKindOf: RefactoryChange]).
    change := aChange.

    "Modified: / 25-07-2009 / 23:40:38 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified (format): / 04-12-2011 / 14:58:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

changeClass

    ^change changeClass
!

changeSource
    "the changes source"

    ^change changeSource

    "Created: / 19-07-2011 / 12:03:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 25-07-2012 / 17:39:39 / cg"
!

children

    children isNil ifTrue:[
        change isCompositeChange ifTrue:[
            children := OrderedCollection new: change changes size.
            self application showConflictsOnlyHolder value ifTrue:[
                change changes do:[:chg|
                    (chg isConflict) ifTrue:[
                        children add: ((self application listEntryFor: chg) parent: self)
                    ]
                ].
            ] ifFalse:[
                |showRemoved showSame|

                showRemoved := self application showRemovedHolder value.
                showSame := self application showSameHolder value.

                change changes do:[:chg|
                    ((showRemoved or:[ chg removed not ])
                        and:[showSame or:[chg delta ~~ #=]]) 
                            ifTrue:[
                                children add: ((self application listEntryFor: chg) parent: self)
                            ]
                ].
            ]
        ] ifFalse:[
            children :=  #()
        ]
    ].
    ^children

    "Created: / 25-07-2009 / 23:32:39 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified (format): / 18-11-2011 / 14:56:25 / cg"
    "Modified: / 04-12-2011 / 15:08:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delta
    "/ obsolete: please use deltaDetail

    ^change delta

    "Created: / 29-10-2010 / 14:32:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 31-08-2011 / 10:30:02 / cg"
!

deltaDetail

    ^change deltaDetail

    "Created: / 29-10-2010 / 14:32:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 31-08-2011 / 10:29:21 / cg"
!

imageSource
    "return the source for the in-image version of the change"

    ^ change imageSource

    "Created: / 19-07-2011 / 12:03:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 25-07-2012 / 17:38:57 / cg"
!

label
    | label |

    label := change displayString.
    self removed ifTrue:[label := label asText colorizeAllWith: Color gray].
    ^label

    "Created: / 05-11-2008 / 08:20:02 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 25-07-2009 / 23:43:23 / Jan Vrany <vranyj1@fel.cvut.cz>"
    "Modified: / 05-12-2009 / 14:46:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 27-07-2012 / 21:26:34 / cg"
!

removed
    ^ change removed
!

removed:aBoolean
    change removed: aBoolean.
!

source

    ^change source
!

x
    ^ x
! !

!ChangeList::ListEntry methodsFor:'displaying'!

displayLabel:aLabel h:lH on:aGC x:newX y:y h:h 
    | cx icon |

    cx := x := newX.
    self application allowRemoveHolder value ifTrue:[
        (icon := self iconRemoved) notNil ifTrue:[
            icon displayOn: aGC x: cx y: y + (h / 2) - (icon height / 2) 
        ].
        cx := cx + 22."experimental value - this looks good"
    ].
    (icon := self iconDelta) notNil ifTrue:[
        icon displayOn: aGC x: cx y: y + (h / 2) - (icon height / 2) 
    ].
    cx := cx + 16."12 + 2px gap"                

    super displayLabel:aLabel h:lH on:aGC x:cx y:y h:h

    "Modified: / 24-01-2012 / 21:44:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 27-07-2012 / 21:26:23 / cg"
!

iconDelta
    | iconSelector |

    iconSelector := self iconSelector.
    iconSelector isNil ifTrue:[^nil].
    self removed ifTrue:[iconSelector := iconSelector , #Grayed].
    ^self application class perform: iconSelector asSymbol.

    "Created: / 05-12-2009 / 14:11:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 18-11-2011 / 14:56:33 / cg"
!

iconRemoved
    |appClass|

    appClass := self application class.
    ^self removed 
        ifTrue: [appClass uncheckedIcon ]
        ifFalse:[appClass checkedIcon ]

    "Created: / 05-12-2009 / 14:11:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

iconSelector
    ^ application iconSelectorForChange:change
! !

!ChangeList::ListEntry methodsFor:'protocol-queries'!

hasChildren
    ^ change isCompositeChange and:[change changes notEmptyOrNil ].

    "Created: / 04-12-2011 / 14:45:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 27-07-2012 / 21:25:34 / cg"
! !

!ChangeList class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.24 2013-04-14 19:55:58 cg Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.24 2013-04-14 19:55:58 cg Exp $'
!

version_SVN
    ^ '§Id: Tools__ChangeList.st 7486 2009-10-26 22:06:24Z vranyj1 §'
! !