Tweaks to dynamic mode
[dasher.git] / Src / DasherCore / DasherInterfaceBase.cpp
blobebf8171bf51a9e0d01108acde65f9fde4d578c19
1 // DasherInterfaceBase.cpp
2 //
3 // Copyright (c) 2002 Iain Murray
5 #include "../Common/Common.h"
7 #include "DasherInterfaceBase.h"
9 #include "CustomColours.h"
10 #include "DasherViewSquare.h"
11 #include "ControlManager.h"
12 #include "DasherScreen.h"
13 #include "DasherView.h"
14 #include "DasherInput.h"
15 #include "DasherModel.h"
16 #include "EventHandler.h"
17 #include "Event.h"
18 #include "UserLog.h"
19 #include "WrapperFactory.h"
21 // Input filters
22 #include "ClickFilter.h"
23 #include "DefaultFilter.h"
24 #include "DasherButtons.h"
25 #include "DynamicFilter.h"
26 #include "EyetrackerFilter.h"
27 //#include "OneButtonFilter.h"
28 #include "OneDimensionalFilter.h"
29 #include "StylusFilter.h"
30 #include "TwoButtonDynamicFilter.h"
32 // STL headers
33 #include <iostream>
34 #include <memory>
36 // Legacy C library headers
37 namespace {
38 #include "stdio.h"
41 // Declare our global file logging object
42 #include "../DasherCore/FileLogger.h"
43 #ifdef _DEBUG
44 const eLogLevel g_iLogLevel = logDEBUG;
45 const int g_iLogOptions = logTimeStamp | logDateStamp | logDeleteOldFile;
46 #else
47 const eLogLevel g_iLogLevel = logNORMAL;
48 const int g_iLogOptions = logTimeStamp | logDateStamp;
49 #endif
50 CFileLogger* g_pLogger = NULL;
52 using namespace Dasher;
53 using namespace std;
55 // Track memory leaks on Windows to the line that new'd the memory
56 #ifdef _WIN32
57 #ifdef _DEBUG
58 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
59 #define new DEBUG_NEW
60 #undef THIS_FILE
61 static char THIS_FILE[] = __FILE__;
62 #endif
63 #endif
65 CDasherInterfaceBase::CDasherInterfaceBase()
66 :m_Alphabet(0), m_pColours(0), m_pDasherModel(0), m_DasherScreen(0),
67 m_pDasherView(0), m_pInput(0), m_AlphIO(0), m_ColourIO(0), m_pUserLog(NULL),
68 m_pInputFilter(NULL) {
70 m_bGlobalLock = false;
71 m_bShutdownLock = false;
73 m_pEventHandler = new CEventHandler(this);
75 strCurrentContext = ". ";
77 strTrainfileBuffer = "";
79 // Global logging object we can use from anywhere
80 g_pLogger = new CFileLogger("dasher.log",
81 g_iLogLevel,
82 g_iLogOptions);
86 void CDasherInterfaceBase::Realize() {
88 // TODO: What exactly needs to have happened by the time we call Realize()?
89 CreateSettingsStore();
90 SetupUI();
91 SetupPaths();
93 std::vector<std::string> vAlphabetFiles;
94 ScanAlphabetFiles(vAlphabetFiles);
95 m_AlphIO = new CAlphIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vAlphabetFiles);
97 std::vector<std::string> vColourFiles;
98 ScanColourFiles(vColourFiles);
99 m_ColourIO = new CColourIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vColourFiles);
101 ChangeColours();
102 ChangeAlphabet();
104 // Create the user logging object if we are suppose to. We wait
105 // until now so we have the real value of the parameter and not
106 // just the default.
108 int iUserLogLevel = GetLongParameter(LP_USER_LOG_LEVEL_MASK);
109 if (iUserLogLevel > 0)
110 m_pUserLog = new CUserLog(m_pEventHandler, m_pSettingsStore, iUserLogLevel, m_Alphabet);
112 CreateFactories();
113 CreateInputFilter();
115 // All the setup is done by now, so let the user log object know
116 // that future parameter changes should be logged.
117 if (m_pUserLog != NULL)
118 m_pUserLog->InitIsDone();
122 CDasherInterfaceBase::~CDasherInterfaceBase() {
124 delete m_pDasherModel; // The order of some of these deletions matters
125 delete m_Alphabet;
126 delete m_pDasherView;
127 delete m_ColourIO;
128 delete m_AlphIO;
129 delete m_pColours;
130 delete m_pInputFilter;
131 // Do NOT delete Edit box or Screen. This class did not create them.
133 // When we destruct on shutdown, we'll output any detailed log file
134 if (m_pUserLog != NULL)
136 m_pUserLog->OutputFile();
137 delete m_pUserLog;
138 m_pUserLog = NULL;
141 if (g_pLogger != NULL) {
142 delete g_pLogger;
143 g_pLogger = NULL;
146 // Must delete event handler after all CDasherComponent derived classes
148 delete m_pEventHandler;
151 void CDasherInterfaceBase::PreSetNotify(int iParameter, const std::string &sNewValue) {
153 // FIXME - make this a more general 'pre-set' event in the message
154 // infrastructure
156 switch(iParameter) {
157 case SP_ALPHABET_ID:
158 // Cycle the alphabet history
159 if(GetStringParameter(SP_ALPHABET_ID) != sNewValue) {
160 if(GetStringParameter(SP_ALPHABET_1) != sNewValue) {
161 if(GetStringParameter(SP_ALPHABET_2) != sNewValue) {
162 if(GetStringParameter(SP_ALPHABET_3) != sNewValue)
163 SetStringParameter(SP_ALPHABET_4, GetStringParameter(SP_ALPHABET_3));
165 SetStringParameter(SP_ALPHABET_3, GetStringParameter(SP_ALPHABET_2));
168 SetStringParameter(SP_ALPHABET_2, GetStringParameter(SP_ALPHABET_1));
171 SetStringParameter(SP_ALPHABET_1, GetStringParameter(SP_ALPHABET_ID));
174 break;
178 void CDasherInterfaceBase::InterfaceEventHandler(Dasher::CEvent *pEvent) {
180 if(pEvent->m_iEventType == 1) {
181 Dasher::CParameterNotificationEvent * pEvt(static_cast < Dasher::CParameterNotificationEvent * >(pEvent));
183 switch (pEvt->m_iParameter) {
185 case BP_COLOUR_MODE: // Forces us to redraw the display
186 // TODO: Is this variable ever used any more?
187 Start();
188 Redraw(true);
189 break;
190 case BP_OUTLINE_MODE:
191 Redraw(true);
192 break;
193 case LP_ORIENTATION:
194 if(GetLongParameter(LP_ORIENTATION) == Dasher::Opts::AlphabetDefault)
195 // TODO: See comment in DasherModel.cpp about prefered values
196 SetLongParameter(LP_REAL_ORIENTATION, m_Alphabet->GetOrientation());
197 else
198 SetLongParameter(LP_REAL_ORIENTATION, GetLongParameter(LP_ORIENTATION));
199 Redraw(true);
200 break;
201 case SP_ALPHABET_ID:
202 ChangeAlphabet();
203 Start();
204 Redraw(true);
205 break;
206 case SP_COLOUR_ID:
207 ChangeColours();
208 Redraw(true);
209 break;
210 case SP_DEFAULT_COLOUR_ID: // Delibarate fallthrough
211 case BP_PALETTE_CHANGE:
212 if(GetBoolParameter(BP_PALETTE_CHANGE))
213 SetStringParameter(SP_COLOUR_ID, GetStringParameter(SP_DEFAULT_COLOUR_ID));
214 break;
215 case LP_LANGUAGE_MODEL_ID:
216 CreateDasherModel();
217 Start();
218 Redraw(true);
219 break;
220 case LP_LINE_WIDTH:
221 Redraw(false); // TODO - make this accessible everywhere
222 break;
223 case LP_DASHER_FONTSIZE:
224 // TODO - make screen a CDasherComponent child?
225 Redraw(true);
226 break;
227 case SP_INPUT_DEVICE:
228 CreateInput();
229 break;
230 case SP_INPUT_FILTER:
231 CreateInputFilter();
232 break;
233 default:
234 break;
237 else if(pEvent->m_iEventType == 2) {
238 CEditEvent *pEditEvent(static_cast < CEditEvent * >(pEvent));
240 if(pEditEvent->m_iEditType == 1) {
241 strCurrentContext += pEditEvent->m_sText;
242 if( strCurrentContext.size() > 20 )
243 strCurrentContext = strCurrentContext.substr( strCurrentContext.size() - 20 );
245 strTrainfileBuffer += pEditEvent->m_sText;
247 else if(pEditEvent->m_iEditType == 2) {
248 strCurrentContext = strCurrentContext.substr( 0, strCurrentContext.size() - pEditEvent->m_sText.size());
250 strTrainfileBuffer = strTrainfileBuffer.substr( 0, strTrainfileBuffer.size() - pEditEvent->m_sText.size());
253 else if(pEvent->m_iEventType == EV_CONTROL) {
254 CControlEvent *pControlEvent(static_cast <CControlEvent*>(pEvent));
256 switch(pControlEvent->m_iID) {
257 case CControlManager::CTL_STOP:
258 PauseAt(0,0);
259 break;
260 case CControlManager::CTL_PAUSE:
261 Halt();
262 break;
265 else if(pEvent->m_iEventType == EV_LOCK) {
266 // TODO: 'Reference counting' for locks?
267 CLockEvent *pLockEvent(static_cast<CLockEvent *>(pEvent));
268 m_bGlobalLock = pLockEvent->m_bLock;
272 void CDasherInterfaceBase::WriteTrainFileFull() {
273 WriteTrainFile(strTrainfileBuffer);
274 strTrainfileBuffer = "";
277 void CDasherInterfaceBase::WriteTrainFilePartial() {
278 // TODO: what if we're midway through a unicode character?
279 WriteTrainFile(strTrainfileBuffer.substr(0,100));
280 strTrainfileBuffer = strTrainfileBuffer.substr(100);
283 void CDasherInterfaceBase::CreateDasherModel()
285 if(!m_AlphIO)
286 return;
288 // TODO: Move training into model?
289 // TODO: Do we really need to check for a valid language model?
290 int lmID = GetLongParameter(LP_LANGUAGE_MODEL_ID);
291 if( lmID != -1 ) {
293 // Train the new language model
294 CLockEvent *pEvent;
296 pEvent = new CLockEvent("Training Dasher", true, 0);
297 m_pEventHandler->InsertEvent(pEvent);
298 delete pEvent;
300 // Delete the old model and create a new one
301 if(m_pDasherModel) {
302 delete m_pDasherModel;
303 m_pDasherModel = 0;
306 if(m_deGameModeStrings.size() == 0)
307 m_pDasherModel = new CDasherModel(m_pEventHandler, m_pSettingsStore, this, m_AlphIO);
308 else {
309 m_pDasherModel = new CDasherModel(m_pEventHandler, m_pSettingsStore, this, m_AlphIO, true, m_deGameModeStrings[0]);
310 // m_deGameModeStrings.pop_front();
313 m_Alphabet = m_pDasherModel->GetAlphabetNew();
315 string T = m_Alphabet->GetTrainingFile();
317 int iTotalBytes = 0;
318 iTotalBytes += GetFileSize(GetStringParameter(SP_SYSTEM_LOC) + T);
319 iTotalBytes += GetFileSize(GetStringParameter(SP_USER_LOC) + T);
321 if(iTotalBytes > 0) {
322 int iOffset;
323 iOffset = TrainFile(GetStringParameter(SP_SYSTEM_LOC) + T, iTotalBytes, 0);
324 TrainFile(GetStringParameter(SP_USER_LOC) + T, iTotalBytes, iOffset);
326 else {
327 CMessageEvent oEvent("No training text is avilable for the selected alphabet. Dasher will function, but it may be difficult to enter text.\nPlease see http://www.dasher.org.uk/alphabets/ for more information.", 0, 0);
328 m_pEventHandler->InsertEvent(&oEvent);
331 pEvent = new CLockEvent("Training Dasher", false, 0);
332 m_pEventHandler->InsertEvent(pEvent);
333 delete pEvent;
337 void CDasherInterfaceBase::Start() {
338 // TODO: Clarify the relationship between Start() and
339 // InvalidateContext() - I believe that they essentially do the same
340 // thing
341 PauseAt(0, 0);
342 if(m_pDasherModel != 0) {
343 m_pDasherModel->Start();
345 if(m_pDasherView != 0) {
346 m_pDasherView->ResetSum();
347 m_pDasherView->ResetSumCounter();
348 m_pDasherView->ResetYAutoOffset();
352 void CDasherInterfaceBase::PauseAt(int MouseX, int MouseY) {
353 SetBoolParameter(BP_DASHER_PAUSED, true);
355 // Request a full redraw at the next time step.
356 SetBoolParameter(BP_REDRAW, true);
358 Dasher::CStopEvent oEvent;
359 m_pEventHandler->InsertEvent(&oEvent);
361 if (m_pUserLog != NULL)
362 m_pUserLog->StopWriting((float) GetNats());
365 void CDasherInterfaceBase::Halt() {
366 SetBoolParameter(BP_DASHER_PAUSED, true);
368 if(GetBoolParameter(BP_MOUSEPOS_MODE)) {
369 SetLongParameter(LP_MOUSE_POS_BOX, 1);
372 // This will cause us to reinitialise the frame rate counter - ie we start off slowly
373 if(m_pDasherModel != 0)
374 m_pDasherModel->Halt();
377 void CDasherInterfaceBase::Unpause(unsigned long Time) {
378 SetBoolParameter(BP_DASHER_PAUSED, false);
380 if(m_pDasherModel != 0) {
381 m_pDasherModel->Reset_framerate(Time);
382 //m_pDasherModel->Set_paused(m_Paused);
384 if(m_pDasherView != 0) {
385 m_pDasherView->ResetSum();
386 m_pDasherView->ResetSumCounter();
389 Dasher::CStartEvent oEvent;
390 m_pEventHandler->InsertEvent(&oEvent);
392 ResetNats();
393 if (m_pUserLog != NULL)
394 m_pUserLog->StartWriting();
397 void CDasherInterfaceBase::CreateInput() {
399 // FIXME - this shouldn't be the model used here - we should just change a parameter and work from the appropriate listener
401 if(m_pInput) {
402 m_pInput->Deactivate();
403 m_pInput->Unref();
406 m_pInput = (CDasherInput *)GetModuleByName(GetStringParameter(SP_INPUT_DEVICE));
408 if(m_pInput) {
409 m_pInput->Ref();
410 m_pInput->Activate();
413 if(m_pDasherView != 0)
414 m_pDasherView->SetInput(m_pInput);
417 void CDasherInterfaceBase::NewFrame(unsigned long iTime) {
418 // Fail if Dasher is locked
419 if(m_bGlobalLock || m_bShutdownLock)
420 return;
422 bool bChanged(false);
424 if(m_pDasherView != 0) {
425 if(!GetBoolParameter(BP_TRAINING)) {
426 if (m_pUserLog != NULL) {
428 Dasher::VECTOR_SYMBOL_PROB vAdded;
429 int iNumDeleted = 0;
431 if(m_pInputFilter) {
432 bChanged = m_pInputFilter->Timer(iTime, m_pDasherView, m_pDasherModel); // FIXME - need logging stuff here
435 if (iNumDeleted > 0)
436 m_pUserLog->DeleteSymbols(iNumDeleted);
437 if (vAdded.size() > 0)
438 m_pUserLog->AddSymbols(&vAdded);
441 else {
442 if(m_pInputFilter) {
443 bChanged = m_pInputFilter->Timer(iTime, m_pDasherView, m_pDasherModel);
447 m_pDasherModel->CheckForNewRoot(m_pDasherView);
451 Redraw(bChanged);
453 // This just passes the time through to the framerate tracker, so we
454 // know how often new frames are being drawn.
455 if(m_pDasherModel != 0)
456 m_pDasherModel->NewFrame(iTime);
459 /// Full redraw - renders model, decorations and blits onto display
460 /// buffer. Not recommended if nothing has changed with the model,
461 /// otherwise we're wasting effort.
463 void CDasherInterfaceBase::Redraw(bool bRedrawNodes) {
464 if(!m_pDasherView || !m_pDasherModel)
465 return;
467 if(bRedrawNodes) {
468 m_pDasherView->Screen()->SendMarker(0);
469 m_pDasherModel->RenderToView(m_pDasherView, true);
472 m_pDasherView->Screen()->SendMarker(1);
474 bool bDecorationsChanged(false);
476 if(m_pInputFilter) {
477 bDecorationsChanged = m_pInputFilter->DecorateView(m_pDasherView);
480 if(bRedrawNodes || bDecorationsChanged)
481 m_pDasherView->Display();
484 void CDasherInterfaceBase::ChangeAlphabet() {
486 if(GetStringParameter(SP_ALPHABET_ID) == "") {
487 SetStringParameter(SP_ALPHABET_ID, m_AlphIO->GetDefault());
488 // This will result in ChangeAlphabet() being called again, so
489 // exit from the first recursion
490 return;
493 // Send a lock event
495 WriteTrainFileFull();
497 // Lock Dasher to prevent changes from happening while we're training.
499 SetBoolParameter( BP_TRAINING, true );
501 // m_AlphInfo = m_AlphIO->GetInfo(NewAlphabetID);
503 // //AlphabetID = m_AlphInfo.AlphID.c_str();
505 // // std::auto_ptr < CAlphabet > ptrOld(m_Alphabet); // So we can delete the old alphabet later
507 // m_Alphabet = new CAlphabet(m_AlphInfo);
509 delete m_pDasherModel;
510 m_pDasherModel = 0;
511 CreateDasherModel();
513 // Let our user log object know about the new alphabet since
514 // it needs to convert symbols into text for the log file.
515 if (m_pUserLog != NULL)
516 m_pUserLog->SetAlphabetPtr(m_Alphabet);
518 // Apply options from alphabet
520 SetBoolParameter( BP_TRAINING, false );
522 Start();
527 // std::string CDasherInterfaceBase::GetCurrentAlphabet() {
528 // return GetStringParameter(SP_ALPHABET_ID);
529 // }
531 void CDasherInterfaceBase::ChangeColours() {
532 if(!m_ColourIO)
533 return;
535 // // delete old colours on editing function (ending function? - not really sure what the point of this is - I guess we might fail)
536 // std::auto_ptr < CCustomColours > ptrColours(m_pColours);
538 if(m_pColours) {
539 delete m_pColours;
540 m_pColours = 0;
544 CColourIO::ColourInfo oColourInfo(m_ColourIO->GetInfo(GetStringParameter(SP_COLOUR_ID)));
545 m_pColours = new CCustomColours(oColourInfo);
547 if(m_DasherScreen != 0) {
548 m_DasherScreen->SetColourScheme(m_pColours);
552 void CDasherInterfaceBase::ChangeScreen(CDasherScreen *NewScreen) {
553 m_DasherScreen = NewScreen;
554 m_DasherScreen->SetColourScheme(m_pColours);
556 if(m_pDasherView != 0) {
557 m_pDasherView->ChangeScreen(m_DasherScreen);
558 } else {
559 if(GetLongParameter(LP_VIEW_ID) != -1)
560 ChangeView();
563 Redraw(true);
566 void CDasherInterfaceBase::ChangeView() {
567 // TODO: Actually respond to LP_VIEW_ID parameter (although there is only one view at the moment)
569 if(m_DasherScreen != 0 && m_pDasherModel != 0)
571 delete m_pDasherView;
572 // if(m_pAutoSpeedControl)
573 // delete m_pAutoSpeedControl;
574 m_pDasherView = new CDasherViewSquare(m_pEventHandler, m_pSettingsStore, m_DasherScreen);
577 if (m_pInput)
578 m_pDasherView->SetInput(m_pInput);
582 void CDasherInterfaceBase::GetAlphabets(std::vector <std::string >*AlphabetList) {
583 m_AlphIO->GetAlphabets(AlphabetList);
586 const CAlphIO::AlphInfo & CDasherInterfaceBase::GetInfo(const std::string &AlphID) {
587 return m_AlphIO->GetInfo(AlphID);
590 void CDasherInterfaceBase::SetInfo(const CAlphIO::AlphInfo &NewInfo) {
591 m_AlphIO->SetInfo(NewInfo);
594 void CDasherInterfaceBase::DeleteAlphabet(const std::string &AlphID) {
595 m_AlphIO->Delete(AlphID);
598 void CDasherInterfaceBase::GetColours(std::vector <std::string >*ColourList) {
599 m_ColourIO->GetColours(ColourList);
603 I've used C style I/O because I found that C++ style I/O bloated
604 the Win32 code enormously. The overhead of loading the buffer into
605 the string instead of reading straight into a string seems to be
606 negligible compared to huge requirements elsewhere.
608 int CDasherInterfaceBase::TrainFile(string Filename, int iTotalBytes, int iOffset) {
609 if(Filename == "")
610 return 0;
612 FILE *InputFile;
613 if((InputFile = fopen(Filename.c_str(), "r")) == (FILE *) 0)
614 return 0;
616 const int BufferSize = 1024;
617 char InputBuffer[BufferSize];
618 string StringBuffer;
619 int NumberRead;
620 int iTotalRead(0);
622 vector < symbol > Symbols;
624 CDasherModel::CTrainer * pTrainer = m_pDasherModel->GetTrainer();
625 do {
626 NumberRead = fread(InputBuffer, 1, BufferSize - 1, InputFile);
627 InputBuffer[NumberRead] = '\0';
628 StringBuffer += InputBuffer;
629 bool bIsMore = false;
630 if(NumberRead == (BufferSize - 1))
631 bIsMore = true;
633 Symbols.clear();
634 m_Alphabet->GetSymbols(&Symbols, &StringBuffer, bIsMore);
636 pTrainer->Train(Symbols);
637 iTotalRead += NumberRead;
639 // TODO: No reason for this to be a pointer (other than cut/paste laziness!)
640 CLockEvent *pEvent;
641 pEvent = new CLockEvent("Training Dasher", true, static_cast<int>((100.0 * (iTotalRead + iOffset))/iTotalBytes));
642 m_pEventHandler->InsertEvent(pEvent);
643 delete pEvent;
645 } while(NumberRead == BufferSize - 1);
647 delete pTrainer;
649 fclose(InputFile);
651 return iTotalRead;
654 void CDasherInterfaceBase::GetFontSizes(std::vector <int >*FontSizes) const {
655 FontSizes->push_back(20);
656 FontSizes->push_back(14);
657 FontSizes->push_back(11);
658 FontSizes->push_back(40);
659 FontSizes->push_back(28);
660 FontSizes->push_back(22);
661 FontSizes->push_back(80);
662 FontSizes->push_back(56);
663 FontSizes->push_back(44);
666 double CDasherInterfaceBase::GetCurCPM() {
668 return 0;
671 double CDasherInterfaceBase::GetCurFPS() {
673 return 0;
676 int CDasherInterfaceBase::GetAutoOffset() {
677 if(m_pDasherView != 0) {
678 return m_pDasherView->GetAutoOffset();
680 return -1;
683 double CDasherInterfaceBase::GetNats() const {
684 if(m_pDasherModel)
685 return m_pDasherModel->GetNats();
686 else
687 return 0.0;
690 void CDasherInterfaceBase::ResetNats() {
691 if(m_pDasherModel)
692 m_pDasherModel->ResetNats();
696 void CDasherInterfaceBase::InvalidateContext(bool bForceStart) {
698 m_pDasherModel->m_strContextBuffer = "";
700 Dasher::CEditContextEvent oEvent(10);
701 m_pEventHandler->InsertEvent(&oEvent);
703 std::string strNewContext(m_pDasherModel->m_strContextBuffer);
705 // We keep track of an internal context and compare that to what
706 // we are given - don't restart Dasher if nothing has changed.
707 // This should really be integrated with DasherModel, which
708 // probably will be the case when we start to deal with being able
709 // to back off indefinitely. For now though we'll keep it in a
710 // separate string.
712 int iContextLength( 6 ); // The 'important' context length - should really get from language model
714 // FIXME - use unicode lengths
716 if(bForceStart || (strNewContext.substr( std::max(static_cast<int>(strNewContext.size()) - iContextLength, 0)) != strCurrentContext.substr( std::max(static_cast<int>(strCurrentContext.size()) - iContextLength, 0)))) {
718 if(m_pDasherModel != NULL) {
719 if(m_pDasherModel->m_bContextSensitive || bForceStart) {
720 m_pDasherModel->SetContext(strNewContext);
721 PauseAt(0,0);
725 strCurrentContext = strNewContext;
726 WriteTrainFileFull();
729 if(m_pDasherView)
730 while( m_pDasherModel->CheckForNewRoot(m_pDasherView) ) {
731 // Do nothing
734 Redraw(true);
738 void CDasherInterfaceBase::SetContext(std::string strNewContext) {
739 m_pDasherModel->m_strContextBuffer = strNewContext;
742 // Control mode stuff
744 void CDasherInterfaceBase::RegisterNode( int iID, const std::string &strLabel, int iColour ) {
745 m_pDasherModel->RegisterNode(iID, strLabel, iColour);
748 void CDasherInterfaceBase::ConnectNode(int iChild, int iParent, int iAfter) {
749 m_pDasherModel->ConnectNode(iChild, iParent, iAfter);
752 void CDasherInterfaceBase::DisconnectNode(int iChild, int iParent) {
753 m_pDasherModel->DisconnectNode(iChild, iParent);
756 void CDasherInterfaceBase::SetBoolParameter(int iParameter, bool bValue) {
757 m_pSettingsStore->SetBoolParameter(iParameter, bValue);
760 void CDasherInterfaceBase::SetLongParameter(int iParameter, long lValue) {
761 m_pSettingsStore->SetLongParameter(iParameter, lValue);
764 void CDasherInterfaceBase::SetStringParameter(int iParameter, const std::string & sValue) {
765 PreSetNotify(iParameter, sValue);
766 m_pSettingsStore->SetStringParameter(iParameter, sValue);
769 bool CDasherInterfaceBase::GetBoolParameter(int iParameter) {
770 return m_pSettingsStore->GetBoolParameter(iParameter);
773 long CDasherInterfaceBase::GetLongParameter(int iParameter) {
774 return m_pSettingsStore->GetLongParameter(iParameter);
777 std::string CDasherInterfaceBase::GetStringParameter(int iParameter) {
778 return m_pSettingsStore->GetStringParameter(iParameter);
781 void CDasherInterfaceBase::ResetParameter(int iParameter) {
782 m_pSettingsStore->ResetParameter(iParameter);
785 // We need to be able to get at the UserLog object from outside the interface
786 CUserLog* CDasherInterfaceBase::GetUserLogPtr() {
787 return m_pUserLog;
790 void CDasherInterfaceBase::KeyDown(int iTime, int iId) {
791 if(m_pInputFilter && !GetBoolParameter(BP_TRAINING)) {
792 m_pInputFilter->KeyDown(iTime, iId, m_pDasherModel);
796 void CDasherInterfaceBase::KeyUp(int iTime, int iId) {
797 if(m_pInputFilter && !GetBoolParameter(BP_TRAINING)) {
798 m_pInputFilter->KeyUp(iTime, iId, m_pDasherModel);
802 void CDasherInterfaceBase::CreateInputFilter()
804 if(m_pInputFilter) {
805 m_pInputFilter->Deactivate();
806 m_pInputFilter->Unref();
807 m_pInputFilter = NULL;
810 m_pInputFilter = (CInputFilter *)GetModuleByName(GetStringParameter(SP_INPUT_FILTER));
812 if(m_pInputFilter) {
813 m_pInputFilter->Ref();
814 m_pInputFilter->Activate();
818 void CDasherInterfaceBase::RegisterFactory(CModuleFactory *pFactory) {
819 m_oModuleManager.RegisterFactory(pFactory);
822 CDasherModule *CDasherInterfaceBase::GetModule(long long int iID) {
823 return m_oModuleManager.GetModule(iID);
826 CDasherModule *CDasherInterfaceBase::GetModuleByName(const std::string &strName) {
827 return m_oModuleManager.GetModuleByName(strName);
831 void CDasherInterfaceBase::CreateFactories() {
832 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDefaultFilter(m_pEventHandler, m_pSettingsStore, this, m_pDasherModel,3, "Normal Control")));
833 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new COneDimensionalFilter(m_pEventHandler, m_pSettingsStore, this, m_pDasherModel)));
834 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CEyetrackerFilter(m_pEventHandler, m_pSettingsStore, this, m_pDasherModel)));
835 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CClickFilter(m_pEventHandler, m_pSettingsStore, this)));
836 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDynamicFilter(m_pEventHandler, m_pSettingsStore, this)));
837 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CTwoButtonDynamicFilter(m_pEventHandler, m_pSettingsStore, this, 14, 1, "Two Button Dynamic Mode")));
838 // TODO: specialist factory for button mode
839 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDasherButtons(m_pEventHandler, m_pSettingsStore, this, 5, 1, true,8, "Menu Mode")));
840 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDasherButtons(m_pEventHandler, m_pSettingsStore, this, 3, 0, false,10, "Direct Mode")));
841 // RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDasherButtons(m_pEventHandler, m_pSettingsStore, this, 4, 0, false,11, "Buttons 3")));
842 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDasherButtons(m_pEventHandler, m_pSettingsStore, this, 3, 3, false,12, "Alternating Direct Mode")));
843 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CDasherButtons(m_pEventHandler, m_pSettingsStore, this, 4, 2, false,13, "Compass Mode")));
844 RegisterFactory(new CWrapperFactory(m_pEventHandler, m_pSettingsStore, new CStylusFilter(m_pEventHandler, m_pSettingsStore, this, m_pDasherModel,15, "Stylus Control")));
848 void CDasherInterfaceBase::GetPermittedValues(int iParameter, std::vector<std::string> &vList) {
849 // TODO: Deprecate direct calls to these functions
850 switch (iParameter) {
851 case SP_ALPHABET_ID:
852 GetAlphabets(&vList);
853 break;
854 case SP_COLOUR_ID:
855 GetColours(&vList);
856 break;
857 case SP_INPUT_FILTER:
858 m_oModuleManager.ListModules(1, vList);
859 break;
860 case SP_INPUT_DEVICE:
861 m_oModuleManager.ListModules(0, vList);
862 break;
866 void CDasherInterfaceBase::StartShutdown() {
867 m_bShutdownLock = true;
870 bool CDasherInterfaceBase::GetModuleSettings(const std::string &strName, SModuleSettings **pSettings, int *iCount) {
871 return GetModuleByName(strName)->GetSettings(pSettings, iCount);