1 /* libobby - Network text editing library
2  * Copyright (C) 2005, 2006 0x539 dev group
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #ifndef _OBBY_JUPITER_CLIENT_HPP_
20 #define _OBBY_JUPITER_CLIENT_HPP_
21 
22 #include <net6/non_copyable.hpp>
23 #include "operation.hpp"
24 #include "record.hpp"
25 #include "jupiter_algorithm.hpp"
26 #include "jupiter_undo.hpp"
27 
28 namespace obby
29 {
30 
31 /** Jupiter client implementation.
32  */
33 template<typename Document>
34 class jupiter_client: private net6::non_copyable
35 {
36 public:
37 	typedef Document document_type;
38 	typedef jupiter_algorithm<document_type> algorithm_type;
39 	typedef jupiter_undo<document_type> undo_type;
40 	typedef operation<document_type> operation_type;
41 	typedef record<document_type> record_type;
42 
43 	typedef sigc::signal<void, const record_type&, const user*>
44 		signal_record_type;
45 
46 	/** Creates a new jupiter_client which uses the given document.
47 	 * Local and remote changes are applied to this document.
48 	 */
49 	jupiter_client(document_type& doc);
50 
51 	/** Adds a new client to the jupiter algorithm.
52 	 */
53 	void client_add(const user& client);
54 
55 	/** Removes a client from the jupiter algorithm.
56 	 */
57 	void client_remove(const user& client);
58 
59 	/** Performs a local operation by the user <em>from</em>. local_event
60 	 * will be emitted with a resulting record that may be transmitted
61 	 * to the server.
62 	 */
63 	void local_op(const operation_type& op, const user* from);
64 
65 	/** Performs a remote operation by the user <em>from</em>.
66 	 */
67 	void remote_op(const record_type& rec, const user* from);
68 
69 	/** Undoes the last operation.
70 	 */
71 	void undo_op(const user* from);
72 
73 	/** Signal which will be emitted when a record has to be transmitted to
74 	 * the server.
75 	 */
76 	signal_record_type record_event() const;
77 
78 protected:
79 	algorithm_type m_algorithm;
80 	undo_type m_undo;
81 
82 	document_type& m_document;
83 	signal_record_type m_signal_record;
84 };
85 
86 template<typename Document>
jupiter_client(document_type & doc)87 jupiter_client<Document>::jupiter_client(document_type& doc):
88 	m_undo(doc), m_document(doc)
89 {
90 }
91 
92 template<typename Document>
client_add(const user & client)93 void jupiter_client<Document>::client_add(const user& client)
94 {
95 	m_undo.client_add(client);
96 }
97 
98 template<typename Document>
client_remove(const user & client)99 void jupiter_client<Document>::client_remove(const user& client)
100 {
101 	m_undo.client_remove(client);
102 }
103 
104 template<typename Document>
local_op(const operation_type & op,const user * from)105 void jupiter_client<Document>::local_op(const operation_type& op,
106                                         const user* from)
107 {
108 	op.apply(m_document, from);
109 	m_undo.local_op(op, from);
110 	std::auto_ptr<record_type> rec(m_algorithm.local_op(op) );
111 	m_signal_record.emit(*rec, from);
112 }
113 
114 template<typename Document>
remote_op(const record_type & rec,const user * from)115 void jupiter_client<Document>::remote_op(const record_type& rec,
116                                          const user* from)
117 {
118 	std::auto_ptr<operation_type> op(m_algorithm.remote_op(rec) );
119 	op->apply(m_document, from);
120 	m_undo.remote_op(*op, from);
121 }
122 
123 template<typename Document>
undo_op(const user * from)124 void jupiter_client<Document>::undo_op(const user* from)
125 {
126 	std::auto_ptr<operation_type> op = m_undo.undo();
127 	op->apply(m_document, from);
128 	std::auto_ptr<record_type> rec(m_algorithm.local_op(*op) );
129 	m_signal_record.emit(*rec, from);
130 }
131 
132 template<typename Document>
133 typename jupiter_client<Document>::signal_record_type
record_event() const134 jupiter_client<Document>::record_event() const
135 {
136 	return m_signal_record;
137 }
138 
139 } // namespace obby
140 
141 #endif // _OBBY_JUPITER_CLIENT_HPP_
142