File: CircleStartHandler.cpp

package info (click to toggle)
dasher 4.11%2Bgit20130508.adc653-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 40,248 kB
  • ctags: 5,158
  • sloc: xml: 185,479; cpp: 32,301; sh: 11,207; makefile: 828; ansic: 483
file content (137 lines) | stat: -rw-r--r-- 5,057 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// CircleStartHandler.cpp
//
// Copyright (c) 2007 The Dasher Team
//
// This file is part of Dasher.
//
// Dasher is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Dasher is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Dasher; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#include "../Common/Common.h"

#include "CircleStartHandler.h"
#include "DefaultFilter.h"
#include "DasherInterfaceBase.h"
#include "Event.h"
#include "DasherInput.h"

using namespace Dasher;

CCircleStartHandler::CCircleStartHandler(CDefaultFilter *pCreator)
: CStartHandler(pCreator), CSettingsUserObserver(pCreator), m_iEnterTime(std::numeric_limits<long>::max()), m_iScreenRadius(-1), m_pView(NULL) {
}

CCircleStartHandler::~CCircleStartHandler() {
  if (m_pView) m_pView->Observable<CDasherView*>::Unregister(this);
}

CDasherScreen::point CCircleStartHandler::CircleCenter(CDasherView *pView) {
  if (m_iScreenRadius!=-1) return m_screenCircleCenter;

  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;
  m_pView->Dasher2Screen(CDasherModel::ORIGIN_X, CDasherModel::ORIGIN_Y + (CDasherModel::MAX_Y*GetLongParameter(LP_CIRCLE_PERCENT))/100, iEdgeX, iEdgeY);

  const Opts::ScreenOrientations iDirection(m_pView->GetOrientation());

  if((iDirection == Opts::TopToBottom) || (iDirection == Opts::BottomToTop)) {
    m_iScreenRadius = iEdgeX - m_screenCircleCenter.x;
  }
  else {
    m_iScreenRadius = iEdgeY - m_screenCircleCenter.y;
  }
  return m_screenCircleCenter;
}

bool CCircleStartHandler::DecorateView(CDasherView *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 (m_pFilter->isPaused()) {
    lineColor=2; lineWidth=1;
    fillColor = bAboutToChange ? 241 : 242;
  } else {
    lineColor=240; fillColor=-1; //don't fill
    lineWidth = bAboutToChange ? 3 : 1;
  }

  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) {
  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-=ctr.x; y-=ctr.y;
  const bool inCircleNow = x*x + y*y <= (m_iScreenRadius * m_iScreenRadius);

  if (inCircleNow) {
    if (m_bInCircle) {
      //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 (m_pFilter->isPaused())
          m_pFilter->run(iTime);
        else
          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
      }
    } else {// !m_bInCircle
      //just entered circle
      m_bInCircle=true;
      m_iEnterTime = iTime;
    }
  } else {
    //currently outside circle
    m_bInCircle=false;
  }
}

void CCircleStartHandler::HandleEvent(int iParameter) {
  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
  if (pNewView != m_pView) {
    if (m_pView) m_pView->Observable<CDasherView*>::Unregister(this);
    (m_pView=pNewView)->Observable<CDasherView*>::Register(this);
  }
}