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

Parenthesis.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 //                                                                   //
00031 
00032 
00033 
00034 // optimization for GCC compiler
00035 #ifdef __GNUG__
00036 #pragma implementation "Parenthesis.h"
00037 #endif
00038 
00039 // includes
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042     #pragma hdrstop
00043 #endif
00044 
00045 #ifndef mcPRECOMP
00046     #include <wx/dcscreen.h>
00047     #include "mc/Parenthesis.h"
00048  #include "mc/Monomial.h"
00049 #endif
00050 
00051 
00052 
00053 mcIMPLEMENT_MAIN_CLASS(mcParenthesis, mcDecoration);
00054 
00055 
00056 // global objects
00057 mcParenthesis mcEmptyParenthesis(NULL);
00058 
00059 
00060 
00061 
00062 // ----------------------------------------
00063 // mcPARENTHESISDATA
00064 // ----------------------------------------
00065 void mcParenthesisHelpers::data_OnNeighborChange()
00066 { 
00067  if (mcMathCore::Get()->isGUIEnabled())
00068   gui_RebuildFont(); 
00069 }
00070 
00071 
00072 // ----------------------------------------
00073 // mcPARENTHESISGUI
00074 // ----------------------------------------
00075 
00076 void mcParenthesisHelpers::gui_DoRecalcSize()
00077 {
00078  wxScreenDC dc;
00079 
00080  // using our special font, get the size of our symbol...
00081  dc.SetFont(mgui_fLastFont);
00082  mgui_sz = gui_GetSizeOf(&dc, data_GetSymbol());
00083 
00084  // ...and add the spaces defined in mcBracketGUI
00085  mgui_sz.SetHeight(mgui_sz.GetHeight()+mcBracketHelpers::sgui_nSpaceAboveBelow*2);
00086  mgui_sz.SetWidth(mgui_sz.GetWidth()+mcBracketHelpers::sgui_nSpaceLeftRight*2);
00087 }
00088 
00089 void mcParenthesisHelpers::gui_RebuildFont()
00090 {
00091  wxString tmp;
00092  wxScreenDC dc;
00093 
00094  // this will be our minimum height
00095  int h = gui_GetHeightOfChar(&dc, this);
00096 
00097  // now, try to find the best height...
00098  h = mcMAX(h, gui_GetMaxHeightToNextBracket(!data_isLeftBracket()));
00099  
00100  // if required, update our font...
00101  if (h != mgui_sz.GetHeight()) {
00102 
00103   mgui_fLastFont = mcBracketHelpers::gui_RebuildFont(this, h);
00104   gui_RecalcSize();
00105   
00106   // if required, notify to the parent that we have changed size,
00107   // forcing its resizing...
00108   //hlp()->RecalcParentSize();
00109   //mcASSERT(0, "");
00110  }
00111 }
00112 
00113 int mcParenthesisHelpers::gui_Draw(wxDC &hDC, int Offsetx, int Offsety, long flags, const wxPoint &pt) const
00114 {
00115  // this piece of code would require that everything is updated each
00116  // time the cursor is moved: this would create flickering...
00117 #if 0
00118  // highlight this parenthesis if it has the focus...
00119  mcElement p = hlp()->GetParent();
00120  if (p && p.data_GetType() == mcET_MONOMIAL) {
00121   if (((mcMonomial &)p).gui_isCursorOn(hlp())) {
00122 
00123    // as highlighting, use a -filled rounded rect
00124    hDC.SetBrush(*wxCYAN_BRUSH);
00125    hDC.gui_DrawRoundedRectangle(Offsetx, Offsety, gui_GetWidth(), gui_GetHeight(), 2);
00126   }
00127  }
00128 #endif
00129 
00130  // draw the bracket... we cannot use the std font to print '('
00131  // or ')', because the contained expression can be taller or
00132  // shorter than the normal font height...
00133  gui_SelectStyle(hDC);
00134  hDC.SetFont(mgui_fLastFont);
00135  hDC.DrawText(data_GetSymbol(), Offsetx, Offsety);
00136 
00137  return data_GetID();
00138 }
00139 
00140 mcInputRes mcParenthesisHelpers::gui_Input(const mcKey &key, mcElement *pnew)
00141 {
00142  wxChar c = (wxChar)key.GetKeyCode();
00143  
00144  // intercept the creation character...
00145  if (!data_hasProperty(mcEP_INITIALIZED)) {
00146   if (mcBracketHelpers::sgui_strLeftParentheses.Contains(c)) {
00147    
00148    // set this as a LEFT parenthesis
00149    mdata_bLeftBracket = TRUE;
00150    
00151   } else if (mcBracketHelpers::sgui_strRightParentheses.Contains(c)) {
00152    
00153    // set this as a RIGHT parenthesis
00154    mdata_bLeftBracket = FALSE;
00155 
00156   } else {
00157    
00158    mcASSERT(0, wxT("Which creation char did we receive ?"));
00159   }
00160 
00161   // now, notify to the polynomial parent that we were added into
00162   // one of its monomials...
00163 /*  mcElement parent1 = hlp()->GetParent();
00164   if (parent1 && parent1.data_GetType() == mcET_MONOMIAL) {
00165   
00166    mcElement parent2 = parent1.GetParent();
00167    if (parent2 && parent2.data_GetType() == mcET_POLYNOMIAL) {
00168 
00169     // ok, we can proceed
00170     ((mcPolynomial*)parent2).gui_
00171      OnNewParenthesis(data_isLeftBracket());
00172    }
00173   }*/
00174   
00175   data_AddProperty(mcEP_INITIALIZED);
00176   gui_RecalcSize();
00177  }
00178 
00179  // handle the input as all other decorations... 
00180  return mcDecorationHelpers::gui_Input(key, pnew);
00181 }
00182 
00183 
00184 
00185 // these macros are used to avoid the repetition of the same code
00186 // in the following functions...
00187 // these macros are able to walk the given mcElementArray both
00188 // going forward and backward, starting from the given index.
00189 
00190 #define START_ARRAY_SCAN(backward, arr, idx)     \
00191  {  /* this is the scope of wxT("max") and wxT("i") */   \
00192   int max = (backward ? 0 : arr.data_GetCount()); \
00193   int i=idx;            \
00194   while (1) {            \
00195    if (backward && i < max)       \
00196     break;           \
00197    if (!backward && i >= max)       \
00198     break;           \
00199    mcElement curr = arr.data_Get(i);
00200 
00201 
00202 #define END_ARRAY_SCAN(backward)        \
00203    if (!backward) i++;  /* go forward */   \
00204    else i--;  /* go backward */     \
00205   }              \
00206  }
00207 
00208 
00209 int mcParenthesisHelpers::gui_GetMaxHeightToNextBracket(bool left)
00210 {
00211  return 50;
00212 /* mcElement parent = hlp()->GetParent();
00213  int h = 0;
00214 
00215  if (parent && parent.data_GetType() == mcET_MONOMIAL) {
00216 
00217   mcMonomial &m = (mcMonomial*)parent;
00218 
00219   // we must adapt our size to the element placed on the right
00220   int idx = m.data_GetIndexOf(hlp());
00221   mcASSERT(idx != -1, 
00222    wxT("This element MUST be a children of the monomial..."));  
00223   
00224   // check the following members of this monomial...
00225   if (SearchInMonomial(m, &h, left, (left ? idx-1 : idx+1)))
00226    return h;
00227   
00228   // now check the members of the following monomials...
00229   if (m.GetParent() && m.GetParent().data_GetType() == mcET_POLYNOMIAL) {
00230 
00231    mcPolynomial &p = (mcPolynomial &)m.GetParent();
00232    int idx = p.data_GetIndexOf(m);
00233    mcASSERT(idx != -1, 
00234     wxT("The monomial MUST be a children of this polynomial..."));
00235 
00236    START_ARRAY_SCAN(left, p, (left ? idx-1 : idx+1))
00237 
00238     if (curr.data_GetType() == mcET_MONOMIAL) {
00239      
00240      mcMonomial &mm = (mcMonomial &)p.data_Get(i);
00241      if (SearchInMonomial(mm, &h, left, 0))
00242       return h;
00243      
00244      // while parsing all the elements which follow this parenthesis,
00245      // also register the height of the tallest element we found..
00246      h = mcMAX(h, curr.gui_GetHeight());
00247     }
00248 
00249    END_ARRAY_SCAN(left)
00250   }
00251  }
00252    
00253  return h;*/
00254 }
00255 
00256 bool mcParenthesisHelpers::gui_SearchInMonomial(mcMonomial &m, int *h, bool left, int idx)
00257 {
00258  START_ARRAY_SCAN(left, m, idx)
00259 
00260   if (curr.data_GetType() == mcET_PARENTHESIS) {
00261    
00262    // ok, we have found another parenthesis in the same monomial
00263    // which contains this one...
00264    if (mcParenthesis(curr).data_isLeftBracket() == left)
00265     return TRUE;
00266   }
00267   
00268   // while parsing all the elements which follow this parenthesis,
00269   // also register the height of the tallest element we found..
00270   if (h) *h = mcMAX(*h, curr.gui_GetHeight());
00271 
00272  END_ARRAY_SCAN(left)
00273 
00274  return FALSE;
00275 }
00276 /*
00277 wxString mcParenthesisHelpers::data_GetSymbol() const
00278 {
00279  if (data_isLeftBracket())
00280   return wxT("(");
00281  return wxT(")");
00282 }*/
00283 
00284 
00285 
00286 
00287 // ----------------------------------------
00288 // mcPARENTHESISIO
00289 // ----------------------------------------
00290 
00291 bool mcParenthesisHelpers::io_isBeginChar(const wxString &str) const
00292 { 
00293  if (mcBracketHelpers::sgui_bCreateBothSymbols)
00294   return FALSE;  // build only mcBrackets 
00295 
00296  // build a mcParenthesis (it will be eventually replaced by a mcBracket later)
00297  wxChar c = str.GetChar(0);
00298  if (mcBracketHelpers::gui_isLeftParenthesis(c) || 
00299   mcBracketHelpers::gui_isRightParenthesis(c))
00300   return TRUE;
00301 
00302  return FALSE;
00303 }
00304 
00305 bool mcParenthesisHelpers::io_ImportInlinedExpr(const wxString &str, int *count, wxString &pErr)
00306 {
00307  wxChar c = str.GetChar(0);
00308 
00309  if (mcBracketHelpers::sgui_strLeftParentheses.Contains(c)) {
00310   
00311   // set this as a LEFT parenthesis
00312   mdata_bLeftBracket = TRUE;
00313   
00314  } else if (mcBracketHelpers::sgui_strRightParentheses.Contains(c)) {
00315   
00316   // set this as a RIGHT parenthesis
00317   mdata_bLeftBracket = FALSE;
00318 
00319   // dow we have to import an exponent ?
00320   if (str.GetChar(1) == wxT('^')) {
00321 
00322    wxString exp(str.Right(str.Len()-1));
00323    mcExpElementHelpers::io_GetExpSubInlinedToken(exp);
00324 
00325    // import the exponent
00326    //mcSAFE_DELETE(mdata_pTmpExp);
00327    mdata_pTmpExp.data_DeleteAll();
00328    if (!mdata_pTmpExp.io_ImportInlinedExpr(exp, count, pErr))
00329     return FALSE;
00330 
00331    // return here
00332    *count += 2;  // this is required for ")^"
00333    return TRUE;
00334   }
00335 
00336  } else {
00337   
00338   mcASSERT(0, wxT("Error in mcParenthesisHelpers::io_isBeginChar"));
00339  }
00340 
00341  *count = 1;
00342  return TRUE;
00343 }
00344 
00345 
00346 


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

[ Top ]