5 * Created by Toshi Nagata on 08/10/24.
6 * Copyright 2008 Toshi Nagata. All rights reserved.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation version 2 of the License.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
18 // For compilers that support precompilation, includes "wx/wx.h".
19 #include "wx/wxprec.h"
29 #if !wxUSE_DOC_VIEW_ARCHITECTURE
30 #error "You should have DocView architecture enabled in your wxWidgets installation."
33 #include "MoleculeView.h"
36 #include "MyDocument.h"
37 #include "MyGLCanvas.h"
38 #include "MyCommand.h"
40 #include "MyListCtrl.h"
41 #include "../MolLib/Missing.h"
44 #include "wx/tglbtn.h"
45 #include "wx/listctrl.h"
46 #include "wx/splitter.h"
47 #include "wx/choice.h"
50 //#include "../MolLib/Ruby_bind/Molby_extern.h"
59 myID_RotateBondSlider,
62 myID_FrameControlPanel,
64 myID_JumpToStartButton,
65 myID_PlayBackwardButton,
67 myID_PlayForwardButton,
73 IMPLEMENT_DYNAMIC_CLASS(MoleculeView, wxView)
75 BEGIN_EVENT_TABLE(MoleculeView, wxView)
76 EVT_TOGGLEBUTTON(myID_RotButton, MoleculeView::OnButtonPressed)
77 EVT_TOGGLEBUTTON(myID_TransButton, MoleculeView::OnButtonPressed)
78 EVT_TOGGLEBUTTON(myID_ScaleButton, MoleculeView::OnButtonPressed)
79 EVT_TOGGLEBUTTON(myID_SelectButton, MoleculeView::OnButtonPressed)
80 EVT_TOGGLEBUTTON(myID_BondButton, MoleculeView::OnButtonPressed)
81 EVT_TOGGLEBUTTON(myID_EraseButton, MoleculeView::OnButtonPressed)
82 EVT_COMMAND(wxID_ANY, MySliderEvent, MoleculeView::OnSliderAction)
83 EVT_COMMAND_SCROLL(myID_FrameSlider, MoleculeView::OnFrameSliderAction)
84 EVT_TEXT_ENTER(myID_FrameText, MoleculeView::OnFrameTextAction)
85 EVT_CHOICE(myID_TableMenu, MoleculeView::OnSelectTable)
86 EVT_ACTIVATE(MoleculeView::OnActivate)
88 #define ConnectMouseDownEvents(src, func, target) \
89 (src->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(func), NULL, target), \
90 src->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(func), NULL, target))
94 MoleculeView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
98 // Make a document frame
99 frame = new wxDocMDIChildFrame(doc, this, GetMainFrame(), wxID_ANY, _T("New Molby Document"),
100 wxPoint(10, 24), wxSize(680, 400),
101 wxDEFAULT_FRAME_STYLE |
102 wxNO_FULL_REPAINT_ON_RESIZE);
108 file_history_menu = NULL;
110 memset(tbuttons, 0, sizeof(tbuttons));
112 frameControlPanel = NULL;
115 isRebuildingTable = false;
117 wxMenuBar *menu_bar = wxGetApp().CreateMenuBar(1, &file_history_menu, &edit_menu);
119 // Associate the menu bar with the frame
120 frame->SetMenuBar(menu_bar);
122 // Associate the edit menu with the command processor
123 doc->GetCommandProcessor()->SetEditMenu(edit_menu);
125 mview = MainView_newMainView(this);
127 // Create the window content
129 // A splitter window embraces a grid (left) and main screen (right)
130 wxSplitterWindow *splitter = new wxSplitterWindow(frame, -1, wxDefaultPosition, wxDefaultSize, wxSP_3D | wxSP_LIVE_UPDATE);
132 // Create the left half
133 // A panel containing a popup menu and a list window
134 wxPanel *panel0 = new wxPanel(splitter);
138 sizer0 = new wxBoxSizer(wxVERTICAL);
139 wxArrayString choiceItems;
141 MainView_tableTitleForIndex(mview, i, buf, sizeof buf);
144 wxString itemTitle(buf, WX_DEFAULT_CONV);
145 choiceItems.Add(itemTitle);
147 /* static wxString choiceItems[] = {
148 wxT("atoms"), wxT("bonds"), wxT("angles"), wxT("dihedrals"), wxT("impropers"), wxT("MO info")
151 listmenu = new wxChoice(panel0, myID_TableMenu, wxDefaultPosition, wxDefaultSize, choiceItems);
152 sizer0->Add(listmenu, 0, wxALL, 0);
154 listctrl = new MyListCtrl();
155 listctrl->Create(panel0, myID_Table, wxDefaultPosition, wxDefaultSize);
156 sizer0->Add(listctrl, 1, wxALL | wxEXPAND, 0);
157 panel0->SetSizer(sizer0);
160 // Create the right half
161 // A panel containing MyGLCanvas, buttons, sliders, etc.
162 wxPanel *panel1 = new wxPanel(splitter);
164 { // Vertical sizer containing [sizer2, sizer3, sizer4]
166 sizer1 = new wxBoxSizer(wxVERTICAL);
168 { // Horizontal sizer containing [button0, button1, ..., button5, infotext]
170 sizer2 = new wxBoxSizer(wxHORIZONTAL);
172 { // Button0..5 (Rot/Trans/Scale/Select/Bond/Erase)
173 wxString labels[] = {
174 wxT("Rot"), wxT("Trans"), wxT("Scale"), wxT("Select"), wxT("Bond"), wxT("Erase")
177 myID_RotButton, myID_TransButton, myID_ScaleButton,
178 myID_SelectButton, myID_BondButton, myID_EraseButton
180 for (i = 0; i < 6; i++) {
181 tbuttons[i] = new wxToggleButton(panel1, ids[i], labels[i], wxDefaultPosition, wxSize(40, 16));
182 sizer2->Add(tbuttons[i], 0, wxALL | wxEXPAND, 3);
184 tbuttons[0]->SetValue(true);
186 { // Information text
187 infotext = new wxStaticText(panel1, -1, wxT(""), wxDefaultPosition, wxSize(40, 16), wxST_NO_AUTORESIZE | wxBORDER_SUNKEN);
188 infotext->SetMinSize(wxSize(80, 32));
189 infotext->SetFont(*wxSMALL_FONT);
190 sizer2->Add(infotext, 1, wxALL | wxEXPAND, 3); // Can expand horizontally
193 sizer1->Add(sizer2, 0, wxALL | wxEXPAND, 0);
196 { // Horizontal sizer containing [sizer31, sizer32, sizer33]
197 wxBoxSizer *sizer3 = new wxBoxSizer(wxHORIZONTAL);
199 { // Vertical sizer containing [button, mySlider]
200 wxBoxSizer *sizer31 = new wxBoxSizer(wxVERTICAL);
201 { // "Rotate bond" button and mySlider
202 #include "../bitmaps/rotate_bond.xpm"
203 wxBitmap bmp1(rotate_bond_xpm, wxBITMAP_TYPE_XPM);
204 wxBitmapButton *button1 = new wxBitmapButton(panel1, -1, bmp1, wxDefaultPosition, wxSize(21, 21));
205 sizer31->Add(button1, 0, 0, 0);
207 MySlider *slider1 = new MySlider(panel1, myID_RotateBondSlider, wxVERTICAL, wxDefaultPosition, wxSize(21, 21));
208 sizer31->Add(slider1, 1, wxEXPAND);
210 sizer3->Add(sizer31, 0, wxALL | wxEXPAND, 0);
213 { // Vertical sizer containing [Canvas, [button, mySlider]]
214 wxBoxSizer *sizer32 = new wxBoxSizer(wxVERTICAL);
216 canvas = new MyGLCanvas(this, panel1, wxDefaultPosition, wxSize(100, 100));
217 sizer32->Add(canvas, 1, wxALL | wxEXPAND, 0);
219 // Let the MyGLCanvas pass the keyboard event to this
220 canvas->Connect(-1, wxEVT_CHAR, wxKeyEventHandler(MoleculeView::OnChar), NULL, this);
223 wxBoxSizer *sizer321 = new wxBoxSizer(wxHORIZONTAL);
225 #include "../bitmaps/rotate_y.xpm"
226 wxBitmap bmp2(rotate_y_xpm, wxBITMAP_TYPE_XPM);
227 wxBitmapButton *button2 = new wxBitmapButton(panel1, -1, bmp2, wxDefaultPosition, wxSize(21, 21));
228 sizer321->Add(button2, 0, 0, 0);
230 MySlider *slider2 = new MySlider(panel1, myID_RotateYSlider, wxHORIZONTAL, wxDefaultPosition, wxSize(21, 21));
231 sizer321->Add(slider2, 1, wxEXPAND);
233 sizer32->Add(sizer321, 0, wxEXPAND);
235 sizer3->Add(sizer32, 1, wxEXPAND);
238 { // Vertical sizer containing [button, mySlider]
239 wxBoxSizer *sizer33 = new wxBoxSizer(wxVERTICAL);
240 { // "Rotate bond" button and mySlider
241 #include "../bitmaps/rotate_x.xpm"
242 wxBitmap bmp3(rotate_x_xpm, wxBITMAP_TYPE_XPM);
243 wxBitmapButton *button3 = new wxBitmapButton(panel1, -1, bmp3, wxDefaultPosition, wxSize(21, 21));
245 sizer33->Add(button3, 0, 0, 0);
247 MySlider *slider3 = new MySlider(panel1, myID_RotateXSlider, wxVERTICAL, wxDefaultPosition, wxSize(21, 21));
248 sizer33->Add(slider3, 1, wxEXPAND);
250 sizer3->Add(sizer33, 0, wxALL | wxEXPAND, 0);
253 sizer1->Add(sizer3, 1, wxALL | wxEXPAND, 0);
256 { // Horizontal sizer containing frame controls
258 const int height = 18;
259 frameControlPanel = new wxPanel(panel1, myID_FrameControlPanel, wxDefaultPosition, wxSize(200, height));
260 wxBoxSizer *sizer4 = new wxBoxSizer(wxHORIZONTAL);
262 frameSlider = new wxSlider(frameControlPanel, myID_FrameSlider, 0, 0, 0, wxDefaultPosition, wxSize(40, height - 2));
263 sizer4->Add(frameSlider, 1, wxALL | wxEXPAND, 1);
265 #include "../bitmaps/jump_to_start.xpm"
266 wxBitmap bmp41(jump_to_start_xpm, wxBITMAP_TYPE_XPM);
267 wxBitmapButton *button41 = new wxBitmapButton(frameControlPanel, myID_JumpToStartButton, bmp41, wxDefaultPosition, wxSize(16, height));
268 sizer4->Add(button41, 0, wxEXPAND);
269 ConnectMouseDownEvents(button41, MoleculeView::OnFrameButtonAction, this);
271 #include "../bitmaps/play_backward.xpm"
272 wxBitmap bmp42(play_backward_xpm, wxBITMAP_TYPE_XPM);
273 wxBitmapButton *button42 = new wxBitmapButton(frameControlPanel, myID_PlayBackwardButton, bmp42, wxDefaultPosition, wxSize(16, height));
274 sizer4->Add(button42, 0, wxEXPAND);
275 ConnectMouseDownEvents(button42, MoleculeView::OnFrameButtonAction, this);
278 frameText = new wxTextCtrl(frameControlPanel, myID_FrameText, wxT(""), wxDefaultPosition, wxSize(40, height));
279 wxFont font(9, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
280 wxTextAttr attr(*wxBLACK, wxNullColour, font);
281 frameText->SetDefaultStyle(attr);
282 sizer4->Add(frameText, 0, wxEXPAND);
285 #include "../bitmaps/play_forward.xpm"
286 wxBitmap bmp43(play_forward_xpm, wxBITMAP_TYPE_XPM);
287 wxBitmapButton *button43 = new wxBitmapButton(frameControlPanel, myID_PlayForwardButton, bmp43, wxDefaultPosition, wxSize(16, height));
288 sizer4->Add(button43, 0, wxEXPAND);
289 ConnectMouseDownEvents(button43, MoleculeView::OnFrameButtonAction, this);
291 #include "../bitmaps/jump_to_end.xpm"
292 wxBitmap bmp44(jump_to_end_xpm, wxBITMAP_TYPE_XPM);
293 wxBitmapButton *button44 = new wxBitmapButton(frameControlPanel, myID_JumpToEndButton, bmp44, wxDefaultPosition, wxSize(16, height));
294 sizer4->Add(button44, 0, wxEXPAND);
295 ConnectMouseDownEvents(button44, MoleculeView::OnFrameButtonAction, this);
297 wxPanel *spacer = new wxPanel(frameControlPanel, -1, wxDefaultPosition, wxSize(21, height));
298 sizer4->Add(spacer, 0, wxEXPAND);
300 frameControlPanel->SetSizer(sizer4);
301 sizer1->Add(frameControlPanel, 0, wxALL | wxEXPAND, 0);
302 // controls->Disable();
305 panel1->SetSizer(sizer1);
308 splitter->SplitVertically(panel0, panel1);
310 wxBoxSizer *mainsizer = new wxBoxSizer(wxHORIZONTAL);
311 mainsizer->Add(splitter, 1, wxEXPAND);
312 frame->SetSizer(mainsizer);
315 splitter->SetSashPosition(240, true);
317 // Associate the molecule with the main view
318 MainView_setMolecule(mview, ((MyDocument *)doc)->GetMolecule());
320 // Initialize table view
321 MainView_createColumnsForTableAtIndex(mview, 0);
323 // Select table popup
324 listmenu->SetSelection(0);
326 #if defined(__X__) || defined(__WXMAC__)
327 // X seems to require a forced resize
329 frame->GetSize(&x, &y);
330 frame->SetSize(wxDefaultCoord, wxDefaultCoord, x, y);
335 // Initial keyboard focus is on the GL canvas (to accept 'S' for scale, etc.)
338 // Connect the notification handler
339 doc->Connect(MyDocumentEvent_documentModified, MyDocumentEvent, wxCommandEventHandler(MoleculeView::OnDocumentModified), NULL, this);
341 wxGetApp().Connect(MyDocumentEvent_scriptMenuModified, MyDocumentEvent, wxCommandEventHandler(MoleculeView::OnScriptMenuModified), NULL, this);
343 // Intercept the double-click handler of MyListCtrl
344 listctrl->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(MoleculeView::OnLeftDClickInListCtrl), NULL, this);
350 MoleculeView::OnDraw(wxDC *dc)
352 if (mview != NULL && mview->mol != NULL) {
353 MoleculeLock(mview->mol);
354 MainView_drawModel(mview);
355 MoleculeUnlock(mview->mol);
360 MoleculeView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint))
365 /* Maybe necessary in some platforms (not in MacOSX and MSW) */
368 wxClientDC dc(canvas);
376 MoleculeView::OnClose(bool deleteWindow)
378 if (!GetDocument()->Close())
381 // Dispose relationship between MainView and Molecule
382 MainView_setMolecule(mview, NULL);
383 // Release the MainView object
384 MainView_release(mview);
387 // Dispose Connection between DocManager and file history menu
388 wxGetApp().DocManager()->FileHistoryRemoveMenu(file_history_menu);
390 // Clear the canvas in case we're in single-window mode,
391 // and the canvas stays.
392 /* canvas->ClearBackground();
396 wxString s(wxTheApp->GetAppName());
413 MoleculeView::UpdateFrameControlValues()
415 if (mview == NULL || mview->mol == NULL)
419 cframe = mview->mol->cframe;
420 str.Printf(_T("%d"), cframe);
421 frameText->SetValue(str);
422 frameSlider->SetValue(cframe);
426 MoleculeView::UpdateFrameControls()
429 bool enabled = false;
430 if (mview != NULL && mview->mol != NULL) {
431 MoleculeLock(mview->mol);
432 nframes = MoleculeGetNumberOfFrames(mview->mol);
433 MoleculeUnlock(mview->mol);
438 frameControlPanel->Enable(enabled);
440 frameSlider->SetRange(0, nframes - 1);
441 UpdateFrameControlValues();
443 frameSlider->SetRange(0, 0);
444 frameText->SetValue(_T(""));
446 frameControlPanel->Update();
450 MoleculeView::SelectButtonForMode(int mode)
453 if (mode >= 1 && mode <= 6) {
454 for (i = 0; i < 6; i++) {
455 tbuttons[i]->SetValue((i == mode - 1));
458 MainViewCallback_setKeyboardFocus(mview);
462 MoleculeView::OnButtonPressed(wxCommandEvent& event)
464 int eventId = event.GetId();
465 int mode = eventId - myID_RotButton + kTrackballRotateMode;
466 MainView_setMode(mview, mode);
467 SelectButtonForMode(mode);
471 MoleculeView::OnSliderAction(wxCommandEvent& event)
473 int eventId = event.GetId();
474 int mode = eventId - myID_RotateBondSlider + 1;
475 MySlider *sender = (MySlider *)event.GetEventObject();
476 float angle = sender->GetFloatValue();
477 int mouseStatus = sender->GetMouseStatus();
478 MoleculeLock(mview->mol);
479 MainView_rotateBySlider(mview, angle * 3.1415927 * 2, mode, mouseStatus, MainViewCallback_modifierFlags(NULL));
480 MoleculeUnlock(mview->mol);
484 MoleculeView::OnFrameButtonAction(wxMouseEvent &event)
486 int ival, nframes, bid;
487 if (mview == NULL || mview->mol == NULL)
489 nframes = MoleculeGetNumberOfFrames(mview->mol);
493 if (bid == myID_JumpToStartButton) {
495 } else if (bid == myID_JumpToEndButton) {
497 } else if (bid == myID_PlayForwardButton) {
498 ival = (mview->mol->cframe + 1) % nframes;
499 } else if (bid == myID_PlayBackwardButton) {
500 ival = (mview->mol->cframe + nframes - 1) % nframes;
502 // TODO: implement continuous move
503 if (ival >= 0 && ival < nframes) {
504 MoleculeLock(mview->mol);
505 MoleculeSelectFrame(mview->mol, ival, 1);
506 MoleculeUnlock(mview->mol);
507 MainViewCallback_display(mview);
508 UpdateFrameControlValues();
516 MoleculeView::OnFrameSliderAction(wxScrollEvent &event)
519 if (mview == NULL || mview->mol == NULL)
521 MoleculeLock(mview->mol);
522 nframes = MoleculeGetNumberOfFrames(mview->mol);
524 ival = frameSlider->GetValue();
525 if (ival >= 0 && ival < nframes) {
526 MoleculeSelectFrame(mview->mol, ival, 1);
527 MoleculeUnlock(mview->mol);
528 MainViewCallback_display(mview);
529 UpdateFrameControlValues();
533 MoleculeUnlock(mview->mol);
537 MoleculeView::OnFrameTextAction(wxCommandEvent &event)
541 if (mview == NULL || mview->mol == NULL)
543 MoleculeLock(mview->mol);
544 nframes = MoleculeGetNumberOfFrames(mview->mol);
546 str = frameText->GetValue();
547 ival = atoi((const char *)str.mb_str(WX_DEFAULT_CONV));
548 if (ival >= 0 && ival < nframes) {
549 MoleculeSelectFrame(mview->mol, ival, 1);
550 MoleculeUnlock(mview->mol);
551 MainViewCallback_display(mview);
552 UpdateFrameControlValues();
556 MoleculeUnlock(mview->mol);
560 MoleculeView::OnDocumentModified(wxCommandEvent& event)
562 if (!mview->freezeScreen) {
565 UpdateFrameControls();
566 MoleculeLock(mview->mol);
567 MainView_refreshTable(mview);
568 MoleculeUnlock(mview->mol);
571 if (mview->tableIndex == kMainViewParameterTableIndex && mview->mol->parameterTableSelectionNeedsClear) {
572 /* Clear parameter selection if necessary */
573 MainViewCallback_setTableSelection(mview, NULL);
574 mview->mol->parameterTableSelectionNeedsClear = 0;
577 /* printf("MoleculeView::OnDocumentModified invoked\n"); */
578 event.Skip(); /* Continue processing of the notification */
582 MoleculeView::OnScriptMenuModified(wxCommandEvent& event)
584 wxGetApp().UpdateScriptMenu(frame->GetMenuBar());
589 MoleculeView::OnChar(wxKeyEvent &event)
591 int code = event.GetKeyCode();
593 bool noMod = ((event.GetModifiers() | wxMOD_SHIFT) == wxMOD_SHIFT);
594 // MyAppCallback_showScriptMessage("MoleculeView::OnChar invoked\n");
595 if (code == WXK_BACK || code == WXK_DELETE || code == 0x7f || code == 8) {
596 MoleculeLock(mview->mol);
597 MainView_delete(mview);
598 MoleculeUnlock(mview->mol);
599 } else if (noMod && (code == 'r' || code == 'R'))
600 mode = kTrackballRotateMode;
601 else if (noMod && (code == 't' || code == 'T'))
602 mode = kTrackballTranslateMode;
603 else if (noMod && (code == 's' || code == 'S'))
604 mode = kTrackballScaleMode;
605 else if (noMod && (code == ' '))
606 mode = kTrackballSelectionMode;
607 else if (noMod && (code == 'b' || code == 'B'))
608 mode = kTrackballCreateMode;
609 else if (noMod && (code == 'e' || code == 'E'))
610 mode = kTrackballEraseMode;
616 MainView_setMode(mview, mode);
617 MainViewCallback_selectMatrixCellForMode(mview, mode);
622 MoleculeView::SelectTable(int idx)
624 if (idx >= 0 && idx < listmenu->GetCount() && idx != mview->tableIndex) {
625 isRebuildingTable = true;
626 listmenu->SetSelection(idx);
627 MainView_createColumnsForTableAtIndex(mview, idx);
628 isRebuildingTable = false;
629 MoleculeLock(mview->mol);
630 MainView_refreshTable(mview);
631 MoleculeUnlock(mview->mol);
632 if (idx == kMainViewParameterTableIndex || idx == kMainViewMOTableIndex) {
633 MainViewCallback_setTableSelection(mview, NULL);
639 MoleculeView::OnSelectTable(wxCommandEvent &event)
641 if (!isRebuildingTable) {
642 MoleculeLock(mview->mol);
643 SelectTable(listmenu->GetSelection());
644 MoleculeUnlock(mview->mol);
649 MoleculeView::OnLeftDClickInListCtrl(wxMouseEvent &event)
651 listctrl->OnLeftDClick(event);
652 if (mview->tableIndex >= kMainViewBondTableIndex && mview->tableIndex <= kMainViewImproperTableIndex && mview->mol->par != NULL) {
654 char names[64], types[64], value[20], params[3][20];
655 char *ptype, *parstr;
656 wxPoint pos = event.GetPosition();
657 if (!listctrl->FindItemAtPosition(pos, &row, &col) || col < 4)
659 /* Start editing the local parameter; open a separate dialog */
660 MainView_valueForTable(mview, 1, row, names, sizeof names);
661 MainView_valueForTable(mview, 2, row, types, sizeof types);
662 MainView_valueForTable(mview, 3, row, value, sizeof value);
663 for (i = 0; i < 3; i++) {
664 MainView_valueForTable(mview, 4 + i, row, params[i], sizeof(params[0]));
666 switch (mview->tableIndex) {
667 case kMainViewBondTableIndex: ptype = "bond"; break;
668 case kMainViewAngleTableIndex: ptype = "angle"; break;
669 case kMainViewDihedralTableIndex: ptype = "dihedral"; break;
670 case kMainViewImproperTableIndex: ptype = "improper"; break;
673 asprintf(&parstr, "%s %s %s", params[0], params[1], params[2]);
674 MolActionCreateAndPerform(mview->mol, SCRIPT_ACTION("sssss"), "cmd_edit_local_parameter_in_mainview", ptype, names, types, value, parstr);
679 MoleculeView::OnActivate(wxActivateEvent &event)
681 if (!event.GetActive()) {
682 listctrl->EndEditText(true);
687 #pragma mark ====== MyListCtrl data source ======
690 MoleculeView::GetItemCount(MyListCtrl *ctrl)
692 return MainView_numberOfRowsInTable(mview);
696 MoleculeView::GetItemText(MyListCtrl *ctrl, long row, long column) const
699 MainView_valueForTable(mview, column, row, buf, sizeof buf);
700 wxString *str = new wxString(buf, WX_DEFAULT_CONV);
705 MoleculeView::SetItemText(MyListCtrl *ctrl, long row, long column, const wxString &value)
707 MainView_setValueForTable(mview, column, row, value.mb_str(WX_DEFAULT_CONV));
712 MoleculeView::DragSelectionToRow(MyListCtrl *ctrl, long row)
714 MainView_dragTableSelectionToRow(mview, row);
718 MoleculeView::IsItemEditable(MyListCtrl *ctrl, long row, long column)
720 return MainView_isTableItemEditable(mview, column, row);
724 MoleculeView::IsDragAndDropEnabled(MyListCtrl *ctrl)
726 /* Only enabled for the atom table */
727 return (MainView_tableType(mview) == 0);
731 MoleculeView::OnSelectionChanged(MyListCtrl *ctrl)
733 MainView_setSelectionFromTable(mview);
737 MoleculeView::SetItemColor(MyListCtrl *ctrl, long row, long col, float *fg, float *bg)
739 if (mview != NULL && mview->mol != NULL) {
740 return MainView_setColorForTable(mview, col, row, fg, bg);
742 if (mview->tableIndex == kMainViewParameterTableIndex && col == -1) {
743 int src = ParameterTableGetItemSource(mview->mol->par, row);
744 if (src == -2) { // separator line
745 bg[0] = bg[1] = bg[2] = 0.6;
747 } else if (src == -1) { // undefined parameters
751 } else if (src == 0) { // local parameter
756 } else if (mview->tableIndex > 0 && mview->tableIndex < 5) {
757 return MainView_setColorForTable(mview, col, row, fg, bg);
764 #pragma mark ====== Plain C interface ======
767 MainViewCallback_modifierFlags(void *eventRef)
771 wxMouseState state = ::wxGetMouseState();
773 if (state.ShiftDown())
774 flags |= kShiftKeyMask;
776 flags |= kAltKeyMask;
781 MainViewCallback_clickCount(void *eventRef)
783 wxMouseEvent *mevent = (wxMouseEvent *)eventRef;
784 if (mevent != NULL) {
785 if (mevent->LeftDClick())
787 else if (mevent->LeftDown() || mevent->LeftUp())
795 MainViewCallback_lockFocus(MainView *mview)
797 if (mview != NULL && mview->ref != NULL)
798 ((MoleculeView *)(mview->ref))->canvas->SetCurrent();
802 MainViewCallback_unlockFocus(MainView *mview)
804 // if (mview != NULL && mview->ref != NULL)
805 // [[(MyWindowController *)(mview->ref) myOpenGLView] unlockFocus];
809 MainViewCallback_frame(MainView *mview, float *rect)
811 if (mview != NULL && mview->ref != NULL) {
813 ((MoleculeView *)(mview->ref))->canvas->GetClientSize(&width, &height);
814 rect[0] = rect[1] = 0.0;
818 rect[0] = rect[1] = rect[2] = rect[3] = 0.0;
823 MainViewCallback_display(MainView *mview)
825 if (mview != NULL && mview->ref != NULL) {
826 wxWindow *canvas = ((MoleculeView *)(mview->ref))->canvas;
833 MainViewCallback_setNeedsDisplay(MainView *mview, int flag)
835 if (mview != NULL && mview->ref != NULL) {
837 ((MoleculeView *)(mview->ref))->canvas->Refresh();
842 MainViewCallback_setKeyboardFocus(MainView *mview)
844 if (mview != NULL && mview->ref != NULL) {
845 ((MoleculeView *)(mview->ref))->canvas->SetFocus();
850 MainViewCallback_clearLabels(MainView *mview)
854 if (mview != NULL && mview->ref != NULL) {
855 id view = [(MyWindowController *)(mview->ref) myOverlayView];
856 NSRect bounds = [view bounds];
859 [[NSColor cyanColor] set];
860 bounds.origin.x = bounds.size.width / 2;
863 [view setNeedsDisplay: YES];
869 MainViewCallback_drawLabel(MainView *mview, const float *pos, const char *label)
873 if (mview != NULL && mview->ref != NULL) {
874 id view = [(MyWindowController *)(mview->ref) myOverlayView];
875 NSString *s = [NSString stringWithUTF8String: label];
876 NSDictionary *attr = [(MyWindowController *)(mview->ref) labelAttributes];
878 [s drawAtPoint: NSMakePoint(pos[0], pos[1]) withAttributes: attr];
880 [view setNeedsDisplay: YES];
886 MainViewCallback_drawInfoText(MainView *mview, const char *label)
888 if (mview != NULL && mview->ref != NULL) {
889 wxString labelstr(label, WX_DEFAULT_CONV);
890 ((MoleculeView *)(mview->ref))->infotext->SetLabel(labelstr);
895 MainViewCallback_mouseCheck(MainView *mview)
901 MainViewCallback_selectMatrixCellForMode(MainView *mview, int mode)
903 if (mview != NULL && mview->ref != NULL)
904 ((MoleculeView *)(mview->ref))->SelectButtonForMode(mode);
908 //MainViewCallback_getTag(MainView *mview)
910 // if (mview != NULL && mview->ref != NULL)
911 // return [(MyWindowController *)(mview->ref) myTag];
916 MainViewCallback_viewWithTag(int tag)
918 wxList &doclist = wxGetApp().DocManager()->GetDocuments();
919 wxList::iterator iter;
921 for (i = 0, iter = doclist.begin(); iter != doclist.end(); ++i, ++iter) {
923 return ((MoleculeView *)(((MyDocument *)(*iter))->GetFirstView()))->mview;
927 //wxList::compatibility_iterator iter = doclist.Item(tag);
929 // return (MyDocument *)(*iter)->GetFirstView()->mview;
933 // if (sMyWindowControllers == nil)
935 // for (i = [sMyWindowControllers count] - 1; i >= 0; i--) {
936 // id obj = [sMyWindowControllers objectAtIndex: i];
937 // if ([obj myTag] == tag)
938 // return [obj mainView];
944 MainViewCallback_activeView(void)
946 MoleculeView *cview = (MoleculeView *)(wxGetApp().DocManager()->GetCurrentView());
951 // return ((MoleculeView *)(wxGetApp().DocManager()->GetCurrentView()))->mview;
952 // return MainViewCallback_viewWithTag(sLastMainViewTag);
956 MainViewCallback_newFromFile(const char *fname)
959 wxDocManager *manager = wxGetApp().DocManager();
960 if (fname == NULL || *fname == 0) {
961 doc = manager->CreateDocument(wxT(""), wxDOC_NEW);
963 wxString fnamestr(fname, wxConvFile);
964 doc = manager->CreateDocument(fnamestr, wxDOC_SILENT);
966 return MainViewCallback_activeView();
970 MainViewCallback_importFromFile(MainView *mview, const char *fname)
973 if (mview != NULL && mview->ref != NULL && (doc = (((MoleculeView *)(mview->ref))->MolDocument())) != NULL) {
974 wxString fnamestr(fname, wxConvFile);
975 // doc->importFromFile(fnamestr);
976 MainViewCallback_setNeedsDisplay(mview, 1);
983 MainViewCallback_getFilename(MainView *mview, char *buf, int bufsize)
986 if (mview != NULL && mview->ref != NULL && (doc = (((MoleculeView *)(mview->ref))->MolDocument())) != NULL) {
988 fname = doc->GetFilename();
989 strncpy(buf, (const char*)fname.mb_str(wxConvFile), bufsize - 1);
990 buf[bufsize - 1] = 0;
997 MainViewCallback_moleculeReplaced(MainView *mview, struct Molecule *mol)
999 if (mview != NULL && mview->ref != NULL) {
1000 MyDocument *doc = ((MoleculeView *)(mview->ref))->MolDocument();
1002 doc->SetMolecule(mol);
1003 MyListCtrl *listctrl = ((MoleculeView *)(mview->ref))->GetListCtrl();
1004 if (listctrl != NULL)
1005 listctrl->SetDataSource((MoleculeView *)(mview->ref));
1009 typedef struct Label {
1010 // StringTexture *tex;
1014 MainViewCallback_newLabel(MainView *mview, const char *message, float fontsize, const float *forecolor, const float *backcolor)
1019 NSColor *textColor, *boxColor;
1020 label = (Label *)malloc(sizeof(Label));
1023 memset(label, 0, sizeof(Label));
1024 // MainViewCallback_lockFocus(mview);
1025 if (forecolor != NULL)
1026 textColor = [NSColor colorWithDeviceRed: forecolor[0] green: forecolor[1] blue: forecolor[2] alpha: forecolor[3]];
1028 textColor = [NSColor whiteColor];
1029 if (backcolor != NULL)
1030 boxColor = [NSColor colorWithDeviceRed: backcolor[0] green: backcolor[1] blue: backcolor[2] alpha: backcolor[3]];
1032 boxColor = [NSColor colorWithDeviceRed:1.0f green:1.0f blue:1.0f alpha:0.0f];
1033 attr = [NSDictionary dictionaryWithObjectsAndKeys: [NSFont userFontOfSize: fontsize], NSFontAttributeName, textColor, NSForegroundColorAttributeName, nil];
1034 label->tex = [[StringTexture alloc]
1035 initWithString: [NSString stringWithUTF8String: message]
1036 withAttributes: attr
1037 withTextColor: textColor
1038 withBoxColor: boxColor
1039 withBorderColor: [NSColor colorWithDeviceRed:1.0f green:1.0f blue:1.0f alpha:0.0f]];
1040 // MainViewCallback_unlockFocus(mview);
1046 MainViewCallback_releaseLabel(struct Label *label)
1048 /* if (label != NULL) {
1049 [label->tex release];
1056 MainViewCallback_drawLabelAtPoint(struct Label *label, const float *pos)
1059 if (label != NULL && pos != NULL) {
1060 // GLint matrixMode;
1061 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1062 // glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
1063 // glMatrixMode(GL_MODELVIEW);
1065 // glTranslatef(0.0f, 0.0f, pos[3]);
1066 [label->tex drawAtPoint: NSMakePoint(pos[0], pos[1]) withDepth: pos[2]];
1068 // glMatrixMode (matrixMode);
1074 MainViewCallback_labelSize(struct Label *label, float *outSize)
1076 /* if (label != NULL) {
1077 NSSize size = [label->tex frameSize];
1078 if (outSize != NULL) {
1079 outSize[0] = size.width;
1080 outSize[1] = size.height;
1086 #pragma mark ====== Plain C Interface (MyListCtrl) ======
1088 /* These interface functions are also used for accessing MyListCtrl of GlobalParameterFrame (when mview == NULL) */
1091 s_MyListCtrlFromMainView(MainView *mview)
1094 return wxGetApp().GetGlobalParameterListCtrl();
1095 if (mview != NULL && mview->ref != NULL)
1096 return ((MoleculeView *)(mview->ref))->GetListCtrl();
1101 MainViewCallback_selectTable(MainView *mview, int idx)
1103 if (mview != NULL && mview->ref != NULL)
1104 ((MoleculeView *)(mview->ref))->SelectTable(idx);
1108 MainViewCallback_numberOfTableColumns(MainView *mview)
1110 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1111 if (listctrl != NULL)
1112 return listctrl->GetColumnCount();
1117 MainViewCallback_addTableColumn(MainView *mview, const char *name, int width, int editable)
1120 wxString nstr(name, WX_DEFAULT_CONV);
1121 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1122 if (listctrl == NULL)
1124 idx = listctrl->GetColumnCount();
1125 listctrl->InsertColumn(idx, nstr, wxLIST_FORMAT_LEFT);
1126 listctrl->SetColumnWidth(idx, width * 10);
1131 MainViewCallback_removeTableColumnAtIndex(MainView *mview, int idx)
1134 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1135 if (listctrl == NULL)
1137 ncolumns = listctrl->GetColumnCount();
1138 if (idx >= 0 && idx < ncolumns) {
1139 listctrl->DeleteColumn(idx);
1146 MainViewCallback_reloadTableData(MainView *mview)
1148 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1149 if (listctrl != NULL)
1150 listctrl->RefreshTable();
1152 int nrows = MainView_numberOfRowsInTable(mview);
1153 listctrl->SetItemCount(nrows);
1155 listctrl->RefreshItems(0, nrows - 1);
1160 MainViewCallback_setTableSelection(MainView *mview, IntGroup *selection)
1163 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1164 if (listctrl == NULL)
1167 listctrl->EnableSelectionChangeNotification(false);
1168 if (selection != NULL) {
1169 for (i = 0; (n1 = IntGroupGetStartPoint(selection, i)) >= 0; i++) {
1170 n2 = IntGroupGetEndPoint(selection, i);
1172 listctrl->SetItemState(n, 0, wxLIST_STATE_SELECTED);
1176 listctrl->SetItemState(n, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
1181 listctrl->RefreshTable();
1182 n1 = MainView_numberOfRowsInTable(mview);
1184 listctrl->SetItemState(n, 0, wxLIST_STATE_SELECTED);
1187 // listctrl->RefreshItems(0, n1 - 1);
1189 // EVT_LIST_ITEM_SELECTED is sent by wxPostEvent rather than ProcessEvent,
1190 // so re-enable of table selection event should also be sent by wxPostEvent.
1191 // Otherwise, the enable flag is set to true _before_ EVT_LIST_ITEM_SELECTED is sent.
1192 wxCommandEvent myEvent(MyListCtrlEvent, MyListCtrlEvent_enableTableSelectionNotification);
1193 wxPostEvent(listctrl, myEvent);
1198 MainViewCallback_getTableSelection(MainView *mview)
1202 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1203 if (listctrl == NULL)
1206 n = MainView_numberOfRowsInTable(mview);
1207 for (i = 0; i < n; i++) {
1208 if (listctrl->GetItemState(i, wxLIST_STATE_SELECTED) != 0)
1209 IntGroupAdd(ig, i, 1);
1215 MainViewCallback_showTable(MainView *mview)
1217 // if (mview != NULL && mview->ref != NULL) {
1218 // MyDocument *doc = (MyDocument *)[(id)(mview->ref) document];
1219 // [doc showTable: doc];
1224 MainViewCallback_hideTable(MainView *mview)
1226 // if (mview != NULL && mview->ref != NULL) {
1227 // MyDocument *doc = (MyDocument *)[(id)(mview->ref) document];
1228 // [doc hideTable: doc];
1233 MainViewCallback_ensureVisible(MainView *mview, int row)
1235 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1236 if (listctrl != NULL)
1237 listctrl->EnsureVisible(row);
1241 MainViewCallback_startEditText(MainView *mview, int row, int column)
1243 MyListCtrl *listctrl = s_MyListCtrlFromMainView(mview);
1244 if (listctrl != NULL)
1245 listctrl->StartEditText(row, column);