Diffstat (limited to 'inputmethods/dasher/DasherModel.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | inputmethods/dasher/DasherModel.cpp | 322 |
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 | |||
12 | using namespace Dasher; | ||
13 | using namespace std; | ||
14 | |||
15 | ////////////////////////////////////////////////////////////////////// | ||
16 | // CDasherModel | ||
17 | ////////////////////////////////////////////////////////////////////// | ||
18 | |||
19 | CDasherModel::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 | |||
33 | CDasherModel::~CDasherModel() | ||
34 | { | ||
35 | m_languagemodel->ReleaseNodeContext(LearnContext); | ||
36 | delete m_Root; // which will also delete all the whole structure | ||
37 | } | ||
38 | |||
39 | |||
40 | void 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 | |||
63 | void 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 | |||
83 | CDasherNode * 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 | |||
91 | CDasherNode * 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 | |||
99 | void 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 | |||
108 | void 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 | |||
122 | void 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 | |||
155 | void 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 | |||
185 | void 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 | |||
246 | void 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 | |||
314 | void 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 | |||