00001 00002 // MathGUI = 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 "MathWnd.h" 00036 #endif 00037 00038 00039 // includes 00040 #include "mg/mgprec.h" 00041 #include <wx/wfstream.h> // not included by wxprec.h 00042 #include <wx/mstream.h> 00043 00044 #ifndef mgPRECOMP 00045 #include "mg/MathWnd.h" 00046 #endif 00047 00048 00049 00050 00051 // tell Doxygen not to parse the following lines 00052 #ifndef DOXYGEN_SKIP 00053 00054 // Creates the array of mgMathBox structures 00055 #include <wx/arrimpl.cpp> // this is a magic incantation which must be done! 00056 WX_DEFINE_OBJARRAY(wxMathBoxArray); 00057 00058 #endif 00059 00060 00061 #define CMATHWND_SPACE_LEFT 10 00062 #define CMATHWND_SPACE_RIGHT 10 00063 #define CMATHWND_SPACE_ABOVE 10 00064 #define CMATHWND_SPACE_BOTTOM 10 00065 00066 #define CMATHWND_DEFAULT_BOXWIDTH 140 00067 #define CMATHWND_DEFAULT_BOXHEIGHT 80 00068 00069 00070 // the event tables connect the wxWidgets events with the functions (event 00071 // handlers) which process them. It can be also done at run-time, but for the 00072 // simple menu events like this the static method is much simpler. 00073 IMPLEMENT_CLASS(mgMathWnd, wxScrolledWindow) 00074 BEGIN_EVENT_TABLE(mgMathWnd, wxScrolledWindow) 00075 00076 // children change handlers 00077 EVT_CHILD_CREATED(wxID_ANY, mgMathWnd::OnChildWindowChange) 00078 EVT_CHILD_MOVED(wxID_ANY, mgMathWnd::OnChildWindowChange) 00079 EVT_CHILD_RESIZED(wxID_ANY, mgMathWnd::OnChildWindowChange) 00080 EVT_CHILD_CLOSED(wxID_ANY, mgMathWnd::OnChildWindowChange) 00081 00082 // focus events 00083 //EVT_SET_FOCUS(mgMathWnd::OnSetFocus) 00084 /* EVT_KILL_FOCUS(mgMathWnd::OnFocusLost) 00085 00086 // miscellaneous events 00087 EVT_SIZE(mgMathWnd::OnSize)*/ 00088 //EVT_PAINT(mgMathWnd::OnPaint) 00089 00090 // mouse events 00091 /* EVT_RIGHT_DOWN(mgMathWnd::OnRDown) 00092 EVT_RIGHT_UP(mgMathWnd::OnRUp) 00093 EVT_LEFT_DOWN(mgMathWnd::OnLDown) 00094 EVT_LEFT_UP(mgMathWnd::OnLUp) 00095 EVT_MOTION(mgMathWnd::OnMouseMove) 00096 00097 // keyboard events 00098 EVT_CHAR(mgMathWnd::OnChar) 00099 00100 // context menu events 00101 EVT_MENU_RANGE(CUSTOMID_BASE, CUSTOMID_BASE+MAXMENU_ITEMS, mgMathWnd::OnCtxMenuItem)*/ 00102 END_EVENT_TABLE() 00103 00104 00105 00106 00107 00109 // Constructor\Destructor 00110 mgMathWnd::mgMathWnd(wxWindow *parent, wxWindowID id, 00111 const wxPoint &pos) : wxScrolledWindow(parent, -1, 00112 pos, parent->GetSize(), wxSUNKEN_BORDER | wxHSCROLL | wxVSCROLL | 00113 wxNO_FULL_REPAINT_ON_RESIZE, wxT("MathWnd")) 00114 { 00115 SetFocus(); 00116 //GetCaret()->Show(); 00117 00118 // set white as the window background color 00119 SetBackgroundColour(wxColour(255, 255, 255)); 00120 00121 // init all 00122 Clean(); 00123 00124 // SetFocus() seems not to work properly; place a SetFocus event 00125 // on the queue... 00126 wxFocusEvent evt(wxEVT_SET_FOCUS, GetId()); 00127 GetEventHandler()->AddPendingEvent(evt); 00128 00129 Refresh(); 00130 } 00131 00132 mgMathWnd::~mgMathWnd() { 00133 00134 // wxMathBoxArray will automatically delete all allocated objects... 00135 // it's too easy !!! :-) 00136 } 00138 00139 00141 // GENERAL functions 00142 void mgMathWnd::Clean() 00143 { 00144 // delete everything 00145 GetChildren().DeleteContents(TRUE); 00146 GetChildren().Clear(); 00147 00148 // re init 00149 m_nSelBox = 0; 00150 m_nActiveElemID = -1; 00151 AddBox(FALSE, FALSE); 00152 00153 // update cursor position, bitmap of current line and client size 00154 //UpdateCaretPos(); 00155 //CheckNewSize(); 00156 //UpdateBoxBmp(0); 00157 } 00158 00159 wxString mgMathWnd::GetDebug() 00160 { 00161 wxString str; 00162 00163 str = wxT("\n------------- Math window debug info: -------------\n\n"); 00164 for (int i=0; i < GetBoxCount(); i++) { 00165 00166 str += wxString::Format(wxT("||||||||||| MATH BOX #%d:\n"), i); 00167 str += GetBox(i)->GetDebug(); 00168 } 00169 00170 return str; 00171 } 00173 00174 00176 // SCROLLBAR functions 00177 void mgMathWnd::UpdateScrollRange() 00178 { 00179 wxNode *Child = GetChildren().First(); 00180 wxSize GesSize; 00181 while (Child) 00182 { 00183 wxWindow *chw = wxDynamicCast(Child->GetData(),wxResizeableControl); 00184 if (chw) 00185 { 00186 wxRect rect = chw->GetRect(); 00187 rect.x += GetScrollPos(wxHORIZONTAL); 00188 rect.y += GetScrollPos(wxVERTICAL); 00189 if (rect.GetBottom() > GesSize.y) 00190 GesSize.y = rect.GetBottom(); 00191 if (rect.GetRight() > GesSize.x) 00192 GesSize.x = rect.GetRight(); 00193 } 00194 Child = Child->Next(); 00195 } 00196 SetScrollbars(1,1,GesSize.x,GesSize.y, 00197 GetScrollPos(wxHORIZONTAL),GetScrollPos(wxVERTICAL),true); 00198 } 00200 00201 00203 // CURSOR functions 00204 /* 00205 void mgMathWnd::UpdateCaretPos() 00206 { 00207 // get current cursor position 00208 wxDC dc; 00209 int n; 00210 00211 GetCaret()->Move(GetBox(m_nSelBox)->GetCursorPos(dc, GetBox(m_nSelBox)->GetPosition().x, 00212 GetBox(m_nSelBox), &n))->GetPosition().y; 00213 GetCaret()->SetSize(mgMathWnd_CURSOR_WIDTH, n); 00214 } 00215 /* 00216 void mgMathWnd::SetCursorColor(wxColour col) 00217 { 00218 //m_brushCursor.SetColour(col); 00219 //m_penCursor.SetColour(col); 00220 }*/ 00221 /* 00222 void mgMathWnd::UpdateBB(wxDC &dc, wxPoint &cursor) 00223 { 00224 // this function must be as fast as possible (it's called at every 00225 // mouse movement) 00226 00227 // create some variables (remember that the window maybe scrolled) 00228 wxRect rc(GetBox(m_nSelBox), GetBox(m_nSelBox)->GetPosition()->GetPosition().y.x, 00229 GetBox(m_nSelBox)->GetWidth(), GetBox(m_nSelBox)->GetHeight()); 00230 00231 // check if cursor is inside the bb of the selected line 00232 if (rc.Inside(cursor)) { 00233 00234 // tranform from scrolled window coord to line coord. 00235 cursor.x -= GetBox(m_nSelBox)->GetPosition().x; 00236 cursor.y -= GetBox(m_nSelBox)->GetPosition().y; 00237 00238 // update the bitmap of the line; this step cannot be skipped because 00239 // this function also checks cursor position and the function isIDChanged() 00240 // is based on this check... 00241 UpdateBoxBmp(&cursor); 00242 00243 } else { 00244 00245 // update the bitmap of the line; this step cannot be skipped because 00246 // this function also checks cursor position and the function isIDChanged() 00247 // is based on this check... 00248 UpdateBoxBmp(DRW_NONACTIVE); 00249 } 00250 00251 // if the activation state hasn't changed, do nothing (to avoid 00252 // flickering) 00253 if (!GetBox(m_nSelBox)->isIDChanged()) 00254 return; 00255 00256 // redraw only the modified element 00257 ReDrawSelBox(dc); 00258 } 00259 /* 00260 void mgMathWnd::DrawCursor(bool bDraw) 00261 { 00262 // if user pressed a key, stop erasing the cursor for a while 00263 /*if (m_nWait > 0 && bDraw == FALSE) { 00264 m_nWait -= mgMathWnd_CURSOR_PERIOD; 00265 return; 00266 } 00267 00268 // create a DC for the window 00269 wxDC dc; 00270 00271 if (bDraw) { 00272 00273 // draw a black cursor 00274 dc.SetBrush(m_brushCursor); 00275 dc.SetPen(m_penCursor); 00276 dc.DrawRectangle(m_rcLastPosCursor); 00277 00278 } else { 00279 00280 // to erase old cursor, blit the current used bitmap on 00281 // the screen (current used bitmap is stored with also 00282 // activation and selection state, but without cursor) 00283 DrawBoxBmp(dc, m_nSelBox); 00284 } 00285 }*/ 00286 00288 00289 00290 00291 00293 // BOX UTILITY functions 00294 /* 00295 int mgMathWnd::UpdateBoxBmp(const wxPoint &p) 00296 { 00297 return GetBox(m_nSelBox)->UpdateBoxBmp(m_hMemDC, GetBox(m_nSelBox), GetBox(m_nSelBox), p)->GetPosition()->GetPosition().y.x; 00298 }*/ 00299 00300 00301 /* 00302 void mgMathWnd::UpdateBoxBmp() 00303 { 00304 wxPoint p = wxGetMousePosition(); 00305 00306 // remap cursor position in the correct way 00307 ScreenToClient(p); // from screen to window coord 00308 p.x -= GetBox(m_nSelBox)->GetPosition().x; // from scrolled window to line coord 00309 p.y -= GetBox(m_nSelBox)->GetPosition().y; 00310 00311 // use std version of the function 00312 UpdateBoxBmp(&p); 00313 }*/ 00314 00315 void mgMathWnd::SelectBox(int n) 00316 { 00317 //mcASSERT(n >= 0 && n < (int)GetBoxCount(), "Invalid new index"); 00318 00319 // save last line in the bitmap, without activation and selection state 00320 //GetBox(m_nSelBox)->DeSelect(); 00321 //UpdateBoxBmp(m_nSelBox, DRW_NONACTIVE); 00322 00323 // select the new line; caller should redraw to get a correct output 00324 m_nSelBox = n; 00325 /*wxFocusEvent ev(wxEVT_SET_FOCUS, GetBox(n)->GetId()); 00326 GetBox(n)->OnSetFocus(ev); 00327 GetBox(n)->Refresh();*/ 00328 //GetBox(n)->SetFocus(); 00329 ((GetChildren().Item(n))->GetData())->SetFocus(); 00330 00331 // update the bitmap of the selected line 00332 //UpdateBoxBmp(m_nSelBox); 00333 } 00334 00335 void mgMathWnd::AddBox(bool bMath, bool bCopyLast) 00336 { 00337 wxSize sz(CMATHWND_DEFAULT_BOXWIDTH, CMATHWND_DEFAULT_BOXHEIGHT); 00338 wxPoint pos(15, 15); 00339 00340 if (GetBoxCount() > 0) { 00341 int n = GetBoxCount()-1; 00342 pos = GetBox(n)->GetPosition(); 00343 pos.x += 0; pos.y += GetBox(n)->GetSize().GetHeight()+10; 00344 sz = GetBox(n)->GetSize(); 00345 } 00346 00347 // first of all, create a new mgMathBox 00348 mgResizeableBox *pnew; 00349 if (bMath) 00350 pnew = new mgResizeableMathBox(this, -1, pos, sz); 00351 else 00352 pnew = new mgResizeableTextBox(this, -1, pos, sz); 00353 m_arrMathBox.Add(pnew); 00354 00355 // create some pointers 00356 mgResizeableBox *pold = GetSelBox(); 00357 00358 // select the new line (so the bitmap of the previous 00359 // selected line is updated) 00360 SelectBox(GetChildren().GetCount()-1); 00361 //mgResizeableBox *boh = GetSelBox(); 00362 //mcASSERT(pnew == boh, "SelectBox doesn't work"); 00363 00364 // then, copy the last line if requested 00365 if (bCopyLast) { 00366 00367 // deep copy everything 00368 pnew->DeepCopy(*pold); 00369 } 00370 00371 // redraw 00372 Refresh(); 00373 } 00374 00375 /* 00376 void mgMathWnd::SelectBoxByPoint(wxPoint &pt) 00377 { 00378 wxRect rc; 00379 00380 // set up some fixed data on the rect structure 00381 rc.width = GetClientSize().GetWidth(); 00382 rc.x = GetBox(m_nSelBox)->GetPosition().x; 00383 00384 // move the cursor on another data line 00385 for (int i=0; i < 1; i++) { 00386 00387 // skip currently selected line; we have already tested 00388 // that it's not the line where the user clicked 00389 if (i == m_nSelBox) continue; 00390 00391 // set up the rect for this line 00392 rc.y = GetBox(m_nSelBox)->GetPosition().y; 00393 rc.height = GetBox(m_nSelBox)->GetHeight(); 00394 00395 // is the cursor inside this line's rectangle ? 00396 if (rc.Inside(pt)) { 00397 00398 // yes, select it 00399 SelectBox(i); 00400 00401 // update cursor data 00402 UpdateCaretPos(); 00404 00405 // redraw and exit this event handler 00406 Refresh(); 00407 return; 00408 } 00409 } 00410 00411 // no lines have been selected; deselect the current line 00412 GetBox(m_nSelBox)->DeSelect(); 00413 UpdateBoxBmp(m_nSelBox, &pt); 00414 Refresh(); 00415 } 00416 */ 00417 void mgMathWnd::DeleteBox(int n) 00418 { 00419 // removes the selected line 00420 (GetChildren().Item(n)->GetData())->Destroy(); 00421 00422 // select previous if following does not exist 00423 if (m_nSelBox >= 1) 00424 m_nSelBox--; 00425 00426 // redraw window 00427 Refresh(); 00428 } 00430 00431 00432 00433 00435 // mgMathWnd EVENT HANDLERS 00436 00437 void mgMathWnd::OnChildWindowChange(wxCommandEvent &ev) 00438 { 00439 // check which child window sent this message 00440 wxWindow *w = FindWindowById(ev.GetId(), this); 00441 if (w != NULL) { 00442 wxPoint newpos = w->GetPosition(); 00443 if (w->GetPosition().x < 0) newpos.x = 0; 00444 if (w->GetPosition().y < 0) newpos.y = 0; 00445 00446 w->Move(newpos); 00447 } 00448 00449 // scrollbar range could have changed 00450 UpdateScrollRange(); 00451 } 00452 00453 void mgMathWnd::OnPaint(wxPaintEvent &ev) 00454 { 00455 wxPaintDC dc(this); 00456 00457 // on MS windows, this sets up some optimizations 00458 dc.BeginDrawing(); 00459 00460 // draw all the lines 00461 //int y = GetBox(m_nSelBox)->GetPosition().y; 00462 //DrawBoxBmp(dc, TRUE); 00463 00464 for (int i=0; i < (int)m_arrMathBox.GetCount(); i++) { 00465 00466 // draw the line using stored bitmap 00467 //DrawBoxBmp(dc, i, TRUE); 00468 00469 // add the space between two lines 00470 //y += mgMathWnd_SPACE_INTERLINE; 00471 GetBox(i)->Refresh(); 00472 } 00473 00474 00475 // be sure to unselect from memory DC previous bmp 00476 //m_hMemDC.SelectObject(wxNullBitmap); 00477 00478 // on MS windows, shut down draw optimizations 00479 dc.EndDrawing(); 00480 } 00481 00482 void mgMathWnd::OnSize(wxSizeEvent &se) 00483 { 00484 //int w = se.GetSize().GetWidth()-GetBox(m_nSelBox)->GetPosition().x-CMATHWND_SPACE_RIGHT; 00485 00486 // update width inside all lines; this is required for line 00487 // description feature 00488 /*for (int i=0; i < 1; i++) 00489 GetBox(m_nSelBox)->SetParentWidth(w);*/ 00490 00491 // update also cursor pos (it could be inside line description) 00492 //UpdateCaretPos(); 00493 } 00494 00495 00497 // MOUSE events 00498 /* 00499 void mgMathWnd::OnLDown(wxMouseEvent &me) 00500 { 00501 // stop flashing cursor 00502 GetCaret()->Show(FALSE); 00503 00504 // prepare some variables 00505 wxDC dc; 00506 wxPoint pt = me.GetLogicalPosition(dc); 00507 00508 // get some data 00509 wxRect rc(GetBox(m_nSelBox), GetBox(m_nSelBox), GetBox(m_nSelBox)->GetWidth()->GetPosition()->GetPosition().y.x, 00510 GetBox(m_nSelBox)->GetHeight());// = GetBoxBB(m_nSelBox); 00511 00512 // move the cursor where user clicked 00513 if (rc.Inside(pt)) { 00514 00515 // move the cursor inside the math data 00516 GetBox(m_nSelBox)->MoveCursor(dc, MC_USEPOINT, pt.x, pt.y-GetBox(m_nSelBox))->GetPosition().y; 00517 UpdateCaretPos(); 00518 00519 } /*else { 00520 00521 // try to select line using the point 00522 SelectBoxByPoint(pt); 00523 }*/ 00524 /* 00525 // set up the capture of the cursor 00526 m_ptOrigin = pt; 00527 00528 m_rcSelection.x = m_ptOrigin.x; 00529 m_rcSelection.y = m_ptOrigin.y; 00530 00531 // capture the mouse (so, if it exits the window 00532 // the OnLUP function will still be called) 00533 CaptureMouse(); 00534 00535 // change cursor 00536 //SetCursor(wxCursor(wxCURSOR_RIGHT_ARROW));//*wxCROSS_CURSOR); 00537 } 00538 00539 void mgMathWnd::OnRDown(wxMouseEvent &me) 00540 { 00541 //wxDC dc; 00542 //wxMenu m; 00543 //wxPoint pt = me.GetLogicalPosition(dc); 00544 //OnLDown(me); 00545 00546 //SelectBoxByPoint(pt); 00547 //GetBox(m_nSelBox)->GetMathObj()->MultiplyBySel(); 00548 00549 //UpdateBoxBmp(m_nSelBox, &pt); 00550 //ReDrawSelBox(dc); 00551 00552 //PopupMenu(&m, me.GetPosition()); 00553 } 00554 00555 void mgMathWnd::OnLUp(wxMouseEvent &me) 00556 { 00557 // maybe the user just selected another data line 00558 if (GetCapture() == this) { 00559 00560 // restore the conditions before the user started the click 00561 ReleaseMouse(); 00562 //SetCursor(wxNullCursor); 00563 //m_tCursor.Start(); 00564 00565 // move the cursor inside the math data 00566 wxDC dc; 00567 wxPoint pt = me.GetLogicalPosition(dc); 00568 wxRect rc(GetBox(m_nSelBox), GetBox(m_nSelBox)->GetPosition()->GetPosition().y.x, 00569 GetBox(m_nSelBox)->GetWidth(), GetBox(m_nSelBox)->GetHeight()); 00570 00571 // check if point is over the selected line 00572 if (rc.Inside(pt)) { 00573 00574 // user released button over the selected line; move the cursor 00575 // to the nearest available position 00576 GetBox(m_nSelBox)->MoveCursor(dc, MC_USEPOINT, pt.x, pt.y-GetBox(m_nSelBox))->GetPosition().y; 00577 UpdateCaretPos(); 00578 } else if (!rc.Inside(m_ptOrigin)) { 00579 00580 // user clicked in an empty area and released the button in another 00581 // empty area 00582 //OnSyntaxErr("Nothing in that point"); 00583 } 00584 00585 /*wxString tmp; 00586 tmp.Printf(wxT("top-left: %d, %d\n\nwidth: %d\nheight: %d\n\norigin: %d, %d"), m_rcSelection.x, m_rcSelection.y, m_rcSelection.width, m_rcSelection.height, m_ptOrigin.x, m_ptOrigin.y); 00587 wxMessageBox(tmp, _(wxT("About g_nsMathStudio")), wxOK | wxICON_INFORMATION, this);*/ 00588 /* } 00589 } 00590 00591 void mgMathWnd::OnRUp(wxMouseEvent &me) 00592 { 00593 wxDC dc; 00594 wxMenu m; 00595 00596 // get the point in scrolled window coord 00597 wxPoint tmp = me.GetLogicalPosition(dc); 00598 00599 if (m_nActiveElemID != DRW_ONSELECTION) { 00600 00601 // create a dummy selection rectangle 00602 m_rcSelection.x = tmp.x; 00603 m_rcSelection.y = tmp.y; 00604 m_rcSelection.width = 1; 00605 m_rcSelection.height = 1; 00606 00607 // select the element under cursor 00608 int n = GetBox(m_nSelBox)->GetPosition().y; 00609 GetBox(m_nSelBox)->OnSelect(dc, GetBox(m_nSelBox), GetBox(m_nSelBox), m_rcSelection)->GetPosition()->GetPosition().y.x; 00610 UpdateBoxBmp(&tmp); 00611 ReDrawSelBox(dc); 00612 } 00613 00614 // get an array of string from the math object 00615 wxArrayString arr = GetBox(m_nSelBox)->GetPossibleOpOnSel(m_nCmdID); 00616 for (int i=0; i < (int)arr.GetCount(); i++) { 00617 m.Append(CUSTOMID_BASE+i, arr.Item(i)); 00618 } 00619 00620 // pop up the context menu 00621 PopupMenu(&m, tmp); 00622 } 00623 00624 void mgMathWnd::OnCtxMenuItem(wxCommandEvent &ce) 00625 { 00626 wxDC dc; 00627 00628 // exec the command chosen by the user 00629 GetBox(m_nSelBox)->ExecCmdOnSel(m_nCmdID[ce.GetId()-CUSTOMID_BASE-2]); 00630 //GetBox(m_nSelBox)->GetMathObj()->Debug(); 00631 00632 // update cursor pos and redraw the window 00633 //CheckNewSize(); 00634 UpdateCaretPos(); 00635 UpdateBoxBmp(); 00636 00637 // redraw only modified line 00638 ReDrawSelBox(dc); 00639 } 00640 00641 void mgMathWnd::OnMouseMove(wxMouseEvent &me) 00642 { 00643 wxDC dc; 00644 00645 // get the point in scrolled window coord 00646 wxPoint tmp = me.GetLogicalPosition(dc); 00647 00648 if (me.LeftIsDown()) { 00649 00650 // update selection rectangle 00651 m_rcSelection.x = m_ptOrigin.x; 00652 m_rcSelection.y = m_ptOrigin.y; 00653 m_rcSelection.width = tmp.x-m_ptOrigin.x; 00654 m_rcSelection.height = tmp.y-m_ptOrigin.y; 00655 if (m_rcSelection.width < 0) { 00656 m_rcSelection.x += m_rcSelection.width; 00657 m_rcSelection.width = -m_rcSelection.width; 00658 } 00659 if (m_rcSelection.height < 0) { 00660 m_rcSelection.y += m_rcSelection.height; 00661 m_rcSelection.height = -m_rcSelection.height; 00662 } 00663 00664 // check that everything's okay 00665 mcASSERT(m_rcSelection.width >= 0 && m_rcSelection.height >= 0, wxT("invalid rect")); 00666 mcASSERT(m_rcSelection.x >= 0 && m_rcSelection.y >= 0, wxT("invalid rect")); 00667 00668 // update selection 00669 GetBox(m_nSelBox)->OnSelect(dc, GetBox(m_nSelBox), GetBox(m_nSelBox), m_rcSelection)->GetPosition()->GetPosition().y.x; 00670 00671 // redraw for some strange reasons... :-) 00673 ReDrawSelBox(dc); 00674 } 00675 00676 UpdateBB(dc, tmp); 00677 } 00678 00679 00680 00682 // FOCUS events 00683 */ 00684 void mgMathWnd::OnSetFocus(wxFocusEvent &fe) 00685 { 00686 //for (int i=0; i < GetBoxCount(); i++) 00687 // GetBox(i)->SetFocus(); 00688 } 00689 /* 00690 void mgMathWnd::OnFocusLost(wxFocusEvent &fe) 00691 { 00692 // stop drawing cursor 00693 //m_tCursor.Stop(); 00694 00695 // erase it, and the next time, draw it 00696 //DrawCursor(FALSE);//, NULL); 00697 //m_nShow = TRUE; 00698 } 00699 00700 00701 00703 // MISCELLANEOUS events 00704 00705 void mgMathWnd::OnTimer(wxTimerEvent &te) 00706 { 00707 // draw or erase the cursor 00708 //DrawCursor(m_nShow);//, NULL); 00709 00710 // next time, do the opposite 00711 //m_nShow = !m_nShow; 00712 } 00713 00714 void mgMathWnd::OnChar(wxKeyEvent &ke) 00715 { 00716 wxDC dc; 00717 00718 switch (ke.m_keyCode) { 00719 00720 // cursor movement keys handlers 00721 case WXK_LEFT: 00722 GetBox(m_nSelBox)->MoveCursor(dc, mcMCF_LEFT, 0, 0); 00723 break; 00724 case WXK_RIGHT: 00725 GetBox(m_nSelBox)->MoveCursor(dc, mcMCF_RIGHT, 0, 0); 00726 break; 00727 case WXK_UP: 00728 GetBox(m_nSelBox)->MoveCursor(dc, mcMCF_UP, 0, 0); 00729 break; 00730 case WXK_DOWN: 00731 GetBox(m_nSelBox)->MoveCursor(dc, mcMCF_DOWN, 0, 0); 00732 break; 00733 case WXK_HOME: 00734 GetBox(m_nSelBox)->SetCursorPos(mcCP_BEGIN); 00735 break; 00736 case WXK_END: 00737 GetBox(m_nSelBox)->SetCursorPos(mcCP_END); 00738 break; 00739 00740 00741 default: 00742 // a numpad key was pressed; ignore it; this function will be called 00743 // again, by wxWidgets, with a translated ASCII code 00744 if (ke.m_keyCode >= WXK_NUMPAD0 && ke.m_keyCode <= WXK_NUMPAD9) 00745 return; 00746 00747 // a little exception: if user pressed CTRL+ENTER we must correct, 00748 // on win32 the key event which we receive.... 00749 if (ke.ControlDown() && ke.GetKeyCode() == 10) { 00750 00751 #ifdef __WXMSW__ 00752 // Get Win32 native scancode 00753 if ((ke.GetRawKeyFlags() >> 16) == 28) // 28 = ENTER scancode 00754 ke.m_keyCode = 13; 00755 #endif 00756 } 00757 00758 // one of ()0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 00759 // or abcdefghijklmnopqrstuvwxyz key was pressed 00760 GetBox(m_nSelBox)->Input(ke);//(unsigned char)ke.GetKeyCode(), (int)ke.GetKeyCode()); 00761 } 00762 00763 // update cursor pos and redraw the window 00764 //CheckNewSize(m_nSelBox); 00765 UpdateCaretPos(); 00766 UpdateBoxBmp(); 00767 00768 // redraw only modified line 00769 ReDrawSelBox(dc); 00770 } 00772 00773 00774 */ 00775 00776 bool mgMathWnd::Export(bool bXHTML, const wxString &filename, 00777 const wxString &title, bool bMathPlayer, bool bUpperTag, 00778 bool bUseNS, const wxString &ns, const wxString &href, 00779 int indentstep) 00780 { 00781 wxFile f; 00782 wxString err; 00783 00784 // create a new file with the given name in write mode, 00785 // overwrite existing if necessary 00786 mcASSERT(filename.Len() > 0, wxT("Incorrect file name")); 00787 if (f.Open(filename, wxFile::write) == FALSE) { 00788 00789 err.Printf(wxT("Cannot overwrite %s. The file is being used by another application\n") \ 00790 wxT("which opened the file in exclusive mode. Close all the applications that use\n") \ 00791 wxT("this file and retry, or choose another file name."), filename.c_str()); 00792 wxMessageBox(err, wxT("Error"), wxICON_ERROR | wxOK | wxCENTRE); 00793 return FALSE; 00794 } 00795 00796 wxFileOutputStream stream(f); 00797 mcASSERT(stream.Ok(), wxT("Something wrong with the creation of file")); 00798 00799 // write in the file using native line ending 00800 //wxTextOutputStream stream(fstream, wxEOL_NATIVE); 00801 return Export(bXHTML, stream, title, FALSE, bMathPlayer, 00802 bUpperTag, bUseNS, ns, href, indentstep); 00803 } 00804 00805 wxString mgMathWnd::GetExportPreview(bool bXHTML, const wxString &title, bool bMathPlayer, 00806 bool bUpperTag, bool bUseNS, const wxString &ns, const wxString &href, 00807 int indentstep) 00808 { 00809 /*wxMemoryOutputStream mos; 00810 wxString res; 00811 00812 if (Export(bXHTML, mos, title, TRUE, bMathPlayer, 00813 bUpperTag, bUseNS, ns, href, indentstep) == FALSE) 00814 return wxString(wxT("CANNOT PREVIEW !!!")); 00815 00816 // copy directly inside the string 00817 mos.CopyTo(res.GetWriteBuf(mos.GetSize()+1), mos.GetSize()); 00818 res[mos.GetSize()] = wxT('\0'); 00819 res.UngetWriteBuf();*/ 00820 00821 return wxEmptyString; 00822 } 00823 00824 bool mgMathWnd::Export(bool bXHTML, wxOutputStream &stream, 00825 const wxString &title, bool bPreview, bool bMathPlayer, 00826 bool bUpperTag, bool bUseNS, const wxString &ns, 00827 const wxString &href, int indentstep) 00828 { 00829 wxString err, str; 00830 00831 00832 // close file and return OK 00833 return TRUE; 00834 } 00835 00836 bool mgMathWnd::Import(int type, const wxString &filename, wxString *pDesc) 00837 { 00838 /* wxXml2Document doc; 00839 wxXml2Node root, cur; 00840 wxString str, err; 00841 int n=0; 00842 00843 // check parameters 00844 mcASSERT(filename.Len() > 0, wxT("Incorrect file name")); 00845 00846 // load the given file 00847 wxFileInputStream def(filename); 00848 wxString file(filename); 00849 wxString tmpfilename; 00850 00851 if (def.Ok() == FALSE) { 00852 00853 // load error 00854 err.Printf(wxT("Cannot read %s. The file is being used by another application\n") \ 00855 wxT("which opened the file in exclusive mode. Close all the applications that use\n") \ 00856 wxT("this file and retry, or choose another file."), filename.c_str()); 00857 wxMessageBox(err, wxT("Error"), wxICON_ERROR | wxOK | wxCENTRE); 00858 return FALSE; 00859 } 00860 00861 // check if loaded file is an XML or an XHTML file 00862 def.Read(str.GetWriteBuf(16), 16); 00863 str.UngetWriteBuf(); 00864 def.SeekI(0); 00865 00866 if (str.CmpNoCase(wxT("<?xml")) != 0 || str.CmpNoCase(wxT("<? xml")) != 0) { 00867 00868 // we must convert this (X)HTML file to an XML file; we will use 00869 // a temporary file 00870 tmpfilename = wxFileName::CreateTempFileName(wxT("ms")); 00871 wxFileOutputStream tmpoutstream(tmpfilename); 00872 00873 wxString xmlhdr = wxT("<?xml version=\")1.0\wxT(" encoding=\")UTF-8\wxT(" standalone=\")no\wxT("?>\n") 00874 wxT("<?xml-stylesheet type=\")text/xsl\wxT(" href=\")" + wxGetCwd() + 00875 wxT("/XSL/mathml.xsl\")?>\n"; 00876 00877 tmpoutstream.Write(xmlhdr, xmlhdr.Len()); 00878 //tmpoutstream.SeekO(0, wxFromEnd); 00879 tmpoutstream.Write(def); 00880 file = tmpfilename; 00881 } 00882 00883 // parse the given file 00884 if (doc.Load(file, &err) == FALSE) { 00885 00886 // parse error 00887 wxMessageBox(wxT(wxT("There was an error while parsing and the given file\n") 00888 wxT("couldn't be imported. Error description:\n\n'")) + err + wxT("'"), 00889 wxT("Error"), wxICON_ERROR | wxOK | wxCENTRE); 00890 if (!tmpfilename.IsEmpty()) 00891 wxRemoveFile(tmpfilename); 00892 return FALSE; 00893 } 00894 00895 // delete the eventually created temporary file 00896 if (!tmpfilename.IsEmpty()) 00897 wxRemoveFile(tmpfilename); 00898 00899 // find MATH tags and import their contents; ignore everything else 00900 root = doc.GetRoot(); 00901 cur = root.Find(wxT("math"), wxT(""), 0, FALSE); 00902 00903 if (cur == wxXml2EmptyNode) { 00904 // we couldn't find it 00905 err.Printf(wxT("Cannot find the MathML main tag <MATH>. The file does not contain\n") 00906 wxT("any MathML information or it is corrupt.")); 00907 wxMessageBox(err, wxT("Error"), wxICON_ERROR | wxOK | wxCENTRE); 00908 return FALSE; 00909 } 00910 00911 // extract MathML content from the xml document 00912 while (cur != wxXml2EmptyNode) { 00913 00914 wxXml2Node toparse = cur.GetChildren(); 00915 00916 while (toparse != wxXml2EmptyNode) { 00917 00918 // be sure everything is embedded in an MROW section 00919 if (toparse.GetType() == wxXML_ELEMENT_NODE) { 00920 00921 if (toparse.GetName() != wxT("mrow")) 00922 toparse = EncapsulateInMROW(toparse); 00923 00924 // add a new line and import this MATH tags in it 00925 //if (n > 0) AddBox(FALSE); 00926 GetBox(m_nSelBox)->ImportMathML(toparse, &err); 00927 } 00928 00929 toparse = toparse.GetNext(); 00930 } 00931 00932 // search other MATH tags 00933 cur = root.Find(wxT("math"), wxT(""), n, FALSE); 00934 } 00935 */ 00936 return TRUE; 00937 } 00938 00939 00940
[ Top ] |