Command(3U)
π Command(3U) π
okay so bestie, welcome to Command, straight out of the InterViews Reference Manual (section 3U). this is a big-deal page, so grab a snack π
β¨ NAME β¨
Command β the base class for command objects. that's it, that's the whole name. iconic.
πΈ SYNOPSIS πΈ
#include <Unidraw/Commands/command.h>
π¦ DESCRIPTION π¦
Command is an abstract base class for objects that define operations on components and other objects. no cap.
Commands are lowkey the same energy as messages in traditional object-oriented systems β components can receive them and respond to them. but also, commands can be executed in isolation to perform arbitrary computation, and they can reverse the effects of that execution to support undo. the range, honestly.
so here's the taxonomy, pay attention:
- some commands β called purely interpretive commands β get interpreted by components but are never executed in isolation.
- some are executed but never interpreted (non-interpretive commands).
- some are used both ways. main character behaviour.
- some commands may be directly accessible to the user through menus, while others are internal to the application.
- in general, an undoable operation should be carried out by a command object. that's the rule, periodt.
π₯ PUBLIC OPERATIONS π₯
virtual void Execute()virtual void Unexecute()virtual boolean Reversible()
Execute performs computation to carry out the command's semantics. Unexecute performs computation to reverse the effects of a previous Execute, based on whatever internal state the command maintains. a command is responsible for maintaining enough state to reverse one Execute operation; repeated Unexecute operations will not undo the effects of more than one Execute. so like, one undo per undo, bestie.
by default, Execute examines the current selection maintained in the command's editor (see below π). Execute will do nothing if nothing is selected and the command's clipboard (see below) is empty or non-existent. otherwise, if something is selected and the command's clipboard is non-existent, then Execute creates a clipboard containing the selected component subjects. finally, Execute will tell each component on the command's clipboard to interpret this. conversely, Unexecute tells each component on the clipboard (if any) to Uninterpret this. thus, commands are purely interpretive by default. that's just their default setting, their factory reset, their natural state π§
it may not be meaningful or appropriate, however, for some commands to reverse their effect. for example, it is probably not feasible to undo a command that generates an external representation. π
the Reversible operation returns whether or not the command is unexecutable and uninterpretable. if the command is irreversible, then it is ignored during the undo process. by default, Reversible examines the command's clipboard; if the command doesn't have one, then the command is reversible if the user has at least one component view selected. if the command has a non-empty clipboard, then it is deemed reversible. subclasses may redefine Reversible to base the command's reversibility on their own criteria. you do you, subclass π
virtual void Store(Component*, Data* = nil)virtual Data* Recall(Component*)
since a command can affect more than one component, commands must let components that interpret them store undo information somewhere. the commands must also let components recall that information during uninterpretation. Store lets a component store a Data object in the command itself as part of the component's interpretation process. the component can later retrieve the data with the Recall operation. Store and Recall require a Component argument to distinguish requests from potentially many components. it's giving group chat with multiple threads, honestly.
virtual void Log()
a convenience function for calling the equivalent function on the global unidraw object. little shortcut, tiny slay β¨
virtual void SetControlInfo(ControlInfo*)virtual void SetEditor(Editor*)virtual void SetClipboard(Clipboard*)virtual ControlInfo* GetControlInfo()virtual Editor* GetEditor()virtual Clipboard* GetClipboard()
operations for setting and getting constructor-specified state stored in the command. commands use a ControlInfo object to store information from which to build a user interface for executing the command. commands keep a pointer to the Editor instance they potentially affect. finally, a command uses a clipboard to store the components it affects or affected. a clipboard containing the components to be affected can be supplied in the constructor, but more often the command itself creates and primes a clipboard based on the editor's selected components.
β οΈ the Set... operations do not delete the object being replaced. no cleanup, no mercy, it just moves on. π
virtual void First(Iterator&)virtual void Last(Iterator&)virtual void Next(Iterator&)virtual void Prev(Iterator&)virtual boolean Done(Iterator)
operations for iterating over the command's children, if any. these operations do nothing by default. commands that compose other commands should redefine these operations to permit traversal of their children. First and Last initialize an iterator to point to the beginning and end of the list of children, respectively. Next increments the iterator to point to the following child, while Prev decrements the iterator to point to the preceding child. Done returns whether or not the iterator points beyond the first or last child in the list. yes bestie, it's a linked list walk, we've all been there πΆββοΈ
virtual Component* Copy()
return a copy of the command. subclasses should redefine this operation to return an instance of their type. clone era. π«Ά
virtual void Read(istream&)virtual void Write(ostream&)
read and write the command's contents to a stream to support catalog operations. Read and Write typically call first the corresponding operations defined by their parent class, and then they read or write their class-specific state.
note that you must ensure that the objects are read in the same order they are written. order matters, bestie, this is not a drill π
virtual ClassId GetClassId()virtual boolean IsA(ClassId)
GetClassId returns the unique class identifier for the Command subclass, while IsA returns whether the instance is of a class or subclass corresponding to the given identifier. IsA typically checks the given identifier against the instance's own (as defined by its GetClassId operation) and, failing that, calls its parent classes' IsA operation.
all subclasses must redefineGetClassIdandIsAto ensure that their identifiers are unique and that instances are written and read properly. non-negotiable, fr fr.
virtual ClassId GetSubstId(const char*& delim)
a Command subclass can redefine GetSubstId to specify a command that can substitute for it. this lets applications that do not define a particular command subclass still read in a substitute that is compatible with the subclass. the substitute class should be one of the predefined commands in the Unidraw library β this guarantees that all applications can instantiate the substitute. π
GetSubstId returns the class identifier for the substitute. when another Unidraw application's catalog reads this object, it can create an instance of the substitute (which it is guaranteed to define) instead of the original (which it may not define).
the original should read and write a superset of the substitute's data. the catalog will read to the end of the substitute's data and then advance the stream to the point following the sequence of characters specified by delim, saving the extra characters between the two points in the stream. when the substitute object is saved subsequently, the original class identifier will be written along with the substitute's data plus the extra characters saved previously. thus information needn't be lost as a result of being read and written by an unsophisticated application. protecting your data from apps that don't understand you? that's self care π
π PROTECTED OPERATIONS π
Command(ControlInfo*, Clipboard* = nil)Command(Editor* = nil, Clipboard* = nil)
the constructors are protected to prevent instantiation of the abstract base class. you can supply a ControlInfo or Editor and an optional clipboard. only commands that will be accessible to the user need a ControlInfo object. all commands should be given an editor object before they are used. like, before. not later. before. π
void InitCopy(Command*)ControlInfo* CopyControlInfo()Clipboard* CopyClipboard()Clipboard* DeepCopyClipboard()
convenience functions for use by subclasses in their Copy operation. InitCopy gives this a copy of the given command's editor, clipboard, and interpretation data stored by the components that interpreted it, if any. CopyControlInfo and CopyClipboard return copies of the command's ControlInfo and Clipboard objects, respectively, if they are non-nil. both CopyControlInfo and CopyClipboard simply check for a nil argument before calling the corresponding Copy operations on the objects. DeepCopyClipboard checks for a nil clipboard before calling DeepCopy on the command's clipboard and returning the result.
GraphicComp* GetGraphicComp()
a convenience function that returns the GraphicComp in the editor that the command affects. one-liner, does exactly what it says on the tin β¨
π SEE ALSO π
go read these next, they're all part of the lore:
Catalog(3U)Clipboard(3U)ControlInfo(3U)Data(3U)Editor(3U)GraphicComp(3U)Iterator(3U)Unidraw(3U)classes(3U)globals(3U)istream(3C++)ostream(3C++)
and that's the page, bestie π this whole thing is brought to you by Unidraw, dated 23 January 1991 β yeah, she's vintage, she's archival, she's a classic, and she still ate. go build something undoable. πβ¨
π¦ where this page comes from
- debian bookworm: ivtools-dev 2.0.11d.a1-1+b4
- debian trixie: ivtools-dev 2.0.11d.a1-3+b4
- ubuntu jammy: ivtools-dev 2.0.11d.a1-1build1
- ubuntu noble: ivtools-dev 2.0.11d.a1-3build1
- ubuntu questing: ivtools-dev 2.0.11d.a1-3build7
- ubuntu resolute: ivtools-dev 2.0.11d.a1-3build9
- ubuntu stonking: ivtools-dev 2.1.1+git.2025.07.26.a1-1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms