Services-Base

BasicRequestor
This class is the root of the Requestor hierarchy.
Requestors are interfaces between services and the system. ServiceActions are given an instance
of a Requestor, and they ask it for the data they need. The requestor is determined by the model of the application. A class used as a model can implement the #requestor message to return the most suited requestor. A requestor knows how to query its model and the user if needed.
Requestor are defined in hierarchies so that the protocol they rely on (methods starting with 'get') can be easily reused.
caption:
get:
getString
getStringCollection
getSymbol
getSymbolCollection
initialize
Subclasses should redefine this method to perform initializations on instance creation
newCaption
BrowserProvider
I define the default categories of services dealing with browsing:
- the class category menu (service identifier: browserClassCategoryMenu)
- the class menu (browserClassMenu)
- the method category menu (browserMethodCategoryMenu)
- the browser method menu (browserMethodMenu)
- the browser button bar (browserButtonBar)
- the browser code pane/selection menu (browserCodePaneMenu)
browser
browserButtonBar
browserClassCategoryMenu
browserClassMenu
browserClassMenushortcut
browserCodePaneMenu
browserMethodCategoryMenu
browserMethodMenu
browserMethodMenushortcut
initialize
Subclasses should redefine this method to perform initializations on instance creation
BrowserRequestor
I am a requestor specialized to fetch information in a Browser.
I can ask a browser its selected class and selected method for example.
If the RB is installed too, I can also fetch ast nodes in the browser's selected
method.
I am the default requestor for CodeHolder and it's subclasses.
To be integrated with services, alternative browsers, such as the OmniBrowser and Whisker should define a specialized requestor subclassing this one. A few core messages would need to be redefined, such as getClass, getMessage ... to be adapted to the browser's data structures.
Only a few of them have to be overridden, the majority of the requests rely on a few base ones.
browser:
getArgumentPermutation
Answer the argument permutation map.
No support for changing argument count.
getBrowser
getClass
getInitializingExpressionForTheNewParameter
getNewSelectorName
getNewVariableName
getPackage
getPackageForCategory
answers a packageinfo for the current class category
getPackageForCategoryName
answers a packageinfo for the current class category
getPackageName
getPackageProvider
getSelection
Sorry to feedle with fillInTheBlankMorph innards, but I had to
getSelector
getSelectorCollection
getSelectorName
getSystemCategory
Requestor
I am an implementation of BasicRequestor with some requests already implemented.
default
getClass
getClassCollection
getMethodBody
getSelection
Sorry to feedle with fillInTheBlankMorph innards, but I had to
getSelector
ServiceAction
ServiceAction are executable objects in various contexts.
They can be displayed as buttons or menu items or bounded to keyboard shortcuts.
ServiceActions are defined in methods in an instance of a ServiceProvider class (in the 'services' method category), using the following template:
serviceIdentifierAndMethodName
^ ServiceAction
text: 'Menu item text'
button: 'Button text'
description: 'Longer text that appears in help balloons'
action: [:r | "Code block fetching data from the requestor instance, r, that is passed to the block"]

or, alternatively:
serviceIdentifierAndMethodName
^ ServiceAction
text: 'Menu item text'
button: 'Button text'
description: 'Longer text that appears in help balloons'
action: [:r | "Code block fetching data from the requestor instance, r, that is passed to the block"]
condition: [:r | "second block returning true if the service can be used at the time being, false otherwise. Data can still be fetched from the requestor instance"]

The method name in which the service is defined becomes its identifier. To build the hierarchy of services and to assign them to shortcuts, you will need to type this names in the relevant fields of the Services Browser.

Services are arranged in a hierarchy. and bound to keyboard shortcuts using the ServicesBrowser.
action:
addPreference:category:selector:
buttonLabel
buttonLabel:
categories
condExecuteWith:
condition:
description
description:
execute
executeCondition
id
id:
id:text:button:description:action:
id:text:button:description:action:condition:
initialize
Subclasses should redefine this method to perform initializations on instance creation
insertPreferences
isCategory
isEnabled
menuLabel
menuLabelNumbered:
perform:orSendTo:
If I wish to intercept and handle selector myself, do it; else send it to otherTarget
preferences
provider
provider:
providerCategory
requestor
returns the focused window's requestor
requestor:
shortcut
shortcutPreference
text
text:
text:button:description:action:
text:button:description:action:condition:
text:description:action:
updateEnable
updateShortcut
ServiceBrowserMorph
I subclass the PreferenceBrowserMorph to adapt the interface to services. So far the changes are minimal.
newButtonRow
Answer a new button row.
ServiceCancelled
Exception raised when a service is cancelled, to inform the user.
defaultAction
The user should be notified of the occurrence of an exceptional occurrence and given an option of continuing or aborting the computation. The description of the occurrence should include any text specified as the argument of the #signal: message.
messageText
Return an exception's message text.
ServiceCategory
I represent a category of services that can be added to a menu.
I can be displayed as a menu or button bar containing my services.
I am also a subclass of ServiceAction, so I can form a subcategory of another service category.
Like services, I am created in methods of a ServiceProvider, in the 'services' method protocol.
The template to create a service category is the following:
methodNameAndServiceCategoryId
^ ServiceCategory
text: 'Menu text'
button: 'Button text'
description: 'Longer descriptive text appearing in help balloons'

To put services in a service category, you have to use the Service Browser, located in the word menu, under the 'Preferences and Services' menu item.
In it, you can look up for the name of your category, and enter service identifiers as children
of the category in the associatedd text field, separating them with spaces.
childrenPreferences
enabledServices
execute
displays the subservices as a submenu
externalPreferences
initialize
Subclasses should redefine this method to perform initializations on instance creation
insertPreferences
isCategory
newChildren
newChildrenValid
prefServices
replaceChildren
requestor:
services
text:button:description:
updateChildren
ServiceGui
I abstract all the UI-related behaviors for the services framework.
In the future I could be changed to be compatible with ToolBuilder
bar
bars
browser:classCategoryMenu:
browser:classMenu:
browser:codePaneMenu:
browser:messageCategoryMenu:
browser:messageListMenu:
browserButtonRow:
browserButtonRow:inlinedIn:
buildButtonBar
buttonBarFor:
buttonBarServices
buttonFor:
buttonForAction:
see getstate for availability?
buttonForCategory:
see getstate for availability?
for:id:
initialize
Subclasses should redefine this method to perform initializations on instance creation
inlineInMenu:
inlineInMenu:for:
inlineServices
menu
menuFor:
menuItemFor:
menuItemForAction:
Returns a menuItem triggering self
menuItemForCategory:
Returns a menuItem triggering self
n
n:
onlyServices
openMenuFor:
popMenu
pushMenu
registerBar:for:
styleBar:
styleButton:
styleMenu:
gradient, etc ..?
subMenuFor:
updateBar:
updateBars
updateMenu:forModel:selector:
worldMenu:
ServicePreferences
I store the preferences related to the servicse framework. The preferences are editable via the Services Browser, based on Hernan Tylim's Preference Browser.
The main preference categories for services are:
-- keyboard shortcuts -- : several text preferences, one per keyboard shortcuts. To edit them, enter a service identifier (equal to the method name under which it is defined in its ServiceProvider), and accept with alt-s or enter
-- menu contents -- : All the service categories in the image have a text preference under here. To edit it, enter the services identifiers you wish to put in this category, separating them with a single space character. The order is important: it defines the order of the items in menus.
-- settings -- : general boolean preferences.
Then there is a preference category for each provider in the image. Under each, you will find:
A boolean preference for each service in the image. If it is false, the service will not appear in menus.
The text preference for each service category defined by the service provider. This is the same as the one appearing in the menu contents preference category.
compileAccessMethodForPreference:
dictionaryOfPreferences
dictionaryOfPreferences:
replayPreferences:
wipe
ServiceProvider
A ServiceProvider references services that are relevant to a given application.
Each application that wishes to use the Services framework must subclass a ServiceProvider.
This class must define a 'services' method category.
Each method implemented in this category will be automatically called by the framework.
Each of these method should be a unary message (taking no argument), and return a fully initialised instance of ServiceAction or ServiceCategory. There are three possible patterns:
1)
serviceIdentifierAndMethodName
^ ServiceAction
text: 'Menu item text'
button: 'Button text'
description: 'Longer text that appears in help balloons'
action: [:r | "Code block fetching data from the requestor instance, r, that is passed to the block"]

2)
serviceIdentifierAndMethodName
^ ServiceAction
text: 'Menu item text'
button: 'Button text'
description: 'Longer text that appears in help balloons'
action: [:r | "Code block fetching data from the requestor instance, r, that is passed to the block"]
condition: [:r | "second block returning true if the service can be used at the time being, false otherwise. Data can still be fetched from the requestor instance"]

3)
methodNameAndServiceCategoryId
^ ServiceCategory
text: 'Menu text'
button: 'Button text'
description: 'Longer descriptive text appearing in help balloons'

The organisation of services into categories, and the services bound to keyboard shortcuts are
specified using the Services Browser (see the comment on the class ServicesPreferences for more details). When editing preferences, they are saved as methods on the ServiceProvider, all defined
in the 'saved preferences' method category. Each of thesse methods stores preferences that the provider can replay.
newProviderFor:
performAndSetId:
registeredProviders
registeredServices
replayPreferences
savePreferencesFor:
pref := ServicePreferences preferenceAt: aService shortcutPreference.
strm := WriteStream with: ''.
strm nextPutAll: aService id;
nextPutAll: 'shortcut';
cr;
tab;
nextPutAll: '^ ';
nextPutAll: {pref name. pref preferenceValue. 1000} storeString.
self class compileSilently: strm contents classified: 'saved preferences'.
savedPreferences
services
ServiceRegistry
The ServiceRegistry is the repository in which services are stored. They are stored in
a dictionary, and keyed by their identifier (which is the name of the method they were defined in).
The registry handles the intialization, building and referencing processes as well.
addService:provider:
beNotInteractiveDuring:
build
ServicePreferences wipe.
buildProvider:
categories
current
ifInteractiveDo:
initialize
Subclasses should redefine this method to perform initializations on instance creation
isInteractive
methodChanged:
rebuild
serviceCollection
serviceWithId:
services
ServiceShortcuts
A data structures implementing a simple form of keyboard shortucts is defined on the class side.
Available keyboard shortcuts are:
command-0 to command-9 (command is also called alt on some systems).
control-0 to control-0
command-control-0 to command-control-9 (command is also alt)
control-command-left arrow
control-command-up arrow
control-command-right arrow
control-command-down arrow
Using the Services Browser (see class ServicePreferences), these shortcuts can be bound to service identifiers.
arrowShortcut:event:
changeShortcut:to:
handleKeystroke:
insertPrefShortcut:
map
process:
setPreferences
shortcut:event:
TextRequestor
A requestor for text areas, able for example to fetch the current selected text.
getCurrentText
returns the unnacepted text in the text morph
getModel
model:
WorldMenuProvider
I define services and categories:
- The world menu category (identifier: world), where services and categories can be put to be displayed in the world menu.
- The preferencesMenu category, where services about services and preferences can be put
- th open menu
browserMethodMenucreateNewService
closeTopWindow
convertOpenCommand:
createNewService
helpOnServices
initialize
Subclasses should redefine this method to perform initializations on instance creation
nextWindow
openMenu
preferencesBrowser
preferencesMenu
preferencesMenuhelpOnServices
preferencesMenupreferencesBrowser
preferencesMenurebuildRegistry
preferencesMenuservicesBrowser
preferencesMenushortcut
rebuildRegistry
servicesBrowser
servicesHelpText
world
worldpreferencesMenu
worldshortcut