-
Notifications
You must be signed in to change notification settings - Fork 6
Add a new plugin to Pyramid
Pyramid makes it easy to add plugins. A plugin is a module that adds new functionalities to the editor. It provides access to various information and systems linked to the editor, such as the list of root elements, the list of selected elements, the command execution system with integrated history, the properties presentation panel, the editor view, etc.
To add a plugin, simply create a new class and register it in the PyramidPluginManager
singleton. The new class must implement 3 methods:
-
#addPanelsOn:
, takes aPyramidWindow
object as argument. Used to modify the editor view. -
#configureBuilder:
, takes aPyramidEditorBuilder
object as argument. Used to configure the editor builder. -
#connectOn:
, takes aPyramidEditor
object as argument. Used to Retrieve information from the editor.
We want to add a plugin that display the executed commands in the Transcript
. It can be toggle on and off with a button.
To create such plugin we need to follow this steps:
- Create the plugin class
- Register the class in the
PyramidPluginManager
singleton. - Create the view object and / or class.
- Connect the view object to the Pyramid Editor View using
#addPanelsOn:
method. - Create the business classes
- Connect the business object to the Pyramid Editor View using
#connectOn:
method.
We create a class named PyramidLogPlugin
that uses the trait TPyramidPlugin
. The trait contains the 3 necessary methods.
Object << #PyramidLogPlugin
traits: {TPyramidPlugin};
slots: { #logSwitchModel . #logSwitchButton . #logCommandExecutor };
tag: 'plugin-log';
package: 'Pyramid'
To automaticly register the plugin to the PyramidPluginManager
we can override the initialize
class method. If the class is loaded in another Pharo image, it will be automaticly register to the PyramidPluginManager
of the new image.
initialize
"Add this method on class side to install the plugin when the class is loaded."
PyramidPluginManager uniqueInstance addPlugin: self
In our example the view consist of a button that can be toggle on and off. To do that we will create a model that indicate if the button is toggle or not. Then we will create a SpButtonPresenter
and connect it to our model.
First, we create the model.
Object << #PyramidLogSwitchModel
slots: { #toggle };
tag: 'plugin-log';
package: 'Pyramid'
PyramidLogSwitchModel >> initialize [
toggle := true ].
PyramidLogSwitchModel >> toggle [
^ toggle ].
PyramidLogSwitchModel >> toggle: anObject [
toggle := anObject ].
Secodly, we create a button in the plugin.
PyramidLogPlugin>> logSwitchButton [
^ logSwitchButton ].
PyramidLogPlugin>> logSwitchModel [
^ logSwitchModel ].
PyramidLogPlugin>> initialize [
logSwitchModel := PyramidLogSwitchModel new.
logSwitchButton := SpButtonPresenter new.
logSwitchButton action: [
self logSwitchModel toggle: self logSwitchModel toggle not.
self updateButtonIconAndHelp ].
self updateButtonIconAndHelp ].
PyramidLogPlugin >> updateButtonIconAndHelp [
self logSwitchButton icon: self logSwitchModel asIcon.
self logSwitchButton adapter ifNotNil: [ :adapater |
adapater widgetDo: [ :w |
w setBalloonText: self logSwitchModel asHelp ] ] ].
PyramidLogSwitchModel >> asIcon [
self toggle
ifTrue: [ ^ self iconNamed: #checkboxSelected ]
ifFalse: [ ^ self iconNamed: #checkboxUnselected ] ].
PyramidLogSwitchModel >> asHelp [
self toggle
ifTrue: [
^ 'The command used will be displayed in the Transcript. Click to desactivate.' ]
ifFalse: [
^ 'The command used will not be displayed in the Transcript. Click to activate.' ] ].
We can change the view on 7 differents place in Pyramid.
-
topLeft, add a Button with an icon. Use a
PyramidToolbarPanelBuilder
with the method#makeButtonWithIcon:order:
. -
topCenter, add a Button with an icon. Use a
PyramidToolbarPanelBuilder
with the method#makeButtonWithIcon:order:
. -
topRight, add a Button with an icon. Use a
PyramidToolbarPanelBuilder
with the method#makeButtonWithIcon:order:
. -
space, add a
BlSpace
preview in the center (you should avoid to change this view). Use aPyramidPresenterPanelBuilder
with the method#makePresenter:
. -
tabLeft, add a "tab" with a title, an icon and a
SpPresenter
to display. Use aPyramidTabPanelBuilder
with the method#makeTab:label:icon:order:
. -
tabRight, add a "tab" with a title, an icon and a
SpPresenter
to display. Use aPyramidTabPanelBuilder
with the method#makeTab:label:icon:order:
. -
selectionMenu, add a menu that will change according to the number of selected items. Use a
PyramidMenuPanelBuilder
with the methods#addGroupEmptySelection:order:
,#addGroupSingleSelection:order:
and#addGroupMultiSelection:order:
.
In our example we want to add a button on the top-right. We need to change the #addPanelsOn:
method.
PyramidLogPlugin >> addPanelsOn: aPyramidSimpleWindow [
aPyramidSimpleWindow at: #topLeft addItem: [ :builder |
builder makeButtonWithIcon: self logSwitchButton order: 200 ] ].
The order is used to choose the display order of the different added views.
Plugin | #topLeft | #topCenter | #topRight |
---|---|---|---|
PyramidPluginDynamicLayout | -9999 : Change left layout | 9999 : Change right layout | |
PyramidSavePlugin | 1 : Save | ||
PyramidSavePlugin | 2 : Save (project menu) | ||
PyramidSpacePlugin | 5 : refresh the BlSpace | ||
PyramidHistoryPlugin | 1 : undo | ||
PyramidHistoryPlugin | 2 : redo |
Plugin | #tabLeft | #tabRight |
---|---|---|
(default) | fisrt : Properties view | |
PyramidTreePlugin | 1 : Tree | |
PyramidPluginSelection | 1 : Playground |
The plugin will detect each time a command is executed by the PyramidMainCommandExecutor
. The PyramidMainCommandExecutor
can be decorated with a PyramidCommandExecutorDecorator
so we will create a class that inherits it.
PyramidCommandExecutorDecorator << #PyramidLogCommandExecutor
slots: {#logSwitchModel};
tag: 'plugin-log';
package: 'Pyramid'
PyramidLogCommandExecutor >> logSwitchButton [
^ logSwitchButton ].
PyramidLogCommandExecutor >> logSwitchModel [
^ logSwitchModel ].
PyramidLogCommandExecutor >> use: aCommand on: aCollection with: arguments [
"This method should be implemented."
"I use the command with the wrappee."
self wrappee use: aCommand on: aCollection with: arguments.
"I then print in the transcript the log only if the model allows it."
self logSwitchModel toggle ifFalse: [ ^ self ].
Transcript crShow: '[Pyramid] - Use of: <' , aCommand class name , '>
with: ' , arguments printString , '
on: ' , aCollection printString ].
We now have to add the command executor decorator to the editor.
PyramidLogPlugin >> logCommandExecutor [
^ logCommandExecutor ].
PyramidLogPlugin >> initialize [
logSwitchModel := PyramidLogSwitchModel new.
logCommandExecutor := PyramidLogCommandExecutor new.
logSwitchButton := SpButtonPresenter new.
logCommandExecutor logSwitchModel: logSwitchModel.
logSwitchButton action: [
self logSwitchModel toggle: self logSwitchModel toggle not.
self updateButtonIconAndHelp ].
self updateButtonIconAndHelp ].
PyramidLogPlugin >> connectOn: aPyramidEditor [
| executor |
executor := aPyramidEditor propertiesManager commandExecutor.
self logCommandExecutor wrappee: executor.
aPyramidEditor propertiesManager commandExecutor:
self logCommandExecutor ].