-
Notifications
You must be signed in to change notification settings - Fork 6
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.
-
#commanInverse
returns 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
.
-
#command
returns the command to be tested. -
#targetContainers
returns a collection ofPyramidCommandTestContainers
.
PyramidCommandTestContainer` is a model used to contains object and there expected results for tests :
-
targetNoProp
is an object in which we want to set the property. -
prop
is the value of a property. -
targetWithProp
is 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.
-
emptyValue
sets the input to an empty value state where the property has no value. -
mixedValues
sets the input to a mixed values state where objects inside the collection have differents values. -
value
returns the value inside the input. -
value: anObject
sets the value of the input without triggering whenValueChangedDo block. -
whenValueChangedDo: aBlock
a 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