Molecular Modeling Software
リビジョン | d7ea430d29abcde0734224c6c097bfb96e0d7ca0 (tree) |
---|---|
日時 | 2022-09-19 00:27:07 |
作者 | Toshi Nagata <alchemist.2005@nift...> |
コミッター | Toshi Nagata |
Handling and scroll and activation is improved
@@ -23,6 +23,7 @@ | ||
23 | 23 | #include "wx/glcanvas.h" |
24 | 24 | #include "wx/menu.h" |
25 | 25 | #include "wx/sizer.h" |
26 | +#include "wx/toplevel.h" | |
26 | 27 | |
27 | 28 | #if wxCHECK_VERSION(3,1,0) |
28 | 29 | #define FromFrameDIP(frame, x) frame->FromDIP(x) |
@@ -219,6 +220,14 @@ MyListCtrl::OnPaint(wxPaintEvent &event) | ||
219 | 220 | RefreshTable(false); |
220 | 221 | |
221 | 222 | wxColour colour; |
223 | + bool isActive; | |
224 | + // Get the nearest TopLevelWindow and see if it is active or not | |
225 | + wxWindow *win = this; | |
226 | + while (win != NULL && !win->IsKindOf(wxCLASSINFO(wxTopLevelWindow))) | |
227 | + win = win->GetParent(); | |
228 | + if (win != NULL && ((wxTopLevelWindow *)win)->IsActive()) | |
229 | + isActive = true; | |
230 | + else isActive = false; | |
222 | 231 | wxPaintDC dc(scroll); |
223 | 232 | scroll->DoPrepareDC(dc); |
224 | 233 | int ox, oy; |
@@ -276,17 +285,24 @@ MyListCtrl::OnPaint(wxPaintEvent &event) | ||
276 | 285 | bg[2] = 1.0; |
277 | 286 | } |
278 | 287 | } else { |
288 | + float bgbase[3] = { 0, 0, 1 }; | |
289 | + if (!isActive) { | |
290 | + bgbase[0] = 0.6; | |
291 | + bgbase[1] = 0.6; | |
292 | + bgbase[2] = 0.7; | |
293 | + } | |
279 | 294 | if (n & 2) { |
280 | - bg[0] = bg[0] * 0.5; | |
281 | - bg[1] = bg[1] * 0.5; | |
282 | - bg[2] = bg[2] * 0.5 + 0.5; | |
295 | + bg[0] = (bg[0] + bgbase[0]) * 0.5; | |
296 | + bg[1] = (bg[1] + bgbase[1]) * 0.5; | |
297 | + bg[2] = (bg[2] + bgbase[2]) * 0.5; | |
283 | 298 | } else if (n0 & 2) { |
284 | - bg[0] = bg0[0] * 0.5; | |
285 | - bg[1] = bg0[1] * 0.5; | |
286 | - bg[2] = bg0[2] * 0.5 + 0.5; | |
299 | + bg[0] = (bg0[0] + bgbase[0]) * 0.5; | |
300 | + bg[1] = (bg0[1] + bgbase[1]) * 0.5; | |
301 | + bg[2] = (bg0[2] + bgbase[2]) * 0.5; | |
287 | 302 | } else { |
288 | - bg[0] = bg[1] = 0; | |
289 | - bg[2] = 1.0; | |
303 | + bg[0] = bgbase[0]; | |
304 | + bg[1] = bgbase[1]; | |
305 | + bg[2] = bgbase[2]; | |
290 | 306 | } |
291 | 307 | } |
292 | 308 | if (n & 1) { |
@@ -479,13 +495,51 @@ MyListCtrl::UnselectAllRows() | ||
479 | 495 | void |
480 | 496 | MyListCtrl::OnLeftDown(wxMouseEvent &event) |
481 | 497 | { |
482 | - int x, y, ux, uy, row, modifiers, i; | |
498 | + int ux, uy, row, col, modifiers, i, n; | |
499 | + wxPoint pos; | |
500 | + char **items; | |
483 | 501 | bool isRowSelected, selectionChanged = false; |
484 | 502 | if (editText) |
485 | 503 | EndEditText(); |
486 | - x = event.GetX(); | |
487 | - y = event.GetY(); | |
488 | - scroll->CalcUnscrolledPosition(x, y, &ux, &uy); | |
504 | + pos = event.GetPosition(); | |
505 | + if (FindItemAtPosition(pos, &row, &col) && dataSource != NULL && (n = dataSource->HasPopUpMenu(this, row, col, &items)) > 0) { | |
506 | + wxMenu mnu; | |
507 | + for (i = 0; i < n; i++) { | |
508 | + char *p = items[i]; | |
509 | + bool enabled = true; | |
510 | + if (*p == '-') { | |
511 | + if (p[1] == 0) { | |
512 | + // Separator | |
513 | + mnu.AppendSeparator(); | |
514 | + p = NULL; | |
515 | + } else { | |
516 | + // Disabled item | |
517 | + p++; | |
518 | + enabled = false; | |
519 | + } | |
520 | + } | |
521 | + if (p != NULL) { | |
522 | + wxString itemStr(p, WX_DEFAULT_CONV); | |
523 | + mnu.Append(i + 1, itemStr); | |
524 | + if (!enabled) | |
525 | + mnu.Enable(i + 1, false); | |
526 | + } | |
527 | + free(items[i]); | |
528 | + items[i] = NULL; | |
529 | + } | |
530 | + free(items); | |
531 | + lastPopUpColumn = col; | |
532 | + lastPopUpRow = row; | |
533 | + mnu.Bind(wxEVT_COMMAND_MENU_SELECTED, &MyListCtrl::OnPopUpMenuSelected, this); | |
534 | + PopupMenu(&mnu); | |
535 | + n = dataSource->GetItemCount(this); | |
536 | + for (i = 0; i < n; i++) | |
537 | + SetItemState(i, (i == row ? wxLIST_STATE_SELECTED : 0), wxLIST_STATE_SELECTED); | |
538 | + PostSelectionChangeNotification(); | |
539 | + return; | |
540 | + } | |
541 | + | |
542 | + scroll->CalcUnscrolledPosition(pos.x, pos.y, &ux, &uy); | |
489 | 543 | row = floor(uy / rowHeight); |
490 | 544 | isRowSelected = IsRowSelected(row); |
491 | 545 | modifiers = event.GetModifiers(); |
@@ -534,6 +588,7 @@ MyListCtrl::OnLeftDown(wxMouseEvent &event) | ||
534 | 588 | // Actually no change occurred |
535 | 589 | selectionChangeNotificationRequired = false; |
536 | 590 | } |
591 | + SetFocus(); // Set focus to MyListCtrl, not wxScrolledWindow | |
537 | 592 | Refresh(); |
538 | 593 | } |
539 | 594 |
@@ -704,32 +759,35 @@ MyListCtrl::PostSelectionChangeNotification() | ||
704 | 759 | } |
705 | 760 | |
706 | 761 | // Find item on list control |
707 | -// Pos is the client coordinate in MyListCtrl (not scroll) | |
762 | +// Pos is the *client* coordinate in scroll (i.e. scrolled position) | |
708 | 763 | bool |
709 | 764 | MyListCtrl::FindItemAtPosition(const wxPoint &pos, int *row, int *col) |
710 | 765 | { |
711 | 766 | int r, cx, i; |
712 | - wxPoint p = this->ClientToScreen(pos); | |
713 | - p = scroll->ScreenToClient(p); | |
714 | - p = scroll->CalcUnscrolledPosition(p); | |
767 | + wxPoint p = scroll->CalcUnscrolledPosition(pos); | |
715 | 768 | r = floor(p.y / rowHeight); |
716 | - if (r < 0 || r >= nrows) | |
769 | + if (r < 0) | |
717 | 770 | r = -1; |
771 | + else if (r >= nrows) | |
772 | + r = nrows; | |
718 | 773 | cx = 0; |
719 | - for (i = 0; i < ncols; i++) { | |
720 | - if (p.x >= cx && p.x < cx + colWidths[i]) | |
721 | - break; | |
722 | - } | |
723 | - if (i >= ncols) | |
774 | + if (p.x < 0) | |
724 | 775 | i = -1; |
776 | + else { | |
777 | + for (i = 0; i < ncols; i++) { | |
778 | + if (p.x >= cx && p.x < cx + colWidths[i]) | |
779 | + break; | |
780 | + cx += colWidths[i]; | |
781 | + } | |
782 | + } | |
725 | 783 | if (row != NULL) |
726 | 784 | *row = r; |
727 | 785 | if (col != NULL) |
728 | 786 | *col = i; |
729 | - return (r >= 0 && i >= 0); | |
787 | + return (r >= 0 && r < nrows && i >= 0 && i < ncols); | |
730 | 788 | } |
731 | 789 | |
732 | -// The return rect is the client coordinate in MyListCtrl (not scroll) | |
790 | +// The return rect is the *client* coordinate in scroll (i.e. scrolled position) | |
733 | 791 | bool |
734 | 792 | MyListCtrl::GetItemRectForRowAndColumn(wxRect &rect, int row, int col) |
735 | 793 | { |
@@ -743,12 +801,51 @@ MyListCtrl::GetItemRectForRowAndColumn(wxRect &rect, int row, int col) | ||
743 | 801 | } |
744 | 802 | scroll->CalcScrolledPosition(cx, cy, &tx, &ty); |
745 | 803 | rect.x = tx; |
746 | - rect.y = ty + headerHeight; | |
804 | + rect.y = ty; | |
747 | 805 | rect.width = colWidths[col]; |
748 | 806 | rect.height = rowHeight; |
749 | 807 | return true; |
750 | 808 | } |
751 | 809 | |
810 | +// Get the left-top position in scroll unit (= rowHeight) | |
811 | +void | |
812 | +MyListCtrl::GetScrollPosition(int *xpos, int *ypos) | |
813 | +{ | |
814 | + *xpos = scroll->GetScrollPos(wxHORIZONTAL); | |
815 | + *ypos = scroll->GetScrollPos(wxVERTICAL); | |
816 | +} | |
817 | + | |
818 | +// Scroll so that (xpos, ypos) position is left-top | |
819 | +// Return false if the position is outside the scrolling limit | |
820 | +bool | |
821 | +MyListCtrl::SetScrollPosition(int xpos, int ypos) | |
822 | +{ | |
823 | + wxSize vsz = scroll->GetVirtualSize(); | |
824 | + wxSize sz = scroll->GetSize(); | |
825 | + bool retval = true; | |
826 | + int xlim = scroll->GetScrollLines(wxHORIZONTAL) - scroll->GetScrollPageSize(wxHORIZONTAL); | |
827 | + int ylim = scroll->GetScrollLines(wxVERTICAL) - scroll->GetScrollPageSize(wxVERTICAL); | |
828 | +// int xlim = (vsz.x - sz.x) / rowHeight; | |
829 | +// int ylim = (vsz.y - sz.y) / rowHeight; | |
830 | + if (xpos > xlim) { | |
831 | + retval = false; | |
832 | + xpos = xlim; | |
833 | + } | |
834 | + if (xpos < 0) { | |
835 | + retval = false; | |
836 | + xpos = 0; | |
837 | + } | |
838 | + if (ypos > ylim) { | |
839 | + retval = false; | |
840 | + ypos = ylim; | |
841 | + } | |
842 | + if (ypos < 0) { | |
843 | + retval = false; | |
844 | + ypos = 0; | |
845 | + } | |
846 | + scroll->Scroll(xpos, ypos); | |
847 | + return retval; | |
848 | +} | |
752 | 849 | |
753 | 850 | bool |
754 | 851 | MyListCtrl::EnsureVisible(int row, int col) |
@@ -756,7 +853,6 @@ MyListCtrl::EnsureVisible(int row, int col) | ||
756 | 853 | wxRect r; |
757 | 854 | if (!GetItemRectForRowAndColumn(r, row, (col == -1 ? 0 : col))) |
758 | 855 | return false; |
759 | - r.y -= headerHeight; // Convert to client coord in scroll | |
760 | 856 | wxSize sz = scroll->GetClientSize(); |
761 | 857 | int scx = -1, scy = -1; |
762 | 858 | int ux, uy; |
@@ -789,7 +885,6 @@ MyListCtrl::StartEditText(int row, int col) | ||
789 | 885 | wxRect r; |
790 | 886 | if (!GetItemRectForRowAndColumn(r, row, col)) |
791 | 887 | return; |
792 | - r.y -= headerHeight; // Convert to client coord in scroll | |
793 | 888 | int i, tx, ty; |
794 | 889 | int cy = rowHeight * row; |
795 | 890 | int cx = 0; |
@@ -95,6 +95,9 @@ public: | ||
95 | 95 | bool Create(wxWindow* parent, wxWindowID wid, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); |
96 | 96 | |
97 | 97 | void SetDataSource(MyListCtrlDataSource *source); |
98 | + MyListCtrlDataSource *GetDataSource() { return dataSource; } | |
99 | + wxWindow *GetHeaderWindow() { return header; } | |
100 | + wxScrolledWindow *GetScrolledWindow() { return scroll; } | |
98 | 101 | |
99 | 102 | void SetNeedsReload(bool flag = true); |
100 | 103 | void RefreshTable(bool refreshWindow = true); |
@@ -115,6 +118,9 @@ public: | ||
115 | 118 | |
116 | 119 | bool FindItemAtPosition(const wxPoint &pos, int *col, int *row); |
117 | 120 | |
121 | + void GetScrollPosition(int *xpos, int *ypos); | |
122 | + bool SetScrollPosition(int xpos, int ypos); | |
123 | + | |
118 | 124 | bool GetItemRectForRowAndColumn(wxRect &rect, int row, int column); |
119 | 125 | bool EnsureVisible(int row, int col = -1); |
120 | 126 |