• R/O
  • HTTP
  • SSH
  • HTTPS

Molby: コミット

Molecular Modeling Software


コミットメタ情報

リビジョン822395e078b3385b7f0fe070d54260d41723631e (tree)
日時2022-09-19 12:50:11
作者Toshi Nagata <alchemist.2005@nift...>
コミッターToshi Nagata

ログメッセージ

Handling key and mouse events in listctrl is improved

変更サマリ

差分

--- a/wxSources/MyListCtrl.cpp
+++ b/wxSources/MyListCtrl.cpp
@@ -80,7 +80,7 @@ MyListCtrl::Create(wxWindow* parent, wxWindowID wid, const wxPoint& pos, const w
8080 {
8181 this->wxWindow::Create(parent, wid, pos, size);
8282
83- header = new wxWindow(this, 1001, wxPoint(0, 0), wxSize(size.x, 16));
83+ header = new wxWindow(this, 1001, wxPoint(0, 0), wxSize(size.x, 16), wxWANTS_CHARS);
8484 scroll = new wxScrolledWindow(this, 1002, wxPoint(0, 16), wxSize(size.x, (size.y <= 16 ? -1 : size.y - 16)));
8585
8686 // Connect events
@@ -98,6 +98,9 @@ MyListCtrl::Create(wxWindow* parent, wxWindowID wid, const wxPoint& pos, const w
9898 scroll->Bind(wxEVT_SCROLLWIN_PAGEUP, &MyListCtrl::OnScrollWin, this);
9999 scroll->Bind(wxEVT_SCROLLWIN_THUMBRELEASE, &MyListCtrl::OnScrollWin, this);
100100 scroll->Bind(wxEVT_SCROLLWIN_THUMBTRACK, &MyListCtrl::OnScrollWin, this);
101+ scroll->Bind(wxEVT_CHAR, &MyListCtrl::OnCharInScroll, this);
102+ scroll->Bind(wxEVT_SET_FOCUS, &MyListCtrl::OnSetFocusInScroll, this);
103+ scroll->Bind(wxEVT_KILL_FOCUS, &MyListCtrl::OnKillFocusInScroll, this);
101104
102105 // Set Fonts
103106 cellFont = GetFont();
@@ -108,10 +111,13 @@ MyListCtrl::Create(wxWindow* parent, wxWindowID wid, const wxPoint& pos, const w
108111 wxClientDC dc(this);
109112 int w, h, descent, leading;
110113 dc.GetTextExtent(_T("M"), &w, &h, &descent, &leading, &cellFont);
111- rowHeight = h + 2;
114+ rowHeight = h + FromFrameDIP(scroll, 2);
112115 dc.GetTextExtent(_T("M"), &w, &h, &descent, &leading, &headerFont);
113- headerHeight = h + 2;
116+ headerHeight = h + FromFrameDIP(scroll, 2);
114117 header->SetSize(wxSize(size.x, headerHeight));
118+ pageHeight = rowHeight;
119+ pageWidth = rowHeight;
120+ scroll->SetScrollbars(rowHeight, rowHeight, 1, 1, true);
115121 }
116122
117123 // Set sizer
@@ -191,8 +197,12 @@ MyListCtrl::RefreshTable(bool refreshWindow)
191197 // Set the subwindow infos
192198 sz.y = headerHeight;
193199 header->SetMinSize(sz);
194- scroll->SetScrollbars(rowHeight, rowHeight, floor((pageWidth + rowHeight - 1) / rowHeight), nrows);
195200 scroll->SetVirtualSize(pageWidth, pageHeight);
201+ int pageSize = floor((pageWidth + rowHeight - 1) / rowHeight);
202+ if (scroll->GetScrollPageSize(wxHORIZONTAL) != pageSize)
203+ scroll->SetScrollPageSize(wxHORIZONTAL, pageSize);
204+ if (scroll->GetScrollPageSize(wxVERTICAL) != pageSize)
205+ scroll->SetScrollPageSize(wxVERTICAL, nrows);
196206 Layout();
197207 }
198208 needsReload = false;
@@ -221,13 +231,8 @@ MyListCtrl::OnPaint(wxPaintEvent &event)
221231
222232 wxColour colour;
223233 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;
234+ isActive = scroll->HasFocus();
235+ isPaintActive = isActive;
231236 wxPaintDC dc(scroll);
232237 scroll->DoPrepareDC(dc);
233238 int ox, oy;
@@ -236,9 +241,9 @@ MyListCtrl::OnPaint(wxPaintEvent &event)
236241 wxSize sz = scroll->GetClientSize();
237242 bool showDragTarget = (draggingRows && (dragTargetRow != mouseRow && dragTargetRow != mouseRow + 1));
238243 // Draw background
239- dc.SetPen(wxNullPen);
244+ dc.SetPen(*wxTRANSPARENT_PEN);
240245 dc.SetBrush(*wxWHITE_BRUSH);
241- dc.DrawRectangle(0, 0, sz.x, sz.y);
246+ dc.DrawRectangle(ox, oy, sz.x, sz.y);
242247 int i, j;
243248 basex = 0;
244249 for (i = 0; i < ncols; i++) {
@@ -501,6 +506,16 @@ MyListCtrl::OnLeftDown(wxMouseEvent &event)
501506 bool isRowSelected, selectionChanged = false;
502507 if (editText)
503508 EndEditText();
509+ if (!isPaintActive) {
510+ // The scroll is still displayed in inactive state;
511+ // Set focus to scroll, and do nothing else.
512+ // This flag is used because we actually want to intercept the mouseDown
513+ // for 'just activate the listview', but wxWidgets may not allow processing
514+ // mouseDown event _before_ the scroll view gets focus.
515+ scroll->SetFocus();
516+ Refresh();
517+ return;
518+ }
504519 pos = event.GetPosition();
505520 if (FindItemAtPosition(pos, &row, &col) && dataSource != NULL && (n = dataSource->HasPopUpMenu(this, row, col, &items)) > 0) {
506521 wxMenu mnu;
@@ -588,7 +603,6 @@ MyListCtrl::OnLeftDown(wxMouseEvent &event)
588603 // Actually no change occurred
589604 selectionChangeNotificationRequired = false;
590605 }
591- SetFocus(); // Set focus to MyListCtrl, not wxScrolledWindow
592606 Refresh();
593607 }
594608
@@ -667,11 +681,11 @@ MyListCtrl::OnLeftUp(wxMouseEvent &event)
667681 dragged = true;
668682 if (row != mouseRow) {
669683 if (draggingRows) {
670- // TODO: change selection; it should be implemented in dataSource
671684 dataSource->DragSelectionToRow(this, dragTargetRow);
672685 selectionChanged = true;
673686 }
674687 }
688+ lastMouseRow = dragTargetRow;
675689 }
676690 if (!dragged) {
677691 if (mouseMode == 1 || mouseMode == 4) {
@@ -820,8 +834,6 @@ MyListCtrl::GetScrollPosition(int *xpos, int *ypos)
820834 bool
821835 MyListCtrl::SetScrollPosition(int xpos, int ypos)
822836 {
823- wxSize vsz = scroll->GetVirtualSize();
824- wxSize sz = scroll->GetSize();
825837 bool retval = true;
826838 int xlim = scroll->GetScrollLines(wxHORIZONTAL) - scroll->GetScrollPageSize(wxHORIZONTAL);
827839 int ylim = scroll->GetScrollLines(wxVERTICAL) - scroll->GetScrollPageSize(wxVERTICAL);
@@ -843,7 +855,16 @@ MyListCtrl::SetScrollPosition(int xpos, int ypos)
843855 retval = false;
844856 ypos = 0;
845857 }
858+ // TextCtrl may be moved during the scroll, so amend the position
846859 scroll->Scroll(xpos, ypos);
860+ if (editText) {
861+ wxRect r;
862+ int delta = FromFrameDIP(scroll, 2);
863+ if (GetItemRectForRowAndColumn(r, editRow, editColumn)) {
864+ editText->SetPosition(wxPoint(r.x - delta, r.y - delta));
865+ }
866+ }
867+ header->Refresh();
847868 return retval;
848869 }
849870
@@ -875,6 +896,7 @@ MyListCtrl::EnsureVisible(int row, int col)
875896 }
876897 if (scx >= 0 || scy >= 0) {
877898 scroll->Scroll(scx, scy);
899+ header->Refresh();
878900 return true;
879901 } else return false;
880902 }
@@ -883,24 +905,24 @@ void
883905 MyListCtrl::StartEditText(int row, int col)
884906 {
885907 wxRect r;
908+ int delta = FromFrameDIP(scroll, 2);
909+ EnsureVisible(row, col);
886910 if (!GetItemRectForRowAndColumn(r, row, col))
887911 return;
888- int i, tx, ty;
889- int cy = rowHeight * row;
890- int cx = 0;
891- for (i = 0; i < col; i++) {
892- cx += colWidths[i];
893- }
894- scroll->CalcScrolledPosition(cx, cy, &tx, &ty);
895912 if (editText == NULL) {
896- editText = new wxTextCtrl(scroll, -1, "", wxPoint(r.x - 2, r.y - 2), wxSize(r.width + 4, r.height + 4), wxTE_PROCESS_ENTER);
913+ editText = new wxTextCtrl(scroll, -1, "", wxPoint(r.x - delta, r.y - delta), wxSize(r.width + delta * 2, r.height + delta * 2), wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxWANTS_CHARS);
897914 editText->Bind(wxEVT_CHAR, &MyListCtrl::OnCharInText, this);
915+ editText->Bind(wxEVT_CHAR_HOOK, &MyListCtrl::OnCharHookInText, this);
898916 } else {
899917 FinalizeEdit();
900- editText->SetPosition(wxPoint(r.x - 2, r.y - 2));
901- editText->SetSize(wxSize(r.width + 4, r.height + 4));
918+ editText->SetPosition(wxPoint(r.x - delta, r.y - delta));
919+ editText->SetSize(wxSize(r.width + delta * 2, r.height + delta * 2));
920+ }
921+ if (selection.size() != 1 || !IsRowSelected(row)) {
922+ UnselectAllRows();
923+ SelectRow(row);
924+ PostSelectionChangeNotification();
902925 }
903- EnsureVisible(row, col);
904926 wxString str = dataSource->GetItemText(this, row, col);
905927 editText->SetValue(str);
906928 editText->Show();
@@ -908,11 +930,6 @@ MyListCtrl::StartEditText(int row, int col)
908930 editText->SelectAll();
909931 editRow = row;
910932 editColumn = col;
911- if (selection.size() != 1 || !IsRowSelected(row)) {
912- UnselectAllRows();
913- SelectRow(row);
914- PostSelectionChangeNotification();
915- }
916933 }
917934
918935 void
@@ -935,6 +952,7 @@ MyListCtrl::EndEditText(bool setValueFlag)
935952 editText->Hide();
936953 editText->Destroy();
937954 editText = NULL;
955+ scroll->SetFocus();
938956 }
939957
940958 void
@@ -1003,8 +1021,62 @@ MyListCtrl::OnCharInText(wxKeyEvent &event)
10031021 EndEditText();
10041022 } else
10051023 event.Skip();
1006- // TODO: arrow up/down key should change selected row (if multiple rows are selected, then
1007- // start from the last clicked row)
1024+}
1025+
1026+void
1027+MyListCtrl::OnCharHookInText(wxKeyEvent &event)
1028+{
1029+#if defined(__WXMAC__) || defined(__WXOSX__)
1030+ // On macOS, shift-TAB is consumed by wxWidgets even when wxTE_PROCESS_TAB and wxWANTS_CHARS
1031+ // are specified (why?); so, we intercept the TAB and shift-TAB here
1032+ int kc = event.GetKeyCode();
1033+ if (kc == WXK_TAB || kc == WXK_NUMPAD_TAB) {
1034+ OnCharInText(event);
1035+ } else event.Skip();
1036+#else
1037+ event.Skip();
1038+#endif
1039+}
1040+
1041+void
1042+MyListCtrl::OnCharInScroll(wxKeyEvent &event)
1043+{
1044+ int kc = event.GetKeyCode();
1045+ if (kc == WXK_DOWN || kc == WXK_UP) {
1046+ int row;
1047+ if (selection.size() > 0) {
1048+ if (selection.size() > 1) {
1049+ if (lastMouseRow >= 0 && lastMouseRow < nrows)
1050+ row = lastMouseRow;
1051+ else if (kc == WXK_DOWN)
1052+ row = selection[selection.size() - 1];
1053+ else
1054+ row = selection[0];
1055+ } else row = selection[0];
1056+ if (kc == WXK_UP && row > 0)
1057+ row--;
1058+ else if (kc == WXK_DOWN && row < nrows - 1)
1059+ row++;
1060+ else return; // Ignore key
1061+ UnselectAllRows();
1062+ SelectRow(row);
1063+ PostSelectionChangeNotification();
1064+ Refresh();
1065+ lastMouseRow = row; // Fake as if this row was clicked
1066+ }
1067+ } else event.Skip();
1068+}
1069+
1070+void
1071+MyListCtrl::OnSetFocusInScroll(wxFocusEvent &event)
1072+{
1073+ Refresh();
1074+}
1075+
1076+void
1077+MyListCtrl::OnKillFocusInScroll(wxFocusEvent &event)
1078+{
1079+ Refresh();
10081080 }
10091081
10101082 void
--- a/wxSources/MyListCtrl.h
+++ b/wxSources/MyListCtrl.h
@@ -144,6 +144,10 @@ public:
144144 void OnMotion(wxMouseEvent &event);
145145 void OnScrollWin(wxScrollWinEvent &event);
146146 void OnCharInText(wxKeyEvent &event);
147+ void OnCharHookInText(wxKeyEvent &event);
148+ void OnCharInScroll(wxKeyEvent &event);
149+ void OnSetFocusInScroll(wxFocusEvent &event);
150+ void OnKillFocusInScroll(wxFocusEvent &event);
147151
148152 void EnableSelectionChangeNotification(bool flag) { selectionChangeNotificationEnabled = flag; }
149153
@@ -154,6 +158,7 @@ public:
154158 bool selectionChangeNotificationRequired;
155159 bool selectionChangeNotificationEnabled;
156160 bool needsReload;
161+ bool isPaintActive; // Flag to show whether the scroll had focus in the last OnPaint call
157162 int lastPopUpColumn, lastPopUpRow;
158163 wxFont cellFont;
159164 wxFont headerFont;
旧リポジトリブラウザで表示