@@ -156,7 +156,7 @@ int wxHeaderCtrl::GetColStart(unsigned int idx) const
156
156
if ( col.IsShown () )
157
157
pos += col.GetWidth ();
158
158
}
159
-
159
+
160
160
return pos;
161
161
}
162
162
@@ -167,7 +167,7 @@ int wxHeaderCtrl::GetColEnd(unsigned int idx) const
167
167
return x + GetColumn (idx).GetWidth ();
168
168
}
169
169
170
- unsigned int wxHeaderCtrl::FindColumnAtPoint (int xPhysical, bool *onSeparator ) const
170
+ unsigned int wxHeaderCtrl::FindColumnAtPoint (int xPhysical, Region& pos_region ) const
171
171
{
172
172
int pos = 0 ;
173
173
int xLogical = xPhysical - m_scrollOffset;
@@ -178,7 +178,8 @@ unsigned int wxHeaderCtrl::FindColumnAtPoint(int xPhysical, bool *onSeparator) c
178
178
const wxHeaderColumn& col = GetColumn (idx);
179
179
if ( col.IsHidden () )
180
180
continue ;
181
-
181
+
182
+ const auto last_col_end = pos;
182
183
pos += col.GetWidth ();
183
184
184
185
// TODO: don't hardcode sensitivity
@@ -188,33 +189,34 @@ unsigned int wxHeaderCtrl::FindColumnAtPoint(int xPhysical, bool *onSeparator) c
188
189
// line separating it from the next column
189
190
if ( col.IsResizeable () && abs (xLogical - pos) < separatorClickMargin )
190
191
{
191
- if ( onSeparator )
192
- *onSeparator = true ;
192
+ pos_region = Region::Separator;
193
193
return idx;
194
194
}
195
195
196
196
// inside this column?
197
- if ( xLogical < pos )
197
+ if ( xLogical < pos && xLogical >= last_col_end )
198
198
{
199
- if ( onSeparator )
200
- *onSeparator = false ;
199
+ if ( xLogical - last_col_end < pos - xLogical)
200
+ pos_region = Region::LeftHalf;
201
+ else
202
+ pos_region = Region::RightHalf;
201
203
return idx;
202
204
}
203
205
}
204
206
205
- if ( onSeparator )
206
- *onSeparator = false ;
207
+ pos_region = Region::NoWhere;
207
208
return COL_NONE;
208
209
}
209
210
210
- unsigned int wxHeaderCtrl::FindColumnClosestToPoint (int xPhysical) const
211
+ unsigned int wxHeaderCtrl::FindColumnClosestToPoint (int xPhysical, Region& pos_region ) const
211
212
{
212
- const unsigned int colIndexAtPoint = FindColumnAtPoint (xPhysical);
213
-
213
+ const unsigned int colIndexAtPoint = FindColumnAtPoint (xPhysical, pos_region );
214
+
214
215
// valid column found?
215
216
if ( colIndexAtPoint != COL_NONE )
216
217
return colIndexAtPoint;
217
-
218
+
219
+ pos_region = Region::NoWhere;
218
220
// if not, xPhysical must be beyond the rightmost column, so return its
219
221
// index instead -- if we have it
220
222
const unsigned int count = GetColumnCount ();
@@ -224,6 +226,37 @@ unsigned int wxHeaderCtrl::FindColumnClosestToPoint(int xPhysical) const
224
226
return m_colIndices[count - 1 ];
225
227
}
226
228
229
+ unsigned int wxHeaderCtrl::FindColumnAfter (const unsigned int column_idx) const {
230
+ const unsigned count = GetColumnCount ();
231
+ auto after_idx = COL_NONE;
232
+ // auto target_column_found = false;
233
+ for ( unsigned n = 0 ; n < count; n++ )
234
+ {
235
+ if (m_colIndices[n] == column_idx && n + 1 < count ){
236
+ after_idx = m_colIndices[n + 1 ];
237
+ break ;
238
+ }
239
+ }
240
+ return after_idx;
241
+ }
242
+
243
+ unsigned int wxHeaderCtrl::FindColumnBefore (const unsigned int column_idx) const {
244
+ const unsigned count = GetColumnCount ();
245
+ auto before_idx = COL_NONE;
246
+ auto target_column_found = false ;
247
+ for ( unsigned n = 0 ; n < count; n++ )
248
+ {
249
+ if (m_colIndices[n] == column_idx){
250
+ target_column_found = true ;
251
+ break ;
252
+ }
253
+ before_idx = m_colIndices[n];
254
+ }
255
+ if (not target_column_found)
256
+ before_idx = COL_NONE;
257
+ return before_idx;
258
+ }
259
+
227
260
// ----------------------------------------------------------------------------
228
261
// wxHeaderCtrl repainting
229
262
// ----------------------------------------------------------------------------
@@ -389,14 +422,21 @@ void wxHeaderCtrl::UpdateReorderingMarker(int xPhysical)
389
422
390
423
// and also a hint indicating where it is going to be inserted if it's
391
424
// dropped now
392
- unsigned int col = FindColumnClosestToPoint (xPhysical);
425
+ auto hover_region = Region::NoWhere;
426
+ unsigned int col = FindColumnClosestToPoint (xPhysical, hover_region);
393
427
if ( col != COL_NONE )
394
428
{
395
429
static const int DROP_MARKER_WIDTH = 4 ;
396
430
397
431
dc.SetBrush (*wxBLUE);
398
- dc.DrawRectangle (GetColEnd (col) - DROP_MARKER_WIDTH/2 , 0 ,
399
- DROP_MARKER_WIDTH, y);
432
+ if (hover_region == Region::LeftHalf){
433
+ dc.DrawRectangle (GetColStart (col) - DROP_MARKER_WIDTH/2 , 0 ,
434
+ DROP_MARKER_WIDTH, y);
435
+ }
436
+ else if (hover_region != Region::NoWhere){
437
+ dc.DrawRectangle (GetColEnd (col) - DROP_MARKER_WIDTH/2 , 0 ,
438
+ DROP_MARKER_WIDTH, y);
439
+ }
400
440
}
401
441
}
402
442
@@ -432,10 +472,39 @@ bool wxHeaderCtrl::EndReordering(int xPhysical)
432
472
ReleaseMouse ();
433
473
434
474
const int colOld = m_colBeingReordered;
435
- const unsigned colNew = FindColumnClosestToPoint (xPhysical);
475
+ auto dropped_region = Region::NoWhere;
476
+ unsigned colNew = FindColumnClosestToPoint (xPhysical, dropped_region);
436
477
437
478
m_colBeingReordered = COL_NONE;
438
-
479
+ auto reg_str = std::string{};
480
+ switch (dropped_region){
481
+ case Region::NoWhere:
482
+ reg_str = " NoWhere" ;
483
+ break ;
484
+ case Region::LeftHalf:
485
+ reg_str = " LeftHalf" ;
486
+ break ;
487
+ case Region::RightHalf:
488
+ reg_str = " RightHalf" ;
489
+ break ;
490
+ case Region::Separator:
491
+ reg_str = " Separator" ;
492
+ break ;
493
+ }
494
+ // printf("Dropped to col %d, region : %s\n", colNew, reg_str.c_str());
495
+ // The actual dropped pos should not simply be colNew, it should also depends on
496
+ // which region the user dropped in.
497
+ // if the user dropped the col on the RightHalf, the colNew should the one next to it on the right.
498
+ auto located_by_previous_col = false ;
499
+ if ((dropped_region == Region::RightHalf || dropped_region == Region::Separator) && colNew != COL_NONE){
500
+ // printf("Looking for the next column pos to inserted for col %d\n", colNew);
501
+ auto nextColumn = FindColumnAfter (colNew);
502
+ if (nextColumn != COL_NONE){
503
+ // printf("Next col for col %d is %d\n", colNew, nextColumn);
504
+ colNew = nextColumn;
505
+ located_by_previous_col = true ;
506
+ }
507
+ }
439
508
// mouse drag must be longer than min distance m_dragOffset
440
509
if ( xPhysical - GetColStart (colOld) == m_dragOffset )
441
510
{
@@ -447,22 +516,45 @@ bool wxHeaderCtrl::EndReordering(int xPhysical)
447
516
{
448
517
return false ;
449
518
}
450
-
451
519
if ( static_cast <int >(colNew) != colOld )
452
520
{
453
521
wxHeaderCtrlEvent event (wxEVT_HEADER_END_REORDER, GetId ());
454
522
event.SetEventObject (this );
455
523
event.SetColumn (colOld);
456
-
457
- const unsigned pos = GetColumnPos (colNew);
458
- event.SetNewOrder (pos);
459
-
460
- if ( !GetEventHandler ()->ProcessEvent (event) || event.IsAllowed () )
461
- {
462
- // do reorder the columns
463
- DoMoveCol (colOld, pos);
524
+ auto new_pos = GetColumnPos (colNew);
525
+ auto old_pos = GetColumnPos (colOld);
526
+ // when the user drag one col from left-to-right(i.e. from low pos to higher one),
527
+ // the actual pos to dropped should be the one just before colNew, i.e. the one on the left hand side of colNew.
528
+ auto move_left = false ;
529
+ if (old_pos < new_pos) {
530
+ // the last column is a bit special, we should consider it differently.
531
+ if (new_pos != GetColumnCount () - 1 || located_by_previous_col || dropped_region == Region::LeftHalf){
532
+ colNew = FindColumnBefore (colNew);
533
+ assert (colNew != COL_NONE);
534
+ new_pos = GetColumnPos (colNew);
535
+ }
536
+ move_left = true ;
537
+ }
538
+ // Simulate the reorder before we actually accept it.
539
+ // Why???
540
+ // ToDo: better code comments to explain the logic, a diagram should be better
541
+ auto new_colIndices = m_colIndices;
542
+ MoveColumnInOrderArray (new_colIndices, colOld, new_pos);
543
+ auto old_after_pos = new_colIndices.Index (colNew);
544
+ auto new_after_pos = new_colIndices.Index (colOld);
545
+ if (old_after_pos != old_pos || new_after_pos != new_pos || move_left || old_pos > new_pos){
546
+ event.SetNewOrder (new_pos);
547
+
548
+ // printf("Move col %d to %d, pos to %d\n", colOld, colNew, new_pos);
549
+ if ( GetEventHandler ()->ProcessEvent (event) || event.IsAllowed () )
550
+ {
551
+ // do reorder the columns
552
+ DoMoveCol (colOld, new_pos);
553
+ }
464
554
}
465
555
}
556
+ // else
557
+ // printf("ColNew and ColOld the same, do not reordering.\n");
466
558
467
559
// whether we moved the column or not, the user did move the mouse and so
468
560
// did try to do it so return true
@@ -651,10 +743,10 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
651
743
652
744
653
745
// find if the event is over a column at all
654
- bool onSeparator ;
746
+ Region mouse_region = Region::NoWhere ;
655
747
const unsigned col = mevent.Leaving ()
656
- ? (onSeparator = false , COL_NONE)
657
- : FindColumnAtPoint (xPhysical, &onSeparator );
748
+ ? COL_NONE
749
+ : FindColumnAtPoint (xPhysical, mouse_region );
658
750
659
751
660
752
// update the highlighted column if it changed
@@ -670,7 +762,7 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
670
762
// update mouse cursor as it moves around
671
763
if ( mevent.Moving () )
672
764
{
673
- SetCursor (onSeparator ? wxCursor (wxCURSOR_SIZEWE) : wxNullCursor);
765
+ SetCursor (mouse_region == Region::Separator ? wxCursor (wxCURSOR_SIZEWE) : wxNullCursor);
674
766
return ;
675
767
}
676
768
@@ -682,7 +774,7 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
682
774
// enter various dragging modes on left mouse press
683
775
if ( mevent.LeftDown () )
684
776
{
685
- if ( onSeparator )
777
+ if ( mouse_region == Region::Separator )
686
778
{
687
779
// start resizing the column
688
780
wxASSERT_MSG ( !IsResizing (), " reentering column resize mode?" );
@@ -712,7 +804,7 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
712
804
{
713
805
case wxMOUSE_BTN_LEFT:
714
806
// treat left double clicks on separator specially
715
- if ( onSeparator && dblclk )
807
+ if ( mouse_region == Region::Separator && dblclk )
716
808
{
717
809
evtType = wxEVT_HEADER_SEPARATOR_DCLICK;
718
810
m_wasSeparatorDClick = true ;
0 commit comments