Disambiguate signals using types instead of special cases.
[kaya.git] / doc / interaction.md
bloba774758faa3ee25f505bffe76b21f1ffd4a2c0a1
1 # Component interaction
3 ## Event handling architecture
5 Event handling is initiated by the scene. Elements react to clicks, drags and drops simply by emitting the corresponding event with appropriate information.
7 At the moment, the controller is responsible for intercepting those events and reacting appropriately, by performing moves and drops.
9 The controller is coupled with the board and pool as far as event handling is concerned, and that makes the architecture non-modular: to add a new element to the mix, the controller must be modified to account for its events.
11 This will be addressed in future releases.
13 ## Examples
15 ### Clicking on a square
17 * Click on a square;
18 * `Scene#mouseReleaseEvent` scans its element to find the recipient   for the click event;
19 * `Board#on_click` emits a *click* event;
20 * `Controller#on_board_click` receives the event, and acts appropriately.
22 ### Dragging a piece
24 * A piece is dragged from the board;
25 * `Scene#mousePressEvent` creates a `@drag_data` hash containing the position where the dragging started;
26 * `Scene#mouseMoveEvent` calls `Board#on_drag` right after a minimal distance from the starting point is reached;
27 * `Board#on_drag` finds the dragged item and emits a *drag* event;
28 * `Controller#on_board_drag` receives the event, and:
29   * prepares the item for being dragged (raise and remove from the board group),
30   * calles `Scene#on_drag` passing the dragged item;
31 * `Scene#on_drag` adds the item to the `@drag_data` hash, so that the following `mouseMoveEvent` invocations can actually move the item along with the pointer.
33 ### Dropping a piece on the board
35 * A piece is dropped on the board
36 * `Scene#mouseReleaseEvent` calls `Board#on_drop`
37 * `Board#on_drop` emits a *drop* event with the source and destination coordinates.
38 * `Controller#on_board_drop` receives the event and performs the corresponding move.
40 ## History
42 The history widget is always kept synchronized with the `History` object of the corresponding controller.
44 Changes in the underlying history are propagated to the widget, which proceeds to update itself to reflect those changes.
46 User interaction with the widget (i.e. selection of a move) results in the history object being modified.
48 Updates in the elements are performed by the controller in the `refresh` method, which is called in response to history update events. The controller maintains an internal index representing which state in the history is currently displayed.
50 The internal controller index is generally synchronized with the history index, but it can differ momentarily between a user navigation event (clicking on the history widget or activating navigation actions) and the corresponding `refresh`.
52 Inside `refresh`, the difference between the internal index and the history index is used to schedule an animation.
54 For this reason, it is important that the history index is never changed in such a way that the interval between the old value and the new value contains states which are not in the history anymore. In case it is necessary to remove states from the history, be sure to update the index *first*, then cause `refresh` to be run when the states are still in the history, and *then* remove them.
56 ## Performing moves
58 Performing moves is not essentially different for navigation. When the controller logic determines that a new move has been made it calls `Match#move`, which proceeds to update the history.
60 The resulting change in the history causes `refresh` to be called, so that the move is actually displayed.
62 ## The `Match` object
64 The `Match` object is responsible for coordinating different players playing in a given game.
66 ### Players
68 There are several kinds of players:
70 * the **controller**, which represents the user interacting with Kaya. The controller is a somewhat special player, in that it can **control** other players (more on this later);
71 * **`ICSPlayer`**: represents an opponent on ICS;
72 * **subclasses of `Engine`**: represents an engine running as an external program;
73 * **`DummyPlayer`**: a player with no specific logic, usually controlled.
75 ### Controlled players
77 *Controlled players* are, as the name suggests, taken over by the controller, that can play moves on their behalf.
79 For example, when editing a chess game, one of the player is the controller (white by convention), and the other is a controlled dummy player.
81 ### Playing moves
83 Moves can be played by calling `Match#move`. It is not enforced that moves are played by the correct player, since this would complicate move handling in certain cases (e.g. controlled players, or ICS examination).
85 `Match#move` validates the move, adds it to the history and informs all the other players by *broadcasting* a *move* event.
87 ### Starting a match
89 To start a match, all players must be registered by calling `Match#register`, and after that, all players must be marked as ready, by calling `Match#start`.
91 When all the players are ready, `Match` emits a *start* event, which should be intercepted to call `Controller#reset`.
93 See `MainWindow#create_game` to see an example of such a procedure.