1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! The HandlerChain design pattern example module
//!
//! Example of using the "Handle Chain" or "Chain of Responsibility" design
//! pattern.
//! 
//! The Handler Chain pattern is used to support a dynamic list of
//! handlers that are passed the same arguments.  It is kind of the
//! inverse of the Visitor pattern, where the Visitor pattern is a
//! handler that is passed to all objects in a list, while the Handler
//! Chain pattern is an object passed to handlers in a list.
//!
//! In this exercise, multiple rectangular regions called
//! MessageWindows embody the handlers and the HandlerChain object
//! passes message objects to each MessageWindow until the message is
//! handled.
//!
//! Accessed through the handlerchain_exercise() function.

//-----------------------------------------------------------------------------

pub mod handlerchain_handlerchain;
pub mod handlerchain_imessagehandler_trait;
pub mod handlerchain_message;
pub mod handlerchain_messagewindow;

//-----------------------------------------------------------------------------

use handlerchain_handlerchain::HandlerChain;
use handlerchain_messagewindow::MessageWindow;
use handlerchain_message::{Message, MessageType};

//-----------------------------------------------------------------------------

/// Helper method to construct a list of windows.  Messages will be passed 
/// to these windows via the HandlerChain object.
///
/// The HandlerChain object takes ownership of the windows due to a limitation
/// in Rust.  I would have preferred a separate list own the MessageWindow
/// instances and the HandlerChain would be given a mutable reference to the
/// IMessageHandler trait on each MessageWindow.  But that requires taking a
/// mutable borrow through the list of windows, one for each window, and Rust
/// does not allow multiple mutable borrows (even though technically the
/// mutable borrow should be on the MessageWindow instance, Rust sees the
/// borrow on the list of windows.  If I take the mutable borrow on the
/// MessageWindow instance before adding it to the list of windows and then add
/// the MessageWindow instance to the list of windows, Rust will not allow the
/// window instance to be added (it's an immutable borrow on a reference that
/// is mutable).
///
/// # Parameters
/// - handler_chain
///
///   A reference to a HandlerChain instance that the messages will be passed
///   to.  This HandlerChain instance also takes ownership of the MessageWindow
///   instances.
fn _handlerchain_construct_window_chain(handler_chain: &mut HandlerChain) {
    let mut window = MessageWindow::new("Window 1", 0, 0, 10, 10);
    handler_chain.add_handler(window);
    window = MessageWindow::new("Window 2", 20, 0, 5, 5);
    handler_chain.add_handler(window);
    window = MessageWindow::new("Window 3", 30, 10, 15, 15);
    handler_chain.add_handler(window);
}

/// Example of using the "Handle Chain" or "Chain of Responsibility" design
/// pattern.
/// 
/// The Handler Chain pattern is used to support a dynamic list of
/// handlers that are passed the same arguments.  It is kind of the
/// inverse of the Visitor pattern, where the Visitor pattern is a
/// handler that is passed to all objects in a list, while the Handler
/// Chain pattern is an object passed to handlers in a list.
///
/// In this exercise, multiple rectangular regions called
/// MessageWindows embody the handlers and the HandlerChain object
/// passes message objects to each MessageWindow until the message is
/// handled.
// ! [Using HandlerChain in Rust]
pub fn handlerchain_exercise() -> Result<(), String> {
    println!("");
    println!("HandlerChain Exercise");

    let mut handler_chain = HandlerChain::new();
    _handlerchain_construct_window_chain(&mut handler_chain);

    println!("  Handler Chain at start:");
    println!("{}", handler_chain.to_string());

    // Now pass messages to the windows.

    println!("  Select Window 2");
    handler_chain.send_message(&Message::new(MessageType::ButtonDown, 22, 1));
    handler_chain.send_message(&Message::new(MessageType::ButtonUp, 22, 1));
    println!("  Current handler chain:");
    println!("{}", handler_chain.to_string());

    println!("  Select Window 3");
    handler_chain.send_message(&Message::new(MessageType::ButtonDown, 35, 11));
    handler_chain.send_message(&Message::new(MessageType::ButtonUp, 35, 11));
    println!("  Current handler chain:");
    println!("{}", handler_chain.to_string());

    println!("  Select Window 1");
    handler_chain.send_message(&Message::new(MessageType::ButtonDown, 4, 4));
    handler_chain.send_message(&Message::new(MessageType::ButtonUp, 4, 4));
    println!("  Current handler chain:");
    println!("{}", handler_chain.to_string());

    println!("  Close Window 2");
    handler_chain.send_message(&Message::new(MessageType::ButtonDown, 24, 0));
    handler_chain.send_message(&Message::new(MessageType::ButtonUp, 24, 0));
    println!("  Current handler chain:");
    println!("{}", handler_chain.to_string());

    println!("  Done.");

    Ok(())
}
// ! [Using HandlerChain in Rust]