Recommended Event Propagation module

Overview

The GUI application consumes all OS events such as keyboard, mouse, system, etc. In general, the application code tends to grow. Typically, the MVC (Model-View-Controller) pattern or its variants are useful for splitting the logic of a GUI application into modules.

Model modules (letter M in the pattern name) must handle application data. Typically, the model code is the simplest part of the GUI application. For example, in a mind map editor, this code keeps the current contents of the mind map (nodes of tree, a selected node, etc.) and implements methods to change the content (insert a new node, add a new letter to node, etc).

View modules (V letter) should display the current state of the model to the user. For example, the View module in the mind map editor draws node text, borders, lines between nodes, cursor, etc. View modules can be complex because the graphic design style is a valuable part of a GUI application. But the core logic of View modules is simple - to display the current state of the model to the user.

Controller modules (C letter) must receive user events, call Model to change its state, and call View to display the model's new state to the user. For example, the control module in the mind map editor draws a mind map, waits for a new event, and in a switch statement for each possible type of event changes the contents of the mind map. And again.

If your application contains two or more controller modules, you must use additional rules to separate events between different application windows.

Some of an options:

Recommended option:

Recommended event propagation rules

For example, a mouse click can be handled by itself or by a child controller. The controller can get the child window rectangle from the child controller and compare it to the click point. If a mouse click occurs in a child window, the controller can pass the event to the child controller and ignore its own event handler.

Basic use of event propagation module

The core of the module is the event channel between parent and child controller. The parent controller must create an eventlink.EventLink variable:

    eventLink := eventlink.New()

and link the child controller to run its Action method as a goroutine:

    eventLink.Link(ctx, appFramer, childController)

The child controller must implement Actor interface to work with eventlink.EventLink:

type Actor interface {
    Action(ctx context.Context, app App)
    Wait()
}

Then at any time the parent controller can put an event to the child channel:

    eventLink.Chan() <- receivedEvent

On the childs side, the eternal Action method of the child controller receives the event from the channel, handles or ignores it and redraws the child state in its or any other window. The eventlink.App is a interface to get events, create child window, etc.

The eventlink.AppFramer is a wrapper from impress.Application at the beginning:

    var appFramer eventlink.AppFramer = eventlink.MainApp(application)

eventlink.App may be used as eventlink.AppFramer parameter of eventlink.Link to create a new link inside the child controller.

See the module documentation and example for details.

Shutdown scenarios

In a typical usecases, child controllers creates on start and run until parent Controller are still alive.

More complex scenarios of parent and child controller coexistence are possible:

To implement complex shutdown scenarios: