Updated German translation
[dasher.git] / Src / DasherCore / DasherInterfaceBase.h
blobb5c448aae26edcfa6bed9576ababf553513335e8
1 // DasherInterfaceBase.h
2 //
3 // Copyright (c) 2008 The Dasher Team
4 //
5 // This file is part of Dasher.
6 //
7 // Dasher is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
12 // Dasher is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with Dasher; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef __DasherInterfaceBase_h__
22 #define __DasherInterfaceBase_h__
24 ///
25 /// \mainpage
26 ///
27 /// This is the Dasher source code documentation. Please try to keep
28 /// it up to date!
29 ///
31 // TODO - there is a list of things to be configurable in my notes
32 // Check that everything that is not self-contained within the GUI is covered.
34 #include "Messages.h"
35 #include "../Common/NoClones.h"
36 #include "../Common/ModuleSettings.h"
37 #include "Alphabet/AlphIO.h"
38 #include "AutoSpeedControl.h"
39 #include "ColourIO.h"
40 #include "InputFilter.h"
41 #include "ModuleManager.h"
42 #include "ControlManager.h"
43 #include "FrameRate.h"
44 #include <set>
45 #include <algorithm>
47 namespace Dasher {
48 class CDasherScreen;
49 class CDasherView;
50 class CDasherInput;
51 class CInputFilter;
52 class CDasherModel;
53 class CSettingsStore;
54 class CGameModule;
55 class CDasherInterfaceBase;
58 class CUserLogBase;
59 class CNodeCreationManager;
61 /// \defgroup Core Core Dasher classes
62 /// @{
65 /// @name Platform dependent utility functions
66 /// These functions provide various platform dependent functions
67 /// required by the core. A derived class is created for each
68 /// supported platform which implements these.
69 // @{
70 class CFileUtils {
71 public:
72 virtual ~CFileUtils(){}
73 ///
74 /// Obtain the size in bytes of a file - the way to do this is
75 /// dependent on the OS (TODO: Check this - any posix on Windows?)
76 ///
77 virtual int GetFileSize(const std::string &strFileName) = 0;
79 ///Look for files, matching a filename pattern, in whatever system and/or user
80 /// locations as may exist - e.g. on disk, in app package, on web, whatever.
81 /// TODO, can we add a default implementation that looks on the Dasher website?
82 /// \param pattern string matching just filename (not path), potentially
83 /// including '*'s (as per glob)
84 virtual void ScanFiles(AbstractParser *parser, const std::string &strPattern) = 0;
86 // Writes file to user data directory.
87 virtual bool WriteUserDataFile(const std::string &filename, const std::string &strNewText, bool append) = 0;
91 /// The central class in the core of Dasher. Ties together the rest of
92 /// the platform independent stuff and provides a single interface for
93 /// the UI to use. Note: CMessageDisplay unimplemented; platforms should
94 /// provide their own methods using appropriate GUI components, or subclass
95 /// CDashIntfScreenMsgs instead.
96 class Dasher::CDasherInterfaceBase : public CMessageDisplay, public Observable<const CEditEvent *>, protected Observer<int>, protected CSettingsUser, private NoClones {
97 public:
98 ///Create a new interface by providing the only-and-only settings store that will be used throughout.
99 CDasherInterfaceBase(CSettingsStore *pSettingsStore, CFileUtils* fileUtils);
100 virtual ~CDasherInterfaceBase();
102 /// @name Access to internal member classes
103 /// Access various classes contained within the interface. These
104 /// should be considered dangerous and use minimised. Eventually to
105 /// be replaced by properly encapsulated equivalents.
106 /// @{
108 CUserLogBase* GetUserLogPtr();
110 // @}
113 /// @name Parameter manipulation
114 /// Members for manipulating the parameters of the core Dasher object.
117 //@{
120 /// Reset a parameter to the default value
123 void ResetParameter(int iParmater);
126 /// Obtain the permitted values for a string parameter - used to
127 /// geneate preferences dialogues etc.
130 void GetPermittedValues(int iParameter, std::vector<std::string> &vList);
133 /// Get a list of settings which apply to a particular module
136 bool GetModuleSettings(const std::string &strName, SModuleSettings **pSettings, int *iCount);
138 //@}
140 /// Called when a parameter changes - but *after* components have been notified.
141 /// Subsumes previous Interface level event handler, for example, responsible for
142 /// restarting the Dasher model whenever parameter changes make it
143 /// invalid. Subclasses should override to forward events to SettingsUI, editbox,
144 /// etc., as appropriate, but should _call_through_to_superclass_method_ first.
145 /// \param iParameter The parameter that's just changed.
146 /// \todo Should be protected (??)
148 virtual void HandleEvent(int iParameter);
150 ///Locks/unlocks Dasher. The default here stores the lock message and percentage
151 /// in m_strLockMessage, such that NewFrame renders this instead of the canvas
152 /// if we are locked. Subclasses may override to implement better (GUI)
153 /// notifications/dialogues, but should call through to this method to ensure
154 /// isLocked() returns the correct value.
155 /// Note that we do not support multiple/concurrent locks; each call to SetLockStatus
156 /// overrides any/all previous ones.
157 /// \param strText text of message to display, excluding %age, _if_ locked;
158 /// ignored, if unlocked.
159 /// \param iPercent -1 unlocks Dasher; anything else locks it, and indicates
160 /// %progress.
161 virtual void SetLockStatus(const std::string &strText, int iPercent);
163 /// Tells us whether Dasher is locked (i.e. for training).
164 /// TODO This just replaces the old BP_TRAINING; however, I'd think that _if_ we
165 /// do actually need a global function to tell whether Dasher's locked, it probably
166 /// needs to be threadsafe, which neither this nor BP_TRAINING is (I don't think!)...
167 inline bool isLocked() {return !m_strLockMessage.empty();}
169 ///Does this subclass support speech (i.e. the speak(string) method?)
170 /// Default is just to return false.
171 virtual bool SupportsSpeech() {return false;}
172 ///Does this subclass support clipboard copying (i.e. the copyToClipboard(string) method?)
173 /// Default is just to return false.
174 virtual bool SupportsClipboard() {return false;}
176 ///Subclasses supporting speech should override to speak the supplied text
177 /// (Default implementation does nothing)
178 virtual void Speak(const std::string &text, bool bInterrupt) {}
180 ///Subclasses supporting clipboard operations should override to copy
181 /// the specified text to the clipboard. (Default implementation does nothing).
182 virtual void CopyToClipboard(const std::string &text) {}
184 ///Called to calculate offset after control-mode "move" or delete commands.
185 ///\param bForwards true to move forwards (right), false for backwards
186 ///\param dist how far to move: character, word, line, ..., file. (Usually defined
187 /// by OS, e.g. for non-european languages)
188 ///\return the offset, into the edit buffer where the cursor would be *after* the move.
189 virtual unsigned int ctrlOffsetAfterMove(unsigned int offsetBefore, bool bForwards,
190 CControlManager::EditDistance iDist) {
191 return offsetBefore;
194 ///Called to execute a control-mode "move" command.
195 ///\param bForwards true to move forwards (right), false for backwards
196 ///\param dist how far to move: character, word, line, file. (Usually defined
197 /// by OS, e.g. for non-european languages)
198 ///\return the offset, into the edit buffer of the cursor *after* the move.
199 virtual unsigned int ctrlMove(bool bForwards, CControlManager::EditDistance dist)=0;
201 ///Called to execute a control-mode "delete" command.
202 ///\param bForwards true to delete forwards (right), false for backwards
203 ///\param dist how much to delete: character, word, line, file. (Usually defined
204 /// by OS, e.g. for non-european languages)
205 ///\return the offset, into the edit buffer, of the cursor *after* the delete
206 /// (for forwards deletion, this will be the same as the offset *before*)
207 virtual unsigned int ctrlDelete(bool bForwards, CControlManager::EditDistance dist)=0;
209 virtual void editOutput(const std::string &strText, CDasherNode *pCause);
210 virtual void editDelete(const std::string &strText, CDasherNode *pCause);
211 virtual void editConvert(CDasherNode *pCause);
212 virtual void editProtect(CDasherNode *pCause);
214 class TextAction {
215 public:
216 TextAction(CDasherInterfaceBase *pMgr);
217 void executeOnDistance(CControlManager::EditDistance dist);
218 void executeOnNew();
219 void executeLast();
220 void NotifyOffset(int iOffset);
221 virtual ~TextAction();
222 protected:
223 virtual void operator()(const std::string &strText)=0;
224 CDasherInterfaceBase *m_pIntf;
225 private:
226 int m_iStartOffset;
227 std::string strLast;
231 /// @name Starting and stopping
232 /// Methods used to instruct dynamic motion of Dasher to start or stop
233 /// @{
235 /// Call when the user has finished writing a piece of text, to execute
236 /// any "on-stop" actions: the default implements speak on stop (if
237 /// BP_SPEAK_ON_STOP is set) and copy-on-stop (if BP_COPY_ALL_ON_STOP) is set;
238 /// subclasses may override to do more.
239 virtual void Done();
241 ///Whether the Done() method does anything (and so should be presented
242 /// to the user) - default deals with speak/copy-on-stop, and subclasses
243 /// which override Done() to add additional on-stop actions must/should
244 /// override this to match.
245 virtual bool hasDone();
246 /// @}
249 /// Append text to the user training file - used to store state between sessions
250 /// \param filename name of training file, without path (e.g. "training_english_GB.txt")
251 /// \param strNewText text to append
253 void WriteTrainFile(const std::string &filename, const std::string &strNewText) {
254 m_fileUtils->WriteUserDataFile(filename, strNewText, true);
257 // App Interface
258 // -----------------------------------------------------
260 // std::map<int, std::string>& GetAlphabets(); // map<key, value> int is a UID string can change. Store UID in preferences. Display string to user.
261 // std::vector<std::string>& GetAlphabets();
262 // std::vector<std::string>& GetLangModels();
263 // std::vector<std::string>& GetViews();
265 /// Supply a new CDasherScreen object onto which to render. Note this should
266 /// only be called (a) at startup, and (b) when the new screen is _significantly_
267 /// different from the old, rather than just a window resize: specifically, this means
268 /// the tree of nodes will be rebuilt with new Labels for the new screen; and in the future,
269 /// maybe also if things like colour depth, alpha transparency support, etc., change.
270 /// If the existing rendering setup should just scale to the new screen dimensions,
271 /// call ScreenResized() instead (we expect this to be the case most/all of the time,
272 /// and this method subsumes a call to ScreenResized.) Note, at startup, ChangeScreen
273 /// and Realize may occur in either order; if ChangeScreen comes after, Resize will create a
274 /// tree with null Labels, which will have to be rebuilt in the call to ChangeScreen.
275 /// \param NewScreen Pointer to the new CDasherScreen.
276 virtual void ChangeScreen(CDasherScreen * NewScreen);
278 ///Call when the screen dimensions have been changed, to recalculate scaling factors etc.
279 /// \param pScreen the screen whose dimensions have changed. TODO we expect this to be
280 /// the same one-and-only screen that we are using anyway, so remove parameter?
281 void ScreenResized(CDasherScreen *pScreen);
283 /// Train Dasher from a file
284 /// All traing data must be in UTF-8
285 /// \param Filename File to load.
286 /// \param iTotalBytes documentme
287 /// \param iOffset Document me
288 // int TrainFile(std::string Filename, int iTotalBytes, int iOffset);
290 /// New control mechanisms:
292 ///Equivalent to SetOffset(iOffset, true)
293 void SetBuffer(int iOffset) {SetOffset(iOffset, true);}
295 /// Rebuilds the model at the specified location, potentially reusing nodes if !bForce
296 /// @param iOffset Cursor position in attached buffer from which to obtain context
297 /// @param bForce if true, model should be completely rebuilt (even for
298 /// same offset) - characters at old offsets may have changed, or we have
299 /// a new AlphabetManager. If false, assume buffer and alphabet unchanged,
300 /// so no need to rebuild the model if an existing node covers this point.
302 /// @param bForce true meaning the entire context may have changed,
303 /// false if we've just moved around within it.
304 void SetOffset(int iOffset, bool bForce=false);
306 /// @name Status reporting
307 /// Get information about the runtime status of Dasher which might
308 /// be of interest for debugging purposes etc.
309 /// @{
311 /// Get the current rate of text entry.
312 /// \retval The rate in characters per minute.
313 /// TODO: Check that this is still used
315 double GetCurCPM();
317 /// Get current refresh rate.
318 /// \retval The rate in frames per second
319 /// TODO: Check that this is still used
321 double GetCurFPS();
323 /// Get the total number of nats (base-e bits) entered.
324 /// \retval The current total
325 /// \todo Obsolete since new logging code?
327 double GetNats() const;
329 /// Reset the count of nats entered.
330 /// \todo Obsolete since new logging code?
332 void ResetNats();
334 /// @}
336 /// @name User input
337 /// Deals with forwarding user input to the core
338 /// @{
339 /// Called from outside to indicate a key or mouse button has just been pushed down
340 /// \param iTime time at which button pressed
341 /// \param iId integer identifying button. TODO we need a better system here.
342 /// At present 1-4 are keys on the keyboard (or external), after mapping from e.g.
343 /// qwerty layout, such that for a user who can press 2 buttons, 1 is the primary, 2
344 /// secondary (maybe harder for them), etc. Direct mode can use an arbitrary number.
345 /// 100 is left mouse button, 101 right, 102 middle (if there is one), and so on.
346 /// (Note we do not specify the location at which mouse presses occur: the current
347 /// pointer location can be obtained from the input device if necessary)
348 void KeyDown(unsigned long iTime, int iId);
350 /// Called from outside to indicate a key or mouse button has just been released
351 /// \param iTime time at which button released
352 /// \param iId integer identifying button. See comments for KeyDown.
353 void KeyUp(unsigned long iTime, int iId);
355 /// @}
357 // Module management functions
358 CDasherModule *RegisterModule(CDasherModule *pModule);
359 CDasherModule *GetModule(ModuleID_t iID);
360 CDasherModule *GetModuleByName(const std::string &strName);
361 CDasherInput *GetActiveInputDevice() {return m_pInput;}
362 CInputFilter *GetActiveInputMethod() {return m_pInputFilter;}
363 const CAlphInfo *GetActiveAlphabet();
364 void SetDefaultInputDevice(CDasherInput *);
365 void SetDefaultInputMethod(CInputFilter *);
367 void StartShutdown();
369 void ScheduleRedraw() {
370 m_bRedrawScheduled = true;
373 ///Subclasses should return the contents of (the specified subrange of) the edit buffer
374 virtual std::string GetContext(unsigned int iStart, unsigned int iLength)=0;
376 ///Clears all written text from edit buffer and rebuilds the model. The default
377 /// implementation does this using the control mode editDelete mechanism
378 /// (one call forward, one back), followed by a call to SetBuffer(0). Subclasses
379 /// may (optionally) override with more efficient / easier implementations, but
380 /// should make the same call to SetBuffer.
381 virtual void ClearAllContext();
382 virtual std::string GetAllContext()=0;
384 /// Subclasses should return the length of whole text. In letters, not bytes.
385 virtual int GetAllContextLenght() = 0;
387 /// Subclasses should return character, word, sentence, ... at current text cursor position.
388 /// For character around cursor decision is arbitrary. Let's settle for character before cursor.
389 /// TODO. Consistently name functions dealing with dasher context, versus functions dealing with editor text.
390 /// I.E. GetAllContext should be named GetAllTtext
391 virtual std::string GetTextAroundCursor(CControlManager::EditDistance) { // =0;
392 return std::string();
395 /// Set a key value pair by name - designed to allow operation from
396 /// the command line. Returns 0 on success, an error string on failure.
398 const char* ClSet(const std::string &strKey, const std::string &strValue);
400 void ImportTrainingText(const std::string &strPath);
402 /// Flush the/all currently-written text to the user's training file(s).
403 /// Just calls through to WriteTrainFileFull(this) on the AlphabetManager;
404 /// public so e.g. iPhone can flush the buffer when app is backgrounded.
405 void WriteTrainFileFull();
407 /// @name Platform dependent utility functions
408 /// These functions provide various platform dependent functions
409 /// required by the core. A derived class is created for each
410 /// supported platform which implements these.
411 // @{
414 /// Obtain the size in bytes of a file - the way to do this is
415 /// dependent on the OS (TODO: Check this - any posix on Windows?)
417 int GetFileSize(const std::string &strFileName) {
418 return m_fileUtils->GetFileSize(strFileName);
421 ///Look for files, matching a filename pattern, in whatever system and/or user
422 /// locations as may exist - e.g. on disk, in app package, on web, whatever.
423 /// TODO, can we add a default implementation that looks on the Dasher website?
424 /// \param pattern string matching just filename (not path), potentially
425 /// including '*'s (as per glob)
426 void ScanFiles(AbstractParser *parser, const std::string &strPattern) {
427 m_fileUtils->ScanFiles(parser, strPattern);
430 // @}
432 ///Gets a pointer to the game module. This is the correct way to determine
433 /// whether game mode is currently on or off.
434 /// \return pointer to current game module, if game mode on; or null, if off.
435 CGameModule *GetGameModule() {
436 return m_pGameModule;
439 ///Call to enter game mode. The correct procedure for UI activation of game
440 /// mode, is to first create a game module (the method CreateGameModule is
441 /// provided for this purpose), and then prompt the user to change any
442 /// ModuleSettings for that GameModule (hence needing to create it first in
443 /// order to determine what settings it has); if the user clicks ok,
444 /// then the created module can be passed to this method. (If the user instead
445 /// clicks cancel, then the module should be deleted.)
446 /// Note method is virtual, so subclasses can override e.g. to detect entering
447 /// game mode (they should call this method, then check GetGameModule()).
448 /// \param pGameModule concrete instance of GameModule to use. This can be null,
449 /// in which case we will use the module returned by CreateGameModule (e.g.
450 /// this is done for demo filter). However
451 /// \param pGameModule newly-constructed GameModule to use, or NULL to use one
452 /// returned from CreateGameModule; in either case, will be deleted when we
453 /// leave game mode.
454 virtual void EnterGameMode(CGameModule *pGameModule);
456 ///Exits game mode, including deleting the game module that was in use.
457 /// virtual so subclasses can override to detect leaving game mode.
458 void LeaveGameMode();
460 protected:
462 /// @name Startup
463 /// Interaction with the derived class during core startup
464 /// @{
467 /// Finish initializing the DasherInterface; we can't do everything in the constructor,
468 /// because some initialization depends on virtual methods provided by subclasses.
469 /// Both Realize and ChangeScreen must be called after construction before other functions
470 /// will work, but they can be called in either order (as the SettingsStore is passed into
471 /// the c'tor).
472 /// \param ulTime timestamp, much as per NewFrame, used for initializing the RNG (i.e. srand).
473 /// (Is that too hacky?)
475 void Realize(unsigned long ulTime);
478 /// Creates a default set of modules. Override in subclasses to create any
479 /// extra/different modules specific to the platform (eg input device drivers)
481 virtual void CreateModules();
483 /// @}
485 ///Creates the game module. Subclasses must implement to return a concrete
486 /// subclass of CGameModule, perhaps by using platform-specific widgets (e.g.
487 /// the edit box?). Note the view and model can be obtained by calling GetView()
488 /// and reading m_pDasherModel, respectively
489 virtual CGameModule *CreateGameModule() = 0;
491 /// Draw a new Dasher frame, regardless of whether we're paused etc.
492 /// \param iTime Current time in ms.
493 /// \param bForceRedraw Passing in true is equivalent to calling ScheduleRedraw() first,
494 /// and forces the nodes/canvas to be re-rendered (even if we haven't moved).
495 void NewFrame(unsigned long iTime, bool bForceRedraw);
497 ///Renders the current state of the nodes (optionally), decorations, etc. (Does not move around the nodes.)
498 /// \param ulTime Time of rendering, for time-dependent decorations (e.g. messages)
499 /// \param bRedrawNodes whether to re-render the nodes (expensive!)
500 /// \param policy if redrawing nodes, use this to expand/collapse nodes, and set m_bLastChanged if any were.
501 bool Redraw(unsigned long ulTime, bool bRedrawNodes, CExpansionPolicy &policy);
503 ///Called at the end of each frame, after lock-message / nodes+decorations have been rendered.
504 /// Default does nothing, but subclasses can override if they need to do anything else.
505 /// \return true if anything has been rendered to the Screen such that it needs to be blitted
506 /// (i.e. Display() called) - the default just returns false.
507 virtual bool FinishRender(unsigned long ulTime) {return false;}
509 /// @}
511 ///Called (from NewFrame) if this frame moved and the previous didn't
512 /// (moved = was scheduled in the model, even if no actual change to
513 /// co-ordinates - the latter might occur if e.g. running default filter
514 /// but with the mouse precisely over the crosshair)
515 virtual void onUnpause(unsigned long lTime);
517 CDasherView *GetView() {return m_pDasherView;}
519 CDasherModel * const m_pDasherModel;
520 ///Framerate monitor; created in constructor, req'd for DynamicFilter subclasses
521 CFrameRate * const m_pFramerate;
523 private:
525 ///We keep a reference to the (currently unique/global) SettingsStore with which
526 /// this interface was created, as ClSet and ResetParameter need to access it.
527 /// (TODO _could_ move these into CSettingsUser, but that seems uglier given so few clients?)
528 CSettingsStore * const m_pSettingsStore;
530 class CPreSetObserver : public Observer<int> {
531 CSettingsStore& m_settingsStore;
532 public:
533 CPreSetObserver(CSettingsStore& settingsStore) : m_settingsStore(settingsStore) {};
534 void HandleEvent(int evt) override;
537 CPreSetObserver m_preSetObserver;
538 CFileUtils* m_fileUtils;
540 //The default expansion policy to use - an amortized policy depending on the LP_NODE_BUDGET parameter.
541 CExpansionPolicy *m_defaultPolicy;
543 /// Provide a new CDasherInput input device object.
545 void CreateInput();
547 void CreateInputFilter();
549 void CreateModel(int iOffset);
550 void CreateNCManager();
552 void ChangeAlphabet();
553 void ChangeColours();
554 void ChangeView();
556 //Compute the screen orientation to use - i.e. combining the user's
557 // preference with the alphabet.
558 Opts::ScreenOrientations ComputeOrientation();
560 class WordSpeaker : public TransientObserver<const CEditEvent *> {
561 public:
562 WordSpeaker(CDasherInterfaceBase *pIntf);
563 void HandleEvent(const CEditEvent *);
564 private:
565 ///builds up the word currently being entered
566 std::string m_strCurrentWord;
567 } *m_pWordSpeaker;
569 /// @name Child components
570 /// Various objects which are 'owned' by the core.
571 /// @{
572 CDasherScreen *m_DasherScreen;
573 CDasherView *m_pDasherView;
574 CDasherInput *m_pInput;
575 CInputFilter* m_pInputFilter;
576 CModuleManager m_oModuleManager;
577 CAlphIO *m_AlphIO;
578 CColourIO *m_ColourIO;
579 CControlBoxIO *m_ControlBoxIO;
580 CNodeCreationManager *m_pNCManager;
581 CUserLogBase *m_pUserLog;
583 // the game mode module - only
584 // initialized if game mode is enabled
585 CGameModule *m_pGameModule;
586 /// @}
588 ///If non-empty, Dasher is locked, and this is the message that should be displayed.
589 std::string m_strLockMessage;
590 /// (Cache) renderable version of previous; created only to render
591 /// (so may still be NULL even if locked)
592 CDasherScreen::Label *m_pLockLabel;
594 ///Whether a full redraw (inc of nodes) has been requested externally,
595 /// via ScheduleRedraw, for the next frame
596 bool m_bRedrawScheduled;
598 ///Whether we moved anywhere in the last call to NewFrame.
599 bool m_bLastMoved;
601 /// @}
603 std::set<TextAction *> m_vTextActions;
605 /// @}
607 #endif /* #ifndef __DasherInterfaceBase_h__ */