Files
wxWidgets/utils/helpview/src/client.cpp
Julian Smart bd5dd71130 Added IPC server capability to helpview, if you compile
with hvUSE_IPC
Added client demo using raw IPC classes (not yet using
a kind of help controller, as we eventually should)


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@17483 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2002-10-08 15:27:13 +00:00

310 lines
8.5 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: client.cpp
// Purpose: Tests helpview in server mode.
// Author: Julian Smart
// Modified by:
// Created: 2002-10-08
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(__APPLE__)
#pragma implementation "client.cpp"
#pragma interface "client.cpp"
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWindows headers
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/ipc.h"
#include "wx/process.h"
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class MyConnection: public wxConnection
{
public:
MyConnection();
~MyConnection();
bool OnAdvise(const wxString& topic, const wxString& item, wxChar *data, int size, wxIPCFormat format);
bool OnDisconnect();
};
class MyClient: public wxClient
{
public:
wxConnectionBase *OnMakeConnection();
};
// Define a new application type, each program should derive a class from wxApp
class HelpClientApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit();
};
// Define a new frame type: this is going to be our main frame
class HelpClientFrame : public wxFrame
{
friend MyClient;
friend MyConnection;
public:
// ctor(s)
HelpClientFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnHelpPage(wxCommandEvent& event);
void OnHelpContents(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
bool CreateConnection();
private:
MyConnection* m_connection;
MyClient* m_client;
// any class wishing to process wxWindows events must use this macro
DECLARE_EVENT_TABLE()
};
HelpClientFrame* g_MainFrame = NULL;
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
HelpClient_Quit = 1,
HelpClient_HelpPage,
HelpClient_HelpContents,
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWindows
// ----------------------------------------------------------------------------
// the event tables connect the wxWindows events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(HelpClientFrame, wxFrame)
EVT_MENU(HelpClient_Quit, HelpClientFrame::OnQuit)
EVT_MENU(HelpClient_HelpPage, HelpClientFrame::OnHelpPage)
EVT_MENU(HelpClient_HelpContents, HelpClientFrame::OnHelpContents)
EVT_CLOSE(HelpClientFrame::OnClose)
END_EVENT_TABLE()
// Create a new application object: this macro will allow wxWindows to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. HelpClientApp and
// not wxApp)
IMPLEMENT_APP(HelpClientApp)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
// `Main program' equivalent: the program execution "starts" here
bool HelpClientApp::OnInit()
{
SetVendorName("wxWindows");
SetAppName("Help Client Demo");
// Create the main application window
HelpClientFrame *frame = new HelpClientFrame("Help Client Demo",
wxPoint(50, 50), wxSize(150, 50));
// Show it and tell the application that it's our main window
// @@@ what does it do exactly, in fact? is it necessary here?
frame->Show(TRUE);
SetTopWindow(frame);
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned FALSE here, the
// application would exit immediately.
return TRUE;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
HelpClientFrame::HelpClientFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
g_MainFrame = this;
// create a menu bar
wxMenu *menuFile = new wxMenu;
menuFile->Append(HelpClient_HelpContents, "&Help Contents");
menuFile->Append(HelpClient_HelpPage, "Help Page");
menuFile->AppendSeparator();
menuFile->Append(HelpClient_Quit, "E&xit");
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
m_connection = NULL;
m_client = new MyClient;
}
// event handlers
void HelpClientFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// TRUE is to force the frame to close
Close(TRUE);
}
void HelpClientFrame::OnHelpPage(wxCommandEvent& WXUNUSED(event))
{
if (CreateConnection())
{
m_connection->Execute(wxT("Book 1"));
}
}
void HelpClientFrame::OnHelpContents(wxCommandEvent& WXUNUSED(event))
{
if (CreateConnection())
{
m_connection->Execute(wxT("test.zip"));
}
}
void HelpClientFrame::OnClose(wxCloseEvent& event)
{
if (m_connection)
{
m_connection->Disconnect();
delete m_connection;
m_connection = NULL;
}
delete m_client;
event.Skip();
}
bool HelpClientFrame::CreateConnection()
{
if (m_connection)
return TRUE;
wxString cmd;
#if defined(__WXMSW__)
cmd = "helpview.exe --server test.zip";
#else
cmd = "./helpview --server test.zip";
#endif
wxProcess *process = new wxProcess(this);
int pid = wxExecute( cmd, FALSE, process );
if( pid <= 0 ) {
wxMessageBox( "Failed to start server" );
return FALSE;
}
// service name (DDE classes) or port number (TCP/IP based classes)
wxString service = wxT("4242");
// ignored under DDE, host name in TCP/IP based classes
wxString hostName = wxT("localhost");
int nsleep = 0;
// suppress the log messages from MakeConnection()
{
wxLogNull nolog;
m_connection = (MyConnection *)m_client->MakeConnection(hostName, service, wxT("HELP"));
while ( !m_connection)
{
//try every second for a while
wxSleep(1);
if( nsleep > 4 ) {
if ( wxMessageBox("Failed to make connection to server.\nRetry?",
"Client Demo Error",
wxICON_ERROR | wxYES_NO | wxCANCEL ) != wxYES )
{
// no server
return FALSE;
}
}
nsleep++;
m_connection = (MyConnection *)m_client->MakeConnection(hostName, service, "HELP");
}
}
return (m_connection != NULL);
}
wxConnectionBase *MyClient::OnMakeConnection()
{
return new MyConnection;
}
MyConnection::MyConnection()
: wxConnection()
{
g_MainFrame->m_connection = this;
}
MyConnection::~MyConnection()
{
g_MainFrame->m_connection = NULL;
}
bool MyConnection::OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format)
{
return TRUE;
}
bool MyConnection::OnDisconnect()
{
g_MainFrame->m_connection = NULL;
delete this;
return TRUE;
}