[dasher: 13/28] Refactor movement, remove BP_DASHER_PAUSED
- From: Patrick Welche <pwelche src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dasher: 13/28] Refactor movement, remove BP_DASHER_PAUSED
- Date: Tue, 22 Nov 2011 17:03:45 +0000 (UTC)
commit 9eae07fcd762b166490cafb053ad1af70e7a60a0
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date: Wed Sep 21 17:04:05 2011 +0100
Refactor movement, remove BP_DASHER_PAUSED
Filters schedule one step or many steps as/when req'd (e.g. in Timer or on Key).
This makes the two DasherModel movement methods, ScheduleZoom & ScheduleOneStep,
_even_more_ similar...hopefully we will soon be able to combine them?
Note much ambiguity remains as to when to call m_pInterface->Done() (was Stop).
Src/DasherCore/AlternatingDirectMode.cpp | 2 +-
Src/DasherCore/BasicLog.cpp | 3 +-
Src/DasherCore/BasicLog.h | 4 +-
Src/DasherCore/ButtonMode.cpp | 4 +-
Src/DasherCore/ButtonMode.h | 2 +-
Src/DasherCore/ButtonMultiPress.cpp | 10 +-
Src/DasherCore/ButtonMultiPress.h | 6 +-
Src/DasherCore/CircleStartHandler.cpp | 69 +++++-----
Src/DasherCore/CircleStartHandler.h | 10 +-
Src/DasherCore/ClickFilter.cpp | 6 +-
Src/DasherCore/ClickFilter.h | 5 +-
Src/DasherCore/ControlManager.cpp | 8 +-
Src/DasherCore/DashIntfScreenMsgs.cpp | 32 ++---
Src/DasherCore/DashIntfScreenMsgs.h | 5 +-
Src/DasherCore/DasherButtons.cpp | 10 +-
Src/DasherCore/DasherButtons.h | 4 +-
Src/DasherCore/DasherInterfaceBase.cpp | 50 ++++---
Src/DasherCore/DasherInterfaceBase.h | 36 +++--
Src/DasherCore/DasherModel.cpp | 212 ++++++++++++++---------------
Src/DasherCore/DasherModel.h | 48 +++----
Src/DasherCore/DefaultFilter.cpp | 70 +++++-----
Src/DasherCore/DefaultFilter.h | 6 +-
Src/DasherCore/DynamicButtons.cpp | 65 ++++-----
Src/DasherCore/DynamicButtons.h | 19 +--
Src/DasherCore/DynamicFilter.cpp | 11 +-
Src/DasherCore/DynamicFilter.h | 14 ++-
Src/DasherCore/GameModule.cpp | 15 ++-
Src/DasherCore/GameModule.h | 2 +
Src/DasherCore/InputFilter.h | 48 ++++++-
Src/DasherCore/OneButtonDynamicFilter.cpp | 5 +-
Src/DasherCore/OneButtonDynamicFilter.h | 2 +-
Src/DasherCore/OneButtonFilter.cpp | 13 +--
Src/DasherCore/OneButtonFilter.h | 5 +-
Src/DasherCore/OneDimensionalFilter.cpp | 31 ++--
Src/DasherCore/Parameters.cpp | 1 -
Src/DasherCore/Parameters.h | 2 +-
Src/DasherCore/StartHandler.h | 3 +-
Src/DasherCore/StylusFilter.cpp | 28 ++---
Src/DasherCore/StylusFilter.h | 7 +-
Src/DasherCore/TwoBoxStartHandler.cpp | 11 +-
Src/DasherCore/TwoBoxStartHandler.h | 4 +-
Src/DasherCore/TwoButtonDynamicFilter.cpp | 8 +-
Src/DasherCore/TwoButtonDynamicFilter.h | 4 +-
Src/DasherCore/TwoPushDynamicFilter.cpp | 20 +--
Src/DasherCore/TwoPushDynamicFilter.h | 6 +-
Src/DasherCore/UserLog.cpp | 7 +-
Src/DasherCore/UserLog.h | 2 +-
Src/DasherCore/UserLogBase.cpp | 15 +--
Src/DasherCore/UserLogBase.h | 9 +-
Src/Gtk2/DasherControl.cpp | 5 +-
Src/Gtk2/DasherControl.h | 4 +-
Src/Gtk2/GtkDasherControl.cpp | 2 +-
Src/iPhone/Classes/DasherAppDelegate.mm | 2 +-
Src/iPhone/Classes/IPhoneFilters.h | 4 +-
Src/iPhone/Classes/IPhoneFilters.mm | 22 ++--
55 files changed, 506 insertions(+), 492 deletions(-)
---
diff --git a/Src/DasherCore/AlternatingDirectMode.cpp b/Src/DasherCore/AlternatingDirectMode.cpp
index ddf7960..9ba5d74 100644
--- a/Src/DasherCore/AlternatingDirectMode.cpp
+++ b/Src/DasherCore/AlternatingDirectMode.cpp
@@ -108,7 +108,7 @@ void CAlternatingDirectMode::DirectKeyDown(unsigned long iTime, int iId, CDasher
return;
}
//iTargetBox now indicates the box into which to zoom
- pModel->ScheduleZoom(iTime, m_pBoxes[iTargetBox].iTop, m_pBoxes[iTargetBox].iBottom);
+ ScheduleZoom(pModel, m_pBoxes[iTargetBox].iTop, m_pBoxes[iTargetBox].iBottom);
}
bool CAlternatingDirectMode::GetSettings(SModuleSettings **pSettings, int *iCount) {
diff --git a/Src/DasherCore/BasicLog.cpp b/Src/DasherCore/BasicLog.cpp
index 3b04771..43f194c 100644
--- a/Src/DasherCore/BasicLog.cpp
+++ b/Src/DasherCore/BasicLog.cpp
@@ -14,7 +14,8 @@
using namespace Dasher;
-CBasicLog::CBasicLog(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pIntf) : CUserLogBase(pCreateFrom,pIntf) {
+CBasicLog::CBasicLog(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pIntf)
+: CUserLogBase(pIntf), CSettingsUser(pCreateFrom) {
m_iSymbolCount = 0;
m_bStarted = false;
}
diff --git a/Src/DasherCore/BasicLog.h b/Src/DasherCore/BasicLog.h
index 34de634..9bb95ee 100644
--- a/Src/DasherCore/BasicLog.h
+++ b/Src/DasherCore/BasicLog.h
@@ -6,9 +6,9 @@
/// \ingroup Logging
/// @{
-class CBasicLog : public CUserLogBase {
+class CBasicLog : public CUserLogBase, public Dasher::CSettingsUser {
public:
- CBasicLog(CSettingsUser *pCreateFrom, Dasher::CDasherInterfaceBase *pIntf);
+ CBasicLog(Dasher::CSettingsUser *pCreateFrom, Dasher::CDasherInterfaceBase *pIntf);
~CBasicLog();
virtual void AddParam(const string& strName, const string& strValue, int iOptionMask = 0) {};
diff --git a/Src/DasherCore/ButtonMode.cpp b/Src/DasherCore/ButtonMode.cpp
index d8c4e5b..248e9ce 100644
--- a/Src/DasherCore/ButtonMode.cpp
+++ b/Src/DasherCore/ButtonMode.cpp
@@ -156,14 +156,14 @@ bool CButtonMode::DecorateView(CDasherView *pView, CDasherInput *pInput) {
return bRV;
}
-bool CButtonMode::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
+void CButtonMode::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
bool m_bOldHighlight(m_bHighlight);
m_bHighlight = (Time - m_iLastTime < 200);
if(m_bOldHighlight != m_bHighlight)
m_bDecorationChanged = true;
- return CDasherButtons::Timer(Time, pView, pInput, pModel, pol);
+ CDasherButtons::Timer(Time, pView, pInput, pModel, pol);
}
void CButtonMode::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
diff --git a/Src/DasherCore/ButtonMode.h b/Src/DasherCore/ButtonMode.h
index 454ac94..a6fb2ac 100644
--- a/Src/DasherCore/ButtonMode.h
+++ b/Src/DasherCore/ButtonMode.h
@@ -24,7 +24,7 @@ class CButtonMode : public CDasherButtons, protected CSettingsObserver
CButtonMode(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, bool bMenu, int iID, const char *szName);
virtual void HandleEvent(int iParameter);
- bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
+ void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
bool DecorateView(CDasherView *pView, CDasherInput *pInput);
//override to get mouse clicks/taps back again
diff --git a/Src/DasherCore/ButtonMultiPress.cpp b/Src/DasherCore/ButtonMultiPress.cpp
index 4ab679f..ec68f79 100644
--- a/Src/DasherCore/ButtonMultiPress.cpp
+++ b/Src/DasherCore/ButtonMultiPress.cpp
@@ -66,14 +66,12 @@ void CButtonMultiPress::pause()
m_deQueueTimes.clear();
}
-void CButtonMultiPress::reverse()
-{
- CDynamicButtons::reverse();
+void CButtonMultiPress::reverse(unsigned long iTime) {
+ CDynamicButtons::reverse(iTime);
m_deQueueTimes.clear();
}
-void CButtonMultiPress::run()
-{
+void CButtonMultiPress::run(unsigned long iTime) {
if (!isRunning()) m_deQueueTimes.clear();
- CDynamicButtons::run();
+ CDynamicButtons::run(iTime);
}
diff --git a/Src/DasherCore/ButtonMultiPress.h b/Src/DasherCore/ButtonMultiPress.h
index 40d59e6..f1fa348 100644
--- a/Src/DasherCore/ButtonMultiPress.h
+++ b/Src/DasherCore/ButtonMultiPress.h
@@ -37,11 +37,11 @@ class CButtonMultiPress : public CDynamicButtons {
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
+ void pause();
protected:
virtual unsigned int maxClickCount()=0;
- virtual void reverse();
- virtual void pause();
- virtual void run();
+ void reverse(unsigned long iTime);
+ void run(unsigned long iTime);
private:
virtual void RevertPresses(int iCount) {};
diff --git a/Src/DasherCore/CircleStartHandler.cpp b/Src/DasherCore/CircleStartHandler.cpp
index a6017da..b5edc5a 100644
--- a/Src/DasherCore/CircleStartHandler.cpp
+++ b/Src/DasherCore/CircleStartHandler.cpp
@@ -36,20 +36,17 @@ CCircleStartHandler::~CCircleStartHandler() {
if (m_pView) m_pView->Observable<CDasherView*>::Unregister(this);
}
-void CCircleStartHandler::ComputeScreenLoc(CDasherView *pView) {
- if (pView != m_pView) {
- if (m_pView) m_pView->Observable<CDasherView*>::Unregister(this);
- (m_pView=pView)->Observable<CDasherView*>::Register(this);
- } else if (m_iScreenRadius!=-1) return;
+CDasherScreen::point CCircleStartHandler::CircleCenter(CDasherView *pView) {
+ if (m_iScreenRadius!=-1) return m_screenCircleCenter;
- pView->Dasher2Screen(CDasherModel::ORIGIN_X, CDasherModel::ORIGIN_Y, m_screenCircleCenter.x, m_screenCircleCenter.y);
+ m_pView->Dasher2Screen(CDasherModel::ORIGIN_X, CDasherModel::ORIGIN_Y, m_screenCircleCenter.x, m_screenCircleCenter.y);
//compute radius against orientation. It'd be simpler to use
// Math.min(screen width, screen height) * LP_CIRCLE_PERCENT / 100
// - should we?
screenint iEdgeX, iEdgeY;
- pView->Dasher2Screen(CDasherModel::ORIGIN_X, CDasherModel::ORIGIN_Y + (CDasherModel::MAX_Y*GetLongParameter(LP_CIRCLE_PERCENT))/100, iEdgeX, iEdgeY);
+ m_pView->Dasher2Screen(CDasherModel::ORIGIN_X, CDasherModel::ORIGIN_Y + (CDasherModel::MAX_Y*GetLongParameter(LP_CIRCLE_PERCENT))/100, iEdgeX, iEdgeY);
- const Opts::ScreenOrientations iDirection(pView->GetOrientation());
+ const Opts::ScreenOrientations iDirection(m_pView->GetOrientation());
if((iDirection == Opts::TopToBottom) || (iDirection == Opts::BottomToTop)) {
m_iScreenRadius = iEdgeX - m_screenCircleCenter.x;
@@ -57,14 +54,16 @@ void CCircleStartHandler::ComputeScreenLoc(CDasherView *pView) {
else {
m_iScreenRadius = iEdgeY - m_screenCircleCenter.y;
}
+ return m_screenCircleCenter;
}
bool CCircleStartHandler::DecorateView(CDasherView *pView) {
- ComputeScreenLoc(pView);
+ if (!m_pView) (m_pView=pView)->Observable<CDasherView*>::Register(this);
+ CDasherScreen::point ctr = CircleCenter(pView);
const bool bAboutToChange = m_bInCircle && m_iEnterTime != std::numeric_limits<long>::max();
int fillColor, lineColor, lineWidth;
- if (GetBoolParameter(BP_DASHER_PAUSED)) {
+ if (m_pFilter->isPaused()) {
lineColor=2; lineWidth=1;
fillColor = bAboutToChange ? 241 : 242;
} else {
@@ -72,16 +71,17 @@ bool CCircleStartHandler::DecorateView(CDasherView *pView) {
lineWidth = bAboutToChange ? 3 : 1;
}
- pView->Screen()->DrawCircle(m_screenCircleCenter.x, m_screenCircleCenter.y, m_iScreenRadius, fillColor, lineColor, lineWidth);
+ pView->Screen()->DrawCircle(ctr.x, ctr.y, m_iScreenRadius, fillColor, lineColor, lineWidth);
return true;
}
void CCircleStartHandler::Timer(unsigned long iTime, dasherint mouseX, dasherint mouseY,CDasherView *pView) {
- ComputeScreenLoc(pView);
+ if (!m_pView) (m_pView=pView)->Observable<CDasherView*>::Register(this);
+ CDasherScreen::point ctr = CircleCenter(pView);
screenint x,y;
pView->Dasher2Screen(mouseX, mouseY, x, y);
- x-=m_screenCircleCenter.x; y-=m_screenCircleCenter.y;
+ x-=ctr.x; y-=ctr.y;
const bool inCircleNow = x*x + y*y <= (m_iScreenRadius * m_iScreenRadius);
if (inCircleNow) {
@@ -89,11 +89,11 @@ void CCircleStartHandler::Timer(unsigned long iTime, dasherint mouseX, dasherint
//still in circle...check they aren't still in there after prev. activation
if (m_iEnterTime != std::numeric_limits<long>::max() && iTime - m_iEnterTime > 1000) {
//activate!
- if (GetBoolParameter(BP_DASHER_PAUSED))
- m_pFilter->Unpause(iTime);
+ if (m_pFilter->isPaused())
+ m_pFilter->run(iTime);
else
- m_pFilter->m_pInterface->Stop();
- //note our HandleEvent method will then set
+ m_pFilter->stop();
+ //note our onPause method will then set
// m_iEnterTime = std::numeric_limits<long>::max()
// thus preventing us from firing until user leaves circle and enters again
}
@@ -109,24 +109,29 @@ void CCircleStartHandler::Timer(unsigned long iTime, dasherint mouseX, dasherint
}
void CCircleStartHandler::HandleEvent(int iParameter) {
- switch (iParameter) {
- case LP_CIRCLE_PERCENT:
- //recompute geometry.
- m_iScreenRadius = -1;
- break;
- case BP_DASHER_PAUSED:
- m_iEnterTime = std::numeric_limits<long>::max();
- //In one-dimensional mode, we have that (un)pausing can _move_ the circle, thus,
- // clicking (or using any other start mechanism) can cause the circle to appear
- // around the mouse. If this happens, you should have to leave and re-enter
- // the circle before the start handler does anything. The following ensures this.
- m_bInCircle = true;
- break;
- }
+ if (iParameter==LP_CIRCLE_PERCENT)
+ m_iScreenRadius = -1; //recompute geometry.
+}
+
+void CCircleStartHandler::onPause() {
+ m_iEnterTime = std::numeric_limits<long>::max();
+ //In one-dimensional mode, we have that (un)pausing can _move_ the circle, thus,
+ // clicking (or using any other start mechanism) can cause the circle to appear
+ // around the mouse. If this happens, you should have to leave and re-enter
+ // the circle before the start handler does anything. The following ensures this.
+ m_bInCircle = true;
+}
+
+void CCircleStartHandler::onRun(unsigned long iTime) {
+ //reset things in exactly the same way as when we pause...
+ onPause();
}
void CCircleStartHandler::HandleEvent(CDasherView *pNewView) {
//need to recompute geometry...
m_iScreenRadius = -1; //even if it's the same view
- ComputeScreenLoc(pNewView);
+ if (pNewView != m_pView) {
+ if (m_pView) m_pView->Observable<CDasherView*>::Unregister(this);
+ (m_pView=pNewView)->Observable<CDasherView*>::Register(this);
+ }
}
diff --git a/Src/DasherCore/CircleStartHandler.h b/Src/DasherCore/CircleStartHandler.h
index 351471d..1cf6129 100644
--- a/Src/DasherCore/CircleStartHandler.h
+++ b/Src/DasherCore/CircleStartHandler.h
@@ -16,7 +16,8 @@ public:
virtual void Timer(unsigned long iTime, dasherint iX, dasherint iY, CDasherView *pView);
virtual void HandleEvent(int iParameter);
virtual void HandleEvent(CDasherView *pView);
-
+ void onPause();
+ void onRun(unsigned long iTime);
protected:
///Time (as unix timestamp) when user entered circle; max() => already acted upon
long m_iEnterTime;
@@ -24,10 +25,11 @@ protected:
bool m_bInCircle;
///Radius of circle in screen coordinates (-1 = needs recomputing)
int m_iScreenRadius;
- ///Center of screen circle (needs recomputing if radius does)
- CDasherScreen::point m_screenCircleCenter;
CDasherView *m_pView;
- virtual void ComputeScreenLoc(CDasherView *pView);
+ virtual CDasherScreen::point CircleCenter(CDasherView *pView);
+private:
+ ///Cached center of screen circle (needs recomputing if radius does)
+ CDasherScreen::point m_screenCircleCenter;
};
}
/// @}
diff --git a/Src/DasherCore/ClickFilter.cpp b/Src/DasherCore/ClickFilter.cpp
index 4c55cd6..e9aa0dd 100644
--- a/Src/DasherCore/ClickFilter.cpp
+++ b/Src/DasherCore/ClickFilter.cpp
@@ -78,10 +78,6 @@ void CZoomAdjuster::AdjustZoomCoords(myint &iDasherX, myint &iDasherY, CDasherVi
}
}
-bool CClickFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
- return pModel->NextScheduledStep();
-}
-
void CClickFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
switch(iId) {
case 100: // Mouse clicks
@@ -91,7 +87,7 @@ void CClickFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDa
pInput->GetDasherCoords(iDasherX, iDasherY, pView);
AdjustZoomCoords(iDasherX, iDasherY, pView);
- pModel->ScheduleZoom(iTime, iDasherY-iDasherX, iDasherY+iDasherX);
+ ScheduleZoom(pModel,iDasherY-iDasherX, iDasherY+iDasherX);
}
break;
default:
diff --git a/Src/DasherCore/ClickFilter.h b/Src/DasherCore/ClickFilter.h
index 6cb9e0e..36231fd 100644
--- a/Src/DasherCore/ClickFilter.h
+++ b/Src/DasherCore/ClickFilter.h
@@ -17,13 +17,12 @@ namespace Dasher {
void AdjustZoomCoords(myint &iDasherX, myint &iDasherY, CDasherView *comp);
};
-class CClickFilter : public CInputFilter, private CZoomAdjuster {
+class CClickFilter : public CStaticFilter, private CZoomAdjuster {
public:
CClickFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface)
- : CInputFilter(pInterface, 7, _("Click Mode")), CZoomAdjuster(pCreator) { };
+ : CStaticFilter(pInterface, 7, _("Click Mode")), CZoomAdjuster(pCreator) { };
virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
- virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pDasherModel, CExpansionPolicy **pol);
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
virtual bool GetSettings(SModuleSettings **pSettings, int *iCount);
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index 5e8828b..9483bdb 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -251,7 +251,7 @@ CControlManager::CControlManager(CSettingsUser *pCreateFrom, CNodeCreationManage
m_pPause = new Pause("Pause",241);
m_pPause->successors.push_back(NULL);
m_pPause->successors.push_back(GetRootTemplate());
- m_pStop = new MethodTemplate<CDasherInterfaceBase>("Stop", 242, pInterface, &CDasherInterfaceBase::Stop);
+ m_pStop = new MethodTemplate<CDasherInterfaceBase>(_("Done"), 242, pInterface, &CDasherInterfaceBase::Done);
m_pStop->successors.push_back(NULL);
m_pStop->successors.push_back(GetRootTemplate());
@@ -268,7 +268,7 @@ CControlManager::CControlManager(CSettingsUser *pCreateFrom, CNodeCreationManage
CControlBase::Pause::Pause(const string &strLabel, int iColour) : NodeTemplate(strLabel,iColour) {
}
void CControlBase::Pause::happen(CContNode *pNode) {
- pNode->mgr()->SetBoolParameter(BP_DASHER_PAUSED,true);
+ pNode->mgr()->m_pInterface->GetActiveInputMethod()->pause();
}
CControlBase::NodeTemplate *CControlManager::parseOther(const XML_Char *name, const XML_Char **atts) {
@@ -389,14 +389,14 @@ void CControlManager::updateActions() {
//stop does something, and we're told to add a node for it
// (either a dynamic filter where the user can't use the normal stop mechanism precisely,
// or a static filter but a 'stop' action is easier than using speak->all / copy->all then pause)
- if (m_pInterface->hasStopTriggers() && GetBoolParameter(BP_CONTROL_MODE_HAS_HALT))
+ if (m_pInterface->hasDone() && GetBoolParameter(BP_CONTROL_MODE_HAS_HALT))
vRootSuccessors.push_back(m_pStop);
if (it!=vOldRootSuccessors.end() && *it == m_pStop) it++;
//filter is pauseable, and either 'stop' would do something (so pause is different),
// or we're told to have a stop node but it would be indistinguishable from pause (=>have pause)
CInputFilter *pInput(m_pInterface->GetActiveInputMethod());
- if (pInput->supportsPause() && (m_pInterface->hasStopTriggers() || GetBoolParameter(BP_CONTROL_MODE_HAS_HALT)))
+ if (pInput->supportsPause() && (m_pInterface->hasDone() || GetBoolParameter(BP_CONTROL_MODE_HAS_HALT)))
vRootSuccessors.push_back(m_pPause);
if (it!=vOldRootSuccessors.end() && *it == m_pPause) it++;
diff --git a/Src/DasherCore/DashIntfScreenMsgs.cpp b/Src/DasherCore/DashIntfScreenMsgs.cpp
index a9d007c..7ef8b30 100644
--- a/Src/DasherCore/DashIntfScreenMsgs.cpp
+++ b/Src/DasherCore/DashIntfScreenMsgs.cpp
@@ -12,7 +12,7 @@ void CDashIntfScreenMsgs::Message(const string &strText, bool bInterrupt) {
CDasherScreen::Label *lab = m_DasherScreen->MakeLabel(strText,GetLongParameter(LP_MESSAGE_FONTSIZE));
if (bInterrupt) {
m_dqModalMessages.push_back(pair<CDasherScreen::Label*,bool>(lab,false));
- SetBoolParameter(BP_DASHER_PAUSED, true);
+ GetActiveInputMethod()->pause();
}
else
m_dqAsyncMessages.push_back(pair<CDasherScreen::Label*,unsigned long>(lab, 0));
@@ -81,25 +81,21 @@ void CDashIntfScreenMsgs::ChangeScreen(CDasherScreen *pNewScreen) {
}
}
-void CDashIntfScreenMsgs::HandleEvent(int iParameter) {
- CDashIntfSettings::HandleEvent(iParameter);
- if (iParameter==BP_DASHER_PAUSED && !GetBoolParameter(BP_DASHER_PAUSED)) {
- //just unpaused.
- while (!m_dqModalMessages.empty()) {
- if (m_dqModalMessages.front().second) {
- //Message has been displayed; delete it
- delete m_dqModalMessages.front().first; //the label
- m_dqModalMessages.pop_front();
- } else {
- //there are more, not-yet displayed, modal messages!
- //These should be after any that were displayed (which have now been erased), so:
- // do not unpause; next frame will render more messages instead.
- m_pDasherModel->ClearScheduledSteps();
- SetBoolParameter(BP_DASHER_PAUSED,true);
- return;
- }
+void CDashIntfScreenMsgs::onUnpause(unsigned long lTime) {
+ while (!m_dqModalMessages.empty()) {
+ if (m_dqModalMessages.front().second) {
+ //Message has been displayed; delete it
+ delete m_dqModalMessages.front().first; //the label
+ m_dqModalMessages.pop_front();
+ } else {
+ //there are more, not-yet displayed, modal messages!
+ //These should be after any that were displayed (which have now been erased),
+ // so do not unpause; next frame will render more messages instead.
+ GetActiveInputMethod()->pause();
+ return;
}
}
+ CDasherInterfaceBase::onUnpause(lTime);
}
CGameModule *CDashIntfScreenMsgs::CreateGameModule(CDasherView *pView, CDasherModel *pModel) {
diff --git a/Src/DasherCore/DashIntfScreenMsgs.h b/Src/DasherCore/DashIntfScreenMsgs.h
index bd7d6d5..a589e25 100644
--- a/Src/DasherCore/DashIntfScreenMsgs.h
+++ b/Src/DasherCore/DashIntfScreenMsgs.h
@@ -55,9 +55,8 @@ public:
///Override to re-MakeLabel any messages.
void ChangeScreen(CDasherScreen *pNewScreen);
- ///Listen for BP_DASHER_PAUSED being cleared to flush any modal messages that
- /// have been displayed before resuming.
- void HandleEvent(int iParameter);
+ ///Flush any modal messages that have been displayed before resuming.
+ void onUnpause(unsigned long lTime);
///Implement to return a ScreenGameModule, i.e. rendering text prompts
/// onto the Screen with Labels, much as we do for messages!
diff --git a/Src/DasherCore/DasherButtons.cpp b/Src/DasherCore/DasherButtons.cpp
index 135c28b..c04adb1 100644
--- a/Src/DasherCore/DasherButtons.cpp
+++ b/Src/DasherCore/DasherButtons.cpp
@@ -24,7 +24,7 @@ static char THIS_FILE[] = __FILE__;
using namespace Dasher;
CDasherButtons::CDasherButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, bool bMenu, ModuleID_t iID, const char *szName)
- : CSettingsUser(pCreator), CInputFilter(pInterface, iID, szName), m_bMenu(bMenu), m_bDecorationChanged(true), m_pBoxes(NULL), iActiveBox(0) {}
+ : CStaticFilter(pInterface, iID, szName), CSettingsUser(pCreator), m_bMenu(bMenu), m_bDecorationChanged(true), m_pBoxes(NULL), iActiveBox(0) {}
CDasherButtons::~CDasherButtons()
{
@@ -54,7 +54,7 @@ void CDasherButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, C
case 3:
case 100:
m_bDecorationChanged = true;
- pModel->ScheduleZoom(iTime, m_pBoxes[iActiveBox].iTop, m_pBoxes[iActiveBox].iBottom);
+ ScheduleZoom(pModel, m_pBoxes[iActiveBox].iTop, m_pBoxes[iActiveBox].iBottom);
if(iActiveBox != m_iNumBoxes-1)
iActiveBox = 0;
break;
@@ -76,10 +76,10 @@ void CDasherButtons::DirectKeyDown(unsigned long iTime, int iId, CDasherView *pV
else
iActiveBox = m_iNumBoxes-2;
- pModel->ScheduleZoom(iTime, m_pBoxes[iActiveBox].iTop,m_pBoxes[iActiveBox].iBottom);
+ ScheduleZoom(pModel, m_pBoxes[iActiveBox].iTop,m_pBoxes[iActiveBox].iBottom);
}
-bool CDasherButtons::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
+void CDasherButtons::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
if (m_bMenu && GetLongParameter(LP_BUTTON_SCAN_TIME) &&
Time > m_iScanTime) {
m_iScanTime = Time + GetLongParameter(LP_BUTTON_SCAN_TIME);
@@ -94,8 +94,6 @@ bool CDasherButtons::Timer(unsigned long Time, CDasherView *pView, CDasherInput
pInput->GetDasherCoords(iDasherX, iDasherY, pView);
// ----
-
- return pModel->NextScheduledStep();
}
void CDasherButtons::NewDrawGoTo(CDasherView *pView, myint iDasherMin, myint iDasherMax, bool bActive) {
diff --git a/Src/DasherCore/DasherButtons.h b/Src/DasherCore/DasherButtons.h
index 32db423..0adb5af 100644
--- a/Src/DasherCore/DasherButtons.h
+++ b/Src/DasherCore/DasherButtons.h
@@ -18,7 +18,7 @@ using namespace std;
namespace Dasher {
/// \ingroup Input
/// @{
-class CDasherButtons : public CInputFilter, protected CSettingsUser
+class CDasherButtons : public CStaticFilter, protected CSettingsUser
{
public:
CDasherButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, bool bMenu, ModuleID_t iID, const char *szName);
@@ -28,7 +28,7 @@ class CDasherButtons : public CInputFilter, protected CSettingsUser
virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput)=0;
void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
- bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
void Activate();
struct SBoxInfo {
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index 6c92a03..e51e938 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -276,9 +276,6 @@ void CDasherInterfaceBase::HandleEvent(int iParameter) {
CreateInputFilter();
ScheduleRedraw();
break;
- case BP_DASHER_PAUSED:
- ScheduleRedraw();
- break;
case LP_MARGIN_WIDTH:
case BP_NONLINEAR_Y:
case LP_NONLINEAR_X:
@@ -445,15 +442,12 @@ void CDasherInterfaceBase::TextAction::NotifyOffset(int iOffset) {
}
-bool CDasherInterfaceBase::hasStopTriggers() {
+bool CDasherInterfaceBase::hasDone() {
return (GetBoolParameter(BP_COPY_ALL_ON_STOP) && SupportsClipboard())
|| (GetBoolParameter(BP_SPEAK_ALL_ON_STOP) && SupportsSpeech());
}
-void CDasherInterfaceBase::Stop() {
- if (GetBoolParameter(BP_DASHER_PAUSED)) return; //already paused, no need to do anything.
- SetBoolParameter(BP_DASHER_PAUSED, true);
-
+void CDasherInterfaceBase::Done() {
ScheduleRedraw();
#ifndef _WIN32_WCE
@@ -516,28 +510,32 @@ void CDasherInterfaceBase::NewFrame(unsigned long iTime, bool bForceRedraw) {
m_DasherScreen->SendMarker(1); //decorations - don't draw any
bBlit = true;
} else {
- bool bChanged(false), bWasPaused(GetBoolParameter(BP_DASHER_PAUSED));
CExpansionPolicy *pol=m_defaultPolicy;
- //1. Move around in the model
+ //1. Schedule any per-frame movement in the model...
if(m_pInputFilter) {
- bChanged = m_pInputFilter->Timer(iTime, m_pDasherView, m_pInput, m_pDasherModel, &pol);
+ m_pInputFilter->Timer(iTime, m_pDasherView, m_pInput, m_pDasherModel, &pol);
}
//2. Render...
- //check: if we were paused before, and the input filter didn't unpause,
- // then nothing can have changed:
- DASHER_ASSERT(!bWasPaused || !GetBoolParameter(BP_DASHER_PAUSED) || !bChanged);
//If we've been told to render another frame via ScheduleRedraw,
// that's the same as passing in true to NewFrame.
if (m_bRedrawScheduled) bForceRedraw=true;
m_bRedrawScheduled=false;
- //If we moved, definitely need to render the nodes. We also make sure
- // to render at least one more frame - think that's a bit of policy
- // just to be on the safe side, and may not be strictly necessary...
- if (bChanged) bForceRedraw=m_bRedrawScheduled=true;
-
+ //Apply any movement that has been scheduled
+ if (m_pDasherModel->NextScheduledStep()) {
+ //yes, we moved...
+ if (!m_bLastMoved) onUnpause(iTime);
+ // ...so definitely need to render the nodes. We also make sure
+ // to render at least one more frame - think that's a bit of policy
+ // just to be on the safe side, and may not be strictly necessary...
+ bForceRedraw=m_bRedrawScheduled=m_bLastMoved=true;
+ } else {
+ //no movement
+ if (m_bLastMoved) bForceRedraw=true;//move into onPause() method if reqd
+ m_bLastMoved=false;
+ }
//2. Render nodes decorations, messages
bBlit = Redraw(iTime, bForceRedraw, *pol);
@@ -555,6 +553,14 @@ void CDasherInterfaceBase::NewFrame(unsigned long iTime, bool bForceRedraw) {
bReentered=false;
}
+void CDasherInterfaceBase::onUnpause(unsigned long lTime) {
+ //TODO When Game+UserLog modules are combined => reduce to just one call here
+ if (m_pGameModule)
+ m_pGameModule->StartWriting(lTime);
+ if (m_pUserLog)
+ m_pUserLog->StartWriting();
+}
+
bool CDasherInterfaceBase::Redraw(unsigned long ulTime, bool bRedrawNodes, CExpansionPolicy &policy) {
DASHER_ASSERT(m_pDasherView);
@@ -742,11 +748,9 @@ void CDasherInterfaceBase::KeyUp(unsigned long iTime, int iId) {
}
}
-void CDasherInterfaceBase::CreateInputFilter()
-{
- SetBoolParameter(BP_DASHER_PAUSED,true); //seems a sensible precaution!
-
+void CDasherInterfaceBase::CreateInputFilter() {
if(m_pInputFilter) {
+ m_pInputFilter->pause();
m_pInputFilter->Deactivate();
m_pInputFilter = NULL;
}
diff --git a/Src/DasherCore/DasherInterfaceBase.h b/Src/DasherCore/DasherInterfaceBase.h
index e7b00ca..0a88681 100644
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@ -198,16 +198,17 @@ public:
/// Methods used to instruct dynamic motion of Dasher to start or stop
/// @{
- /// Stop Dasher - Sets BP_DASHER_PAUSED and executes any on-stop actions
- /// (speech, clipboard - subclasses may override to do more).
- /// (But does nothing if BP_DASHER_PAUSED is not set)
- virtual void Stop();
-
- ///Whether any actions are currently setup to occur when Dasher 'stop's.
- /// Default is to return TRUE iff we support speech and BP_SPEAK_ON_STOP is set,
- /// and/or if we support clipboard and BP_COPY_ALL_ON_STOP is set; subclasses may
- /// override if they have additional on-stop actions.
- virtual bool hasStopTriggers();
+ /// Call when the user has finished writing a piece of text, to execute
+ /// any "on-stop" actions: the default implements speak on stop (if
+ /// BP_SPEAK_ON_STOP is set) and copy-on-stop (if BP_COPY_ALL_ON_STOP) is set;
+ /// subclasses may override to do more.
+ virtual void Done();
+
+ ///Whether the Done() method does anything (and so should be presented
+ /// to the user) - default deals with speak/copy-on-stop, and subclasses
+ /// which override Done() to add additional on-stop actions must/should
+ /// override this to match.
+ virtual bool hasDone();
/// @}
///
@@ -410,6 +411,12 @@ protected:
/// @}
+ ///Called (from NewFrame) if this frame moved and the previous didn't
+ /// (moved = was scheduled in the model, even if no actual change to
+ /// co-ordinates - the latter might occur if e.g. running default filter
+ /// but with the mouse precisely over the crosshair)
+ virtual void onUnpause(unsigned long lTime);
+
CDasherScreen *m_DasherScreen;
CDasherModel * const m_pDasherModel;
@@ -513,11 +520,12 @@ protected:
/// (so may still be NULL even if locked)
CDasherScreen::Label *m_pLockLabel;
- /// @name State variables
- /// Represent the current overall state of the core
- /// @{
+ ///Whether a full redraw (inc of nodes) has been requested externally,
+ /// via ScheduleRedraw, for the next frame
bool m_bRedrawScheduled;
- bool m_bOldVisible;
+
+ ///Whether we moved anywhere in the last call to NewFrame.
+ bool m_bLastMoved;
/// @}
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index 1127e8d..b3ed700 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -250,119 +250,12 @@ int CDasherModel::GetOffset() {
return m_pLastOutput ? m_pLastOutput->offset()+1 : m_Root ? m_Root->offset()+1 : 0;
};
-void CDasherModel::Get_new_root_coords(dasherint X, dasherint Y, dasherint &r1, dasherint &r2, int iSteps, dasherint iMinSize) {
- DASHER_ASSERT(m_Root != NULL);
- // Avoid X == 0, as this corresponds to infinite zoom
- if (X <= 0) X = 1;
-
- // If X is too large we risk overflow errors, so limit it
- dasherint iMaxX = (1 << 29) / iSteps;
- if (X > iMaxX) X = iMaxX;
-
- // Mouse coords X, Y
- // const dasherint Y1 = 0;
- const dasherint Y2(MAX_Y);
-
- // Calculate what the extremes of the viewport will be when the
- // point under the cursor is at the cross-hair. This is where
- // we want to be in iSteps updates
-
- dasherint y1(Y - (Y2 * X) / (2 * ORIGIN_X));
- dasherint y2(Y + (Y2 * X) / (2 * ORIGIN_Y));
- dasherint oy1(y1),oy2(y2); //back these up to use later
- // iSteps is the number of update steps we need to get the point
- // under the cursor over to the cross hair. Calculated in order to
- // keep a constant bit-rate.
-
- DASHER_ASSERT(iSteps > 0);
-
- // Calculate the new values of y1 and y2 required to perform a single update
- // step.
- {
- const dasherint denom = Y2 + (iSteps - 1) * (y2 - y1),
- newy1 = y1 * Y2 / denom,
- newy2 = ((y2 * iSteps - y1 * (iSteps - 1)) * Y2) / denom;
-
- y1 = newy1;
- y2 = newy2;
- }
-
- // Calculate the minimum size of the viewport corresponding to the
- // maximum zoom.
-
- if((y2 - y1) < iMinSize) {
- const dasherint newy1 = y1 * (Y2 - iMinSize) / (Y2 - (y2 - y1)),
- newy2 = newy1 + iMinSize;
-
- y1 = newy1;
- y2 = newy2;
- }
-
- //okay, we now have target bounds for the viewport, after allowing for framerate etc.
- // we now go there in one step...
-
- // new root{min,max} r1,r2, old root{min,max} R1,R2
- const dasherint R1 = m_Rootmin;
- const dasherint R2 = m_Rootmax;
-
- // If |(0,Y2)| = |(y1,y2)|, the "zoom factor" is 1, so we just translate.
- if (Y2 == y2 - y1)
- {
- r1 = R1 - y1;
- r2 = R2 - y1;
- return;
- }
-
- // There is a point C on the y-axis such the ratios (y1-C):(Y1-C) and
- // (y2-C):(Y2-C) are equal - iow that divides the "target" region y1-y2
- // into the same proportions as it divides the screen (0-Y2). I.e., this
- // is the center of expansion - the point on the y-axis which everything
- // moves away from (or towards, if reversing).
-
- //We prefer to compute C from the _original_ (y1,y2) pair, as this is more
- // accurate (and avoids drifting up/down when heading straight along the
- // x-axis in dynamic button modes). However...
- if (((y2-y1) < Y2) ^ ((oy2-oy1) < Y2)) {
- //Sometimes (very occasionally), the calculation of a single-step above
- // can turn a zoom-in into a zoom-out, or vice versa, when the movement
- // is mostly translation. In which case, must compute C consistently with
- // the (scaled, single-step) movement we are going to perform, or else we
- // will end up suddenly going the wrong way along the y-axis (i.e., the
- // sense of translation will be reversed) !
- oy1=y1; oy2=y2;
- }
- const dasherint C = (oy1 * Y2) / (oy1 + Y2 - oy2);
-
- r1 = ((R1 - C) * Y2) / (y2 - y1) + C;
- r2 = ((R2 - C) * Y2) / (y2 - y1) + C;
-}
-
bool CDasherModel::NextScheduledStep()
{
- DASHER_ASSERT (!GetBoolParameter(BP_DASHER_PAUSED) || m_deGotoQueue.size()==0);
if (m_deGotoQueue.size() == 0) return false;
- myint iNewMin, iNewMax;
- iNewMin = m_deGotoQueue.front().iN1;
- iNewMax = m_deGotoQueue.front().iN2;
+ myint newRootmin(m_deGotoQueue.front().iN1), newRootmax(m_deGotoQueue.front().iN2);
m_deGotoQueue.pop_front();
- UpdateBounds(iNewMin, iNewMax);
- if (m_deGotoQueue.size() == 0) SetBoolParameter(BP_DASHER_PAUSED, true);
- return true;
-}
-
-void CDasherModel::OneStepTowards(myint miMousex, myint miMousey, int iSteps, dasherint iMinSize) {
- DASHER_ASSERT(!GetBoolParameter(BP_DASHER_PAUSED));
-
- myint iNewMin, iNewMax;
- // works out next viewpoint
- Get_new_root_coords(miMousex, miMousey, iNewMin, iNewMax, iSteps, iMinSize);
-
- UpdateBounds(iNewMin, iNewMax);
-}
-
-void CDasherModel::UpdateBounds(myint newRootmin, myint newRootmax) {
-
m_dTotalNats += log((newRootmax - newRootmin) / static_cast<double>(m_Rootmax - m_Rootmin));
m_iDisplayOffset = (m_iDisplayOffset * 90) / 100;
@@ -383,7 +276,7 @@ void CDasherModel::UpdateBounds(myint newRootmin, myint newRootmax) {
if (GetBoolParameter(BP_GAME_MODE) && !pChild->GetFlag(NF_GAME)) {
//If the user's strayed that far off the game path,
// having Dasher stop seems reasonable!
- return;
+ return false;
}
//make pChild the root node...
@@ -424,8 +317,103 @@ void CDasherModel::UpdateBounds(myint newRootmin, myint newRootmax) {
if ((newRootmax - newRootmin) > MAX_Y / 4) {
m_Rootmax = newRootmax;
m_Rootmin = newRootmin;
+ return true;
} //else, we just stop - this prevents the user from zooming too far back
- //outside the root node (when we can't generate an older root).
+ //outside the root node (when we can't generate an older root). return true;
+ return false;
+}
+
+void CDasherModel::ScheduleOneStep(myint X, myint Y, int iSteps, dasherint iMinSize) {
+ myint r1, r2;
+ // works out next viewpoint
+
+ DASHER_ASSERT(m_Root != NULL);
+ // Avoid X == 0, as this corresponds to infinite zoom
+ if (X <= 0) X = 1;
+
+ // If X is too large we risk overflow errors, so limit it
+ dasherint iMaxX = (1 << 29) / iSteps;
+ if (X > iMaxX) X = iMaxX;
+
+ // Mouse coords X, Y
+ // const dasherint Y1 = 0;
+ const dasherint Y2(MAX_Y);
+
+ // Calculate what the extremes of the viewport will be when the
+ // point under the cursor is at the cross-hair. This is where
+ // we want to be in iSteps updates
+
+ dasherint y1(Y - (Y2 * X) / (2 * ORIGIN_X));
+ dasherint y2(Y + (Y2 * X) / (2 * ORIGIN_Y));
+ dasherint oy1(y1),oy2(y2); //back these up to use later
+
+ // iSteps is the number of update steps we need to get the point
+ // under the cursor over to the cross hair. Calculated in order to
+ // keep a constant bit-rate.
+ DASHER_ASSERT(iSteps > 0);
+
+ // Calculate the new values of y1 and y2 required to perform a single update
+ // step.
+ {
+ const dasherint denom = Y2 + (iSteps - 1) * (y2 - y1),
+ newy1 = y1 * Y2 / denom,
+ newy2 = ((y2 * iSteps - y1 * (iSteps - 1)) * Y2) / denom;
+
+ y1 = newy1;
+ y2 = newy2;
+ }
+
+ // Calculate the minimum size of the viewport corresponding to the
+ // maximum zoom.
+
+ if((y2 - y1) < iMinSize) {
+ const dasherint newy1 = y1 * (Y2 - iMinSize) / (Y2 - (y2 - y1)),
+ newy2 = newy1 + iMinSize;
+
+ y1 = newy1;
+ y2 = newy2;
+ }
+
+ //okay, we now have target bounds for the viewport, after allowing for framerate etc.
+ // we now go there in one step...
+
+ // new root{min,max} r1,r2, old root{min,max} R1,R2
+ const dasherint R1 = m_Rootmin;
+ const dasherint R2 = m_Rootmax;
+
+ // If |(0,Y2)| = |(y1,y2)|, the "zoom factor" is 1, so we just translate.
+ if (Y2 == y2 - y1) {
+ r1 = R1 - y1;
+ r2 = R2 - y1;
+ } else {
+ // There is a point C on the y-axis such the ratios (y1-C):(Y1-C) and
+ // (y2-C):(Y2-C) are equal - iow that divides the "target" region y1-y2
+ // into the same proportions as it divides the screen (0-Y2). I.e., this
+ // is the center of expansion - the point on the y-axis which everything
+ // moves away from (or towards, if reversing).
+
+ //We prefer to compute C from the _original_ (y1,y2) pair, as this is more
+ // accurate (and avoids drifting up/down when heading straight along the
+ // x-axis in dynamic button modes). However...
+ if (((y2-y1) < Y2) ^ ((oy2-oy1) < Y2)) {
+ //Sometimes (very occasionally), the calculation of a single-step above
+ // can turn a zoom-in into a zoom-out, or vice versa, when the movement
+ // is mostly translation. In which case, must compute C consistently with
+ // the (scaled, single-step) movement we are going to perform, or else we
+ // will end up suddenly going the wrong way along the y-axis (i.e., the
+ // sense of translation will be reversed) !
+ oy1=y1; oy2=y2;
+ }
+ const dasherint C = (oy1 * Y2) / (oy1 + Y2 - oy2);
+
+ r1 = ((R1 - C) * Y2) / (y2 - y1) + C;
+ r2 = ((R2 - C) * Y2) / (y2 - y1) + C;
+ }
+ m_deGotoQueue.clear();
+ SGotoItem item;
+ item.iN1 = r1;
+ item.iN2 = r2;
+ m_deGotoQueue.push_back(item);
}
void CDasherModel::OutputTo(CDasherNode *pNewNode) {
@@ -519,7 +507,7 @@ void CDasherModel::RenderToView(CDasherView *pView, CExpansionPolicy &policy) {
}
-void CDasherModel::ScheduleZoom(long time, dasherint y1, dasherint y2) {
+void CDasherModel::ScheduleZoom(dasherint y1, dasherint y2) {
DASHER_ASSERT(y2>y1);
// Rename for readability.
@@ -563,8 +551,6 @@ void CDasherModel::ScheduleZoom(long time, dasherint y1, dasherint y2) {
sNewItem.iN2 = r2 - (s * (r2 - R2)) / nsteps;
m_deGotoQueue.push_back(sNewItem);
}
- //steps having been scheduled, we're gonna start moving accordingly...
- SetBoolParameter(BP_DASHER_PAUSED, false);
}
void CDasherModel::ClearScheduledSteps() {
diff --git a/Src/DasherCore/DasherModel.h b/Src/DasherCore/DasherModel.h
index 529bab3..ada4a03 100644
--- a/Src/DasherCore/DasherModel.h
+++ b/Src/DasherCore/DasherModel.h
@@ -80,9 +80,19 @@ class Dasher::CDasherModel: private CSettingsUser, public Observable<CDasherNode
/// @{
///
- /// Update the root location with *one step* towards the specified
- /// co-ordinates - used by timer callbacks (for non-button modes)
- void OneStepTowards(myint, myint, int iSteps, dasherint iMinSize);
+ /// Schedules *one step* of movement towards the specified
+ /// co-ordinates - used by timer callbacks for non-button modes.
+ /// Interpolates movement according to iSteps and iMinSize, and calculates
+ /// new co-ordinates for the root node (after *one step*) into m_deGotoQueue
+ /// just as ScheduleZoom. For further information, see Doc/geometry.tex.
+ ///
+ /// \param mousex dasherx co-ordinate towards which to move (e.g. mouse pos)
+ /// \param mousey dashery co-ordinate towards which to move (e.g. mouse pos)
+ /// \param iSteps number of frames which should get us all the way to (mousex,mousey)
+ /// \param iMinSize limit on rate of expansion due to bitrate (as moving
+ /// all the way to the mouse at mousex==1 would be an absurd rate of data entry,
+ /// becoming infinite at mousex==0).
+ void ScheduleOneStep(myint mousex, myint mousey, int iSteps, dasherint iMinSize);
///
/// Apply an offset to the 'target' coordinates - implements the jumps in
@@ -136,19 +146,23 @@ class Dasher::CDasherModel: private CSettingsUser, public Observable<CDasherNode
///
/// Schedule a zoom such that the given range of Dasher coordinates
/// will fill the Y-axis. (used in click mode, button mode etc.)
- /// Note that safety margin, max-zoom, etc., as desired, are the responsibility
- /// of the caller; this method requires only that y2 > y1.
+ /// Note that this will take LP_ZOOM_STEPS frames to complete; safety margin,
+ /// max-zoom, etc., as desired, are the responsibility of the caller
+ /// (this method requires only that y2 > y1).
/// \param y1 Minimum Y-coordinate (will be moved to dasher-y of 0)
/// \param y2 Maximum Y-coordinate (will be moved to dasher-y of 4096)
///
- void ScheduleZoom(long time, dasherint y1, dasherint y2);
+ void ScheduleZoom(dasherint y1, dasherint y2);
+ ///Cancel any steps previously scheduled (most likely by ScheduleZoom)
void ClearScheduledSteps();
///
- /// Update the bounds of the root node for the next step in any
- /// still-in-progress zoom scheduled by ScheduleZoom (does nothing
- /// if no steps remaining / no zoom scheduled).
+ /// Called by DasherInterfaceBase to update the bounds of the root node for
+ /// the next step that has been scheduled (whether a multi-step zoom or a
+ /// single step from ScheduleOneStep).
+ /// \return True if this moves the model (by applying a previously-scheduled
+ /// step); false if there were no scheduled steps (=> the model hasn't moved).
///
bool NextScheduledStep();
@@ -186,10 +200,6 @@ class Dasher::CDasherModel: private CSettingsUser, public Observable<CDasherNode
private:
- /// Common portion of OneStepTowards / NextScheduledStep, taking
- /// bounds for the root node in the next frame.
- void UpdateBounds(myint iNewMin, myint iNewMax);
-
/// Struct representing intermediate stages in the goto queue
///
struct SGotoItem {
@@ -242,18 +252,6 @@ class Dasher::CDasherModel: private CSettingsUser, public Observable<CDasherNode
// Information entered so far in this model
double m_dTotalNats;
- /// Calculate the new co-ordinates for the root node after a single
- /// update step. For further information, see Doc/geometry.tex.
- ///
- /// \param mousex x mouse co-ordinate measured right to left.
- /// \param mousey y mouse co-ordinate measured top to bottom.
- /// \param iNewMin New root min
- /// \param iNewMax New root max
- /// \param iSteps Number of frames which should get us all the way to (mousex,mousey)
- /// \param iMinSize limit on rate of expansion due to bitrate (as we use a poor
- /// approximation to the true interpolation!)
- void Get_new_root_coords(myint mousex, myint mousey, myint &iNewMin, myint &iNewMax, int iSteps, dasherint iMinSize);
-
///
/// Make a child of the root into a new root
///
diff --git a/Src/DasherCore/DefaultFilter.cpp b/Src/DasherCore/DefaultFilter.cpp
index 8707e45..3ba3ab0 100644
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@ -106,15 +106,14 @@ bool CDefaultFilter::DecorateView(CDasherView *pView, CDasherInput *pInput) {
return bDidSomething;
}
-bool CDefaultFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
+void CDefaultFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
if (!(m_bGotMouseCoords = pInput->GetDasherCoords(m_iLastX, m_iLastY, pView))) {
- m_pInterface->Stop(); //does nothing if already paused
- return false;
+ stop();
+ return;
};
//Got coordinates
ApplyTransform(m_iLastX, m_iLastY, pView);
- bool bDidSomething(false);
- if (!GetBoolParameter(BP_DASHER_PAUSED))
+ if (!isPaused())
{
if(GetBoolParameter(BP_STOP_OUTSIDE)) {
myint iDasherMinX;
@@ -124,8 +123,8 @@ bool CDefaultFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput
pView->VisibleRegion(iDasherMinX, iDasherMinY, iDasherMaxX, iDasherMaxY);
if((m_iLastX > iDasherMaxX) || (m_iLastX < iDasherMinX) || (m_iLastY > iDasherMaxY) || (m_iLastY < iDasherMinY)) {
- m_pInterface->Stop();
- return false;
+ stop();
+ return;
}
}
@@ -133,7 +132,6 @@ bool CDefaultFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput
if (m_bTurbo) dSpeedMul*=1.75;
OneStepTowards(m_pDasherModel, m_iLastX,m_iLastY, Time, dSpeedMul);
- bDidSomething = true;
if (GetLongParameter(LP_BOOSTFACTOR)==100 && dSpeedMul==1.0)
m_pAutoSpeedControl->SpeedControl(m_iLastX, m_iLastY, pView);
@@ -141,45 +139,45 @@ bool CDefaultFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput
if(m_pStartHandler)
m_pStartHandler->Timer(Time, m_iLastX, m_iLastY, pView);
+}
- return bDidSomething;
+void CDefaultFilter::run(unsigned long iTime) {
+ CDynamicFilter::run(iTime);
+ if (m_pStartHandler) m_pStartHandler->onRun(iTime);
+}
+
+void CDefaultFilter::pause() {
+ CDynamicFilter::pause();
+ if (m_pStartHandler) m_pStartHandler->onPause();
}
void CDefaultFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {
- switch(iId) {
- case 0: // Start on space
- // FIXME - wrap this in a 'start/stop' method (and use for buttons as well as keys)
- if(GetBoolParameter(BP_START_SPACE)) {
- if(GetBoolParameter(BP_DASHER_PAUSED))
- Unpause(iTime);
- else
- m_pInterface->Stop();
- }
- break;
- case 100: // Start on mouse
- if(GetBoolParameter(BP_START_MOUSE)) {
- if(GetBoolParameter(BP_DASHER_PAUSED))
- Unpause(iTime);
- else
- m_pInterface->Stop();
- }
- break;
- case 101: case 102: //Other mouse buttons, if platforms support?
- case 1: //button 1
- if (GetBoolParameter(BP_TURBO_MODE)) {
- m_bTurbo = true;
- }
- default:
- break;
+ if ((iId==0 && GetBoolParameter(BP_START_SPACE))
+ || (iId==100 && GetBoolParameter(BP_START_MOUSE))) {
+ if(isPaused())
+ run(iTime);
+ else
+ stop();
+ }
+ else if (iId==101 || iId==102 || iId==1) {
+ //Other mouse buttons, if platforms support; or button 1
+ if (GetBoolParameter(BP_TURBO_MODE))
+ m_bTurbo = true;
}
}
void CDefaultFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
- if (iId==101 || iId==1)
+ if (iId==101 || iId==102 || iId==1)
m_bTurbo=false;
}
+void CDefaultFilter::stop() {
+ if (isPaused()) return;
+ pause();
+ m_pInterface->Done();
+}
+
void CDefaultFilter::HandleEvent(int iParameter) {
switch (iParameter) {
case BP_CIRCLE_START:
@@ -264,7 +262,7 @@ void CDefaultFilter::ApplyOffset(myint &iDasherX, myint &iDasherY) {
iDasherY += 10 * GetLongParameter(LP_TARGET_OFFSET);
- if(GetBoolParameter(BP_AUTOCALIBRATE) && !GetBoolParameter(BP_DASHER_PAUSED)) {
+ if(GetBoolParameter(BP_AUTOCALIBRATE) && !isPaused()) {
// Auto-update the offset
m_iSum += CDasherModel::ORIGIN_Y - iDasherY; // Distance above crosshair
diff --git a/Src/DasherCore/DefaultFilter.h b/Src/DasherCore/DefaultFilter.h
index f42c90e..6eb7f75 100644
--- a/Src/DasherCore/DefaultFilter.h
+++ b/Src/DasherCore/DefaultFilter.h
@@ -17,14 +17,18 @@ class CDefaultFilter : public CDynamicFilter, public CSettingsObserver {
virtual void HandleEvent(int iParameter);
virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
- virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
+ virtual void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
virtual void Activate();
virtual void Deactivate();
bool GetSettings(SModuleSettings **, int *);
+ void pause();
+ //pauses, and calls the interface's Done() method
+ void stop();
protected:
void CreateStartHandler();
+ void run(unsigned long iTime);
virtual CStartHandler *MakeStartHandler();
virtual void ApplyTransform(myint &iDasherX, myint &iDasherY, CDasherView *pView);
void ApplyOffset(myint &iDasherX, myint &iDasherY);
diff --git a/Src/DasherCore/DynamicButtons.cpp b/Src/DasherCore/DynamicButtons.cpp
index f241b1c..a337021 100644
--- a/Src/DasherCore/DynamicButtons.cpp
+++ b/Src/DasherCore/DynamicButtons.cpp
@@ -24,32 +24,31 @@
using namespace Dasher;
CDynamicButtons::CDynamicButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
- : CDynamicFilter(pCreator, pInterface, pFramerate, iID, szName), CSettingsObserver(pCreator), m_pModel(NULL) {
+ : CDynamicFilter(pCreator, pInterface, pFramerate, iID, szName), m_pModel(NULL) {
m_bDecorationChanged = true;
m_bKeyDown = false;
pause();
}
-bool CDynamicButtons::Timer(unsigned long iTime, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
+void CDynamicButtons::Timer(unsigned long iTime, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
{
if(m_bKeyDown && !m_bKeyHandled && ((iTime - m_iKeyDownTime) > GetLongParameter(LP_HOLD_TIME))) {
ButtonEvent(iTime, m_iHeldId, 1, m_pDasherModel);
m_bKeyHandled = true;
//return true; //ACL although that's what old DynamicButtons did, surely we should progress normally?
}
- if (isPaused()) return false;
+ if (isPaused()) return;
if (isReversing()) {
OneStepTowards(m_pDasherModel, 41943,2048, iTime, SlowStartSpeedMul(iTime));
- return true;
- }
- //moving forwards. Check auto speed control...
- if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < iTime)
- {
- if (m_uSpeedControlTime > 0) //has actually been set?
- SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) * (1.0 + GetLongParameter(LP_DYNAMIC_SPEED_INC)/100.0));
- m_uSpeedControlTime = iTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
+ } else {
+ //moving forwards. Check auto speed control...
+ if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < iTime) {
+ if (m_uSpeedControlTime > 0) //has actually been set?
+ SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) * (1.0 + GetLongParameter(LP_DYNAMIC_SPEED_INC)/100.0));
+ m_uSpeedControlTime = iTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
+ }
+ TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
}
- return TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
}
void CDynamicButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
@@ -87,15 +86,13 @@ void CDynamicButtons::ButtonEvent(unsigned long iTime, int iButton, int iType, C
//Any button causes a restart
if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
pUserLog->KeyDown(iButton, iType, 1);
- run();
- Unpause(iTime);
+ run(iTime);
} else if (isReversing()) {
//Any button pauses
if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
pUserLog->KeyDown(iButton, iType, 2);
-
- m_pInterface->Stop();
- //change in BP_DASHER_PAUSED calls pause().
+ m_pInterface->Done();
+ pause();
} else {
//running; examine event/button-press type
switch(iType) {
@@ -104,14 +101,15 @@ void CDynamicButtons::ButtonEvent(unsigned long iTime, int iButton, int iType, C
//dedicated pause button
if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
pUserLog->KeyDown(iButton, iType, 2);
- m_pInterface->Stop();
+ m_pInterface->Done();
+ pause();
break;
}
else if(iButton == 1) {
//dedicated reverse button
if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
pUserLog->KeyDown(iButton, iType, 6);
- reverse();
+ reverse(iTime);
break;
}
//else - any non-special button - fall through
@@ -121,24 +119,14 @@ void CDynamicButtons::ButtonEvent(unsigned long iTime, int iButton, int iType, C
}
}
-void CDynamicButtons::HandleEvent(int iParameter) {
- if (iParameter==BP_DASHER_PAUSED) {
- if (GetBoolParameter(BP_DASHER_PAUSED))
- pause(); //make sure we're in sync
- else if (m_pInterface->GetActiveInputMethod()==this && isPaused())
- //if we're active: can't unpause, as we don't know which way to go, run or reverse?
- SetBoolParameter(BP_DASHER_PAUSED, true);
- }
-}
-
void CDynamicButtons::pause() {
- m_iState = 0;
+ CDynamicFilter::pause();
if (m_pModel) m_pModel->AbortOffset();
}
-void CDynamicButtons::reverse()
-{
- m_iState = 1;
+void CDynamicButtons::reverse(unsigned long iTime) {
+ m_bForwards=false;
+ CDynamicFilter::run(iTime);
if (GetBoolParameter(BP_AUTO_SPEEDCONTROL)) {
//treat reversing as a sign of distress --> slow down!
SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) *
@@ -146,11 +134,12 @@ void CDynamicButtons::reverse()
}
}
-void CDynamicButtons::run()
-{
- if (m_iState<2) //wasn't running previously
- m_uSpeedControlTime = 0; //will be set in Timer()
- m_iState = 2;
+void CDynamicButtons::run(unsigned long iTime) {
+ m_bForwards=true;
+ if (!isPaused()) return;
+ //wasn't running previously
+ CDynamicFilter::run(iTime);
+ m_uSpeedControlTime = 0; //will be set in Timer()
}
void CDynamicButtons::ApplyOffset(CDasherModel *pModel, int iOffset) {
diff --git a/Src/DasherCore/DynamicButtons.h b/Src/DasherCore/DynamicButtons.h
index 3b76a1e..f308324 100644
--- a/Src/DasherCore/DynamicButtons.h
+++ b/Src/DasherCore/DynamicButtons.h
@@ -27,18 +27,16 @@
/// @{
namespace Dasher {
///filter with three states: paused, reversing, running. Hold any button down to reverse.
-class CDynamicButtons : public CDynamicFilter, public CSettingsObserver {
+class CDynamicButtons : public CDynamicFilter {
public:
CDynamicButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName);
///when reversing, backs off; when paused, does nothing; when running, delegates to TimerImpl
- virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ virtual void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
- //respond to changes to BP_DASHER_PAUSED to keep m_iState in sync
- virtual void HandleEvent(int iParameter);
protected:
///Called when a key event is detected - could be a single press (a la KeyDown/KeyUp),
/// but is also called with explicit indication of "long" or other types of press,
@@ -58,20 +56,19 @@ class CDynamicButtons : public CDynamicFilter, public CSettingsObserver {
bool m_bKeyDown;
bool m_bKeyHandled;
bool m_bDecorationChanged;
- bool isPaused() {return m_iState == 0;}
- bool isReversing() {return m_iState == 1;}
- bool isRunning() {return m_iState==2;}
+ bool isReversing() {return !isPaused() && !m_bForwards;}
+ bool isRunning() {return !isPaused() && m_bForwards;}
virtual void pause();
- virtual void reverse();
- virtual void run();
+ virtual void reverse(unsigned long iTime);
+ virtual void run(unsigned long iTime);
- virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) = 0;
+ virtual void TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) = 0;
///Subclasses should all this (rather than pModel->Offset()) to offset the model
/// (it also stores the model, to abort the offset upon pause if necessary)
void ApplyOffset(CDasherModel *pModel, int iOffset);
private:
- int m_iState; // 0 = paused, 1 = reversing, >=2 = running (extensible by subclasses)
+ bool m_bForwards;
int m_iHeldId;
unsigned long m_iKeyDownTime;
unsigned long m_uSpeedControlTime;
diff --git a/Src/DasherCore/DynamicFilter.cpp b/Src/DasherCore/DynamicFilter.cpp
index 026f17c..aa73f10 100644
--- a/Src/DasherCore/DynamicFilter.cpp
+++ b/Src/DasherCore/DynamicFilter.cpp
@@ -23,7 +23,8 @@
using namespace Dasher;
-CDynamicFilter::CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName) : CInputFilter(pInterface, iID, szName), CSettingsUser(pCreator), m_pFramerate(pFramerate) {
+CDynamicFilter::CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
+: CInputFilter(pInterface, iID, szName), CSettingsUser(pCreator), m_bPaused(true), m_pFramerate(pFramerate) {
}
bool CDynamicFilter::OneStepTowards(CDasherModel *pModel, myint y1, myint y2, unsigned long iTime, double dSpeedMul) {
@@ -34,7 +35,7 @@ bool CDynamicFilter::OneStepTowards(CDasherModel *pModel, myint y1, myint y2, un
// Adjust for slow start etc. TODO: can we fix to use integer math (or at least no pow?)
if (dSpeedMul!=1.0) dRXMax=pow(dRXMax, dSpeedMul);
- pModel->OneStepTowards(y1, y2, static_cast<int>(m_pFramerate->Steps() / dSpeedMul), static_cast<myint>(CDasherModel::MAX_Y/dRXMax));
+ pModel->ScheduleOneStep(y1, y2, static_cast<int>(m_pFramerate->Steps() / dSpeedMul), static_cast<myint>(CDasherModel::MAX_Y/dRXMax));
return true;
}
@@ -47,10 +48,10 @@ double CDynamicFilter::SlowStartSpeedMul(unsigned long iTime) {
return 1.0;
}
-void CDynamicFilter::Unpause(unsigned long Time) {
- if (!GetBoolParameter(BP_DASHER_PAUSED)) return; //already running, no need to / can't really do anything
+void CDynamicFilter::run(unsigned long Time) {
+ if (!isPaused()) return; //already running, no need to / can't really do anything
- SetBoolParameter(BP_DASHER_PAUSED, false);
+ m_bPaused = false;
m_pFramerate->Reset_framerate(Time);
m_iStartTime = Time;
diff --git a/Src/DasherCore/DynamicFilter.h b/Src/DasherCore/DynamicFilter.h
index 33791e9..a5c2119 100644
--- a/Src/DasherCore/DynamicFilter.h
+++ b/Src/DasherCore/DynamicFilter.h
@@ -38,20 +38,26 @@ class CDynamicFilter : public CInputFilter, public CSettingsUser {
CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName);
virtual bool supportsPause() {return true;}
-
+
+ void pause() {m_bPaused = true;}
+
protected:
bool OneStepTowards(CDasherModel *pModel, myint y1, myint y2, unsigned long iTime, double dSpeedMul);
double SlowStartSpeedMul(unsigned long iTime);
- /// Starts moving. Clears BP_DASHER_PAUSED.
- /// (But does nothing if BP_DASHER_PAUSED is currently set).
+ ///Starts moving, i.e. just records that we are no longer paused,
+ /// for the next call to Timer. Protected, to prevent external calls
+ /// so subclasses have control over all calls, as a call to run() may not be
+ /// appropriate without performing other setup first.
/// \param Time Time in ms, used to keep a constant frame rate and
/// initialize slow start.
- void Unpause(unsigned long iTime);
+ virtual void run(unsigned long iTime);
+ bool isPaused() {return m_bPaused;}
private:
CFrameRate *m_pFramerate;
//Time at which Unpause() was called, used for Slow Start.
unsigned long m_iStartTime;
+ bool m_bPaused;
};
}
#endif
diff --git a/Src/DasherCore/GameModule.cpp b/Src/DasherCore/GameModule.cpp
index 053ff12..7c8071a 100644
--- a/Src/DasherCore/GameModule.cpp
+++ b/Src/DasherCore/GameModule.cpp
@@ -93,13 +93,18 @@ void CGameModule::SetWordGenerator(const CAlphInfo *pAlph, CWordGeneratorBase *p
}
}
+void CGameModule::StartWriting(unsigned long lTime) {
+ if (!m_ulSentenceStartTime) {
+ m_ulSentenceStartTime = lTime;
+ m_dSentenceStartNats = numeric_limits<double>::max();
+ }
+}
+
void CGameModule::DecorateView(unsigned long lTime, CDasherView *pView, CDasherModel *pModel) {
- if (GetBoolParameter(BP_DASHER_PAUSED) && !m_ulSentenceStartTime) {
- m_ulSentenceStartTime = lTime;
+ if (m_dSentenceStartNats == numeric_limits<double>::max())
m_dSentenceStartNats = pModel->GetNats();
- }
-
+
m_vTargetY.push_back((m_y1+m_y2)/2);
//draw a line along the y axis
@@ -133,7 +138,7 @@ void CGameModule::DecorateView(unsigned long lTime, CDasherView *pView, CDasherM
if(m_iLastSym == m_vTargetSymbols.size() - 1) {
m_pInterface->Message(ComputeStats(m_vTargetY),true);
m_vTargetY.clear(); //could preserve if samples not excessive...but is it meaningful (given restart)?
- SetBoolParameter(BP_DASHER_PAUSED, true);
+ m_pInterface->GetActiveInputMethod()->pause();
m_ulTotalTime += (lTime - m_ulSentenceStartTime);
m_dTotalNats += (pModel->GetNats() - m_dSentenceStartNats);
m_uiTotalSyms += m_vTargetSymbols.size();
diff --git a/Src/DasherCore/GameModule.h b/Src/DasherCore/GameModule.h
index 3fa13c2..ecdcac0 100644
--- a/Src/DasherCore/GameModule.h
+++ b/Src/DasherCore/GameModule.h
@@ -47,6 +47,8 @@ class CGameModule : protected CSettingsUser, protected TransientObserver<const C
~CGameModule();
+ void StartWriting(unsigned long lTime);
+
/**
* Draws Game Mode specific visuals to the screen.
* \param pView The Dasher View to be modified
diff --git a/Src/DasherCore/InputFilter.h b/Src/DasherCore/InputFilter.h
index 38ceadc..33f60a1 100644
--- a/Src/DasherCore/InputFilter.h
+++ b/Src/DasherCore/InputFilter.h
@@ -19,13 +19,34 @@ class CInputFilter : public CDasherModule {
: CDasherModule(iID, InputMethod, szName), m_pInterface(pInterface) {
};
+ ///Called after nodes have been rendered, to draw any decorations on the view.
+ ///\return True if the decorations were (potentially) different from the last
+ /// frame; false if the decorations drawn are definitely the same as those
+ /// drawn in the previous frame.
virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput) { return false; };
virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {}
virtual void KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {}
- virtual bool Timer(unsigned long Time, CDasherView *m_pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)=0;// { return false; };
+ ///Called for each frame, before rendering. Filter thus has the opportunity
+ /// to schedule one or more steps with the model (or cancel scheduled steps!);
+ /// after calling, model will move to the next step that has been scheduled -
+ /// whether by Timer(), or elsewhere. Thus, a filter in which movement is
+ /// continuous while the filter is in some unpaused state, can ScheduleOneStep
+ /// in each call to Timer; alternatively, a filter responding to clicks, can
+ /// schedule a whole bunch of steps when a click occurs, and then Timer need
+ /// do nothing (as the model will run through those steps, one per frame).
+ ///\param pView useful for co-ordinate conversions; however, no drawing should
+ /// be performed here (that should be done in DecorateView).
+ virtual void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {};
+
+ ///Called to tell the Filter to halt any movement that may be in progress:
+ /// e.g. if some UI action has occurred taking focus/control away from the
+ /// Dasher canvas. Thus, filters should (a) ensure they do not schedule any
+ /// movement in subsequent Timer() calls; and (b) also ensure the model is
+ /// cleared of any steps already scheduled with it.
+ virtual void pause() = 0;
virtual void Activate() {};
virtual void Deactivate() {};
@@ -33,12 +54,35 @@ class CInputFilter : public CDasherModule {
virtual bool GetMinWidth(int &iMinWidth) {
return false;
}
-
+
+ ///Used by Control Mode to determine whether to display a Pause node (perhaps
+ /// in addition to a Stop/Done). If general, this is desirable if the filter
+ /// will continuously enter bits in the absence of user input, and thus there
+ /// should be the option to tell the filter to stop doing this (without the
+ /// user necessarily having finished the phrase); no if the filter will not
+ /// enter bits without the user actively pushing buttons / performing input.
virtual bool supportsPause() {return false;}
protected:
CDasherInterfaceBase * const m_pInterface;
};
+
+ ///Simple class, basis for filters using ScheduleZoom rather than
+ /// ScheduleOneStep, providing a ScheduleZoom method wrapping the
+ /// DasherModel, such that pause() cancels any such zoom in progress.
+ class CStaticFilter : public CInputFilter {
+ public:
+ CStaticFilter(CDasherInterfaceBase *pIntf, ModuleID_t iId, const char *szName)
+ : CInputFilter(pIntf, iId, szName), m_pModel(NULL) {
+ }
+ void pause() {if (m_pModel) m_pModel->ClearScheduledSteps();}
+ protected:
+ void ScheduleZoom(CDasherModel *pModel, myint x, myint y) {
+ (m_pModel = pModel)->ScheduleZoom(x,y);
+ }
+ private:
+ CDasherModel *m_pModel;
+ };
}
/// @}
diff --git a/Src/DasherCore/OneButtonDynamicFilter.cpp b/Src/DasherCore/OneButtonDynamicFilter.cpp
index dec1b31..cb813fd 100644
--- a/Src/DasherCore/OneButtonDynamicFilter.cpp
+++ b/Src/DasherCore/OneButtonDynamicFilter.cpp
@@ -108,15 +108,14 @@ void COneButtonDynamicFilter::KeyUp(unsigned long Time, int iId, CDasherView *pD
CButtonMultiPress::KeyUp(Time, iId, pDasherView, pInput, pModel);
}
-bool COneButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
+void COneButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
OneStepTowards(m_pDasherModel, m_iTargetX[m_iTarget], m_iTargetY[m_iTarget], Time, SlowStartSpeedMul(Time));
- return true;
}
void COneButtonDynamicFilter::ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel) {
if (iType != 0) {
//double/long push
- reverse();
+ reverse(iTime);
return;
}
diff --git a/Src/DasherCore/OneButtonDynamicFilter.h b/Src/DasherCore/OneButtonDynamicFilter.h
index 467f921..858c648 100644
--- a/Src/DasherCore/OneButtonDynamicFilter.h
+++ b/Src/DasherCore/OneButtonDynamicFilter.h
@@ -41,7 +41,7 @@ class COneButtonDynamicFilter : public CButtonMultiPress {
private:
unsigned int maxClickCount() {return 2;} //double-click to reverse
- virtual bool TimerImpl(unsigned long Time, CDasherView *pView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ virtual void TimerImpl(unsigned long Time, CDasherView *pView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
virtual void ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel);
int m_iTarget;
diff --git a/Src/DasherCore/OneButtonFilter.cpp b/Src/DasherCore/OneButtonFilter.cpp
index 6ebd8c8..c09291b 100644
--- a/Src/DasherCore/OneButtonFilter.cpp
+++ b/Src/DasherCore/OneButtonFilter.cpp
@@ -14,16 +14,13 @@ static SModuleSettings sSettings[] = {
};
COneButtonFilter::COneButtonFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface)
- : CInputFilter(pInterface, 9, "Static One Button Mode"), CSettingsUser(pCreator) {
+ : CStaticFilter(pInterface, 9, "Static One Button Mode"), CSettingsUser(pCreator) {
bStarted = 0;
iLocation = 0;
}
-COneButtonFilter::~COneButtonFilter() {
-}
-
bool COneButtonFilter::DecorateView(CDasherView *pView, CDasherInput *pInput) {
CDasherScreen *pScreen(pView->Screen());
@@ -52,7 +49,7 @@ bool COneButtonFilter::DecorateView(CDasherView *pView, CDasherInput *pInput) {
return true;
}
-bool COneButtonFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
+void COneButtonFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
if(bStarted) {
iLocation = (Time - iStartTime) * 4096 / GetLongParameter(LP_STATIC1B_TIME);
@@ -66,8 +63,6 @@ bool COneButtonFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInpu
iLocation = 8192-iLocation;
}
}
-
- return m_pDasherModel->NextScheduledStep();
}
void COneButtonFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
@@ -75,12 +70,12 @@ void COneButtonFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView,
if (iLocation == 0) {
//back up by one zoom step.
const myint x(GetLongParameter(LP_STATIC1B_ZOOM)*2048);
- pModel->ScheduleZoom(iTime, 2048-x, 2048+x);
+ ScheduleZoom(pModel, 2048-x, 2048+x);
} else {
iLocation -= (GetLongParameter(LP_DYNAMIC_BUTTON_LAG)*4096) / GetLongParameter(LP_STATIC1B_TIME);
if (iLocation>4096) iLocation =8192-iLocation;
const myint x(2048/GetLongParameter(LP_STATIC1B_ZOOM));
- pModel->ScheduleZoom(iTime, 2048-x, 2048+x);
+ ScheduleZoom(pModel, 2048-x, 2048+x);
}
bStarted = false;
} else {
diff --git a/Src/DasherCore/OneButtonFilter.h b/Src/DasherCore/OneButtonFilter.h
index 79dccc6..347e12b 100644
--- a/Src/DasherCore/OneButtonFilter.h
+++ b/Src/DasherCore/OneButtonFilter.h
@@ -6,13 +6,12 @@
namespace Dasher {
/// \ingroup InputFilter
/// @{
-class COneButtonFilter : public CInputFilter, private CSettingsUser {
+class COneButtonFilter : public CStaticFilter, private CSettingsUser {
public:
COneButtonFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface);
- ~COneButtonFilter();
virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
- virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ virtual void Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
bool GetSettings(SModuleSettings **pSettings, int *iCount);
private:
diff --git a/Src/DasherCore/OneDimensionalFilter.cpp b/Src/DasherCore/OneDimensionalFilter.cpp
index 464363c..90ebe52 100644
--- a/Src/DasherCore/OneDimensionalFilter.cpp
+++ b/Src/DasherCore/OneDimensionalFilter.cpp
@@ -80,24 +80,25 @@ CStartHandler *COneDimensionalFilter::MakeStartHandler() {
public:
C1DCircleStartHandler(COneDimensionalFilter *f) : CCircleStartHandler(f) {
}
- void ComputeScreenLoc(CDasherView *pView) {
- if (m_iScreenRadius!=-1) return;
- CCircleStartHandler::ComputeScreenLoc(pView);
- if (GetBoolParameter(BP_DASHER_PAUSED)) {
- //put start circle at center of 1D transform, rather than center of screen
- // (leave m_iScreenRadius, in pixels, as computed by above)
+ CDasherScreen::point CircleCenter(CDasherView *pView) {
+ if (m_iScreenRadius==-1) {//if we need to recompute
+ CCircleStartHandler::CircleCenter(pView); //that does the radius
const myint rad(GetLongParameter(LP_CIRCLE_PERCENT) * CDasherModel::ORIGIN_Y / 100); //~~rad/2 in dasher-coords
- pView->Dasher2Screen(CDasherModel::ORIGIN_X-static_cast<COneDimensionalFilter*>(m_pFilter)->forwardmax+rad, CDasherModel::ORIGIN_Y,m_screenCircleCenter.x, m_screenCircleCenter.y);
- }
- }
- void HandleEvent(int iParameter) {
- if (iParameter==BP_DASHER_PAUSED) {
- //circle needs to move for pause/unpause; setting radius to -1 causes
- // next call to DecorateView or Timer to re-call ComputeScreenLoc.
- m_iScreenRadius=-1;
+ m_pView->Dasher2Screen(CDasherModel::ORIGIN_X-static_cast<COneDimensionalFilter*>(m_pFilter)->forwardmax+rad, CDasherModel::ORIGIN_Y,m_fwdCenter.x, m_fwdCenter.y);
}
- CCircleStartHandler::HandleEvent(iParameter);
+ if (!static_cast<COneDimensionalFilter*>(m_pFilter)->isPaused()) return CCircleStartHandler::CircleCenter(pView);
+ //paused. put start circle at center of 1D transform, rather than center of screen
+ // but keep the same m_iScreenRadius, in pixels - so recompute if necessary:
+ return m_fwdCenter;
+ }
+ void onPause() {
+ //circle needs to move for pause/unpause; setting radius to -1 causes
+ // next call to DecorateView or Timer to re-call ComputeScreenLoc.
+ m_iScreenRadius=-1;
+ CCircleStartHandler::onPause();
}
+ private:
+ CDasherScreen::point m_fwdCenter;
};
return new C1DCircleStartHandler(this);
}
diff --git a/Src/DasherCore/Parameters.cpp b/Src/DasherCore/Parameters.cpp
index 9be39c1..3a4fc78 100644
--- a/Src/DasherCore/Parameters.cpp
+++ b/Src/DasherCore/Parameters.cpp
@@ -24,7 +24,6 @@ const bp_table boolparamtable[] = {
{BP_TURBO_MODE, "TurboMode", PERS, true, "Boost speed when holding key1 or right mouse button"},
{BP_AUTOCALIBRATE, "Autocalibrate", PERS, false, "Automatically learn TargetOffset e.g. gazetracking"},
{BP_REMAP_XTREME, "RemapXtreme", PERS, false, "Pointer at extreme Y translates more and zooms less"},
- {BP_DASHER_PAUSED, "DasherPaused", !PERS, true, "Dasher Paused"},
{BP_GAME_MODE, "GameMode", !PERS, false, "Dasher Game Mode"},
{BP_LM_DICTIONARY, "Dictionary", PERS, true, "Whether the word-based language model uses a dictionary"},
{BP_LM_LETTER_EXCLUSION, "LetterExclusion", PERS, true, "Whether to do letter exclusion in the word-based model"},
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index 0a171bd..89b5ed7 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -33,7 +33,7 @@ enum {
BP_START_SPACE, BP_STOP_IDLE, BP_CONTROL_MODE,
BP_COLOUR_MODE, BP_MOUSEPOS_MODE,
BP_PALETTE_CHANGE, BP_TURBO_MODE,
- BP_AUTOCALIBRATE, BP_REMAP_XTREME, BP_DASHER_PAUSED,
+ BP_AUTOCALIBRATE, BP_REMAP_XTREME,
BP_GAME_MODE, BP_LM_DICTIONARY,
BP_LM_LETTER_EXCLUSION, BP_AUTO_SPEEDCONTROL,
BP_LM_ADAPTIVE, BP_SOCKET_INPUT_ENABLE, BP_SOCKET_DEBUG,
diff --git a/Src/DasherCore/StartHandler.h b/Src/DasherCore/StartHandler.h
index 14f71e2..caa8366 100644
--- a/Src/DasherCore/StartHandler.h
+++ b/Src/DasherCore/StartHandler.h
@@ -17,7 +17,8 @@ public:
virtual bool DecorateView(CDasherView *pView) = 0;
virtual void Timer(unsigned long iTime, dasherint iX, dasherint iY, CDasherView *pView) = 0;
-
+ virtual void onRun(unsigned long iTime) {}
+ virtual void onPause() {}
protected:
CDefaultFilter * const m_pFilter;
};
diff --git a/Src/DasherCore/StylusFilter.cpp b/Src/DasherCore/StylusFilter.cpp
index 5f043c0..a8adda9 100644
--- a/Src/DasherCore/StylusFilter.cpp
+++ b/Src/DasherCore/StylusFilter.cpp
@@ -7,38 +7,32 @@
using namespace Dasher;
CStylusFilter::CStylusFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
- : CDefaultFilter(pCreator, pInterface, pFramerate, iID, szName) {
-}
-
-bool CStylusFilter::Timer(unsigned long iTime, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol)
-{
- //First, try to continue any zoom scheduled by a previous click...
- if (pModel->NextScheduledStep()) {
- //note that this skips the rest of CDefaultFilter::Timer;
- //however, given we're paused, this is only the Start Handler,
- //which we're not using anyway.
- return true;
- }
- return CDefaultFilter::Timer(iTime, pView, pInput, pModel, pol);
+ : CDefaultFilter(pCreator, pInterface, pFramerate, iID, szName), m_pModel(NULL) {
}
void CStylusFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
if(iId == 100) {
- pModel->ClearScheduledSteps();
- Unpause(iTime);
+ //pModel->ClearScheduledSteps(); //no need - each one step scheduled by superclass, will do this
+ run(iTime);
m_iKeyDownTime = iTime;
} else
CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel);
}
+void CStylusFilter::pause() {
+ CDefaultFilter::pause();
+ if (m_pModel) m_pModel->ClearScheduledSteps();
+}
+
void CStylusFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
if(iId == 100) {
+ pause(); //stops superclass from scheduling any more one-step movements
if (iTime - m_iKeyDownTime < GetLongParameter(LP_TAP_TIME)) {
pInput->GetDasherCoords(m_iLastX, m_iLastY, pView);
ApplyClickTransform(m_iLastX, m_iLastY, pView);
- pModel->ScheduleZoom(iTime, m_iLastY-m_iLastX, m_iLastY+m_iLastX);
+ (m_pModel=pModel)->ScheduleZoom(m_iLastY-m_iLastX, m_iLastY+m_iLastX);
} else {
- m_pInterface->Stop();
+ m_pInterface->Done();
}
} else
CDefaultFilter::KeyUp(iTime, iId, pView, pInput, pModel);
diff --git a/Src/DasherCore/StylusFilter.h b/Src/DasherCore/StylusFilter.h
index 8ee2222..7e6e4dd 100644
--- a/Src/DasherCore/StylusFilter.h
+++ b/Src/DasherCore/StylusFilter.h
@@ -13,7 +13,11 @@ class CStylusFilter : public CDefaultFilter {
///Override DefaultFilter (which supports pause), as we don't
/// - motion requires continually holding stylus against screen
virtual bool supportsPause() {return false;}
- virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
+
+ //no Timer method required: DefaultFilter does fine when we're moving,
+ // and will ignore any zoom scheduled by a click.
+
+ void pause();
virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
protected:
@@ -24,6 +28,7 @@ class CStylusFilter : public CDefaultFilter {
virtual CStartHandler *MakeStartHandler();
private:
unsigned long m_iKeyDownTime;
+ CDasherModel *m_pModel;
};
}
/// @}
diff --git a/Src/DasherCore/TwoBoxStartHandler.cpp b/Src/DasherCore/TwoBoxStartHandler.cpp
index a5305a6..0f52f2d 100644
--- a/Src/DasherCore/TwoBoxStartHandler.cpp
+++ b/Src/DasherCore/TwoBoxStartHandler.cpp
@@ -5,11 +5,11 @@
using namespace Dasher;
CTwoBoxStartHandler::CTwoBoxStartHandler(CDefaultFilter *pCreator)
-: CStartHandler(pCreator), CSettingsUserObserver(pCreator), m_bFirstBox(true), m_iBoxEntered(std::numeric_limits<long>::max()) {
+: CStartHandler(pCreator), CSettingsUser(pCreator), m_bFirstBox(true), m_iBoxEntered(std::numeric_limits<long>::max()) {
}
bool CTwoBoxStartHandler::DecorateView(CDasherView *pView) {
- if (!GetBoolParameter(BP_DASHER_PAUSED)) return false;
+ if (!m_pFilter->isPaused()) return false;
int iHeight = pView->Screen()->GetHeight();
int iWidth = pView->Screen()->GetWidth();
@@ -27,7 +27,7 @@ bool CTwoBoxStartHandler::DecorateView(CDasherView *pView) {
}
void CTwoBoxStartHandler::Timer(unsigned long iTime, dasherint iDasherX, dasherint iDasherY, CDasherView *pView) {
- if (!GetBoolParameter(BP_DASHER_PAUSED)) return;
+ if (!m_pFilter->isPaused()) return;
int iBoxMin, iBoxMax;
if(m_bFirstBox) {
@@ -52,7 +52,7 @@ void CTwoBoxStartHandler::Timer(unsigned long iTime, dasherint iDasherX, dasheri
if(m_bFirstBox)
m_bFirstBox=false;
else
- m_pFilter->Unpause(iTime);
+ m_pFilter->run(iTime);
m_iBoxEntered = std::numeric_limits<long>::max();
}
} else {
@@ -64,7 +64,6 @@ void CTwoBoxStartHandler::Timer(unsigned long iTime, dasherint iDasherX, dasheri
}
}
-void CTwoBoxStartHandler::HandleEvent(int iParameter) {
- if (iParameter==BP_DASHER_PAUSED)
+void CTwoBoxStartHandler::onPause() {
m_bFirstBox = true;
}
diff --git a/Src/DasherCore/TwoBoxStartHandler.h b/Src/DasherCore/TwoBoxStartHandler.h
index 35709b8..cf6d8f1 100644
--- a/Src/DasherCore/TwoBoxStartHandler.h
+++ b/Src/DasherCore/TwoBoxStartHandler.h
@@ -7,13 +7,13 @@
namespace Dasher {
/// \ingroup Start
/// @{
-class CTwoBoxStartHandler : public CStartHandler, public CSettingsUserObserver {
+class CTwoBoxStartHandler : public CStartHandler, public CSettingsUser {
public:
CTwoBoxStartHandler(CDefaultFilter *pCreator);
virtual bool DecorateView(CDasherView *pView);
virtual void Timer(unsigned long iTime, dasherint iX, dasherint iY, CDasherView *pView);
- virtual void HandleEvent(int iParameter);
+ virtual void onPause();
private:
///Box currently being displayed, _iff_ BP_DASHER_PAUSED is set
diff --git a/Src/DasherCore/TwoButtonDynamicFilter.cpp b/Src/DasherCore/TwoButtonDynamicFilter.cpp
index ad3b4ea..4be5a14 100644
--- a/Src/DasherCore/TwoButtonDynamicFilter.cpp
+++ b/Src/DasherCore/TwoButtonDynamicFilter.cpp
@@ -49,7 +49,7 @@ static SModuleSettings sSettings[] = {
};
CTwoButtonDynamicFilter::CTwoButtonDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate)
- : CButtonMultiPress(pCreator, pInterface, pFramerate, 14, _("Two Button Dynamic Mode")), m_iMouseButton(-1)
+ : CButtonMultiPress(pCreator, pInterface, pFramerate, 14, _("Two Button Dynamic Mode")), CSettingsObserver(pCreator), m_iMouseButton(-1)
{
//ensure that m_dLagMul is properly initialised
HandleEvent(LP_DYNAMIC_BUTTON_LAG);
@@ -117,9 +117,8 @@ void CTwoButtonDynamicFilter::KeyUp(unsigned long Time, int iId, CDasherView *pV
CButtonMultiPress::KeyUp(Time, iId, pView, pInput,pModel);
}
-bool CTwoButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
+void CTwoButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
OneStepTowards(m_pDasherModel, 100,2048, Time, SlowStartSpeedMul(Time));
- return true;
}
void CTwoButtonDynamicFilter::ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel) {
@@ -134,7 +133,7 @@ void CTwoButtonDynamicFilter::ActionButton(unsigned long iTime, int iButton, int
dFactor *= - (1.0 + exp(pModel->GetNats())); //prev jump is further now
}
else if (iType != 0) {
- reverse();
+ reverse(iTime);
return;
}
@@ -186,5 +185,4 @@ void CTwoButtonDynamicFilter::HandleEvent(int iParameter)
case LP_TWO_BUTTON_OFFSET:
m_bDecorationChanged = true;
}
- CButtonMultiPress::HandleEvent(iParameter);
}
diff --git a/Src/DasherCore/TwoButtonDynamicFilter.h b/Src/DasherCore/TwoButtonDynamicFilter.h
index d4669b4..451391e 100644
--- a/Src/DasherCore/TwoButtonDynamicFilter.h
+++ b/Src/DasherCore/TwoButtonDynamicFilter.h
@@ -28,7 +28,7 @@
namespace Dasher {
/// \ingroup InputFilter
/// @{
-class CTwoButtonDynamicFilter : public CButtonMultiPress {
+class CTwoButtonDynamicFilter : public CButtonMultiPress, public CSettingsObserver {
public:
CTwoButtonDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate);
@@ -48,7 +48,7 @@ class CTwoButtonDynamicFilter : public CButtonMultiPress {
private:
unsigned int maxClickCount() {return GetBoolParameter(BP_2B_INVERT_DOUBLE) ? 3 : 2;}
- virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ virtual void TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
virtual void ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel);
double m_dLagMul;
///id of physical key, whose pressing we have emulated, in response
diff --git a/Src/DasherCore/TwoPushDynamicFilter.cpp b/Src/DasherCore/TwoPushDynamicFilter.cpp
index e7feef7..e6bf99c 100644
--- a/Src/DasherCore/TwoPushDynamicFilter.cpp
+++ b/Src/DasherCore/TwoPushDynamicFilter.cpp
@@ -44,7 +44,7 @@ static SModuleSettings sSettings[] = {
};
CTwoPushDynamicFilter::CTwoPushDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate)
- : CDynamicButtons(pCreator, pInterface, pFramerate, 14, _("Two-push Dynamic Mode (New One Button)")), m_dNatsSinceFirstPush(-std::numeric_limits<double>::infinity()) {
+ : CDynamicButtons(pCreator, pInterface, pFramerate, 14, _("Two-push Dynamic Mode (New One Button)")), CSettingsObserver(pCreator), m_dNatsSinceFirstPush(-std::numeric_limits<double>::infinity()) {
HandleEvent(LP_TWO_PUSH_OUTER);//and all the others too!
}
@@ -99,9 +99,7 @@ bool CTwoPushDynamicFilter::DecorateView(CDasherView *pView, CDasherInput *pInpu
return bRV;
}
-void CTwoPushDynamicFilter::HandleEvent(int iParameter)
-{
- CDynamicButtons::HandleEvent(iParameter);
+void CTwoPushDynamicFilter::HandleEvent(int iParameter) {
switch (iParameter)
{
case LP_TWO_PUSH_OUTER:
@@ -189,7 +187,7 @@ void CTwoPushDynamicFilter::ActionButton(unsigned long iTime, int iButton, int i
// 1 = long click
if (iType != 0) {
- reverse();
+ reverse(iTime);
return;
}
if (m_dNatsSinceFirstPush == -std::numeric_limits<double>::infinity()) //no button pushed (recently)
@@ -202,7 +200,7 @@ void CTwoPushDynamicFilter::ActionButton(unsigned long iTime, int iButton, int i
{
//cout << "Second push - event type " << iType << " logGrowth " << pModel->GetNats() << "\n";
if (m_iActiveMarker == -1)
- reverse();
+ reverse(iTime);
else
{
ApplyOffset(pModel,m_aiTarget[m_iActiveMarker]);
@@ -220,8 +218,7 @@ bool doSet(int &var, const int val)
return true;
}
-bool CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
-{
+void CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
DASHER_ASSERT(isRunning());
if (m_dNatsSinceFirstPush > -std::numeric_limits<double>::infinity()) // first button has been pushed
{
@@ -248,7 +245,7 @@ bool CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDashe
{
//cout << " growth " << dLogGrowth << " - reversing\n";
//button pushed, but then waited too long.
- reverse();
+ reverse(iTime);
}
else if (dLogGrowth >= m_dMinShortTwoPushTime && dLogGrowth <= m_dMaxShortTwoPushTime)
m_bDecorationChanged |= doSet(m_iActiveMarker, 0 /*up*/);
@@ -257,12 +254,11 @@ bool CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDashe
else m_bDecorationChanged |= doSet(m_iActiveMarker, -1 /*in middle (neither/both) or too short*/);
}
OneStepTowards(m_pDasherModel, 100, 2048, iTime, SlowStartSpeedMul(iTime));
- return true;
}
-void CTwoPushDynamicFilter::run() {
+void CTwoPushDynamicFilter::run(unsigned long iTime) {
m_dNatsSinceFirstPush = -std::numeric_limits<double>::infinity();
- CDynamicButtons::run();
+ CDynamicButtons::run(iTime);
}
bool CTwoPushDynamicFilter::GetSettings(SModuleSettings **pSettings, int *iCount) {
diff --git a/Src/DasherCore/TwoPushDynamicFilter.h b/Src/DasherCore/TwoPushDynamicFilter.h
index 6a0c7a4..f893e8f 100644
--- a/Src/DasherCore/TwoPushDynamicFilter.h
+++ b/Src/DasherCore/TwoPushDynamicFilter.h
@@ -25,7 +25,7 @@
namespace Dasher {
/// \ingroup InputFilter
/// @{
-class CTwoPushDynamicFilter : public CDynamicButtons /*long push, but do our own "multi-push" detection*/ {
+class CTwoPushDynamicFilter : public CDynamicButtons, public CSettingsObserver /*long push, but do our own "multi-push" detection*/ {
public:
CTwoPushDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate);
@@ -40,12 +40,12 @@ class CTwoPushDynamicFilter : public CDynamicButtons /*long push, but do our own
virtual void KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
protected:
- virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
+ virtual void TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
virtual void ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel);
virtual void HandleEvent(int iParameter);
- virtual void run();
+ virtual void run(unsigned long iTime);
private:
double m_dLogUpMul, m_dLogDownMul, m_dLagBits;
diff --git a/Src/DasherCore/UserLog.cpp b/Src/DasherCore/UserLog.cpp
index 1be4d83..947e89e 100644
--- a/Src/DasherCore/UserLog.cpp
+++ b/Src/DasherCore/UserLog.cpp
@@ -46,8 +46,8 @@ static UserLogParamMask s_UserLogParamMaskTable [] = {
};
CUserLog::CUserLog(CSettingsUser *pCreateFrom,
- Observable<const CEditEvent *> *pObsv,
- int iLogTypeMask) : CUserLogBase(pCreateFrom, pObsv) {
+ Observable<const CEditEvent *> *pObsv, int iLogTypeMask)
+: CUserLogBase(pObsv), CSettingsUserObserver(pCreateFrom) {
//CFunctionLogger f1("CUserLog::CUserLog", g_pLogger);
InitMemberVars();
@@ -1134,7 +1134,8 @@ void CUserLog::UpdateParam(int iParameter, int iOptionMask)
// TODO these are broken by settings rewrite. Fix???
// Load the object from an XML file
-CUserLog::CUserLog(string strXMLFilename) : CUserLogBase(NULL, NULL) {
+CUserLog::CUserLog(string strXMLFilename)
+: CUserLogBase(NULL), CSettingsUserObserver(NULL) {
//CFunctionLogger f1("CUserLog::CUserLog(XML)", g_pLogger);
InitMemberVars();
diff --git a/Src/DasherCore/UserLog.h b/Src/DasherCore/UserLog.h
index fd12675..af91ee9 100644
--- a/Src/DasherCore/UserLog.h
+++ b/Src/DasherCore/UserLog.h
@@ -74,7 +74,7 @@ typedef vector<VECTOR_STRING>::iterator VECTOR_VECTOR_STRING_ITER;
// We need to be notified when parameters we are logging get changed, but UserLogBase
// is already watching BP_DASHER_PAUSED
-class CUserLog : public CUserLogBase {
+class CUserLog : public CUserLogBase, protected Dasher::CSettingsUserObserver {
public:
CUserLog(Dasher::CSettingsUser *pCreateFrom, Observable<const Dasher::CEditEvent *> *pHandler, int iLogTypeMask);
diff --git a/Src/DasherCore/UserLogBase.cpp b/Src/DasherCore/UserLogBase.cpp
index 14b9787..894362c 100644
--- a/Src/DasherCore/UserLogBase.cpp
+++ b/Src/DasherCore/UserLogBase.cpp
@@ -14,8 +14,8 @@
using namespace Dasher;
-CUserLogBase::CUserLogBase(CSettingsUser *pCreateFrom, Observable<const CEditEvent *> *pHandler)
-: CSettingsUserObserver(pCreateFrom), TransientObserver<const CEditEvent *>(pHandler), m_iNumDeleted(0) {
+CUserLogBase::CUserLogBase(Observable<const CEditEvent *> *pHandler)
+: TransientObserver<const CEditEvent *>(pHandler), m_iNumDeleted(0) {
};
void CUserLogBase::HandleEvent(const CEditEvent *evt) {
@@ -28,17 +28,6 @@ void CUserLogBase::HandleEvent(const CEditEvent *evt) {
}
}
-void CUserLogBase::HandleEvent(int iParameter) {
- if (iParameter==BP_DASHER_PAUSED) {
- if (!GetBoolParameter(BP_DASHER_PAUSED)) {
- //Just unpaused
- StartWriting(); //note this happens for _each_ click/zoom
- // in Click Mode, Direct Mode, Menu Mode etc.
- // (but StartWriting generally ignores extra calls after the first)
- }
- }
-}
-
void CUserLogBase::FrameEnded() {
//pass on added/deleted if any, and get ready for next frame
if (m_iNumDeleted) {
diff --git a/Src/DasherCore/UserLogBase.h b/Src/DasherCore/UserLogBase.h
index 177bd2c..4cbfe65 100644
--- a/Src/DasherCore/UserLogBase.h
+++ b/Src/DasherCore/UserLogBase.h
@@ -16,13 +16,16 @@ namespace Dasher {
/// \defgroup Logging Logging routines
/// @{
-class CUserLogBase : protected Dasher::CSettingsUserObserver, protected TransientObserver<const Dasher::CEditEvent *> {
+class CUserLogBase : protected TransientObserver<const Dasher::CEditEvent *> {
public:
- CUserLogBase(CSettingsUser *pCreateFrom, Observable<const Dasher::CEditEvent*> *pHandler);
+ CUserLogBase(Observable<const Dasher::CEditEvent*> *pHandler);
virtual void AddParam(const std::string& strName, const std::string& strValue, int iOptionMask = 0) = 0;
virtual void AddParam(const std::string& strName, double dValue, int iOptionMask = 0) = 0;
virtual void AddParam(const std::string& strName, int iValue, int iOptionMask = 0) = 0;
+ //Called when the user starts moving. Note this happens for _each_ click/zoom
+ // in Click Mode, Direct Mode, Menu Mode etc. (so should ignore extra calls
+ // after the first.)
virtual void StartWriting() = 0;
virtual void StopWriting(float dNats) = 0;
virtual void StopWriting() = 0;
@@ -36,8 +39,6 @@ class CUserLogBase : protected Dasher::CSettingsUserObserver, protected Transien
virtual void SetOuputFilename(const std::string& strFilename = "") = 0;
virtual int GetLogLevelMask() = 0;
virtual void KeyDown(int iId, int iType, int iEffect) = 0;
- ///Watch for BP_DASHER_PAUSED being cleared, call StartWriting().
- virtual void HandleEvent(int iParameter);
///Watches output events to record symbols added/deleted
virtual void HandleEvent(const Dasher::CEditEvent *pEvent);
///Passes record of symbols added/deleted to AddSymbols/DeleteSymbols
diff --git a/Src/Gtk2/DasherControl.cpp b/Src/Gtk2/DasherControl.cpp
index a06afa7..781709c 100644
--- a/Src/Gtk2/DasherControl.cpp
+++ b/Src/Gtk2/DasherControl.cpp
@@ -585,9 +585,8 @@ gboolean CDasherControl::ExposeEvent() {
return 0;
}
-void CDasherControl::Stop() {
- if (GetBoolParameter(BP_DASHER_PAUSED)) return;
- CDasherInterfaceBase::Stop();
+void CDasherControl::Done() {
+ CDasherInterfaceBase::Done();
g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_stop");
}
diff --git a/Src/Gtk2/DasherControl.h b/Src/Gtk2/DasherControl.h
index e9aa8a1..55a6249 100644
--- a/Src/Gtk2/DasherControl.h
+++ b/Src/Gtk2/DasherControl.h
@@ -130,8 +130,8 @@ public:
gboolean ExposeEvent();
- ///Override to broadcast signal...
- virtual void Stop();
+ ///Override to broadcast dasher_stop signal...
+ virtual void Done();
virtual void WriteTrainFile(const std::string &filename, const std::string &strNewText);
virtual int GetFileSize(const std::string &strFileName);
diff --git a/Src/Gtk2/GtkDasherControl.cpp b/Src/Gtk2/GtkDasherControl.cpp
index 4e0c397..6645ea1 100644
--- a/Src/Gtk2/GtkDasherControl.cpp
+++ b/Src/Gtk2/GtkDasherControl.cpp
@@ -290,7 +290,7 @@ gtk_dasher_control_get_module_settings(GtkDasherControl * pControl, const gchar
void
gtk_dasher_control_force_pause(GtkDasherControl *pControl) {
GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pControl);
- pPrivate->pControl->Stop();
+ pPrivate->pControl->GetActiveInputMethod()->pause();
}
const char *
diff --git a/Src/iPhone/Classes/DasherAppDelegate.mm b/Src/iPhone/Classes/DasherAppDelegate.mm
index 31eae7a..7809b57 100644
--- a/Src/iPhone/Classes/DasherAppDelegate.mm
+++ b/Src/iPhone/Classes/DasherAppDelegate.mm
@@ -318,7 +318,7 @@ using namespace Dasher;
- (void)settings {
//avoid awful muddle if we change out of tap-to-start mode whilst running....
- _dasherInterface->Stop();
+ _dasherInterface->GetActiveInputMethod()->pause();
UITabBarController *tabs = [[[UITabBarController alloc] init] autorelease];
tabs.title = @"Settings";
diff --git a/Src/iPhone/Classes/IPhoneFilters.h b/Src/iPhone/Classes/IPhoneFilters.h
index 507536e..15487d4 100644
--- a/Src/iPhone/Classes/IPhoneFilters.h
+++ b/Src/iPhone/Classes/IPhoneFilters.h
@@ -33,11 +33,11 @@ public:
///override to enable hold-to-go
virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
- ///respond to BP_DASHER_PAUSED by engaging wakelock (if !hold-to-go)
- virtual void HandleEvent(int iParameter);
+ virtual void pause(); ///Override to re-enable idle timer
void iPhonePrefsChanged(NSString *key);
bool supportsPause();
protected:
+ virtual void run(unsigned long iTime); ///Override to disable idle timer
///Override to choose whether to apply 1D transform or not, and to get X coord from touch if appropriate
virtual void ApplyTransform(myint &iDasherX, myint &iDasherY, CDasherView *pView);
///Never apply offset (just eyetracker remapping!) - otherwise would be done when operating in 2d mode
diff --git a/Src/iPhone/Classes/IPhoneFilters.mm b/Src/iPhone/Classes/IPhoneFilters.mm
index c46a1fe..f76f562 100644
--- a/Src/iPhone/Classes/IPhoneFilters.mm
+++ b/Src/iPhone/Classes/IPhoneFilters.mm
@@ -43,13 +43,13 @@ void CIPhoneTiltFilter::ApplyTransform(myint &iDasherX, myint &iDasherY, CDasher
void CIPhoneTiltFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
if(iId == 100 && bHoldToGo)
- Unpause(iTime);
+ run(iTime);
else COneDimensionalFilter::KeyDown(iTime, iId, pView, pInput, pModel);
}
void CIPhoneTiltFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
if(iId == 100 && bHoldToGo)
- m_pInterface->Stop();
+ stop();
else COneDimensionalFilter::KeyUp(iTime, iId, pView, pInput, pModel);
}
@@ -61,12 +61,14 @@ void CIPhoneTiltFilter::ApplyOffset(myint &iDasherX, myint &iDasherY) {
//Do not apply LP_TARGET_OFFSET, or BP_AUTO_CALIBRATE
}
-void CIPhoneTiltFilter::HandleEvent(int iParameter) {
- if (iParameter==BP_DASHER_PAUSED
- && m_pInterface->GetActiveInputMethod()==this) {
- [UIApplication sharedApplication].idleTimerDisabled=(!GetBoolParameter(BP_DASHER_PAUSED) && !bHoldToGo);
- }
- COneDimensionalFilter::HandleEvent(iParameter);
+void CIPhoneTiltFilter::pause() {
+ COneDimensionalFilter::pause();
+ [UIApplication sharedApplication].idleTimerDisabled=NO;
+}
+
+void CIPhoneTiltFilter::run(unsigned long iTime) {
+ COneDimensionalFilter::run(iTime);
+ [UIApplication sharedApplication].idleTimerDisabled = !bHoldToGo;
}
void CIPhoneTiltFilter::iPhonePrefsChanged(NSString *key) {
@@ -137,12 +139,12 @@ CIPhoneTwoFingerFilter::CIPhoneTwoFingerFilter(CSettingsUser *pCreator, CDasherI
}
void CIPhoneTwoFingerFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
- if (iId==101) Unpause(iTime);
+ if (iId==101) run(iTime);
else if (iId!=100) CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel);
}
void CIPhoneTwoFingerFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
- if (iId==101) m_pInterface->Stop();
+ if (iId==101) stop();
else if (iId!=100) CDefaultFilter::KeyUp(iTime, iId, pView, pInput, pModel);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]