-
Notifications
You must be signed in to change notification settings - Fork 7
Deprecated ‐ Add new properties to Pyramid
A property is an object used to display and modify part of an element. For example there is a property to modify the background of a BlElement and one to modify the visibility. All property are display on the right side panel of Pyramid. It contains a command and a spec presenter builder.
Together, we're going to implement the property to display and modify the value of the text in a BlTextElement.
A command is used by Pyramid to obtain and change the value of an element. It is also used to save the state inside the history plugin.
A command inherits from the PyramidCommand class. To create a new command, you must implement at least 3 methods #canBeUsedFor:, #getValueFor: and #setValueFor:with:.
-
#canBeUsedFor:returns a Boolean if the command can be used. -
#getValueFor:returns the value of an object property. -
#setValueFor:with:modifies the value of an element.
It is sometimes necessary to modify the #commanInverse function.
-
#commanInversereturns the inverse of the current command. For example, the inverse command of add to a collection is remove from a collection.
We'll create an abstract class, PyramidBlocTextCommand, which will implement the #canBeUsedFor: method.
canBeUsedFor: anObject
^ anObject class = BlTextElement or: [
anObject class inheritsFrom: BlTextElement ]
Next, we create the text change command: PyramidChangeTextCommand.
-
#getValueFor:returns a string of text from the BlTextElement. -
#setValueFor:with:takes a string as argument and changes the text while retaining the properties (size, color, etc.) of the BlTextElement.
getValueFor: aBlTextElement
^ aBlTextElement text asString
setValueFor: aBlTextElement with: aString
| attributes rope |
attributes := self getAttributesOf: aBlTextElement text.
rope := aString asRopedText.
rope attributes: attributes.
aBlTextElement text: rope
getAttributesOf: aBlText
^ aBlText attributesFinder attributesAndIndicesSuchThat: [ :a | true ]
Now we need to test what we've done. We create the PyramidChangeTextCommandTest class and use the trait TPyramidCommandTest on it to help us test the command we created.
TPyramidCommandTest has 2 methods that must be implemented: #command and #targetContainers.
-
#commandreturns the command to be tested. -
#targetContainersreturns a collection ofPyramidCommandTestContainers.
PyramidCommandTestContainer` is a model used to contains object and there expected results for tests :
-
targetNoPropis an object in which we want to set the property. -
propis the value of a property. -
targetWithPropis an object where the property is defined.
In our example, we have :
command
^ PyramidChangeTextCommand new
targetContainers
^ {
(PyramidCommandTestContainer
no: BlTextElement new
with: 'test1' asRopedText asElement
prop: 'test1').
(PyramidCommandTestContainer
no: 'hello' asRopedText asElement
with: 'test2' asRopedText asElement
prop: 'test2').
(PyramidCommandTestContainer
no: ('I am BOLD' asRopedText
bold;
attribute: (BlFontSizeAttribute size: 20);
attribute: (BlTextForegroundAttribute color: Color green);
yourself) asElement
with: ('test3' asRopedText
bold;
attribute: (BlFontSizeAttribute size: 20);
attribute: (BlTextForegroundAttribute color: Color green);
yourself) asElement
prop: 'test3') }
All tests are green. But in our case, we also want to test if the properties after setting a value are still the same (the collor didnt't change, or the font is still the same). So we're going to modify the method #testSetValueForWith.
testSetValueForWith
| attributes |
self targetsWithoutValuesAndValues do: [ :each |
attributes := (each key text attributesFinder
attributesAndIndicesSuchThat: [ :a | true ])
collect: [ :a | a key ].
self command setValueFor: each key with: each value.
self assert: (self command getValueFor: each key) equals: each value.
self
assert:
((each key text attributesFinder attributesAndIndicesSuchThat: [
:a | true ]) collect: [ :a | a key ])
equals: attributes ]Now we need to create a view that can display our property and offer the possibility to the user to change it. This view will use the common API for the properties's views define in PyramidInputPresenter.
We want to have a simple text entry to enter the text. It already exist, it is called PyramidTextInputPresenter. So we do not need to create a custom one. If you want to create a custom one you must implements the PyramidInputPresenter API.
-
emptyValuesets the input to an empty value state where the property has no value. -
mixedValuessets the input to a mixed values state where objects inside the collection have differents values. -
valuereturns the value inside the input. -
value: anObjectsets the value of the input without triggering whenValueChangedDo block. -
whenValueChangedDo: aBlocka block to trigger when the value is updated. As one argument who is the new value of the property.
To install the property we create a plugin.
Object << #PyramidBlocTextPlugin
traits: {TPyramidPlugin};
slots: {};
tag: 'plugin-bloc-text';
package: 'Pyramid-Bloc'connectOn: aPyramidEditor
aPyramidEditor propertiesManager addProperty: self class changeText.changeText
| property |
property := PyramidProperty new
name: 'Text';
command: PyramidChangeTextCommand new;
pyramidInputPresenterClass: PyramidTextInputPresenter;
yourself.
property pyramidInputPresenterModel help:
'Change the value of the text'.
^ property