summaryrefslogtreecommitdiff
path: root/inputmethods/dasher/DasherModel.cpp
Unidiff
Diffstat (limited to 'inputmethods/dasher/DasherModel.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--inputmethods/dasher/DasherModel.cpp322
1 files changed, 322 insertions, 0 deletions
diff --git a/inputmethods/dasher/DasherModel.cpp b/inputmethods/dasher/DasherModel.cpp
new file mode 100644
index 0000000..0450d66
--- a/dev/null
+++ b/inputmethods/dasher/DasherModel.cpp
@@ -0,0 +1,322 @@
1// DasherModel.h
2//
3/////////////////////////////////////////////////////////////////////////////
4//
5// Copyright (c) 2001-2002 David Ward
6//
7/////////////////////////////////////////////////////////////////////////////
8
9#include <iostream>
10#include "DasherModel.h"
11
12using namespace Dasher;
13using namespace std;
14
15//////////////////////////////////////////////////////////////////////
16// CDasherModel
17//////////////////////////////////////////////////////////////////////
18
19CDasherModel::CDasherModel(CDashEditbox* Editbox, CLanguageModel* LanguageModel, bool Dimensions)
20 : m_editbox(Editbox), m_languagemodel(LanguageModel), m_Root(0), m_Dimensions(Dimensions)
21{
22 LearnContext = m_languagemodel->GetRootNodeContext();
23
24 // various settings
25 int iShift = 12;
26 m_DasherY = 1<<iShift;
27 m_DasherOY = m_DasherY/2;
28 m_DasherOX = m_DasherY/2;
29 m_dAddProb = 0.003;
30}
31
32
33CDasherModel::~CDasherModel()
34{
35 m_languagemodel->ReleaseNodeContext(LearnContext);
36 delete m_Root; // which will also delete all the whole structure
37}
38
39
40void CDasherModel::Make_root(int whichchild)
41 // find a new root node
42{
43 symbol t=m_Root->Symbol();
44 if (t) {
45 m_editbox->output(t);
46 m_languagemodel->LearnNodeSymbol(LearnContext, t);
47 }
48
49 CDasherNode * oldroot=m_Root;
50
51 CDasherNode **children=m_Root->Children();
52 m_Root=children[whichchild];
53 //oldroot->Children()[whichchild]=0; // null the pointer so we don't delete the whole tree
54 //delete oldroot;
55
56 oldroots.push_back(oldroot);
57
58 myint range=m_Rootmax-m_Rootmin;
59 m_Rootmax=m_Rootmin+(range*m_Root->Hbnd())/Normalization();
60 m_Rootmin+=(range*m_Root->Lbnd())/Normalization();
61}
62
63void CDasherModel::Reparent_root(int lower, int upper)
64{
65 /* Change the root node to the parent of the existing node
66 We need to recalculate the coordinates for the "new" root as the
67 user may have moved around within the current root */
68
69 /* Determine how zoomed in we are */
70 float scalefactor=(m_Rootmax-m_Rootmin)/(upper-lower);
71
72 m_Rootmax=int(m_Rootmax+((1024-upper)*scalefactor));
73 m_Rootmin=int(m_Rootmin-(lower*scalefactor));
74
75 m_editbox->deletetext();
76
77 m_Root=oldroots.back();
78 oldroots.pop_back();
79}
80
81/////////////////////////////////////////////////////////////////////////////
82
83CDasherNode * CDasherModel::Get_node_under_crosshair()
84{
85 return m_Root->Get_node_under(Normalization(),m_Rootmin,m_Rootmax,m_DasherOX,m_DasherOY);
86}
87
88/////////////////////////////////////////////////////////////////////////////
89
90
91CDasherNode * CDasherModel::Get_node_under_mouse(myint Mousex,myint Mousey)
92{
93 return m_Root->Get_node_under(Normalization(),m_Rootmin,m_Rootmax,Mousex,Mousey);
94}
95
96/////////////////////////////////////////////////////////////////////////////
97
98
99void CDasherModel::Get_string_under_mouse(const myint Mousex,const myint Mousey, vector<symbol> &str)
100{
101 m_Root->Get_string_under(Normalization(),m_Rootmin,m_Rootmax,Mousex,Mousey,str);
102 return;
103}
104
105/////////////////////////////////////////////////////////////////////////////
106
107
108void CDasherModel::Flush(const myint Mousex,const myint Mousey)
109{
110 vector<symbol> vtUnder;
111 Get_string_under_mouse(m_DasherOX,m_DasherOY,vtUnder);
112 unsigned int i;
113 for (i=0;i<vtUnder.size();i++) {
114 if (vtUnder[i]==0)
115 continue;
116 m_editbox->flush(vtUnder[i]);
117 }
118}
119
120/////////////////////////////////////////////////////////////////////////////
121
122void CDasherModel::Update(CDasherNode *node,CDasherNode *under_mouse,int iSafe)
123// go through the Dasher nodes, delete ones who have expired
124// decrease the time left for nodes which arent safe
125// safe nodes are those which are under the mouse or offspring of this node
126{
127 //if (node->pushme )
128 // node->push_node();
129 if (node==under_mouse)
130 iSafe=1;
131 if (!iSafe)
132 node->Age();
133 //dchar debug[256];
134 //wsprintf(debug,TEXT("node->Age %d %f\n"),node->Age, fr.framerate());
135 //OutputDebugString(debug);
136
137
138 if (node->Age() > Framerate())
139 node->Kill();
140
141
142 if (node->Alive()) {
143 CDasherNode **children=node->Children();
144 if (children) {
145 unsigned int i;
146 for (i=1;i<node->Chars();i++)
147 Update(children[i],under_mouse,iSafe);
148 }
149 }
150 return;
151}
152
153/////////////////////////////////////////////////////////////////////////////
154
155void CDasherModel::Start()
156{
157 m_Rootmin=0;
158 m_Rootmax=m_DasherY;
159
160 delete m_Root;
161 CLanguageModel::CNodeContext* therootcontext=m_languagemodel->GetRootNodeContext();
162
163 //Rootparent=new DasherNode(0,0,0,therootcontext,0,0,0,Normalization(),languagemodel);
164 if (m_editbox) {
165 m_editbox->set_flushed(0);
166 string ContextString;
167 m_editbox->get_new_context(ContextString,5);
168 if (ContextString.size() != 0) {
169 m_languagemodel->EnterText(therootcontext, ContextString);
170 }
171 m_languagemodel->ReleaseNodeContext(LearnContext);
172 LearnContext = m_languagemodel->CloneNodeContext(therootcontext);
173 }
174 m_Root=new CDasherNode(0,0,0,0,Opts::Nodes1,0,Normalization(),m_languagemodel);
175 m_Root->Push_Node(therootcontext);
176
177 m_languagemodel->ReleaseNodeContext(therootcontext);
178 //ppmmodel->dump();
179 //dump();
180
181}
182
183/////////////////////////////////////////////////////////////////////////////
184
185void CDasherModel::Get_new_root_coords(myint Mousex,myint Mousey)
186{
187 int cappedrate=0;
188 double dRx=1.0,dRxnew=1.0;
189 double dRxnew2;
190
191 int iSteps=m_fr.Steps();
192
193 if (Mousex<m_DasherOX) {
194 //rx=1.0001*Ixmap[mx]/Ixmap[cx];
195 if (Mousex<=0)
196 Mousex=1;
197 dRx=1.0*m_DasherOX/Mousex;
198 dRxnew=pow(dRx,1.0/iSteps); // or exp(log(rx)/steps) - i think the replacement is faster
199
200 dRxnew2=1+(dRx-1)/iSteps;
201 //+(rx-1)*(rx-1)*(1.0/fr.steps()-1.0)/2/fr.steps();
202
203
204 const double dRxmax=m_fr.Rxmax();
205 if (dRxnew>dRxmax)
206 dRxnew=dRxmax;
207 // cappedrate=1;
208 } else {
209 if (Mousex==m_DasherOX)
210 Mousex++;
211 // OutputDebugString(TEXT("zoom out\n"));
212 dRx=1.0001*m_DasherOX/Mousex;
213 dRxnew=exp(log(dRx)/iSteps);
214 //get_coords(root->lbnd,root->hbnd,&x1,&y1,&y2);
215 //if (x1>0 || y1>0 || y2<CanvasY)
216 //go_back_a_char();
217 if (m_Rootmax<m_DasherY && m_Rootmin>0)
218 return;
219 }
220 //dchar debug[256];
221 //_stprintf(debug,TEXT("rx %f rxnew %f approx %f\n"),rx,rxnew,rxnew2);
222 //OutputDebugString(debug);
223 //wsprintf(debug,TEXT("rx %f rxnew %f\n"),rx,rxnew);
224 //OutputDebugString(debug);
225 myint above=(Mousey-m_Rootmin);//*(1-rxnew)/(1-rx);
226 myint below=(m_Rootmax-Mousey);//*(1-rxnew)/(1-rx);
227
228 //wsprintf(debug,TEXT("above %I64d below %I64d \n"),above,below);
229 //OutputDebugString(debug);
230
231 myint miDistance=m_DasherY/2-Mousey;
232 miDistance=myint(miDistance*(dRxnew-1)/(dRx-1));
233 myint miNewrootzoom=Mousey+miDistance;
234
235 myint newRootmax=miNewrootzoom+myint(below*dRxnew);
236 myint newRootmin=miNewrootzoom-myint(above*dRxnew);
237 if (newRootmin<m_DasherY/2 && newRootmax>m_DasherY/2 && newRootmax<LLONG_MAX && newRootmin>LLONG_MIN) {
238 m_Rootmax=newRootmax;
239 m_Rootmin=newRootmin;
240 }
241
242}
243
244/////////////////////////////////////////////////////////////////////////////
245
246void CDasherModel::Tap_on_display(myint miMousex,myint miMousey, unsigned long Time)
247 // work out the next viewpoint, opens some new nodes
248{
249 // works out next viewpoint
250 Get_new_root_coords(miMousex,miMousey);
251
252 // opens up new nodes
253
254 // push node under mouse
255 CDasherNode *under_mouse=Get_node_under_mouse(miMousex,miMousey);
256 under_mouse->Push_Node();
257
258
259 if (Framerate() > 4) {
260 // push node under mouse but with x coord on RHS
261 CDasherNode *right=Get_node_under_mouse(50,miMousey);
262 right->Push_Node();
263 }
264
265 if (Framerate() > 8) {
266 // push node under the crosshair
267 CDasherNode *under_cross=Get_node_under_crosshair();
268 under_cross->Push_Node();
269 }
270
271 unsigned int iRandom;
272#if defined(_WIN32_WCE)
273 iRandom=Random();
274#else
275 iRandom=rand();
276#endif
277 if (Framerate() > 8) {
278 // add some noise and push another node
279 CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%500-250);
280 right->Push_Node();
281 }
282#if defined(_WIN32_WCE)
283 iRandom=Random();
284#else
285 iRandom=rand();
286#endif
287 if (Framerate() > 15) {
288 // add some noise and push another node
289 CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%500-250);
290 right->Push_Node();
291 }
292
293 // only do this is Dasher is flying
294 if (Framerate() > 30) {
295 for (int i=1;i<int(Framerate()-30)/3;i++) {
296 #if defined(_WIN32_WCE)
297 iRandom=Random();
298#else
299 iRandom=rand();
300#endif
301 // push at a random node on the RHS
302 CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%1000-500);
303 right->Push_Node();
304
305 }
306 }
307 Update(m_Root,under_mouse,0);
308
309
310}
311
312/////////////////////////////////////////////////////////////////////////////
313
314void CDasherModel::Dump() const
315 // diagnostic dump
316{
317 // OutputDebugString(TEXT(" ptr symbol context Next Child pushme pushed cscheme lbnd hbnd \n"));
318 m_Root->Dump_node();
319}
320
321
322