├── .github ├── stale.yml └── workflows │ └── runTests.yaml ├── .project ├── .smalltalk.ston ├── FEATURES.md ├── README.md ├── lepiter ├── 3pc995dl252amolepioa9xo7v.lepiter ├── cuv8keto50y1q22h33ya2exm1.lepiter ├── cuv8ketsk2asgtq1na38o7hze.lepiter ├── cuv8keu0rcw67mhkv4juu0kjs.lepiter ├── cuv8kex3dqlfsb604nb7ytijp.bak ├── cuv8kex3dqlfsb604nb7ytijp.lepiter ├── cuv8kexr155gznlyjl1dzd4bf.lepiter ├── cuv8keyv2dlho053qbfe8vs1a.lepiter ├── cuv8kez6xiqmrhfp8hasvn9ki.lepiter ├── cuv8kf0cw6aoxog2xhaap0sf0.lepiter ├── d7hyk2iipxwmivsgijclbq2y0.bak ├── d7hyk2iipxwmivsgijclbq2y0.lepiter └── lepiter.properties └── source ├── .properties ├── BaselineOfMagritte ├── BaselineOfMagritte.class.st └── package.st ├── BaselineOfMagritteForGToolkit ├── BaselineOfMagritteForGToolkit.class.st └── package.st ├── ConfigurationOfMagritte3 ├── ConfigurationOfMagritte3.class.st └── package.st ├── ConfigurationOfMagritteContactManager ├── ConfigurationOfMagritteContactManager.class.st └── package.st ├── ConfigurationOfMagritteContactManagerTutorial ├── ConfigurationOfMagritteContactManager.class.st └── package.st ├── ConfigurationOfMagritteSeaside ├── ConfigurationOfMagritteSeaside.class.st └── package.st ├── Magritte-Bootstrap ├── MAAccessor.extension.st ├── TMagritteBootstrap.trait.st └── package.st ├── Magritte-ContactManager ├── CMAddress.class.st ├── CMPerson.class.st ├── CMPhone.class.st └── package.st ├── Magritte-Deprecated ├── BlockClosure.extension.st ├── GRPharoPlatform.extension.st ├── GRPlatform.extension.st ├── MADynamicObject.class.st ├── MADynamicObjectTest.class.st ├── MANamedBuilder.class.st ├── MAProxyObject.class.st ├── Object.extension.st ├── Symbol.extension.st └── package.st ├── Magritte-Deprecated3dot7 ├── MACheckboxMorph.class.st ├── MAContainerMorph.class.st ├── MADateMorph.class.st ├── MADescription.extension.st ├── MADirectoryMorph.class.st ├── MADropListMorph.class.st ├── MAExternalEditorMorph.class.st ├── MAFileMorph.class.st ├── MAInternalEditorMorph.class.st ├── MAListMorph.class.st ├── MAMemoMorph.class.st ├── MAMultiSelectListMorph.class.st ├── MAOneToManyMorph.class.st ├── MAOneToOneMorph.class.st ├── MAPasswordMorph.class.st ├── MARelationMorph.class.st ├── MASilentContainerMorph.class.st ├── MASingleSelectListMorph.class.st ├── MATextMorph.class.st ├── MATokenCompletionMorph.class.st ├── ManifestMagritteDeprecateddot.class.st ├── Object.extension.st └── package.st ├── Magritte-Developer ├── Class.extension.st ├── MAClyAddFieldCommand.class.st ├── MADeveloperMenus.class.st ├── MADeveloperTests.class.st ├── MAElementDescription.extension.st ├── MASelectorAccessor.extension.st ├── Object.extension.st └── package.st ├── Magritte-FileDirectory ├── GRPackage.extension.st ├── MAExternalFileModel.class.st └── package.st ├── Magritte-FileSystem ├── GRPackage.extension.st ├── MAExternalFileModel.class.st ├── MAFileDatabase.class.st ├── MAFileDescription.extension.st ├── MAFileSystem.class.st └── package.st ├── Magritte-Files-Model ├── GRPackage.extension.st └── package.st ├── Magritte-GT ├── ClyTagInspectorExtensionCommand.class.st ├── CompiledMethod.extension.st ├── Object.extension.st └── package.st ├── Magritte-GToolkit ├── GtPhlowProtoView.extension.st ├── GtPhlowView.extension.st ├── MAActionDescription.extension.st ├── MABrTextEditor.class.st ├── MACompositeAccessor.extension.st ├── MACompositeElementBuilder.class.st ├── MADescription.extension.st ├── MADropdownElement.class.st ├── MADropdownWish.class.st ├── MAElementBuilder.class.st ├── MAElementDescription.extension.st ├── MAFieldElement.class.st ├── MAGtInputFieldAptitude.class.st ├── MAIconDescription.extension.st ├── MATokenCollectorElement.class.st ├── MATokenElement.class.st ├── MATokenRequest.class.st ├── MATokenSelectorElement.class.st ├── MaGtPhlowViewsCollector.class.st ├── Object.extension.st └── package.st ├── Magritte-GemStone-Model ├── AbstractDictionary.extension.st ├── GRGemStonePlatform.extension.st ├── MAError.extension.st └── package.st ├── Magritte-GemStone-Seaside ├── ExecutableBlock.extension.st ├── MAExternalFileModel.extension.st └── package.st ├── Magritte-Glamour ├── GLMCompositePresentation.extension.st ├── GLMListingPresentation.extension.st ├── GLMMagrittePresentation.class.st ├── GLMMorphicMagritteRenderer.class.st ├── GLMMorphicRenderer.extension.st ├── GLMPresentation.extension.st ├── MAElementDescription.extension.st ├── MAStringDescription.extension.st └── package.st ├── Magritte-Merging-Bloc ├── MAPatchMacro.extension.st ├── MAPatchMacroElement.class.st ├── MAPatchOperation.extension.st └── package.st ├── Magritte-Merging ├── MAElementDescription.extension.st ├── MAPatchMacro.class.st ├── MAPatchOperation.class.st ├── Object.extension.st └── package.st ├── Magritte-Model ├── ArrayedCollection.extension.st ├── BlockClosure.extension.st ├── Class.extension.st ├── Collection.extension.st ├── Dictionary.extension.st ├── GRPackage.extension.st ├── GRPlatform.extension.st ├── Integer.extension.st ├── MAAccessor.class.st ├── MAActionDescription.class.st ├── MAActionPragmaBuilder.class.st ├── MAAdaptiveModel.class.st ├── MABasicObject.class.st ├── MABlockDescription.class.st ├── MABooleanDescription.class.st ├── MACachedMemento.class.st ├── MAChainAccessor.class.st ├── MACheckedMemento.class.st ├── MAClassDescription.class.st ├── MAColorDescription.class.st ├── MAComposedDescriptionBuilder.class.st ├── MACompositeAccessor.class.st ├── MACompositeConflict.class.st ├── MACondition.class.st ├── MAConditionError.class.st ├── MAConflictError.class.st ├── MAConjunctiveCondition.class.st ├── MAContainer.class.st ├── MADateAndTimeDescription.class.st ├── MADateDescription.class.st ├── MADelegatorAccessor.class.st ├── MADescription.class.st ├── MADescriptionBuilder.class.st ├── MADescriptionContext.class.st ├── MADescriptionFlattener.class.st ├── MADescriptionHolder.class.st ├── MADictionaryAccessor.class.st ├── MADirectoryDescription.class.st ├── MADurationDescription.class.st ├── MADynamicDescribedObject.class.st ├── MADynamicDescriptionCache.class.st ├── MADynamicOptions.class.st ├── MADynamicVariable.class.st ├── MAElementDescription.class.st ├── MAElementDescription.extension.st ├── MAError.class.st ├── MAFileDescription.class.st ├── MAFileModel.class.st ├── MAIconDescription.class.st ├── MAIdentityAccessor.class.st ├── MAKindError.class.st ├── MAMagnitudeDescription.class.st ├── MAMemento.class.st ├── MAMemoDescription.class.st ├── MAMemoryFileModel.class.st ├── MAMessagingStringWriter.class.st ├── MAMultipleErrors.class.st ├── MAMultipleOptionDescription.class.st ├── MANegationCondition.class.st ├── MANullAccessor.class.st ├── MANumberDescription.class.st ├── MAObject.class.st ├── MAOptionDescription.class.st ├── MAPasswordDescription.class.st ├── MAPluggableAccessor.class.st ├── MAPluggableCondition.class.st ├── MAPragmaBuilder.class.st ├── MAPriorityContainer.class.st ├── MAPropertyAccessor.class.st ├── MAPropertyChangedAnnouncement.class.st ├── MAPropertyError.class.st ├── MARangeError.class.st ├── MAReadError.class.st ├── MAReader.class.st ├── MAReferenceDescription.class.st ├── MARelationDescription.class.st ├── MARequiredError.class.st ├── MASelectorAccessor.class.st ├── MASingleOptionDescription.class.st ├── MASortBlock.class.st ├── MAStraightMemento.class.st ├── MAStreamingVisitor.class.st ├── MAStringDescription.class.st ├── MAStringReader.class.st ├── MAStringWriter.class.st ├── MASymbolDescription.class.st ├── MATPropertyOwner.extension.st ├── MATPropertyOwner.trait.st ├── MATableDescription.class.st ├── MATableModel.class.st ├── MATimeDescription.class.st ├── MAToManyRelationDescription.class.st ├── MAToManyScalarRelationDescription.class.st ├── MAToOneRelationDescription.class.st ├── MATokenDescription.class.st ├── MAUrlDescription.class.st ├── MAValidationError.class.st ├── MAValidatorVisitor.class.st ├── MAValueHolder.class.st ├── MAVariableAccessor.class.st ├── MAVisitor.class.st ├── MAWriteError.class.st ├── MAWriter.class.st ├── ManifestMagritteModel.class.st ├── NumberParser.extension.st ├── Object.extension.st ├── SequenceableCollection.extension.st ├── String.extension.st ├── Symbol.extension.st ├── UndefinedObject.extension.st ├── WriteStream.extension.st └── package.st ├── Magritte-Money ├── MAMoneyDescription.class.st ├── MAVisitor.extension.st └── package.st ├── Magritte-Morph ├── GRPackage.extension.st ├── MAActionDescription.extension.st ├── MABlockDescription.extension.st ├── MABooleanDescription.extension.st ├── MAContainer.extension.st ├── MADateDescription.extension.st ├── MADescription.extension.st ├── MADirectoryDescription.extension.st ├── MAElementDescription.extension.st ├── MAElementRow.class.st ├── MAFileDescription.extension.st ├── MAMemoDescription.extension.st ├── MAMorphicCheckbox.class.st ├── MAMorphicContainer.class.st ├── MAMorphicDate.class.st ├── MAMorphicDescription.class.st ├── MAMorphicDirectory.class.st ├── MAMorphicDropList.class.st ├── MAMorphicElement.class.st ├── MAMorphicExternalEditor.class.st ├── MAMorphicFile.class.st ├── MAMorphicInternalEditor.class.st ├── MAMorphicList.class.st ├── MAMorphicMemo.class.st ├── MAMorphicMultiSelectList.class.st ├── MAMorphicOneToMany.class.st ├── MAMorphicOneToOne.class.st ├── MAMorphicPassword.class.st ├── MAMorphicRelation.class.st ├── MAMorphicSilentContainer.class.st ├── MAMorphicSingleSelectList.class.st ├── MAMorphicText.class.st ├── MAMorphicTokenCompletion.class.st ├── MAMultipleOptionDescription.extension.st ├── MAPasswordDescription.extension.st ├── MARelationDescription.extension.st ├── MASingleOptionDescription.extension.st ├── MAToManyRelationDescription.extension.st ├── MAToOneRelationDescription.extension.st ├── MorphicUIManager.extension.st ├── Object.extension.st ├── SpDatePresenter.extension.st ├── TokenCollectorMorph.class.st ├── TokenMorph.class.st └── package.st ├── Magritte-NotGToolkit ├── Symbol.extension.st └── package.st ├── Magritte-Pharo-Model ├── GRPackage.extension.st ├── GRPharoPlatform.extension.st ├── MorphicUIManager.extension.st └── package.st ├── Magritte-Pharo-Seaside ├── GRPackage.extension.st ├── MAExternalFileModel.extension.st └── package.st ├── Magritte-Pharo-Tools ├── MAClassRefactoring.class.st ├── MADescriptionRenameRefactoring.class.st ├── MAMethodRefactoring.class.st ├── MAPackageRefactoring.class.st ├── ORCmdMagritteDescriptionUpdate.class.st ├── ORCmdMagritteDescriptionsClassUpdate.class.st ├── ORCmdMagritteDescriptionsPackageUpdate.class.st ├── ORCmdMagritteDescriptionsPackageUpdateWrapper.class.st └── package.st ├── Magritte-Pharo3-Model ├── GRPackage.extension.st ├── GRPharoPlatform.extension.st ├── MAExternalFileModel.class.st ├── MAFileDatabase.class.st ├── MAFileSystem.class.st ├── MorphicUIManager.extension.st └── package.st ├── Magritte-Pharo7-Model ├── GRPackage.extension.st ├── GRPharoPlatform.extension.st └── package.st ├── Magritte-Pillar ├── Collection.extension.st ├── MAElementDescription.extension.st ├── MAPillarRenderer.class.st ├── MAToManyRelationDescription.extension.st ├── MAToOneRelationDescription.extension.st ├── MAUrlDescription.extension.st ├── Object.extension.st ├── PRDocumentItem.extension.st └── package.st ├── Magritte-Seaside ├── GRPackage.extension.st ├── MAActionColumn.class.st ├── MABooleanDescription.extension.st ├── MACheckboxColumn.class.st ├── MACheckboxComponent.class.st ├── MACheckboxGroupComponent.class.st ├── MAClassDescription.extension.st ├── MAColumn.class.st ├── MACommandColumn.class.st ├── MAComponent.class.st ├── MAComponentDecoration.class.st ├── MAComponentRenderer.class.st ├── MAContainer.extension.st ├── MAContainerComponent.class.st ├── MAContainerDecoration.class.st ├── MACssRenderer.class.st ├── MADateAndTimeDescription.extension.st ├── MADateDescription.extension.st ├── MADateInputComponent.class.st ├── MADateSelectorComponent.class.st ├── MADescribedColumn.class.st ├── MADescribedComponentColumn.class.st ├── MADescribedScalarColumn.class.st ├── MADescription.extension.st ├── MADescriptionComponent.class.st ├── MADescriptionEditor.class.st ├── MADurationDescription.extension.st ├── MAElementComponent.class.st ├── MAElementDescription.extension.st ├── MAExampleEditor.class.st ├── MAExternalEditorComponent.class.st ├── MAFileDescription.extension.st ├── MAFileModel.extension.st ├── MAFileModelHandler.class.st ├── MAFileUploadComponent.class.st ├── MAFormDecoration.class.st ├── MAIndexedCommandColumn.class.st ├── MAInternalEditorComponent.class.st ├── MAListCompositionComponent.class.st ├── MAMemoDescription.extension.st ├── MAMultipleErrors.extension.st ├── MAMultipleOptionDescription.extension.st ├── MAMultipleSelectionComponent.class.st ├── MAMultiselectListComponent.class.st ├── MANumberDescription.extension.st ├── MAOneToManyComponent.class.st ├── MAOneToManyScalarComponent.class.st ├── MAOneToOneComponent.class.st ├── MAOptionComponent.class.st ├── MAOptionboxColumn.class.st ├── MAPasswordDescription.extension.st ├── MARadioGroupComponent.class.st ├── MARangeComponent.class.st ├── MARelationComponent.class.st ├── MAReport.class.st ├── MASelectListComponent.class.st ├── MASelectListRowsComponent.class.st ├── MASelectionColumn.class.st ├── MASingleOptionDescription.extension.st ├── MASingleSelectionComponent.class.st ├── MAStringDescription.extension.st ├── MASwitchDecoration.class.st ├── MATableComponent.class.st ├── MATableDescription.extension.st ├── MATableRenderer.class.st ├── MATextAreaComponent.class.st ├── MATextInputComponent.class.st ├── MATextPasswordComponent.class.st ├── MATimeDescription.extension.st ├── MATimeInputComponent.class.st ├── MATimeSelectorComponent.class.st ├── MATimeStampInputComponent.class.st ├── MAToManyRelationDescription.extension.st ├── MAToManyScalarRelationDescription.extension.st ├── MAToOneRelationDescription.extension.st ├── MAToggleColumn.class.st ├── MATokenDescription.extension.st ├── MAUndefinedComponent.class.st ├── MAValidationDecoration.class.st ├── MAVerifiedPasswordComponent.class.st ├── Object.extension.st ├── Symbol.extension.st ├── WAComponent.extension.st ├── WAPresenter.extension.st └── package.st ├── Magritte-Tests-Files-Model ├── GRPackage.extension.st ├── MAExternalFileModelTest.class.st └── package.st ├── Magritte-Tests-GemStone-Model ├── MAExternalFileModelTest.class.st └── package.st ├── Magritte-Tests-Model ├── GRPackage.extension.st ├── MAAccessorMock.class.st ├── MAAccessorTest.class.st ├── MAAdaptiveModelTest.class.st ├── MABooleanDescriptionTest.class.st ├── MACachedMementoTest.class.st ├── MAChainAccessorTest.class.st ├── MACheckedMementoTest.class.st ├── MAClassDescriptionTest.class.st ├── MAColorDescriptionTest.class.st ├── MAConditionTest.class.st ├── MAContainerTest.class.st ├── MADateAndTimeDescriptionTest.class.st ├── MADateDescriptionTest.class.st ├── MADelegatorAccessorTest.class.st ├── MADerivedDescriptions.class.st ├── MADescriptionBuilderTest.class.st ├── MADescriptionTest.class.st ├── MADictionaryAccessorTest.class.st ├── MADurationDescriptionTest.class.st ├── MAElementDescriptionTest.class.st ├── MAExtensionsTest.class.st ├── MAFileDescriptionTest.class.st ├── MAFileModelStub.class.st ├── MAFileModelTest.class.st ├── MAIdentityAccessorTest.class.st ├── MAMagnitudeDescriptionTest.class.st ├── MAMementoTest.class.st ├── MAMemoDescriptionTest.class.st ├── MAMemoryFileModelTest.class.st ├── MAMockAddress.class.st ├── MAMockAddress2.class.st ├── MAMultipleOptionDescriptionTest.class.st ├── MANullAccessorTest.class.st ├── MANumberDescriptionTest.class.st ├── MAObjectTest.class.st ├── MAOptionDescriptionTest.class.st ├── MAPasswordDescriptionTest.class.st ├── MAPluggableAccessorTest.class.st ├── MAPriorityContainerTest.class.st ├── MAReferenceDescriptionTest.class.st ├── MARelationDescriptionTest.class.st ├── MASelectorAccessorTest.class.st ├── MASingleOptionDescriptionTest.class.st ├── MAStraightMementoTest.class.st ├── MAStringDescriptionTest.class.st ├── MASymbolDescriptionTest.class.st ├── MATableDescriptionTest.class.st ├── MATableModelTest.class.st ├── MATimeDescriptionTest.class.st ├── MAToManyRelationDescriptionTest.class.st ├── MAToManyScalarRelationDescriptionTest.class.st ├── MAToOneRelationDescriptionTest.class.st ├── MATokenDescriptionTest.class.st ├── MAValidatorVisitorTest.class.st ├── MAVariableAccessorTest.class.st └── package.st ├── Magritte-Traits-Model ├── GRPackage.extension.st ├── Trait.extension.st └── package.st ├── Magritte-UI ├── MABlocContainerPresenter.class.st ├── MAContainerPresenter.class.st ├── MADescriptionPresenter.class.st ├── MAPatchBrowser.class.st ├── MATContainerPresenter.trait.st ├── MATDescriptionPresenter.trait.st └── package.st └── Spec-Widgets ├── AbstractBasicWidget.class.st ├── ButtonModel.class.st ├── CheckBoxModel.class.st ├── DateModel.class.st ├── DialogWindowModel.class.st ├── DropListModel.class.st ├── IconListModel.class.st ├── LabelModel.class.st ├── ListComposableModel.class.st ├── MethodToolbar.class.st ├── MorphWrapper.class.st ├── MultiColumnListModel.class.st ├── OkCancelToolbar.class.st ├── OkToolbar.class.st ├── PanelMorphWithSplitters.class.st ├── PickListModel.class.st ├── RadioButtonGroup.class.st ├── RadioButtonModel.class.st ├── SearchableList.class.st ├── SliderModel.class.st ├── TextInputFieldModel.class.st ├── TextModel.class.st ├── TreeModel.class.st ├── WindowModel.class.st └── package.st /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: stale 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | To limit bug bankruptcy (see https://www.joelonsoftware.com/2012/07/09/software-inventory/) this issue has been automatically marked as stale because it has not had any activity in 6 months. If no further activity occurs, it might be closed. If this issue remains important to you, please comment to reactivate the issue. Thank you for your contributions. 14 | # Comment to post when closing a stale issue. Set to `false` to disable 15 | closeComment: false 16 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | { 2 | 'srcDirectory' : 'source' 3 | } -------------------------------------------------------------------------------- /.smalltalk.ston: -------------------------------------------------------------------------------- 1 | SmalltalkCISpec { 2 | #loading : [ 3 | SCIMetacelloLoadSpec { 4 | #baseline : 'Magritte', 5 | #load : [ 'Tests' ], 6 | #directory : 'source', 7 | #platforms : [ #pharo ] 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /FEATURES.md: -------------------------------------------------------------------------------- 1 | # Merging 2 | 3 | ## Installation 4 | Load `Margitte-Merging` on top of Magritte default 5 | 6 | ## Usage 7 | 8 | ### Automatic Merging 9 | To describe scenarios when a field should be merged automatically, set the `#shouldAutoMergeBlock` property to a condition block. For example, let's say you have a `Name` class with a `#firstName` field, and you want to merge whenever you're changing from an initial to a full first name starting with that letter: 10 | ```smalltalk 11 | Name>>#descriptionFirstName 12 | 13 | ^ MAStringDescription new 14 | accessor: #firstName; 15 | propertyAt: #shouldAutoMergeBlock put: [ :old :new | 16 | | oldNoPeriod | 17 | oldNoPeriod := old trimRight: [ :e | e = $. ]. 18 | oldNoPeriod size = 1 and: [ new beginsWith: oldNoPeriod ] ]; 19 | yourself 20 | ``` 21 | -------------------------------------------------------------------------------- /lepiter/lepiter.properties: -------------------------------------------------------------------------------- 1 | { 2 | "databaseName" : "Magritte", 3 | "uuid" : "11a6ef55-8084-0d00-b98d-5e6e0f742dd9", 4 | "schema" : "4.1" 5 | } 6 | -------------------------------------------------------------------------------- /source/.properties: -------------------------------------------------------------------------------- 1 | { 2 | #format : #tonel 3 | } -------------------------------------------------------------------------------- /source/BaselineOfMagritte/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #BaselineOfMagritte } 2 | -------------------------------------------------------------------------------- /source/BaselineOfMagritteForGToolkit/BaselineOfMagritteForGToolkit.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #BaselineOfMagritteForGToolkit, 3 | #superclass : #BaselineOf, 4 | #category : #BaselineOfMagritteForGToolkit 5 | } 6 | 7 | { #category : #baselines } 8 | BaselineOfMagritteForGToolkit >> baseline: spec [ 9 | 10 | 11 | spec for: #common do: [ 12 | spec 13 | baseline: 'GreaseForGToolkit' 14 | with: [ 15 | spec repository: 'github://feenkcom/Grease:feenk/repository' ]. 16 | 17 | spec 18 | package: 'Magritte-Model' 19 | with: [ spec requires: #( 'GreaseForGToolkit' ) ] ] 20 | ] 21 | -------------------------------------------------------------------------------- /source/BaselineOfMagritteForGToolkit/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #BaselineOfMagritteForGToolkit } 2 | -------------------------------------------------------------------------------- /source/ConfigurationOfMagritte3/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #ConfigurationOfMagritte3 } 2 | -------------------------------------------------------------------------------- /source/ConfigurationOfMagritteContactManager/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #ConfigurationOfMagritteContactManager } 2 | -------------------------------------------------------------------------------- /source/ConfigurationOfMagritteContactManagerTutorial/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #ConfigurationOfMagritteContactManagerTutorial } 2 | -------------------------------------------------------------------------------- /source/ConfigurationOfMagritteSeaside/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #ConfigurationOfMagritteSeaside } 2 | -------------------------------------------------------------------------------- /source/Magritte-Bootstrap/MAAccessor.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAAccessor } 2 | 3 | { #category : #'*Magritte-Bootstrap' } 4 | MAAccessor >> handleMessage: aMessage for: anObject [ 5 | ^ aMessage hasArguments 6 | ifTrue: [ self write: aMessage arguments first to: anObject ] 7 | ifFalse: [ self read: anObject ] 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-Bootstrap/TMagritteBootstrap.trait.st: -------------------------------------------------------------------------------- 1 | Trait { 2 | #name : #TMagritteBootstrap, 3 | #category : 'Magritte-Bootstrap' 4 | } 5 | 6 | { #category : #'reflective operations' } 7 | TMagritteBootstrap >> doesNotUnderstand: aMessage [ 8 | 9 | ^ self magritteDescription 10 | detect: [ :d | d accessor handlesSelector: aMessage selector ] 11 | ifFound: [ :handler | handler handleMessage: aMessage for: self ] 12 | ifNone: [ super doesNotUnderstand: aMessage ]. 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Bootstrap/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Bootstrap' } 2 | -------------------------------------------------------------------------------- /source/Magritte-ContactManager/CMPhone.class.st: -------------------------------------------------------------------------------- 1 | " 2 | A simple phone model 3 | " 4 | Class { 5 | #name : #CMPhone, 6 | #superclass : #Object, 7 | #instVars : [ 8 | 'kind', 9 | 'number' 10 | ], 11 | #category : 'Magritte-ContactManager' 12 | } 13 | 14 | { #category : #comparing } 15 | CMPhone >> = anObject [ 16 | ^ self species = anObject species 17 | and: [ self kind = anObject kind 18 | and: [ self number = anObject number ] ] 19 | ] 20 | 21 | { #category : #descriptions } 22 | CMPhone >> descriptionKind [ 23 | 24 | ^ MAStringDescription new 25 | accessor: #kind; 26 | label: 'Kind'; 27 | priority: 10; 28 | yourself 29 | ] 30 | 31 | { #category : #descriptions } 32 | CMPhone >> descriptionNumber [ 33 | 34 | 35 | ^ MAStringDescription new 36 | accessor: #number; 37 | label: 'Number'; 38 | priority: 20; 39 | yourself 40 | ] 41 | 42 | { #category : #comparing } 43 | CMPhone >> hash [ 44 | ^ self kind hash bitXor: self number hash 45 | ] 46 | 47 | { #category : #accessing } 48 | CMPhone >> kind [ 49 | ^ kind 50 | ] 51 | 52 | { #category : #accessing } 53 | CMPhone >> kind: anObject [ 54 | kind := anObject 55 | ] 56 | 57 | { #category : #accessing } 58 | CMPhone >> number [ 59 | ^ number 60 | ] 61 | 62 | { #category : #accessing } 63 | CMPhone >> number: anObject [ 64 | number := anObject 65 | ] 66 | -------------------------------------------------------------------------------- /source/Magritte-ContactManager/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-ContactManager' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/BlockClosure.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #BlockClosure } 2 | 3 | { #category : #'*magritte-deprecated' } 4 | BlockClosure >> magritteDynamicObject [ 5 | "Answer an object that will automatically evaluate the receiver when it receives a message. It will eventually pass the message to the resulting object. Use with caution, for details see *MADynamicObject*." 6 | 7 | self greaseDeprecatedApi: 'BlockContext>>#magritteDynamicObject' details: '#magritteDynamicObject is no longer necessary as descriptions are now dynamically created'. 8 | 9 | ^ MADynamicObject on: self 10 | 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/GRPlatform.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPlatform } 2 | 3 | { #category : #'*magritte-deprecated' } 4 | GRPlatform >> magritteEvaluate: aBlock onUnhandledErrorDo: errorBlock [ 5 | "Evaluate aBlock. If an Error is signaled and is not handled higher up the 6 | stack, evaluate errorBlock with the Error instead of opening a debugger." 7 | 8 | self subclassResponsibility 9 | ] 10 | 11 | { #category : #'*magritte-deprecated' } 12 | GRPlatform >> magritteRegister: anObject forMethodChangeNotificationsUsing: selector [ 13 | "Register anObject with the system to be notified whenever a method is 14 | added, removed, or modified. When this happens, the specified selector 15 | should be called on anObject." 16 | 17 | self subclassResponsibility 18 | ] 19 | 20 | { #category : #'*magritte-deprecated' } 21 | GRPlatform >> magritteUnregister: anObject forMethodChangeNotificationsUsing: selector [ 22 | "Unregister anObject with the system for notification whenever a method is 23 | added, removed, or modified. anObject should no longer receive notifications 24 | using the specified selector." 25 | 26 | self subclassResponsibility 27 | ] 28 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/MADynamicObject.class.st: -------------------------------------------------------------------------------- 1 | " 2 | A dynamic object can be used for almost any property within Magritte that is not static but calculated dynamically. This is a shortcut to avoid having to build context sensitive descriptions manually over and over again, however there are a few drawbacks: 3 | 4 | - Some messages sent to this proxy, for example ==#class== and ==#value==, might not get resolved properly. 5 | - Raising an unhandled exception will not always open a debugger on your proxy, because tools are unable to properly work with the invalid object and might even crash your image. 6 | " 7 | Class { 8 | #name : #MADynamicObject, 9 | #superclass : #MAProxyObject, 10 | #category : 'Magritte-Deprecated' 11 | } 12 | 13 | { #category : #accessing } 14 | MADynamicObject >> realSubject [ 15 | ^ GRPlatform current 16 | magritteEvaluate: super realSubject 17 | onUnhandledErrorDo: [ :err | err return: nil ] 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*magritte-deprecated' } 4 | Object class >> description [ 5 | self greaseDeprecatedApi: 'Object class>>#description' details: '#description has been renamed to #magritteDescription as #description is a heavily overloaded term.'. 6 | 7 | ^ self magritteDescription 8 | ] 9 | 10 | { #category : #'*magritte-deprecated' } 11 | Object >> description [ 12 | self greaseDeprecatedApi: 'Object>>#description' details: '#description has been renamed to #magritteDescription as #description is a heavily overloaded term.'. 13 | 14 | ^ self magritteDescription 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/Symbol.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Symbol } 2 | 3 | { #category : #'*magritte-deprecated' } 4 | Symbol >> isDescriptionDefinition [ 5 | "Answer wheter the receiver is a method selector following the naming conventions of a description definition." 6 | 7 | ^ self isDescriptionSelector 8 | and: [ self isUnary ] 9 | ] 10 | 11 | { #category : #'*magritte-deprecated' } 12 | Symbol >> isDescriptionExtension: aSelector [ 13 | "Answer wheter the receiver is a method selector following the naming conventions of a description extension to aSelector." 14 | 15 | ^ self isDescriptionSelector 16 | and: [ self numArgs = 1 17 | and: [ self beginsWith: aSelector ] ] 18 | ] 19 | 20 | { #category : #'*magritte-deprecated' } 21 | Symbol >> isDescriptionSelector [ 22 | "Answer wheter the receiver is a method selector following the naming conventions of a description selector." 23 | 24 | ^ self ~= #description 25 | and: [ self beginsWith: #description ] 26 | ] 27 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Deprecated' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MACheckboxMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MACheckboxMorph, 3 | #superclass : #MAMorphicCheckbox, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAContainerMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAContainerMorph, 3 | #superclass : #MAMorphicContainer, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MADateMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADateMorph, 3 | #superclass : #MAMorphicDate, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MADirectoryMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADirectoryMorph, 3 | #superclass : #MAMorphicDirectory, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MADropListMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADropListMorph, 3 | #superclass : #MAMorphicDropList, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAExternalEditorMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAExternalEditorMorph, 3 | #superclass : #MAMorphicExternalEditor, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAFileMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileMorph, 3 | #superclass : #MAMorphicFile, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAInternalEditorMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAInternalEditorMorph, 3 | #superclass : #MAMorphicInternalEditor, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAListMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAListMorph, 3 | #superclass : #MAMorphicList, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAMemoMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMemoMorph, 3 | #superclass : #MAMorphicMemo, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAMultiSelectListMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMultiSelectListMorph, 3 | #superclass : #MAMorphicMultiSelectList, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAOneToManyMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAOneToManyMorph, 3 | #superclass : #MAMorphicOneToMany, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAOneToOneMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAOneToOneMorph, 3 | #superclass : #MAMorphicOneToOne, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MAPasswordMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPasswordMorph, 3 | #superclass : #MAMorphicPassword, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MARelationMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MARelationMorph, 3 | #superclass : #MAMorphicRelation, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MASilentContainerMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MASilentContainerMorph, 3 | #superclass : #MAMorphicSilentContainer, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MASingleSelectListMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MASingleSelectListMorph, 3 | #superclass : #MAMorphicSingleSelectList, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MATextMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATextMorph, 3 | #superclass : #MAMorphicText, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/MATokenCompletionMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATokenCompletionMorph, 3 | #superclass : #MAMorphicTokenCompletion, 4 | #category : #'Magritte-Deprecated3dot7' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/ManifestMagritteDeprecateddot.class.st: -------------------------------------------------------------------------------- 1 | " 2 | To be removed in Magritte 4 3 | " 4 | Class { 5 | #name : #ManifestMagritteDeprecateddot, 6 | #superclass : #PackageManifest, 7 | #category : #'Magritte-Deprecated3dot7-Manifest' 8 | } 9 | 10 | { #category : #deprecation } 11 | ManifestMagritteDeprecateddot class >> isDeprecated [ 12 | ^ true 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*Magritte-Deprecated3dot7' } 4 | Object >> maLazyFrom: description [ 5 | self 6 | deprecated: 'Renamed to #maLazyInstVarUsing: because now there is also #maLazyPropertyUsing:' 7 | transformWith: '`@receiver maLazyFrom: `@statements1' 8 | -> '`@receiver maLazyInstVarUsing: `@statements1'. 9 | ^ self maLazyInstVarUsing: description 10 | ] 11 | 12 | { #category : #'*Magritte-Deprecated3dot7' } 13 | Object >> magritteActionDescriptions [ 14 | self 15 | deprecated: 'Renamed to #magritteActions for ease of use and also slightly more accurate (see new method comment' 16 | transformWith: '`@receiver magritteActionDescriptions' 17 | -> '`@receiver magritteActions'. 18 | ^ self magritteActions 19 | ] 20 | -------------------------------------------------------------------------------- /source/Magritte-Deprecated3dot7/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Deprecated3dot7' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Developer/Class.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Class } 2 | 3 | { #category : #'*Magritte-Developer' } 4 | Class >> maAddField [ 5 | | fieldName | 6 | fieldName := UIManager default request: 'Field name?'. 7 | fieldName ifNil: [ ^ self ]. 8 | self maAddField: fieldName asSymbol 9 | ] 10 | -------------------------------------------------------------------------------- /source/Magritte-Developer/MAClyAddFieldCommand.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAClyAddFieldCommand, 3 | #superclass : #SycSingleClassCommand, 4 | #instVars : [ 5 | 'fieldName' 6 | ], 7 | #category : 'Magritte-Developer' 8 | } 9 | 10 | { #category : #activation } 11 | MAClyAddFieldCommand class >> contextMenuActivation [ 12 | 13 | ^ CmdContextMenuActivation byRootGroupItemFor: ClyClassContextOfFullBrowser 14 | ] 15 | 16 | { #category : #accessing } 17 | MAClyAddFieldCommand class >> defaultMenuItemName [ 18 | ^'Add Field (Magritte)' 19 | ] 20 | 21 | { #category : #execution } 22 | MAClyAddFieldCommand >> execute [ 23 | targetClass maAddField: fieldName asSymbol 24 | ] 25 | 26 | { #category : #execution } 27 | MAClyAddFieldCommand >> prepareFullExecutionInContext: aToolContext [ 28 | super prepareFullExecutionInContext: aToolContext. 29 | fieldName := UIManager default request: 'Field name'. 30 | fieldName isEmptyOrNil ifTrue: [ CmdCommandAborted signal ] 31 | ] 32 | -------------------------------------------------------------------------------- /source/Magritte-Developer/MADeveloperMenus.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADeveloperMenus, 3 | #superclass : #Object, 4 | #category : 'Magritte-Developer' 5 | } 6 | 7 | { #category : #'nautilus menus' } 8 | MADeveloperMenus class >> maNautilusMethodMenu: aBuilder [ 9 | 10 | 11 | | selection | 12 | selection := aBuilder model selectedClass. 13 | selection ifNil: [ ^ self ]. 14 | 15 | (aBuilder item: #'MA Add Field') 16 | action: [ selection maAddField ]; 17 | order: 0; 18 | help: 'Add Magritte Field'. 19 | ] 20 | -------------------------------------------------------------------------------- /source/Magritte-Developer/MADeveloperTests.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADeveloperTests, 3 | #superclass : #TestCase, 4 | #category : #'Magritte-Developer-Tests' 5 | } 6 | 7 | { #category : #accessing } 8 | MADeveloperTests >> testGenerateDescriptionSource [ 9 | 10 | | desc | 11 | desc := MANumberDescription new 12 | default: 5; 13 | yourself. 14 | 15 | self 16 | assert: desc storeString 17 | equals: 'MANumberDescription new 18 | default: 5; 19 | yourself' 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Developer/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAElementDescription } 2 | 3 | { #category : #'*Magritte-Developer' } 4 | MAElementDescription >> addTo: aClass as: aSymbol [ 5 | | source formattedSource | 6 | source := String streamContents: [ :s | 7 | s 8 | nextPutAll: aSymbol; nextPutAll: 'Description'; cr; 9 | nextPutAll: ''. 10 | s 11 | nextPutAll: '^ '; 12 | store: self ]. 13 | formattedSource := (RBParser parseMethod: source) formattedCode. 14 | aClass compile: formattedSource classified: 'magritte-accessing'. 15 | self accessor maSetUp: aClass for: self 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Developer/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Developer' } 2 | -------------------------------------------------------------------------------- /source/Magritte-FileDirectory/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-filedirectory' } 4 | GRPackage class >> magritteFileDirectory [ 5 | ^ self new 6 | name: 'Magritte-FileDirectory'; 7 | addDependency: 'Magritte-Files-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-FileDirectory/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-FileDirectory' } 2 | -------------------------------------------------------------------------------- /source/Magritte-FileSystem/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-filesystem' } 4 | GRPackage class >> magritteFileSystem [ 5 | ^ self new 6 | name: 'Magritte-FileSystem'; 7 | addDependency: 'Magritte-Files-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-FileSystem/MAFileDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAFileDescription } 2 | 3 | { #category : #'*Magritte-FileSystem' } 4 | MAFileDescription >> defaultDirectory [ 5 | 6 | ^ self propertyAt: #defaultDirectory ifAbsent: [ MAFileSystem imageDirectory ]. 7 | ] 8 | 9 | { #category : #'*Magritte-FileSystem' } 10 | MAFileDescription >> defaultDirectory: fileReference [ 11 | "fileReference - a FileSystem FileReference, or an MAFileReference if FileSystem is not installed" 12 | 13 | self propertyAt: #defaultDirectory put: fileReference 14 | ] 15 | -------------------------------------------------------------------------------- /source/Magritte-FileSystem/MAFileSystem.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileSystem, 3 | #superclass : #Object, 4 | #category : 'Magritte-FileSystem' 5 | } 6 | 7 | { #category : #paths } 8 | MAFileSystem class >> extensionFor: aString [ 9 | 10 | ^ aString asFileReference extension. 11 | ] 12 | 13 | { #category : #entries } 14 | MAFileSystem class >> fileSizeFor: filenameString [ 15 | ^ filenameString asFileReference size 16 | ] 17 | 18 | { #category : #paths } 19 | MAFileSystem class >> fullNameFor: aString [ 20 | 21 | ^ aString asFileReference fullName. 22 | ] 23 | 24 | { #category : #locations } 25 | MAFileSystem class >> imageDirectory [ 26 | 27 | ^ FileLocator imageDirectory. 28 | ] 29 | 30 | { #category : #'mime types' } 31 | MAFileSystem class >> mimeTypesForExtension: aString [ 32 | 33 | | types | 34 | types := MIMEType forExtensionReturnMimeTypesOrNil: aString. 35 | ^ types ifNotNil: [ types collect: [ :e | e asString ] ]. 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-FileSystem/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-FileSystem' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Files-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-files-model' } 4 | GRPackage class >> magritteFilesModel [ 5 | ^ self new 6 | name: 'Magritte-Files-Model'; 7 | addDependency: 'Magritte-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Files-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Files-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-GT/ClyTagInspectorExtensionCommand.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #ClyTagInspectorExtensionCommand, 3 | #superclass : #SycMethodCommand, 4 | #category : 'Magritte-GT' 5 | } 6 | 7 | { #category : #testing } 8 | ClyTagInspectorExtensionCommand class >> canBeExecutedInContext: aToolContext [ 9 | ^ aToolContext selectedMethods allSatisfy: [ :e | e maIsDescription ] 10 | ] 11 | 12 | { #category : #accessing } 13 | ClyTagInspectorExtensionCommand class >> defaultMenuItemName [ 14 | ^'Show in GT-Inspector' 15 | ] 16 | 17 | { #category : #accessing } 18 | ClyTagInspectorExtensionCommand class >> methodContextMenuActivation [ 19 | 20 | 21 | ^ CmdContextMenuActivation byItemOf: CmdExtraMenuGroup for: ClyMethod asCalypsoItemContext 22 | ] 23 | 24 | { #category : #execution } 25 | ClyTagInspectorExtensionCommand >> execute [ 26 | 27 | methods do: [ :m | m maShowInGtInspector ] 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-GT/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*Magritte-GT' } 4 | Object >> exampleGtInspectorReadOnlyMagritteIn: composite [ 5 | "" 6 | "A simple GT presentation. Disabled by default because we have one that shows the full editable form, but could be useful..." 7 | | table | 8 | table := composite table 9 | title: 'Magritte'; 10 | display: [ self magritteDescription children collect: [ :desc | 11 | desc label -> (desc toString: (desc accessor read: self)) ] ]; 12 | when: [ self magritteDescription notEmpty ]; 13 | column: 'Field' evaluated: #key; 14 | column: 'Value' evaluated: #value; 15 | send: #value 16 | ] 17 | 18 | { #category : #'*Magritte-GT' } 19 | Object >> gtInspectorMagritteIn: composite [ 20 | 21 | composite magritte 22 | title: 'Form'; 23 | display: [ self ]; 24 | when: [ self magritteDescription isContainer not or: [ self magritteDescription notEmpty ] ] 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-GT/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-GT' } 2 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/GtPhlowProtoView.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GtPhlowProtoView } 2 | 3 | { #category : #'*Magritte-GToolkit' } 4 | GtPhlowProtoView >> maColumnedListOf: aClassOrContainer [ 5 | 6 | ^ self 7 | maColumnedListOf: aClassOrContainer 8 | descriptionsSelect: [ :desc | true ] 9 | ] 10 | 11 | { #category : #'*Magritte-GToolkit' } 12 | GtPhlowProtoView >> maColumnedListOf: aClassOrContainer descriptionsSelect: aBlock [ 13 | 14 | | result container | 15 | result := self columnedList. 16 | 17 | container := aClassOrContainer isClass 18 | ifTrue: [ aClassOrContainer magritteTemplate magritteDescription ] 19 | ifFalse: [ aClassOrContainer ]. 20 | 21 | container children 22 | select: aBlock 23 | thenDo: [ :desc | desc gtAddColumnTo: result ]. 24 | 25 | ^ result 26 | ] 27 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/GtPhlowView.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GtPhlowView } 2 | 3 | { #category : #'*Magritte-GToolkit' } 4 | GtPhlowView >> maOn: anObject perform: aMessageSymbol withContext: aContext [ 5 | "Adapted from on:perform:withArguments:" 6 | 7 | "" 8 | 9 | | aCollectionOfArguments | 10 | aCollectionOfArguments := { self. aContext }. 11 | 12 | ^ [ 13 | | aDescription aPhlowView | 14 | aDescription := thisContext 15 | object: anObject 16 | perform: aMessageSymbol 17 | withArguments: #() 18 | inClass: anObject class. 19 | aPhlowView := aDescription gtView cull: self cull: aDescription cull: anObject. 20 | self 21 | assert: [ aPhlowView ~= self ] 22 | description: [ 'Phlow view definition cannot return same view that is passed as an argument. Use `aView empty` instead in: ', 23 | anObject printString, '>>#', aMessageSymbol asString ]. 24 | aPhlowView object: anObject arguments: aCollectionOfArguments. 25 | ] on: Error do: [ :anException | 26 | NonInteractiveTranscript stdout 27 | nextPut: $[; 28 | nextPutAll: self class name; 29 | nextPut: $]; 30 | space; 31 | print: anException; 32 | cr. 33 | 34 | self 35 | phlowErrorViewWithException: anException 36 | forBuildContext: (GtPhlowBuildContext new object: anObject; arguments: aCollectionOfArguments) 37 | andSelector: aMessageSymbol ] 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MACompositeAccessor.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MACompositeAccessor } 2 | 3 | { #category : #'*Magritte-GToolkit' } 4 | MACompositeAccessor class >> sampleContainer [ 5 | 6 | | desc | 7 | desc := MAContainer samplePersonDescription 8 | blocClass: MACompositeElementBuilder; 9 | yourself. 10 | desc children do: [ :e | 11 | | acc prefixAccessor | 12 | prefixAccessor := MADictionaryAccessor key: #people. 13 | acc := MACompositeAccessor via: prefixAccessor using: e ]. 14 | ^ desc 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MADescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADescription } 2 | 3 | { #category : #'*Magritte-GToolkit' } 4 | MADescription >> blocClass [ 5 | ^ self propertyAt: #blocClass ifAbsent: [ MAElementBuilder"self class defaultMorphicClass" ] 6 | ] 7 | 8 | { #category : #'*Magritte-GToolkit' } 9 | MADescription >> blocClass: aClass [ 10 | ^ self propertyAt: #blocClass put: aClass 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MADropdownWish.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADropdownWish, 3 | #superclass : #BrWish, 4 | #instVars : [ 5 | 'selection' 6 | ], 7 | #category : 'Magritte-GToolkit-Support' 8 | } 9 | 10 | { #category : #accessing } 11 | MADropdownWish >> selection [ 12 | ^ selection 13 | ] 14 | 15 | { #category : #accessing } 16 | MADropdownWish >> selection: anObject [ 17 | selection := anObject 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MAFieldElement.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFieldElement, 3 | #superclass : #BrVerticalPane, 4 | #category : #'Magritte-GToolkit' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MAGtInputFieldAptitude.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAGtInputFieldAptitude, 3 | #superclass : #BrGlamorousInputFieldSpacingAptitude, 4 | #category : #'Magritte-GToolkit' 5 | } 6 | 7 | { #category : #accessing } 8 | MAGtInputFieldAptitude >> initialize [ 9 | 10 | super initialize. 11 | self add: BrGlamorousEditorAptitude 12 | ] 13 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MAIconDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAIconDescription } 2 | 3 | { #category : #'*Magritte-GToolkit' } 4 | MAIconDescription >> gtAddColumnTo: aView [ 5 | 6 | self 7 | propertyAt: #columnWidth 8 | ifPresent: [ :width | 9 | aView 10 | column: self label 11 | iconName: [ :anObject | anObject perform: self iconNameAccessor ] 12 | width: width. 13 | ^ self ]. 14 | 15 | aView 16 | column: self label 17 | iconName: [ :anObject | anObject perform: self iconNameAccessor ] 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MATokenCollectorElement.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATokenCollectorElement, 3 | #superclass : #MATokenSelectorElement, 4 | #category : #'Magritte-GToolkit-Widgets' 5 | } 6 | 7 | { #category : #accessing } 8 | MATokenCollectorElement >> onTokenRemovedFor: anObject [ 9 | | collection | 10 | collection := self object readUsing: self relationDescription. 11 | collection remove: anObject 12 | ] 13 | 14 | { #category : #accessing } 15 | MATokenCollectorElement >> onTokenRequestFor: anObject [ 16 | | collection | 17 | collection := self object readUsing: self relationDescription. 18 | collection add: anObject. 19 | self refreshTokens 20 | ] 21 | 22 | { #category : #accessing } 23 | MATokenCollectorElement >> refreshTokens [ 24 | 25 | | collection | 26 | self tokenContainer removeChildren. 27 | collection := self object readUsing: self relationDescription. 28 | collection isEmptyOrNil ifTrue: [ ^ self ]. 29 | collection do: [ :e | self addTokenFor: e ]. 30 | ] 31 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MATokenRequest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATokenRequest, 3 | #superclass : #BlEvent, 4 | #instVars : [ 5 | 'action' 6 | ], 7 | #category : #'Magritte-GToolkit-Support' 8 | } 9 | 10 | { #category : #'api - stream' } 11 | MATokenRequest class >> action: aBlock [ 12 | 13 | ^ self new 14 | action: aBlock; 15 | yourself 16 | ] 17 | 18 | { #category : #accessing } 19 | MATokenRequest >> action [ 20 | 21 | ^ action 22 | ] 23 | 24 | { #category : #accessing } 25 | MATokenRequest >> action: anObject [ 26 | 27 | action := anObject 28 | ] 29 | 30 | { #category : #accessing } 31 | MATokenRequest >> answer: player [ 32 | ^ self action value: player 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/MaGtPhlowViewsCollector.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MaGtPhlowViewsCollector, 3 | #superclass : #GtPhlowViewsCollector, 4 | #category : #'Magritte-GToolkit' 5 | } 6 | 7 | { #category : #accessing } 8 | MaGtPhlowViewsCollector class >> defaultViewPragmaNames [ 9 | ^ #( #maGtView ) 10 | ] 11 | 12 | { #category : #actions } 13 | MaGtPhlowViewsCollector >> collect [ 14 | 15 | 16 | | theViews | 17 | theViews := self collectPragmas 18 | collect: [ :eachPragma | 19 | | aView | 20 | aView := GtPhlowView empty 21 | maOn: self object 22 | perform: eachPragma methodSelector 23 | withContext: self context. 24 | self object gtActions do: [ :eachAction | 25 | (eachAction target isForViewDefinedIn: eachPragma methodSelector) ifTrue: [ 26 | aView addPhlowAction: eachAction ] ]. 27 | aView ]. 28 | self sortByPriority: theViews. 29 | ^ theViews 30 | ] 31 | -------------------------------------------------------------------------------- /source/Magritte-GToolkit/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-GToolkit' } 2 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Model/AbstractDictionary.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #AbstractDictionary } 2 | 3 | { #category : #'*magritte-gemstone-model' } 4 | AbstractDictionary >> optionFor: anObject ifPresent: aBlock [ 5 | self at: anObject ifPresent: aBlock 6 | 7 | ] 8 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Model/MAError.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAError } 2 | 3 | { #category : #'*magritte-gemstone-model' } 4 | MAError >> greaseString [ 5 | ^ self printString 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-GemStone-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Seaside/ExecutableBlock.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #ExecutableBlock } 2 | 3 | { #category : #'*magritte-gemstone-seaside' } 4 | ExecutableBlock >> decompile [ 5 | "used by MaPluggableAccessort>>storeBlockOn:, but I'm suspicious ot wheter it will really work ... probably used for 6 | export/import of Pier which GemStone will do differently" 7 | 8 | ^self _sourceString 9 | ] 10 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Seaside/MAExternalFileModel.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAExternalFileModel } 2 | 3 | { #category : #'*magritte-gemstone-seaside-accessing' } 4 | MAExternalFileModel >> url [ 5 | ^ self baseUrl isNil 6 | ifTrue: [ super url ] 7 | ifFalse: [ self baseUrl , '/' , (self location reduce: [ :a :b | a , '/' , b ]) , '/' , self filename ] 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-GemStone-Seaside/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-GemStone-Seaside' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/GLMCompositePresentation.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GLMCompositePresentation } 2 | 3 | { #category : #'*Magritte-Glamour' } 4 | GLMCompositePresentation >> magritte [ 5 | ^ self custom: GLMMagrittePresentation new 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/GLMListingPresentation.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GLMListingPresentation } 2 | 3 | { #category : #'*Magritte-Glamour' } 4 | GLMListingPresentation >> maAddSelectionActionsFor: aClass [ 5 | 6 | aClass magritteActions do: [ :desc | 7 | | glmAction actionBlock | 8 | actionBlock := [ :list | 9 | desc performOn: list selection. 10 | desc isMutator ifTrue: [ list update ] ]. 11 | glmAction := GLMGenericAction new 12 | action: actionBlock; 13 | icon: desc icon; 14 | title: desc label; 15 | yourself. 16 | desc shortcut ifNotNil: [ :sc | glmAction shortcut: sc key "assumes single key" ]. 17 | self addSelectionAction: glmAction ]. 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/GLMMagrittePresentation.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #GLMMagrittePresentation, 3 | #superclass : #GLMPresentation, 4 | #instVars : [ 5 | 'magritteDescription', 6 | 'answerBlock' 7 | ], 8 | #category : 'Magritte-Glamour' 9 | } 10 | 11 | { #category : #accessing } 12 | GLMMagrittePresentation >> description: anObject [ 13 | "convenience method for scripting" 14 | 15 | magritteDescription := anObject 16 | ] 17 | 18 | { #category : #accessing } 19 | GLMMagrittePresentation >> magritteDescription [ 20 | "By default the we read it via the #description selector" 21 | ^ magritteDescription ifNil: [ magritteDescription := #magritteDescription ] 22 | ] 23 | 24 | { #category : #accessing } 25 | GLMMagrittePresentation >> onAnswer: aBlock [ 26 | answerBlock := aBlock 27 | ] 28 | 29 | { #category : #accessing } 30 | GLMMagrittePresentation >> reactOnAnswerFor: aValue [ 31 | self update. 32 | ^ answerBlock glamourValue: 33 | (aValue asGlamorousMultiValue, 34 | self asGlamorousMultiValue, 35 | self entity asGlamorousMultiValue) 36 | ] 37 | 38 | { #category : #rendering } 39 | GLMMagrittePresentation >> renderGlamorouslyOn: aRenderer [ 40 | ^ aRenderer renderMagrittePresentation: self 41 | ] 42 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/GLMMorphicRenderer.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GLMMorphicRenderer } 2 | 3 | { #category : #'*Magritte-Glamour' } 4 | GLMMorphicRenderer >> renderMagrittePresentation: aMagrittePresentation [ 5 | ^ GLMMorphicMagritteRenderer render: aMagrittePresentation from: self 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/GLMPresentation.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GLMPresentation } 2 | 3 | { #category : #'*Magritte-Glamour' } 4 | GLMPresentation >> glmAddActions [ 5 | self dynamicActions: [ :pres | pres entity magritteActionDescriptions collect: #asGlmAction ] 6 | ] 7 | 8 | { #category : #'*Magritte-Glamour' } 9 | GLMPresentation >> glmAddSelectionActions [ 10 | self dynamicActionsOnSelection: [ :pres | 11 | pres selection magritteActionDescriptions collect: #asGlmAction ] 12 | ] 13 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/MAStringDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAStringDescription } 2 | 3 | { #category : #'*Magritte-Glamour' } 4 | MAStringDescription >> glmDefaultPresentation [ 5 | ^ #text 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Glamour/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Glamour' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Merging-Bloc/MAPatchMacro.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAPatchMacro } 2 | 3 | { #category : #'*Magritte-Merging-Bloc' } 4 | MAPatchMacro >> asElement [ 5 | ^ MAPatchMacroElement on: self 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Merging-Bloc/MAPatchOperation.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAPatchOperation } 2 | 3 | { #category : #'*Magritte-Merging-Bloc' } 4 | MAPatchOperation >> asElement [ 5 | ^ BlElement new 6 | layout: (BlLinearLayout horizontal cellSpacing: 10); 7 | constraintsDo: [ :c | 8 | c horizontal fitContent. 9 | c vertical fitContent ]; 10 | addChild: 11 | (BrCheckbox new 12 | aptitude: BrGlamorousCheckboxAptitude; 13 | checked: self isEnabled; 14 | when: BrCheckboxChanged do: [ :evt | self isEnabled: evt isChecked ]); 15 | addChild: 16 | (BrLabel new 17 | aptitude: BrGlamorousLabelAptitude; 18 | text: (self field label , ':') asRopedText; 19 | addEventHandlerOn: BlClickEvent 20 | do: [ :evt | evt target phlow spawnObject: self ]); 21 | addChild: 22 | (BrLabel new 23 | aptitude: BrGlamorousLabelAptitude; 24 | text: self oldValue displayString asRopedText; 25 | addEventHandlerOn: BlClickEvent 26 | do: [ :evt | evt target phlow spawnObject: self oldValue ]); 27 | addChild: 28 | (BrLabel new 29 | aptitude: BrGlamorousLabelAptitude; 30 | text: ' > ' asRopedText); 31 | addChild: 32 | (BrLabel new 33 | aptitude: BrGlamorousLabelAptitude; 34 | text: self newValue displayString asRopedText; 35 | addEventHandlerOn: BlClickEvent 36 | do: [ :evt | evt target phlow spawnObject: self newValue ]); 37 | yourself 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Merging-Bloc/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Merging-Bloc' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Merging/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAElementDescription } 2 | 3 | { #category : #'*Magritte-Merging' } 4 | MAElementDescription >> mergeInPlace: aBoolean [ 5 | self flag: 'Hook for GH Issue #4. NB Not currently used'. 6 | self propertyAt: #mergeInPlace put: aBoolean 7 | ] 8 | 9 | { #category : #'*Magritte-Merging' } 10 | MAElementDescription >> patch: target relativeTo: base [ 11 | | oldValue newValue | 12 | oldValue := self read: base. 13 | newValue := self read: target. 14 | ^ newValue patchRelativeToBase: oldValue as: self of: base. 15 | ] 16 | 17 | { #category : #'*Magritte-Merging' } 18 | MAElementDescription >> shouldMerge [ 19 | ^ self propertyAt: #shouldMerge ifAbsent: [ true ] 20 | ] 21 | 22 | { #category : #'*Magritte-Merging' } 23 | MAElementDescription >> shouldMerge: aBoolean [ 24 | self propertyAt: #shouldMerge put: aBoolean 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Merging/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*Magritte-Merging' } 4 | Object >> is: newValue anInterestingReplacementFor: oldValue [ 5 | newValue isNil ifTrue: [ ^ false ]. 6 | oldValue = newValue ifTrue: [ ^ false ]. 7 | ^ true 8 | ] 9 | 10 | { #category : #'*Magritte-Merging' } 11 | Object >> patchRelativeToBase: baseName [ 12 | 13 | | operations relevantFields relevantOperations | 14 | relevantFields := self magritteDescription children select: #shouldMerge. 15 | operations := relevantFields collect: [ :desc | desc patch: self relativeTo: baseName ]. 16 | relevantOperations := operations reject: #isEmptyOrNil. 17 | ^ MAPatchMacro new 18 | operations: relevantOperations; 19 | yourself 20 | ] 21 | 22 | { #category : #'*Magritte-Merging' } 23 | Object >> patchRelativeToBase: oldValue as: description of: receiver [ 24 | 25 | ^ (receiver is: self anInterestingReplacementFor: oldValue) 26 | ifTrue: [ 27 | MAPatchOperation new 28 | receiver: receiver; 29 | field: description; 30 | oldValue: oldValue; 31 | newValue: self ] 32 | ifFalse: [ nil ]. 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Merging/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Merging' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Model/ArrayedCollection.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #ArrayedCollection } 2 | 3 | { #category : #'*magritte-model' } 4 | ArrayedCollection >> copyWithAll: aCollection [ 5 | ^ (self species new: self size + aCollection size) 6 | replaceFrom: 1 to: self size with: self startingAt: 1; 7 | replaceFrom: self size + 1 to: self size + aCollection size with: aCollection startingAt: 1; 8 | yourself 9 | ] 10 | -------------------------------------------------------------------------------- /source/Magritte-Model/BlockClosure.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #BlockClosure } 2 | 3 | { #category : #'*Magritte-Model' } 4 | BlockClosure >> optionFor: anObject ifPresent: aBlock [ 5 | aBlock value: (self cull: anObject) 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Model/Class.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Class } 2 | 3 | { #category : #'*magritte-model-configuration' } 4 | Class >> descriptionContainer [ 5 | "Return the default description container." 6 | 7 | ^ MAPriorityContainer new 8 | label: self label; 9 | yourself 10 | ] 11 | 12 | { #category : #'*Magritte-Model' } 13 | Class >> label [ 14 | "Answer a human-readable name of the receiving class. This implementation tries to be smart and return a nice label, unfortunately for a lot of classes this doesn't work well so subclasses might want to override this method and return soemthing more meaningfull to end-users." 15 | 16 | | start input | 17 | start := self name findFirst: [ :each | each isLowercase ]. 18 | input := (self name copyFrom: (1 max: start - 1) to: self name size) 19 | readStream. 20 | ^ String streamContents: [ :stream | 21 | [ input atEnd ] whileFalse: [ 22 | stream nextPut: input next. 23 | (input atEnd or: [ input peek isLowercase ]) 24 | ifFalse: [ stream nextPut: Character space ] ] ] 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Model/Collection.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Collection } 2 | 3 | { #category : #'*magritte-model' } 4 | Collection >> asMultilineString [ 5 | ^ String streamContents: [ :stream | 6 | self 7 | do: [ :each | stream nextPutAll: each ] 8 | separatedBy: [ stream nextPut: Character cr ] ] 9 | ] 10 | 11 | { #category : #'*magritte-model' } 12 | Collection >> copyWithAll: aCollection [ 13 | ^ self copy 14 | addAll: aCollection; 15 | yourself 16 | ] 17 | 18 | { #category : #'*magritte-model' } 19 | Collection >> copyWithoutFirst: anObject [ 20 | | done | 21 | done := false. 22 | ^ self reject: [ :each | 23 | (each = anObject 24 | and: [ done not ]) 25 | and: [ done := true ] ] 26 | ] 27 | 28 | { #category : #'*magritte-model' } 29 | Collection >> copyWithoutFirstOccurrenceOf: anObject [ 30 | | done | 31 | done := false. 32 | ^ self reject: [ :each | 33 | each = anObject 34 | and: [ done not 35 | and: [ done := true ] ] ] 36 | ] 37 | 38 | { #category : #'*magritte-model-dynopt' } 39 | Collection >> maAllOptionsFor: aDescription [ 40 | ^ aDescription prepareOptions: self copy 41 | ] 42 | 43 | { #category : #'*Magritte-Model' } 44 | Collection >> maSelectMatching: aString [ 45 | ^ self select: [ :e | e asString startsWith: aString ] 46 | ] 47 | -------------------------------------------------------------------------------- /source/Magritte-Model/Dictionary.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Dictionary } 2 | 3 | { #category : #'*Magritte-Model' } 4 | Dictionary >> optionFor: anObject ifPresent: aBlock [ 5 | self at: anObject ifPresent: aBlock 6 | 7 | ] 8 | -------------------------------------------------------------------------------- /source/Magritte-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-model' } 4 | GRPackage class >> magritteModel [ 5 | ^ self new 6 | name: 'Magritte-Model'; 7 | description: 'The Magritte metamodel.'; 8 | addDependency: 'Grease-Core'; 9 | url: #magritteUrl; 10 | yourself 11 | ] 12 | 13 | { #category : #'*magritte-model' } 14 | GRPackage >> magritteUrl [ 15 | ^ 'http://source.lukas-renggli.ch/magritte2' 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Model/Integer.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Integer } 2 | 3 | { #category : #'*Magritte-Model' } 4 | Integer >> asFileSize [ 5 | #( 'B' 'KB' 'MB' 'GB' 'TB' 'PB' 'EB' 'ZB' 'YB' ) 6 | inject: self 7 | into: [ :value :each | 8 | value < 1024 9 | ifFalse: [ value // 1024 ] 10 | ifTrue: [ ^ value asString , ' ' , each ] ] 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAActionPragmaBuilder.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAActionPragmaBuilder, 3 | #superclass : #MAPragmaBuilder, 4 | #category : #'Magritte-Model-Utility' 5 | } 6 | 7 | { #category : #constants } 8 | MAActionPragmaBuilder class >> magritteDescriptionExtensionPragma [ 9 | ^ #magritteActionDescription: 10 | ] 11 | 12 | { #category : #constants } 13 | MAActionPragmaBuilder class >> magritteDescriptionPragma [ 14 | ^ #magritteActionDescription 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Model/MABasicObject.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MABasicObject, 3 | #superclass : #GRObject, 4 | #category : 'Magritte-Model-Core' 5 | } 6 | 7 | { #category : #'error handling' } 8 | MABasicObject class >> defaultErrorClass [ 9 | ^ MAError 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Model/MABlockDescription.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MABlockDescription, 3 | #superclass : #MAElementDescription, 4 | #category : #'Magritte-Model-Description' 5 | } 6 | 7 | { #category : #'accessing-defaults' } 8 | MABlockDescription class >> defaultKind [ 9 | ^ BlockClosure 10 | ] 11 | 12 | { #category : #'accessing-defaults' } 13 | MABlockDescription class >> defaultLineCount [ 14 | ^ 3 15 | ] 16 | 17 | { #category : #testing } 18 | MABlockDescription class >> isAbstract [ 19 | ^ false 20 | ] 21 | 22 | { #category : #accessing } 23 | MABlockDescription class >> label [ 24 | ^ 'Block' 25 | ] 26 | 27 | { #category : #visiting } 28 | MABlockDescription >> acceptMagritte: aVisitor [ 29 | aVisitor visitBlockDescription: self 30 | ] 31 | 32 | { #category : #'accessing-magritte' } 33 | MABlockDescription >> descriptionLineCount [ 34 | 35 | ^ MANumberDescription new 36 | accessor: #lineCount; 37 | label: 'Number of Lines'; 38 | priority: 400; 39 | default: self class defaultLineCount; 40 | beInteger; 41 | min: 1; 42 | yourself 43 | ] 44 | 45 | { #category : #accessing } 46 | MABlockDescription >> lineCount [ 47 | ^ self propertyAt: #lineCount ifAbsent: [ self class defaultLineCount ] 48 | ] 49 | 50 | { #category : #accessing } 51 | MABlockDescription >> lineCount: anInteger [ 52 | self propertyAt: #lineCount put: anInteger 53 | ] 54 | -------------------------------------------------------------------------------- /source/Magritte-Model/MACachedMemento.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I cache values being read and written without touching the model. When committing changes, the modifications will be propagated to the model all at once. 3 | " 4 | Class { 5 | #name : #MACachedMemento, 6 | #superclass : #MAMemento, 7 | #instVars : [ 8 | 'cache' 9 | ], 10 | #category : #'Magritte-Model-Memento' 11 | } 12 | 13 | { #category : #testing } 14 | MACachedMemento class >> isAbstract [ 15 | ^ false 16 | ] 17 | 18 | { #category : #accessing } 19 | MACachedMemento >> cache [ 20 | ^ cache 21 | ] 22 | 23 | { #category : #actions } 24 | MACachedMemento >> commit [ 25 | super commit. 26 | self push: self cache. 27 | self reset 28 | ] 29 | 30 | { #category : #testing } 31 | MACachedMemento >> hasChanges [ 32 | "Answer ==true==, if the cached data is different to the data in the model." 33 | 34 | ^ self has: self cache changedFrom: self pullRaw 35 | ] 36 | 37 | { #category : #private } 38 | MACachedMemento >> readUsing: aDescription [ 39 | ^ self cache at: aDescription 40 | ] 41 | 42 | { #category : #actions } 43 | MACachedMemento >> reset [ 44 | super reset. 45 | self setCache: self pull 46 | ] 47 | 48 | { #category : #initialization } 49 | MACachedMemento >> setCache: aDictionary [ 50 | cache := aDictionary 51 | ] 52 | 53 | { #category : #private } 54 | MACachedMemento >> write: anObject using: aDescription [ 55 | self cache at: aDescription put: anObject 56 | ] 57 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAClassDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of Smalltalk classes, possible values can be any of ==Smalltalk allClasses==. 3 | " 4 | Class { 5 | #name : #MAClassDescription, 6 | #superclass : #MAElementDescription, 7 | #category : #'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAClassDescription class >> defaultDisplayProperty [ 12 | ^ #name 13 | ] 14 | 15 | { #category : #'accessing-defaults' } 16 | MAClassDescription class >> defaultKind [ 17 | ^ Class 18 | ] 19 | 20 | { #category : #testing } 21 | MAClassDescription class >> isAbstract [ 22 | ^ false 23 | ] 24 | 25 | { #category : #accessing } 26 | MAClassDescription class >> label [ 27 | ^ 'Class' 28 | ] 29 | 30 | { #category : #visiting } 31 | MAClassDescription >> acceptMagritte: aVisitor [ 32 | aVisitor visitClassDescription: self 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAColorDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of colors, possible values are instances of ==Color==. My visual representation could be a color-chooser. 3 | " 4 | Class { 5 | #name : #MAColorDescription, 6 | #superclass : #MAElementDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAColorDescription class >> defaultKind [ 12 | ^ GRPlatform current magritteColorClass 13 | ] 14 | 15 | { #category : #testing } 16 | MAColorDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MAColorDescription class >> label [ 22 | ^ 'Color' 23 | ] 24 | 25 | { #category : #visiting } 26 | MAColorDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitColorDescription: self 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MACompositeConflict.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MACompositeConflict, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'kind', 6 | 'string' 7 | ], 8 | #category : #'Magritte-Model' 9 | } 10 | 11 | { #category : #comparing } 12 | MACompositeConflict >> = rhs [ 13 | ^ self species = rhs species 14 | ] 15 | 16 | { #category : #accessing } 17 | MACompositeConflict >> doesNotUnderstand: aMessage [ 18 | ^ (self kind canUnderstand: aMessage selector) 19 | ifTrue: [ self string ] 20 | ifFalse: [ super doesNotUnderstand: aMessage ] 21 | ] 22 | 23 | { #category : #comparing } 24 | MACompositeConflict >> hash [ 25 | ^ self species hash 26 | ] 27 | 28 | { #category : #'class membership' } 29 | MACompositeConflict >> isKindOf: aClass [ 30 | "This is to pass #validateKind:" 31 | ^ (super isKindOf: aClass) or: [ self kind = aClass ] 32 | ] 33 | 34 | { #category : #accessing } 35 | MACompositeConflict >> kind [ 36 | ^ kind 37 | ] 38 | 39 | { #category : #accessing } 40 | MACompositeConflict >> kind: aClass [ 41 | kind := aClass 42 | ] 43 | 44 | { #category : #printing } 45 | MACompositeConflict >> printOn: aStream [ 46 | aStream nextPutAll: self string 47 | ] 48 | 49 | { #category : #accessing } 50 | MACompositeConflict >> string [ 51 | ^ string ifNil: [ '(Multiple values)' ] 52 | ] 53 | 54 | { #category : #accessing } 55 | MACompositeConflict >> string: aString [ 56 | string := aString 57 | ] 58 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAConditionError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever a user-defined condition is failing. 3 | " 4 | Class { 5 | #name : #MAConditionError, 6 | #superclass : #MAValidationError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAConflictError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever there is an edit conflict. 3 | " 4 | Class { 5 | #name : #MAConflictError, 6 | #superclass : #MAValidationError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAConjunctiveCondition.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAConjunctiveCondition, 3 | #superclass : #MACondition, 4 | #instVars : [ 5 | 'conditions' 6 | ], 7 | #category : 'Magritte-Model-Utility' 8 | } 9 | 10 | { #category : #operators } 11 | MAConjunctiveCondition >> & aCondition [ 12 | conditions := conditions copyWith: aCondition 13 | ] 14 | 15 | { #category : #initialization } 16 | MAConjunctiveCondition >> initialize [ 17 | conditions := #() 18 | ] 19 | 20 | { #category : #evaluating } 21 | MAConjunctiveCondition >> value: anObject [ 22 | ^ conditions allSatisfy: [ :each | each value: anObject ] 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADateAndTimeDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of date and times, possible values are instances of ==DateAndTime==. My visual representation could be a date- and time-picker. 3 | " 4 | Class { 5 | #name : #MADateAndTimeDescription, 6 | #superclass : #MAMagnitudeDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MADateAndTimeDescription class >> defaultKind [ 12 | ^ DateAndTime 13 | ] 14 | 15 | { #category : #testing } 16 | MADateAndTimeDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MADateAndTimeDescription class >> label [ 22 | ^ 'Date and Time' 23 | ] 24 | 25 | { #category : #visiting } 26 | MADateAndTimeDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitDateAndTimeDescription: self 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADateDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of dates, possible values are instances of ==Date==. My visual representation could be a date-picker. 3 | " 4 | Class { 5 | #name : #MADateDescription, 6 | #superclass : #MAMagnitudeDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MADateDescription class >> defaultKind [ 12 | ^ Date 13 | ] 14 | 15 | { #category : #testing } 16 | MADateDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MADateDescription class >> label [ 22 | ^ 'Date' 23 | ] 24 | 25 | { #category : #visiting } 26 | MADateDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitDateDescription: self 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADirectoryDescription.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADirectoryDescription, 3 | #superclass : #MAFileDescription, 4 | #category : #'Magritte-Model-Description' 5 | } 6 | 7 | { #category : #acessing } 8 | MADirectoryDescription class >> label [ 9 | ^ 'Directory' 10 | ] 11 | 12 | { #category : #visiting } 13 | MADirectoryDescription >> acceptMagritte: aVisitor [ 14 | aVisitor visitDirectoryDescription: self 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADurationDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of durations, possible values are instances of ==Duration==. 3 | " 4 | Class { 5 | #name : #MADurationDescription, 6 | #superclass : #MAMagnitudeDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MADurationDescription class >> defaultKind [ 12 | ^ Duration 13 | ] 14 | 15 | { #category : #testing } 16 | MADurationDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MADurationDescription class >> label [ 22 | ^ 'Duration' 23 | ] 24 | 25 | { #category : #visiting } 26 | MADurationDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitDurationDescription: self 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADynamicDescribedObject.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADynamicDescribedObject, 3 | #superclass : #MADynamicVariable, 4 | #category : 'Magritte-Model-Utility' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADynamicDescriptionCache.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a dynamic variable that caches descriptions defined in the current call stack. I prevent infinite recursion when a description refers to itself. 3 | " 4 | Class { 5 | #name : #MADynamicDescriptionCache, 6 | #superclass : #MADynamicVariable, 7 | #category : #'Magritte-Model-Utility' 8 | } 9 | 10 | { #category : #defaults } 11 | MADynamicDescriptionCache class >> defaultValue [ 12 | ^ IdentityDictionary new 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Model/MADynamicVariable.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADynamicVariable, 3 | #superclass : #GRNotification, 4 | #category : 'Magritte-Model-Utility' 5 | } 6 | 7 | { #category : #defaults } 8 | MADynamicVariable class >> defaultValue [ 9 | ^ nil 10 | ] 11 | 12 | { #category : #private } 13 | MADynamicVariable class >> use: anObject during: aBlock [ 14 | "Set the dynamic value of the receiver to anObject during the evaluation of aBlock." 15 | 16 | ^ aBlock on: self do: [ :notification | notification resume: anObject ] 17 | ] 18 | 19 | { #category : #evaluating } 20 | MADynamicVariable class >> value [ 21 | "Answer the dynamic value of the receiver." 22 | 23 | ^ self signal 24 | ] 25 | 26 | { #category : #defaults } 27 | MADynamicVariable >> defaultAction [ 28 | ^ self class defaultValue 29 | ] 30 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAElementDescription } 2 | 3 | { #category : #'*magritte-model' } 4 | MAElementDescription >> printFor: anObject on: aWriteStream [ 5 | (self read: anObject) ifNotNil: [ :value | aWriteStream nextPutAll: (self toString: value) ] 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I represent a generic Magritte error. 3 | " 4 | Class { 5 | #name : #MAError, 6 | #superclass : #GRError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAFileDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of files, their contents, filename and mime-type. Possible values include instances of *MAFileModel*. My visual representation could be a file-upload dialog. 3 | " 4 | Class { 5 | #name : #MAFileDescription, 6 | #superclass : #MAElementDescription, 7 | #category : #'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAFileDescription class >> defaultDisplayProperty [ 12 | ^ #filename 13 | ] 14 | 15 | { #category : #'accessing-defaults' } 16 | MAFileDescription class >> defaultKind [ 17 | ^ MAMemoryFileModel 18 | ] 19 | 20 | { #category : #testing } 21 | MAFileDescription class >> isAbstract [ 22 | ^ false 23 | ] 24 | 25 | { #category : #accessing } 26 | MAFileDescription class >> label [ 27 | ^ 'File' 28 | ] 29 | 30 | { #category : #visiting } 31 | MAFileDescription >> acceptMagritte: aVisitor [ 32 | aVisitor visitFileDescription: self 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAIconDescription.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAIconDescription, 3 | #superclass : #MAElementDescription, 4 | #instVars : [ 5 | 'iconNameAccessor' 6 | ], 7 | #category : #'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #accessing } 11 | MAIconDescription >> iconNameAccessor [ 12 | ^ iconNameAccessor 13 | ] 14 | 15 | { #category : #accessing } 16 | MAIconDescription >> iconNameAccessor: anObject [ 17 | iconNameAccessor := anObject 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAIdentityAccessor.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a read-only access strategy and I answer the model itself when being read. 3 | " 4 | Class { 5 | #name : #MAIdentityAccessor, 6 | #superclass : #MAAccessor, 7 | #category : 'Magritte-Model-Accessor' 8 | } 9 | 10 | { #category : #testing } 11 | MAIdentityAccessor class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #testing } 16 | MAIdentityAccessor >> canRead: aModel [ 17 | ^ true 18 | ] 19 | 20 | { #category : #model } 21 | MAIdentityAccessor >> read: aModel [ 22 | ^ aModel 23 | ] 24 | 25 | { #category : #model } 26 | MAIdentityAccessor >> write: anObject to: aModel [ 27 | MAWriteError signal: 'Not supposed to write to ' , aModel greaseString , '.' 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAKindError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever a description is applied to the wrong type of data. 3 | " 4 | Class { 5 | #name : #MAKindError, 6 | #superclass : #MAValidationError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAMemoDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of multiline strings, possible values are instances of ==String==. My visual representation could be a text-area field. 3 | " 4 | Class { 5 | #name : #MAMemoDescription, 6 | #superclass : #MAStringDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAMemoDescription class >> defaultLineCount [ 12 | ^ 3 13 | ] 14 | 15 | { #category : #accessing } 16 | MAMemoDescription class >> label [ 17 | ^ 'Memo' 18 | ] 19 | 20 | { #category : #visiting } 21 | MAMemoDescription >> acceptMagritte: aVisitor [ 22 | aVisitor visitMemoDescription: self 23 | ] 24 | 25 | { #category : #'acessing-magritte' } 26 | MAMemoDescription >> descriptionLineCount [ 27 | 28 | ^ MANumberDescription new 29 | accessor: #lineCount; 30 | label: 'Number of Lines'; 31 | priority: 400; 32 | default: self class defaultLineCount; 33 | beInteger; 34 | min: 1; 35 | yourself 36 | ] 37 | 38 | { #category : #'accessing-properties' } 39 | MAMemoDescription >> lineCount [ 40 | ^ self propertyAt: #lineCount ifAbsent: [ self class defaultLineCount ] 41 | ] 42 | 43 | { #category : #'accessing-properties' } 44 | MAMemoDescription >> lineCount: anInteger [ 45 | self propertyAt: #lineCount put: anInteger 46 | ] 47 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAMemoryFileModel.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I represent a file using a ByteArray in the object memory. I am not practicable for big files: use me for development and testing only. 3 | " 4 | Class { 5 | #name : #MAMemoryFileModel, 6 | #superclass : #MAFileModel, 7 | #instVars : [ 8 | 'contents' 9 | ], 10 | #category : 'Magritte-Model-Models' 11 | } 12 | 13 | { #category : #comparing } 14 | MAMemoryFileModel >> = anObject [ 15 | ^ super = anObject and: [ self contents = anObject contents ] 16 | ] 17 | 18 | { #category : #accessing } 19 | MAMemoryFileModel >> contents [ 20 | ^ contents ifNil: [ contents := ByteArray new ] 21 | ] 22 | 23 | { #category : #accessing } 24 | MAMemoryFileModel >> contents: aByteArray [ 25 | super contents: aByteArray. 26 | contents := aByteArray asByteArray 27 | ] 28 | 29 | { #category : #initialization } 30 | MAMemoryFileModel >> finalize [ 31 | super finalize. 32 | contents := nil 33 | ] 34 | 35 | { #category : #comparing } 36 | MAMemoryFileModel >> hash [ 37 | ^ super hash bitXor: self contents hash 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAMultipleErrors.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever there are multiple validation rules failing. 3 | " 4 | Class { 5 | #name : #MAMultipleErrors, 6 | #superclass : #MAValidationError, 7 | #instVars : [ 8 | 'collection' 9 | ], 10 | #category : 'Magritte-Model-Exception' 11 | } 12 | 13 | { #category : #'instance creation' } 14 | MAMultipleErrors class >> description: aDescription errors: aCollection signal: aString [ 15 | ^ self new 16 | setDescription: aDescription; 17 | setCollection: aCollection; 18 | signal: aString; 19 | yourself 20 | ] 21 | 22 | { #category : #accessing } 23 | MAMultipleErrors >> collection [ 24 | ^ collection 25 | ] 26 | 27 | { #category : #printing } 28 | MAMultipleErrors >> printOn: aStream [ 29 | self collection 30 | do: [ :each | aStream print: each ] 31 | separatedBy: [ aStream nextPut: Character cr ] 32 | ] 33 | 34 | { #category : #initialization } 35 | MAMultipleErrors >> setCollection: aCollection [ 36 | collection := aCollection 37 | ] 38 | -------------------------------------------------------------------------------- /source/Magritte-Model/MANegationCondition.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MANegationCondition, 3 | #superclass : #MACondition, 4 | #instVars : [ 5 | 'condition' 6 | ], 7 | #category : 'Magritte-Model-Utility' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | MANegationCondition class >> with: aCondition [ 12 | ^ self new initializeWith: aCondition 13 | ] 14 | 15 | { #category : #initialization } 16 | MANegationCondition >> initializeWith: aCondition [ 17 | condition := aCondition 18 | ] 19 | 20 | { #category : #evaluating } 21 | MANegationCondition >> value: anObject [ 22 | ^ (condition value: anObject) not 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPasswordDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of a password string, possible values are instances of ==String==. My visual representation could be a password field, where there are stars printed instead of the characters the user enters. 3 | " 4 | Class { 5 | #name : #MAPasswordDescription, 6 | #superclass : #MAStringDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #accessing } 11 | MAPasswordDescription class >> label [ 12 | ^ 'Password' 13 | ] 14 | 15 | { #category : #visiting } 16 | MAPasswordDescription >> acceptMagritte: aVisitor [ 17 | aVisitor visitPasswordDescription: self 18 | ] 19 | 20 | { #category : #testing } 21 | MAPasswordDescription >> isObfuscated: anObject [ 22 | ^ anObject notNil 23 | and: [ anObject isString 24 | and: [ anObject isEmpty not 25 | and: [ anObject allSatisfy: [ :each | each = $* ] ] ] ] 26 | ] 27 | 28 | { #category : #testing } 29 | MAPasswordDescription >> isSortable [ 30 | ^ false 31 | ] 32 | 33 | { #category : #operators } 34 | MAPasswordDescription >> obfuscated: anObject [ 35 | ^ String new: (self toString: anObject) size withAll: $* 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPluggableCondition.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPluggableCondition, 3 | #superclass : #MACondition, 4 | #instVars : [ 5 | 'receiver', 6 | 'selector', 7 | 'arguments', 8 | 'index' 9 | ], 10 | #category : 'Magritte-Model-Utility' 11 | } 12 | 13 | { #category : #initialization } 14 | MAPluggableCondition >> initializeReceiver: anObject selector: aSelector arguments: anArray index: anInteger [ 15 | receiver := anObject. 16 | selector := aSelector. 17 | arguments := anArray. 18 | index := anInteger 19 | ] 20 | 21 | { #category : #evaluating } 22 | MAPluggableCondition >> value: anObject [ 23 | | actualReceiver actualArguments | 24 | actualReceiver := index = 0 25 | ifFalse: [ receiver ] 26 | ifTrue: [ anObject ]. 27 | actualArguments := index > 0 28 | ifFalse: [ arguments ] 29 | ifTrue: [ 30 | arguments copy 31 | at: index put: anObject; 32 | yourself ]. 33 | ^ actualReceiver 34 | perform: selector 35 | withArguments: actualArguments 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPriorityContainer.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a container holding a collection of descriptions and I keep them sorted according to their priority. 3 | " 4 | Class { 5 | #name : #MAPriorityContainer, 6 | #superclass : #MAContainer, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAPriorityContainer class >> defaultCollection [ 12 | ^ SortedCollection new 13 | ] 14 | 15 | { #category : #visiting } 16 | MAPriorityContainer >> acceptMagritte: aVisitor [ 17 | aVisitor visitPriorityContainer: self 18 | ] 19 | 20 | { #category : #moving } 21 | MAPriorityContainer >> moveDown: aDescription [ 22 | self shouldNotImplement 23 | ] 24 | 25 | { #category : #moving } 26 | MAPriorityContainer >> moveUp: aDescription [ 27 | self shouldNotImplement 28 | ] 29 | 30 | { #category : #actions } 31 | MAPriorityContainer >> resort [ 32 | self setChildren: self children copy 33 | ] 34 | 35 | { #category : #initialization } 36 | MAPriorityContainer >> setChildren: aCollection [ 37 | super setChildren: aCollection asSortedCollection 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPropertyAccessor.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I access an MAObject's properties. 3 | 4 | Note that my lineage might a bit confusing because my superclass is used when a model object *is* a dictionary, but I access a dictionary *contained by* a model object. 5 | " 6 | Class { 7 | #name : #MAPropertyAccessor, 8 | #superclass : #MADictionaryAccessor, 9 | #category : #'Magritte-Model-Accessor' 10 | } 11 | 12 | { #category : #model } 13 | MAPropertyAccessor >> read: aModel [ 14 | ^ aModel propertyAt: self key ifAbsent: [ nil ] 15 | ] 16 | 17 | { #category : #model } 18 | MAPropertyAccessor >> write: anObject to: aModel [ 19 | aModel propertyAt: self key put: anObject 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPropertyChangedAnnouncement.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPropertyChangedAnnouncement, 3 | #superclass : #Announcement, 4 | #instVars : [ 5 | 'key', 6 | 'value', 7 | 'owner' 8 | ], 9 | #category : #'Magritte-Model-Core' 10 | } 11 | 12 | { #category : #accessing } 13 | MAPropertyChangedAnnouncement >> key [ 14 | ^ key 15 | ] 16 | 17 | { #category : #accessing } 18 | MAPropertyChangedAnnouncement >> key: anObject [ 19 | key := anObject 20 | ] 21 | 22 | { #category : #accessing } 23 | MAPropertyChangedAnnouncement >> owner [ 24 | ^ owner 25 | ] 26 | 27 | { #category : #accessing } 28 | MAPropertyChangedAnnouncement >> owner: anObject [ 29 | owner := anObject 30 | ] 31 | 32 | { #category : #accessing } 33 | MAPropertyChangedAnnouncement >> value [ 34 | ^ value 35 | ] 36 | 37 | { #category : #accessing } 38 | MAPropertyChangedAnnouncement >> value: anObject [ 39 | value := anObject 40 | ] 41 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAPropertyError.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPropertyError, 3 | #superclass : #MAError, 4 | #category : 'Magritte-Model-Exception' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Model/MARangeError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever a described value is out of bounds. 3 | " 4 | Class { 5 | #name : #MARangeError, 6 | #superclass : #MAValidationError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAReadError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that gets raised when there is problem reading serialized data. 3 | " 4 | Class { 5 | #name : #MAReadError, 6 | #superclass : #MAError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAReader.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAReader, 3 | #superclass : #MAStreamingVisitor, 4 | #category : 'Magritte-Model-Visitor' 5 | } 6 | 7 | { #category : #'instance creation' } 8 | MAReader class >> read: aStream description: aDescription [ 9 | ^ self new read: aStream description: aDescription 10 | ] 11 | 12 | { #category : #private } 13 | MAReader >> error: aString [ 14 | MAReadError signal: aString 15 | ] 16 | 17 | { #category : #visiting } 18 | MAReader >> read: aStream description: aDescription [ 19 | self 20 | stream: aStream; 21 | visit: aDescription. 22 | ^ self object 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Model/MARequiredError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that is raised whenever a required value is not supplied. 3 | " 4 | Class { 5 | #name : #MARequiredError, 6 | #superclass : #MAValidationError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MASortBlock.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MASortBlock, 3 | #superclass : #MABasicObject, 4 | #instVars : [ 5 | 'accessor', 6 | 'selector' 7 | ], 8 | #category : 'Magritte-Model-Utility' 9 | } 10 | 11 | { #category : #'instance creation' } 12 | MASortBlock class >> accessor: anAccessor selector: aSelector [ 13 | ^ self basicNew initializeAccessor: anAccessor selector: aSelector 14 | ] 15 | 16 | { #category : #'instance creation' } 17 | MASortBlock class >> selector: aSelector [ 18 | ^ self 19 | accessor: MAIdentityAccessor new 20 | selector: aSelector 21 | ] 22 | 23 | { #category : #actions } 24 | MASortBlock >> fixTemps [ 25 | ] 26 | 27 | { #category : #initialization } 28 | MASortBlock >> initializeAccessor: anAccessor selector: aSelector [ 29 | accessor := anAccessor asAccessor. 30 | selector := aSelector 31 | ] 32 | 33 | { #category : #evaluating } 34 | MASortBlock >> value: aFirstObject value: aSecondObject [ 35 | ^ (accessor read: aFirstObject) 36 | perform: selector 37 | with: (accessor read: aSecondObject) 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAStraightMemento.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a memento that forwards read- and write-access directly to the model. I can mostly be replaced with the model itself. 3 | " 4 | Class { 5 | #name : #MAStraightMemento, 6 | #superclass : #MAMemento, 7 | #category : #'Magritte-Model-Memento' 8 | } 9 | 10 | { #category : #testing } 11 | MAStraightMemento class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #private } 16 | MAStraightMemento >> readUsing: aDescription [ 17 | ^ (self model readUsing: aDescription) 18 | ifNil: [ aDescription default ] 19 | ] 20 | 21 | { #category : #private } 22 | MAStraightMemento >> write: anObject using: aDescription [ 23 | (self shouldPush: anObject using: aDescription) ifFalse: [ ^ self ]. 24 | self model write: anObject using: aDescription 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAStreamingVisitor.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAStreamingVisitor, 3 | #superclass : #MAVisitor, 4 | #instVars : [ 5 | 'stream', 6 | 'object' 7 | ], 8 | #category : 'Magritte-Model-Visitor' 9 | } 10 | 11 | { #category : #streaming } 12 | MAStreamingVisitor >> contents [ 13 | ^ self stream contents 14 | ] 15 | 16 | { #category : #accessing } 17 | MAStreamingVisitor >> object [ 18 | ^ object 19 | ] 20 | 21 | { #category : #accessing } 22 | MAStreamingVisitor >> object: anObject [ 23 | object := anObject 24 | ] 25 | 26 | { #category : #private } 27 | MAStreamingVisitor >> object: anObject during: aBlock [ 28 | | previous | 29 | previous := self object. self object: anObject. 30 | aBlock ensure: [ self object: previous ] 31 | ] 32 | 33 | { #category : #accessing } 34 | MAStreamingVisitor >> stream [ 35 | ^ stream 36 | ] 37 | 38 | { #category : #accessing } 39 | MAStreamingVisitor >> stream: aStream [ 40 | stream := aStream 41 | ] 42 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAStringDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of strings, possible values are instances of ==String==. My visual representation could be a single line text-field. Use ==*MAMemoDescription*== for multi-line strings. 3 | " 4 | Class { 5 | #name : #MAStringDescription, 6 | #superclass : #MAElementDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MAStringDescription class >> defaultKind [ 12 | ^ String 13 | ] 14 | 15 | { #category : #testing } 16 | MAStringDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MAStringDescription class >> label [ 22 | ^ 'String' 23 | ] 24 | 25 | { #category : #visiting } 26 | MAStringDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitStringDescription: self 28 | ] 29 | 30 | { #category : #testing } 31 | MAStringDescription >> isSortable [ 32 | ^ true 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Model/MASymbolDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of symbols, possible values are instances of ==Symbol==. 3 | " 4 | Class { 5 | #name : #MASymbolDescription, 6 | #superclass : #MAStringDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MASymbolDescription class >> defaultKind [ 12 | ^ Symbol 13 | ] 14 | 15 | { #category : #accessing } 16 | MASymbolDescription class >> label [ 17 | ^ 'Symbol' 18 | ] 19 | 20 | { #category : #visiting } 21 | MASymbolDescription >> acceptMagritte: aVisitor [ 22 | aVisitor visitSymbolDescription: self 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Model/MATPropertyOwner.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MATPropertyOwner } 2 | 3 | { #category : #'*Magritte-Model' } 4 | MATPropertyOwner >> maLazyPropertyUsing: description [ 5 | "Return the current value of a field as specified by its description. See #lazilyInitializeFrom:for: comment for more info. 6 | - NB: Only works with a selector accessor with matching property e.g. (readSelector = property = #myField). It could be extended to other cases if the need arises." 7 | 8 | | currentValue | 9 | currentValue := self propertyAt: description accessor readSelector ifAbsent: [ nil ]. 10 | ^ description lazilyInitializeFrom: currentValue for: self. 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Model/MATimeDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of times, possible values are instances of ==Time==. My visual representation could be a time-picker. 3 | " 4 | Class { 5 | #name : #MATimeDescription, 6 | #superclass : #MAMagnitudeDescription, 7 | #category : #'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #'accessing-defaults' } 11 | MATimeDescription class >> defaultKind [ 12 | ^ Time 13 | ] 14 | 15 | { #category : #testing } 16 | MATimeDescription class >> isAbstract [ 17 | ^ false 18 | ] 19 | 20 | { #category : #accessing } 21 | MATimeDescription class >> label [ 22 | ^ 'Time' 23 | ] 24 | 25 | { #category : #visiting } 26 | MATimeDescription >> acceptMagritte: aVisitor [ 27 | aVisitor visitTimeDescription: self 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAToManyScalarRelationDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | Like MAToManyRelationDescription but for scalar values. 3 | " 4 | Class { 5 | #name : #MAToManyScalarRelationDescription, 6 | #superclass : #MAToManyRelationDescription, 7 | #category : 'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #accessing } 11 | MAToManyScalarRelationDescription class >> label [ 12 | ^ '1:m scalar Relation' 13 | ] 14 | 15 | { #category : #visiting } 16 | MAToManyScalarRelationDescription >> acceptMagritte: aVisitor [ 17 | aVisitor visitToManyScalarRelationDescription: self 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAToOneRelationDescription.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a description of an one-to-one relationship. 3 | " 4 | Class { 5 | #name : #MAToOneRelationDescription, 6 | #superclass : #MARelationDescription, 7 | #category : #'Magritte-Model-Description' 8 | } 9 | 10 | { #category : #testing } 11 | MAToOneRelationDescription class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #accessing } 16 | MAToOneRelationDescription class >> label [ 17 | ^ '1:1 Relation' 18 | ] 19 | 20 | { #category : #visiting } 21 | MAToOneRelationDescription >> acceptMagritte: aVisitor [ 22 | aVisitor visitToOneRelationDescription: self 23 | ] 24 | 25 | { #category : #'ToMany compatibility' } 26 | MAToOneRelationDescription >> isDefinitive [ 27 | "I'm really not sure what this does, but we need to respond to it to get MAElementRow to work, which was copied over from ToMany" 28 | ^ false 29 | ] 30 | 31 | { #category : #'ToMany compatibility' } 32 | MAToOneRelationDescription >> isOrdered [ 33 | "See #isDefinitive comment" 34 | ^ false 35 | ] 36 | 37 | { #category : #validating } 38 | MAToOneRelationDescription >> validateKind: anObject [ 39 | super validateKind: anObject. 40 | (self classes anySatisfy: [ :class | anObject species includesBehavior: class ]) 41 | ifFalse: [ MAKindError description: self signal: self kindErrorMessage ] 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAUrlDescription.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAUrlDescription, 3 | #superclass : #MAElementDescription, 4 | #category : #'Magritte-Model-Description' 5 | } 6 | 7 | { #category : #visiting } 8 | MAUrlDescription >> acceptMagritte: aVisitor [ 9 | aVisitor visitUrlDescription: self 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAValidationError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a generic validation error. I reference the description that caused the validation error. 3 | " 4 | Class { 5 | #name : #MAValidationError, 6 | #superclass : #MAError, 7 | #category : #'Magritte-Model-Exception' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | MAValidationError class >> description: aDescription signal: aString [ 12 | ^ self new 13 | setDescription: aDescription; 14 | signal: aString; 15 | yourself 16 | ] 17 | 18 | { #category : #testing } 19 | MAValidationError >> isResumable [ 20 | ^ true 21 | ] 22 | 23 | { #category : #printing } 24 | MAValidationError >> printOn: aStream [ 25 | (self tag isDescription and: [ self tag label notNil ]) 26 | ifTrue: [ aStream nextPutAll: self tag label greaseString; nextPutAll: ': ' ]. 27 | aStream nextPutAll: self messageText greaseString 28 | ] 29 | 30 | { #category : #initialization } 31 | MAValidationError >> setDescription: aDescription [ 32 | self tag: aDescription 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAValueHolder.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAValueHolder, 3 | #superclass : #MABasicObject, 4 | #instVars : [ 5 | 'contents' 6 | ], 7 | #category : 'Magritte-Model-Utility' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | MAValueHolder class >> on: anObject [ 12 | ^ self new contents: anObject 13 | ] 14 | 15 | { #category : #accessing } 16 | MAValueHolder >> contents [ 17 | ^ contents 18 | ] 19 | 20 | { #category : #accessing } 21 | MAValueHolder >> contents: anObject [ 22 | contents := anObject 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAWriteError.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am an error that gets raised when there is problem writing serialized data. 3 | " 4 | Class { 5 | #name : #MAWriteError, 6 | #superclass : #MAError, 7 | #category : 'Magritte-Model-Exception' 8 | } 9 | -------------------------------------------------------------------------------- /source/Magritte-Model/MAWriter.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAWriter, 3 | #superclass : #MAStreamingVisitor, 4 | #category : 'Magritte-Model-Visitor' 5 | } 6 | 7 | { #category : #'instance creation' } 8 | MAWriter class >> write: anObject [ 9 | ^ self new write: anObject 10 | ] 11 | 12 | { #category : #'instance creation' } 13 | MAWriter class >> write: anObject description: aDescription [ 14 | ^ self new write: anObject description: aDescription 15 | ] 16 | 17 | { #category : #'instance creation' } 18 | MAWriter class >> write: anObject description: aDescription to: aStream [ 19 | ^ self new write: anObject description: aDescription to: aStream 20 | ] 21 | 22 | { #category : #private } 23 | MAWriter >> defaultWriteStream [ 24 | self subclassResponsibility 25 | ] 26 | 27 | { #category : #private } 28 | MAWriter >> error: aString [ 29 | MAWriteError signal: aString 30 | ] 31 | 32 | { #category : #visiting } 33 | MAWriter >> write: anObject [ 34 | ^ self write: anObject description: anObject magritteDescription 35 | ] 36 | 37 | { #category : #visiting } 38 | MAWriter >> write: anObject description: aDescription [ 39 | ^ self write: anObject description: aDescription to: self defaultWriteStream 40 | ] 41 | 42 | { #category : #visiting } 43 | MAWriter >> write: anObject description: aDescription to: aStream [ 44 | self 45 | object: anObject; 46 | stream: aStream; 47 | visit: aDescription. 48 | ^ self contents 49 | ] 50 | -------------------------------------------------------------------------------- /source/Magritte-Model/ManifestMagritteModel.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I store metadata for this package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser 3 | " 4 | Class { 5 | #name : #ManifestMagritteModel, 6 | #superclass : #PackageManifest, 7 | #category : #'Magritte-Model-Manifest' 8 | } 9 | 10 | { #category : #'code-critics' } 11 | ManifestMagritteModel class >> ruleRBBadMessageRuleV1FalsePositive [ 12 | ^ #(#(#(#RGMethodDefinition #(#Object #maLazyInstVarUsing: #false)) #'2019-03-23T09:33:42.523345-04:00') ) 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Model/NumberParser.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #NumberParser } 2 | 3 | { #category : #'*Magritte-Model' } 4 | NumberParser class >> isValidNumber: aStringOrStream [ 5 | | stream parser | 6 | stream := aStringOrStream readStream. 7 | parser := (Smalltalk at: #ExtendedNumberParser ifAbsent: [self]). 8 | parser parse: stream onError: [ ^ false ]. 9 | ^ stream atEnd 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Model/SequenceableCollection.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #SequenceableCollection } 2 | 3 | { #category : #'*magritte-model' } 4 | SequenceableCollection >> asAccessor [ 5 | ^ MAChainAccessor accessors: self 6 | ] 7 | 8 | { #category : #'*magritte-model' } 9 | SequenceableCollection >> moveDown: anObject [ 10 | | first second | 11 | first := self findFirst: [ :value | value == anObject ]. 12 | second := (first > 0 and: [ first < self size ]) 13 | ifTrue: [ first + 1 ] 14 | ifFalse: [ ^ first ]. 15 | self swap: first with: second. 16 | ^ second 17 | ] 18 | 19 | { #category : #'*magritte-model' } 20 | SequenceableCollection >> moveUp: anObject [ 21 | | first second | 22 | 23 | first := self findFirst: [ :value | value == anObject ]. 24 | second := first > 1 ifTrue: [ first - 1 ] ifFalse: [ ^ first ]. 25 | self swap: first with: second. 26 | ^ second 27 | ] 28 | -------------------------------------------------------------------------------- /source/Magritte-Model/String.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #String } 2 | 3 | { #category : #'*Magritte-Model' } 4 | String >> matches: aString [ 5 | aString isEmpty ifTrue: [ ^ true ]. 6 | ^ (aString includesAnyOf: '*#') 7 | ifTrue: [ aString match: self ] 8 | ifFalse: [ self includesSubstring: aString caseSensitive: false ] 9 | ] 10 | 11 | { #category : #'*magritte-model' } 12 | String >> normalizeCamelCase [ 13 | 14 | ^ self class streamContents: [ :out | 15 | self do: [ :e | 16 | | isNewWord | 17 | isNewWord := e isUppercase and: [ out position > 0 and: [ out peekLast isUppercase not ] ]. 18 | isNewWord ifTrue: [ out nextPut: Character space ]. 19 | out nextPut: e ] ] 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Model/Symbol.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Symbol } 2 | 3 | { #category : #'*magritte-model-converting' } 4 | Symbol >> asAccessor [ 5 | ^ MASelectorAccessor selector: self 6 | ] 7 | 8 | { #category : #'*Magritte-Model' } 9 | Symbol >> optionFor: anObject ifPresent: aBlock [ 10 | aBlock value: (anObject perform: self) 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Model/UndefinedObject.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #UndefinedObject } 2 | 3 | { #category : #'*Magritte-Model' } 4 | UndefinedObject >> asAccessor [ 5 | ^ MANullAccessor new 6 | ] 7 | 8 | { #category : #'*Magritte-Model' } 9 | UndefinedObject >> label [ 10 | ^ 'n/a' 11 | ] 12 | 13 | { #category : #'*Magritte-Model' } 14 | UndefinedObject >> magritteDescription [ 15 | ^ MAContainer new 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Money/MAVisitor.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAVisitor } 2 | 3 | { #category : #'*Magritte-Money' } 4 | MAVisitor >> visitMoneyDescription: anObject [ 5 | self visitElementDescription: anObject 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Money/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Money' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Morph/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-morph' } 4 | GRPackage class >> magritteMorph [ 5 | ^ self new 6 | name: 'Magritte-Morph'; 7 | description: 'Morphic integration for the Magritte metamodel.'; 8 | addDependency: 'Magritte-Model'; 9 | url: #magritteUrl; 10 | yourself 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAActionDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAActionDescription } 2 | 3 | { #category : #'*magritte-morph' } 4 | MAActionDescription >> buttonOn: anObject [ 5 | | buttonLabel | 6 | "Copied alpha morph wrapping from TEasilyThemed. Not sure how/why it works..." 7 | buttonLabel := self icon ifNil: [ self label ] ifNotNil: [ :i | AlphaImageMorph new image: i ]. 8 | ^ Smalltalk ui theme builder 9 | newButtonFor: self 10 | getState: nil 11 | action: #performOn: 12 | arguments: {anObject} 13 | getEnabled: #isEnabled 14 | label: buttonLabel 15 | help: comment 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MABlockDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MABlockDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MABlockDescription class >> defaultMorphClasses [ 5 | ^ Array with: MAMorphicMemo 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MABooleanDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MABooleanDescription } 2 | 3 | { #category : #'*magritte-morph-default' } 4 | MABooleanDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicCheckbox with: MAMorphicSingleSelectList 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAContainer.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAContainer } 2 | 3 | { #category : #'*magritte-morph-converting' } 4 | MAContainer >> asMorphOn: anObject [ 5 | | memento | 6 | memento := anObject mementoClass 7 | model: anObject 8 | description: self. 9 | ^ self morphicClass memento: memento 10 | ] 11 | 12 | { #category : #'*Magritte-Morph' } 13 | MAContainer class >> defaultMorphicClasses [ 14 | ^ Array with: MAMorphicContainer 15 | ] 16 | 17 | { #category : #'*magritte-morph-converting' } 18 | MAContainer >> elementBuilderFor: anObject [ 19 | 20 | self flag: 'Commented out from #asMorphOn:'. 21 | "memento := anObject mementoClass 22 | model: anObject 23 | description: self." 24 | ^ self blocClass on: anObject"memento: memento" 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MADateDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADateDescription } 2 | 3 | { #category : #'*magritte-morph-default' } 4 | MADateDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicDate. 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MADirectoryDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADirectoryDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MADirectoryDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicDirectory 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAElementDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MAElementDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicText 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAFileDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAFileDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MAFileDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicFile 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMemoDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAMemoDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MAMemoDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicMemo 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicCheckbox.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicCheckbox, 3 | #superclass : #MAMorphicElement, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicCheckbox >> buildMorphView [ 9 | ^ self theme 10 | newCheckboxIn: nil 11 | for: self 12 | getSelected: #selected 13 | setSelected: #selected: 14 | getEnabled: #enabled 15 | label: '' 16 | help: self magritteDescription comment 17 | ] 18 | 19 | { #category : #actions } 20 | MAMorphicCheckbox >> enabled [ 21 | ^ true 22 | ] 23 | 24 | { #category : #actions } 25 | MAMorphicCheckbox >> selected [ 26 | ^ (self value ifNil: [ self magritteDescription default ]) ifNil: [ false ] 27 | ] 28 | 29 | { #category : #actions } 30 | MAMorphicCheckbox >> selected: aBoolean [ 31 | self value: aBoolean 32 | ] 33 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicDate.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicDate, 3 | #superclass : #MAMorphicElement, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #'private-building' } 8 | MAMorphicDate >> buildMorphView [ 9 | 10 | ^ SpDatePresenter new 11 | display: [ :e | self magritteDescription toString: e ]; 12 | date: self value; 13 | whenDateChanged: [ :newDate | self value: newDate ]; 14 | build 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicDirectory.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicDirectory, 3 | #superclass : #MAMorphicFile, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicDirectory >> choose: titleString in: defaultDirectory [ 9 | 10 | ^ UIManager default chooseDirectory: titleString from: defaultDirectory. 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicDropList.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicDropList, 3 | #superclass : #MAMorphicList, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #'private-building' } 8 | MAMorphicDropList >> buildMorphView [ 9 | 10 | ^ SpDropListPresenter new 11 | items: self options; 12 | display: [ :e | 13 | e 14 | ifNil: [ '' ] 15 | ifNotNil: [ self magritteDescription reference toString: e ] ]; 16 | selectItem: self value; 17 | whenSelectedItemChangedDo: [ :e | self value: e ]; 18 | build 19 | ] 20 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicExternalEditor.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicExternalEditor, 3 | #superclass : #MAMorphicOneToOne, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #testing } 8 | MAMorphicExternalEditor class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #actions } 13 | MAMorphicExternalEditor >> create [ 14 | self newRelation asMagritteMorph 15 | onAnswer: [ :result | result isNil ifFalse: [ self value: result ] ]; 16 | addButtons; 17 | addWindow; 18 | openInWorld 19 | ] 20 | 21 | { #category : #actions } 22 | MAMorphicExternalEditor >> edit [ 23 | self chooser: (self editorFor: self value) 24 | ] 25 | 26 | { #category : #rendering } 27 | MAMorphicExternalEditor >> renderButtonsOn: html [ 28 | html submitButton on: #remove of: self. 29 | html submitButton on: #edit of: self 30 | ] 31 | 32 | { #category : #rendering } 33 | MAMorphicExternalEditor >> renderViewerOn: html [ 34 | html render: (self reference toString: self value) 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicInternalEditor.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicInternalEditor, 3 | #superclass : #MAMorphicOneToOne, 4 | #instVars : [ 5 | 'component' 6 | ], 7 | #category : #'Magritte-Morph-Model' 8 | } 9 | 10 | { #category : #testing } 11 | MAMorphicInternalEditor class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #private } 16 | MAMorphicInternalEditor >> buildComponent [ 17 | ^ self value isNil ifFalse: [ 18 | (self magritteDescription reference asComponentOn: self value) 19 | setParent: self; 20 | yourself ] 21 | ] 22 | 23 | { #category : #accessing } 24 | MAMorphicInternalEditor >> children [ 25 | ^ Array with: self component 26 | ] 27 | 28 | { #category : #accessing } 29 | MAMorphicInternalEditor >> component [ 30 | ^ component ifNil: [ component := self buildComponent ] 31 | ] 32 | 33 | { #category : #actions } 34 | MAMorphicInternalEditor >> create [ 35 | self value: self newRelation. 36 | component := nil 37 | ] 38 | 39 | { #category : #rendering } 40 | MAMorphicInternalEditor >> renderViewerOn: html [ 41 | html render: (self component 42 | readOnly: self isReadOnly; 43 | yourself) 44 | ] 45 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicList.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicList, 3 | #superclass : #MAMorphicElement, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #'accessing-dynamic' } 8 | MAMorphicList >> options [ 9 | ^ self magritteDescription allOptions 10 | ] 11 | 12 | { #category : #'accessing-dynamic' } 13 | MAMorphicList >> strings [ 14 | ^ self options collect: [ :each | self magritteDescription reference toString: each ] 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicMemo.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicMemo, 3 | #superclass : #MAMorphicText, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #accessing } 8 | MAMorphicMemo >> annotation [ 9 | ^ self string 10 | ] 11 | 12 | { #category : #private } 13 | MAMorphicMemo >> buildMorphView [ 14 | "The selector #annotation should be #string instead, but we use this one and dispatch since this prevents morphic to draw a thin red border around changed fields. Stupid hack, really, but doesn't work otherwise." 15 | 16 | | result lineSpacingFactor height | 17 | result := RubPluggableTextMorph on: self text: #annotation accept: #string: readSelection: nil menu: nil. 18 | 19 | "We want to set the height to honor the #lineCount from the description, but PluggableTextMorph doesn't seem to have an API to get the height of a hypothetical block of text e.g. 5 lines in the current font. So we work out an approximation as follows..." 20 | lineSpacingFactor := 1.1. "This seems to account well for space between lines" 21 | height := (self magritteDescription lineCount * result font height * lineSpacingFactor) + (result borderWidth * 2). 22 | 23 | ^ result 24 | height: height; 25 | hResizing: #spaceFill; 26 | borderColor: #inset; 27 | borderWidth: 1 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicMultiSelectList.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicMultiSelectList, 3 | #superclass : #MAMorphicList, 4 | #instVars : [ 5 | 'selected' 6 | ], 7 | #category : #'Magritte-Morph-Model' 8 | } 9 | 10 | { #category : #private } 11 | MAMorphicMultiSelectList >> buildMorphView [ 12 | ^ (PluggableListMorph on: self list: #strings primarySelection: #selected changePrimarySelection: #selected: listSelection: #selectionAt: changeListSelection: #selectionAt:put: menu: nil) 13 | hResizing: #spaceFill; 14 | borderColor: #inset; 15 | borderWidth: 1; 16 | beMultipleSelection; 17 | yourself 18 | ] 19 | 20 | { #category : #accessing } 21 | MAMorphicMultiSelectList >> selected [ 22 | ^ selected ifNil: [ selected := 0 ] 23 | ] 24 | 25 | { #category : #accessing } 26 | MAMorphicMultiSelectList >> selected: anInteger [ 27 | selected := anInteger. 28 | self changed: #selected 29 | ] 30 | 31 | { #category : #accessing } 32 | MAMorphicMultiSelectList >> selectionAt: anInteger [ 33 | ^ self value includes: (self options at: anInteger) 34 | ] 35 | 36 | { #category : #accessing } 37 | MAMorphicMultiSelectList >> selectionAt: anInteger put: aBoolean [ 38 | | option | 39 | option := self options at: anInteger. 40 | self value: (aBoolean 41 | ifTrue: [ self value copyWith: option ] 42 | ifFalse: [ self value copyWithout: option ]). 43 | self changed: #selected 44 | ] 45 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicOneToOne.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicOneToOne, 3 | #superclass : #MAMorphicRelation, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicOneToOne >> buildMorphView [ 9 | 10 | | table | 11 | table := self rectangleMorph 12 | listDirection: #topToBottom; 13 | yourself. 14 | self value 15 | ifNotNil: [ MAElementRow addMorphFor: self value of: self to: table ] 16 | ifNil: [ self addSelectListTo: table ]. 17 | ^ table. 18 | ] 19 | 20 | { #category : #private } 21 | MAMorphicOneToOne >> buildSelectButton [ 22 | ^ self theme builder 23 | newButtonFor: self 24 | action: #create 25 | label: 'Create' 26 | help: '' 27 | ] 28 | 29 | { #category : #actions } 30 | MAMorphicOneToOne >> create [ 31 | self subclassResponsibility 32 | ] 33 | 34 | { #category : #removing } 35 | MAMorphicOneToOne >> remove: anObject [ 36 | self value: nil 37 | ] 38 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicPassword.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicPassword, 3 | #superclass : #MAMorphicText, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicPassword >> buildMorphView [ 9 | ^ super buildMorphView 10 | font: (StrikeFont passwordFontSize: 12); 11 | yourself 12 | ] 13 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicSilentContainer.class.st: -------------------------------------------------------------------------------- 1 | " 2 | The only difference to the superclass is that on answer it does not delete the morph. This is useful when we want the morph to be embedded. 3 | " 4 | Class { 5 | #name : #MAMorphicSilentContainer, 6 | #superclass : #MAMorphicContainer, 7 | #category : #'Magritte-Morph-Model' 8 | } 9 | 10 | { #category : #answering } 11 | MAMorphicSilentContainer >> answer: anObject [ 12 | answerBlock isNil 13 | ifFalse: [ answerBlock value: anObject ]. 14 | ] 15 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicSingleSelectList.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicSingleSelectList, 3 | #superclass : #MAMorphicList, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicSingleSelectList >> buildMorphView [ 9 | ^ (PluggableListMorph on: self list: #strings selected: #selected changeSelected: #selected:) 10 | hResizing: #spaceFill; 11 | borderColor: #inset; 12 | borderWidth: 1; 13 | yourself 14 | ] 15 | 16 | { #category : #accessing } 17 | MAMorphicSingleSelectList >> selected [ 18 | ^ self options indexOf: self value 19 | ] 20 | 21 | { #category : #accessing } 22 | MAMorphicSingleSelectList >> selected: anInteger [ 23 | self value: (self options at: anInteger ifAbsent: [ nil ]). 24 | self changed: #selected 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicText.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicText, 3 | #superclass : #MAMorphicElement, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAMorphicText >> buildMorphView [ 9 | ^ self theme 10 | newTextEntryIn: nil 11 | for: self 12 | get: #string 13 | set: #string: 14 | class: String 15 | getEnabled: #enabled 16 | help: self magritteDescription comment 17 | ] 18 | 19 | { #category : #accessing } 20 | MAMorphicText >> enabled [ 21 | 22 | ^ self magritteDescription readOnly not 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMorphicTokenCompletion.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMorphicTokenCompletion, 3 | #superclass : #MAMorphicList, 4 | #category : #'Magritte-Morph-Model' 5 | } 6 | 7 | { #category : #'private-building' } 8 | MAMorphicTokenCompletion >> buildMorphView [ 9 | 10 | self flag: 'Obviously, the inline conditionals are horrifying. I think the nil check will go away if we set a default value'. 11 | ^ TokenCollectorMorph new 12 | hResizing: #spaceFill; 13 | vResizing: #rigid; 14 | borderColor: #inset; 15 | borderWidth: 1; 16 | options: self options; 17 | objects: (self magritteDescription isMultiple 18 | ifTrue: [ self value copy ] 19 | ifFalse: [ self value copy ifNotNil: [ :v | { v } ] ifNil: [ OrderedCollection new ] ]); 20 | whenObjectsChanged: [ :e | 21 | self magritteDescription isMultiple 22 | ifTrue: [ self value: e ] 23 | ifFalse: [ self value: e first ] ]; 24 | factory: self magritteDescription initializer; 25 | height: 150; 26 | yourself 27 | ] 28 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAMultipleOptionDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAMultipleOptionDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MAMultipleOptionDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicTokenCompletion with: MAMorphicMultiSelectList 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAPasswordDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAPasswordDescription } 2 | 3 | { #category : #'*magritte-morph-default' } 4 | MAPasswordDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicPassword 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MARelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MARelationDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MARelationDescription >> descriptionClassesWithMorphic: description [ 5 | 6 | ^ description 7 | morphicClass: MAMorphicTokenCompletion; 8 | yourself 9 | ] 10 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MASingleOptionDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MASingleOptionDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MASingleOptionDescription class >> defaultMorphicClasses [ 5 | ^ Array 6 | with: MAMorphicSingleSelectList 7 | with: MAMorphicDropList 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAToManyRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAToManyRelationDescription } 2 | 3 | { #category : #'*magritte-morph-defaults' } 4 | MAToManyRelationDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicOneToMany 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MAToOneRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAToOneRelationDescription } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MAToOneRelationDescription class >> defaultMorphicClasses [ 5 | ^ Array with: MAMorphicExternalEditor with: MAMorphicInternalEditor 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Morph/MorphicUIManager.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MorphicUIManager } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | MorphicUIManager >> chooseFile: windowTitle in: directoryString [ 5 | | chooser | 6 | chooser := FileDialogWindow newWithTheme: Smalltalk ui theme. 7 | chooser 8 | title: windowTitle; 9 | selectDirectory: directoryString; 10 | answerFileEntry. 11 | ^ chooser openModal answer 12 | ifNotNil: [ :answer | answer asFileReference ] 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Morph/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | Object >> asMagritteMorph [ 5 | ^ self magritteDescription asMorphOn: self 6 | ] 7 | 8 | { #category : #'*Magritte-Morph' } 9 | Object >> maEdit [ 10 | 11 | self maEditAnswering: [ :editedObj | ] 12 | ] 13 | 14 | { #category : #'*Magritte-Morph' } 15 | Object >> maEditAnswering: aBlock [ 16 | 17 | self asMagritteMorph 18 | addButtons; 19 | addWindow; 20 | onAnswer: aBlock; 21 | openInWorld. 22 | ] 23 | 24 | { #category : #'*Magritte-Morph' } 25 | Object >> magritteActionButtons [ 26 | ^ self magritteActions collect: [ :e | e buttonOn: self ]. 27 | ] 28 | -------------------------------------------------------------------------------- /source/Magritte-Morph/SpDatePresenter.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #SpDatePresenter } 2 | 3 | { #category : #'*Magritte-Morph' } 4 | SpDatePresenter >> whenDateChanged: aBlock [ 5 | 6 | self flag: 7 | 'Hotfix for broken Spec2 method. Remove this method and let it be replaced by original Spec2 one once it is fixed in Spec2 and the fix is properly applied in all relevant versions of Pharo. See https://github.com/pharo-spec/Spec/issues/1302'. 8 | 9 | dateModel whenTextChangedDo: [ :newText :oldText | 10 | | oldDate | 11 | oldDate := date. 12 | date := newText 13 | ifNotEmpty: [ Date readFrom: newText readStream ] 14 | ifEmpty: [ nil ]. 15 | aBlock cull: date cull: oldDate ] 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Morph/TokenMorph.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #TokenMorph, 3 | #superclass : #Morph, 4 | #instVars : [ 5 | 'object' 6 | ], 7 | #category : #'Magritte-Morph-Morphs' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | TokenMorph class >> on: anObject [ 12 | 13 | ^ self new 14 | object: anObject; 15 | yourself 16 | ] 17 | 18 | { #category : #accessing } 19 | TokenMorph >> initialize [ 20 | super initialize. 21 | self roundedCorners: #(1 2 3 4). "Seems to do nothing" 22 | self 23 | color: 24 | self theme buttonColor; 25 | changeTableLayout; 26 | vResizing: #shrinkWrap; 27 | hResizing: #shrinkWrap; 28 | layoutInset: 5 @ 1 29 | ] 30 | 31 | { #category : #accessing } 32 | TokenMorph >> object [ 33 | ^ object 34 | ] 35 | 36 | { #category : #accessing } 37 | TokenMorph >> object: anObject [ 38 | object := anObject. 39 | self removeAllMorphs. 40 | self addMorph: object asString asMorph 41 | ] 42 | -------------------------------------------------------------------------------- /source/Magritte-Morph/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Morph' } 2 | -------------------------------------------------------------------------------- /source/Magritte-NotGToolkit/Symbol.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Symbol } 2 | 3 | { #category : #'*Magritte-NotGToolkit' } 4 | Symbol >> cull: receiverObject cull: argumentObject [ 5 | ^ receiverObject perform: self withEnoughArguments: { argumentObject } 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-NotGToolkit/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-NotGToolkit' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-pharo-model' } 4 | GRPackage class >> magrittePharoModel [ 5 | ^ self new 6 | name: 'Magritte-Pharo-Model'; 7 | addDependency: 'Magritte-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Model/MorphicUIManager.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MorphicUIManager } 2 | 3 | { #category : #'*Magritte-Pharo-Model' } 4 | MorphicUIManager >> chooseFile: windowTitle in: directoryString [ 5 | 6 | | chooser | 7 | chooser := FileDialogWindow newWithTheme: UITheme current. 8 | chooser 9 | title: windowTitle; 10 | selectDirectory: directoryString; 11 | answerFileEntry. 12 | ^ chooser openModal answer ifNotNil: [ :answer | answer asFileReference ]. 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Pharo-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Seaside/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-pharo-seaside' } 4 | GRPackage class >> magrittePharoSeaside [ 5 | ^ self new 6 | name: 'Magritte-Pharo-Seaside'; 7 | addDependency: 'Magritte-Seaside'; 8 | addDependency: 'Magritte-Pharo-Model'; 9 | addDependency: 'Seaside-Pharo-Canvas'; 10 | url: #magritteUrl; 11 | yourself 12 | ] 13 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Seaside/MAExternalFileModel.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAExternalFileModel } 2 | 3 | { #category : #'*magritte-pharo-seaside-accessing' } 4 | MAExternalFileModel >> url [ 5 | ^ self baseUrl isNil 6 | ifTrue: [ super url ] 7 | ifFalse: [ self baseUrl , '/' , (self location reduce: [ :a :b | a , '/' , b ]) , '/' , self filename ] 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Seaside/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Pharo-Seaside' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/MAClassRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAClassRefactoring, 3 | #superclass : #RBClassRefactoring, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #transforming } 8 | MAClassRefactoring >> descriptionMethodRename [ 9 | | class | 10 | class := self classObjectFor: className asSymbol. 11 | (class selectors detect: [ :each | each = #description ] ifNone: [ nil ]) notNil ifTrue: [ 12 | self performComponentRefactoring: (MADescriptionRenameRefactoring forClass: class) ] 13 | ] 14 | 15 | { #category : #preconditions } 16 | MAClassRefactoring >> preconditions [ 17 | ^ RBCondition empty 18 | ] 19 | 20 | { #category : #accessing } 21 | MAClassRefactoring >> refactorings [ 22 | | class | 23 | class := self theClass. 24 | ^ class selectors select: #isDescriptionSelector thenCollect: [ :each | 25 | MAMethodRefactoring 26 | model: self model 27 | swapMethod: each 28 | in: class ] 29 | ] 30 | 31 | { #category : #accessing } 32 | MAClassRefactoring >> theClass [ 33 | | class | 34 | class := self classObjectFor: className asSymbol. 35 | ^ class isMeta ifFalse: [ class theMetaClass ] ifTrue: [ class ] 36 | ] 37 | 38 | { #category : #transforming } 39 | MAClassRefactoring >> transform [ 40 | self descriptionMethodRename. 41 | self refactorings do: [ :each | self performComponentRefactoring: each ] 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/MADescriptionRenameRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADescriptionRenameRefactoring, 3 | #superclass : #RBMethodRefactoring, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #initialization } 8 | MADescriptionRenameRefactoring class >> forClass: class [ 9 | ^ self new 10 | class: class 11 | yourself 12 | ] 13 | 14 | { #category : #accessing } 15 | MADescriptionRenameRefactoring >> class: aClass [ 16 | class := aClass 17 | ] 18 | 19 | { #category : #preconditions } 20 | MADescriptionRenameRefactoring >> preconditions [ 21 | ^ RBCondition empty 22 | ] 23 | 24 | { #category : #transforming } 25 | MADescriptionRenameRefactoring >> transform [ 26 | | selector target parseTree | 27 | parseTree := class parseTreeFor: #description. 28 | parseTree selector: #magritteDescription. 29 | class compile: (parseTree formattedCode) classified: 'acessing-magritte'. 30 | class removeMethod: #description. 31 | ] 32 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/MAPackageRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPackageRefactoring, 3 | #superclass : #RBRefactoring, 4 | #instVars : [ 5 | 'classes' 6 | ], 7 | #category : 'Magritte-Pharo-Tools' 8 | } 9 | 10 | { #category : #initialization } 11 | MAPackageRefactoring class >> model: model classes: classes [ 12 | ^ self new 13 | model: model; 14 | classes: classes; 15 | yourself 16 | ] 17 | 18 | { #category : #accessing } 19 | MAPackageRefactoring >> classes [ 20 | ^ classes 21 | ] 22 | 23 | { #category : #accessing } 24 | MAPackageRefactoring >> classes: anObject [ 25 | classes := anObject 26 | ] 27 | 28 | { #category : #preconditions } 29 | MAPackageRefactoring >> preconditions [ 30 | ^ RBCondition empty 31 | ] 32 | 33 | { #category : #transforming } 34 | MAPackageRefactoring >> transform [ 35 | self classes 36 | collect: [ :each | MAClassRefactoring model: self model className: each ] 37 | thenDo: [ :each | self performComponentRefactoring: each ] 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/ORCmdMagritteDescriptionUpdate.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #ORCmdMagritteDescriptionUpdate, 3 | #superclass : #ORCmdMethodRefactoring, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #accessing } 8 | ORCmdMagritteDescriptionUpdate >> label [ 9 | ^ 'Update Magritte description' 10 | ] 11 | 12 | { #category : #accessing } 13 | ORCmdMagritteDescriptionUpdate >> longDescription [ 14 | ^ 'Move Magritte description to instance side and convert to use pragmas.' 15 | ] 16 | 17 | { #category : #accessing } 18 | ORCmdMagritteDescriptionUpdate >> refactoring [ 19 | ^ MAMethodRefactoring 20 | model: self model 21 | swapMethod: self currentNode selector 22 | in: self currentNode theClass 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/ORCmdMagritteDescriptionsClassUpdate.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #ORCmdMagritteDescriptionsClassUpdate, 3 | #superclass : #ORCmdClassRefactoring, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #accessing } 8 | ORCmdMagritteDescriptionsClassUpdate >> label [ 9 | ^ 'Update Magritte descriptions' 10 | ] 11 | 12 | { #category : #accessing } 13 | ORCmdMagritteDescriptionsClassUpdate >> longDescription [ 14 | ^ 'Move Magritte descriptions to instance side and convert to use pragmas.' 15 | ] 16 | 17 | { #category : #accessing } 18 | ORCmdMagritteDescriptionsClassUpdate >> refactoring [ 19 | ^ MAClassRefactoring model: self model className: self currentNode theClass name 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/ORCmdMagritteDescriptionsPackageUpdate.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #ORCmdMagritteDescriptionsPackageUpdate, 3 | #superclass : #ORCmdRefactoring, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #accessing } 8 | ORCmdMagritteDescriptionsPackageUpdate >> cluster [ 9 | ^ #Refactor 10 | ] 11 | 12 | { #category : #accessing } 13 | ORCmdMagritteDescriptionsPackageUpdate >> group [ 14 | ^ #open 15 | ] 16 | 17 | { #category : #testing } 18 | ORCmdMagritteDescriptionsPackageUpdate >> isActive [ 19 | ^ super isActive and: [ self currentNode isKindOf: OBClassCategoryNode ] 20 | ] 21 | 22 | { #category : #accessing } 23 | ORCmdMagritteDescriptionsPackageUpdate >> label [ 24 | ^ 'Update Magritte descriptions' 25 | ] 26 | 27 | { #category : #accessing } 28 | ORCmdMagritteDescriptionsPackageUpdate >> longDescription [ 29 | ^ 'Move Magritte descriptions to instance side and convert to use pragmas.' 30 | ] 31 | 32 | { #category : #accessing } 33 | ORCmdMagritteDescriptionsPackageUpdate >> refactoring [ 34 | ^ MAPackageRefactoring model: self model classes: (self currentNode classes collect: [ :each | each theClass name ]) 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/ORCmdMagritteDescriptionsPackageUpdateWrapper.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #ORCmdMagritteDescriptionsPackageUpdateWrapper, 3 | #superclass : #ORCmdOpen, 4 | #category : 'Magritte-Pharo-Tools' 5 | } 6 | 7 | { #category : #'instance creation' } 8 | ORCmdMagritteDescriptionsPackageUpdateWrapper class >> on: target for: requestor [ 9 | ^ ORCmdMagritteDescriptionsPackageUpdate new setTarget: target requestor: requestor 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Pharo-Tools/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Pharo-Tools' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pharo3-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*Magritte-Pharo3-Model' } 4 | GRPackage class >> magrittePharoModel [ 5 | ^ self new 6 | name: 'Magritte-Pharo-Model'; 7 | addDependency: 'Magritte-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Pharo3-Model/MAFileSystem.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileSystem, 3 | #superclass : #Object, 4 | #category : 'Magritte-Pharo3-Model' 5 | } 6 | 7 | { #category : #paths } 8 | MAFileSystem class >> extensionFor: aString [ 9 | 10 | ^ aString asFileReference extension. 11 | ] 12 | 13 | { #category : #entries } 14 | MAFileSystem class >> fileSizeFor: filenameString [ 15 | ^ filenameString asFileReference size 16 | ] 17 | 18 | { #category : #paths } 19 | MAFileSystem class >> fullNameFor: aString [ 20 | 21 | ^ aString asFileReference fullName. 22 | ] 23 | 24 | { #category : #locations } 25 | MAFileSystem class >> imageDirectory [ 26 | 27 | ^ FileLocator imageDirectory. 28 | ] 29 | 30 | { #category : #'mime types' } 31 | MAFileSystem class >> mimeTypesForExtension: aString [ 32 | 33 | | types | 34 | types := MIMEType forExtensionReturnMimeTypesOrNil: aString. 35 | ^ types ifNotNil: [ types collect: [ :e | e asString ] ]. 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-Pharo3-Model/MorphicUIManager.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MorphicUIManager } 2 | 3 | { #category : #'*Magritte-Pharo3-Model' } 4 | MorphicUIManager >> chooseFile: windowTitle in: directoryString [ 5 | 6 | | chooser | 7 | chooser := FileDialogWindow newWithTheme: UITheme current. 8 | chooser 9 | title: windowTitle; 10 | selectDirectory: directoryString; 11 | answerFileEntry. 12 | ^ chooser openModal answer ifNotNil: [ :answer | answer asFileReference ]. 13 | ] 14 | -------------------------------------------------------------------------------- /source/Magritte-Pharo3-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Pharo3-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pharo7-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*Magritte-Pharo7-Model' } 4 | GRPackage class >> magrittePharoModel [ 5 | ^ self new 6 | name: 'Magritte-Pharo-Model'; 7 | addDependency: 'Magritte-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Pharo7-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Pharo7-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/Collection.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'Collection' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | Collection >> maPillarPushTo: stack do: aBlock [ 5 | self do: [ :e | 6 | stack top add: e. 7 | stack push: e ]. 8 | aBlock value. 9 | self size timesRepeat: [ stack pop ] 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'MAElementDescription' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | MAElementDescription >> pillarFor: anObject [ 5 | ^ PRText content: (self toString: (self read: anObject)) 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/MAToManyRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'MAToManyRelationDescription' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | MAToManyRelationDescription >> pillarFor: anObject [ 5 | | doc elements | 6 | doc := PRTable new. 7 | elements := self read: anObject. 8 | elements do: [ :e | 9 | | cell row | 10 | cell := PRTableCell new. 11 | row := PRTableRow new 12 | add: cell; 13 | yourself. 14 | MAPillarRenderer new 15 | object: e; 16 | renderOn: cell. 17 | doc add: row ]. 18 | ^ doc. 19 | 20 | "Implementation note: tried implementing as `MAPillarRenderer >> #visitToManyRelationDescription:`, but then it wasn't straightforward to reuse other common logic e.g. all elements need a label and then a control rendered" 21 | ] 22 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/MAToOneRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'MAToOneRelationDescription' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | MAToOneRelationDescription >> pillarFor: anObject [ 5 | | container | 6 | "Implementation note: A bit hackish maybe, but renderOn: needs a parent on which to render, so we make a document and then discard it" 7 | container := PRDocument new. 8 | MAPillarRenderer new 9 | object: (self read: anObject); 10 | renderOn: container. 11 | ^ container children first 12 | ] 13 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/MAUrlDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'MAUrlDescription' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | MAUrlDescription >> pillarFor: anObject [ 5 | ^ PRExternalLink new reference: (self toString: (self read: anObject)) 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'Object' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | Object >> maPillar [ 5 | | doc | 6 | doc := PRDocument new. 7 | self maPillarRenderer renderOn: doc. 8 | ^ doc 9 | ] 10 | 11 | { #category : '*Magritte-Pillar' } 12 | Object >> maPillarRenderer [ 13 | ^ MAPillarRenderer new 14 | object: self; 15 | yourself 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/PRDocumentItem.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : 'PRDocumentItem' } 2 | 3 | { #category : '*Magritte-Pillar' } 4 | PRDocumentItem >> maPillarPushTo: stack do: aBlock [ 5 | stack top add: self. 6 | stack push: self. 7 | aBlock value. 8 | stack pop 9 | ] 10 | -------------------------------------------------------------------------------- /source/Magritte-Pillar/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : 'Magritte-Pillar' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-seaside' } 4 | GRPackage class >> magritteSeaside [ 5 | ^ self new 6 | name: 'Magritte-Seaside'; 7 | description: 'Seaside integration for the Magritte metamodel.'; 8 | addDependency: 'Magritte-Model'; 9 | addDependency: 'Seaside-Component'; 10 | addDependency: 'Seaside-Canvas'; 11 | "MADescriptionEditor registers itself as an example application" 12 | addDependency: 'Seaside-Tools-Core'; 13 | url: #magritteUrl; 14 | yourself 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAActionColumn.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAActionColumn, 3 | #superclass : #MAColumn, 4 | #category : 'Magritte-Seaside-Report' 5 | } 6 | 7 | { #category : #'accessing-defaults' } 8 | MAActionColumn >> defaultLabel [ 9 | ^ String new 10 | ] 11 | 12 | { #category : #'accessing-defaults' } 13 | MAActionColumn >> defaultUseLinks [ 14 | ^ true 15 | ] 16 | 17 | { #category : #rendering } 18 | MAActionColumn >> renderCellContent: anObject on: html [ 19 | self useLinks 20 | ifTrue: [ self renderCellLinkContent: anObject on: html ] 21 | ifFalse: [ self renderCellFormContent: anObject on: html ] 22 | ] 23 | 24 | { #category : #rendering } 25 | MAActionColumn >> renderCellFormContent: anObject on: html [ 26 | self subclassResponsibility 27 | ] 28 | 29 | { #category : #rendering } 30 | MAActionColumn >> renderCellLinkContent: anObject on: html [ 31 | self subclassResponsibility 32 | ] 33 | 34 | { #category : #accessing } 35 | MAActionColumn >> useLinks [ 36 | ^ self propertyAt: #useLinks ifAbsent: [ self defaultUseLinks ] 37 | ] 38 | 39 | { #category : #accessing } 40 | MAActionColumn >> useLinks: aBoolean [ 41 | self propertyAt: #useLinks put: aBoolean 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MABooleanDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MABooleanDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MABooleanDescription class >> defaultComponentClasses [ 5 | ^ Array with: MACheckboxComponent with: MASelectListComponent with: MARadioGroupComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MACheckboxColumn.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MACheckboxColumn, 3 | #superclass : #MASelectionColumn, 4 | #category : 'Magritte-Seaside-Report' 5 | } 6 | 7 | { #category : #'accessing-defaults' } 8 | MACheckboxColumn >> defaultSelection [ 9 | ^ Set new 10 | ] 11 | 12 | { #category : #'accessing-defaults' } 13 | MACheckboxColumn >> defaultStringDeselected [ 14 | ^ self webdings: 'c' 15 | ] 16 | 17 | { #category : #'accessing-defaults' } 18 | MACheckboxColumn >> defaultStringSelected [ 19 | ^ self webdings: 'g' 20 | ] 21 | 22 | { #category : #actions } 23 | MACheckboxColumn >> deselectRow: anObject [ 24 | self selection remove: anObject ifAbsent: nil 25 | ] 26 | 27 | { #category : #testing } 28 | MACheckboxColumn >> isSelected: anObject [ 29 | ^ self selection includes: anObject 30 | ] 31 | 32 | { #category : #rendering } 33 | MACheckboxColumn >> renderCellFormContent: anObject on: html [ 34 | html checkbox 35 | value: (self isSelected: anObject); 36 | callback: [ :value | self selectRow: anObject value: value ] 37 | ] 38 | 39 | { #category : #actions } 40 | MACheckboxColumn >> selectRow: anObject [ 41 | self selection add: anObject 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MACheckboxComponent.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I'm a seaside component used to display MABooleanDescription. If I'm writeable (readonly property of my description to false) I display a checkbox otherwise, I display a string: 'yes' if true, 'no' if false', '' if nil. 3 | " 4 | Class { 5 | #name : #MACheckboxComponent, 6 | #superclass : #MAElementComponent, 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #testing } 11 | MACheckboxComponent class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #testing } 16 | MACheckboxComponent >> hasLabelId [ 17 | ^ true 18 | ] 19 | 20 | { #category : #rendering } 21 | MACheckboxComponent >> renderEditorOn: html [ 22 | html label: [ 23 | html checkbox 24 | id: self labelId; 25 | disabled: self isReadOnly; 26 | on: #value of: self. 27 | html space; render: self magritteDescription checkboxLabel ] 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAClassDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAClassDescription } 2 | 3 | { #category : #'*magritte-seaside-accessing-defaults' } 4 | MAClassDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAComponent, 3 | #superclass : #WAComponent, 4 | #category : 'Magritte-Seaside-Core' 5 | } 6 | 7 | { #category : #'error handling' } 8 | MAComponent class >> defaultErrorClass [ 9 | ^ MAError 10 | ] 11 | 12 | { #category : #testing } 13 | MAComponent class >> isAbstract [ 14 | ^ true 15 | ] 16 | 17 | { #category : #'instance creation' } 18 | MAComponent class >> new [ 19 | "Create a new instance of the receiving component class and checks if it is not abstract." 20 | 21 | self isAbstract 22 | ifTrue: [ self error: self name , ' is abstract.' ]. 23 | ^ super new 24 | ] 25 | 26 | { #category : #reflection } 27 | MAComponent class >> withAllConcreteClasses [ 28 | ^ Array streamContents: [ :stream | 29 | self withAllConcreteClassesDo: [ :each | 30 | stream nextPut: each ] ] 31 | ] 32 | 33 | { #category : #reflection } 34 | MAComponent class >> withAllConcreteClassesDo: aBlock [ 35 | self withAllSubclassesDo: [ :each | 36 | each isAbstract ifFalse: [ 37 | aBlock value: each ] ] 38 | ] 39 | 40 | { #category : #accessing } 41 | MAComponent >> ajaxId [ 42 | ^ self ajaxId: String new 43 | ] 44 | 45 | { #category : #accessing } 46 | MAComponent >> ajaxId: aSymbol [ 47 | ^ String streamContents: [ :stream | 48 | stream 49 | nextPutAll: 'ajax'; 50 | nextPutAll: self class name; 51 | print: self hash; 52 | nextPutAll: aSymbol ] 53 | ] 54 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAComponentDecoration.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAComponentDecoration, 3 | #superclass : #WADecoration, 4 | #category : 'Magritte-Seaside-Decorations' 5 | } 6 | 7 | { #category : #defaults } 8 | MAComponentDecoration class >> defaultErrorClass [ 9 | ^ MAError 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAContainer.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAContainer } 2 | 3 | { #category : #'*magritte-seaside-converting' } 4 | MAContainer >> asComponentOn: anObject [ 5 | ^ self componentClass 6 | memento: (anObject mementoClass 7 | model: anObject 8 | description: self) 9 | ] 10 | 11 | { #category : #'*magritte-seaside-accessing' } 12 | MAContainer >> componentRenderer [ 13 | ^ self propertyAt: #componentRenderer ifAbsent: [ self class defaultComponentRenderer ] 14 | ] 15 | 16 | { #category : #'*magritte-seaside-accessing' } 17 | MAContainer >> componentRenderer: aClass [ 18 | self propertyAt: #componentRenderer put: aClass 19 | ] 20 | 21 | { #category : #'*magritte-seaside-defaults' } 22 | MAContainer class >> defaultComponentClasses [ 23 | ^ Array with: MAContainerComponent 24 | ] 25 | 26 | { #category : #'*magritte-seaside-defaults' } 27 | MAContainer class >> defaultComponentRenderer [ 28 | ^ MATableRenderer 29 | ] 30 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MACssRenderer.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MACssRenderer, 3 | #superclass : #MAComponentRenderer, 4 | #category : 'Magritte-Seaside-Renderer' 5 | } 6 | 7 | { #category : #rendering } 8 | MACssRenderer >> renderContainer: aDescription [ 9 | html definitionList 10 | class: (self classFor: aDescription); 11 | with: [ super renderContainer: aDescription ] 12 | ] 13 | 14 | { #category : #rendering } 15 | MACssRenderer >> renderControl: aDescription [ 16 | html definitionData 17 | class: (self classFor: aDescription); 18 | with: [ super renderControl: aDescription ] 19 | ] 20 | 21 | { #category : #rendering } 22 | MACssRenderer >> renderGroup: aDescription [ 23 | super renderGroup: aDescription. 24 | group isNil ifTrue: [ ^ self ]. 25 | html definitionTerm 26 | class: 'group'; 27 | with: group 28 | ] 29 | 30 | { #category : #rendering } 31 | MACssRenderer >> renderLabel: aDescription [ 32 | html definitionTerm 33 | title: aDescription comment; 34 | class: (self classFor: aDescription); 35 | with: [ super renderLabel: aDescription ] 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADateAndTimeDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADateAndTimeDescription } 2 | 3 | { #category : #'*magritte-seaside' } 4 | MADateAndTimeDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATimeStampInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADateDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADateDescription } 2 | 3 | { #category : #'*magritte-seaside' } 4 | MADateDescription class >> defaultComponentClasses [ 5 | ^ Array with: MADateInputComponent with: MADateSelectorComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADateInputComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADateInputComponent, 3 | #superclass : #MATextInputComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #actions } 8 | MADateInputComponent >> choose [ 9 | | calendar | 10 | calendar := WAMiniCalendar new. 11 | calendar 12 | date: ((self value notNil 13 | and: [ self magritteDescription isSatisfiedBy: self value ]) 14 | ifFalse: [ Date current ] 15 | ifTrue: [ self value ]); 16 | selectBlock: [ :value | calendar answer: value ]; 17 | canSelectBlock: [ :value | self magritteDescription isSatisfiedBy: value ]. 18 | self chooser: calendar 19 | ] 20 | 21 | { #category : #rendering } 22 | MADateInputComponent >> renderButtonOn: html [ 23 | html submitButton on: #choose of: self 24 | ] 25 | 26 | { #category : #actions } 27 | MADateInputComponent >> today [ 28 | | calendar | 29 | calendar := WAMiniCalendar new. 30 | calendar 31 | date: ((self value notNil 32 | and: [ self magritteDescription isSatisfiedBy: self value ]) 33 | ifFalse: [ Date current ] 34 | ifTrue: [ self value ]); 35 | selectBlock: [ :value | calendar answer: value ]; 36 | canSelectBlock: [ :value | self magritteDescription isSatisfiedBy: value ]. 37 | self chooser: calendar 38 | ] 39 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADateSelectorComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADateSelectorComponent, 3 | #superclass : #MADateInputComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #testing } 8 | MADateSelectorComponent class >> isAbstract [ 9 | ^false 10 | ] 11 | 12 | { #category : #rendering } 13 | MADateSelectorComponent >> renderButtonOn: html [ 14 | ] 15 | 16 | { #category : #rendering } 17 | MADateSelectorComponent >> renderInputOn: html [ 18 | html dateInput 19 | value: self value; 20 | callback: [ :value | self value: value ] 21 | ] 22 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADescribedComponentColumn.class.st: -------------------------------------------------------------------------------- 1 | " 2 | This column uses the component of a description to render the cell value. 3 | " 4 | Class { 5 | #name : #MADescribedComponentColumn, 6 | #superclass : #MADescribedColumn, 7 | #instVars : [ 8 | 'component' 9 | ], 10 | #category : 'Magritte-Seaside-Report' 11 | } 12 | 13 | { #category : #readme } 14 | MADescribedComponentColumn >> NOW [ 15 | " very experimental ... use only if you're willing to fix bugs 16 | this only works for readonly views without callbacks 17 | on the positive side: only one component per column is created " 18 | ] 19 | 20 | { #category : #accessing } 21 | MADescribedComponentColumn >> component [ 22 | component isNil ifTrue: [ 23 | component := self magritteDescription componentClass new 24 | setDescription: self magritteDescription; 25 | yourself ]. 26 | ^component 27 | ] 28 | 29 | { #category : #rendering } 30 | MADescribedComponentColumn >> renderCellContent: anObject on: html [ 31 | self component setMemento: (anObject mementoClass 32 | model: anObject 33 | description: self magritteDescription asContainer). 34 | self component renderViewerOn: html 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADescribedScalarColumn.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADescribedScalarColumn, 3 | #superclass : #MADescribedColumn, 4 | #category : 'Magritte-Seaside-Report' 5 | } 6 | 7 | { #category : #rendering } 8 | MADescribedScalarColumn >> renderCellContent: anObject on: html [ 9 | html render: (self magritteDescription reference toString: (self valueFor: anObject)) 10 | ] 11 | 12 | { #category : #actions } 13 | MADescribedScalarColumn >> valueFor: aRow [ 14 | ^aRow 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MADurationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MADurationDescription } 2 | 3 | { #category : #'*magritte-seaside' } 4 | MADurationDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAElementDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAElementDescription } 2 | 3 | { #category : #'*magritte-seaside-accessing' } 4 | MAElementDescription >> checkboxLabel [ 5 | ^ self propertyAt: #checkboxLabel ifAbsent: [ self label ] 6 | ] 7 | 8 | { #category : #'*magritte-seaside-accessing' } 9 | MAElementDescription >> checkboxLabel: aString [ 10 | self propertyAt: #checkboxLabel put: aString 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAExternalEditorComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAExternalEditorComponent, 3 | #superclass : #MAOneToOneComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #testing } 8 | MAExternalEditorComponent class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #actions } 13 | MAExternalEditorComponent >> create [ 14 | self chooser: (self editorFor: self selected new) 15 | ] 16 | 17 | { #category : #actions } 18 | MAExternalEditorComponent >> edit [ 19 | self chooser: (self editorFor: self value) 20 | ] 21 | 22 | { #category : #rendering } 23 | MAExternalEditorComponent >> renderButtonsOn: html [ 24 | html submitButton on: #remove of: self. 25 | html submitButton on: #edit of: self 26 | ] 27 | 28 | { #category : #rendering } 29 | MAExternalEditorComponent >> renderViewerOn: html [ 30 | html render: (self reference toString: self value) 31 | ] 32 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAFileDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAFileDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MAFileDescription class >> defaultComponentClasses [ 5 | ^ Array with: MAFileUploadComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAFileModel.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAFileModel } 2 | 3 | { #category : #'*magritte-seaside-rendering' } 4 | MAFileModel >> renderOn: html [ 5 | "Renders a download link of the receiver." 6 | 7 | html anchor 8 | title: (String streamContents: [ :stream | 9 | stream nextPutAll: self filename; nextPutAll: ' ('. 10 | stream nextPutAll: self filesize asFileSize; nextPutAll: ', '. 11 | stream nextPutAll: self mimetype; nextPut: $) ]); 12 | url: self url; 13 | with: self filename 14 | ] 15 | 16 | { #category : #'*magritte-seaside-accessing' } 17 | MAFileModel >> url [ 18 | "Answer a link to a request handler for the given file." 19 | | handler | 20 | handler := MAFileModelHandler on: self. 21 | ^ WACurrentRequestContext value registry 22 | register: handler; 23 | urlFor: handler 24 | ] 25 | 26 | { #category : #'*magritte-seaside-accessing' } 27 | MAFileModel >> urlFor: aRenderContext [ 28 | self 29 | greaseDeprecatedApi: 'MAFileModel>>#urlFor:' 30 | details: 'Use MAFileModel>>#url.'. 31 | ^ self url 32 | ] 33 | 34 | { #category : #'*magritte-seaside-accessing' } 35 | MAFileModel >> urlOn: html [ 36 | self 37 | greaseDeprecatedApi: 'MAFileModel>>#urlOn:' 38 | details: 'Use MAFileModel>>#url.'. 39 | ^ self url 40 | ] 41 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAFileModelHandler.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileModelHandler, 3 | #superclass : #WARequestHandler, 4 | #instVars : [ 5 | 'model' 6 | ], 7 | #category : 'Magritte-Seaside-Core' 8 | } 9 | 10 | { #category : #'error handling' } 11 | MAFileModelHandler class >> defaultErrorClass [ 12 | ^ MAError 13 | ] 14 | 15 | { #category : #'instance creation' } 16 | MAFileModelHandler class >> on: aFileModel [ 17 | ^ self new initializeOn: aFileModel 18 | ] 19 | 20 | { #category : #comparing } 21 | MAFileModelHandler >> = aHandler [ 22 | ^ self species = aHandler species and: [ self model = aHandler model ] 23 | ] 24 | 25 | { #category : #processing } 26 | MAFileModelHandler >> handleFiltered: aRequestContext [ 27 | | response mimeType | 28 | response := aRequestContext response. 29 | mimeType := self model mimetype seasideMimeType. 30 | response 31 | binary; 32 | cacheForever; 33 | contentType: mimeType; 34 | headerAt: 'Content-Disposition' put: 'inline; filename="' , self model filename , '"'. 35 | response 36 | nextPutAll: self model contents; 37 | respond 38 | ] 39 | 40 | { #category : #comparing } 41 | MAFileModelHandler >> hash [ 42 | ^ self model hash 43 | ] 44 | 45 | { #category : #initialization } 46 | MAFileModelHandler >> initializeOn: aFileModel [ 47 | model := aFileModel 48 | ] 49 | 50 | { #category : #accessing } 51 | MAFileModelHandler >> model [ 52 | ^ model 53 | ] 54 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAFormDecoration.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I surround the owning component with a XHTML form element and render the form buttons. 3 | " 4 | Class { 5 | #name : #MAFormDecoration, 6 | #superclass : #MAContainerDecoration, 7 | #instVars : [ 8 | 'buttons' 9 | ], 10 | #category : 'Magritte-Seaside-Decorations' 11 | } 12 | 13 | { #category : #'instance creation' } 14 | MAFormDecoration class >> buttons: aCollection [ 15 | ^ self new 16 | addButtons: aCollection; 17 | yourself 18 | ] 19 | 20 | { #category : #actions } 21 | MAFormDecoration >> addButton: aSymbol [ 22 | self addButton: aSymbol label: (self labelForSelector: aSymbol) 23 | ] 24 | 25 | { #category : #actions } 26 | MAFormDecoration >> addButton: aSymbolOrOneArgumentBlock label: aString [ 27 | self buttons add: aSymbolOrOneArgumentBlock -> aString 28 | ] 29 | 30 | { #category : #actions } 31 | MAFormDecoration >> addButtons: aCollection [ 32 | aCollection do: [ :each | 33 | each isVariableBinding 34 | ifFalse: [ self addButton: each ] 35 | ifTrue: [ self addButton: each key label: each value ] ] 36 | ] 37 | 38 | { #category : #accessing } 39 | MAFormDecoration >> buttons [ 40 | ^ buttons 41 | ] 42 | 43 | { #category : #accessing } 44 | MAFormDecoration >> buttons: aCollection [ 45 | buttons := aCollection 46 | ] 47 | 48 | { #category : #initialization } 49 | MAFormDecoration >> initialize [ 50 | super initialize. 51 | self buttons: OrderedCollection new 52 | ] 53 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAIndexedCommandColumn.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAIndexedCommandColumn, 3 | #superclass : #MACommandColumn, 4 | #category : 'Magritte-Seaside-Report' 5 | } 6 | 7 | { #category : #'accessing-defaults' } 8 | MAIndexedCommandColumn >> defaultFormat [ 9 | ^ MessageSend receiver: self selector: #renderCellContent:on:index: 10 | ] 11 | 12 | { #category : #rendering } 13 | MAIndexedCommandColumn >> renderCellContent: anObject on: html index: anInteger [ 14 | self commands 15 | do: [ :each | 16 | html anchor 17 | callback: [ each key valueWithArguments: (Array 18 | with: anObject 19 | with: anInteger) ]; 20 | with: each value ] 21 | separatedBy: [ html space ] 22 | ] 23 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAInternalEditorComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAInternalEditorComponent, 3 | #superclass : #MAOneToOneComponent, 4 | #instVars : [ 5 | 'component' 6 | ], 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #testing } 11 | MAInternalEditorComponent class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #private } 16 | MAInternalEditorComponent >> buildComponent [ 17 | ^ self value isNil ifFalse: [ 18 | (self magritteDescription reference asComponentOn: self value) 19 | setParent: self; 20 | yourself ] 21 | ] 22 | 23 | { #category : #accessing } 24 | MAInternalEditorComponent >> children [ 25 | ^ Array with: self component 26 | ] 27 | 28 | { #category : #accessing } 29 | MAInternalEditorComponent >> component [ 30 | ^ component ifNil: [ component := self buildComponent ] 31 | ] 32 | 33 | { #category : #actions } 34 | MAInternalEditorComponent >> create [ 35 | self value: self selected new. 36 | component := nil 37 | ] 38 | 39 | { #category : #rendering } 40 | MAInternalEditorComponent >> renderViewerOn: html [ 41 | html render: (self component 42 | readOnly: self isReadOnly; 43 | yourself) 44 | ] 45 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAMemoDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAMemoDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MAMemoDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextAreaComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAMultipleErrors.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAMultipleErrors } 2 | 3 | { #category : #'*magritte-seaside-rendering' } 4 | MAMultipleErrors >> renderOn: html [ 5 | html unorderedList: [ 6 | self collection 7 | do: [ :each | html listItem: each ] ] 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAMultipleOptionDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAMultipleOptionDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MAMultipleOptionDescription class >> defaultComponentClasses [ 5 | ^ Array with: MAMultiselectListComponent with: MACheckboxGroupComponent with: MAListCompositionComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAMultiselectListComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMultiselectListComponent, 3 | #superclass : #MAMultipleSelectionComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #testing } 8 | MAMultiselectListComponent class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #testing } 13 | MAMultiselectListComponent >> isDistinct [ 14 | ^ true 15 | ] 16 | 17 | { #category : #rendering } 18 | MAMultiselectListComponent >> renderEditorOn: html [ 19 | html multiSelect 20 | size: 8; 21 | id: self labelId; 22 | list: self availableList; 23 | selected: self selectedList; 24 | labels: [ :value | self labelForOption: value ]; 25 | callback: [ :value | self value: value ] 26 | ] 27 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MANumberDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MANumberDescription } 2 | 3 | { #category : #'*magritte-seaside' } 4 | MANumberDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextInputComponent with: MARangeComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAOneToOneComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAOneToOneComponent, 3 | #superclass : #MARelationComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #actions } 8 | MAOneToOneComponent >> create [ 9 | self subclassResponsibility 10 | ] 11 | 12 | { #category : #actions } 13 | MAOneToOneComponent >> remove [ 14 | self value: nil 15 | ] 16 | 17 | { #category : #rendering } 18 | MAOneToOneComponent >> renderButtonsOn: html [ 19 | ] 20 | 21 | { #category : #rendering } 22 | MAOneToOneComponent >> renderEditorOn: html [ 23 | self value isNil 24 | ifTrue: [ self renderSelectListOn: html ] 25 | ifFalse: [ self renderViewerOn: html; renderButtonsOn: html ] 26 | ] 27 | 28 | { #category : #'rendering-tools' } 29 | MAOneToOneComponent >> renderSelectButtonOn: html [ 30 | html submitButton on: #create of: self 31 | ] 32 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAOptionComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAOptionComponent, 3 | #superclass : #MAElementComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #private } 8 | MAOptionComponent >> labelForOption: anObject [ 9 | ^ self magritteDescription labelForOption: anObject 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAPasswordDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAPasswordDescription } 2 | 3 | { #category : #'*magritte-seaside-default' } 4 | MAPasswordDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextPasswordComponent with: MAVerifiedPasswordComponent with: MATextInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MARelationComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MARelationComponent, 3 | #superclass : #MAElementComponent, 4 | #instVars : [ 5 | 'selected' 6 | ], 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #'accessing-dynamic' } 11 | MARelationComponent >> classes [ 12 | ^ self magritteDescription classes 13 | ] 14 | 15 | { #category : #private } 16 | MARelationComponent >> editorFor: anObject [ 17 | ^ anObject asComponent 18 | addValidatedForm; 19 | yourself 20 | ] 21 | 22 | { #category : #'rendering-tools' } 23 | MARelationComponent >> renderSelectButtonOn: html [ 24 | self subclassResponsibility 25 | ] 26 | 27 | { #category : #'rendering-tools' } 28 | MARelationComponent >> renderSelectListOn: html [ 29 | self classes size > 1 ifTrue: [ 30 | html select 31 | list: self classes; 32 | selected: self selected; 33 | callback: [ :value | self selected: value ]; 34 | labels: [ :value | value label ] ]. 35 | self classes notEmpty 36 | ifTrue: [ self renderSelectButtonOn: html ] 37 | ] 38 | 39 | { #category : #accessing } 40 | MARelationComponent >> selected [ 41 | ^ selected ifNil: [ selected := self classes first ] 42 | ] 43 | 44 | { #category : #accessing } 45 | MARelationComponent >> selected: aClass [ 46 | selected := aClass 47 | ] 48 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MASelectListRowsComponent.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am similar to MASelectListComponent, but rather than displaying the options in a drop-down I display the options in a list. 3 | " 4 | Class { 5 | #name : #MASelectListRowsComponent, 6 | #superclass : #MASelectListComponent, 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #private } 11 | MASelectListRowsComponent >> itemsDisplayed [ 12 | ^ (self options size min: self maxItemsDisplayed) max: 5 13 | 14 | ] 15 | 16 | { #category : #private } 17 | MASelectListRowsComponent >> maxItemsDisplayed [ 18 | ^ self magritteDescription propertyAt: #maxItemsDisplayed ifAbsent: [ 10 ] 19 | 20 | ] 21 | 22 | { #category : #'rendering-grouped' } 23 | MASelectListRowsComponent >> renderEditorForGroupedOn: html [ 24 | html select 25 | id: self labelId; 26 | dispatchCallback; 27 | size: self itemsDisplayed; 28 | with: [ self renderGroupsOn: html ] 29 | ] 30 | 31 | { #category : #rendering } 32 | MASelectListRowsComponent >> renderEditorForUngroupedOn: html [ 33 | html select 34 | id: self labelId; 35 | list: self options; 36 | size: self itemsDisplayed; 37 | selected: self value; 38 | callback: [ :value | self value: value ]; 39 | labels: [ :value | self labelForOption: value ] 40 | ] 41 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MASingleOptionDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MASingleOptionDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MASingleOptionDescription class >> defaultComponentClasses [ 5 | ^ Array with: MASelectListComponent with: MARadioGroupComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MASingleSelectionComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MASingleSelectionComponent, 3 | #superclass : #MAOptionComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #accessing } 8 | MASingleSelectionComponent >> options [ 9 | ^ self magritteDescription allOptionsWith: self value 10 | ] 11 | 12 | { #category : #rendering } 13 | MASingleSelectionComponent >> renderViewerOn: html [ 14 | html render: (self labelForOption: self value) 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAStringDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAStringDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MAStringDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MASwitchDecoration.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I turn the owning component read-only and add an edit button. Clicking that button allows one to toggle between view and edit-mode. 3 | " 4 | Class { 5 | #name : #MASwitchDecoration, 6 | #superclass : #MAContainerDecoration, 7 | #category : 'Magritte-Seaside-Decorations' 8 | } 9 | 10 | { #category : #accessing } 11 | MASwitchDecoration >> buttons [ 12 | ^ self decoratedComponent isReadOnly 13 | ifTrue: [ Array with: #edit -> 'Edit' ] 14 | ifFalse: [ Array with: #save -> 'Save' with: #cancel -> 'Cancel' ] 15 | ] 16 | 17 | { #category : #processing } 18 | MASwitchDecoration >> handleAnswer: anObject continueWith: aBlock [ 19 | self decoratedComponent readOnly: true. 20 | super handleAnswer: anObject continueWith: aBlock 21 | ] 22 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATableDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MATableDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MATableDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATableComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATextAreaComponent.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I display an html text area for the magritte MAMemoDescription. 3 | " 4 | Class { 5 | #name : #MATextAreaComponent, 6 | #superclass : #MAElementComponent, 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #testing } 11 | MATextAreaComponent class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #testing } 16 | MATextAreaComponent >> hasLabelId [ 17 | ^ self isReadOnly not 18 | ] 19 | 20 | { #category : #rendering } 21 | MATextAreaComponent >> renderEditorOn: html [ 22 | html textArea 23 | id: self labelId; 24 | rows: self magritteDescription lineCount; 25 | on: #string of: self 26 | ] 27 | 28 | { #category : #rendering } 29 | MATextAreaComponent >> renderViewerOn: html [ 30 | (self string findTokens: Character cr) 31 | do: [ :each | html render: each ] 32 | separatedBy: [ html break ] 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATextInputComponent.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I'm a simple input box for MAStringDescription. 3 | " 4 | Class { 5 | #name : #MATextInputComponent, 6 | #superclass : #MAElementComponent, 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #testing } 11 | MATextInputComponent class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #testing } 16 | MATextInputComponent >> hasLabelId [ 17 | ^ self isReadOnly not 18 | ] 19 | 20 | { #category : #rendering } 21 | MATextInputComponent >> renderButtonOn: html [ 22 | ] 23 | 24 | { #category : #rendering } 25 | MATextInputComponent >> renderEditorOn: html [ 26 | self renderInputOn: html. 27 | self renderButtonOn: html 28 | ] 29 | 30 | { #category : #rendering } 31 | MATextInputComponent >> renderInputOn: html [ 32 | html textInput 33 | id: self labelId; 34 | on: #string of: self 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATextPasswordComponent.class.st: -------------------------------------------------------------------------------- 1 | " 2 | Password seaside component, I display stars '*' instead of the text typed by the user. My description is MAPasswordDescription. 3 | " 4 | Class { 5 | #name : #MATextPasswordComponent, 6 | #superclass : #MAElementComponent, 7 | #category : 'Magritte-Seaside-Components' 8 | } 9 | 10 | { #category : #testing } 11 | MATextPasswordComponent class >> isAbstract [ 12 | ^ false 13 | ] 14 | 15 | { #category : #testing } 16 | MATextPasswordComponent >> hasLabelId [ 17 | ^ self isReadOnly not 18 | ] 19 | 20 | { #category : #rendering } 21 | MATextPasswordComponent >> renderEditorOn: html [ 22 | html passwordInput 23 | id: self labelId; 24 | on: #string of: self 25 | ] 26 | 27 | { #category : #accessing } 28 | MATextPasswordComponent >> string [ 29 | ^ self magritteDescription obfuscated: super string 30 | ] 31 | 32 | { #category : #accessing } 33 | MATextPasswordComponent >> string: aString [ 34 | (self magritteDescription isObfuscated: aString) 35 | ifFalse: [ super string: aString ] 36 | ] 37 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATimeDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MATimeDescription } 2 | 3 | { #category : #'*magritte-seaside' } 4 | MATimeDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATimeInputComponent with: MATimeSelectorComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATimeInputComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATimeInputComponent, 3 | #superclass : #MATextInputComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #actions } 8 | MATimeInputComponent >> now [ 9 | self value: Time now 10 | ] 11 | 12 | { #category : #rendering } 13 | MATimeInputComponent >> renderButtonOn: html [ 14 | html submitButton on: #now of: self 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATimeSelectorComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATimeSelectorComponent, 3 | #superclass : #MATimeInputComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #testing } 8 | MATimeSelectorComponent class >> isAbstract [ 9 | ^false 10 | ] 11 | 12 | { #category : #rendering } 13 | MATimeSelectorComponent >> renderInputOn: html [ 14 | html timeInput 15 | withSeconds; 16 | value: self value; 17 | callback: [ :value | self value: value ] 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATimeStampInputComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATimeStampInputComponent, 3 | #superclass : #MATextInputComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #actions } 8 | MATimeStampInputComponent >> current [ 9 | self value: GRPlatform current magritteTimeStampClass current 10 | ] 11 | 12 | { #category : #rendering } 13 | MATimeStampInputComponent >> renderButtonOn: html [ 14 | html submitButton on: #current of: self 15 | ] 16 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAToManyRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAToManyRelationDescription } 2 | 3 | { #category : #'*magritte-seaside-accessing-defaults' } 4 | MAToManyRelationDescription class >> defaultComponentClasses [ 5 | ^ Array with: MAOneToManyComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAToManyScalarRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAToManyScalarRelationDescription } 2 | 3 | { #category : #'*magritte-seaside-accessing-defaults' } 4 | MAToManyScalarRelationDescription class >> defaultComponentClasses [ 5 | ^ Array with: MAOneToManyScalarComponent 6 | ] 7 | 8 | { #category : #'*magritte-seaside-accessing-defaults' } 9 | MAToManyScalarRelationDescription class >> defaultReportColumnClasses [ 10 | ^ Array with: MADescribedScalarColumn 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAToOneRelationDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MAToOneRelationDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MAToOneRelationDescription class >> defaultComponentClasses [ 5 | ^ Array with: MAExternalEditorComponent with: MAInternalEditorComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAToggleColumn.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAToggleColumn, 3 | #superclass : #MADescribedColumn, 4 | #category : 'Magritte-Seaside-Report' 5 | } 6 | 7 | { #category : #rendering } 8 | MAToggleColumn >> renderCellContent: anObject on: html [ 9 | | value | 10 | value := self valueFor: anObject. 11 | html anchor 12 | callback: [ anObject write: value not using: self magritteDescription ]; 13 | with: (self magritteDescription toString: value) 14 | ] 15 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MATokenDescription.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #MATokenDescription } 2 | 3 | { #category : #'*magritte-seaside-defaults' } 4 | MATokenDescription class >> defaultComponentClasses [ 5 | ^ Array with: MATextInputComponent 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAUndefinedComponent.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAUndefinedComponent, 3 | #superclass : #MAElementComponent, 4 | #category : 'Magritte-Seaside-Components' 5 | } 6 | 7 | { #category : #testing } 8 | MAUndefinedComponent class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #testing } 13 | MAUndefinedComponent >> hasLabelId [ 14 | ^ true 15 | ] 16 | 17 | { #category : #rendering } 18 | MAUndefinedComponent >> renderContentOn: html [ 19 | html span 20 | id: self labelId; 21 | style: 'color: red;'; 22 | with: 'Undefined Component' 23 | ] 24 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/MAValidationDecoration.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am a normally invisible component. I show a list of validation errors in case the owner component fails to validate. 3 | " 4 | Class { 5 | #name : #MAValidationDecoration, 6 | #superclass : #MAComponentDecoration, 7 | #category : 'Magritte-Seaside-Decorations' 8 | } 9 | 10 | { #category : #accessing } 11 | MAValidationDecoration >> errors [ 12 | ^ self decoratedComponent errors 13 | ] 14 | 15 | { #category : #rendering } 16 | MAValidationDecoration >> renderContentOn: html [ 17 | self errors isEmpty 18 | ifFalse: [ self renderErrorsOn: html ]. 19 | super renderContentOn: html 20 | ] 21 | 22 | { #category : #rendering } 23 | MAValidationDecoration >> renderErrorsOn: html [ 24 | html unorderedList 25 | class: 'errors'; 26 | list: self errors; 27 | with: nil 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/Object.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Object } 2 | 3 | { #category : #'*magritte-seaside-converting' } 4 | Object >> asComponent [ 5 | ^ self magritteDescription asComponentOn: self 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/Symbol.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Symbol } 2 | 3 | { #category : #'*magritte-seaside' } 4 | Symbol >> fixTemps [ 5 | ^ self 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/WAComponent.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #WAComponent } 2 | 3 | { #category : #'*magritte-seaside' } 4 | WAComponent >> isMagritteContainer [ 5 | ^ false 6 | ] 7 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/WAPresenter.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #WAPresenter } 2 | 3 | { #category : #'*magritte-seaside' } 4 | WAPresenter >> requiresMultipartForm [ 5 | "Answer true if the receiving component or one of its children requires a multipart form." 6 | 7 | ^ self children anySatisfy: [ :each | each requiresMultipartForm ] 8 | ] 9 | -------------------------------------------------------------------------------- /source/Magritte-Seaside/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Seaside' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Files-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-tests-files-model' } 4 | GRPackage class >> magritteTestsFilesModel [ 5 | ^ self new 6 | name: 'Magritte-Tests-Files-Model'; 7 | addDependency: 'Magritte-Tests-Model'; 8 | addDependency: 'Magritte-Files-Model'; 9 | url: #magritteUrl; 10 | yourself 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Files-Model/MAExternalFileModelTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAExternalFileModelTest, 3 | #superclass : #MAFileModelTest, 4 | #category : 'Magritte-Tests-Files-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAExternalFileModelTest >> actualClass [ 9 | ^ MAExternalFileModel 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Files-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Tests-Files-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Tests-GemStone-Model/MAExternalFileModelTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAExternalFileModelTest, 3 | #superclass : #MAFileModelTest, 4 | #category : 'Magritte-Tests-GemStone-Model' 5 | } 6 | 7 | { #category : #private } 8 | MAExternalFileModelTest >> actualClass [ 9 | ^ MAExternalFileModel 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Tests-GemStone-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Tests-GemStone-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-tests-model' } 4 | GRPackage class >> magritteTestsModel [ 5 | ^ self new 6 | name: 'Magritte-Tests-Model'; 7 | description: 'Unit tests for the Magritte metamodel.'; 8 | addDependency: 'Magritte-Model'; 9 | url: #magritteUrl; 10 | yourself 11 | ] 12 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAAccessorMock.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAAccessorMock, 3 | #superclass : #Object, 4 | #category : 'Magritte-Tests-Model-Accessor' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAAdaptiveModelTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAAdaptiveModelTest, 3 | #superclass : #TestCase, 4 | #instVars : [ 5 | 'scaffolder' 6 | ], 7 | #category : 'Magritte-Tests-Model-Models' 8 | } 9 | 10 | { #category : #accessing } 11 | MAAdaptiveModelTest >> descriptions [ 12 | ^ self scaffolder magritteDescription children 13 | ] 14 | 15 | { #category : #accessing } 16 | MAAdaptiveModelTest >> scaffolder [ 17 | ^ scaffolder 18 | ] 19 | 20 | { #category : #running } 21 | MAAdaptiveModelTest >> setUp [ 22 | scaffolder := MAAdaptiveModel new. 23 | scaffolder magritteDescription 24 | add: MAStringDescription new; 25 | add: MANumberDescription new. 26 | scaffolder write: 'foo' using: self descriptions first. 27 | scaffolder write: 123 using: self descriptions second 28 | ] 29 | 30 | { #category : #tests } 31 | MAAdaptiveModelTest >> testRead [ 32 | self assert: (self scaffolder readUsing: self descriptions first) = 'foo'. 33 | self assert: (self scaffolder readUsing: self descriptions second) = 123 34 | ] 35 | 36 | { #category : #tests } 37 | MAAdaptiveModelTest >> testWrite [ 38 | self scaffolder write: 'bar' using: self descriptions first. 39 | self scaffolder write: 321 using: self descriptions second. 40 | 41 | self assert: (self scaffolder readUsing: self descriptions first) = 'bar'. 42 | self assert: (self scaffolder readUsing: self descriptions second) = 321 43 | ] 44 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAClassDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAClassDescriptionTest, 3 | #superclass : #MAElementDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAClassDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAClassDescriptionTest >> actualClass [ 14 | ^ MAClassDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAClassDescriptionTest >> includedInstance [ 19 | ^ String 20 | ] 21 | 22 | { #category : #private } 23 | MAClassDescriptionTest >> nonIdenticalInstance [ 24 | "Classes cannot be copied on some platforms, so we override the inherited 25 | behaviour in order to return a different class." 26 | 27 | ^ Object 28 | ] 29 | 30 | { #category : #private } 31 | MAClassDescriptionTest >> shouldSkipStringTests [ 32 | ^ true 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAColorDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAColorDescriptionTest, 3 | #superclass : #MAElementDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAColorDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAColorDescriptionTest >> actualClass [ 14 | ^ MAColorDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAColorDescriptionTest >> includedInstance [ 19 | ^ GRPlatform current magritteColorClass blue 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MADateAndTimeDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADateAndTimeDescriptionTest, 3 | #superclass : #MAMagnitudeDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MADateAndTimeDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MADateAndTimeDescriptionTest >> actualClass [ 14 | ^ MADateAndTimeDescription 15 | ] 16 | 17 | { #category : #private } 18 | MADateAndTimeDescriptionTest >> excludedInstance [ 19 | ^ DateAndTime year: 1980 month: 1 day: 11 hour: 11 minute: 38 second: 12 20 | ] 21 | 22 | { #category : #private } 23 | MADateAndTimeDescriptionTest >> includedInstance [ 24 | ^ DateAndTime year: 1980 month: 6 day: 11 hour: 11 minute: 38 second: 12 25 | ] 26 | 27 | { #category : #private } 28 | MADateAndTimeDescriptionTest >> maxInstance [ 29 | ^ DateAndTime year: 1980 month: 6 day: 12 hour: 11 minute: 38 second: 12 30 | ] 31 | 32 | { #category : #private } 33 | MADateAndTimeDescriptionTest >> minInstance [ 34 | ^ DateAndTime year: 1980 month: 6 day: 10 hour: 11 minute: 38 second: 12 35 | ] 36 | 37 | { #category : #tests } 38 | MADateAndTimeDescriptionTest >> testDisplay [ 39 | 40 | self testDisplay: [ :e | e asDate monthName ]. 41 | self testDisplay: #monthName. 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MADateDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADateDescriptionTest, 3 | #superclass : #MAMagnitudeDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MADateDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MADateDescriptionTest >> actualClass [ 14 | ^ MADateDescription 15 | ] 16 | 17 | { #category : #private } 18 | MADateDescriptionTest >> excludedInstance [ 19 | ^ Date newDay: 1 month: (Date nameOfMonth: 6) year: 1980 20 | ] 21 | 22 | { #category : #private } 23 | MADateDescriptionTest >> includedInstance [ 24 | ^ Date newDay: 11 month: (Date nameOfMonth: 6) year: 1980 25 | ] 26 | 27 | { #category : #private } 28 | MADateDescriptionTest >> maxInstance [ 29 | ^ Date newDay: 12 month: (Date nameOfMonth: 6) year: 1980 30 | ] 31 | 32 | { #category : #private } 33 | MADateDescriptionTest >> minInstance [ 34 | ^ Date newDay: 10 month: (Date nameOfMonth: 6) year: 1980 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MADerivedDescriptions.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADerivedDescriptions, 3 | #superclass : #TestCase, 4 | #instVars : [ 5 | 'baseModel', 6 | 'derivedModel' 7 | ], 8 | #category : 'Magritte-Tests-Model-Utility' 9 | } 10 | 11 | { #category : #running } 12 | MADerivedDescriptions >> setUp [ 13 | super setUp. 14 | 15 | baseModel := MAMockAddress new. 16 | derivedModel := MAMockAddress2 new. 17 | ] 18 | 19 | { #category : #tests } 20 | MADerivedDescriptions >> testContainer [ 21 | self assert: (baseModel magritteDescription hasProperty: #addressContainerBase). 22 | self assert: (derivedModel magritteDescription hasProperty: #addressContainerDerived) 23 | ] 24 | 25 | { #category : #tests } 26 | MADerivedDescriptions >> testDescription [ 27 | | baseDescription derivedDescription | 28 | 29 | baseDescription := baseModel magritteDescription detect: [ :each | each accessor selector = #street ]. 30 | self assert: baseDescription isRequired not. 31 | 32 | derivedDescription := derivedModel magritteDescription detect: [ :each | each accessor selector = #street ]. 33 | self assert: derivedDescription isRequired. 34 | 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MADurationDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MADurationDescriptionTest, 3 | #superclass : #MAMagnitudeDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MADurationDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MADurationDescriptionTest >> actualClass [ 14 | ^ MADurationDescription 15 | ] 16 | 17 | { #category : #private } 18 | MADurationDescriptionTest >> excludedInstance [ 19 | ^ Duration days: 0 hours: 0 minutes: 0 seconds: 2 20 | ] 21 | 22 | { #category : #private } 23 | MADurationDescriptionTest >> includedInstance [ 24 | ^ Duration days: 1 hours: 2 minutes: 3 seconds: 4 25 | ] 26 | 27 | { #category : #private } 28 | MADurationDescriptionTest >> maxInstance [ 29 | ^ Duration days: 2 hours: 2 minutes: 3 seconds: 4 30 | ] 31 | 32 | { #category : #private } 33 | MADurationDescriptionTest >> minInstance [ 34 | ^ Duration days: 0 hours: 2 minutes: 3 seconds: 4 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAFileDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileDescriptionTest, 3 | #superclass : #MAElementDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAFileDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAFileDescriptionTest >> actualClass [ 14 | ^ MAFileDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAFileDescriptionTest >> includedInstance [ 19 | ^ MAMemoryFileModel new 20 | contents: 'Lukas Renggli'; 21 | filename: 'author.txt'; 22 | yourself 23 | ] 24 | 25 | { #category : #private } 26 | MAFileDescriptionTest >> shouldSkipStringTests [ 27 | ^ true 28 | ] 29 | 30 | { #category : #'tests-accessing' } 31 | MAFileDescriptionTest >> testKind [ 32 | super testKind. 33 | self description kind: MAFileModelStub. 34 | self assert: self description kind = MAFileModelStub 35 | ] 36 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAFileModelStub.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAFileModelStub, 3 | #superclass : #MAFileModel, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAIdentityAccessorTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAIdentityAccessorTest, 3 | #superclass : #MAAccessorTest, 4 | #category : 'Magritte-Tests-Model-Accessor' 5 | } 6 | 7 | { #category : #testing } 8 | MAIdentityAccessorTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAIdentityAccessorTest >> accessorInstance [ 14 | ^ self actualClass new 15 | ] 16 | 17 | { #category : #private } 18 | MAIdentityAccessorTest >> actualClass [ 19 | ^ MAIdentityAccessor 20 | ] 21 | 22 | { #category : #'tests-testing' } 23 | MAIdentityAccessorTest >> testCanRead [ 24 | self assert: (self accessor canRead: self) 25 | ] 26 | 27 | { #category : #'tests-testing' } 28 | MAIdentityAccessorTest >> testCanWrite [ 29 | self deny: (self accessor canWrite: self) 30 | ] 31 | 32 | { #category : #tests } 33 | MAIdentityAccessorTest >> testRead [ 34 | self assert: (self accessor read: 123) = 123 35 | ] 36 | 37 | { #category : #tests } 38 | MAIdentityAccessorTest >> testWrite [ 39 | self 40 | should: [ self accessor write: 123 to: self ] 41 | raise: MAWriteError. 42 | self assert: self value isNil 43 | ] 44 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAMemoDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMemoDescriptionTest, 3 | #superclass : #MAStringDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #private } 8 | MAMemoDescriptionTest >> actualClass [ 9 | ^ MAMemoDescription 10 | ] 11 | 12 | { #category : #'tests-properties' } 13 | MAMemoDescriptionTest >> testLineCount [ 14 | self description lineCount: 123. 15 | self assert: self description lineCount = 123 16 | ] 17 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAMemoryFileModelTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMemoryFileModelTest, 3 | #superclass : #MAFileModelTest, 4 | #category : 'Magritte-Tests-Model-Models' 5 | } 6 | 7 | { #category : #private } 8 | MAMemoryFileModelTest >> actualClass [ 9 | ^ MAMemoryFileModel 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAMockAddress2.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMockAddress2, 3 | #superclass : #MAMockAddress, 4 | #category : 'Magritte-Tests-Model-Mocks' 5 | } 6 | 7 | { #category : #'acessing-magritte' } 8 | MAMockAddress2 >> descriptionContainer [ 9 | "this pragma #magritteContainer is optional as the pragma will be retrieved from the super class's overridden method." 10 | 11 | 12 | ^ super descriptionContainer 13 | propertyAt: #addressContainerDerived put: nil; 14 | yourself 15 | ] 16 | 17 | { #category : #'acessing-magritte' } 18 | MAMockAddress2 >> descriptionStreet [ 19 | "this pragma #magritteDescription is optional as the pragma will be retrieved from the super class's overridden method." 20 | 21 | 22 | ^ super descriptionStreet 23 | beRequired; 24 | yourself 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAMultipleOptionDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAMultipleOptionDescriptionTest, 3 | #superclass : #MAOptionDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #'accessing-default' } 8 | MAMultipleOptionDescriptionTest class >> defaultUnique [ 9 | ^ false 10 | ] 11 | 12 | { #category : #testing } 13 | MAMultipleOptionDescriptionTest class >> isAbstract [ 14 | ^ false 15 | ] 16 | 17 | { #category : #private } 18 | MAMultipleOptionDescriptionTest >> actualClass [ 19 | ^ MAMultipleOptionDescription 20 | ] 21 | 22 | { #category : #private } 23 | MAMultipleOptionDescriptionTest >> includedInstance [ 24 | ^ self optionInstances copyFrom: 1 to: 2 25 | ] 26 | 27 | { #category : #'tests-properties' } 28 | MAMultipleOptionDescriptionTest >> testOrdered [ 29 | self description beOrdered. 30 | self assert: self description isOrdered. 31 | self assert: self description ordered. 32 | 33 | self description beUnordered. 34 | self deny: self description isOrdered. 35 | self deny: self description ordered 36 | ] 37 | 38 | { #category : #'tests-properties' } 39 | MAMultipleOptionDescriptionTest >> testSorted [ 40 | self description beDistinct. 41 | self assert: self description isDistinct. 42 | self assert: self description distinct. 43 | 44 | self description beIndefinite. 45 | self deny: self description isDistinct. 46 | self deny: self description distinct 47 | ] 48 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MANullAccessorTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MANullAccessorTest, 3 | #superclass : #MAAccessorTest, 4 | #category : 'Magritte-Tests-Model-Accessor' 5 | } 6 | 7 | { #category : #testing } 8 | MANullAccessorTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MANullAccessorTest >> accessorInstance [ 14 | ^ self actualClass new 15 | ] 16 | 17 | { #category : #private } 18 | MANullAccessorTest >> actualClass [ 19 | ^ MANullAccessor 20 | ] 21 | 22 | { #category : #'tests-identity' } 23 | MANullAccessorTest >> testAsAccessor [ 24 | super testAsAccessor. 25 | self assert: (nil asAccessor isKindOf: self actualClass) 26 | ] 27 | 28 | { #category : #'tests-testing' } 29 | MANullAccessorTest >> testCanRead [ 30 | self deny: (self accessor canRead: self) 31 | ] 32 | 33 | { #category : #'tests-testing' } 34 | MANullAccessorTest >> testCanWrite [ 35 | self deny: (self accessor canWrite: nil) 36 | ] 37 | 38 | { #category : #tests } 39 | MANullAccessorTest >> testRead [ 40 | self 41 | should: [ self accessor read: self ] 42 | raise: MAReadError 43 | ] 44 | 45 | { #category : #tests } 46 | MANullAccessorTest >> testWrite [ 47 | self 48 | should: [ self accessor write: 123 to: self ] 49 | raise: MAWriteError. 50 | self assert: self value isNil 51 | ] 52 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAPasswordDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPasswordDescriptionTest, 3 | #superclass : #MAStringDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAPasswordDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAPasswordDescriptionTest >> actualClass [ 14 | ^ MAPasswordDescription 15 | ] 16 | 17 | { #category : #tests } 18 | MAPasswordDescriptionTest >> testIsObfuscated [ 19 | self deny: (self description isObfuscated: ''). 20 | self deny: (self description isObfuscated: nil). 21 | self deny: (self description isObfuscated: 123). 22 | self deny: (self description isObfuscated: '**1'). 23 | self assert: (self description isObfuscated: '******') 24 | ] 25 | 26 | { #category : #tests } 27 | MAPasswordDescriptionTest >> testObfuscated [ 28 | self assert: (self description obfuscated: nil) = ''. 29 | self assert: (self description obfuscated: 'zork') = '****'. 30 | self assert: (self description obfuscated: 'foobar') = '******' 31 | ] 32 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAPriorityContainerTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPriorityContainerTest, 3 | #superclass : #MAContainerTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAPriorityContainerTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAPriorityContainerTest >> actualClass [ 14 | ^ MAPriorityContainer 15 | ] 16 | 17 | { #category : #'tests-moving' } 18 | MAPriorityContainerTest >> testMoveDown [ 19 | self should: [ super testMoveDown ] raise: Error 20 | ] 21 | 22 | { #category : #'tests-moving' } 23 | MAPriorityContainerTest >> testMoveUp [ 24 | self should: [ super testMoveUp ] raise: Error 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAReferenceDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAReferenceDescriptionTest, 3 | #superclass : #MAElementDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAReferenceDescriptionTest class >> isAbstract [ 9 | ^ true 10 | ] 11 | 12 | { #category : #private } 13 | MAReferenceDescriptionTest >> actualClass [ 14 | ^ MAReferenceDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAReferenceDescriptionTest >> referenceInstance [ 19 | ^ MAStringDescription new 20 | ] 21 | 22 | { #category : #running } 23 | MAReferenceDescriptionTest >> setUp [ 24 | super setUp. 25 | self description reference: self referenceInstance. 26 | self assert: self description reference accessor notNil 27 | ] 28 | 29 | { #category : #'tests-copying' } 30 | MAReferenceDescriptionTest >> testCopyReference [ 31 | self assert: self description copy reference = self description reference. 32 | self deny: self description copy reference == self description reference 33 | ] 34 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MARelationDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MARelationDescriptionTest, 3 | #superclass : #MAReferenceDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MARelationDescriptionTest class >> isAbstract [ 9 | ^ true 10 | ] 11 | 12 | { #category : #private } 13 | MARelationDescriptionTest >> actualClass [ 14 | ^ MARelationDescription 15 | ] 16 | 17 | { #category : #private } 18 | MARelationDescriptionTest >> addressInstance1 [ 19 | ^ MAMockAddress new 20 | street: 'Tillierstrasse 17'; 21 | plz: 3005; place: 'Bern'; 22 | yourself 23 | ] 24 | 25 | { #category : #private } 26 | MARelationDescriptionTest >> addressInstance2 [ 27 | ^ MAMockAddress new 28 | street: 'In der Au'; 29 | plz: 8765; place: 'Engi'; 30 | yourself 31 | ] 32 | 33 | { #category : #running } 34 | MARelationDescriptionTest >> setUp [ 35 | super setUp. 36 | self description 37 | reference: MAMockAddress magritteDescription; 38 | classes: (Array with: MAMockAddress) 39 | ] 40 | 41 | { #category : #private } 42 | MARelationDescriptionTest >> shouldSkipStringTests [ 43 | ^ true 44 | ] 45 | 46 | { #category : #'tests-copying' } 47 | MARelationDescriptionTest >> testCopyClasses [ 48 | self assert: self description copy classes = self description classes. 49 | self deny: self description copy classes == self description classes 50 | ] 51 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAStringDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAStringDescriptionTest, 3 | #superclass : #MAElementDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAStringDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAStringDescriptionTest >> actualClass [ 14 | ^ MAStringDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAStringDescriptionTest >> includedInstance [ 19 | ^ 'Lukas Renggli' 20 | ] 21 | 22 | { #category : #tests } 23 | MAStringDescriptionTest >> testDisplay [ 24 | 25 | self testDisplay: [ :e | e asString allButLast: 2 ]. 26 | self testDisplay: #asString. "Since #asString is the default behavior, this is only showing an example of the API, not actually testing anything. In real use, you might send e.g. #allButLast" 27 | ] 28 | 29 | { #category : #'tests-strings' } 30 | MAStringDescriptionTest >> testFromStringInvalid [ 31 | "There is no invalid string input." 32 | ] 33 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MASymbolDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MASymbolDescriptionTest, 3 | #superclass : #MAStringDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MASymbolDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MASymbolDescriptionTest >> actualClass [ 14 | ^ MASymbolDescription 15 | ] 16 | 17 | { #category : #private } 18 | MASymbolDescriptionTest >> includedInstance [ 19 | ^ #magritte 20 | ] 21 | 22 | { #category : #'tests-validation' } 23 | MASymbolDescriptionTest >> testValidateConditions [ 24 | ] 25 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MATableDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATableDescriptionTest, 3 | #superclass : #MAReferenceDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MATableDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MATableDescriptionTest >> actualClass [ 14 | ^ MATableDescription 15 | ] 16 | 17 | { #category : #private } 18 | MATableDescriptionTest >> includedInstance [ 19 | ^ MATableModel rows: 3 columns: 3 contents: #( '1' '2' '3' '2' '4' '6' '3' '6' '9' ) 20 | ] 21 | 22 | { #category : #private } 23 | MATableDescriptionTest >> shouldSkipStringTests [ 24 | ^ true 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MATimeDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATimeDescriptionTest, 3 | #superclass : #MAMagnitudeDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MATimeDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MATimeDescriptionTest >> actualClass [ 14 | ^ MATimeDescription 15 | ] 16 | 17 | { #category : #private } 18 | MATimeDescriptionTest >> excludedInstance [ 19 | ^ Time hour: 9 minute: 33 second: 12 20 | ] 21 | 22 | { #category : #private } 23 | MATimeDescriptionTest >> includedInstance [ 24 | ^ Time hour: 11 minute: 33 second: 12 25 | ] 26 | 27 | { #category : #private } 28 | MATimeDescriptionTest >> maxInstance [ 29 | ^ Time hour: 12 minute: 33 second: 12 30 | ] 31 | 32 | { #category : #private } 33 | MATimeDescriptionTest >> minInstance [ 34 | ^ Time hour: 10 minute: 33 second: 12 35 | ] 36 | 37 | { #category : #tests } 38 | MATimeDescriptionTest >> testDisplay [ 39 | 40 | self testDisplay: [ :e | e hour asString ]. 41 | self testDisplay: #print24. 42 | ] 43 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAToManyScalarRelationDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAToManyScalarRelationDescriptionTest, 3 | #superclass : #MAToManyRelationDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #private } 8 | MAToManyScalarRelationDescriptionTest >> actualClass [ 9 | ^ MAToManyScalarRelationDescription 10 | ] 11 | 12 | { #category : #private } 13 | MAToManyScalarRelationDescriptionTest >> includedInstance [ 14 | ^ Array with: '1' with: '2' 15 | ] 16 | 17 | { #category : #running } 18 | MAToManyScalarRelationDescriptionTest >> setUp [ 19 | super setUp. 20 | self description 21 | reference: (MAStringDescription new 22 | accessor: MANullAccessor new; 23 | yourself); 24 | classes: (Array with: String) 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAToOneRelationDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAToOneRelationDescriptionTest, 3 | #superclass : #MARelationDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MAToOneRelationDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MAToOneRelationDescriptionTest >> actualClass [ 14 | ^ MAToOneRelationDescription 15 | ] 16 | 17 | { #category : #private } 18 | MAToOneRelationDescriptionTest >> includedInstance [ 19 | ^ self addressInstance1 20 | ] 21 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MATokenDescriptionTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MATokenDescriptionTest, 3 | #superclass : #MAReferenceDescriptionTest, 4 | #category : 'Magritte-Tests-Model-Description' 5 | } 6 | 7 | { #category : #testing } 8 | MATokenDescriptionTest class >> isAbstract [ 9 | ^ false 10 | ] 11 | 12 | { #category : #private } 13 | MATokenDescriptionTest >> actualClass [ 14 | ^ MATokenDescription 15 | ] 16 | 17 | { #category : #private } 18 | MATokenDescriptionTest >> includedInstance [ 19 | ^ #( 'foo' 'bar' ) 20 | ] 21 | 22 | { #category : #'tests-strings' } 23 | MATokenDescriptionTest >> testFromStringInvalid [ 24 | "There is no invalid string input." 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/MAValidatorVisitorTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAValidatorVisitorTest, 3 | #superclass : #TestCase, 4 | #category : #'Magritte-Tests-Model-Visitor' 5 | } 6 | 7 | { #category : #tests } 8 | MAValidatorVisitorTest >> testUndefinedValue [ 9 | self 10 | shouldnt: [ 11 | MAValidatorVisitor new 12 | validate: 'null' 13 | using: 14 | (MABooleanDescription new 15 | undefinedValue: 'null'; 16 | yourself) ] 17 | raise: MAKindError 18 | ] 19 | -------------------------------------------------------------------------------- /source/Magritte-Tests-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Tests-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-Traits-Model/GRPackage.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #GRPackage } 2 | 3 | { #category : #'*magritte-traits-model' } 4 | GRPackage class >> magritteTraitsModel [ 5 | ^ self new 6 | name: 'Magritte-Traits-Model'; 7 | addDependency: 'Magritte-Model'; 8 | url: #magritteUrl; 9 | yourself 10 | ] 11 | -------------------------------------------------------------------------------- /source/Magritte-Traits-Model/Trait.extension.st: -------------------------------------------------------------------------------- 1 | Extension { #name : #Trait } 2 | 3 | { #category : #'*magritte-traits-model-configuration' } 4 | Trait >> descriptionContainer [ 5 | "Return the default description container." 6 | 7 | ^ MAPriorityContainer new 8 | label: self label; 9 | yourself 10 | ] 11 | 12 | { #category : #'*magritte-traits-model-accessing' } 13 | Trait >> label [ 14 | "Answer a human-readable name of the receiving class. This implementation tries to be smart and return a nice label, unfortunately for a lot of classes this doesn't work well so subclasses might want to override this method and return soemthing more meaningfull to end-users." 15 | 16 | | start input | 17 | start := self name findFirst: [ :each | each isLowercase ]. 18 | input := (self name copyFrom: (1 max: start - 1) to: self name size) 19 | readStream. 20 | ^ String streamContents: [ :stream | 21 | [ input atEnd ] whileFalse: [ 22 | stream nextPut: input next. 23 | (input atEnd or: [ input peek isLowercase ]) 24 | ifFalse: [ stream nextPut: Character space ] ] ] 25 | ] 26 | -------------------------------------------------------------------------------- /source/Magritte-Traits-Model/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-Traits-Model' } 2 | -------------------------------------------------------------------------------- /source/Magritte-UI/MAPatchBrowser.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #MAPatchBrowser, 3 | #superclass : #SpPresenter, 4 | #category : #'Magritte-UI' 5 | } 6 | 7 | { #category : #building } 8 | MAPatchBrowser >> compose [ 9 | self tabulator with: [ :browser | 10 | "self configureBrowser: browser." 11 | self composeBrowserOn: browser ] 12 | ] 13 | 14 | { #category : #building } 15 | MAPatchBrowser >> composeBrowserOn: browser [ 16 | browser 17 | row: #tree; 18 | row: #diff. 19 | 20 | browser transmit 21 | to: #tree; 22 | andShow: [ :a | 23 | a fastTree 24 | children: #children ]. 25 | browser transmit to: #diff; from: #tree; andShow: [ :a | 26 | a diff 27 | display: [ :op | op diffStrings ] ] 28 | ] 29 | -------------------------------------------------------------------------------- /source/Magritte-UI/MATDescriptionPresenter.trait.st: -------------------------------------------------------------------------------- 1 | Trait { 2 | #name : #MATDescriptionPresenter, 3 | #instVars : [ 4 | 'memento', 5 | 'description', 6 | 'parent' 7 | ], 8 | #category : #'Magritte-UI' 9 | } 10 | 11 | { #category : #testing } 12 | MATDescriptionPresenter >> isRoot [ 13 | ^ self parent isNil 14 | ] 15 | 16 | { #category : #accessing } 17 | MATDescriptionPresenter >> magritteDescription [ 18 | ^ description 19 | ] 20 | 21 | { #category : #accessing } 22 | MATDescriptionPresenter >> memento [ 23 | ^ memento 24 | ] 25 | 26 | { #category : #'accessing-dynamic' } 27 | MATDescriptionPresenter >> model [ 28 | ^ self memento model 29 | ] 30 | 31 | { #category : #accessing } 32 | MATDescriptionPresenter >> parent [ 33 | ^ parent 34 | ] 35 | 36 | { #category : #actions } 37 | MATDescriptionPresenter >> reset [ 38 | self memento reset 39 | ] 40 | 41 | { #category : #'accessing-dynamic' } 42 | MATDescriptionPresenter >> root [ 43 | ^ self isRoot 44 | ifTrue: [ self ] 45 | ifFalse: [ self parent root ] 46 | ] 47 | 48 | { #category : #initialization } 49 | MATDescriptionPresenter >> setDescription: aDescription [ 50 | description := aDescription 51 | ] 52 | 53 | { #category : #initialization } 54 | MATDescriptionPresenter >> setMemento: aMemento [ 55 | memento := aMemento 56 | ] 57 | 58 | { #category : #initialization } 59 | MATDescriptionPresenter >> setParent: aMorph [ 60 | parent := aMorph 61 | ] 62 | -------------------------------------------------------------------------------- /source/Magritte-UI/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Magritte-UI' } 2 | -------------------------------------------------------------------------------- /source/Spec-Widgets/MorphWrapper.class.st: -------------------------------------------------------------------------------- 1 | " 2 | A MorphWrapper is used to wrap a morph with a layout in the goal to be easily added to another morph 3 | " 4 | Class { 5 | #name : #MorphWrapper, 6 | #superclass : #Object, 7 | #instVars : [ 8 | 'layout', 9 | 'morph' 10 | ], 11 | #category : 'Spec-Widgets-Utilities' 12 | } 13 | 14 | { #category : #'instance creation' } 15 | MorphWrapper class >> morph: morph layout: layout [ 16 | 17 | ^ self new 18 | layout: layout; 19 | morph: morph; 20 | yourself 21 | ] 22 | 23 | { #category : #adding } 24 | MorphWrapper >> addIn: aContainer [ 25 | 26 | aContainer 27 | addMorph: morph 28 | fullFrame: layout 29 | ] 30 | 31 | { #category : #accessing } 32 | MorphWrapper >> frame: rectangle [ 33 | 34 | layout := rectangle asLayoutFrame 35 | ] 36 | 37 | { #category : #accessing } 38 | MorphWrapper >> fullFrame: anObject [ 39 | 40 | layout := anObject 41 | ] 42 | 43 | { #category : #accessing } 44 | MorphWrapper >> morph: anObject [ 45 | 46 | morph := anObject 47 | ] 48 | -------------------------------------------------------------------------------- /source/Spec-Widgets/RadioButtonGroup.class.st: -------------------------------------------------------------------------------- 1 | " 2 | A RadioButtonGroup is a group for radio buttons which ensure that only radio button of this group is activated at the same time. 3 | " 4 | Class { 5 | #name : #RadioButtonGroup, 6 | #superclass : #Object, 7 | #instVars : [ 8 | 'buttons' 9 | ], 10 | #category : 'Spec-Widgets-Utilities' 11 | } 12 | 13 | { #category : #protocol } 14 | RadioButtonGroup >> addRadioButton: aButton [ 15 | 16 | buttons do: [:b | 17 | aButton whenActivatedDo: [ b privateSetState: false ]. 18 | b whenActivatedDo: [ aButton privateSetState: false ]]. 19 | 20 | buttons add: aButton. 21 | aButton privateSetState: false 22 | ] 23 | 24 | { #category : #protocol } 25 | RadioButtonGroup >> default: aButton [ 26 | 27 | aButton privateSetState: true. 28 | aButton takeKeyboardFocus. 29 | ] 30 | 31 | { #category : #initialization } 32 | RadioButtonGroup >> initialize [ 33 | "Initialization code for RadioButtonGroup" 34 | 35 | super initialize. 36 | 37 | buttons := OrderedCollection new. 38 | ] 39 | -------------------------------------------------------------------------------- /source/Spec-Widgets/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Spec-Widgets' } 2 | --------------------------------------------------------------------------------