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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
// ControlManager.h
//
// Copyright (c) 2007 The Dasher Team
//
// This file is part of Dasher.
//
// Dasher is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Dasher is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Dasher; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef __controlmanager_h__
#define __controlmanager_h__
#include "DasherNode.h"
#include "Event.h"
#include "NodeManager.h"
#include "NodeCreationManager.h"
#include <vector>
#include <map>
#include <fstream>
#include <iostream>
#ifndef _WIN32_WCE
#include <sys/stat.h>
#endif
#include <string>
#include <expat.h>
using namespace std;
class CNodeCreationManager;
namespace Dasher {
class CDasherInterfaceBase;
/// \ingroup Model
/// @{
/// A node manager which deals with control nodes.
///
class CControlBase : public CNodeManager, protected CSettingsUser {
public:
class NodeTemplate;
class CContNode : public CDasherNode {
public:
CControlBase *mgr() const {return m_pMgr;}
CContNode(int iOffset, int iColour, NodeTemplate *pTemplate, CControlBase *pMgr);
bool bShove() {return false;}
double SpeedMul() {return 0.5;}
///
/// Provide children for the supplied node
///
virtual void PopulateChildren();
virtual int ExpectedNumChildren();
virtual void Output();
private:
NodeTemplate *m_pTemplate;
CControlBase *m_pMgr;
};
class Action {
public:
virtual void happen(CContNode *pNode) {}
};
class NodeTemplate : public Action {
public:
NodeTemplate(const std::string &strLabel, int iColour);
virtual ~NodeTemplate();
const std::string m_strLabel;
const int m_iColour;
std::vector<NodeTemplate *> successors;
private:
friend class CControlBase;
CDasherScreen::Label *m_pLabel;
};
class Pause : public NodeTemplate {
public:
Pause(const std::string &strLabel, int iColour);
void happen(CContNode *pNode);
};
template <typename T> class MethodTemplate : public NodeTemplate {
public:
///A "Method" is pointer to a function "void X()", that is a member of a T...
typedef void (T::*Method)();
MethodTemplate(const std::string &strLabel, int color, T *pRecv, Method f) : NodeTemplate(strLabel,color),m_pRecv(pRecv),m_f(f) {
}
virtual void happen(CContNode *pNode) {
//invoke pointer-to-member-function m_f on object *m_pRecv!
(m_pRecv->*m_f)();
}
private:
T *m_pRecv;
Method m_f;
};
NodeTemplate *GetRootTemplate();
CControlBase(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager);
///Make this manager ready to make nodes renderable on the screen by preallocating labels
virtual void ChangeScreen(CDasherScreen *pScreen);
///
/// Get a new root node owned by this manager
///
virtual CDasherNode *GetRoot(CDasherNode *pContext, int iOffset);
protected:
///Sets the root - should be called by subclass constructor to make
/// superclass ready for use.
///Note, may only be called once, and with a non-null pRoot, or will throw an error message.
void SetRootTemplate(NodeTemplate *pRoot);
CDasherInterfaceBase *m_pInterface;
CNodeCreationManager *m_pNCManager;
int getColour(NodeTemplate *pTemplate, CDasherNode *pParent);
CDasherScreen *m_pScreen;
private:
NodeTemplate *m_pRoot;
};
///Class reads node tree definitions from an XML file, linking together the NodeTemplates
/// according to defined names, nesting of <node/>s, and <ref/>s. Also handles the
/// <alph/> tag, meaning one child of the node is to escape back to the alphabet. Subclasses
/// may override parseAction to provide actions for the nodes to perform, also parseOther
/// to link with NodeTemplates from other sources.
class CControlParser : public AbstractXMLParser {
public:
CControlParser(CMessageDisplay *pMsgs);
protected:
///Loads all node definitions from the specified filename. Note that
/// system files will not be loaded if user files are (and user files will
/// clear out any nodes from system ones). However, multiple system or multiple
/// user files, will be concatenated. (However, files are processed separately:
/// e.g. names defined in one file will not be seen from another)
/// \param strFilename name+full-path of xml file to load
/// \param bUser true if from user-specific location (takes priority over system)
/// \return true if the file was opened successfully; false if not.
bool ParseFile(const std::string &strFilename, bool bUser);
/// \return all node definitions that have been loaded by this CControlParser.
const vector<CControlBase::NodeTemplate*> &parsedNodes();
///Subclasses may override to parse other nodes (besides "node", "ref" and "alph").
///The default implementation always returns NULL.
/// \return A node template, if the name was recognised; NULL if not recognised.
virtual CControlBase::NodeTemplate *parseOther(const XML_Char *name, const XML_Char **atts) {
return NULL;
}
///Subclasses may override to parse actions within nodes.
///The default implementation always returns NULL.
/// \return A (new) action pointer, if the name+attributes were successfully parsed; NULL if not recognised.
virtual CControlBase::Action *parseAction(const XML_Char *name, const XML_Char **atts) {
return NULL;
};
//TODO cleanup/deletion
void XmlStartHandler(const XML_Char *name, const XML_Char **atts);
void XmlEndHandler(const XML_Char *szName);
private:
///all top-level parsed nodes
vector<CControlBase::NodeTemplate *> m_vParsed;
///whether parsed nodes were from user file or not
bool m_bUser;
///Following only used as temporary variables during parsing...
map<string,CControlBase::NodeTemplate*> namedNodes;
vector<pair<CControlBase::NodeTemplate**,string> > unresolvedRefs;
vector<CControlBase::NodeTemplate*> nodeStack;
};
///subclass which we actually construct! Parses editing node definitions from a file,
/// then adds Pause and/or Stop, Speak, and Copy (to clipboard), all as children
/// of the "root" control node.
class CControlManager : public CSettingsObserver, public CControlBase, public CControlParser {
public:
CControlManager(CSettingsUser *pCreateFrom, CNodeCreationManager *pNCManager, CDasherInterfaceBase *pInterface);
void HandleEvent(int iParameter);
typedef enum {
EDIT_CHAR, EDIT_WORD, EDIT_LINE, EDIT_FILE
} EditDistance;
///Recomputes which of pause, stop, speak and copy the root control node should have amongst its children.
/// Automatically called whenever copy-on-stop/speak-on-stop or input filter changes;
/// subclasses of CDasherInterfaceBase should also call this if
/// (a) they override Stop() and hasStopTriggers() with additional actions, if these are enabled/disabled
/// and this causes the value returned by hasStopTriggers() to change;
/// (b) the values returned by SupportsSpeech() and/or SupportsClipboard() ever change.
void updateActions();
~CControlManager();
protected:
///Override to allow a <root/> tag to include a fresh control root
NodeTemplate *parseOther(const XML_Char *name, const XML_Char **atts);
///Override to recognise <move/> and <delete/> tags as actions.
Action *parseAction(const XML_Char *name, const XML_Char **atts);
private:
NodeTemplate *m_pPause, *m_pStop;
///group headers, with three children each (all/new/repeat)
NodeTemplate *m_pSpeech, *m_pCopy;
};
/// @}
}
#endif
|