tagging release
[dasher.git] / Src / DasherCore / DasherView.cpp
bloba758dd4b447758af882e4041624ab778694a93d6
1 // DasherView.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2001-2005 David Ward
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 #include "../Common/Common.h"
11 #include "DasherView.h"
12 #include "Event.h"
13 #include "EventHandler.h"
14 #include "DasherModel.h"
15 #include "DasherInput.h"
17 #include <iostream>
19 using namespace Dasher;
21 // Track memory leaks on Windows to the line that new'd the memory
22 #ifdef _WIN32
23 #ifdef _DEBUG
24 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
25 #define new DEBUG_NEW
26 #undef THIS_FILE
27 static char THIS_FILE[] = __FILE__;
28 #endif
29 #endif
31 /////////////////////////////////////////////////////////////////////////////
33 CDasherView::CDasherView(CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherScreen *DasherScreen)
34 :CDasherComponent(pEventHandler, pSettingsStore), m_pScreen(DasherScreen), m_pInput(0) {
37 void CDasherView::HandleEvent(Dasher::CEvent *pEvent) {
38 if(pEvent->m_iEventType == 1) {
39 Dasher::CParameterNotificationEvent * pEvt(static_cast < Dasher::CParameterNotificationEvent * >(pEvent));
41 switch (pEvt->m_iParameter) {
42 case BP_DASHER_PAUSED:
44 break;
45 default:
46 break;
51 /////////////////////////////////////////////////////////////////////////////
53 void CDasherView::ChangeScreen(CDasherScreen *NewScreen) {
54 m_pScreen = NewScreen;
57 /////////////////////////////////////////////////////////////////////////////
59 bool CDasherView::Render(CDasherNode *pRoot, myint iRootMin, myint iRootMax, std::vector<CDasherNode *> &vNodeList, std::vector<CDasherNode *> &vDeleteList, bool bRedrawDisplay, bool bGameMode) {
61 m_iRenderCount = 0;
62 myint iGamePointer;
63 Screen()->SetLoadBackground(false);
64 RenderNodes(pRoot, iRootMin, iRootMax, vNodeList, vDeleteList, &iGamePointer);
66 if(bGameMode)
67 DrawGameModePointer(iGamePointer);
69 return true;
72 int CDasherView::GetCoordinateCount() {
73 // TODO: Do we really need support for co-ordinate counts other than 2?
74 if(m_pInput)
75 return m_pInput->GetCoordinateCount();
76 else
77 return 0;
80 int CDasherView::GetInputCoordinates(int iN, myint * pCoordinates) {
81 if(m_pInput)
82 return m_pInput->GetCoordinates(iN, pCoordinates);
83 else
84 return 0;
87 void CDasherView::SetInput(CDasherInput * _pInput) {
88 // TODO: Is it sensible to make this responsible for the input
89 // device - I guess it makes sense for now
91 DASHER_ASSERT_VALIDPTR_RW(_pInput);
93 // Don't delete the old input class; whoever is calling this method
94 // might want to keep several Input class instances around and
95 // change which one is currently driving dasher without deleting any
97 m_pInput = _pInput;
99 // Tell the new object about maximum values
101 myint iMaxCoordinates[2];
103 iMaxCoordinates[0] = GetLongParameter(LP_MAX_Y);
104 iMaxCoordinates[1] = GetLongParameter(LP_MAX_Y);
106 m_pInput->SetMaxCoordinates(2, iMaxCoordinates);
109 void CDasherView::Display() {
111 Screen()->SetLoadBackground(true);
112 m_pScreen->Display();
115 /// Draw a polyline specified in Dasher co-ordinates
117 void CDasherView::DasherPolyline(myint *x, myint *y, int n, int iWidth, int iColour) {
119 CDasherScreen::point * ScreenPoints = new CDasherScreen::point[n];
121 for(int i(0); i < n; ++i)
122 Dasher2Screen(x[i], y[i], ScreenPoints[i].x, ScreenPoints[i].y);
124 if(iColour != -1) {
125 Screen()->Polyline(ScreenPoints, n, iWidth, iColour);
127 else {
128 Screen()->Polyline(ScreenPoints, n, iWidth,0);//no color given
130 delete[]ScreenPoints;
133 // Draw a filled polygon specified in Dasher co-ordinates
135 void CDasherView::DasherPolygon(myint *x, myint *y, int n, int iColour) {
137 CDasherScreen::point * ScreenPoints = new CDasherScreen::point[n];
139 for(int i(0); i < n; ++i)
140 Dasher2Screen(x[i], y[i], ScreenPoints[i].x, ScreenPoints[i].y);
142 Screen()->Polygon(ScreenPoints, n, iColour);
143 delete[]ScreenPoints;
146 // Draw a box specified in Dasher co-ordinates
148 void CDasherView::DasherDrawRectangle(myint iLeft, myint iTop, myint iRight, myint iBottom, const int Color, int iOutlineColour, Opts::ColorSchemes ColorScheme, bool bDrawOutline, bool bFill, int iThickness) {
150 screenint iScreenLeft;
151 screenint iScreenTop;
152 screenint iScreenRight;
153 screenint iScreenBottom;
155 Dasher2Screen(iLeft, iTop, iScreenLeft, iScreenTop);
156 Dasher2Screen(iRight, iBottom, iScreenRight, iScreenBottom);
158 Screen()->DrawRectangle(iScreenLeft, iScreenTop, iScreenRight, iScreenBottom, Color, iOutlineColour, ColorScheme, bDrawOutline, bFill, iThickness);
161 /// Draw a rectangle centred on a given dasher co-ordinate, but with a size specified in screen co-ordinates (used for drawing the mouse blob)
163 void CDasherView::DasherDrawCentredRectangle(myint iDasherX, myint iDasherY, screenint iSize, const int Color, Opts::ColorSchemes ColorScheme, bool bDrawOutline) {
165 screenint iScreenX;
166 screenint iScreenY;
168 Dasher2Screen(iDasherX, iDasherY, iScreenX, iScreenY);
170 Screen()->DrawRectangle(iScreenX - iSize, iScreenY - iSize, iScreenX + iSize, iScreenY + iSize, Color, -1, ColorScheme, bDrawOutline, true, 1);
173 /// Draw text specified in Dasher co-ordinates. The position is
174 /// specified as two co-ordinates, intended to the be the corners of
175 /// the leading edge of the containing box.
177 void CDasherView::DasherDrawText(myint iAnchorX1, myint iAnchorY1, myint iAnchorX2, myint iAnchorY2, const std::string &sDisplayText, int &mostleft, bool bShove) {
179 // Don't draw text which will overlap with text in an ancestor.
181 if(iAnchorX1 > mostleft)
182 iAnchorX1 = mostleft;
184 if(iAnchorX2 > mostleft)
185 iAnchorX2 = mostleft;
187 myint iDasherMinX;
188 myint iDasherMinY;
189 myint iDasherMaxX;
190 myint iDasherMaxY;
192 VisibleRegion(iDasherMinX, iDasherMinY, iDasherMaxX, iDasherMaxY);
194 iAnchorY1 = std::min( iDasherMaxY, std::max( iDasherMinY, iAnchorY1 ) );
195 iAnchorY2 = std::min( iDasherMaxY, std::max( iDasherMinY, iAnchorY2 ) );
197 screenint iScreenAnchorX1;
198 screenint iScreenAnchorY1;
199 screenint iScreenAnchorX2;
200 screenint iScreenAnchorY2;
202 // FIXME - Truncate here before converting - otherwise we risk integer overflow in screen coordinates
204 Dasher2Screen(iAnchorX1, iAnchorY1, iScreenAnchorX1, iScreenAnchorY1);
205 Dasher2Screen(iAnchorX2, iAnchorY2, iScreenAnchorX2, iScreenAnchorY2);
207 // Truncate the ends of the anchor line to be on the screen - this
208 // prevents us from loosing characters off the top and bottom of the
209 // screen
211 // TruncateToScreen(iScreenAnchorX1, iScreenAnchorY1);
212 // TruncateToScreen(iScreenAnchorX2, iScreenAnchorY2);
214 // Actual anchor point is the midpoint of the anchor line
216 screenint iScreenAnchorX((iScreenAnchorX1 + iScreenAnchorX2) / 2);
217 screenint iScreenAnchorY((iScreenAnchorY1 + iScreenAnchorY2) / 2);
219 // Compute font size based on position
220 int Size = GetLongParameter( LP_DASHER_FONTSIZE );
222 // FIXME - this could be much more elegant, and probably needs a
223 // rethink anyway - behvaiour here is too dependent on screen size
225 screenint iLeftTimesFontSize = ((myint)GetLongParameter(LP_MAX_Y) - (iAnchorX1 + iAnchorX2)/ 2 )*Size;
226 if(iLeftTimesFontSize < (myint)GetLongParameter(LP_MAX_Y) * 19/ 20)
227 Size *= 20;
228 else if(iLeftTimesFontSize < (myint)GetLongParameter(LP_MAX_Y) * 159 / 160)
229 Size *= 14;
230 else
231 Size *= 11;
234 screenint TextWidth, TextHeight;
236 Screen()->TextSize(sDisplayText, &TextWidth, &TextHeight, Size);
238 // Poistion of text box relative to anchor depends on orientation
240 screenint newleft2 = 0;
241 screenint newtop2 = 0;
242 screenint newright2 = 0;
243 screenint newbottom2 = 0;
245 switch (Dasher::Opts::ScreenOrientations(GetLongParameter(LP_REAL_ORIENTATION))) {
246 case (Dasher::Opts::LeftToRight):
247 newleft2 = iScreenAnchorX;
248 newtop2 = iScreenAnchorY - TextHeight / 2;
249 newright2 = iScreenAnchorX + TextWidth;
250 newbottom2 = iScreenAnchorY + TextHeight / 2;
251 break;
252 case (Dasher::Opts::RightToLeft):
253 newleft2 = iScreenAnchorX - TextWidth;
254 newtop2 = iScreenAnchorY - TextHeight / 2;
255 newright2 = iScreenAnchorX;
256 newbottom2 = iScreenAnchorY + TextHeight / 2;
257 break;
258 case (Dasher::Opts::TopToBottom):
259 newleft2 = iScreenAnchorX - TextWidth / 2;
260 newtop2 = iScreenAnchorY;
261 newright2 = iScreenAnchorX + TextWidth / 2;
262 newbottom2 = iScreenAnchorY + TextHeight;
263 break;
264 case (Dasher::Opts::BottomToTop):
265 newleft2 = iScreenAnchorX - TextWidth / 2;
266 newtop2 = iScreenAnchorY - TextHeight;
267 newright2 = iScreenAnchorX + TextWidth / 2;
268 newbottom2 = iScreenAnchorY;
269 break;
270 default:
271 break;
274 // Update the value of mostleft to take into account the new text
276 if(bShove) {
277 myint iDasherNewLeft;
278 myint iDasherNewTop;
279 myint iDasherNewRight;
280 myint iDasherNewBottom;
282 Screen2Dasher(newleft2, newtop2, iDasherNewLeft, iDasherNewTop,false,true);
283 Screen2Dasher(newright2, newbottom2, iDasherNewRight, iDasherNewBottom,false,true);
285 mostleft = std::min(iDasherNewRight, iDasherNewLeft);
288 // Actually draw the text. We use DelayDrawText as the text should
289 // be overlayed once all of the boxes have been drawn.
291 m_pDelayDraw->DelayDrawText(sDisplayText, newleft2, newtop2, Size);
295 int CDasherView::GetCoordinates(unsigned long Time, myint &iDasherX, myint &iDasherY) {
297 // FIXME - Actually turn autocalibration on and off!
298 // FIXME - AutoCalibrate should use Dasher co-ordinates, not raw mouse co-ordinates?
299 // FIXME - Have I broken this by moving it before the offset is applied?
300 // FIXME - put ymap stuff back in
301 // FIXME - optimise this
302 // TODO: Time isn't used!
304 int iCoordinateCount(GetCoordinateCount());
306 myint *pCoordinates(new myint[iCoordinateCount]);
308 int iType(GetInputCoordinates(iCoordinateCount, pCoordinates));
310 screenint mousex;
311 screenint mousey;
313 if(iCoordinateCount == 1) {
314 mousex = 0;
315 mousey = pCoordinates[0];
317 else {
318 mousex = pCoordinates[0];
319 mousey = pCoordinates[1];
322 delete[]pCoordinates;
324 Screen2Dasher(mousex, mousey, iDasherX, iDasherY, false, true );
326 #ifndef WITH_MAEMO
327 // FIXME
328 // iDasherX = myint(xmap(iDasherX / static_cast < double >(GetLongParameter(LP_MAX_Y))) * GetLongParameter(LP_MAX_Y));
329 // iDasherY = m_ymap.map(iDasherY);
330 #endif
332 return iType;