Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

MathSystem.cpp

Go to the documentation of this file.
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 


Documentation generated with Doxygen on Sun Feb 6 17:10:47 2005
Visit MathStudio home page for more info

[ Top ]