1 // ConversionManager.cpp
3 // Copyright (c) 2007 The Dasher Team
5 // This file is part of Dasher.
7 // Dasher is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
12 // Dasher is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with Dasher; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "ConversionManager.h"
27 #include "Observable.h"
28 #include "NodeCreationManager.h"
29 #include "DasherModel.h"
30 #include "DasherInterfaceBase.h"
38 //Note the new implementation in Mandarin Dasher may not be compatible with the previous implementation of Japanese Dasher
39 //Need to reconcile (a small project)
41 using namespace Dasher
;
44 CConversionManager::CConversionManager(CSettingsUser
*pCreateFrom
, CDasherInterfaceBase
*pInterface
, CNodeCreationManager
*pNCManager
, const CAlphInfo
*pAlphabet
, CLanguageModel
*pLanguageModel
)
45 : CSettingsUser(pCreateFrom
), m_pInterface(pInterface
), m_pNCManager(pNCManager
), m_pAlphabet(pAlphabet
), m_pLanguageModel(pLanguageModel
) {
47 //Testing for alphabet details, delete if needed:
49 int alphSize = pNCManager->GetAlphabet()->GetNumberSymbols();
50 std::cout<<"Alphabet size: "<<alphSize<<std::endl;
51 for(int i =0; i<alphSize; i++)
52 std::cout<<"symbol: "<<i<<" display text:"<<pNCManager->GetAlphabet()->GetDisplayText(i)<<std::endl;
54 colourStore
[0][0]=66;//light blue
55 colourStore
[0][1]=64;//very light green
56 colourStore
[0][2]=62;//light yellow
57 colourStore
[1][0]=78;//light purple
58 colourStore
[1][1]=81;//brownish
59 colourStore
[1][2]=60;//red
61 m_iLearnContext
= m_pLanguageModel
->CreateEmptyContext();
65 CConversionManager::CConvNode
*CConversionManager::makeNode(int iOffset
, int iColour
, CDasherScreen::Label
*pLabel
) {
66 return new CConvNode(iOffset
, iColour
, pLabel
, this);
69 void CConversionManager::ChangeScreen(CDasherScreen
*pScreen
) {
70 if (m_pScreen
==pScreen
) return;
71 for (map
<string
, CDasherScreen::Label
*>::iterator it
=m_vLabels
.begin(); it
!=m_vLabels
.end(); it
++)
77 CDasherScreen::Label
*CConversionManager::GetLabel(const char *pszConversion
) {
78 string
strConv(pszConversion
);
79 if (m_vLabels
[strConv
])
80 return m_vLabels
[strConv
];
81 return m_vLabels
[strConv
] = m_pScreen
->MakeLabel(strConv
);
84 CConversionManager::CConvNode
*CConversionManager::GetRoot(int iOffset
, CLanguageModel::Context newCtx
) {
86 // TODO: Parameters here are placeholders - need to figure out what's right
88 //TODO: hard-coded colour, and hard-coded displaytext... (ACL: read from Alphabet -> startConversionSymbol ?)
89 CConvNode
*pNewNode
= makeNode(iOffset
, 9, NULL
);
91 pNewNode
->iContext
= newCtx
;
93 pNewNode
->bisRoot
= true;
95 pNewNode
->pSCENode
= 0;
100 CConversionManager::CConvNode::CConvNode(int iOffset
, int iColour
, CDasherScreen::Label
*pLabel
, CConversionManager
*pMgr
)
101 : CDasherNode(iOffset
, iColour
, pLabel
), m_pMgr(pMgr
) {
104 CConversionManager::CConvNode::~CConvNode() {
105 m_pMgr
->m_pLanguageModel
->ReleaseContext(iContext
);
108 void CConversionManager::RecursiveDumpTree(ostream
&out
, SCENode
*pCurrent
, unsigned int iDepth
) {
109 const std::vector
<SCENode
*> &children
= pCurrent
->GetChildren();
110 for (std::vector
<SCENode
*>::const_iterator it
= children
.begin(); it
!=children
.end(); it
++) {
111 SCENode
*pCurrent(*it
);
112 for(unsigned int i(0); i
< iDepth
; ++i
)
114 out
<< " " << pCurrent
->pszConversion
<< std::endl
;//" " << pCurrent->IsHeadAndCandNum << " " << pCurrent->CandIndex << " " << pCurrent->IsComplete << " " << pCurrent->AcCharCount << std::endl;
115 RecursiveDumpTree(out
, pCurrent
, iDepth
+ 1);
119 void CConversionManager::CConvNode::GetContext(CDasherInterfaceBase
*pInterface
, const CAlphabetMap
*pAlphabetMap
, std::vector
<symbol
> &vContextSymbols
, int iOffset
, int iLength
) {
120 if (!GetFlag(NF_SEEN
) && iOffset
+iLength
-1 == offset()) {
121 //ACL I'm extrapolating from PinYinConversionHelper (in which root nodes have their
122 // Symbol set by SetConvSymbol, and child nodes are created in PopulateChildren
123 // from SCENode's with Symbols having been set in in AssignSizes); not really sure
124 // whether this is applicable in the general case(! - but although I think it's right
125 // for PinYin, it wouldn't actually be used there, as MandarinDasher overrides contexts
127 DASHER_ASSERT(bisRoot
|| pSCENode
);
128 if (bisRoot
|| pSCENode
->Symbol
!=-1) {
129 if (iLength
>1) Parent()->GetContext(pInterface
, pAlphabetMap
, vContextSymbols
, iOffset
, iLength
-1);
130 vContextSymbols
.push_back(bisRoot
? iSymbol
: pSCENode
->Symbol
);
132 } //else, non-root with pSCENode->Symbol==-1 => fallthrough back to superclass code
134 CDasherNode::GetContext(pInterface
, pAlphabetMap
, vContextSymbols
, iOffset
, iLength
);
137 void CConversionManager::CConvNode::Output() {
138 // TODO: Reimplement this
139 // m_pNCManager->m_bContextSensitive = true;
141 SCENode
*pCurrentSCENode(pSCENode
);
144 m_pMgr
->m_pInterface
->editOutput(pCurrentSCENode
->pszConversion
, this);
146 if((GetChildren())[0]->mgr() == m_pMgr
) {
147 if (static_cast<CConvNode
*>(GetChildren()[0])->m_pMgr
== m_pMgr
) {
148 m_pMgr
->m_pInterface
->editProtect(this); //TODO used to pass in offset 0, will now get this node's offset...
153 m_pMgr
->m_pInterface
->editOutput(bisRoot
? ">" : "|", this);
155 m_pMgr
->m_pInterface
->editConvert(this); //TODO used to pass in offset 0, will now get this node's offset...
159 void CConversionManager::CConvNode::Undo() {
160 SCENode
*pCurrentSCENode(pSCENode
);
162 if(pCurrentSCENode
) {
163 if(pCurrentSCENode
->pszConversion
&& (strlen(pCurrentSCENode
->pszConversion
) > 0)) {
164 m_pMgr
->m_pInterface
->editDelete(pCurrentSCENode
->pszConversion
, this);
168 m_pMgr
->m_pInterface
->editDelete(bisRoot
? ">" : "|", this);
172 // TODO: This function needs to be significantly tidied up
173 // TODO: get rid of pSizes
175 void CConversionManager::AssignChildSizes(const std::vector
<SCENode
*> &nodes
, CLanguageModel::Context context
) {
177 AssignSizes(nodes
, context
, CDasherModel::NORMALIZATION
, GetLongParameter(LP_UNIFORM
));
181 void CConversionManager::CConvNode::PopulateChildren() {
182 DASHER_ASSERT(mgr()->m_pNCManager
);
184 // Do the conversion and build the tree (lattice) if it hasn't been
189 if(bisRoot
&& !pSCENode
) {
190 mgr()->BuildTree(this);
194 if(pSCENode
&& !pSCENode
->GetChildren().empty()) {
195 const std::vector
<SCENode
*> &vChildren
= pSCENode
->GetChildren();
196 // RecursiveDumpTree(pSCENode, 1);
197 mgr()->AssignChildSizes(vChildren
, iContext
);
202 // int parentClr = pNode->Colour();
206 // Finally loop through and create the children
208 for (std::vector
<SCENode
*>::const_iterator it
= vChildren
.begin(); it
!=vChildren
.end(); it
++) {
209 // std::cout << "Current scec: " << pCurrentSCEChild << std::endl;
210 SCENode
*pCurrentSCEChild(*it
);
211 DASHER_ASSERT(pCurrentSCEChild
!= NULL
);
212 unsigned int iLbnd(iCum
);
213 unsigned int iHbnd(iCum
+ pCurrentSCEChild
->NodeSize
);
214 //CDasherModel::NORMALIZATION);//
218 // TODO: Parameters here are placeholders - need to figure out
221 // std::cout << "#" << pCurrentSCEChild->pszConversion << "#" << std::endl;
223 CConvNode
*pNewNode
= mgr()->makeNode(offset()+1, mgr()->AssignColour(parentClr
, pCurrentSCEChild
, iIdx
), mgr()->GetLabel(pCurrentSCEChild
->pszConversion
));
225 // TODO: Reimplement ----
227 // FIXME - handle context properly
228 // pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
231 pNewNode
->bisRoot
= false;
232 pNewNode
->pSCENode
= pCurrentSCEChild
;
234 pNewNode
->iContext
= mgr()->m_pLanguageModel
->CloneContext(this->iContext
);
236 if(pCurrentSCEChild
->Symbol
!=-1)
237 mgr()->m_pLanguageModel
->EnterSymbol(pNewNode
->iContext
, pCurrentSCEChild
->Symbol
); // TODO: Don't use symbols?
239 pNewNode
->Reparent(this, iLbnd
, iHbnd
);
245 else {//End of conversion -> default to alphabet
248 // TODO: Placeholder algorithm here
249 // TODO: Add an 'end of conversion' node?
250 //ACL 1/12/09 Note that this adds one to the m_iOffset of the created node
251 // (whereas code that was once here did not, but was otherwise identical...)
252 CDasherNode
*pNewNode
= m_pMgr
->m_pNCManager
->GetAlphabetManager()->GetRoot(this, false, offset() + 1);
253 pNewNode
->Reparent(this, 0, CDasherModel::NORMALIZATION
);
257 int CConversionManager::CConvNode::ExpectedNumChildren() {
258 if(bisRoot
&& !pSCENode
) mgr()->BuildTree(this);
259 if (pSCENode
&& !pSCENode
->GetChildren().empty()) return pSCENode
->GetChildren().size();
260 return 1;//Alphabet root
263 void CConversionManager::BuildTree(CConvNode
*pRoot
) {
264 // Build the string to convert.
265 std::string strCurrentString
;
266 // Search backwards but stop at any conversion node.
267 for (CDasherNode
*pNode
= pRoot
->Parent();
268 pNode
&& pNode
->mgr() == this;
269 pNode
= pNode
->Parent()) {
271 // TODO: Need to make this the edit text rather than the display text
273 m_pAlphabet
->GetText(pNode
->GetAlphSymbol())
276 // Handle/store the result.
278 Convert(strCurrentString
, &pStartTemp
);
280 // Store all conversion trees (SCENode trees) in the pUserData->pSCENode
281 // of each Conversion Root.
283 pRoot
->pSCENode
= pStartTemp
;
286 void CConversionManager::CConvNode::SetFlag(int iFlag
, bool bValue
) {
287 CDasherNode::SetFlag(iFlag
, bValue
);
295 symbol s
=pSCENode
->Symbol
;
299 mgr()->m_pLanguageModel
->LearnSymbol(mgr()->m_iLearnContext
, s
);