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 "ExpContainer.cpp"
00037 #endif
00038
00039
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042 #pragma hdrstop
00043 #endif
00044
00045 #ifndef mcPRECOMP
00046 #include "mc/Element.h"
00047 #include "mc/ExpContainer.h"
00048 #endif
00049
00050
00051
00052 mcIMPLEMENT_ABSTRACT_CLASS(mcExpContainer, mcExpElement);
00053
00054
00055
00056
00057
00058
00059
00060 bool mcExpContainerHelpers::gui_isBaseEndKey(const mcKey &ev) const
00061 {
00062
00063 switch (mgui_nCursorPos) {
00064 case mcEXPCONTAINER_LEFTMOST:
00065 case mcEXPCONTAINER_RIGHTMOST:
00066 if (mcMathCore::Get()->MatchEditKeys(ev))
00067 return FALSE;
00068 return TRUE;
00069 }
00070
00071
00072 mcASSERT(mgui_nCursorPos == mcEXPCONTAINER_INSIDEEXPR, wxT("Invalid cursor position"));
00073 return FALSE;
00074 }
00075
00076 void mcExpContainerHelpers::gui_EditBase()
00077 {
00078
00079 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00080 mgui_nCursorLoc = mcECL_INSIDEBASE;
00081 }
00082
00083 void mcExpContainerHelpers::gui_OnBaseSelect(wxDC &dc, wxRect &rc)
00084 {
00085
00086
00087 wxPoint orig(gui_GetContentOffsetX(), gui_GetContentOffsetY());
00088 wxRect content(orig, data_GetContent().gui_GetSize());
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 if (content.Intersects(rc)) {
00105
00106 rc.Offset(-content.x, -content.y);
00107 data_GetContent().gui_OnSelect(dc, rc);
00108 }
00109
00110
00111 if (data_GetContent().gui_isSelected())
00112 gui_Select();
00113 }
00114
00115 int mcExpContainerHelpers::gui_DrawBase(wxDC &dc, int x, int y, long flags,
00116 const wxPoint &pt) const
00117 {
00118 wxPoint org(x+gui_GetContentOffsetX(), y+gui_GetContentOffsetY()), mypt=pt;
00119 wxRect rc(org, data_GetContent().gui_GetSize());
00120 bool ret = FALSE;
00121 int r;
00122
00123 if (flags & mcDRW_USEPOINT) {
00124
00125 if (rc.Inside(pt)) {
00126
00127
00128
00129 ret = TRUE;
00130
00131 } else {
00132
00133
00134
00135 flags &= ~mcDRW_USEPOINT;
00136 }
00137 }
00138
00139
00140
00141 flags &= ~mcDRW_ALLOW_TOTAL_SELECTION;
00142 if (!data_GetContent().gui_isAllSelected())
00143 flags |= mcDRW_ALLOW_TOTAL_SELECTION;
00144
00145
00146 r = data_GetContent().gui_Draw(dc, org.x, org.y, flags, mypt);
00147
00148
00149 gui_DrawContainer(dc, x, y, flags, pt);
00150
00151
00152 return (ret == TRUE) ? r : data_GetID();
00153 }
00154
00155 mcInputRes mcExpContainerHelpers::gui_BaseInput(const mcKey &key, mcElement *pnew)
00156 {
00157
00158 if (gui_isBeginKey(key) != FALSE &&
00159 !data_hasProperty(mcEP_INITIALIZED)) {
00160
00161
00162 data_GetContent().gui_AddNewEmptyMonomial();
00163
00164
00165 data_AddProperty(mcEP_INITIALIZED);
00166 gui_RecalcSize();
00167
00168 return mcIR_OKAY;
00169 }
00170
00171
00172
00173 if (mgui_nCursorPos == mcEXPCONTAINER_LEFTMOST ||
00174 mgui_nCursorPos == mcEXPCONTAINER_RIGHTMOST) {
00175
00176 if (gui_HandleSubExpEditKeys(key) == mcIR_OKAY)
00177 return mcIR_OKAY;
00178 }
00179
00180 switch (mgui_nCursorPos) {
00181 case mcEXPCONTAINER_LEFTMOST:
00182
00183 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key)) {
00184
00185
00186 return mcIR_DELETE_PREVIOUS;
00187
00188 } else if (mcMathCore::Get()->m_pCancelKey->MatchKey(key)) {
00189
00190
00191 return mcIR_DELETE_THIS;
00192 }
00193
00194 mcMathCore::Get()->SyntaxError(wxT("Cannot type here"));
00195 break;
00196
00197 case mcEXPCONTAINER_RIGHTMOST:
00198
00199 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key)) {
00200
00201
00202 return mcIR_DELETE_THIS;
00203
00204 } else if (mcMathCore::Get()->m_pCancelKey->MatchKey(key)) {
00205
00206
00207 return mcIR_DELETE_NEXT;
00208 }
00209
00210 mcMathCore::Get()->SyntaxError(wxT("Cannot type here"));
00211 break;
00212
00213 case mcEXPCONTAINER_INSIDEEXPR:
00214
00215
00216 mcInputRes r = data_GetContent().gui_Input(key, pnew);
00217 return gui_HandleContentInput(r, pnew);
00218 }
00219
00220 return mcIR_OKAY;
00221 }
00222
00223 mcInsertRes mcExpContainerHelpers::gui_BaseInsert(const mcElement &toinsert, mcElement *)
00224 {
00225 mcASSERT(mgui_nCursorPos != mcEXPCONTAINER_LEFTMOST &&
00226 mgui_nCursorPos != mcEXPCONTAINER_RIGHTMOST,
00227 wxT("Invalid position"));
00228
00229 return data_GetContent().gui_Insert(toinsert, NULL);
00230 }
00231
00232 mcInputRes mcExpContainerHelpers::gui_HandleContentInput(mcInputRes r, mcElement *)
00233 {
00234 switch (r) {
00235 case mcIR_OKAY:
00236 break;
00237
00238 case mcIR_DELETE_THIS:
00239 case mcIR_DELETE_PREVIOUS:
00240 case mcIR_DELETE_NEXT:
00241 return mcIR_DELETE_THIS;
00242
00243 default:
00244 mcASSERT(0, wxT("Unhandled return flag"));
00245 }
00246
00247
00248 gui_RecalcSize();
00249 return mcIR_OKAY;
00250 }
00251
00252 mcMoveCursorRes mcExpContainerHelpers::gui_BaseMoveCursor(mcMoveCursorFlag flag, long modifiers)
00253 {
00254 mcMoveCursorRes result;
00255
00256
00257
00258 if (mgui_nCursorPos == mcEXPCONTAINER_LEFTMOST ||
00259 mgui_nCursorPos == mcEXPCONTAINER_RIGHTMOST) {
00260
00261 if (flag == mcMCF_UP)
00262 return mcMCR_SETFOCUS_ABOVE;
00263 if (flag == mcMCF_DOWN)
00264 return mcMCR_SETFOCUS_BELOW;
00265 }
00266
00267 switch (mgui_nCursorPos) {
00268 case mcEXPCONTAINER_LEFTMOST:
00269 mcASSERT(gui_isLeftPosEnabled(), wxT("Cursor position is wrong"));
00270
00271
00272
00273 if (flag == mcMCF_LEFT) {
00274
00275
00276
00277 return mcMCR_SETFOCUS_PREVIOUS;
00278
00279 } else if (flag == mcMCF_RIGHT) {
00280
00281
00282
00283 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00284 data_GetContent().gui_SetCursorPos(mcCP_BEGIN);
00285 }
00286 break;
00287
00288 case mcEXPCONTAINER_INSIDEEXPR:
00289
00290
00291
00292
00293 result = data_GetContent().gui_MoveCursor(flag, modifiers);
00294
00295
00296 if (result == mcMCR_SETFOCUS_PREVIOUS) {
00297 if (gui_isLeftPosEnabled())
00298 mgui_nCursorPos = mcEXPCONTAINER_LEFTMOST;
00299 else
00300 return mcMCR_SETFOCUS_PREVIOUS;
00301
00302 } else if (result == mcMCR_SETFOCUS_NEXT) {
00303 if (gui_isRightPosEnabled())
00304 mgui_nCursorPos = mcEXPCONTAINER_RIGHTMOST;
00305 else
00306 return mcMCR_SETFOCUS_NEXT;
00307
00308 } else if (result == mcMCR_SETFOCUS_BELOW || result == mcMCR_SETFOCUS_ABOVE) {
00309
00310
00311 return result;
00312 }
00313 break;
00314
00315 case mcEXPCONTAINER_RIGHTMOST:
00316 mcASSERT(gui_isRightPosEnabled(), wxT("Cursor position is wrong"));
00317
00318
00319
00320 if (flag == mcMCF_RIGHT) {
00321
00322
00323 return mcMCR_SETFOCUS_NEXT;
00324
00325 } else if (flag == mcMCF_LEFT) {
00326
00327
00328
00329 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00330 data_GetContent().gui_SetCursorPos(mcCP_END);
00331 }
00332 break;
00333
00334 default:
00335 mcASSERT(0, wxT("Unhandled cursor position"));
00336 }
00337
00338 return mcMCR_OKAY;
00339 }
00340
00341 int mcExpContainerHelpers::gui_BaseMoveCursorUsingPoint(wxDC &hDC, const wxPoint &pt)
00342 {
00343 wxRect rc(wxPoint(0, 0), data_GetContent().gui_GetSize());
00344 wxPoint mypt(pt);
00345
00346
00347 if (rc.Inside(mypt)) {
00348
00349 mypt.x -= gui_GetContentOffsetX();
00350 mypt.y -= gui_GetContentOffsetY();
00351
00352
00353 int r = data_GetContent().gui_MoveCursorUsingPoint(hDC, mypt);
00354 if (r == mcMCR_CANNOT_SETFOCUS)
00355 return mcMCR_CANNOT_SETFOCUS;
00356
00357
00358 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00359 return mcMCR_OKAY;
00360 }
00361
00362
00363 if (mypt.x < gui_GetContentOffsetX() && gui_isLeftPosEnabled()) {
00364 mgui_nCursorPos = mcEXPCONTAINER_LEFTMOST;
00365 return mcMCR_OKAY;
00366 }
00367 if (mypt.x > gui_GetContentOffsetX()+rc.GetWidth() && gui_isRightPosEnabled()) {
00368 mgui_nCursorPos = mcEXPCONTAINER_RIGHTMOST;
00369 return mcMCR_OKAY;
00370 }
00371
00372 return mcMCR_CANNOT_SETFOCUS;
00373 }
00374
00375 int mcExpContainerHelpers::gui_GetBaseRelCursorPos(wxDC &hDC, wxPoint *pt) const
00376 {
00377 int n;
00378
00379 switch (mgui_nCursorPos) {
00380 case mcEXPCONTAINER_LEFTMOST:
00381 pt->x = 0;
00382 pt->y = 0;
00383
00384
00385 return gui_GetBaseSize().GetHeight();
00386
00387 case mcEXPCONTAINER_INSIDEEXPR:
00388 n = data_GetContent().gui_GetRelCursorPos(hDC, pt);
00389 pt->x += gui_GetContentOffsetX();
00390 pt->y += gui_GetContentOffsetY();
00391
00392
00393 return n;
00394
00395 case mcEXPCONTAINER_RIGHTMOST:
00396 pt->x = gui_GetBaseSize().GetWidth();
00397 pt->y = 0;
00398
00399
00400 return gui_GetBaseSize().GetHeight();
00401 }
00402
00403
00404
00405 mcASSERT(0, wxT("Unhandled cursor position"));
00406
00407
00408 return 0;
00409 }
00410
00411 void mcExpContainerHelpers::gui_GetBaseCursorPos(mcCursorPos &cp) const
00412 {
00413 if (mgui_nCursorPos == mcEXPCONTAINER_LEFTMOST)
00414 cp.gui_Push(mcCP_BEGIN);
00415 else if (mgui_nCursorPos == mcEXPCONTAINER_RIGHTMOST)
00416 cp.gui_Push(mcCP_END);
00417 else
00418 cp.gui_Push(mgui_nCursorPos);
00419 }
00420
00421 void mcExpContainerHelpers::gui_SetBaseCursorPos(const mcCursorPos &n)
00422 {
00423 if (n.isBegin()) {
00424 if (gui_isLeftPosEnabled())
00425 mgui_nCursorPos = mcEXPCONTAINER_LEFTMOST;
00426 else {
00427 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00428 data_GetContent().gui_SetCursorPos(mcCP_BEGIN);
00429 }
00430 }
00431
00432 if (n.isEnd()) {
00433 if (gui_isRightPosEnabled())
00434 mgui_nCursorPos = mcEXPCONTAINER_RIGHTMOST;
00435 else {
00436 mgui_nCursorPos = mcEXPCONTAINER_INSIDEEXPR;
00437 data_GetContent().gui_SetCursorPos(mcCP_END);
00438 }
00439 }
00440 }
00441
00442 int mcExpContainerHelpers::gui_GetYAnchor() const
00443 {
00444 return gui_GetContentOffsetY() + gui_GetBaseOffsety() +
00445 data_GetContent().gui_GetYAnchor();
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455 wxXml2Node mcExpContainerHelpers::io_GetBaseMathML(bool bGetPresentation) const
00456 {
00457 wxXml2Node maintag(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, io_GetMathMLPresentationTag());
00458 wxXml2Node child = data_GetContent().io_GetMathML(bGetPresentation);
00459 maintag.AddChild(child);
00460
00461 return maintag;
00462 }
00463
00464 bool mcExpContainerHelpers::io_ImportPresentationMathML(wxXml2Node tag, wxString &pErr)
00465 {
00466 mcASSERT(tag.GetName() == io_GetMathMLPresentationTag(),
00467 wxT("Error in mcExpContainerHelpers::io_isBeginTag"));
00468
00469
00470 wxXml2Node child = tag.GetChildren();
00471 if (child.GetNext() != wxXml2EmptyNode) {
00472
00473
00474 child.Encapsulate(wxT("mrow"));
00475 }
00476
00477 return data_GetContent().io_ImportPresentationMathML(child, pErr);
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 bool mcExpContainerHelpers::math_CompareThisOnly(const mcElement &p, long flags) const
00489 {
00490 if (p.data_GetType() == data_GetType()) {
00491
00492
00493
00494 const mcPolynomial &pcontents = mcExpContainer(p).data_GetConstContent();
00495
00496 if (pcontents.math_Compare(data_GetContent(), flags))
00497 return TRUE;
00498 }
00499
00500 return FALSE;
00501 }
00502
00503 bool mcExpContainerHelpers::math_CanBeAddedWith(const mcElement &p) const
00504 {
00505
00506 if (p.data_GetType() != data_GetType())
00507 return FALSE;
00508
00509 mcExpContainer e(p);
00510 const mcPolynomial &content = e.data_GetContent();
00511 return data_GetContent().math_CanBeAddedWith(content);
00512 }
00513
00514 bool mcExpContainerHelpers::math_CanBeDivBy(const mcElement &p) const
00515 {
00516
00517 if (p.data_GetType() != data_GetType())
00518 return FALSE;
00519
00520 mcExpContainer e(p);
00521 const mcPolynomial &content = e.data_GetConstContent();
00522 return data_GetContent().math_CanBeDivBy(content);
00523 }
00524
00525 bool mcExpContainerHelpers::math_CanBeMultWith(const mcElement &p) const
00526 {
00527
00528 if (p.data_GetType() != data_GetType())
00529 return FALSE;
00530
00531 mcExpContainer e(p);
00532 const mcPolynomial &content = e.data_GetContent();
00533 return data_GetContent().math_CanBeMultWith(content);
00534 }
00535
00536 mcPolynomial mcExpContainerHelpers::math_GetRaisedContents() const
00537 {
00538 mcPolynomial res(data_GetContent());
00539 if (!math_hasExp()) return res;
00540
00541
00542
00543 res.math_RaiseTo(math_GetExp());
00544
00545 return res;
00546 }
00547
00548 mcExpSimRes mcExpContainerHelpers::math_SimplifyBaseExp(long flags, mcElement *pnew)
00549 {
00550 mcMATHLOG(wxT("mcExpContainerHelpers::math_SimplifyBaseExp [%s]"), mcTXTTHIS);
00551
00552
00553
00554
00555
00556
00557 if (!data_GetContent().math_CanBeRaisedTo(math_GetExp()) ||
00558 (flags & mcEXPSIM_KEEP_FACTORIZATION))
00559 return mcESR_DONE;
00560
00561
00562
00563
00564 data_GetContent().math_RaiseTo(math_GetExp());
00565 data_DestroyExpSub(TRUE);
00566
00567 return mcESR_NOTFINISHED;
00568 }
00569
00570 mcExpSimRes mcExpContainerHelpers::math_SimplifyBase(long flags, mcElement *newelem)
00571 {
00572
00573 mcExpSimRes res = data_GetContent().math_Simplify(flags, newelem);
00574 if (res != mcESR_DONE) return res;
00575
00576
00577 return math_SimplifyContents(flags, newelem);
00578 }
00579
00580 mcExpSimRes mcExpContainerHelpers::math_ExpandBase(long flags, mcElement *newelem)
00581 {
00582
00583 mcExpSimRes res = data_GetContent().math_Expand(flags, newelem);
00584 if (res != mcESR_DONE) return res;
00585
00586
00587 return math_ExpandContents(flags, newelem);
00588 }
00589
00590 mcBasicOpRes mcExpContainerHelpers::math_DivideBaseOnlyBy(const mcElement &p, mcElement *pp)
00591 {
00592 if (p.data_GetType() != data_GetType()) return mcBOR_INVALID;
00593 mcExpContainer e(p);
00594 return data_GetContent().math_DivideBy(e.data_GetContent(), pp);
00595 }
00596
00597 mcBasicOpRes mcExpContainerHelpers::math_Add(const mcElement &p, mcElement *pp, bool add)
00598 {
00599 if (p.data_GetType() != data_GetType()) return mcBOR_INVALID;
00600 mcExpContainer e(p);
00601 return data_GetContent().math_Add(e.data_GetContent(), pp, add);
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611 mcBasicOpRes mcExpContainerHelpers::math_MultiplyBaseOnlyBy(const mcElement &p, mcElement *pp)
00612 {
00613 if (p.data_GetType() != data_GetType()) return mcBOR_INVALID;
00614 mcExpContainer e(p);
00615 return data_GetContent().math_MultiplyBy(e.data_GetContent(), pp);
00616 }
00617
00618 mcMonomial mcExpContainerHelpers::math_GetFactors() const
00619 { return data_GetContent().math_GetFactors(); }
00620