The principles of the Text Message Bus bus are described in the main TMB article. Do read that article first.
Brief summary of components
common (library) | A few common declarations. |
drawing (library) | Create Bezier curves for circle, square and triangle. |
networking (library) | Socket-level networking based on CFStream. Reads and writes data. |
class Figure | NSView that draws a geometric figure. |
class MainView | NSViewController for the main NSView. Singleton. |
class MessageBusTester | Application delegate. Processes incoming messages. Singleton. |
class MessageBusClient | Message bus logic. Sends and receives messages. Singleton. |
User interface | Created with Interface Builder. |
Each of the three singleton classes have a function instance() that returns the instance, and each use a static variable the_instance.
Libraries drawing and network offload some source from Figure and MessageBusClient respectively.
Execution flow
Starting
in main() calls NSApplicationMain creates the complete main view from NIB does [MainView awakeFromNib] sets the_instance to self creates the the application delegate ($MessageBusTester) does [MessageBusTester applicationDidFinishLaunching] does [self start] sets the_instance to self create the single instance of $MessageBusClient by calling +instance sets the_instance to self calls [MessageBusClient start] calls network_start() creates client socket connects to server set network_read_callback() as read callback
Incoming message
data becomes available on the socket the framework calls network_read_callback() reads data from the socket calls [ MessageBusClient on_incoming_data ] build lines from incoming character for each complete line calls [ MessageBusTester on_incoming_message ] decodes message into group, key and value calls [ MainView set_property ] calls [ Figure +get_figure group ] calls [ Figure set_property key value ]
Sending a figure property
Example for the upper Figure, property colour and value red.
someone calls [ Figure send :key :value] with "colour" and "red" builds string "/upper/colour red" calls [ MessageBusClient send_peer_message ] calls [ MessageBusClient send_message ] prepends a colon appends a newline calls network_write() calls CFWriteStreamWrite()
Colour or shape button clicked
Example for the upper “Red” button.
user clicks the upper "Red" button framework calls [ Figure redClicked ] calls [ Figure send ] with "colour" and "red" ... as Sending a figure property ...
“Send all” button clicked
user clicks on the "Send all" button framework calls [ MainView send_all ] for each Figure (upper and lower) calls [ Figure send_all ] for each property (colour and shape) calls [ Figure send ] with property and property value ... as Sending a figure property ...
Subscription button clicked
Connections from buttons to methods are set up in Interface Builder.
These buttons send their own labels.
user clicks on a subscribe or unsubscribe button framework calls [ MainView send_button_verbatim ] extracts the buttons text calls [ MessageBusClient send_command_message ] calls [ MessageBusClient send_message ] append a newline calls network_write() calls CFWriteStreamWrite()
Guide to the source code
The code is mostly limited to header files. Only the most important parts of the files are included.
Summary of source code
The code is mostly limited to header files. Only the most important parts of the files are included.
common.h
# define VECTSIZE(x) ((sizeof (x)) / (sizeof ((x)[0]))) typedef const char cchar; NSString *a2nss(cchar *); -- ASCII C string to NSString
Main program
int main(int argc, const char *argv[]) { return NSApplicationMain(argc, argv); }
drawing.h
NSBezierPath *drawCircle (void); NSBezierPath *drawSquare (void); NSBezierPath *drawTriangle(void);
These functions return Bezier curves. Implementation of these functions go into a separate modules to make class Figure smaller and easier to understand.
Figure
@interface Figure : NSView + (Figure *)get_figure :(NSString *)id; - (void )send_all; -- Callback for button "Send all" - (void )set_property :(NSString *)name :(NSString *)value; @end
Figure keeps track of all instances of Figure. +get_figure() returns a figure based on the buttons string property identifier:
Figure → NSView → NSUserInterfaceItemIdentification → identifier
There are two figures, “upper” and “lower”.
MainView
@interface MainView : NSViewController + (MainView *)instance; - (void)set_property :(NSString *)group key:(NSString *)key value:(NSString *)value; @end
Method set_property is called by [MessageBusTester on_incoming_message]. It uses [Figure get_figure] to get the Figure that matches group (group is ether “upper” or “lower”), and calls [Figure set_property] on that Figure.
MessageBusClient.h
@interface MessageBusClient : NSObject @property (strong, nonatomic) NSWindow *window; + (MessageBusClient *)instance; - (void) start; -- Called by applicationDidFinishLaunching - (void) stop; -- Called by applicationWillTerminate - (void) send_peer_message :(cchar *)msg; -- Called by Figure - (void) send_command_message :(cchar *)msg; -- Called by MainView - (void) on_incoming_data :(char *)msg; -- Called by network_read_callback() @end
Methods send_peer_message and send_command_message both append a newline and pass the line on to network_write().In addition, send_peer_message prepends a colon.
MessageBusTester
@interface MessageBusTester : NSObject+ (MessageBusTester *)instance; - (void) on_incoming_message: (char *)msg; -- Called by MessageBusClient @end
networking
@class MessageBusClient; void network_start(NSString *host, int port, MessageBusClient *client); void network_stop (void); <em>-- Called by MessageBusClient</em> long network_write(char *buf); <em>-- Called by MessageBusClient</em> static void network_read_callback(...); <em>-- Called by framework</em>
Implements socket-level networking using CFStream.When data is available, network_read_callback() calls [MessageBusClient on_incoming_data].The instance to call is passed as a parameter to network_start().
You can reach me by email at “lars dash 7 dot sdu dot se” or by telephone +46 705 189090