]> git.saurik.com Git - wxWidgets.git/blame - samples/ipc/baseclient.cpp
Support using GetTextExtent() with empty string to get descent in wxOSX.
[wxWidgets.git] / samples / ipc / baseclient.cpp
CommitLineData
ebe887ed
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: samples/ipc/baseclient.cpp
3// Purpose: IPC sample: console client
4// Author: Anders Larsen
5// Most of the code was stolen from: samples/ipc/client.cpp
6// (c) Julian Smart, Jurgen Doornik
7// Created: 2007-11-08
8// RCS-ID: $Id$
9// Copyright: (c) 2007 Anders Larsen
526954c5 10// Licence: wxWindows licence
ebe887ed
VZ
11///////////////////////////////////////////////////////////////////////////////
12
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25 #pragma hdrstop
26#endif
27
28#ifndef WX_PRECOMP
29 #include "wx/wx.h"
30#endif
31
32// Settings common to both executables: determines whether
33// we're using TCP/IP or real DDE.
34#include "ipcsetup.h"
35
521d3436
VZ
36#include "connection.h"
37
ebe887ed
VZ
38#include "wx/timer.h"
39#include "wx/datetime.h"
05b93327
VZ
40#include "wx/vector.h"
41
42class MyClient;
ebe887ed
VZ
43
44// ----------------------------------------------------------------------------
05b93327 45// classes
ebe887ed
VZ
46// ----------------------------------------------------------------------------
47
05b93327 48class MyApp : public wxApp
ebe887ed
VZ
49{
50public:
05b93327
VZ
51 MyApp() { Connect(wxEVT_IDLE, wxIdleEventHandler(MyApp::OnIdle)); }
52
ebe887ed
VZ
53 virtual bool OnInit();
54 virtual int OnExit();
55
05b93327
VZ
56private:
57 void OnIdle(wxIdleEvent& event);
58
59 MyClient *m_client;
ebe887ed
VZ
60};
61
521d3436 62class MyConnection : public MyConnectionBase
ebe887ed
VZ
63{
64public:
ebe887ed
VZ
65 virtual bool DoExecute(const void *data, size_t size, wxIPCFormat format);
66 virtual const void *Request(const wxString& item, size_t *size = NULL, wxIPCFormat format = wxIPC_TEXT);
67 virtual bool DoPoke(const wxString& item, const void* data, size_t size, wxIPCFormat format);
68 virtual bool OnAdvise(const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format);
69 virtual bool OnDisconnect();
ebe887ed
VZ
70};
71
05b93327
VZ
72class MyClient : public wxClient,
73 private wxTimer
ebe887ed
VZ
74{
75public:
76 MyClient();
77 virtual ~MyClient();
05b93327 78
ebe887ed
VZ
79 bool Connect(const wxString& sHost, const wxString& sService, const wxString& sTopic);
80 void Disconnect();
81 wxConnectionBase *OnMakeConnection();
82 bool IsConnected() { return m_connection != NULL; };
05b93327 83
ebe887ed
VZ
84 virtual void Notify();
85
05b93327
VZ
86 void StartNextTestIfNecessary();
87
88private:
89 void TestRequest();
90 void TestPoke();
91 void TestExecute();
92 void TestStartAdvise();
93 void TestStopAdvise();
94 void TestDisconnect();
95
96
97 MyConnection *m_connection;
98
99 // the test functions to be executed by StartNextTestIfNecessary()
100 typedef void (MyClient::*MyClientTestFunc)();
101 wxVector<MyClientTestFunc> m_tests;
102
103 // number of seconds since the start of the test
104 int m_step;
ebe887ed
VZ
105};
106
107// ============================================================================
108// implementation
109// ============================================================================
110
2e334012 111IMPLEMENT_APP_CONSOLE(MyApp)
ebe887ed
VZ
112
113// ----------------------------------------------------------------------------
114// MyApp
115// ----------------------------------------------------------------------------
116
117// The `main program' equivalent, creating the windows and returning the
118// main frame
119bool MyApp::OnInit()
120{
121 if ( !wxApp::OnInit() )
122 return false;
123
ebe887ed
VZ
124 // Create a new client
125 m_client = new MyClient;
126 bool retval = m_client->Connect("localhost", "4242", "IPC TEST");
127
05b93327
VZ
128 wxLogMessage("Client host=\"localhost\" port=\"4242\" topic=\"IPC TEST\" %s",
129 retval ? "connected" : "failed to connect");
ebe887ed
VZ
130
131 return retval;
132}
133
134int MyApp::OnExit()
135{
136 delete m_client;
137
138 return 0;
139}
140
05b93327
VZ
141void MyApp::OnIdle(wxIdleEvent& event)
142{
143 if ( m_client )
144 m_client->StartNextTestIfNecessary();
145
146 event.Skip();
147}
148
ebe887ed
VZ
149// ----------------------------------------------------------------------------
150// MyClient
151// ----------------------------------------------------------------------------
152
05b93327
VZ
153MyClient::MyClient()
154 : wxClient()
ebe887ed
VZ
155{
156 m_connection = NULL;
157 m_step = 0;
158}
159
05b93327
VZ
160bool
161MyClient::Connect(const wxString& sHost,
162 const wxString& sService,
163 const wxString& sTopic)
ebe887ed
VZ
164{
165 // suppress the log messages from MakeConnection()
166 wxLogNull nolog;
167
168 m_connection = (MyConnection *)MakeConnection(sHost, sService, sTopic);
05b93327
VZ
169 if ( !m_connection )
170 return false;
171
172 Start(1000);
173
174 return true;
ebe887ed
VZ
175}
176
177wxConnectionBase *MyClient::OnMakeConnection()
178{
179 return new MyConnection;
180}
181
182void MyClient::Disconnect()
183{
184 if (m_connection)
185 {
186 m_connection->Disconnect();
5276b0a5 187 wxDELETE(m_connection);
05b93327 188 wxLogMessage("Client disconnected from server");
ebe887ed
VZ
189 }
190 wxGetApp().ExitMainLoop();
191}
192
193MyClient::~MyClient()
194{
195 Disconnect();
196}
197
198void MyClient::Notify()
199{
05b93327
VZ
200 // we shouldn't call wxIPC methods from here directly as we may be called
201 // from inside an IPC call when using TCP/IP as the sockets are used in
202 // non-blocking code and so can dispatch events, including the timer ones,
203 // while waiting for IO and so starting another IPC call would result in
204 // fatal reentrancies -- instead, just set a flag and perform the test
205 // indicated by it later from our idle event handler
206 MyClientTestFunc testfunc = NULL;
207 switch ( m_step++ )
ebe887ed
VZ
208 {
209 case 0:
05b93327 210 testfunc = &MyClient::TestRequest;
ebe887ed 211 break;
05b93327 212
ebe887ed 213 case 1:
05b93327 214 testfunc = &MyClient::TestPoke;
ebe887ed 215 break;
05b93327 216
ebe887ed 217 case 2:
05b93327 218 testfunc = &MyClient::TestExecute;
ebe887ed 219 break;
05b93327 220
ebe887ed 221 case 3:
05b93327 222 testfunc = &MyClient::TestStartAdvise;
ebe887ed 223 break;
05b93327 224
ebe887ed 225 case 10:
05b93327 226 testfunc = &MyClient::TestStopAdvise;
ebe887ed 227 break;
05b93327 228
ebe887ed 229 case 15:
05b93327 230 testfunc = &MyClient::TestDisconnect;
67eca664
VZ
231 // We don't need the timer any more, we're going to exit soon.
232 Stop();
ebe887ed 233 break;
67eca664
VZ
234
235 default:
236 // No need to wake up idle handling.
237 return;
ebe887ed 238 }
05b93327 239
67eca664 240 m_tests.push_back(testfunc);
05b93327
VZ
241
242 wxWakeUpIdle();
243}
244
245void MyClient::StartNextTestIfNecessary()
246{
67eca664 247 while ( !m_tests.empty() )
05b93327
VZ
248 {
249 MyClientTestFunc testfunc = m_tests.front();
250 m_tests.erase(m_tests.begin());
251 (this->*testfunc)();
252 }
253}
254
255void MyClient::TestRequest()
256{
257 size_t size;
258 m_connection->Request("Date");
259 m_connection->Request("Date+len", &size);
260 m_connection->Request("bytes[3]", &size, wxIPC_PRIVATE);
261}
262
263void MyClient::TestPoke()
264{
265 wxString s = wxDateTime::Now().Format();
266 m_connection->Poke("Date", s);
267 s = wxDateTime::Now().FormatTime() + " " + wxDateTime::Now().FormatDate();
268 m_connection->Poke("Date", (const char *)s.c_str(), s.length() + 1);
269 char bytes[3];
270 bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
271 m_connection->Poke("bytes[3]", bytes, 3, wxIPC_PRIVATE);
272}
273
274void MyClient::TestExecute()
275{
276 wxString s = "Date";
277 m_connection->Execute(s);
278 m_connection->Execute((const char *)s.c_str(), s.length() + 1);
279 char bytes[3];
280 bytes[0] = '1';
281 bytes[1] = '2';
282 bytes[2] = '3';
283 m_connection->Execute(bytes, WXSIZEOF(bytes));
284}
285
286void MyClient::TestStartAdvise()
287{
288 wxLogMessage("StartAdvise(\"something\")");
289 m_connection->StartAdvise("something");
290}
291
292void MyClient::TestStopAdvise()
293{
294 wxLogMessage("StopAdvise(\"something\")");
295 m_connection->StopAdvise("something");
296}
297
298void MyClient::TestDisconnect()
299{
300 Disconnect();
ebe887ed
VZ
301}
302
303// ----------------------------------------------------------------------------
304// MyConnection
305// ----------------------------------------------------------------------------
306
ebe887ed
VZ
307bool MyConnection::OnAdvise(const wxString& topic, const wxString& item, const void *data,
308 size_t size, wxIPCFormat format)
309{
05b93327 310 Log("OnAdvise", topic, item, data, size, format);
ebe887ed
VZ
311 return true;
312}
313
314bool MyConnection::OnDisconnect()
315{
05b93327 316 wxLogMessage("OnDisconnect()");
ebe887ed
VZ
317 wxGetApp().ExitMainLoop();
318 return true;
319}
320
321bool MyConnection::DoExecute(const void *data, size_t size, wxIPCFormat format)
322{
05b93327 323 Log("Execute", wxEmptyString, wxEmptyString, data, size, format);
ebe887ed
VZ
324 bool retval = wxConnection::DoExecute(data, size, format);
325 if (!retval)
43b2d5e7 326 {
05b93327 327 wxLogMessage("Execute failed!");
43b2d5e7 328 }
ebe887ed
VZ
329 return retval;
330}
331
332const void *MyConnection::Request(const wxString& item, size_t *size, wxIPCFormat format)
333{
334 const void *data = wxConnection::Request(item, size, format);
05b93327 335 Log("Request", wxEmptyString, item, data, size ? *size : wxNO_LEN, format);
ebe887ed
VZ
336 return data;
337}
338
339bool MyConnection::DoPoke(const wxString& item, const void *data, size_t size, wxIPCFormat format)
340{
05b93327 341 Log("Poke", wxEmptyString, item, data, size, format);
ebe887ed
VZ
342 return wxConnection::DoPoke(item, data, size, format);
343}