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
[ Top ] |