diff --git a/src/Spec2-Core/SpApplication.class.st b/src/Spec2-Core/SpApplication.class.st index 892b5502..6c847e66 100644 --- a/src/Spec2-Core/SpApplication.class.st +++ b/src/Spec2-Core/SpApplication.class.st @@ -50,7 +50,8 @@ Class { 'properties', 'configuration', 'iconManager', - 'iconProvider' + 'iconProvider', + 'notificationCenter' ], #classVars : [ 'DefaultApplication' @@ -285,11 +286,22 @@ SpApplication >> newPresenter: aPresenterClass [ ^ aPresenterClass newApplication: self ] -{ #category : 'ui - notifying' } -SpApplication >> notify: aSpecNotification [ - "how notifications are handled depends on the backend" +{ #category : 'accessing' } +SpApplication >> notificationCenter [ + "should be placed in initialize." + ^ notificationCenter ifNil: [ notificationCenter := SpNotificationCenter new forApplication: self; yourself ] +] + +{ #category : 'ui - dialogs' } +SpApplication >> notificationClass [ + + ^ SpNotificationItem +] + +{ #category : 'ui - dialogs' } +SpApplication >> notify: aString [ - aSpecNotification dispatchTo: self backend + self notificationCenter add: (self notificationClass with: aString) ] { #category : 'accessing - properties' } diff --git a/src/Spec2-Core/SpNotificationCenter.class.st b/src/Spec2-Core/SpNotificationCenter.class.st new file mode 100644 index 00000000..666432b3 --- /dev/null +++ b/src/Spec2-Core/SpNotificationCenter.class.st @@ -0,0 +1,68 @@ +" +I'm a simple object holding a limited list of notification items. +" +Class { + #name : #SpNotificationCenter, + #superclass : #Object, + #instVars : [ + 'items', + 'limit', + 'application' + ], + #category : #'Spec2-Core-Notification' +} + +{ #category : #adding } +SpNotificationCenter >> add: aSpNotificationItem [ + items size > limit + ifTrue: [ items removeLast: self bulkSize ]. + items addFirst: aSpNotificationItem. + self updateIfNecessary. +] + +{ #category : #accessing } +SpNotificationCenter >> application [ + ^ application +] + +{ #category : #adding } +SpNotificationCenter >> bulkSize [ + "Returns the number of itesm that should be removed when the limit is reached. + Pay attention that the limit MUST always be larger than bulkSize" + + ^ 5 +] + +{ #category : #adding } +SpNotificationCenter >> forApplication: app [ + + application := app +] + +{ #category : #initialization } +SpNotificationCenter >> initialize [ + + super initialize. + "Pay attention limit must not smaller than bulkSize because else + we will try to remove more elements than the number we have." + limit := 30. + items := OrderedCollection new. +] + +{ #category : #accessing } +SpNotificationCenter >> items [ + ^ items +] + +{ #category : #accessing } +SpNotificationCenter >> limit [ + ^ limit +] + +{ #category : #adding } +SpNotificationCenter >> updateIfNecessary [ + + | notifs | + notifs := self application windows select: [ :each | each presenter class = SpNotificationCenterPresenter ]. + notifs do: [ :each | each presenter updatePresenter ] +] diff --git a/src/Spec2-Core/SpNotificationItem.class.st b/src/Spec2-Core/SpNotificationItem.class.st new file mode 100644 index 00000000..3c369893 --- /dev/null +++ b/src/Spec2-Core/SpNotificationItem.class.st @@ -0,0 +1,27 @@ +" +I'm a simple object representing a notification. +" +Class { + #name : #SpNotificationItem, + #superclass : #Object, + #instVars : [ + 'text' + ], + #category : #'Spec2-Core-Notification' +} + +{ #category : #'instance creation' } +SpNotificationItem class >> with: aString [ + + ^ self new text: aString ; yourself +] + +{ #category : #accessing } +SpNotificationItem >> text [ + ^ text +] + +{ #category : #accessing } +SpNotificationItem >> text: aString [ + text := aString +] diff --git a/src/Spec2-Core/SpPresenter.class.st b/src/Spec2-Core/SpPresenter.class.st index de236dac..60312d74 100644 --- a/src/Spec2-Core/SpPresenter.class.st +++ b/src/Spec2-Core/SpPresenter.class.st @@ -738,6 +738,11 @@ SpPresenter >> localeChanged [ ] +{ #category : 'simple dialog helpers' } +SpPresenter >> notify: aString [ + self application notify: aString +] + { #category : 'private' } SpPresenter >> okToChange [ diff --git a/src/Spec2-Dialogs/SpNotificationCenterPresenter.class.st b/src/Spec2-Dialogs/SpNotificationCenterPresenter.class.st new file mode 100644 index 00000000..b0b9d5f5 --- /dev/null +++ b/src/Spec2-Dialogs/SpNotificationCenterPresenter.class.st @@ -0,0 +1,90 @@ +Class { + #name : #SpNotificationCenterPresenter, + #superclass : #SpPresenterWithModel, + #instVars : [ + 'itemList', + 'descriptionText', + 'clearButton' + ], + #category : #'Spec2-Dialogs' +} + +{ #category : #examples } +SpNotificationCenterPresenter class >> example2 [ + + + | app notificationPresenter | + app := SpApplication new. + notificationPresenter := self newApplication: app model: app notificationCenter. + notificationPresenter open. + ^ app inspect + "1 to: 10 do: [ :each | app notify: each printString ]" +] + +{ #category : #initialization } +SpNotificationCenterPresenter >> clearNotificationsAction [ + + itemList items: OrderedCollection new. + descriptionText text: ' No notification ' +] + +{ #category : #initialization } +SpNotificationCenterPresenter >> connectPresenters [ + + "Why this is not working + itemList whenSelectedItemChangedDo: [ :each | descriptionText text: each text]." + + itemList whenSelectedDo: [ :each | each ifNotNil: [descriptionText text: each text]] + +] + +{ #category : #layout } +SpNotificationCenterPresenter >> defaultLayout [ + + | upperLayout lowerLayout | + upperLayout := SpBoxLayout newLeftToRight + addLast: clearButton; + yourself. + lowerLayout := SpPanedLayout newTopToBottom + positionOfSlider: 0.8; + add: itemList; + add: descriptionText; + yourself. + ^ SpBoxLayout newTopToBottom + add: upperLayout expand: false; + add: lowerLayout; + yourself +] + +{ #category : #initialization } +SpNotificationCenterPresenter >> initializePresenters [ + + itemList := self newList + display: [ :each | ' ' , each text contractTo: 20 ]; + yourself. + descriptionText := self newText. + clearButton := self newButton + icon: (self iconNamed: #smallUpdate); + label: 'Clear notifications'; + action: [ self clearNotificationsAction ]; + yourself +] + +{ #category : #initialization } +SpNotificationCenterPresenter >> initializeWindow: aWindowPresenter [ + + aWindowPresenter title: 'Notifications' +] + +{ #category : #initialization } +SpNotificationCenterPresenter >> modelChanged [ + + itemList items: announcingObject value items. + itemList selectFirst +] + +{ #category : #updating } +SpNotificationCenterPresenter >> updatePresenter [ + + self modelChanged +] diff --git a/src/Spec2-Tests/SpNotificationCenterTest.class.st b/src/Spec2-Tests/SpNotificationCenterTest.class.st new file mode 100644 index 00000000..a9e75f5b --- /dev/null +++ b/src/Spec2-Tests/SpNotificationCenterTest.class.st @@ -0,0 +1,54 @@ +Class { + #name : 'SpNotificationCenterTest', + #superclass : 'TestCase', + #category : 'Spec2-Tests-Notifications', + #package : 'Spec2-Tests', + #tag : 'Notifications' +} + +{ #category : 'tests' } +SpNotificationCenterTest >> testAddAnItemAddsIt [ + + | f center | + f := SpNotificationItem with: 'first'. + center := SpApplication new notificationCenter. + center add: f. + self assert: center items first text equals: 'first' +] + +{ #category : 'tests' } +SpNotificationCenterTest >> testAddingOverTheLimitCutFirst [ + + | f center | + center := SpApplication new notificationCenter. + 1 to: 35 do: [ :each | + f := SpNotificationItem with: each printString. + center add: f ] . + + self assert: center items size equals: center limit +] + +{ #category : 'tests' } +SpNotificationCenterTest >> testAddingOverTheLimitRemoveBuldElements [ + + | f center | + center := SpApplication new notificationCenter. + 1 to: 32 do: [ :each | + f := SpNotificationItem with: each printString. + center add: f ] . + + "when we added 31 we removed buld elements (5) and added 31 and 32 so we have 27 elements" + self assert: center items size equals: center limit - center bulkSize + (32 - center limit) +] + +{ #category : 'tests' } +SpNotificationCenterTest >> testItemsAreOrderedLIFO [ + + | f center f2 | + f := SpNotificationItem with: 'first'. + center := SpApplication new notificationCenter. + center add: f. + f2 := SpNotificationItem with: 'second'. + center add: f2. + self assert: center items first text equals: 'second' +] diff --git a/src/Spec2-Tests/SpNotificationTest.class.st b/src/Spec2-Tests/SpNotificationTest.class.st new file mode 100644 index 00000000..a81e4696 --- /dev/null +++ b/src/Spec2-Tests/SpNotificationTest.class.st @@ -0,0 +1,19 @@ +Class { + #name : 'SpNotificationTest', + #superclass : 'TestCase', + #category : 'Spec2-Tests-Notifications', + #package : 'Spec2-Tests', + #tag : 'Notifications' +} + +{ #category : 'tests' } +SpNotificationTest >> testNotificationIsKeptAround [ + + | pres app | + app := SpApplication new. + pres := SpPresenter newApplication: app. + pres notify: 'You should see this notification'. + self + assert: app notificationCenter items first text + equals: 'You should see this notification' +]