00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00031
00032
00033
00034
00035 #ifdef __GNUG__
00036 #pragma implementation "Element.cpp"
00037 #endif
00038
00039
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042 #pragma hdrstop
00043 #endif
00044
00045 #ifndef mcPRECOMP
00046 #include <wx/dcscreen.h>
00047
00048 #include "mc/EmptyBox.h"
00049 #include "mc/Number.h"
00050 #include "mc/Bracket.h"
00051 #include "mc/Fraction.h"
00052 #include "mc/Function.h"
00053 #include "mc/Radical.h"
00054 #include "mc/Text.h"
00055 #include "mc/Symbol.h"
00056 #include "mc/Operator.h"
00057 #include "mc/AddSubOp.h"
00058 #include "mc/MultDivOp.h"
00059 #include "mc/Monomial.h"
00060 #include "mc/Parenthesis.h"
00061 #endif
00062
00063
00064
00065 wxBrush *mcElementHelpers::sgui_pSelectionBrush = NULL;
00066 wxBrush *mcElementHelpers::sgui_pActivationBrush = NULL;
00067 mcStyleArray *mcElementHelpers::sgui_pDefaultStyles = NULL;
00068 int mcElementHelpers::sgui_nAdditionalActivationSpaceLeftRight = 2;
00069 mcElement *mcElementHelpers::sdata_pElem[];
00070
00071
00072 mcElement mcEmptyElement;
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #ifdef __MCDEBUG__
00083
00084 void mcElementHelpers::data_Check() const
00085 {
00086
00087 mcASSERT(mdata_nProperties >= 0, wxT("Not valid"));
00088 mcASSERT(mdata_nID >= 0, wxT("Not valid"));
00089
00090
00091 for (int i=0,max=data_GetChildrenCount(); i < max; i++) {
00092
00093 const mcElement &tocheck = data_GetConstChild(i);
00094
00095
00096
00097
00098
00099
00100 tocheck.data_Check();
00101 }
00102 }
00103
00104 wxString mcElementHelpers::data_GetDebug(int indent, long flags) const
00105 {
00106 wxString str, tmp;
00107
00108
00109
00110
00111
00112
00113 str += wxString(wxT(' '), indent);
00114
00115
00116 if (flags & mcELEMENT_DBG_EXPDEPTH)
00117 str += wxString::Format(wxT("EXPDEPTH: %2d "), gui_GetExpDepth());
00118
00119 if (flags & mcELEMENT_DBG_SELECTION &&
00120 mcMathCore::Get()->isGUIEnabled())
00121 str += wxString::Format(wxT("SELECTED: %s "),
00122 (gui_isSelected() ? wxT("YES") : wxT("NO ")));
00123
00124 if (flags & mcELEMENT_DBG_ID)
00125 str += wxString::Format(wxT("ID: %2d "), data_GetID());
00126
00127
00128 str += data_Debug(flags);
00129 str = wxIndent(str, indent);
00130
00131
00132 return str;
00133 }
00134
00135 void mcElement::data_CheckContainer() const
00136 {
00137
00138
00139 if (data_GetRefData()) {
00140 mcElementHelpers *helpers = (mcElementHelpers *)data_GetRefData();
00141 mcUNUSED(helpers);
00142
00143
00144
00145 mcASSERT(data_isValidContainerFor(helpers->data_GetType()),
00146 wxT("Invalid container (this is a ") +
00147 data_GetDebugName() +
00148 wxT(") for the given helper class (") +
00149 helpers->data_GetDebugName() +
00150 wxT("Helpers) !!"));
00151 }
00152 }
00153
00154 void mcElement::data_Check() const
00155 {
00156
00157 data_CheckContainer();
00158
00159
00160 if (chlp()) chlp()->data_Check();
00161 }
00162
00163 #endif
00164
00165
00166 mcElementHelpers::mcElementHelpers()
00167 {
00168
00169
00170
00171
00172 mdata_nID = mcElementHelpers::data_GenID();
00173
00174
00175 mdata_nProperties = mcEP_NOPROPERTIES;
00176 mgui_nExpDepth = 0;
00177 }
00178
00179 void mcElementHelpers::data_Init()
00180 {
00181
00182 if (mcMathCore::Get()->isGUIEnabled()) gui_Init();
00183 if (mcMathCore::Get()->isMathEnabled()) math_Init();
00184 if (mcMathCore::Get()->isIOEnabled()) io_Init();
00185 }
00186
00187 bool mcElementHelpers::io_Init(const wxString &str)
00188 {
00189 wxString err;
00190 int n;
00191
00192
00193 if (!mcMathCore::Get()->isIOEnabled())
00194 return FALSE;
00195 if (io_isBeginChar(str) == FALSE)
00196 return FALSE;
00197 return io_ImportInlinedExpr(str, &n, err);
00198 }
00199
00200 void mcElementHelpers::gui_OnRecalcSize(wxSize old)
00201 {
00202
00203 if (old == mgui_sz)
00204 return;
00205
00206
00207
00208
00209
00210 }
00211
00212 void mcElementHelpers::gui_SetStyleArray(const mcStyleArray *p)
00213 {
00214
00215 if (!mcMathCore::Get()->isGUIEnabled())
00216 return;
00217
00218 mgui_pStyleArray = p;
00219
00220
00221 for (int i=0; i < data_GetChildrenCount(); i++)
00222 data_GetChild(i).gui_SetStyleArray(p);
00223 }
00224
00225 mcElement &mcElementHelpers::data_GetElemFromID(int id) const
00226 {
00227
00228
00229
00230 for (int i=0; i < data_GetChildrenCount(); i++) {
00231 mcElement &p = data_GetConstChild(i).data_GetElemFromID(id);
00232 if (p != mcEmptyElement)
00233 return p;
00234 }
00235
00236 return mcEmptyElement;
00237 }
00238
00239
00240 void mcElementHelpers::data_AddRecursiveProperty(mcElementType t, int p, void *val1, void *val2)
00241 {
00242 if (data_GetType() == t)
00243 data_AddProperty(p, val1, val2);
00244
00245
00246 for (int i=0; i < data_GetChildrenCount(); i++)
00247 data_GetChild(i).data_AddRecursiveProperty(t, p, val1, val2);
00248 }
00249
00250 bool mcElementHelpers::data_hasRecursiveProperty(mcElementType t, int p) const
00251 {
00252 if (data_GetType() == t)
00253 return ((mdata_nProperties & p) != 0);
00254
00255
00256 for (int i=0; i < data_GetChildrenCount(); i++)
00257 if (data_GetConstChild(i).data_hasRecursiveProperty(t, p))
00258 return TRUE;
00259 return FALSE;
00260 }
00261
00262 void mcElementHelpers::data_RemoveRecursiveProperty(mcElementType t, int p)
00263 {
00264 if (data_GetType() == t)
00265 mdata_nProperties &= ~p;
00266
00267
00268 for (int i=0; i < data_GetChildrenCount(); i++)
00269 data_GetChild(i).data_RemoveRecursiveProperty(t, p);
00270 }
00271
00272 void mcElementHelpers::data_Update()
00273 {
00274
00275
00276
00277 for (int i=0; i < data_GetChildrenCount(); i++)
00278 data_GetChild(i).data_Update();
00279 }
00280
00281 bool mcElementHelpers::data_AddChildrenTo(mcElement p)
00282 {
00283 if (p.data_GetType() != data_GetType())
00284 return FALSE;
00285
00286 for (int i=0, max=data_GetChildrenCount(); i < max; i++)
00287 p.data_SetChild(i, data_GetChild(i));
00288 return TRUE;
00289 }
00290
00291 int mcElementHelpers::data_GetChildIdx(const mcElement &p) const
00292 {
00293 for (int i=0,max=data_GetChildrenCount(); i < max; i++)
00294 if (data_GetConstChild(i) == p)
00295 return i;
00296
00297 return -1;
00298 }
00299
00300 mcElement &mcElementHelpers::data_GetChild(int n)
00301 { return (mcElement &)data_GetConstChild(n);}
00302
00303 const mcElement &mcElementHelpers::data_GetConstChild(int) const
00304 { return mcEmptyElement;}
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 mcElement::mcElement(const mcElementHelpers *helpers)
00315 {
00316
00317 data_SetRefData((mcObjectRefData *)helpers);
00318
00319
00320 if (data_GetRefData())
00321 data_GetRefData()->data_IncRefCount();
00322 #ifndef mcENABLE_COW
00323 if (data_GetRefData())
00324 data_MakePrivateCopy();
00325 #endif
00326 }
00327
00328 mcElement::~mcElement()
00329 {
00330 #ifdef mcENABLE_COW_DEBUG
00331 if (data_GetRefData() && mcMathCore::isOk())
00332 mcMathCore::Get()->m_nMaxSharing =
00333 mcMAX(mcMathCore::Get()->m_nMaxSharing, chlp()->data_GetRefCount());
00334 #endif
00335 }
00336
00337 void mcElement::data_Ref(const mcObject &toclone)
00338 {
00339 mcObject::data_Ref(toclone);
00340
00341
00342
00343
00344
00345
00346
00347 #ifdef __MCDEBUG__
00348 wxLogNull logNo;
00349 data_CheckContainer();
00350 #endif
00351 }
00352
00353 void mcElementHelpers::Init()
00354 {
00355 for (int t=0; t < mcNUM_ELEMENT_TYPES; t++)
00356 sdata_pElem[t] = NULL;
00357
00358
00359 data_UpdateElemArray();
00360 }
00361
00362 void mcElementHelpers::Cleanup()
00363 {
00364 for (int t=0; t < mcNUM_ELEMENT_TYPES; t++)
00365 mcSAFE_DELETE(sdata_pElem[t]);
00366 }
00367
00368 void mcElementHelpers::data_UpdateElemArray()
00369 {
00370
00371
00372
00373 for (int t=0; t < mcNUM_ELEMENT_TYPES; t++) {
00374 mcSAFE_DELETE(sdata_pElem[t]);
00375
00376
00377
00378 sdata_pElem[t] = new mcElement(data_NewElem((mcElementType)t));
00379 }
00380 }
00381
00382
00383 #define mcDEFINE_ALLOCATOR(x) \
00384 if (towrap) \
00385 return x(towrap); \
00386 else \
00387 return x();
00388
00389 #define mcDEFINE_SPECIAL_ALLOCATOR(x, param1) \
00390 if (towrap) \
00391 return x(towrap); \
00392 else \
00393 return x(param1);
00394
00395 mcElement mcElementHelpers::data_NewElem(mcElementType type, const mcElementHelpers *towrap)
00396 {
00397
00398
00399
00400
00401 switch (type) {
00402 case mcET_NUMBER:
00403 mcDEFINE_ALLOCATOR(mcNumber)
00404 case mcET_PARENTHESIS:
00405 mcDEFINE_ALLOCATOR(mcParenthesis)
00406 case mcET_BRACKET:
00407 mcDEFINE_ALLOCATOR(mcBracket)
00408 case mcET_RADICAL:
00409 mcDEFINE_ALLOCATOR(mcRadical)
00410 case mcET_FRACTION:
00411 mcDEFINE_ALLOCATOR(mcFraction)
00412 case mcET_SYMBOL:
00413 mcDEFINE_ALLOCATOR(mcSymbol)
00414 case mcET_FUNCTION:
00415 mcDEFINE_ALLOCATOR(mcFunction)
00416 case mcET_TEXT:
00417 mcDEFINE_ALLOCATOR(mcText)
00418 case mcET_EMPTYBOX:
00419 mcDEFINE_ALLOCATOR(mcEmptyBox)
00420 case mcET_ADDOP:
00421 mcDEFINE_SPECIAL_ALLOCATOR(mcAddSubOp, mcET_ADDOP);
00422 case mcET_SUBOP:
00423 mcDEFINE_SPECIAL_ALLOCATOR(mcAddSubOp, mcET_SUBOP);
00424 case mcET_MULTOP:
00425 mcDEFINE_SPECIAL_ALLOCATOR(mcMultDivOp, mcET_MULTOP);
00426 case mcET_DIVOP:
00427 mcDEFINE_SPECIAL_ALLOCATOR(mcMultDivOp, mcET_DIVOP);
00428 case mcET_POLYNOMIAL:
00429 mcDEFINE_ALLOCATOR(mcPolynomial)
00430 case mcET_MONOMIAL:
00431 mcDEFINE_ALLOCATOR(mcMonomial)
00432 default:
00433 mcASSERT(0, wxT("The allocation of an undefined class was requested"));
00434 }
00435
00436 return NULL;
00437 }
00438
00439
00440
00441 #define SCAN_REGISTERED_CLASSES(fnc, params) \
00442 \
00443 for (int i=0; i < mcNUM_ELEMENT_TYPES; i++) { \
00444 if (sdata_pElem[i]->fnc(params) != FALSE) { \
00445 \
00446 \
00447 return (mcElementType)i; \
00448 } \
00449 } \
00450 \
00451 \
00452 return mcET_INVALID;
00453
00454
00455
00456 mcElementType mcElementHelpers::gui_isKeyBeginKey(const mcKey &key) {
00457 SCAN_REGISTERED_CLASSES(gui_isBeginKey, key);
00458 }
00459
00460 mcElementType mcElementHelpers::io_isCharBeginChar(const wxString &str) {
00461 SCAN_REGISTERED_CLASSES(io_isBeginChar, str);
00462 }
00463
00464 mcElementType mcElementHelpers::io_isTagBeginTag(const wxXml2Node &tag) {
00465 SCAN_REGISTERED_CLASSES(io_isBeginTag, tag);
00466 }
00467
00468 wxString mcElementHelpers::data_GetGlobalMemoryInfo()
00469 {
00470 wxString res;
00471
00472 for (int i=0; i < mcNUM_ELEMENT_TYPES; i++) {
00473
00474 res += wxString::Format(wxT("Class number #%d: %d\n"),
00475 i,
00476 sdata_pElem[i]->data_GetMemoryInfo());
00477 }
00478
00479 return res;
00480 }
00481
00482 int mcElementHelpers::data_GenID(bool bFirstMember)
00483 {
00484
00485 static int l=0, r=0xFFFF;
00486 if (bFirstMember)
00487 return l++;
00488 return r++;
00489 }
00490
00491 mcObjectRefData *mcElement::data_MakePrivateCopy()
00492 {
00493 const mcElementHelpers *h = chlp();
00494
00495
00496
00497 if (h->data_GetRefCount() == 1)
00498 return (mcElementHelpers *)h;
00499
00500
00501 #ifdef mcENABLE_COW_DEEPDEBUG
00502 mcLOG(wxT("mcElementHelpers::data_MakePrivateCopy"));
00503 #endif
00504 data_UnRef();
00505
00506
00507 data_SetRefData(h->data_Clone());
00508
00509
00510 return (mcElementHelpers *)data_GetRefData();
00511 }
00512
00513 void mcElementHelpers::gui_UpdateExpDepth()
00514 {
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 gui_RecalcSize();
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 bool mcElementHelpers::data_isSameAs(const mcElementHelpers *p) const
00563 {
00564 bool b = TRUE;
00565
00566
00567
00568
00569
00570 b &= (data_GetType() == p->data_GetType());
00571 b &= (mdata_nProperties == p->mdata_nProperties);
00572 if (!b) return FALSE;
00573
00574
00575 for (int i=0; i < data_GetChildrenCount(); i++)
00576 if (!data_GetConstChild(i).data_isSameAs(p->data_GetConstChild(i)))
00577 return FALSE;
00578
00579 return TRUE;
00580 }
00581
00582
00583
00584 void mcElementHelpers::data_DeepCopy(const mcElementHelpers *p)
00585 {
00586
00587
00588 mcASSERT(data_GetType() == p->data_GetType(), wxT("Cannot perform deep copy !!"));
00589
00590
00591 mdata_nProperties = p->mdata_nProperties;
00592
00593 mgui_bSelected = p->mgui_bSelected;
00594 mgui_sz = p->mgui_sz;
00595 mgui_pStyleArray = p->mgui_pStyleArray;
00596 mgui_nExpDepth = p->mgui_nExpDepth;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 void mcElementHelpers::gui_Init()
00609 {
00610
00611
00612 mgui_sz.Set(-1, -1);
00613
00614
00615 mgui_bSelected = FALSE;
00616
00617
00618 if (!mcMathCore::Get()->isGUIEnabled())
00619 return;
00620
00621
00622
00623
00624
00625
00626 mcASSERT(sgui_pDefaultStyles != NULL,
00627 wxT("pDefaultStyles must always be a valid array !!!"));
00628
00629
00630
00631 mgui_pStyleArray = sgui_pDefaultStyles;
00632
00633 gui_RecalcSize();
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 mcElement mcElementHelpers::gui_GetSelection() const
00674 {
00675
00676
00677 return mcElement(this);
00678 }
00679
00680 mcElement &mcElementHelpers::gui_GetActiveElem(int x, int y, const wxPoint &pt) const
00681 {
00682 wxScreenDC tmp;
00683
00684
00685 int n = gui_Draw(tmp, x, y, mcDRW_USEPOINT, pt);
00686
00687
00688
00689 if (n != mcDRW_NOACTIVEELEM && n != mcDRW_ONSELECTION)
00690 return data_GetElemFromID(n);
00691 return mcEmptyElement;
00692 }
00693
00694 void mcElementHelpers::gui_RecalcSize()
00695 {
00696 wxSize old = mgui_sz;
00697 gui_DoRecalcSize();
00698
00699
00700 gui_OnRecalcSize(old);
00701 }
00702
00703 void mcElementHelpers::gui_DeepRecalcSize()
00704 {
00705 mcGUILOG(wxT("mcElementHelpers::gui_DeepRecalcSize [%s]"), mcTXTTHIS);
00706
00707
00708 for (int i=0; i < data_GetChildrenCount(); i++)
00709 data_GetChild(i).gui_DeepRecalcSize();
00710
00711
00712 gui_RecalcSize();
00713 }
00714
00715 void mcElementHelpers::gui_SelectAll()
00716 {
00717
00718 for (int i=0; i < data_GetChildrenCount(); i++)
00719 data_GetChild(i).gui_SelectAll();
00720
00721
00722 gui_Select();
00723 }
00724
00725 void mcElementHelpers::gui_DeSelect()
00726 {
00727
00728 for (int i=0; i < data_GetChildrenCount(); i++)
00729 data_GetChild(i).gui_DeSelect();
00730
00731
00732 mgui_bSelected = FALSE;
00733 }
00734
00735 bool mcElementHelpers::gui_isAllSelected() const
00736 {
00737
00738 for (int i=0; i < data_GetChildrenCount(); i++)
00739 if (!data_GetConstChild(i).gui_isAllSelected())
00740 return FALSE;
00741
00742
00743 return gui_isSelected();
00744 }
00745
00746 void mcElementHelpers::gui_DeleteSelection()
00747 {
00748 mcASSERT(!gui_isAllSelected(),
00749 wxT("This element is completely selected: it should be removed by the caller"));
00750
00751
00752 for (int i=0; i < data_GetChildrenCount(); i++)
00753 data_GetChild(i).gui_DeleteSelection();
00754
00755
00756 gui_RecalcSize();
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 void mcElementHelpers::gui_SetAsExpOf(const mcElement &p)
00768 {
00769 if (p != mcEmptyElement)
00770 mgui_nExpDepth = p.gui_GetExpDepth()+1;
00771
00772
00773 gui_UpdateExpDepth();
00774 }
00775
00776 void mcElementHelpers::gui_SetAtSameLevelOf(const mcElement &p)
00777 {
00778 if (p != mcEmptyElement)
00779 mgui_nExpDepth = p.gui_GetExpDepth();
00780
00781
00782 gui_UpdateExpDepth();
00783 }
00784
00785 void mcElementHelpers::gui_InitDefaultStyles()
00786 {
00787 mcGUILOG(wxT("mcElementHelpers::gui_InitDefaultStyles"));
00788
00789
00790 gui_DeleteDefaultStyles();
00791
00792
00793 sgui_pDefaultStyles = new mcStyleArray();
00794 mcStyle *p = new mcStyle();
00795
00796
00797 for (int j=0; j < sgui_pDefaultStyles->GetCount(); j++) {
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 #if defined(__WXMSW__)
00812
00813
00814 wxString face1 = wxT("Lucida Sans Unicode");
00815 wxString face2 = wxT("Tahoma");
00816 wxString face3 = wxT("Verdana");
00817 const int size = 25;
00818 const int size2 = 20;
00819
00820
00821
00822
00823
00824
00825 #else
00826
00827 wxString face1 = wxT("Lucida");
00828 wxString face2 = wxT("Lucida");
00829 wxString face3 = wxT("Lucida");
00830 const int size = 25;
00831 const int size2 = 25;
00832
00833 #endif
00834
00835
00836 wxString num = wxString::Format(wxT("%d-%s-%d-%d-%d"), wxSWISS,
00837 face1.c_str(), size/(j+1), wxNORMAL, wxNORMAL);
00838
00839 wxString fnc = wxString::Format(wxT("%d-%s-%d-%d-%d"), wxSWISS,
00840 face2.c_str(), size/(j+1), wxNORMAL, wxITALIC);
00841
00842 wxString sym = wxString::Format(wxT("%d-%s-%d-%d-%d"), wxROMAN,
00843 face3.c_str(), size/(j+1), wxNORMAL, wxITALIC);
00844
00845 wxString text = wxString::Format(wxT("%d-%s-%d-%d-%d"), wxSWISS,
00846 face2.c_str(), size2/(j+1), wxBOLD, wxNORMAL);
00847
00848 wxString spec = wxString::Format(wxT("%d-%s-%d-%d-%d"), wxSWISS,
00849 wxT("MathStudio Special"), size/(j+1), wxBOLD, wxNORMAL);
00850
00851
00852 p->SetTextSettingsFor(mcET_NUMBER, mcINITWX(0xFF0000), *wxWHITE, num);
00853 p->SetTextSettingsFor(mcET_FUNCTION, mcINITWX(0x4080FF), *wxWHITE, fnc);
00854 p->SetTextSettingsFor(mcET_SYMBOL, mcINITWX(0x14A03C), *wxWHITE, sym);
00855 p->SetTextSettingsFor(mcET_TEXT, mcINITWX(0x329C7A), *wxWHITE, text);
00856
00857
00858
00859 p->SetTextSettingsFor(mcET_ADDOP, mcINITWX(0x0), *wxWHITE, num);
00860
00861
00862 p->SetSpecialTextSettings(mcINITWX(0x0), *wxWHITE, spec);
00863
00864
00865 mcASSERT(p->Ok(), wxT("Problems in style creation"));
00866
00867
00868 sgui_pDefaultStyles->Set(p, j);
00869 }
00870
00871
00872
00873 delete p;
00874 }
00875
00876 double mcElementHelpers::gui_GetPointSize()
00877 {
00878
00879
00880 static double pxperpoint = 0;
00881
00882 if (pxperpoint == 0) {
00883
00884 wxScreenDC dc;
00885
00886
00887
00888 dc.SetMapMode(wxMM_POINTS);
00889 pxperpoint = dc.LogicalToDeviceYRel(72);
00890 }
00891
00892 return pxperpoint;
00893 }
00894
00895 void mcElementHelpers::gui_DeleteDefaultStyles()
00896 {
00897
00898 mcSAFE_DELETE(sgui_pDefaultStyles);
00899 }
00900
00901 double mcElementHelpers::gui_PointSize2Pixels(double pointsize)
00902 {
00903
00904
00905
00906
00907
00908 return (pointsize * gui_GetPointSize());
00909 }
00910
00911 double mcElementHelpers::gui_Pixels2PointSize(double pixels)
00912 {
00913
00914 return (72.0 * pixels / gui_GetPointSize());
00915 }
00916
00917 int mcElementHelpers::gui_GetBaseOffsety(int exph) const
00918 {
00919
00920
00921 return (int)((exph/100.0)*50.);
00922 }
00923
00924 int mcElementHelpers::gui_GetSubscriptOffsety(int baseh) const
00925 {
00926
00927
00928 return (int)((baseh/100.0)*60.);
00929 }
00930
00931 const mcStyle *mcElementHelpers::gui_GetStyleForThis() const {
00932
00933 return mgui_pStyleArray->gui_GetStyleFor(this);
00934 }
00935
00936 const mcStyle *mcElementHelpers::gui_GetDefaultStyle(int n) {
00937 return sgui_pDefaultStyles->Get(n);
00938 }
00939
00940 const mcStyle *mcElementHelpers::gui_GetStyle(int n) const {
00941
00942 return mgui_pStyleArray->Get(n);
00943 }
00944
00945
00946
00947
00948
00949
00950 void mcElementHelpers::gui_SelectStyle(wxDC &hDC) const {
00951 const mcStyle *p = gui_GetStyleForThis();
00952
00953
00954
00955
00956 mcASSERT(hDC.Ok(), wxT("Invalid DC"));
00957
00958
00959 p->gui_Select(hDC, this);
00960 }
00961
00962 int mcElementHelpers::gui_GetThickness(wxDC *dc) const {
00963 mcGUILOG(wxT("mcElementHelpers::gui_GetThickness"));
00964 bool bClean = FALSE;
00965
00966 if (dc == NULL) {
00967 dc = new wxScreenDC();
00968 bClean = TRUE;
00969 }
00970
00971
00972 gui_SelectStyle(*dc);
00973 int nWeight = dc->GetFont().GetWeight();
00974 int nHeight = dc->GetFont().GetPointSize();
00975
00976
00977 if (bClean)
00978 delete dc;
00979
00980
00981
00982 return (int)(nWeight/527.5 + nHeight/12.8);
00983 }
00984
00985 wxSize mcElementHelpers::gui_GetSizeOf(wxDC *hDC, const wxString &str) {
00986 mcGUILOG(wxT("mcElementHelpers::gui_GetSizeOf [%s]"), str.c_str());
00987 bool bClean=FALSE;
00988 int w=0, h=0;
00989
00990
00991 if (hDC == NULL) {
00992 hDC = new wxScreenDC();
00993 bClean = TRUE;
00994 }
00995
00996
00997 if (str.IsEmpty()) return wxSize(0,0);
00998
00999
01000 #ifdef __WXGTK20__
01001 mcGUILOG(wxT("------------------ Using the buggy wxScreenDC function -----------------"));
01002 hDC->GetTextExtent(str, &w, &h);
01003 #else
01004 hDC->GetTextExtent(str, &w, &h);
01005 #endif
01006 mcASSERT(w != 0 && h != 0, wxT("Cannot retrieve character size"));
01007
01008
01009 if (bClean)
01010 delete hDC;
01011
01012
01013 return wxSize(w, h);
01014 }
01015
01016 int mcElementHelpers::gui_GetWidthOf(wxDC *h, const wxString &str) {
01017 return gui_GetSizeOf(h, str).GetWidth();
01018 }
01019
01020 int mcElementHelpers::gui_GetHeightOf(wxDC *h, const wxString &str) {
01021 return gui_GetSizeOf(h, str).GetHeight();
01022 }
01023
01024 wxSize mcElementHelpers::gui_GetSizeOfChar(wxDC *hDC, const mcElement &p) const {
01025 return wxSize(mcElementHelpers::gui_GetWidthOfChar(hDC, p),
01026 mcElementHelpers::gui_GetHeightOfChar(hDC, p));
01027 }
01028
01029 int mcElementHelpers::gui_GetWidthOfChar(wxDC *hDC, const mcElement &p) const {
01030 mcGUILOG(wxT("mcElementHelpers::gui_GetWidthOfChar"));
01031 bool bClean=FALSE;
01032 int w;
01033
01034
01035 if (hDC == NULL) {
01036 hDC = new wxScreenDC();
01037 bClean = TRUE;
01038 }
01039
01040
01041
01042 if (p != NULL)
01043 p.gui_SelectStyle(*hDC);
01044
01045
01046 w = hDC->GetCharWidth();
01047 mcASSERT(w != 0, wxT("Cannot retrieve character size"));
01048
01049
01050 if (bClean)
01051 delete hDC;
01052
01053
01054 return w;
01055 }
01056
01057 int mcElementHelpers::gui_GetHeightOfChar(wxDC *hDC, const mcElement &p) const {
01058 mcGUILOG(wxT("mcElementHelpers::sgui_GetHeightOfChar"));
01059 bool bClean=FALSE;
01060 int h;
01061
01062
01063 if (hDC == NULL) {
01064 hDC = new wxScreenDC();
01065 bClean = TRUE;
01066 }
01067
01068
01069
01070 if (p != NULL)
01071 p.gui_SelectStyle(*hDC);
01072
01073
01074 h = hDC->GetCharHeight();
01075 mcASSERT(h != 0, wxT("Cannot retrieve character size"));
01076
01077
01078 if (bClean)
01079 delete hDC;
01080
01081
01082 return h;
01083 }
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 void mcElementHelpers::io_PostProcessChildren()
01094 {
01095 for (int i=0; i < data_GetChildrenCount(); i++)
01096 data_GetChild(i).hlp()->io_PostProcess();
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 mcElement mcElement::operator^(const mcRealValue &r) const
01108 { mcElement ret(*this); ret.math_RaiseTo(mcPolynomial(r)); return ret; }
01109
01110 void mcElementHelpers::math_SimpleAdd(const mcElement &p, bool add)
01111 {
01112 mcMATHLOG(wxT("mcElementHelpers::math_SimpleAdd [%s] - simple adding with [%s]"),
01113 mcTXTTHIS, mcTXT(p));
01114 mcBasicOpRes r = math_Add(p, NULL, add);
01115 mcASSERT(r == mcBOR_REMOVE_OPERAND,
01116 wxT("The operation could not be completely performed: ")
01117 wxT("the given operand has not been completely merged in *this"));
01118 mcUNUSED(r);
01119 }
01120
01121 void mcElementHelpers::math_SimpleMultiplyBy(const mcElement &p)
01122 {
01123 mcMATHLOG(wxT("mcElementHelpers::math_SimpleMultiplyBy [%s] - simple multiplying by [%s]"),
01124 mcTXTTHIS, mcTXT(p));
01125 mcBasicOpRes r = math_MultiplyBy(p, NULL);
01126 mcASSERT(r == mcBOR_REMOVE_OPERAND,
01127 wxT("The operation could not be completely performed: ")
01128 wxT("the given operand has not been completely merged in *this"));
01129 mcUNUSED(r);
01130 }
01131
01132 void mcElementHelpers::math_SimpleDivideBy(const mcElement &p)
01133 {
01134 mcMATHLOG(wxT("mcElementHelpers::math_SimpleDivideBy [%s] - simple dividing by [%s]"),
01135 mcTXTTHIS, mcTXT(p));
01136 mcBasicOpRes r = math_DivideBy(p, NULL);
01137 mcASSERT(r == mcBOR_REMOVE_OPERAND,
01138 wxT("The operation could not be completely performed: ")
01139 wxT("the given operand has not been completely merged in *this"));
01140 mcUNUSED(r);
01141 }
01142
01143 void mcElementHelpers::math_SimpleRaiseTo(const mcPolynomial &p)
01144 {
01145 mcMATHLOG(wxT("mcElementHelpers::math_SimpleRaiseTo [%s] - simple raising by [%s]"),
01146 mcTXTTHIS, mcTXT(p));
01147 mcBasicOpRes r = math_RaiseTo(p);
01148 mcASSERT(r == mcBOR_REMOVE_OPERAND,
01149 wxT("The operation could not be completely performed: ")
01150 wxT("the given operand has not been completely merged in *this"));
01151 mcUNUSED(r);
01152 }
01153
01154 bool mcElementHelpers::math_isExpAllowed(mcElement p)
01155 {
01156
01157
01158 return TRUE;
01159
01160 }
01161
01162 bool mcElementHelpers::math_isSubAllowed(mcElement )
01163 {
01164
01165 return TRUE;
01166 }
01167
01168 void mcElementHelpers::math_SetExp(const mcPolynomial &pol)
01169 {
01170
01171
01172
01173
01174 for (int i=0; i<data_GetChildrenCount(); i++)
01175 data_GetChild(i).math_SetExp(pol);
01176 }
01177
01178 mcBasicOpRes mcElementHelpers::math_MakeReciprocal(mcElement *replacement)
01179 {
01180 mcFraction f;
01181 f.data_GetNum().math_WrapNumber(1);
01182 f.data_GetDen().math_WrapSimple(mcElement(this));
01183 *replacement = f;
01184
01185 return mcBOR_REPLACE_BOTH;
01186 }
01187
01188 mcExpSimRes mcElementHelpers::math_MaxSimplify(long flags)
01189 {
01190 mcExpSimRes retflag = mcESR_NOTFINISHED;
01191 int cycles=0;
01192
01193
01194
01195 while (retflag != mcESR_DONE) {
01196 retflag = math_Simplify(flags, NULL);
01197 cycles++;
01198
01199 if (cycles >= mcELEMENTMATH_MAX_PROCESS_CYCLES)
01200 return mcESR_NOTFINISHED;
01201 }
01202
01203 return mcESR_DONE;
01204 }
01205
01206 bool mcElementHelpers::math_isMaxSimplified(long flags) const
01207 {
01208 mcExpSimRes retflag = mcESR_NOTFINISHED;
01209 int cycles=0;
01210
01211
01212 mcElementHelpers *backup = data_Clone();
01213
01214
01215
01216 while (retflag != mcESR_DONE) {
01217 retflag = backup->math_Simplify(flags, NULL);
01218 cycles++;
01219
01220 if (cycles >= mcELEMENTMATH_MAX_PROCESS_CYCLES)
01221 break;
01222 }
01223
01224
01225
01226 return (cycles == 1);
01227 }
01228
01229 mcRealValue mcElementHelpers::math_GetTotalLenght() const
01230 {
01231
01232
01233
01234
01235 mcRealValue l = math_GetLenght();
01236
01237 for (int i=0; i < data_GetChildrenCount(); i++)
01238 l += data_GetConstChild(i).math_GetTotalLenght();
01239
01240 return l;
01241 }
01242
01243 bool mcElementHelpers::math_isFinite() const
01244 {
01245 mcRealValue res = math_Evaluate();
01246 if (res.math_isFinite())
01247 return TRUE;
01248 return FALSE;
01249 }
01250
01251 bool mcElementHelpers::math_isValidMath() const
01252 {
01253 switch (data_GetType()) {
01254 case mcET_INVALID:
01255 case mcET_PARENTHESIS:
01256 case mcET_EMPTYBOX:
01257
01258
01259
01260
01261 case mcET_TEXT:
01262 return FALSE;
01263
01264 default:
01265 break;
01266 }
01267
01268
01269 for (int i=0; i < data_GetChildrenCount(); i++)
01270 if (!data_GetConstChild(i).math_isValidMath())
01271 return FALSE;
01272
01273
01274 return TRUE;
01275 }
01276
01277 bool mcElementHelpers::math_isListedBeforeOf(const mcElement &p) const
01278 {
01279 if (math_GetOrderPos() < p.math_GetOrderPos())
01280 return TRUE;
01281 return FALSE;
01282 }
01283
01284 mcMonomial mcElementHelpers::math_GetFactors() const
01285 {
01286 mcMonomial pol;
01287 pol.math_WrapSimple(this);
01288
01289 return pol;
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299 bool mcElementHelpers::math_Contains(const mcElement &p, long flags) const
01300 { return math_Find(0, p, flags) != mcEmptyElement; }
01301
01302 bool mcElementHelpers::math_ContainsNumber(const mcRealValue &num,
01303 const mcPolynomial &exp) const
01304 {
01305 mcNumber n(num);
01306
01307
01308 if (exp != mcEmptyPolynomial)
01309 n.data_SetExpSub(TRUE, exp);
01310
01311 return math_Contains(n);
01312 }
01313
01314 bool mcElementHelpers::math_ContainsSymbol(const mcSymbolProperties *prop,
01315 const mcPolynomial &exp) const
01316 {
01317 mcSymbol safe(prop->data_GetSafeLinkedSym());
01318 mcASSERT(safe.data_isOk(), wxT("Invalid safe symbol ?"));
01319
01320
01321 if (exp != mcEmptyPolynomial)
01322 safe.data_SetExpSub(TRUE, exp);
01323
01324 return math_Contains(safe);
01325 }
01326
01327 bool mcElementHelpers::math_ContainsOneOf(const mcSymbolArray *arr) const
01328 {
01329 int max = arr->data_GetCount();
01330 for (int i=0; i < max; i++) {
01331
01332
01333
01334
01335
01336
01337 const mcSymbolProperties *curr = arr->data_GetSymbol(i);
01338
01339
01340
01341
01342 if (math_Contains(curr->data_GetSafeLinkedSym())) {
01343
01344
01345 return TRUE;
01346 }
01347 }
01348
01349
01350 return FALSE;
01351 }
01352
01353 bool mcElementHelpers::math_ContainsUnknowns() const
01354 { return math_ContainsOneOf(&mcSymbol::arrUnknowns); }
01355
01356 bool mcElementHelpers::math_ContainsConstants() const
01357 { return math_ContainsOneOf(&mcSymbol::arrConstants); }
01358
01359 bool mcElementHelpers::math_ContainsParameters() const
01360 { return math_ContainsOneOf(&mcSymbol::arrParameters); }
01361
01362 bool mcElementHelpers::math_ContainsSymbols() const
01363 {
01364
01365 return math_ContainsUnknowns() ||
01366 math_ContainsConstants() ||
01367 math_ContainsParameters();
01368 }
01369
01370 bool mcElementHelpers::math_ContainsInvalidSymbols() const
01371 {
01372
01373 return math_ContainsOneOf(&mcSymbol::arrUnregistered);
01374 }
01375
01376 bool mcElementHelpers::math_isConstant() const
01377 {
01378
01379
01380
01381 return !math_ContainsParameters() && !math_ContainsUnknowns();
01382 }
01383
01384 int mcElementHelpers::math_GetSymbolList(mcSymbol **arr, int size, const mcSymbol &tofind) const
01385 {
01386 int n = 0;
01387
01388
01389
01390 const mcElement p = math_Find(n, tofind);
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 return n;
01404 }
01405
01406 int mcElementHelpers::math_GetSymbolList(mcSymbol **arr, int size, mcSymbolProperties &tofind) const
01407 {
01408 mcSymbol tmp;
01409 tmp.data_LinkWith(&tofind);
01410
01411 return math_GetSymbolList(arr, size, tmp);
01412 }
01413
01414 bool mcElementHelpers::math_CompareThisOnly(const mcElement &p, long) const
01415 {
01416
01417
01418
01419 return (data_GetType() == p.data_GetType());
01420 }
01421
01422 mcElement mcElementHelpers::math_Find(int n, const mcElement &p, long flags) const
01423 {
01424 mcASSERT(n >= 0, wxT("Invalid occurrence to find"));
01425 int k = n;
01426
01427
01428 return math_RecursiveFind(k, p, flags);
01429 }
01430
01431 mcElement mcElementHelpers::math_FindInChildrenOnly(int n, const mcElement &p, long flags) const
01432 {
01433 mcASSERT(n >= 0, wxT("Invalid occurrence to find"));
01434 int k = n;
01435
01436
01437 return math_RecursiveFindInChildrenOnly(k, p, flags);
01438 }
01439
01440 int mcElementHelpers::math_NonRecursiveFindInChildren(int n,
01441 const mcElement &p, long flags) const
01442 {
01443 mcASSERT(n >= 0, wxT("Invalid occurrence to find"));
01444
01445
01446 for (int i=0,max=data_GetChildrenCount(); i<max; i++) {
01447
01448 if (data_GetConstChild(i).math_Compare(p, flags)) {
01449
01450
01451 if (--n == -1)
01452 return i;
01453
01454
01455 }
01456 }
01457
01458
01459 return -1;
01460 }
01461
01462 mcElement mcElementHelpers::math_RecursiveFindInChildrenOnly(int &n,
01463 const mcElement &p, long flags) const
01464 {
01465 mcASSERT(n >= 0, wxT("Invalid occurrence to find"));
01466
01467
01468 for (int i=0,max=data_GetChildrenCount(); i<max; i++) {
01469
01470
01471 const mcElement &res = data_GetConstChild(i).chlp()->math_RecursiveFind(n, p, flags);
01472
01473
01474
01475
01476
01477 if (n == -1) {
01478
01479
01480 if (res != mcEmptyElement)
01481 return res;
01482
01483
01484
01485
01486 mcASSERT(flags & mcFIND_PARENT, wxT("Something wrong"));
01487
01488
01489
01490
01491 mcASSERT(math_NonRecursiveFindInChildren(n+1, p, flags & ~mcFIND_PARENT) != -1,
01492 wxT("Cannot find the element tofind in the children of *this..."));
01493 return mcElement(this);
01494 }
01495 }
01496
01497 return mcEmptyElement;
01498 }
01499
01500
01501
01502
01503
01504
01505 mcElement mcElementHelpers::math_RecursiveFind(int &n,
01506 const mcElement &p, long flags) const
01507 {
01508 mcASSERT(n >= 0, wxT("Invalid occurrence to find"));
01509
01510
01511
01512 if (math_CompareThisOnly(p, flags) &&
01513 data_GetChildrenCount() >= p.data_GetChildrenCount()) {
01514
01515
01516
01517
01518
01519
01520 for (int i=0,max=p.data_GetChildrenCount(); i<max; i++)
01521 if (!data_GetConstChild(i).math_Compare(p.data_GetConstChild(i), flags))
01522 return math_RecursiveFindInChildrenOnly(n, p, flags);
01523
01524
01525
01526
01527
01528
01529 if (--n == -1) {
01530
01531
01532
01533
01534
01535
01536 if (flags & mcFIND_PARENT)
01537 return mcEmptyElement;
01538
01539 return mcElement(this);
01540 }
01541 }
01542
01543
01544 return math_RecursiveFindInChildrenOnly(n, p, flags);
01545 }
01546
01547 int mcElementHelpers::math_GetCountOfChildrenOnly(const mcElement &p, long flags) const
01548 {
01549 int total = 0;
01550
01551 for (int i=0,max=data_GetChildrenCount(); i<max; i++)
01552 total += data_GetConstChild(i).math_GetCountOf(p, flags);
01553
01554 return total;
01555 }
01556
01557 int mcElementHelpers::math_GetCountOf(const mcElement &p, long flags) const
01558 {
01559 int total = 0;
01560
01561 if (math_CompareThisOnly(p, flags) &&
01562 data_GetChildrenCount() >= p.data_GetChildrenCount()) {
01563
01564 for (int i=0,max=p.data_GetChildrenCount(); i<max; i++)
01565 if (!data_GetConstChild(i).math_Compare(p.data_GetConstChild(i), flags))
01566 return math_GetCountOfChildrenOnly(p, flags);
01567
01568 total++;
01569 }
01570
01571 return total+math_GetCountOfChildrenOnly(p, flags);
01572 }
01573
01574 int mcElementHelpers::math_GetCountOf(const mcSymbolProperties *p, long flags) const
01575 {
01576 mcSymbol safe(p->data_GetSafeLinkedSym());
01577 mcASSERT(safe.data_isOk(), wxT("Invalid safe symbol ?"));
01578
01579 return math_GetCountOf(safe, flags);
01580 }
01581
01582 int mcElementHelpers::math_GetCountOf(const mcSymbolArray *p, long flags) const
01583 {
01584 int total = 0;
01585
01586
01587 for (int i=0; i<p->data_GetCount(); i++)
01588 total += math_GetCountOf(p->data_GetSymbol(i), flags);
01589
01590 return total;
01591 }
01592
01593 int mcElementHelpers::math_GetCountOfSymbolsType(const mcSymbolArray *p, long flags) const
01594 {
01595 int total = 0;
01596
01597
01598
01599
01600
01601 for (int i=0; i<p->data_GetCount(); i++)
01602 total += (int)math_ContainsSymbol(p->data_GetSymbol(i));
01603
01604 return total;
01605 }
01606
01607 int mcElementHelpers::math_Replace(const mcElement &tofind, int n, long flags,
01608 const mcElement &replacement, bool addchildren)
01609 {
01610 mcMATHLOG(wxT("mcElementHelpers::math_Replace [%s] - going to replace [%s] with [%s]"),
01611 mcTXTTHIS, mcTXT(tofind), mcTXT(replacement));
01612 mcElement p(mcEmptyElement);
01613 int ntotal = 0;
01614 bool onlyone = (n != -1);
01615 int occ = (onlyone ? n : 0);
01616
01617
01618 mcElement parent = math_Find(occ, tofind, flags | mcFIND_PARENT);
01619 if (parent == mcEmptyElement) return 0;
01620 const mcElement *currtofind = &parent;
01621
01622 mcElement currparent(mcEmptyElement);
01623 while (currtofind) {
01624
01625
01626
01627 currparent = math_Find(0, *currtofind, flags | mcFIND_PARENT);
01628 if (currparent == mcEmptyElement) break;
01629
01630
01631
01632 if (currparent.data_GetRefData()->data_GetRefCount() > 2)
01633 currtofind = &currparent;
01634 else
01635 currtofind = NULL;
01636 }
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 return ntotal;
01701 }
01702
01703
01704
01705
01706 mcMonomial mcElement::math_GetLCM(const mcElement &p) const
01707 { return hlp()->math_GetLCM(p); }
01708
01709 mcMonomial mcElement::math_GetGCD(const mcElement &p) const
01710 { return hlp()->math_GetGCD(p); }
01711
01712 mcMonomial mcElement::math_GetFactors() const
01713 { return hlp()->math_GetFactors(); }
01714
01715
01716
01717
01718 mcRealValue mcElementHelpers::math_EvaluateAt(const mcSymbolProperties *sym,
01719 const mcRealValue &symvalue) const
01720 {
01721 mcMATHLOG(wxT("mcElementHelpers::math_EvaluateAt [%s] - evaluating at [%s]=%s"),
01722 mcTXTTHIS, mcTXTP(sym), mcTXTV(symvalue));
01723
01724 #if 0
01725 mcSymbol symtorep;
01726 symtorep.data_LinkWith(&sym);
01727 mcNumber replacement;
01728 replacement.math_Set(symvalue);
01729
01730
01731
01732 mcMathMng *clone = this->Clone();
01733 clone.math_Replace(&symtorep, -1, &replacement, TRUE);
01734 mcRealValue res = clone.math_Evaluate();
01735 delete clone;
01736 #endif
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769 mcSymbolProperties *psym = (mcSymbolProperties *)sym;
01770
01771
01772 psym->m_bEvaluating = TRUE;
01773 psym->m_fValue = symvalue;
01774
01775
01776 mcRealValue res = math_Evaluate();
01777
01778
01779 psym->m_bEvaluating = FALSE;
01780 psym->m_fValue = *mcRealValue::pNAN;
01781
01782 mcMATHLOG(wxT("mcElementHelpers::math_EvaluateAt - result is %s"), mcTXTV(res));
01783 return res;
01784 }