diff --git a/src/Spec2-CommonWidgets-Tests/SpChooserPresenterTest.class.st b/src/Spec2-CommonWidgets-Tests/SpChooserPresenterTest.class.st index 6a688454..c476eace 100644 --- a/src/Spec2-CommonWidgets-Tests/SpChooserPresenterTest.class.st +++ b/src/Spec2-CommonWidgets-Tests/SpChooserPresenterTest.class.st @@ -43,6 +43,47 @@ SpChooserPresenterTest >> testAddAll [ self assert: chooserPresenter targetList unfilteredItems isNotEmpty ] +{ #category : 'tests' } +SpChooserPresenterTest >> testAddAllOfFiltered [ + + | sourceItemsToAdd sourceItems targetItems allItems presenter | + sourceItemsToAdd := #( ToAdd1 ToAdd2 ). + sourceItems := { 'S1' } , sourceItemsToAdd. + targetItems := { 'T1'. 'T2' }. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter sourceList filterInputPresenter text: 'ToAdd'. + + self + assertCollection: presenter sourceList items + hasSameElements: sourceItemsToAdd. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: targetItems. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter addAll. + + self + assert: presenter sourceList filterInputPresenter text + equals: ''. + self + assertCollection: presenter sourceList items + hasSameElements: sourceItems \ sourceItemsToAdd. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems \ sourceItemsToAdd +] + { #category : 'tests' } SpChooserPresenterTest >> testAddItemUsingFilter [ @@ -74,6 +115,93 @@ SpChooserPresenterTest >> testAddSelected [ equals: self items size - 1 ] +{ #category : 'tests' } +SpChooserPresenterTest >> testAddSelectedAllOfFiltered [ + + | sourceItemsToAdd sourceItems targetItems allItems presenter | + sourceItemsToAdd := #( ToAdd1 ToAdd2 ). + sourceItems := { 'S1' } , sourceItemsToAdd. + targetItems := { 'T1'. 'T2' }. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter sourceList filterInputPresenter text: 'ToAdd'. + + self + assertCollection: presenter sourceList items + hasSameElements: sourceItemsToAdd. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: targetItems. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter sourceList selectItems: sourceItemsToAdd. + presenter addSelected. + + self + assert: presenter sourceList filterInputPresenter text + equals: ''. + self + assertCollection: presenter sourceList items + hasSameElements: sourceItems \ sourceItemsToAdd. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems \ sourceItemsToAdd +] + +{ #category : 'tests' } +SpChooserPresenterTest >> testAddSelectedPartOfFiltered [ + + | sourceItemToAdd sourceItems targetItems allItems presenter | + sourceItemToAdd := 'ToAdd'. + sourceItems := { + 'S1'. + 'ToNotAdd'. + sourceItemToAdd }. + targetItems := { 'T1'. 'T2' }. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter sourceList filterInputPresenter text: 'To'. + + self + assertCollection: presenter sourceList items + hasSameElements: #( ToAdd ToNotAdd ). + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: targetItems. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter sourceList selectItem: sourceItemToAdd. + presenter addSelected. + + self + assert: presenter sourceList filterInputPresenter text + equals: 'To'. + self + assertCollection: presenter sourceList items + hasSameElements: { 'ToNotAdd' }. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: (sourceItems copyWithout: sourceItemToAdd) +] + { #category : 'tests' } SpChooserPresenterTest >> testAllRemoveThenAdd [ @@ -151,11 +279,32 @@ SpChooserPresenterTest >> testFilterBothThenRemove [ presenter sourceList filterInputPresenter text: 'ToAdd'. presenter targetList filterInputPresenter text: 'ToRemove'. + + + self + assertCollection: presenter sourceList items + hasSameElements: { sourceItemToAdd }. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: { targetItemToRemove }. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + presenter removeAll. + self + assert: presenter sourceList filterInputPresenter text + equals: 'ToAdd'. + self + assert: presenter targetList filterInputPresenter text + equals: ''. self assertCollection: presenter sourceList items - hasSameElements: sourceItems , { targetItemToRemove }. + hasSameElements: { sourceItemToAdd }. self assertCollection: presenter sourceList unfilteredItems hasSameElements: sourceItems , { targetItemToRemove }. @@ -225,6 +374,47 @@ SpChooserPresenterTest >> testRemoveAll [ self assert: chooserPresenter targetList unfilteredItems isEmpty ] +{ #category : 'tests' } +SpChooserPresenterTest >> testRemoveAllOfFiltered [ + + | targetItemsToRemove sourceItems targetItems allItems presenter | + targetItemsToRemove := #( ToRemove1 ToRemove2 ). + sourceItems := { 'S1'. 'S2' }. + targetItems := { 'T1' } , targetItemsToRemove. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter targetList filterInputPresenter text: 'ToRemove'. + + self + assertCollection: presenter sourceList items + hasSameElements: sourceItems. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: targetItemsToRemove. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter removeAll. + + self + assert: presenter targetList filterInputPresenter text + equals: ''. + self + assertCollection: presenter targetList items + hasSameElements: targetItems \ targetItemsToRemove. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems \ targetItemsToRemove +] + { #category : 'tests' } SpChooserPresenterTest >> testRemoveItemUsingFilter [ @@ -257,6 +447,93 @@ SpChooserPresenterTest >> testRemoveSelected [ equals: self items size - 1 ] +{ #category : 'tests' } +SpChooserPresenterTest >> testRemoveSelectedAllOfFiltered [ + + | targetItemsToRemove sourceItems targetItems allItems presenter | + targetItemsToRemove := #( ToRemove1 ToRemove2 ). + sourceItems := { 'S1'. 'S2' }. + targetItems := { 'T1' } , targetItemsToRemove. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter targetList filterInputPresenter text: 'ToRemove'. + + self + assertCollection: presenter sourceList items + hasSameElements: sourceItems. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: targetItemsToRemove. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter targetList selectItems: targetItemsToRemove. + presenter removeSelected. + + self + assert: presenter targetList filterInputPresenter text + equals: ''. + self + assertCollection: presenter targetList items + hasSameElements: targetItems \ targetItemsToRemove. + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems \ targetItemsToRemove +] + +{ #category : 'tests' } +SpChooserPresenterTest >> testRemoveSelectedPartOfFiltered [ + + | targetItemToRemove sourceItems targetItems allItems presenter | + targetItemToRemove := 'ToRemove'. + sourceItems := { 'S1'. 'S2' }. + targetItems := { + 'T1'. + 'ToNotRemove'. + targetItemToRemove }. + allItems := sourceItems , targetItems. + + presenter := SpChooserPresenter + sourceItems: sourceItems copy + chosenItems: targetItems copy. + + presenter targetList filterInputPresenter text: 'To'. + + self + assertCollection: presenter sourceList items + hasSameElements: sourceItems. + self + assertCollection: presenter sourceList unfilteredItems + hasSameElements: sourceItems. + self + assertCollection: presenter targetList items + hasSameElements: #( ToNotRemove ToRemove ). + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: targetItems. + + presenter targetList selectItem: targetItemToRemove. + presenter removeSelected. + + self + assert: presenter targetList filterInputPresenter text + equals: 'To'. + self + assertCollection: presenter targetList items + hasSameElements: #( ToNotRemove ). + self + assertCollection: presenter targetList unfilteredItems + hasSameElements: (targetItems copyWithout: targetItemToRemove) +] + { #category : 'tests' } SpChooserPresenterTest >> testSelectedAddThenRemove [ diff --git a/src/Spec2-CommonWidgets/SpChooserPresenter.class.st b/src/Spec2-CommonWidgets/SpChooserPresenter.class.st index 31a78ba8..9dfd0f99 100644 --- a/src/Spec2-CommonWidgets/SpChooserPresenter.class.st +++ b/src/Spec2-CommonWidgets/SpChooserPresenter.class.st @@ -10,8 +10,7 @@ Class { 'sourceLabel', 'sourceList', 'targetLabel', - 'targetList', - 'displayBlock' + 'targetList' ], #category : 'Spec2-CommonWidgets-Core', #package : 'Spec2-CommonWidgets', @@ -101,15 +100,13 @@ SpChooserPresenter class >> title [ { #category : 'actions' } SpChooserPresenter >> addAll [ - self moveAllFrom: sourceList to: targetList. - self sortLists + self moveAllFrom: sourceList to: targetList ] { #category : 'actions' } SpChooserPresenter >> addSelected [ - self moveSelectedFrom: sourceList to: targetList. - self sortLists + self moveSelectedFrom: sourceList to: targetList ] { #category : 'accessing' } @@ -122,8 +119,7 @@ SpChooserPresenter >> chosenItems [ SpChooserPresenter >> defaultChosenItems: aCollection [ targetList items: aCollection. - sourceList items: sourceList unfilteredItems \ aCollection. - self sortLists + sourceList items: sourceList unfilteredItems \ aCollection ] { #category : 'layout' } @@ -148,9 +144,9 @@ SpChooserPresenter >> defaultLayout [ { #category : 'accessing' } SpChooserPresenter >> displayBlock: aBlock [ - displayBlock := aBlock. sourceList display: aBlock. - targetList display: aBlock + targetList display: aBlock. + self initializeSortingBlocks ] { #category : 'initialization' } @@ -199,7 +195,7 @@ SpChooserPresenter >> initializeLists [ sourceList := self instantiate: SpFilteringSelectableListPresenter. targetList := self instantiate: SpFilteringSelectableListPresenter. - displayBlock := sourceList display + self initializeSortingBlocks ] { #category : 'initialization' } @@ -211,6 +207,15 @@ SpChooserPresenter >> initializePresenters [ self initializeButtonBarLayout ] +{ #category : 'initialization' } +SpChooserPresenter >> initializeSortingBlocks [ + + | sortingBlock | + sortingBlock := sourceList display ascending. + sourceList sortingBlock: sortingBlock. + targetList sortingBlock: sortingBlock +] + { #category : 'private' } SpChooserPresenter >> moveAllFrom: fromList to: toList [ @@ -219,8 +224,7 @@ SpChooserPresenter >> moveAllFrom: fromList to: toList [ newFromListItems := OrderedCollection withAll: fromList unfilteredItems. newFromListItems removeAllFoundIn: fromList items. - fromList items: newFromListItems. - self sortLists + fromList items: newFromListItems ] { #category : 'private' } @@ -231,22 +235,19 @@ SpChooserPresenter >> moveSelectedFrom: fromList to: toList [ newFromListItems := OrderedCollection withAll: fromList unfilteredItems. newFromListItems removeAllFoundIn: fromList selectedItems. - fromList items: newFromListItems. - self sortLists + fromList items: newFromListItems ] { #category : 'actions' } SpChooserPresenter >> removeAll [ - self moveAllFrom: targetList to: sourceList. - self sortLists + self moveAllFrom: targetList to: sourceList ] { #category : 'actions' } SpChooserPresenter >> removeSelected [ - self moveSelectedFrom: targetList to: sourceList. - self sortLists + self moveSelectedFrom: targetList to: sourceList ] { #category : 'actions' } @@ -256,30 +257,10 @@ SpChooserPresenter >> resetSelectedItems [ targetList selectItems: #(). ] -{ #category : 'actions' } -SpChooserPresenter >> sortLists [ - - self sortSourceList. - self sortTargetList -] - -{ #category : 'actions' } -SpChooserPresenter >> sortSourceList [ - - sourceList items: (sourceList items sorted: displayBlock ascending) -] - -{ #category : 'actions' } -SpChooserPresenter >> sortTargetList [ - - targetList items: (targetList items sorted: displayBlock ascending) -] - { #category : 'accessing' } SpChooserPresenter >> sourceItems: aCollection [ - sourceList items: aCollection. - self sortLists + sourceList items: aCollection ] { #category : 'accessing' } diff --git a/src/Spec2-CommonWidgets/SpFilteringListPresenter.class.st b/src/Spec2-CommonWidgets/SpFilteringListPresenter.class.st index 2e93a489..d145c528 100644 --- a/src/Spec2-CommonWidgets/SpFilteringListPresenter.class.st +++ b/src/Spec2-CommonWidgets/SpFilteringListPresenter.class.st @@ -127,9 +127,10 @@ SpFilteringListPresenter >> filterText [ SpFilteringListPresenter >> initializePresenters [ filterInputPresenter := self newTextInput - placeholder: 'Filter...'; - yourself. + placeholder: 'Filter...'; + yourself. listPresenter := self newListToFilter. + unfilteredItems := #( ). self matchSubstring ] @@ -162,7 +163,7 @@ SpFilteringListPresenter >> items: aCollection [ listPresenter items: aCollection. unfilteredItems := aCollection. - self resetFilter + self reapplyOrResetFilter ] { #category : 'accessing' } @@ -202,6 +203,13 @@ SpFilteringListPresenter >> outputSelectionPort [ ^ listPresenter outputSelectionPort ] +{ #category : 'api' } +SpFilteringListPresenter >> reapplyOrResetFilter [ + + self filterListItems: self filterText. + self items ifEmpty: [ self resetFilter ] +] + { #category : 'api' } SpFilteringListPresenter >> resetFilter [ @@ -220,6 +228,18 @@ SpFilteringListPresenter >> selectedItem [ ^ listPresenter selectedItem ] +{ #category : 'sorting' } +SpFilteringListPresenter >> sorted: aSortBlock [ + + listPresenter items: (listPresenter items sorted: aSortBlock) +] + +{ #category : 'accessing' } +SpFilteringListPresenter >> sortingBlock: aBlockOrNil [ + + listPresenter sortingBlock: aBlockOrNil +] + { #category : 'accessing' } SpFilteringListPresenter >> unfilteredItems [