--- a/Tools__ChangeList.st Wed Feb 05 19:58:07 2014 +0100
+++ b/Tools__ChangeList.st Wed Feb 05 19:58:09 2014 +0100
@@ -28,9 +28,9 @@
"{ NameSpace: Tools }"
BrowserListWithFilter subclass:#ChangeList
- instanceVariableNames:'listHolder showRemovedHolder showSameHolder
- showConflictsOnlyHolder allowRemoveHolder allowAcceptHolder
- applyAction'
+ instanceVariableNames:'listHolder showRemovedHolder showSameHolder showTimestampHolder
+ allowRemoveHolder allowAcceptHolder scrollToBottom applyAction
+ showConflictsOnlyHolder'
classVariableNames:'LastSelectionConditionString'
poolDictionaries:''
category:'Interface-Browsers-ChangeSet'
@@ -132,54 +132,171 @@
<resource: #canvas>
- ^
+ ^
#(FullSpec
- name: windowSpec
- window:
+ name: windowSpec
+ window:
(WindowSpec
- label: 'Change List'
- name: 'Change List'
- min: (Point 10 10)
- bounds: (Rectangle 0 0 300 300)
- )
- component:
+ 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:
- )
- )
-
- )
+ collection: (
+ (InputFieldSpec
+ name: 'Filter'
+ layout: (LayoutFrame 0 0 0 0 0 1 25 0)
+ initiallyInvisible: true
+ model: filterPatternHolder
+ immediateAccept: true
+ acceptOnLeave: false
+ acceptOnReturn: false
+ acceptOnTab: false
+ acceptOnPointerLeave: false
+ emptyFieldReplacementText: 'Search Filter...'
+ postBuildCallback: postBuildFilterView:
+ )
+ (DataSetSpec
+ name: 'List'
+ layout: (LayoutFrame 0 0 0 0 0 1 0 1)
+ model: selectionHolder
+ menu: menuHolderWithShowFilter
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ dataList: listHolder
+ useIndex: false
+ doubleClickSelector: selectionDoubleclicked
+ columnHolder: listColumns
+ showLabels: false
+ multipleSelectOk: true
+ postBuildCallback: postBuildListView:
+ properties:
+ (PropertyListDictionary
+ startDragSelector: nil
+ dropObjectSelector: dragObjects:
+ canDropSelector: canDrop:
+ dropSelector: dropObjects:
+ )
+ )
+ )
+
+ )
+ )
+! !
+
+!ChangeList class methodsFor:'list specs'!
+
+listColumnSpec
+ "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:Tools::ChangeList andSelector:#listColumnSpec
+ "
+
+ <resource: #tableColumns>
+
+ ^#(
+ (DataSetColumnSpec
+ label: 'Removed'
+ id: 'removed'
+ labelButtonType: Button
+ width: 20
+ minWidth: 20
+ editorType: CheckToggle
+ rendererType: CheckToggle
+ model: notRemoved
+ menuFromApplication: false
+ printSelector: notRemoved
+ isResizeable: false
+ showRowSeparator: false
+ showSelectionHighLighted: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Delta'
+ id: 'delta'
+ labelButtonType: Button
+ width: 20
+ minWidth: 20
+ menuFromApplication: false
+ printSelector: iconDelta
+ canSelect: false
+ isResizeable: false
+ showRowSeparator: false
+ showSelectionHighLighted: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Change'
+ id: change
+ labelAlignment: left
+ labelButtonType: Button
+ menuFromApplication: false
+ printSelector: label
+ canSelect: false
+ showRowSeparator: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Class'
+ id: 'className'
+ labelAlignment: left
+ activeHelpKey: ''
+ activeHelpKeyForLabel: ''
+ labelButtonType: Button
+ usePreferredWidth: true
+ model: className
+ menuFromApplication: false
+ canSelect: false
+ showRowSeparator: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Selector'
+ id: 'selector'
+ labelAlignment: left
+ activeHelpKey: ''
+ activeHelpKeyForLabel: ''
+ labelButtonType: Button
+ usePreferredWidth: true
+ model: selector
+ menuFromApplication: false
+ canSelect: false
+ showRowSeparator: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Category'
+ id: category
+ labelAlignment: left
+ labelButtonType: Button
+ usePreferredWidth: true
+ model: category
+ menuFromApplication: false
+ canSelect: false
+ showRowSeparator: false
+ showColSeparator: false
+ )
+ (DataSetColumnSpec
+ label: 'Time Stamp'
+ id: timeStamp
+ labelAlignment: left
+ labelButtonType: Button
+ usePreferredWidth: true
+ model: timeStamp
+ menuFromApplication: false
+ canSelect: false
+ showRowSeparator: false
+ showColSeparator: false
+ )
)
- "Modified: / 29-11-2011 / 15:52:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!ChangeList class methodsFor:'menu specs'!
@@ -325,17 +442,17 @@
^ #(
#allowAcceptHolder
#allowRemoveHolder
-
#inGeneratorHolder
#menuHolder
#outGeneratorHolder
#selectionHolder
+ #showFilterHolder
#showRemovedHolder
#showSameHolder
+ #showTimestampHolder
#showConflictsOnlyHolder
).
- "Modified: / 24-01-2012 / 19:54:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!ChangeList methodsFor:'accessing'!
@@ -377,13 +494,31 @@
"Created: / 27-12-2011 / 14:18:25 / cg"
!
+scrollToBottom:aBoolean
+ "If set to true, list will automaticallu scroll to bottom
+ ehen the list is updated and clears this flag.
+
+ This is required as the list is updated asynchronously"
+
+ scrollToBottom := aBoolean.
+
+ "Modified (comment): / 30-03-2012 / 17:05:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
selection
- ^self selectionHolder value
+ ^(self selectionHolder value ? #()) reject:[:e|e isNil].
"Created: / 05-12-2009 / 14:48:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+selection: selection
+
+ self selectionHolder value: selection
+
+ "Created: / 30-03-2012 / 12:29:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
selectionIndices
|sel|
@@ -469,6 +604,19 @@
].
!
+listColumns
+
+ |holder|
+ (holder := builder bindingAt:#listColumns) isNil ifTrue:[
+ builder aspectAt:#listColumns put:(holder := List new).
+ self listColumnShow: #delta.
+ self listColumnShow: #change.
+ ].
+ ^ holder
+
+ "Created: / 26-07-2012 / 18:03:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
listHolder
listHolder isNil ifTrue:[
listHolder := ValueHolder new.
@@ -563,6 +711,35 @@
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:showSameHolder.
].
+!
+
+showTimestampHolder
+ "return/create the 'showTimestampHolder' value holder (automatically generated)"
+
+ showTimestampHolder isNil ifTrue:[
+ showTimestampHolder := ValueHolder new.
+ showTimestampHolder addDependent:self.
+ ].
+ ^ showTimestampHolder
+!
+
+showTimestampHolder:something
+ "set the 'showTimestampHolder' value holder (automatically generated)"
+
+ |oldValue newValue|
+
+ showTimestampHolder notNil ifTrue:[
+ oldValue := showTimestampHolder value.
+ showTimestampHolder removeDependent:self.
+ ].
+ showTimestampHolder := something.
+ showTimestampHolder notNil ifTrue:[
+ showTimestampHolder addDependent:self.
+ ].
+ newValue := showTimestampHolder value.
+ oldValue ~~ newValue ifTrue:[
+ self update:#value with:newValue from:showTimestampHolder.
+ ].
! !
!ChangeList methodsFor:'change & update'!
@@ -573,12 +750,24 @@
update: aspect with: param from: sender
+ sender == allowRemoveHolder ifTrue:[
+ self listColumn: #removed visible: allowRemoveHolder value.
+ ^self.
+ ].
+
+ sender == showTimestampHolder ifTrue:[
+ self listColumn: #timeStamp visible: showTimestampHolder value.
+ ^self.
+ ].
+
+
sender == selectionHolder ifTrue:[
self selectionChanged.
^ self
].
sender == showSameHolder ifTrue:[
- self updateList
+ self updateList.
+ ^self.
].
sender == showRemovedHolder ifTrue:[
self updateList
@@ -591,6 +780,38 @@
"Created: / 24-10-2009 / 19:47:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 27-12-2011 / 14:20:30 / cg"
+ "Modified: / 26-07-2012 / 18:44:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!ChangeList methodsFor:'drag & drop'!
+
+canDrop: aDropContext
+
+ ^(self inGeneratorHolder value isKindOf: Iterator) not
+ and:[aDropContext dropObjects allSatisfy:[:obj|(obj theObject isKindOf: Change)]].
+
+ "Created: / 01-08-2012 / 17:53:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+dragObjects: aDropSource
+
+ ^self selection collect:[:item|(DropObject new: item change) displayObject: (item labelAndIcon)]
+
+ "Created: / 01-08-2012 / 17:50:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+dropObjects:aDropContext
+ "drop manager wants to drop.
+ This is ony sent, if #canDrop: returned true.
+ Must be redefined in order for drop to work."
+
+ | changes |
+
+ changes := self inGeneratorHolder value.
+ aDropContext dropObjects do:[:obj|changes add: obj theObject].
+ self inGeneratorHolder changed: #value
+
+ "Modified: / 01-08-2012 / 18:15:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!ChangeList methodsFor:'event processing'!
@@ -634,11 +855,9 @@
!
keyPress:key x:x y:y view:aView
- <resource: #keyboard (#Ctrls #Accept)>
-
(key == #Accept or:[ key == #Ctrls]) ifTrue:[
- self listMenuApply.
- ^ self
+ self listMenuApply.
+ ^ self
].
"Created: / 08-02-2012 / 14:42:18 / cg"
@@ -675,15 +894,15 @@
!ChangeList methodsFor:'initialization'!
initialize
+
super initialize.
-
menuHolder := [self menuFor: #listMenu].
+ scrollToBottom := false.
applyAction isNil ifTrue:[
- applyAction := [:change | change apply ].
+ 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'!
@@ -897,6 +1116,62 @@
^ nil.
!
+listColumn: columnId visible: visible
+ visible ifTrue:[
+ self listColumnShow: columnId
+ ] ifFalse:[
+ self listColumnHide: columnId
+ ]
+
+ "Created: / 26-07-2012 / 18:20:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+listColumnHide: columnId
+ self listColumns do:[:spec|
+ spec id = columnId ifTrue:[
+ self listColumns remove: spec.
+ listView notNil ifTrue:[
+ listView invalidate.
+ ].
+ ^self
+ ].
+ ]
+
+ "Created: / 26-07-2012 / 18:19:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+listColumnShow: columnId
+
+ | columns |
+ columns := self listColumns.
+
+ columns do:[:spec|
+ spec id = columnId ifTrue:[
+ ^self.
+ ]
+ ].
+
+ self class listColumnSpec do:[:specArray|
+ | spec |
+
+ spec := specArray decodeAsLiteralArray.
+ spec id = columnId ifTrue:[
+ columnId == #removed ifTrue:[
+ columns addFirst: spec.
+ ] ifFalse:[
+ columns add: spec.
+ ].
+ listView notNil ifTrue:[
+ listView invalidate.
+ ].
+ ^self.
+ ]
+
+ ].
+
+ "Created: / 26-07-2012 / 17:56:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
listEntryFor:chg
^ListEntry change:chg application: self
@@ -921,35 +1196,47 @@
!
updateList
- |inGenerator changeset newList|
-
+ |inGenerator changeset firstLineShown oldSel newList newSel |
self withWaitCursorDo:[
inGenerator := self inGeneratorHolder value.
- changeset := inGenerator ifNil:[ #() ] ifNotNil:[ inGenerator ].
- self showConflictsOnlyHolder value ifTrue:[
- newList := changeset select: [:chg |
- chg isConflict
- ].
- ] ifFalse:[
- | showRemoved showSame |
+ listView notNil ifTrue:[
+ ((listView isKindOf: ScrollableView) not or:[listView scrolledView notNil]) ifTrue:[
+ firstLineShown := listView firstLineShown
+ ].
+ ].
+ oldSel := self selection.
- showRemoved := self showRemovedHolder value.
- showSame := self showSameHolder value.
-
- newList := changeset select: [:chg |
- (showRemoved or:[ chg removed not ])
- and:[showSame or:[chg delta ~~ #=]]
- ].
- ].
+ changeset := inGenerator isNil ifTrue:[ #() ] ifFalse:[ inGenerator ].
+ newList := changeset
+ select:
+ [:chg |
+ (self showRemovedHolder value or:[ chg removed not ])
+ and:[self showSameHolder value or:[chg delta ~~ #=]]
+ ].
newList := self filterList: newList.
newList := newList collect:[:chg | self listEntryFor:chg ].
self listHolder value ~= newList ifTrue:[
self listHolder value: newList.
+ ((newList size ~~ 0) and:[scrollToBottom]) ifTrue:[
+ self selection: { newList last }
+ ] ifFalse:[
+ oldSel notEmptyOrNil ifTrue:[
+ newSel := OrderedCollection new: oldSel size.
+ oldSel := oldSel reject:[:e|e isNil].
+ oldSel := oldSel collect:[:e|e change].
+ newList do:[:e|(oldSel includes:e change) ifTrue:[newSel add:e]].
+ self selection: newSel.
+ ].
+ (listView notNil and:[firstLineShown notNil]) ifTrue:[
+ listView scrollToLine: (newList size min: firstLineShown).
+ ].
+ ].
+ scrollToBottom := false.
+
]
]
-
- "Modified: / 29-11-2011 / 15:38:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-12-2011 / 15:46:15 / cg"
+ "Modified: / 01-08-2012 / 18:10:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!ChangeList methodsFor:'queries'!
@@ -981,6 +1268,13 @@
].
].
^ true
+!
+
+showColumn: columnSymbol
+
+ ^self showColumnSpecHolder value includes: columnSymbol.
+
+ "Created: / 03-04-2012 / 11:28:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!ChangeList::ListEntry class methodsFor:'instance creation'!
@@ -1040,10 +1334,17 @@
changeSource
"the changes source"
- ^change changeSource
+ "/ Hack to make sure code is displayed in similar way
+ "/ (i.e., with no namespace pragma)
+ ^ (change isClassDefinitionChange and:[change isPrivateClassDefinitionChange]) ifTrue:[
+ change definitionStringInNamespace: nil.
+ ] ifFalse:[
+ 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"
+ "Modified: / 14-11-2013 / 14:55:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
children
@@ -1112,6 +1413,23 @@
| label |
label := change displayString.
+
+ "Hack: if the printString contains multiple lines, then
+ if there are just 2 lines, then merge them, otherwise add
+ ... to the first line"
+ (label includes: Character cr) ifTrue:[
+ | firstCR secondCR |
+ firstCR := label indexOf: Character cr.
+ firstCR ~~ label size ifTrue:[
+ secondCR := label indexOf: Character cr startingAt: firstCR + 1.
+ ].
+ secondCR isNil ifTrue:[
+ "/2 lines only
+ label := label copy at: firstCR put: Character space.
+ ] ifFalse:[
+ label := (label copyTo: firstCR - 1) , '...'
+ ].
+ ].
self removed ifTrue:[label := label asText colorizeAllWith: Color gray].
^label
@@ -1121,8 +1439,28 @@
"Modified (format): / 27-07-2012 / 21:26:34 / cg"
!
+labelAndIcon
+ ^(LabelAndIcon label: self label icon: self iconDelta)
+
+ "Created: / 01-08-2012 / 18:14:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+notRemoved
+ ^ self removed not
+
+ "Created: / 26-07-2012 / 18:31:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+notRemoved: aBoolean
+ ^ self removed: aBoolean not
+
+ "Created: / 26-07-2012 / 18:31:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
removed
- ^ change removed
+ ^ change removed == true
+
+ "Modified: / 26-07-2012 / 18:30:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
removed:aBoolean
@@ -1134,31 +1472,50 @@
^change source
!
+timeStamp
+ ^change timeOfChangeIfKnown
+
+ "Created: / 26-07-2012 / 18:38:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
x
^ x
! !
!ChangeList::ListEntry methodsFor:'displaying'!
-displayLabel:aLabel h:lH on:aGC x:newX y:y h:h
- | cx icon |
+displayLabel:aLabel h:lH on:aGC x:newX y:y h:h
+ | list cx icon colW colS |
+ list := self application.
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"
+ (list allowRemoveHolder value and:[list showRemovedHolder 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)
+ icon displayOn: aGC x: cx y: y + (h / 2) - (icon height / 2)
].
- cx := cx + 16."12 + 2px gap"
+ cx := cx + 16."12 + 2px gap"
+
+ super displayLabel:aLabel h:lH on:aGC x:cx y:y h:h.
- super displayLabel:aLabel h:lH on:aGC x:cx y:y h:h
+"/ "Now, display additional columns..."
+"/ (list showColumn: #timestamp) ifTrue:[
+"/ cx := cx + (aLabel widthOn: aGC) + 5."px - padding"
+"/ colS := change timeOfChangeIfKnown notNil
+"/ ifTrue:[change timeOfChangeIfKnown printString]
+"/ ifFalse:['???'].
+"/ [ (colW := colS widthOn: aGC) > (aGC width - cx - 5) ] whileTrue:[
+"/ colS = '...' ifTrue:[ ^ self ].
+"/ colS := '...' , (colS copyFrom: 6).
+"/ ].
+"/ super displayLabel:colS h:lH on:aGC x: (aGC width - 5 - colW) 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"
+ "Modified: / 27-07-2012 / 17:13:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
iconDelta
@@ -1200,14 +1557,14 @@
!ChangeList class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.26 2013-09-05 23:18:30 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.27 2014-02-05 18:58:09 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.26 2013-09-05 23:18:30 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libtool/Tools__ChangeList.st,v 1.27 2014-02-05 18:58:09 cg Exp $'
!
version_SVN
- ^ '$Id: Tools__ChangeList.st,v 1.26 2013-09-05 23:18:30 cg Exp $'
+ ^ '$Id: Tools__ChangeList.st,v 1.27 2014-02-05 18:58:09 cg Exp $'
! !