Actions are an implementation of the design-by-contract approach to object orientation. Common activities such as showing and hiding an object on the display, or reading and writing data have been given a dedicated action interface. The 'contract' exists in the strict objectives of each action, as documented in this manual. For instance, calling `Show` and `Hide` actions on a UI object will change its visibility as one would expect.
If an action isn't applicable to an object, calling it is legal but will do nothing.
This document describes the available action interfaces, including the expectations of behaviour for the client, as well as implementation details of each contract.
Where necessary, classes will often clarify the details of how they support their actions. These details are documented in the class manuals.
# Action Interfaces
The Core API provides multiple functions for action related tasks. `Action()` is used to make immediate calls, and requires an object pointer. `AsyncAction()` launches the action in a separate thread and returns immediately. `QueueAction()` is a pure messaging function, requiring only the object UID and delaying the call until the next message processing cycle. The aforementioned functions are documented completely in the Core API.
For C++ users, additional macros are also provided. All actions listed in this document will have an associated stub function prefixed with `ac`. For example, `acShow(Object)` and `acSetKey(Object, Key, Value)`. Automated header generation also ensures that relevant methods are created at class level, meaning `Object->show()` and `Object->setKey(Key, Value)` are similarly valid.
Tiri users can call actions with the `acName` template, in this case `object.acShow()` and `object.acSetKey(Key, Value)` would be equivalent to the C++ counterpart.
Run-time inspection is supported with the Core API's `CheckAction()` function, which confirms if an object's class supports a given action. The `ActionList()` function provides insight into all known actions and their parameters.
Finally, the `SubscribeAction()` function provides a monitoring feature that will call a custom function whenever a given action has been executed for a target object.
# Action Index
[`Activate`](#activate) | [`Clear`](#clear) | [`Clipboard`](#clipboard) | [`CopyData`](#copydata) | [`DataFeed`](#datafeed) | [`Deactivate`](#deactivate) | [`Disable`](#disable) | [`DragDrop`](#dragdrop) | [`Draw`](#draw) | [`Enable`](#enable) | [`Flush`](#flush) | [`Focus`](#focus) | [`Free`](#free) | [`GetKey`](#getkey) | [`Hide`](#hide) | [`Init`](#init) | [`Lock`](#lock) | [`Move`](#move) | [`MoveToBack`](#movetoback) | [`MoveToFront`](#movetofront) | [`MoveToPoint`](#movetopoint) | [`Next`](#next) | [`Prev`](#prev) | [`Query`](#query) | [`Read`](#read) | [`Redimension`](#redimension) | [`Redo`](#redo) | [`Refresh`](#refresh) | [`Rename`](#rename) | [`Reset`](#reset) | [`Resize`](#resize) | [`SaveImage`](#saveimage) | [`SaveSettings`](#savesettings) | [`SaveToObject`](#savetoobject) | [`Seek`](#seek) | [`SetField`](#setfield) | [`SetKey`](#setkey) | [`Show`](#show) | [`Signal`](#signal) | [`Undo`](#undo) | [`Unlock`](#unlock) | [`Write`](#write)
# Internal Actions
These actions are implemented for use internally, and must never be called from client code.
[`FreeWarning`](#freewarning) | [`LostFocus`](#lostfocus) | [`NewChild`](#newchild) | [`NewObject`](#newobject) | [`NewOwner`](#newowner) | [`NewPlacement`](#newplacement)
---
## Activate
`ERR acActivate(Object)`
`Activate` causes an object to perform its "native activity". Although ambiguous, the activity should be relevant to the class in question. Here are a few examples of what some existing classes do when their objects are activated:
|Class|Description|
|:-|:-|
|Sound|Plays audio data.|
|Script|Runs a scripted program.|
|Image|Loads a source image.|
It is typical for most classes that support the loading and processing of data to do so in their `Activate` support.
Some objects will continue to perform their native activity after they return back to the client - for example, activating a `Sound` object will cause it to play audio in the background. If background processing needs to be cancelled, this should be done with a [`Deactivate`](#Deactivate) call.
### Implementation Details
The `Activate` action is intentionally ambiguous, giving free reign as to the nature of the implementation. Even so, it should be intuitively clear what the user would expect from the activation process. If that is not the case, the `Activate` action should probably go unsupported.
Remember to support the `Deactivate` action if background activity can be cancelled.
## Clear
`ERR acClear(Object)`
This action will clear an object of all its data. Typical use cases are the clearing of graphics and data records. Here are some examples:
|Class|Description|
|:-|:-|
|File|Clears file data by reducing the file length down to 0.|
|Text|Deletes all lines of text.|
|Bitmap|Clears the bitmap of graphics data.|
The overall state of the object will normally remain intact - so clearing a file will not cause the file handle to be closed for instance.
## Clipboard
`ERR acClipboard(Object, CLIPMODE Mode)`
|Name|Type|Description|
|:-|:-|:-|
|Mode|CLIPMODE|The mode that will be used to shift data between the target object and clipboard system.|
The `Clipboard` action is used on objects for the purpose of shifting data between them and the clipboard system. Generally, clients should only use this action when the user has done something that requires it to be called, for instance, holding the `CTRL+C` keys to make a copy operation.
Three modes are currently available for performing clip operations, as illustrated in the following table:
|CLIPMODE|Description|
|:-|:-|
|CUT|Cut (copy and delete) the currently selected data from the target object and copy it into the clipboard.|
|COPY|Copy the currently selected data from the target object into the clipboard.|
|PASTE|Paste the most recent data from the clipboard into the target object.|
The specifics of how a target object interacts with a clipboard is down to the developer of the object's class. If you need more information on how an object might interface with the clipboard system, check its class documentation.
### Implementation Details
Supporting the system-wide clipboard service requires code to be written for the `Clipboard` action. This action is closely related to the `Clipboard` class, which you will need to instantiate as necessary. The `Mode` reflects the type of action that needs to be performed.
Copy and cut operations are identical, apart from the fact that cutting data will require you to delete the information after pasting it into the clipboard. To copy data to a clipboard, use any of the mechanisms supported by the `Clipboard` class, such as the `AddText()` method. Please refer to the documentation for the `Clipboard` class for more information.
To paste data from a clipboard into one of your objects, call the `GetFiles()` method to retrieve the data from the file system. You may be 'selective' in the data that you retrieve from the clipboard, for instance, if the next clip is an image and your class only supports text data, you can ignore the image and extract the text data instead. The documentation for the `Clipboard` class has more information on how to scan the data store.
## CopyData
`ERR acCopyData(Object, OBJECTPTR Dest)`
|Name|Type|Description|
|:-|:-|:-|
|Dest|OBJECTPTR|The unique ID of the destination object.|
The `CopyData` action is used to copy data between objects. To execute the copy process, call the `CopyData` action on the _source_ object, and set the `Dest` to the object that you are copying the data to. If the source object does not recognise the destination object type, it will make calls to the [`Write`](#Write) action to copy the data across. If it does understand the destination object type, it may make an 'intelligent' copy. For instance, when copying the data from one Bitmap to another, the image source will be _drawn_ to the destination.
### Implementation Details
The `CopyData` action is provided so that data in one object can be copied across to another. This may or may not involve data conversion. For example, copying data between files is a straight forward process of copying a raw binary stream. However, copying data between two Bitmaps would be more complicated, because we need to consider clipping and colour conversion issues. Copying between different classes is also permitted, for example copying an `Image` to a `File` could output the image as raw data.
If you wish to write your routine so that it only supports recognised classes, return `ERR::NoSupport` for those at are unsupported. To support all classes, include a fallback that uses the [`Write`](#Write) action to stream data to the destination object.
## DataFeed
```
ERR acDataFeed(Object, OBJECTPTR Object, DATA Datatype, APTR Buffer, INT Size)
```
|Name|Type|Description|
|:-|:-|:-|
|Object|OBJECTPTR|Must refer to the unique ID of the object that you represent. If you do not represent an object, set this parameter to the current task ID.|
|Datatype|DATA|The type of data being sent.|
|Buffer|APTR|The data being sent to the target object.|
|Size|INT|The size of the data in `Buffer`.|
The `DataFeed` action provides a mechanism for writing typed data to objects. The target `Object` will check the `Datatype` to determine if the `Buffer` content is supported, and if so, will process the data according to what is appropriate for the object's class.
The following `Datatype` values are supported:
#### DATA::CONTENT
This is a special datatype used by the `Document` class to pass XML content to embedded objects. Although this duplicates the `DATA::XML` type, it may be desirable to parse such data differently to `DATA::XML` due to nature of the content.
#### DATA::FILE
This datatype is used to declare a file path that contains the data to be transferred. It is frequently used to speed up data transfers where loading file data into a buffer and passing it through the DataFeed system would be inefficient. Set the `Size` to the path's string length, including the null byte.
#### DATA::RAW
Sending raw binary data to an object is equivalent to calling the [`Write`](#Write) action. Set the `Size` to the byte length of the data.
#### DATA::RECEIPT
In response to a `DATA::REQUEST` from an object, a `RECEIPT` must be sent to the requesting object. The receipt will contain a null-terminated XML string with the data that has been requested. Please refer to the [`DragDrop`](#DragDrop) action for further information.
#### DATA::REQUEST
The `REQUEST` datatype is intended for supporting drag and drop operations, but theoretically can be used for any type of data transfer between objects where uniquely numbered items may be used.
A request for data is achieved by passing an `Item` UID and indicating up to three types of data formats that would be accepted from the source. The `dcRequest` structure for managing the request is configured as follows:
|Field|Type|Description|
|:-|:-|:-|
|Item|INT|Item to retrieve from the source.|
|Preference|DATA [4]|Data preferences for the returned item(s).|
The datatypes indicated by the Preference field can be any of the pure datatypes supported by the `DataFeed` action, for example `DATA::TEXT` or `DATA::XML`. Any unused elements of the `Preference` array must be set to zero.
#### DATA::TEXT
Use the `TEXT` datatype when sending UTF-8 text to an object. The `Size` of the string must include the null byte.
#### DATA::XML
The XML datatype shares the same qualities as `DATA::TEXT`, but explicitly declares the content as being XML formatted. How the information is interpreted by the receiving class is context dependent. It is recommended that you check the class' documentation to see the level of support that is offered.
## Deactivate
`ERR acDeactivate(Object)`
Deactivating an object that is still in an active state from the [`Activate`](#Activate) action will cause it to halt its activity. If the object is not in an active state, this action does nothing.
### Implementation Details
A class that supports the `Activate` action should consider support for `Deactivate` if the object's active state persists beyond the original `Activate` call.
If the target object is in an inactive state at the time of the `Deactivate` call, do nothing and return `ERR::Okay` to the client.
## Disable
`ERR acDisable(Object)`
The `Disable` action is used to put an object into a state where it cannot respond to user interaction. It is typically used to temporarily "turn off" objects in the interface. For instance, disabling a `Vector` object will cause it to drop incoming user events such as button clicks and cursor motion. An object will remain in a disabled state until enabled again with the [`Enable`](#Enable) action.
Multiple calls to the `Disable` action will not nest unless the documentation for the object's class states otherwise.
### Implementation Details
The Disable action is provided for the purposes of disabling the interactive elements of an object. It is typically supported by classes that have a presence in the UI, or have some other form of user interaction.
It is important that only the user-interactive elements of the object are disabled. The object should not be disabled to the point of being useless, as non-interactive changes are still valid.
If necessary, a class can nest multiple calls to the Disable action, although this would be considered to be an exception to the rule. If you are going to support nesting, document this fact in the class.
Support for the `Disable` action should also be matched with support for the [`Enable`](#Enable) action. This will allow your disabled objects to return to a normal state, as disablement is usually only a temporary measure.
## DragDrop
`ERR acDragDrop(Object, OBJECTPTR Source, INT Item, STRVIEW Datatype)`
|Name|Type|Description|
|:-|:-|:-|
|Source|OBJECTPTR|Refers to the object containing the source data.|
|Item|INT|An item ID, relevant to the source object.|
|Datatype|STRVIEW|A sequence of DATA values indicating the types of data supported by the source item. Priority is given to the first.|
The `DragDrop` action provides the core functionality of a universal drag and drop system. The process of drag and drop works as follows:
1. The user initiates a drag and drop operation by clicking and holding the mouse button on an interface item.
2. The owner of that item will monitor click and motion activity that could instigate a drag and drop operation.
3. On detecting the initial stages of the drag and drop operation, the object will create a new graphics `Surface` utilising the `COMPOSITE` and `STICK_TO_FRONT` flags. The Display API's `StartCursorDrag()` function is called to link this surface to the mouse pointer. No further action needs to be taken until the mouse button is released.
When the item is dropped by releasing the mouse button over a `Surface`, the following occurs:
1. The mouse pointer will hide the draggable surface that was attached to it.
2. The `DragDrop` action will be called on the surface that is under the pointer's hot spot. The `Source`, `Item` number and datatype originally passed to `StartCursorDrag()` will be included in this action call.
3. If a listener is subscribed to the `DragDrop` action of the targeted surface, it will be able to respond to the drag and drop operation. The listener will need to send a `DATA::REQUEST` via the [`DataFeed`](#DataFeed) action to the object that is referenced in the `Source` parameter. The listener can indicate supported datatypes that it will accept from the source (see the `DataFeed` action for further information) and the Item number received from the `DragDrop` action.
4. The source object will respond by sending a `DATA::RECEIPT` message via the [`DataFeed`](#DataFeed) action. This contains the item data in one of the requested formats.
Data for drag and drop activity is defined in XML format. The following template must be adhered to:
```
`
A choice can be made between defining a `path` or `object`. The `object` must belong to the `Sound` class.
#### DATA::FILE
``
#### DATA::IMAGE
``
A choice can be made between defining a `path` or `object`. The object must belong to either the `Image` or `Bitmap` classes.
#### DATA::RAW
``
A choice can be made between defining a `path` or `object`. The object must support the `Read` action for reading the data.
#### DATA::TEXT
`[UTF8Content]`
#### DATA::XML
`[XMLContent]`
### Implementation Details
To support drag and drop, do not write a routine specifically targeting the `DragDrop` action. Instead, use `SubscribeAction()` to listen to the `DragDrop` action of the surface that is used by your object. In response to the receipt of a `DragDrop` action, send a `DATA::REQUEST` (via data feed) to the indicated Source object. The rest of your support code for drag and drop will need to be written in your [`DataFeed`](#DataFeed) support routine.
## Draw
```
ERR acDrawArea(Object, INT X, INT Y, INT Width, INT Height)
ERR acDraw(Object)
```
|Name|Type|Description|
|:-|:-|:-|
|X, Y|INT|The top-left position of the region to be drawn.|
|Width, Height|INT|The size of the region to be drawn.|
This action will draw an object's graphics, either to the video display or to a virtual drawing space, according to the object state and class specifications. If the object is not linked to a drawable area, or if the object belongs to a non-graphical class, calling this action will usually have no effect and an error code will be returned.
The dimension parameters specify the size of the region that will be drawn. The `Width` and `Height` can both be zero if the entire region of the object should be drawn.
### Implementation Details
The `Draw` action is provided for classes that need graphics support. The client should configure the object with sufficient information to draw something of value. A 'target' field will be needed in the class spec so that `Draw` has an appropriate graphics destination. The exact technical details of the process are for you to define.
The dimension parameters are provided so that the client can declare the precise region that needs to be drawn. Supporting these parameters is optional - if they are not appropriate for the class, ignore them.
## Enable
`ERR acEnable(Object)`
The Enable action is provided for the purposes of reactivating objects that have been disabled with the [`Disable`](#Disable) action. When an object is enabled, it should be operating in its normal state.
### Implementation Details
The Enable action is implemented as a counter to `Disable`. If your `Disable` code includes support for nesting then you will also need to take this into consideration.
If an `Enable` call is made to an object that is not disabled, do nothing and return `ERR::Okay`.
## Flush
`ERR acFlush(Object)`
This action will flush all buffered data from an object. Flushing can be useful when applied to I/O based objects that buffer data to speed up processing times. As a result of flushing, unwritten data will either be dumped to its physical location or related output device, depending on the object specifications.
Note that any object using a buffering technique will automatically flush its data when you [`Free`](#Free) it.
### Implementation Details
Flush is a useful action for buffered objects such as files, as it ensures that buffered content is permanently saved to its destination. Novel applications for data flushing are also possible, for instance the flushing of a series of graphics commands to the display would be valid. In general, if a class is designed to buffer content then giving consideration for `Flush` should be a priority.
## Focus
`ERR acFocus(Object)`
The `Focus` action is primarily used within the UI for focussing on interactive widgets. Objects supporting the `Focus` action are typically members of the Drawable category, of which the `Surface` and `Vector` classes currently qualify.
When a drawable object receives the focus it will usually do very little, but external objects that are listening for focus activity will respond to the change accordingly. For instance, input based objects within surface areas often listen to focus changes so that they know when to start responding to keyboard input.
### Implementation Details
This action is usually called on drawable objects (e.g. `Surface` objects) when the user interacts with them. Your class should only support this action if it is used in an area that is in close proximity to the user's actions.
If your class requires notification when a drawable object has received the focus, do not write support for the `Focus` action. You should instead use the `SubscribeAction()` function to listen to the `Focus` action of the drawable object that you are interested in.
If your class needs to be informed when one of its objects has lost the focus, support the [`LostFocus`](#LostFocus) action.
## Free
`ERR FreeResource(Object)`
Objects are permanently removed with the `Free` action, which is achieved via a call to `FreeResource()`. If the object has one or more child objects attached to it, they will also be removed as a result of calling this action. After calling `Free`, remove any UID and pointer references to the object as a measure of bug prevention.
If an exclusive lock is active at the time of calling `Free`, the object will be _marked for deletion_ only. The object will not be permanently removed until the last lock is released.
> [!NOTE]
> The means of terminating an object can vary between languages. C++ uses `FreeResource()`, while in Tiri, objects are manually terminated with the `obj:free()` interface, or automatically via garbage collection. The specifics of this should be documented in your language of choice.
### Implementation Details
`Free` support is essential for all classes that allocate resources. It is correctly implemented by removing all resources that were created during an object's life-cycle.
Derived classes need to support this action if their code tracks resources seperately to the base class. To prevent allocations between a base class and derived class from being confused, the fields that reference resources should be driven to `NULL` after their termination. If your derived class requires its own private data area for resource management, the `DerivedPtr` field is available for this purpose.
## FreeWarning
This is an internal action that is used for receiving a warning prior to an object being freed. It should never be called from client code.
### Implementation Details
`FreeWarning` is useful for preventing an object from being terminated when it is in an unready state. This is achieved by returning an error code of `ERR::InUse`. All other error codes are ignored.
If an object is in a `collecting` state, for instance if the app is shutting down, then it will not be possible to abort termination. If this is an important factor for your code, use the C++ `collecting()` method to verify the object's state.
## GetKey
`ERR acGetKey(Object, STRVIEW Key, std::string &Value)`
|Name|Type|Description|
|:-|:-|:-|
|Key|STRVIEW|The name of a key value.|
|Value|STRING|A reference to a string that will receive the retrieved value.|
The `GetKey` action is used to retrieve custom key-values from an object. Keys can either be functional, as is the case for `XML`'s xpath support, or they can be created by the client using [`SetKey`](#SetKey).
To retrieve a key-value, set the `Key` and the matching value will be returned in the `Value` string. If the requested `Key` does not exist, `Value` will be cleared.
`Key` names are case-insensitive unless documented otherwise. If the requested `Key` doesn't exist, `ERR::UnsupportedField` will typically be returned from the object's class.
### Implementation Details
If your class design allows for key-values then you will need to support `GetKey`. This can include support for functional keys, which are key names that are documented in advance and backed by coded functionality. The `XML` class is one such example that does this to support the xpath standard.
Keys should be case-insensitive by default. If this is not the case, document this fact for the client.
If the requested `Key` does not exist, return an error code of `ERR::UnsupportedField`.
Adequate documentation for the client is strongly recommended when supporting this action.
## Hide
`ERR acHide(Object)`
Hiding is used to remove objects from the sight of the user. Examples of this include hiding `Vector` and `File` objects. Use the [`Show`](#Show) action to make the object visible again.
### Implementation Details
If a class represents objects that are visible to the user (for example, a UI class) then being able to control that visibility is usually necessary.
If the visible state of the object is already hidden, do nothing and return `ERR::Okay`.
Changing the visible state of a graphics object can trigger a redraw of the display, but this is at your discretion. Documenting whether or not the changes will be immediately visible is advised.
`Hide` and `Show` should always be supported in tandem as would be expected by the client.
## Init
`ERR acInit(Object)`
This action initialises objects so that they can be used for their intended purpose. The process of initialisation is compulsory, and _you may not use any other actions on an object until it has been initialised_. Exceptions to this rule only apply to the [`Free`](#Free), [`GetKey`](#GetKey) and [`SetKey`](#SetKey) actions.
If the initialisation of an object fails due to a support problem (for example, if you ask an `Image` object to load a TIFF image when it only supports PNG), the `Init` action can look for a derived class that handles the data. If a supporting derived class exists, a partial transfer of ownership will occur and the object's management will be shared between both the base class and the derived class.
Part of the initialisation process is to check a client's configuration settings up-front, and a suitable error code will be returned if these checks are failed.
C++ users can check the initialisation state of an object by calling its `initialised()` method.
### Implementation Details
This action is called when a program initialises an object that belongs to your class. The purpose of this action is to prepare the object for the necessary handling for other actions such as `Draw`, `Activate`, `Show` etc.
Data-centric classes that fail to recognise the source data should always return `ERR::NoSupport` (e.g. a PNG class cannot process a JPEG file). Your code should also strive to keep the object state untarnished. The initialisation manager will look for a derived class that can support the object correctly. If your class supports the data but initialisation fails due to a system error or similar, return any error-code other than `ERR::NoSupport` and `ERR::Okay`. This will cause the initialisation process to fail immediately and return to the program.
It is a requirement that the object state is sufficiently validated when `Init` is called. Do not assume that the object is configured correctly by the client.
Never free an object from inside its own initialisation routine; this is a matter for the client.
## Lock
`ERR acLock(Object)`
The `Lock` action can be used on an object when you don't want it to be moved, deleted or otherwise altered by other processes for a period of time. This is commonly needed for files.
Each initial and subsequent calls to Lock must be matched with calls to the [`Unlock`](#Unlock) action, because locks will nest. Once all locks have been removed, manipulation of the object is possible again. The following conditions apply to locking behaviour:
* Other tasks _may_ be able to gain limited access to the object's data after you have locked it (e.g. locking a file may prevent writing, but other processes could still read the file). The class should document this behaviour. If it doesn't, work on the assumption that other processes will have read access to the object's data.
* The object will be fixed in place and cannot be moved or deleted, even by your own process, until it is unlocked.
* If you [`Free`](#Free) a locked object, its class will automatically reverse all locks that exist at the time of termination.
Please be aware that the `Lock` action and `LockObject()` are functionally very different. To clarify, the `LockObject()` function is used to gain exclusive, temporary access to the use of an object's interface. It has no impact on the material use of the underlying data that the object might be referencing.
### Implementation Details
Locking is provided for developers that need to prevent object data from being altered. Locks can either be shared or exclusive to processes, depending on what is suitable for the object and its class.
As a result of locking, the object will be fixed in place and cannot be moved or deleted, even by the process that holds the lock, until the object is unlocked with the `Unlock` action. As the developer, you have a responsibility to enforce your own rules to support locks. Feel free to place other restrictions on the object where appropriate.
Detailed documentation on locking behaviour is strongly recommended for the client.
Supporting the [`Unlock`](#Unlock) action is required in tandem with `Lock`. Multiple locking calls are expected to nest, and a counter should be used to ensure that this is the case.
## LostFocus
This is an internal action managed by the `Surface` class. It should never be called by the client.
### Implementation Details
This action is automatically called on `Surface` objects when they lose the user focus. Other UI classes are not expected to support it.
## Move
`ERR acMove(Object, DOUBLE DeltaX, DOUBLE DeltaY, DOUBLE DeltaZ)`
|Name|Type|Description|
|:-|:-|:-|
|DeltaX, DeltaY, DeltaZ|DOUBLE|The number of units to move along each axis.|
The `Move` action is provided to move graphical objects to a new position. Coordinates are specified as a delta, so the current position of the object will be taken into account. If the current coordinates of an object are needed to compute the desired target position, reading the `X` and `Y` fields is the most typical way of doing so.
Note: The `DeltaZ` parameter is ignored if the target does not support three dimensions.
The [`MoveToPoint`](#MoveToPoint) action may also be available as an alternative choice to `Move`, and uses absolute positioning.
### Implementation Details
If a class supports a coordinate system (typically the case for all graphics classes) then supporting the `Move` action is advised. Movement is achieved with delta values, so the current X, Y and Z positions will need to be tracked and available to the client via equivalent field values.
If there is a limit as to how far an object can move in any direction, keeping the object to the edge of its bounds is permitted. You should still return an error code of `ERR::Okay` in cases where it was not possible to move by the requested amount.
## MoveToBack
`ERR acMoveToBack(Object)`
The `MoveToBack` and `MoveToFront` actions are used for shuffling objects to the back or front of their containers. Generally this is applied to graphics classes, but other class types can support these actions for sorting purposes.
In some instances it may not be possible for an object to be moved completely to the front or back, in which case the object will move as close to the requested position as possible. This situation will typically occur when groups of objects are locked to their position, preventing others from being promoted ahead of them.
### Implementation Details
Support `MoveToBack` and `MoveToFront` to allow the client to make adjustments to the sort order of overlapping objects.
If your class supports the `Lock` action, it may be appropriate for locked objects to hold their position when at the front of the queue. This is a design choice, so documenting the class' behaviour in this area is recommended.
## MoveToFront
`ERR acMoveToFront(Object)`
The `MoveToBack` and `MoveToFront` actions are used for shuffling objects to the back or front of their containers. Generally this is applied to graphics classes, but other class types can support these actions for sorting purposes.
In some instances it may not be possible for an object to be moved completely to the front or back, in which case the object will move as close to the requested position as possible. This situation will typically occur when groups of objects are locked to their position, preventing others from being promoted ahead of them.
### Implementation Details
Support `MoveToBack` and `MoveToFront` to allow the client to make adjustments to the sort order of overlapping objects.
If your class supports the `Lock` action, it may be appropriate for locked objects to hold their position when at the front of the queue. This is a design choice, so documenting the class' behaviour in this area is recommended.
## MoveToPoint
`ERR acMoveToPoint(Object, DOUBLE X, DOUBLE Y, DOUBLE Z, MTF Flags)`
|Name|Type|Description|
|:-|:-|:-|
|X, Y, Z|DOUBLE|The new position to move the object to.|
|Flags|MTF|Set the relevant `MTF` flag for each provided parameter.|
The `MoveToPoint` action is provided to move graphical objects to a new position. The shift to the new position is immediate, but may be subject to certain conditions - for instance it may not be possible to move to negative coordinates. Limitations may be circumstantial and subject to class specifications. An `ERR::Okay` code will be returned irrespective of whether or not movement to the requested position was succesful. The coordinates of the object can be confirmed after the move by reading the `X` and `Y` fields.
The client is required to set the `MTF::X`, `MTF::Y` and/or `MTF::Z` flags according to the parameters that were specified. This feature allows you to move the object to a specific horizontal coordinate without altering the vertical position, for example.
The [`Move`](#Move) action may also be available as an alternative choice to `MoveToPoint`, and uses relative positioning.
## NewChild
|Name|Type|Description|
|:-|:-|:-|
|NewChild|OBJECTPTR|Pointer to the new child.|
For internal use only.
### Implementation Details
The `NewChild` action is used to alert an object that it has inherited a new child from the Core's `SetOwner()` function. By supporting this action you can respond to the presence of new children immediately, as well as preventing objects from forming an attachment if they fail your own criteria (return an error code to do this).
In some circumstances it may be necessary for a new child to be forwarded to another object that is better suited as the owner. To do this legitimately, call the `SetOwner()` function to forward the child to the other object, then return `ERR::OwnerPassThrough`. Any other error code will be interpreted as failure, which would cause the process to abort.
## NewOwner
|Name|Type|Description|
|:-|:-|:-|
|NewOwner|OBJECTPTR|Pointer to the new owner.|
For internal use only.
### Implementation Details
The `NewOwner` action is used to alert an object that its owner has been changed successfully. Supporting this action provides an opportunity to respond to the change before the client next uses the object.
The error code returned by your function will have no effect on the `SetOwner()` process.
## NewObject
For internal use only.
### Implementation Details
`NewObject` is called when a new object instance from your class has been created. It is recommended that your support routine performs the bare necessities only, meaning the setting of default values and allocating resources without initialising them. Anything more important should occur in the `Init` action.
Returning an error code will cause the object creation process to fail.
## NewPlacement
For internal use only.
### Implementation Details
`NewPlacement` is called during the in-place construction of a new object, immediately after the raw memory has been allocated and the `Object` header has been initialised. It exists for classes that need to construct C++ members in-place before the standard `NewObject` hook runs.
The object context is not yet established at this stage, so allocations that pass through `AllocMemory()` are not permitted; defer any such work to the `NewObject` hook. Where a derived and base class both provide `NewPlacement` support, the derived class takes priority.
Returning an error code will cause the object creation process to fail.
## Next
`ERR acNext(Object)`
The `Next` and [`Prev`](#Prev) actions are used to traverse a sequence of related objects, such as the entries in a list or a chain of sibling objects. Calling `Next` advances to the object that follows the target in its sequence.
The meaning of 'next' is defined by the object's class, so consult the class documentation to confirm the behaviour and how the resulting position is reported. If the target has no successor, `ERR::NothingDone` is typically returned.
### Implementation Details
Support `Next` if your class represents a member of an ordered sequence and forward traversal is meaningful. Pair it with [`Prev`](#Prev) so that the client can move in either direction.
## Prev
`ERR acPrev(Object)`
The `Prev` and [`Next`](#Next) actions are used to traverse a sequence of related objects. Calling `Prev` moves to the object that precedes the target in its sequence.
The meaning of 'previous' is defined by the object's class, so consult the class documentation to confirm the behaviour and how the resulting position is reported. If the target has no predecessor, `ERR::NothingDone` is typically returned.
### Implementation Details
Support `Prev` if your class represents a member of an ordered sequence and backward traversal is meaningful. Pair it with [`Next`](#Next) so that the client can move in either direction.
## Query
`ERR acQuery(Object)`
Calling the `Query` action will update the target object's state to match its source, typically in the form of a file or hardware device.
Check the class documentation for the target object before utilising `Query`, as the exact nature of the process will be implementation dependent.
### Implementation Details
`Query` is useful action for ensuring that an object's state is reflective of the external source that it represents. Classes that are linked to some form of hardware will often benefit by supporting it. A basic example is the `Time` class, which updates its time values whenever `Query` is used.
It is advised that your documentation specifies the exact fields that are updated after a successful `Query` call.
## Read
`ERR acRead(Object, APTR Buffer, INT Length, INT *Result)`
|Name|Type|Description|
|:-|:-|:-|
|Buffer|APTR|Points a buffer that will receive the data.|
|Length|INT|The total number of bytes to read from the object. This value cannot exceed the size of the `Buffer`.|
|Result|INT|The Read action will write this parameter with the total number of bytes read into the `Buffer`.|
Use the `Read` action to read data from an object and into a supplied memory buffer. While commonly used for file I/O, `Read` is useful for many situations involving the streaming of data from an external source.
Making a `Read` call will result in the object reading the total number of bytes defined by `Length` into the provided `Buffer`. If the class supports a seek marker, the read will start from the `Position` field's index. The `Position` will be incremented by the amount of bytes read if the call succeeds. Altering the position of the seek marker is possible with the [`Seek`](#Seek) action, if the class supports it.
If the `Length` exceeds the total number of bytes left in the object, `Read` will only read as many bytes as there are available. If the class supports a `Size` field then it can be used to determine the number of bytes that are left to read.
The `Result` parameter will be updated to reflect the total amount of data that was read into the supplied `Buffer`. If an error occurred, or if no data is left to read, the `Result` will be set to zero.
### Implementation Details
The `Read` action is commonly used to read data from files, but can theoretically be used in any circumstance involving data storage and streaming content.
The `Buffer` parameter points directly to the area that will receive data from your object. The `Length` will indicate the number of bytes that a program wants to retrieve. If the `Length` is larger than the amount of data that is available, write out the full amount of data remaining.
Your class should support a `Position` field to indicate the current byte position from which the `Read` action will start. Increment the `Position` by the number of bytes that were read from the object's data store before returning to the client. Also consider supporting the [`Seek`](#Seek) action to manipulate the `Position` value.
Your class should also support a `Size` field if the total amount of available data is a known quantity. If the source is a stream of unknown size then the `Size` should be set to zero, and the client should be given a means to determine that the source is streaming.
Before returning, your support routine must set the `Result` parameter to indicate the total amount of bytes that were read from the object. If no data is available to read, return `ERR::Okay` and make sure that the `Result` is set to zero.
## Redimension
`ERR acRedimension(Object, DOUBLE X, DOUBLE Y, DOUBLE Z, DOUBLE Width, DOUBLE Height, DOUBLE Depth)`
|Name|Type|Description|
|:-|:-|:-|
|X, Y, Z|DOUBLE|The new position to apply to the target object.|
|Width, Height, Depth|DOUBLE|The new size of the target object.|
Use `Redimension` to reposition and resize an object in a single action call. This is considered to be more optimal than moving and resizing an object with sequential calls to the `Move` and `Resize` actions. By default, the target object will be redrawn automatically as a result of calling this action.
If the target contains other drawable objects, they will often respond by adjusting their dimensions to the new size. The exact result will depend on their configuration.
Setting any of the `Width`, `Height` and `Depth` values to zero is permitted if the existing dimension should be unchanged.
The `Depth` parameter is typically used for objects supporting a Z-order or Z-axis, and can be set to zero if not applicable. If the `Z` coordinate represents a scale factor, a setting of `1.0` would represent the normal size of the target object.
## Redo
`ERR acRedo(Object, INT Steps)`
|Name|Type|Description|
|:-|:-|:-|
|Steps|INT|The number of undo operations to reverse.|
Calling Redo will reverse previous calls to the [`Undo`](#Undo) action. The `Steps` value defines how many operations to redo and can be set to one for a single step. This action can be called once for every previous call to Undo. If there is nothing to redo, `ERR::NothingDone` will be returned.
## Refresh
`ERR acRefresh(Object)`
Some classes support the `Refresh` action if their objects represent external data sources. For example, the Document class can be refreshed if the source has changed.
If a `Refresh` action fails, the object should remain in its original state unless the object's class states otherwise.
### Implementation Details
A class that represents a view of an 'external' data source should typically support the `Refresh` action. The purpose of a refresh is to re-read the origins of an object's data and then update the object to reflect any differences between the object and its data source.
If the refresh process fails, avoid allowing the object to fall into an invalid state. It is recommended that either the object is left in its original state, or that the object reports the error in a way that makes it known to the user.
## Rename
`ERR acRename(Object, STRVIEW Name)`
|Name|Type|Description|
|:-|:-|:-|
|Name|STRVIEW|The new name for the object.|
Objects that support naming conventions will typically support the `Rename` action. The `File` class is a typical example of a class that provides this kind of support to change filenames.
`Rename` does not impose limits on the length of the supplied `Name`, but the underlying system might; for instance all filesystems impose a hard limit on filename length.
### Implementation Details
If your class supports naming (e.g. for the purpose of representing a data location such as a filename) then support the `Rename` action. If there is a limit on the number of characters that are supported by your code, document this restriction in the class manual.
## Reset
`ERR acReset(Object)`
Using `Reset` on an object will revert its state to one that is similar to when it was first initialised.
The exact behaviour of a reset is class dependent, but as a rule, object data will not be destroyed as a result of calling this action (the [`Clear`](#Clear) action is typically used for this purpose). A common example of a reset is to [`Seek`](#Seek) back to a position of zero, stop any currently running activity, then reset the object state back to normal.
Be wary of confusing the consequences of a `Reset` with the [`Flush`](#Flush) action. Some objects will flush themselves as a consequence of a `Reset`, but the key difference is that calling [`Flush`](#Flush) will not result in a change of state.
### Implementation Details
The most common reason for supporting the `Reset` action is to allow an object to get back to its most basic state, similar to when the object was first initialised. Examples could be resetting a file position back to the beginning, or restarting a running procedure from scratch.
It is strongly recommended that you do not destroy any data in your support routine, but you may manipulate the object's state as required.
## Resize
`ERR acResize(Object, DOUBLE Width, DOUBLE Height, DOUBLE Depth)`
|Name|Type|Description|
|:-|:-|:-|
|Width, Height, Depth|DOUBLE|The new size of the object.|
The `Resize` action is used to alter the size of an object with a single action call. Resizing is commonly used in the UI for manipulating vector dimensions.
If a resized object contains other drawable objects, they may respond to the resize by adjusting their dimensions to the new size. The exact result will dependent on their configuration.
Setting any of the `Width`, `Height` and `Depth` values to zero is permitted if the existing dimension should be unchanged.
## SaveImage
`ERR acSaveImage(Object, OBJECTPTR Dest, CLASSID ClassID)`
|Name|Type|Description|
|:-|:-|:-|
|Dest|OBJECTPTR|Refers to an object that will receive the encoded image data.|
|ClassID|CLASSID|The `Image` class to use for encoding the image data.|
`SaveImage` is used to save an object's graphics to a storage object of your choosing. The process of saving the image will leverage the `Image` class, which by default saves images in PNG format. If an alternative image format provided by a `Image` derived class is desired, it can be referenced in the `ClassID` parameter. For instance, specifying `ID_JPEG` in `ClassID` is sufficient to save an image in JPEG format.
The object referenced in `Dest` must be from a class that supports the [`Write`](#Write) action. Typically this would be a `File` object, but this is not imposed as a restriction.
In some cases, the `SaveImage` and [`SaveToObject`](#SaveToObject) actions will both save image information (for example the `Image` and `Bitmap` classes will do this) but objects that can be represented as an image and in a native data format will make a clear distinction between the two.
### Implementation Details
This action is provided for classes that wish to make a distinction between the image of an object and the data of an object. For instance, using `SaveToObject` on a GUI object could store its meta information, while `SaveToImage` can save the object as it is seen by the user.
When supporting this action you must save the image using the `Image` class so that the data can be saved in the user's preferred format.
## SaveSettings
`ERR acSaveSettings(Object)`
The SaveSettings action exists to simplify the saving of configuration information to a default file path. In some classes it can also save altered object data back to its origin file.
## SaveToObject
`ERR acSaveToObject(Object, OBJECTPTR Dest, CLASSID ClassID)`
|Name|Type|Description|
|:-|:-|:-|
|Dest|OBJECTPTR|Refers to an object that will receive the encoded data.|
|ClassID|CLASSID|Can refer to a derived class that should be used when encoding the data.|
This action will save an object's data to a storage object of your choosing. The data will be saved in a file format that can be reloaded at a later time using the same class.
The object referenced in `Dest` must be from a class that supports the [`Write`](#Write) action. Typically this would be a `File` object, but this is not imposed as a restriction.
The `ClassID` is optional, and can be used to specify a derived class that is preferred for encoding the object data. For example, the `Sound` class supports WAV data by default, but we could save audio in MP3 format if the `MP3` class was referenced here.
### Implementation Details
By supporting the `SaveToObject` action, you can make it possible to save an object's data to a `File` or similar data storage object.
It is a requirement that the data being saved can be loaded by the class at a later time.
## Seek
```
ERR acSeek(Object, DOUBLE Offset, SEEK Position)
ERR acSeekStart(Object, DOUBLE Offset)
ERR acSeekEnd(Object, DOUBLE Offset)
ERR acSeekCurrent(Object, DOUBLE Offset)
```
|Name|Type|Description|
|:-|:-|:-|
|Offset|DOUBLE|The desired offset to seek to, relative to the `Position` parameter.|
|Position|SEEK|The position that defines the starting point for `Offset`.|
The `Seek` action defines the next read/write position for the [`Read`](#read) and [`Write`](#write) actions. In some cases this can affect live tracking, for instance seeking to a new position in an active `MP3` object has an immediate effect on audio playback.
The `Position` can be set to `SEEK::START`, `SEEK::CURRENT` or `SEEK::END` to indicate the relative start position. For example, +20 from `SEEK::CURRENT` is `20` bytes from the current position, while `-20` would be `20` bytes back from the current position. In `SEEK::START` and `SEEK::END` modes the `Position` should be unsigned; if the value is negative then the sign will be dropped.
You cannot seek beyond the 'end' of an object, nor can you seek to a position less than zero.
To get the current position of an object, read its `Position` field.
### Implementation Details
A class that supports the `Read` and `Write` actions should support `Seek` wherever possible. Seeking is used to position the 'read/write head' so that the next time some I/O occurs, it will start at the seeked position.
Your class is required to define a `Position` field that always reflects the current byte position in your object's data. When the `Seek` action is called, the `Position` must be altered to reflect the absolute byte position that the program has seeked to.
When writing your support routine, you must write code for each of the three different modes - `SEEK::START`, `SEEK::CURRENT` and `SEEK::END`. `SEEK::START` refers to the beginning of the data, `SEEK::CURRENT` refers to the current byte position and `SEEK::END` refers to the end of the data. The `Position` parameter can be either negative or positive when used in conjunction with `SEEK::CURRENT`, but in the `SEEK::START` and `SEEK::END` modes the sign of the `Position` is ignored (i.e. read it as an absolute value and then offset in the appropriate direction).
Seeking beyond the boundaries of an object's data is not permitted. If the client makes such a request, the new position value must be clamped and `ERR::Okay` should still be returned.
## SetKey
`ERR acSetKey(Object, STRVIEW Key, STRVIEW Value)`
|Name|Type|Description|
|:-|:-|:-|
|Key|STRVIEW|The name of the target key.|
|Value|STRVIEW|The string value to associate with `Key`.|
The `SetKey` action is used to set custom key-values on an object. Keys can either be functional, as is the case for `XML`'s xpath support, or they can be created by the client ad-hoc and permanently stored with the object.
`Key` names are case-insensitive unless documented otherwise, and can be retrieved with the [`GetKey`](#getkey) action.
### Implementation Details
If your class design allows for key-values then you will need to support `SetKey` as the mechanism for setting the values.
The general recommendation for C++ developers to use a `std::unordered_map` to store the key values. Be sure that your method can overwrite existing values when the same key is set more than once.
Keys should be case-insensitive by default. If this is not the case, document this fact for the client.
Please note that if you support this action then it is recommended that you provide a reasonable amount of documentation so that the developer knows just how your class supports key values.
## Show
`ERR acShow(Object)`
Calling this action will make the target object visible to the user. While graphics objects are the obvious use-case for this action, non-visual objects such as files can also support visibility changes.
Showing an object that is already visible has no effect. To make the target object invisible, call the [`Hide`](#Hide) action.
### Implementation Details
If a class represents objects that are visible to the user (for example, a UI class) then being able to control that visibility is usually necessary.
If the visible state of the object is already `true`, do nothing and return `ERR::Okay`.
Changing the visible state of a graphics object can trigger a redraw of the display, but this is at your discretion. Documenting whether or not the changes will be immediately visible is advised.
`Hide` and `Show` should always be supported in tandem as would be expected by the client.
## Signal
`ERR acSignal(Object)`
The signalling of objects is a feature created specifically for the Core API's `WaitForObjects()` function. By calling `Signal` on an object that has been referenced in a `WaitForObjects()` call, the process will be woken up.
Further detail is available in the `WaitForObjects()` documentation.
## Undo
`ERR acUndo(Object, INT Steps)`
|Name|Type|Description|
|:-|:-|:-|
|Steps|INT|The number of recorded operations to reverse.|
The `Undo` action reverses the last activity performed by the object. The `Steps` value defines how many operations to reverse and can be set to one for a single step. Objects that support this action maintain an internal stack of operations that have been performed since the creation of the object (subject to undo buffer limits). You may call `Undo` for as many operations as have been recorded on the stack.
There is no distinction between user and automated operations performed against the object's data - both are treated equally.
Some class types may need to be configured before they will initialise an undo buffer that can be utilised by this action.
## Unlock
`ERR acUnlock(Object)`
The `Unlock` action complements [`Lock`](#lock) in order to provide the necessary means for releasing locks. Unlocking an object will release all the locking conditions that have been placed on it (but bear in mind that multiple locks will nest).
If you [`Free`](#Free) an object that is still under lock conditions, the object will automatically unlock itself.
## Write
`ERR acWrite(Object, APTR Buffer, INT Length, INT Result)`
|Name|Type|Description|
|:-|:-|:-|
|Buffer|APTR|A buffer containing the data that will be written to the object.|
|Length|INT|The total number of bytes to write to the object.|
|Result|INT|This parameter with be updated with the total number of bytes written from the buffer.|
Use the `Write` action to write data from a buffer to an object. While commonly used for file I/O, `Write` is useful for many situations involving the streaming of data to an external source.
Making a `Write` call will write `Length` number of bytes from the provided `Buffer` to the object. If the class supports a seek marker, it will start the write operation from the point determined by the `Position` field. The `Position` field will be incremented to `Position + Length` if the call succeeds. Altering the position of the seek marker is possible with the [`Seek`](#Seek) action, if the class supports it.
If the object is at capacity then it may attempt to increase its space to write out the entire `Buffer` that has been provided. If it cannot do this, it will attempt to write as much information as possible and return an `ERR::Okay` code. If it cannot write out any data, it will return a fail code. If the object's class has a `Size` field, this may be expanded as a result of the call.
To confirm how much data was written after a successful `Write` call, check the `Result` parameter and compare it to the `Length` that was supplied.
### Implementation Details
The `Write` action is commonly used to write data to files, but can theoretically be used in any circumstance involving data storage and streaming content.
If the `Length` exceeds the total amount of space available for writing data and nothing further can be written, return an error code of `ERR::LowCapacity`.
Your class should support a `Position` field to indicate the current byte position from which the `Write` action will start. Increment the `Position` by the number of bytes that were written to the object's data store before returning to the client. Also consider supporting the [`Seek`](#Seek) action to manipulate the `Position` value.
Your class should also support a `Size` field if the size of its objects is discrete. If an object is functioning as a stream, the `Size` should be set to zero, and the client should be given a means to determine that the object is in streaming mode.
Before returning to the client, your support routine must set the `Result` parameter to indicate the total number of bytes that were written to the object.