00001 00002 // MathCore = a WYSIWYG equation editor + a powerful math engine // 00003 // Copyright (C) 2003 by Francesco Montorsi // 00004 // // 00005 // This library is free software; you can redistribute it and/or // 00006 // modify it under the terms of the GNU Lesser General Public // 00007 // License as published by the Free Software Foundation; either // 00008 // version 2.1 of the License, or (at your option) any later // 00009 // version. // 00010 // // 00011 // This library is distributed in the hope that it will be useful, // 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00014 // GNU Lesser General Public License for more details. // 00015 // // 00016 // You should have received a copy of the GNU Lesser General Public // 00017 // License along with this program; if not, write to the Free // 00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, // 00019 // MA 02111-1307, USA. // 00020 // // 00021 // For any comment, suggestion or feature request, please contact // 00022 // the administrator of the project at frm@users.sourceforge.net // 00023 // // 00030 00031 00032 00033 // optimization for GCC compiler 00034 #ifdef __GNUG__ 00035 #pragma implementation "MathSystem.h" 00036 #endif 00037 00038 // includes 00039 #include "mc/mcprec.h" 00040 #ifdef __BORLANDC__ 00041 #pragma hdrstop 00042 #endif 00043 00044 #ifndef mcPRECOMP 00045 #include <wx/dcscreen.h> 00046 #include "mc/MathCore.h" 00047 #include "mc/Text.h" 00048 #include "mc/MathLine.h" 00049 #include "mc/MathSystem.h" 00050 #endif 00051 00052 #include <wx/tokenzr.h> // not included in wx.h 00053 00054 00055 00056 // global objects 00057 mcMathSystem mcEmptySystem; 00058 00059 00060 00061 // -------------------------------- 00062 // mcMATHSYSTEMDATA 00063 // -------------------------------- 00064 00065 #ifdef __MCDEBUG__ 00066 00067 void mcMathSystemHelpers::data_Check() const 00068 { mcAbstractArray::data_Check(); } 00069 00070 #endif 00071 00072 void mcMathSystemHelpers::data_DeepCopy(const mcElementHelpers *p) 00073 { 00074 const mcMathSystemHelpers *ms = (const mcMathSystemHelpers *)p; 00075 00076 // copy all the lines contained 00077 mcAbstractArray::data_DeepCopy(*ms); 00078 00079 // copy all other simple variables 00080 mgui_fLastFont = ms->mgui_fLastFont; 00081 mgui_szSymbol = ms->mgui_szSymbol; 00082 mgui_nSel = ms->mgui_nSel; 00083 mgui_nLastActive = ms->mgui_nLastActive; 00084 mgui_nCurrentActive = ms->mgui_nCurrentActive; 00085 } 00086 00087 /* 00088 void mcMathAndSystem::data_OnArrayChange() 00089 { 00090 if (!mcMathCore::isOk() || !mcMathCore::Get()->isGUIEnabled()) 00091 return; 00092 00093 // update gui 00094 gui_UpdateSystemSym(); 00095 gui_CheckSelLineIdx(); 00096 }*/ 00097 00098 00099 00100 00101 // -------------------------------- 00102 // mcMATHSYSTEMGUI 00103 // -------------------------------- 00104 00105 // mcMATHSYSTEM rendering system (for the horizontal orientation): 00106 // ________________________________________ 00107 // ! ! <- a 00108 // ! .----. .----. .----. ! 00109 // ! |0 | .------. |1 | .------. |2 | ! 00110 // ! | | |or/and| | | |or/and| | | ! 00111 // ! ·----· ·------· ·----· ·------· ·----· ! 00112 // !l______x________x______x________x______l! <- a 00113 // 00114 // where the columns marked with 00115 // "x" stay for the value returned by gui_GetSpaceBetween() 00116 // "l" stay for the value returned by gui_GetSpaceLeftRight() 00117 // and the rows marked with 00118 // "a" stay for the value returned by gui_GetSpaceAboveBelow() 00119 // and the boxes number from 0 to n, are of a variable width, 00120 // and the OR/AND boxes are all of the same size (gui_GetSymbolSize()) 00121 00122 int mcMathSystemHelpers::gui_GetXOf(int n) const 00123 { 00124 if (gui_DrawHorizontally()) { 00125 00126 // since we are drawn with horizontal horientation, 00127 // we need to take in count the size of all previous elements... 00128 // the size of the symbols among them and the space to leave 00129 // between them: 00130 int x = gui_GetSpaceLeftRight(); 00131 for (int i=0; i<n; i++) 00132 x += data_Get(i).gui_GetWidth()+ 00133 gui_GetSymbolSize().GetWidth()+gui_GetSpaceBetween()*2; 00134 return x; 00135 } 00136 00137 // we don't need to add gui_GetSpaceLeftRight() because it should 00138 // have been already counted in gui_GetWidth()... 00139 return (gui_GetWidth()-data_Get(n).gui_GetWidth())/2; 00140 } 00141 00142 int mcMathSystemHelpers::gui_GetYOf(int n) const 00143 { 00144 if (gui_DrawVertically()) { 00145 00146 // since we are NOT drawn with horizontal horientation, 00147 // we need to take in count the size of all previous elements... 00148 // the size of the symbols among them and the space to leave 00149 // between them: 00150 int x = gui_GetSpaceAboveBelow(); 00151 for (int i=0; i<n; i++) 00152 x += data_Get(i).gui_GetHeight()+ 00153 gui_GetSymbolSize().GetHeight()+gui_GetSpaceBetween()*2; 00154 return x; 00155 } 00156 00157 // we don't need to add gui_GetSpaceLeftRight() because it should 00158 // have been already counted in gui_GetWidth()... 00159 return (gui_GetHeight()-data_Get(n).gui_GetHeight())/2; 00160 } 00161 00162 int mcMathSystemHelpers::gui_GetYOfSymbol(int n) const 00163 { 00164 // if we need the Y for the n-th connector symbol, 00165 // then we need to add to the Y for the n-th element 00166 // the n-th element's height and the space between constant... 00167 if (gui_DrawVertically()) 00168 return gui_GetYOf(n)+data_Get(n).gui_GetHeight()+gui_GetSpaceBetween(); 00169 00170 // center the symbol into this array... 00171 return (gui_GetHeight()-gui_GetSymbolSize().GetHeight())/2; 00172 } 00173 00174 int mcMathSystemHelpers::gui_GetXOfSymbol(int n) const 00175 { 00176 // if we need the X for the n-th connector symbol, 00177 // then we need to add to the X for the n-th element 00178 // the n-th element's width and the space between constant... 00179 if (gui_DrawHorizontally()) 00180 return gui_GetXOf(n)+data_Get(n).gui_GetWidth()+gui_GetSpaceBetween(); 00181 00182 // center the symbol into this array... 00183 return (gui_GetWidth()-gui_GetSymbolSize().GetWidth())/2; 00184 } 00185 00186 int mcMathSystemHelpers::gui_Draw(wxDC &dc, int x, int y, long flags, const wxPoint &p) const 00187 { 00188 // first of all, draw the symbols of the system... 00189 gui_DrawSystemSymbols(dc, x, y, flags); 00190 00191 // now, just draw the elements contained at their positions... 00192 int ret = mcDRW_NOACTIVEELEM; 00193 for (int i=0; i<data_GetCount(); i++) { 00194 00195 // we just need to offset with (x; y) the rect returned 00196 // by #gui_GetRectOf because it already took in count 00197 // the space left/right and above/below... 00198 wxRect rc(gui_GetRectOf(i)); 00199 rc.Offset(x, y); 00200 00201 if (rc.Inside(p)) { 00202 00203 ret = data_Get(i).gui_Draw(dc, rc.x, rc.y, flags, p); 00204 00205 } else { 00206 00207 // force the bmp update without caring about the point 00208 data_Get(i).gui_Draw(dc, rc.x, rc.y, flags & ~mcDRW_USEPOINT, p); 00209 } 00210 } 00211 00212 #ifdef mcMATHSYSTEM_DRAW_BOUNDINGBOX 00213 dc.SetBrush(*wxTRANSPARENT_BRUSH); 00214 dc.DrawRectangle(x, y, gui_GetWidth(), gui_GetHeight()); 00215 #endif 00216 00217 return ret; 00218 } 00219 00220 int mcMathSystemHelpers::gui_DrawBmp(wxDC &dc, int x, int y) const 00221 { 00222 gui_DrawSystemSymbols(dc, x, y, 0); 00223 00224 for (int i=0; i<data_GetCount(); i++) 00225 gui_Get(i)->gui_DrawBmp(dc, x+gui_GetXOf(i), y+gui_GetYOf(i)); 00226 00227 #ifdef mcMATHSYSTEM_DRAW_BOUNDINGBOX 00228 dc.SetBrush(*wxTRANSPARENT_BRUSH); 00229 dc.DrawRectangle(x, y, gui_GetWidth(), gui_GetHeight()); 00230 #endif 00231 return mcDRW_NOACTIVEELEM; 00232 } 00233 00234 int mcMathSystemHelpers::gui_ForceBmpUpdate(int x, int y, long flags, const wxPoint &p) 00235 { 00236 if (!(flags & mcDRW_USEPOINT)) { 00237 00238 // just propagate the call to the elements contained recursively... 00239 // we can safely ignore the given point's coordinates because 00240 // "flags" does not contain mcDRW_USEPOINT 00241 for (int j=0; j<data_GetCount(); j++) 00242 gui_Get(j)->gui_ForceBmpUpdate(x+gui_GetXOf(j), y+gui_GetYOf(j), flags, p); 00243 return mcDRW_NOACTIVEELEM; 00244 } 00245 00246 // we need to care about point coordinates... 00247 int ret = mcDRW_NOACTIVEELEM; 00248 for (int i=0; i<data_GetCount(); i++) { 00249 00250 // we just need to offset with (x; y) the rect returned 00251 // by #gui_GetRectOf because it already took in count 00252 // the space left/right and above/below... 00253 wxRect rc(gui_GetRectOf(i)); 00254 rc.Offset(x, y); 00255 00256 if (rc.Inside(p)) { 00257 00258 ret = gui_Get(i)->gui_ForceBmpUpdate(rc.x, rc.y, flags, p); 00259 00260 } else { 00261 00262 // force the bmp update without caring about the point 00263 gui_Get(i)->gui_ForceBmpUpdate(rc.x, rc.y, flags & ~mcDRW_USEPOINT, p); 00264 } 00265 } 00266 00267 return ret; 00268 } 00269 00270 int mcMathSystemHelpers::gui_UpdateBmp(int x, int y, long flags, const wxPoint &p) 00271 { 00272 if (!(flags & mcDRW_USEPOINT)) { 00273 00274 // since we don't have to care about the given point, update the selected line 00275 gui_Get(mgui_nSel)->gui_UpdateBmp(x+gui_GetXOf(mgui_nSel), 00276 y+gui_GetYOf(mgui_nSel), flags, p); 00277 return mcDRW_NOACTIVEELEM; 00278 } 00279 00280 // the user has given us a valid pointer... we must update 00281 // only that line containing the given point. 00282 wxPoint pt(p); 00283 00284 // translate absolute coord to relative coord 00285 pt.x -= x; 00286 pt.y -= y; 00287 00288 int nline = gui_GetElemContaining(pt); 00289 if (nline == -1) { 00290 00291 // we should draw everything as non-active 00292 //for (int i=0; i<data_GetCount(); i++) 00293 // gui_Get(i)->gui_UpdateBmp(0, 0, mcDRW_NONACTIVE, p); 00294 mgui_nLastActive = mgui_nCurrentActive; 00295 mgui_nCurrentActive = -1; 00296 00297 if (mgui_nLastActive != -1) 00298 gui_Get(mgui_nLastActive)->gui_UpdateBmp(0, 0, mcDRW_NONACTIVE, p); 00299 00300 return mcDRW_NOACTIVEELEM; // no element containing that point ! 00301 } 00302 00303 // save the last active line 00304 mgui_nLastActive = mgui_nCurrentActive; 00305 mgui_nCurrentActive = nline; 00306 00307 // update the active elem 00308 return gui_Get(nline)->gui_UpdateBmp(x+gui_GetXOf(nline), y+gui_GetYOf(nline), flags, p); 00309 } 00310 00311 bool mcMathSystemHelpers::gui_NeedsRefresh() const 00312 { 00313 // check if something changed... 00314 if (mgui_nCurrentActive == mgui_nLastActive) { 00315 00316 // if the last active line as still the same active element, 00317 // then the ID has not changed... 00318 if (mgui_nCurrentActive != -1) 00319 return gui_Get(mgui_nCurrentActive)->gui_NeedsRefresh(); 00320 return FALSE; 00321 } 00322 00323 return TRUE; 00324 } 00325 00326 void mcMathSystemHelpers::gui_SetMask(const wxColour &col) 00327 { 00328 // just update the masks of all our elements... 00329 for (int i=0; i<data_GetCount(); i++) 00330 gui_Get(i)->gui_SetMask(col); 00331 } 00332 00333 void mcMathSystemHelpers::gui_SetBmpBackgroundBrush(const wxBrush &br) 00334 { 00335 // just update the brushes of all our elements... 00336 for (int i=0; i<data_GetCount(); i++) 00337 gui_Get(i)->gui_SetBmpBackgroundBrush(br); 00338 } 00339 00340 /*{ 00341 if (!mcMathCore::Get()->isGUIEnabled() || 00342 data_GetCount() == 0) 00343 return; 00344 00345 wxScreenDC dc; 00346 int w, h; 00347 00348 // update the font used to draw the system symbol 00349 // (we added a new math line => height change of the system) 00350 const mcTextSettings *p = gui_GetStyle(0)->GetTextSettingsFor(mcET_ADDOP); 00351 mgui_fLastFont.SetFaceName(p->m_hFont.GetFaceName()); 00352 mgui_fLastFont.SetPointSize((int)mcElementHelpers::gui_Pixels2PointSize(gui_GetContentHeight())); 00353 mgui_fLastFont.SetWeight(wxLIGHT); 00354 00355 // update the font & the font size 00356 dc.SetFont(mgui_fLastFont); 00357 dc.GetTextExtent(wxT("{"), &w, &h); 00358 mgui_szSymbol.SetWidth(w); 00359 mgui_szSymbol.SetHeight(h); 00360 }*/ 00361 00362 void mcMathSystemHelpers::gui_SetCursorPos(const mcCursorPos &cp) 00363 { 00364 if (cp.isBegin()) 00365 mgui_nSel = 0; 00366 else if (cp.isEnd()) 00367 mgui_nSel = data_GetCount()-1; 00368 else 00369 mgui_nSel = cp.gui_Last();//mcASSERT(0, "Invalid cursor position"); 00370 00371 // always update also the line recursively 00372 mcCursorPos tmp(cp); 00373 tmp.gui_Pop(); 00374 gui_GetFocus().gui_SetCursorPos(tmp); 00375 } 00376 00377 void mcMathSystemHelpers::gui_GetCursorPos(mcCursorPos &cp) const 00378 { 00379 if (mgui_nSel == 0 && data_Get(0).gui_GetCursorPos().isBegin()) 00380 cp.gui_Push(mcCP_BEGIN); 00381 else if (mgui_nSel == data_GetCount()-1 && data_GetLast().gui_GetCursorPos().isEnd()) 00382 cp.gui_Push(mcCP_END); 00383 00384 cp.gui_Push(mgui_nSel); 00385 data_Get(mgui_nSel).gui_GetCursorPos(cp); 00386 } 00387 00388 mcInputRes mcMathSystemHelpers::gui_Input(const mcKey &ev, mcElement *newelem) 00389 { 00390 // just drop GUI input to the line which has the keyboard focus... 00391 mcInputRes r = gui_GetFocus().gui_Input(ev, newelem); 00392 00393 gui_RecalcSize(); 00394 return r; 00395 } 00396 00397 mcInsertRes mcMathSystemHelpers::gui_Insert(const mcElement &toinsert, mcElement *newelem) 00398 { 00399 gui_GetFocus().gui_Insert(toinsert, NULL); 00400 00401 gui_RecalcSize(); 00402 return mcINSR_OKAY; 00403 } 00404 00405 void mcMathSystemHelpers::gui_DoRecalcSize() 00406 { 00407 // the space left/right, above/below must be left 00408 // not only before the leftmost/abovemost element but 00409 // also at the end of the rightmost/bottommost element 00410 mgui_sz.Set(gui_GetSpaceLeftRight()*2, gui_GetSpaceAboveBelow()*2); 00411 00412 for (int i=0; i<data_GetCount(); i++) { 00413 00414 // if this is the 2nd, 3rd, n-th element, then there 00415 // is a connector symbol placed before it which has 00416 // a width and an height, too... 00417 if (i > 0) { 00418 00419 if (gui_DrawHorizontally()) 00420 mgui_sz.SetWidth(mgui_sz.GetWidth()+gui_GetSymbolSize().GetWidth()+ 00421 gui_GetSpaceBetween()*2); 00422 else 00423 mgui_sz.SetHeight(mgui_sz.GetHeight()+gui_GetSymbolSize().GetHeight()+ 00424 gui_GetSpaceBetween()*2); 00425 } 00426 00427 if (gui_DrawHorizontally()) 00428 mgui_sz.Set(mgui_sz.GetWidth()+data_Get(i).gui_GetWidth(), 00429 mcMAX(mgui_sz.GetHeight(), data_Get(i).gui_GetHeight())); 00430 else 00431 mgui_sz.Set(mcMAX(mgui_sz.GetWidth(), data_Get(i).gui_GetWidth()), 00432 mgui_sz.GetHeight()+data_Get(i).gui_GetHeight()); 00433 } 00434 00435 if (gui_DrawHorizontally()) 00436 mgui_sz.SetHeight(mgui_sz.GetHeight()+gui_GetSpaceAboveBelow()*2); 00437 else 00438 mgui_sz.SetWidth(mgui_sz.GetWidth()+gui_GetSpaceLeftRight()*2); 00439 00440 // don't forget to recalculate symbol size 00441 gui_RecalcSymbolSize(); 00442 } 00443 00444 void mcMathSystemHelpers::gui_CheckSelLineIdx() 00445 { 00446 // adjust the selected line index if it's wrong 00447 if (mgui_nSel < 0) mgui_nSel = 0; 00448 if (mgui_nSel >= data_GetCount()) mgui_nSel = data_GetCount()-1; 00449 00450 // if the array is empty, the index will be set to -1 00451 } 00452 00453 wxRect mcMathSystemHelpers::gui_GetRectOf(int n) const 00454 { 00455 // using simpler functions, it's not a problem to code such a function !!! 00456 return wxRect(gui_GetXOf(n), gui_GetYOf(n), 00457 data_Get(n).gui_GetWidth(), data_Get(n).gui_GetHeight()); 00458 } 00459 /* 00460 mcElement &mcMathSystemHelpers::gui_GetActiveElem(int x, int y, const wxPoint &pt) 00461 { 00462 for (int i=0; i < data_GetCount(); i++) { 00463 00464 // create the bounding box of this line 00465 wxRect rc(x+gui_GetLineXPos(i), y+gui_GetLineYPos(i), 00466 data_Get(i).gui_GetWidth(), data_Get(i).gui_GetHeight()); 00467 00468 // then check if it contains the given point 00469 if (rc.Inside(pt)) 00470 return data_Get(i).gui_GetActiveElem(rc.x, rc.y, pt); 00471 } 00472 00473 return mcEmptyElement; 00474 } 00475 */ 00476 00477 void mcMathSystemHelpers::gui_OnSelect(wxDC &dc, wxRect &rc) 00478 { 00479 // remove old selection 00480 gui_DeSelect(); 00481 00482 // create new 00483 for (int i=0; i<data_GetCount(); i++) { 00484 wxRect irc(gui_GetRectOf(i)); 00485 00486 if (irc.Intersects(rc)) { 00487 00488 rc.Offset(-irc.x, -irc.y); 00489 gui_SetFocusIdx(i); 00490 gui_GetFocus().gui_OnSelect(dc, rc); 00491 break; 00492 } 00493 } 00494 00495 // mark also ourselves as selected if we contain 00496 // something which is selected... 00497 if (gui_GetFocus().gui_isSelected()) 00498 gui_Select(); 00499 } 00500 00501 int mcMathSystemHelpers::gui_GetRelCursorPos(wxDC &dc, wxPoint *p) const 00502 { 00503 int ret = gui_GetFocus().gui_GetRelCursorPos(dc, p); 00504 00505 p->x += gui_GetXOf(gui_GetFocusIdx()); 00506 p->y += gui_GetYOf(gui_GetFocusIdx()); 00507 return ret; 00508 } 00509 00510 wxPoint mcMathSystemHelpers::gui_GetRelCursorPos(wxDC &dc, int x, int y, int *height) const 00511 { 00512 wxPoint pt; 00513 00514 int h = gui_GetFocus().gui_GetRelCursorPos(dc, &pt); 00515 pt.x += x+gui_GetXOf(gui_GetFocusIdx()); 00516 pt.y += y+gui_GetYOf(gui_GetFocusIdx()); 00517 if (height) *height = h; 00518 00519 return pt; 00520 } 00521 00522 mcMoveCursorRes mcMathSystemHelpers::gui_MoveCursor(mcMoveCursorFlag flag, long modifiers) 00523 { 00524 mcMoveCursorRes res = gui_GetFocus().gui_MoveCursor(flag, modifiers); 00525 00526 // handle the possible return codes 00527 switch (res) { 00528 case mcMCR_SETFOCUS_ABOVE: 00529 if (mgui_nSel > 0) { 00530 00531 // select previous line and return a success code 00532 mgui_nSel--; 00533 return mcMCR_OKAY; 00534 } 00535 break; 00536 00537 case mcMCR_SETFOCUS_BELOW: 00538 if (mgui_nSel < data_GetCount()-1) { 00539 00540 // select previous line and return a success code 00541 mgui_nSel++; 00542 return mcMCR_OKAY; 00543 } 00544 break; 00545 00546 case mcMCR_OKAY: 00547 case mcMCR_SETFOCUS_PREVIOUS: 00548 case mcMCR_SETFOCUS_NEXT: 00549 case mcMCR_CANNOT_SETFOCUS: 00550 break; 00551 } 00552 00553 return res; 00554 } 00555 00556 int mcMathSystemHelpers::gui_MoveCursorUsingPoint(wxDC &dc, const wxPoint &pos) 00557 { 00558 mcGUILOG(wxT("mcMathSystemHelpers::gui_MoveCursorUsingPoint - moving to [%d;%d]"), pos.x, pos.y); 00559 int idx = gui_GetElemContaining(pos); 00560 00561 // an invalid point ? 00562 if (idx < 0 || idx >= data_GetCount()) 00563 return mcMCR_CANNOT_SETFOCUS; 00564 00565 // adjust point's coords 00566 wxPoint pt(pos); 00567 pt.x -= gui_GetXOf(idx); 00568 pt.y -= gui_GetYOf(idx); 00569 00570 // update selected line & move the cursor 00571 gui_SetFocusIdx(idx); 00572 return gui_GetFocus().gui_MoveCursorUsingPoint(dc, pt); 00573 } 00574 00575 wxBitmap mcMathSystemHelpers::gui_GetBmp() const 00576 { 00577 // do not allocate a wxBitmap through the new() function since 00578 // wxBitmap just contains a pointer to data which is copied 00579 // on function exit (a very fast operation !) 00580 wxBitmap result(gui_GetWidth(), gui_GetHeight(), -1); 00581 wxMemoryDC dc; 00582 00583 dc.SelectObject(result); 00584 gui_Draw(dc, 0, 0, mcDRW_NOFLAGS, wxPoint(-1,-1)); 00585 dc.SelectObject(wxNullBitmap); 00586 00587 return result; 00588 } 00589 00590 int mcMathSystemHelpers::gui_GetElemContaining(const wxPoint &pt) const 00591 { 00592 for (int i=0; i<data_GetCount(); i++) { 00593 00594 // just check which bounding box contains the given point 00595 wxRect rc(gui_GetRectOf(i)); 00596 if (rc.Inside(pt)) 00597 return i; 00598 } 00599 00600 return -1; // not found 00601 } 00602 00603 void mcMathSystemHelpers::gui_UpdateExpDepth() 00604 { 00605 // the call to mcElementHelpers::gui_SetExpDepth 00606 // will automatically: 00607 // 1) update the exponent depth of all children of our 00608 // children 00609 // 2) recalc the size of all the elements 00610 for (int i=0; i<data_GetCount(); i++) 00611 data_Get(i).gui_SetExpDepth(0); 00612 00613 // we must call the base version _always_ 00614 mcElementHelpers::gui_UpdateExpDepth(); 00615 } 00616 00617 wxString mcMathSystemHelpers::gui_GetSelInlinedExpr() const 00618 { 00619 // get the selection 00620 mcMathSystem ms(gui_GetSelection()); 00621 if (ms == mcEmptySystem) return wxEmptyString; 00622 00623 wxString str = ms.io_GetInlinedExpr(); // copy only selection.... 00624 if (ms.data_GetCount() == 1) { 00625 00626 // adjust the exported line... 00627 /*wxString sym = ms.data_GetLine(0)->GetSeparatorSymbol(FALSE); 00628 int n = str.Find(sym); 00629 00630 if (n != -1) { 00631 wxString l = str.Left(n); 00632 wxString r = str.Right(str.Len()-n-sym.Len()); 00633 00634 // remove empty members 00635 if (l == mcEmptyBoxHelpers::io_GetInlinedExprTag()) 00636 str = r; 00637 if (r == mcEmptyBoxHelpers::io_GetInlinedExprTag()) 00638 str = l; 00639 }*/ 00640 } 00641 00642 return str; 00643 } 00644 00645 00646 00647 00648 00649 // ----------------------------- 00650 // mcMATHSYSTEM - IO functions 00651 // ----------------------------- 00652 00653 wxString mcMathSystemHelpers::io_GetInlinedExpr() const 00654 { 00655 wxString res; 00656 res.Alloc(data_GetCount()*32); 00657 00658 // encode as inlined expression the entire system 00659 for (int i=0; i < data_GetCount(); i++) { 00660 00661 if (i>0) res += wxT(" ") + io_GetInlinedExprOfLogicalOperator() + wxT(" "); 00662 res += data_Get(i).io_GetInlinedExpr(); 00663 } 00664 00665 return res; 00666 } 00667 00668 wxString mcMathSystemHelpers::io_GetInlinedExprOfLogicalOperator(mcLogicOperator op, 00669 bool shortversion) const 00670 { 00671 switch (op) { 00672 case mcLO_AND: 00673 if (shortversion) 00674 return wxT("&"); 00675 return wxT("AND"); 00676 case mcLO_OR: 00677 if (shortversion) 00678 return wxT("|"); 00679 return wxT("OR"); 00680 00681 case mcLO_NOTSET: 00682 case mcLO_MAX: 00683 return wxEmptyString; 00684 } 00685 00686 return wxEmptyString; 00687 } 00688 00689 wxString mcMathSystemHelpers::io_GetInlinedExprOfAllLogicalOp() const 00690 { 00691 wxString str; 00692 00693 for (int i=0; i < mcLO_MAX; i++) 00694 str += io_GetInlinedExprOfLogicalOperator((mcLogicOperator)i); 00695 return str; 00696 } 00697 00698 wxXml2Node mcMathSystemHelpers::io_GetMathML(bool bGetPresentation) const 00699 { 00700 // with a single line to export, we don't need to 00701 if (data_GetCount() == 1) 00702 return data_Get(0).io_GetMathML(bGetPresentation); 00703 00704 // enclose all the lines we contain into an MROW tag 00705 wxXml2Node total(wxXML_ELEMENT_NODE, wxXml2EmptyNode, wxT("mrow")); 00706 for (int i=0; i < data_GetCount(); i++) { 00707 wxXml2Node tmp(data_Get(i).io_GetMathML(bGetPresentation)); 00708 total.AddChild(tmp); 00709 } 00710 00711 return total; 00712 } 00713 00714 bool mcMathSystemHelpers::io_ImportPresentationMathML(wxXml2Node pDoc, wxString &pErr) 00715 { 00716 // FIXME: by now, just import a single line 00717 data_Clear(); 00718 //data_AddEmptyLine(); 00719 00720 return data_Get(0).io_ImportPresentationMathML(pDoc, pErr); 00721 } 00722 00723 int mcMathSystemHelpers::io_FilterInlinedExpr(wxString &str) 00724 { 00725 const wxString allowed = wxT("abcdefghijklmnopqrstuvwxyz") 00726 wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZ") 00727 wxT("0123456789.,+-*/:^_<>=()[]{}"); 00728 int out = 0; 00729 00730 // scan the string removing unwanted characters 00731 for (int i=0; i < (int)str.Len(); i++) { 00732 if (!allowed.Contains(str.GetChar(i))) { 00733 00734 // remove this character 00735 str.Remove(i, 1); 00736 out++; 00737 } 00738 } 00739 00740 mcIOLOG(wxT("mcMathSystemHelpers::io_FilterInlinedExpr - filtered string: [%s] ") 00741 wxT("(%d characters filtered out)"), str.c_str(), out); 00742 return out; 00743 } 00744 00745 bool mcMathSystemHelpers::io_ImportInlinedExpr(const wxString &str, int *, wxString &perr) 00746 { 00747 mcIOLOG(wxT("mcMathSystemHelpers::io_ImportInlinedExpr - going to import [%s]"), str.c_str()); 00748 00749 // remove everything before importing 00750 data_Clear(); 00751 00752 if (str.IsEmpty()) 00753 return TRUE; // our task is complete... 00754 00755 // we have to be sure not to import something which could be 00756 // "dangerous" for our input system like strange characters... 00757 wxString toimport = str; 00758 io_FilterInlinedExpr(toimport); 00759 00760 // we'll now substitute our logical operator (AND or OR) with "#": 00761 // it is a special character which was removed by user input in the 00762 // previous step and we are now going to use as delimiter for our tokens 00763 for (int i=0; i < mcLO_MAX; i++) 00764 toimport.Replace(io_GetInlinedExprOfLogicalOperator(), wxT("#"), TRUE); 00765 00766 // break in various tokens the string to import 00767 wxStringTokenizer tkz(toimport, wxT("#")); 00768 while (tkz.HasMoreTokens()) { 00769 wxString token = tkz.GetNextToken(); 00770 00771 // trim both left & right spaces 00772 token.Trim(FALSE); 00773 token.Trim(TRUE); 00774 00775 // create a new line chaining it with the previous ones through the 00776 // operator found at the end of the previous line 00777 // NOTE: on first line, lastop will be set to mcLO_NOTSET since 00778 // no lines were imported before but this is okay: it does not 00779 // make sense setting the chain operator for the first line. 00780 if (!io_ImportToken(token, &perr)) 00781 return FALSE; 00782 } 00783 00784 data_Check(); 00785 return TRUE; 00786 } 00787 00788 00789 00790 00791 // -------------------------------- 00792 // mcMATHSYSTEMMATH 00793 // -------------------------------- 00794 /* 00795 mcMathAndSystem *mcMathAndSystem::math_Merge(const mcMathAndSystem *p) const 00796 { 00797 mcMATHLOG(wxT("mcMathAndSystem::math_Merge [%s] - merging with [%s]"), 00798 mcTXTTHIS, p->io_GetInlinedExpr().c_str()); 00799 mcMathAndSystem *res = new mcMathAndSystem(*this); 00800 00801 for (int i=0; i<p->data_GetLineCount(); i++) 00802 res->data_AddLine(new mcMathLine(*p->data_GetLine(i))); 00803 00804 mcMATHLOG(wxT("mcMathAndSystem::math_Merge - result is [%s]"), 00805 res->io_GetInlinedExpr().c_str()); 00806 return res; 00807 }*/ 00808 00809 00810 #define mcMATHSYSTEM_SIMPLE_PROPAGATION(func) \ 00811 for (int i=0; i < data_GetCount(); i++) \ 00812 data_Get(i).func; \ 00813 return mcBOR_REMOVE_OPERAND; 00814 00815 mcBasicOpRes mcMathSystemHelpers::math_MultiplyBy(const mcElement &pol, mcElement *) 00816 { mcMATHSYSTEM_SIMPLE_PROPAGATION(math_SimpleMultiplyBy(pol)); } 00817 00818 mcBasicOpRes mcMathSystemHelpers::math_DivideBy(const mcElement &pol, mcElement *) 00819 { mcMATHSYSTEM_SIMPLE_PROPAGATION(math_SimpleDivideBy(pol)); } 00820 00821 mcBasicOpRes mcMathSystemHelpers::math_Add(const mcElement &pol, mcElement *, bool add) 00822 { mcMATHSYSTEM_SIMPLE_PROPAGATION(math_SimpleAdd(pol, add)); } 00823 00824 mcBasicOpRes mcMathSystemHelpers::math_Subtract(const mcElement &pol, mcElement *) 00825 { mcMATHSYSTEM_SIMPLE_PROPAGATION(math_SimpleSubtract(pol)); } 00826 00827 mcBasicOpRes mcMathSystemHelpers::math_RaiseTo(const mcPolynomial &pol) 00828 { 00829 for (int i=0; i < data_GetCount(); i++) 00830 data_Get(i).math_SimpleRaiseTo(pol); 00831 00832 return mcBOR_REMOVE_OPERAND; 00833 } 00834 00835 bool mcMathSystemHelpers::math_Compare(const mcElement &p, long flags) const 00836 { 00837 bool res = TRUE; 00838 00839 // first of all, be sure we are of the same type 00840 if (!math_CompareThisOnly(p, flags)) 00841 return FALSE; 00842 00843 // compare each element 00844 const mcMathSystem &arr = (const mcMathSystem &)p; 00845 for (int i=0; i < data_GetCount(); i++) 00846 for (int j=0; j < arr.data_GetCount(); j++) 00847 res &= data_Get(i).math_Compare(arr.data_Get(j), flags); 00848 00849 return res; 00850 } 00851 /* 00852 mcElement mcMathSystemHelpers::math_Find(int n, const mcElement &tofind, 00853 long flags, int *pos, int *entry) const 00854 { 00855 for (int i=0; i < data_GetCount(); i++) { 00856 00857 // check if this line contains the requid occurrence... 00858 int count = data_Get(i).math_GetCountOf(tofind, flags); 00859 if (count <= n) { 00860 00861 // this line does not contain enough occurrences 00862 n -= count; 00863 } else { 00864 00865 // ok; this is the line we were searching for... 00866 if (entry) *entry = i; 00867 return data_Get(i).math_Find(n, tofind, flags, pos); 00868 } 00869 } 00870 00871 return mcEmptyElement; // not found 00872 } 00873 00874 int mcMathSystemHelpers::math_GetCountOf(const mcElement &tocount, long flags) const 00875 { 00876 int total = 0; 00877 for (int i=0; i < data_GetCount(); i++) 00878 total += data_Get(i).math_GetCountOf(tocount, flags); 00879 return total; 00880 }*/ 00881 00882 /*mcRealValue mcMathSystemHelpers::math_Evaluate() const 00883 { 00884 const mcMathLine *p = ((n == -1) ? gui_GetFocus() : data_GetLine(n)); 00885 00886 // it does not make sense to evaluate all the lines of this 00887 // system: we would get an useless set of numbers. 00888 return p->math_Evaluate(); 00889 }*/ 00890 00891 mcExpSimRes mcMathSystemHelpers::math_ExpSimAllLines(bool simp) 00892 { 00893 mcExpSimRes res, r = mcESR_DONE; 00894 long flags = mcEXPSIM_NOFLAGS; 00895 mcElement *pp = NULL; 00896 00897 // try to make a simplification step in all lines 00898 for (int i=0; i < data_GetCount(); i++) { 00899 00900 if (simp) 00901 res = data_Get(i).math_Simplify(flags, pp); 00902 else 00903 res = data_Get(i).math_Expand(flags, pp); 00904 00905 // if at least one of the line returns mcESR_NOTFINISHED 00906 // keep this result as the global result. 00907 // Same for INVALID_DATA (but this has higher priority) 00908 if (res == mcESR_NOTFINISHED && r != mcESR_INVALID_DATA) 00909 r = mcESR_NOTFINISHED; 00910 else if (res == mcESR_INVALID_DATA) 00911 r = mcESR_INVALID_DATA; 00912 } 00913 00914 return r; 00915 } 00916 00917 mcExpSimRes mcMathSystemHelpers::math_Simplify(long flags, mcElement *) 00918 { 00919 mcExpSimRes r = math_ExpSimAllLines(TRUE); 00920 00921 // TODO: what should we simplify here ? 00922 return r; 00923 } 00924 00925 mcExpSimRes mcMathSystemHelpers::math_Expand(long flags, mcElement *) 00926 { 00927 mcExpSimRes r = math_ExpSimAllLines(FALSE); 00928 00929 // TODO 00930 return r; 00931 } 00932 00933 mcRealValue mcMathSystemHelpers::math_GetLenght() const 00934 { 00935 mcMathSystemType t(math_GetMathSystemType()); 00936 00937 switch (t.m_tMath1) { 00938 case mcMSTL1_MIXED: 00939 return 2.0; // this is the most complex 00940 case mcMSTL1_INEQUALITIES: 00941 return 1.5; 00942 case mcMSTL1_EQUATIONS: 00943 return 1.0; 00944 case mcMSTL1_EXPRESSION: 00945 return 0.5; 00946 00947 case mcMSTL1_NOT_RECOGNIZED: 00948 default: 00949 // an unrecognized mathsystem type ? 00950 return -1000; 00951 } 00952 } 00953 /* 00954 int mcMathSystemHelpers::math_Replace(const mcElement &tofind, int n, long flags, 00955 const mcElement &replacement, bool bAttachChildren) 00956 { 00957 int total = 0; 00958 for (int i=0; i < data_GetCount(); i++) 00959 total += data_Get(i).math_Replace(tofind, n, flags, 00960 replacement, bAttachChildren); 00961 00962 return total; 00963 } 00964 */ 00965 00966 mcMathType mcMathSystemHelpers::math_GetMathType() const 00967 { 00968 mcMathType res(mcMTL1_POLYNOMIAL, mcMTL2_ALGEBRAIC, mcMTL3_CONSTANT); 00969 00970 // just take the math type of each line and merge it 00971 // with the type of the previous ones as if they were 00972 // all joined using a "+" 00973 for (int i=0; i < data_GetCount(); i++) 00974 res.math_Add(data_Get(i).math_GetMathType()); 00975 return res; 00976 } 00977 00978
[ Top ] |