~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/generic/headerctrlg.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/generic/headerctrlg.cpp
 
3
// Purpose:     generic wxHeaderCtrl implementation
 
4
// Author:      Vadim Zeitlin
 
5
// Created:     2008-12-03
 
6
// RCS-ID:      $Id: headerctrlg.cpp 67384 2011-04-03 20:31:32Z DS $
 
7
// Copyright:   (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
 
8
// Licence:     wxWindows licence
 
9
///////////////////////////////////////////////////////////////////////////////
 
10
 
 
11
// ============================================================================
 
12
// declarations
 
13
// ============================================================================
 
14
 
 
15
// ----------------------------------------------------------------------------
 
16
// headers
 
17
// ----------------------------------------------------------------------------
 
18
 
 
19
// for compilers that support precompilation, includes "wx.h".
 
20
#include "wx/wxprec.h"
 
21
 
 
22
#ifdef __BORLANDC__
 
23
    #pragma hdrstop
 
24
#endif
 
25
 
 
26
#if wxUSE_HEADERCTRL
 
27
 
 
28
#include "wx/headerctrl.h"
 
29
 
 
30
#ifdef wxHAS_GENERIC_HEADERCTRL
 
31
 
 
32
#include "wx/dcbuffer.h"
 
33
#include "wx/renderer.h"
 
34
 
 
35
// ----------------------------------------------------------------------------
 
36
// constants
 
37
// ----------------------------------------------------------------------------
 
38
 
 
39
namespace
 
40
{
 
41
 
 
42
const unsigned COL_NONE = (unsigned)-1;
 
43
 
 
44
} // anonymous namespace
 
45
 
 
46
// ============================================================================
 
47
// wxHeaderCtrl implementation
 
48
// ============================================================================
 
49
 
 
50
// ----------------------------------------------------------------------------
 
51
// wxHeaderCtrl creation
 
52
// ----------------------------------------------------------------------------
 
53
 
 
54
void wxHeaderCtrl::Init()
 
55
{
 
56
    m_numColumns = 0;
 
57
    m_hover =
 
58
    m_colBeingResized =
 
59
    m_colBeingReordered = COL_NONE;
 
60
    m_dragOffset = 0;
 
61
    m_scrollOffset = 0;
 
62
}
 
63
 
 
64
bool wxHeaderCtrl::Create(wxWindow *parent,
 
65
                          wxWindowID id,
 
66
                          const wxPoint& pos,
 
67
                          const wxSize& size,
 
68
                          long style,
 
69
                          const wxString& name)
 
70
{
 
71
    if ( !wxHeaderCtrlBase::Create(parent, id, pos, size,
 
72
                                   style, wxDefaultValidator, name) )
 
73
        return false;
 
74
 
 
75
    // tell the system to not paint the background at all to avoid flicker as
 
76
    // we paint the entire window area in our OnPaint()
 
77
    SetBackgroundStyle(wxBG_STYLE_CUSTOM);
 
78
 
 
79
    return true;
 
80
}
 
81
 
 
82
wxHeaderCtrl::~wxHeaderCtrl()
 
83
{
 
84
}
 
85
 
 
86
// ----------------------------------------------------------------------------
 
87
// wxHeaderCtrl columns manipulation
 
88
// ----------------------------------------------------------------------------
 
89
 
 
90
void wxHeaderCtrl::DoSetCount(unsigned int count)
 
91
{
 
92
    // update the column indices order array before changing m_numColumns
 
93
    DoResizeColumnIndices(m_colIndices, count);
 
94
 
 
95
    m_numColumns = count;
 
96
 
 
97
    InvalidateBestSize();
 
98
    Refresh();
 
99
}
 
100
 
 
101
unsigned int wxHeaderCtrl::DoGetCount() const
 
102
{
 
103
    return m_numColumns;
 
104
}
 
105
 
 
106
void wxHeaderCtrl::DoUpdate(unsigned int idx)
 
107
{
 
108
    InvalidateBestSize();
 
109
 
 
110
    // we need to refresh not only this column but also the ones after it in
 
111
    // case it was shown or hidden or its width changed -- it would be nice to
 
112
    // avoid doing this unnecessary by storing the old column width (TODO)
 
113
    RefreshColsAfter(idx);
 
114
}
 
115
 
 
116
// ----------------------------------------------------------------------------
 
117
// wxHeaderCtrl scrolling
 
118
// ----------------------------------------------------------------------------
 
119
 
 
120
void wxHeaderCtrl::DoScrollHorz(int dx)
 
121
{
 
122
    m_scrollOffset += dx;
 
123
 
 
124
    // don't call our own version which calls this function!
 
125
    wxControl::ScrollWindow(dx, 0);
 
126
}
 
127
 
 
128
// ----------------------------------------------------------------------------
 
129
// wxHeaderCtrl geometry
 
130
// ----------------------------------------------------------------------------
 
131
 
 
132
wxSize wxHeaderCtrl::DoGetBestSize() const
 
133
{
 
134
    wxWindow *win = GetParent();
 
135
    int height = wxRendererNative::Get().GetHeaderButtonHeight( win );
 
136
 
 
137
    // the vertical size is rather arbitrary but it looks better if we leave
 
138
    // some space around the text
 
139
    const wxSize size(IsEmpty() ? wxHeaderCtrlBase::DoGetBestSize().x
 
140
                                : GetColEnd(GetColumnCount() - 1),
 
141
                                height ); // (7*GetCharHeight())/4);
 
142
    CacheBestSize(size);
 
143
    return size;
 
144
}
 
145
 
 
146
int wxHeaderCtrl::GetColStart(unsigned int idx) const
 
147
{
 
148
    int pos = m_scrollOffset;
 
149
    for ( unsigned n = 0; ; n++ )
 
150
    {
 
151
        const unsigned i = m_colIndices[n];
 
152
        if ( i == idx )
 
153
            break;
 
154
 
 
155
        const wxHeaderColumn& col = GetColumn(i);
 
156
        if ( col.IsShown() )
 
157
            pos += col.GetWidth();
 
158
    }
 
159
 
 
160
    return pos;
 
161
}
 
162
 
 
163
int wxHeaderCtrl::GetColEnd(unsigned int idx) const
 
164
{
 
165
    int x = GetColStart(idx);
 
166
 
 
167
    return x + GetColumn(idx).GetWidth();
 
168
}
 
169
 
 
170
unsigned int wxHeaderCtrl::FindColumnAtPoint(int x, bool *onSeparator) const
 
171
{
 
172
    int pos = 0;
 
173
    const unsigned count = GetColumnCount();
 
174
    for ( unsigned n = 0; n < count; n++ )
 
175
    {
 
176
        const unsigned idx = m_colIndices[n];
 
177
        const wxHeaderColumn& col = GetColumn(idx);
 
178
        if ( col.IsHidden() )
 
179
            continue;
 
180
 
 
181
        pos += col.GetWidth();
 
182
 
 
183
        // if the column is resizable, check if we're approximatively over the
 
184
        // line separating it from the next column
 
185
        //
 
186
        // TODO: don't hardcode sensitivity
 
187
        if ( col.IsResizeable() && abs(x - pos) < 8 )
 
188
        {
 
189
            if ( onSeparator )
 
190
                *onSeparator = true;
 
191
            return idx;
 
192
        }
 
193
 
 
194
        // inside this column?
 
195
        if ( x < pos )
 
196
        {
 
197
            if ( onSeparator )
 
198
                *onSeparator = false;
 
199
            return idx;
 
200
        }
 
201
    }
 
202
 
 
203
    if ( onSeparator )
 
204
        *onSeparator = false;
 
205
    return COL_NONE;
 
206
}
 
207
 
 
208
// ----------------------------------------------------------------------------
 
209
// wxHeaderCtrl repainting
 
210
// ----------------------------------------------------------------------------
 
211
 
 
212
void wxHeaderCtrl::RefreshCol(unsigned int idx)
 
213
{
 
214
    wxRect rect = GetClientRect();
 
215
    rect.x += GetColStart(idx);
 
216
    rect.width = GetColumn(idx).GetWidth();
 
217
 
 
218
    RefreshRect(rect);
 
219
}
 
220
 
 
221
void wxHeaderCtrl::RefreshColIfNotNone(unsigned int idx)
 
222
{
 
223
    if ( idx != COL_NONE )
 
224
        RefreshCol(idx);
 
225
}
 
226
 
 
227
void wxHeaderCtrl::RefreshColsAfter(unsigned int idx)
 
228
{
 
229
    wxRect rect = GetClientRect();
 
230
    const int ofs = GetColStart(idx);
 
231
    rect.x += ofs;
 
232
    rect.width -= ofs;
 
233
 
 
234
    RefreshRect(rect);
 
235
}
 
236
 
 
237
// ----------------------------------------------------------------------------
 
238
// wxHeaderCtrl dragging/resizing/reordering
 
239
// ----------------------------------------------------------------------------
 
240
 
 
241
bool wxHeaderCtrl::IsResizing() const
 
242
{
 
243
    return m_colBeingResized != COL_NONE;
 
244
}
 
245
 
 
246
bool wxHeaderCtrl::IsReordering() const
 
247
{
 
248
    return m_colBeingReordered != COL_NONE;
 
249
}
 
250
 
 
251
void wxHeaderCtrl::ClearMarkers()
 
252
{
 
253
    wxClientDC dc(this);
 
254
 
 
255
    wxDCOverlay dcover(m_overlay, &dc);
 
256
    dcover.Clear();
 
257
}
 
258
 
 
259
void wxHeaderCtrl::EndDragging()
 
260
{
 
261
    // We currently only use markers for reordering, not for resizing
 
262
    if (IsReordering())
 
263
    {
 
264
        ClearMarkers();
 
265
        m_overlay.Reset();
 
266
    }
 
267
 
 
268
    // don't use the special dragging cursor any more
 
269
    SetCursor(wxNullCursor);
 
270
}
 
271
 
 
272
void wxHeaderCtrl::CancelDragging()
 
273
{
 
274
    wxASSERT_MSG( IsDragging(),
 
275
                  "shouldn't be called if we're not dragging anything" );
 
276
 
 
277
    EndDragging();
 
278
 
 
279
    unsigned int& col = IsResizing() ? m_colBeingResized : m_colBeingReordered;
 
280
 
 
281
    wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED, GetId());
 
282
    event.SetEventObject(this);
 
283
    event.SetColumn(col);
 
284
 
 
285
    GetEventHandler()->ProcessEvent(event);
 
286
 
 
287
    col = COL_NONE;
 
288
}
 
289
 
 
290
int wxHeaderCtrl::ConstrainByMinWidth(unsigned int col, int& xPhysical)
 
291
{
 
292
    const int xStart = GetColStart(col);
 
293
 
 
294
    // notice that GetMinWidth() returns 0 if there is no minimal width so it
 
295
    // still makes sense to use it even in this case
 
296
    const int xMinEnd = xStart + GetColumn(col).GetMinWidth();
 
297
 
 
298
    if ( xPhysical < xMinEnd )
 
299
        xPhysical = xMinEnd;
 
300
 
 
301
    return xPhysical - xStart;
 
302
}
 
303
 
 
304
void wxHeaderCtrl::StartOrContinueResizing(unsigned int col, int xPhysical)
 
305
{
 
306
    wxHeaderCtrlEvent event(IsResizing() ? wxEVT_COMMAND_HEADER_RESIZING
 
307
                                         : wxEVT_COMMAND_HEADER_BEGIN_RESIZE,
 
308
                            GetId());
 
309
    event.SetEventObject(this);
 
310
    event.SetColumn(col);
 
311
 
 
312
    event.SetWidth(ConstrainByMinWidth(col, xPhysical));
 
313
 
 
314
    if ( GetEventHandler()->ProcessEvent(event) && !event.IsAllowed() )
 
315
    {
 
316
        if ( IsResizing() )
 
317
        {
 
318
            ReleaseMouse();
 
319
            CancelDragging();
 
320
        }
 
321
        //else: nothing to do -- we just don't start to resize
 
322
    }
 
323
    else // go ahead with resizing
 
324
    {
 
325
        if ( !IsResizing() )
 
326
        {
 
327
            m_colBeingResized = col;
 
328
            SetCursor(wxCursor(wxCURSOR_SIZEWE));
 
329
            CaptureMouse();
 
330
        }
 
331
        //else: we had already done the above when we started
 
332
 
 
333
    }
 
334
}
 
335
 
 
336
void wxHeaderCtrl::EndResizing(int xPhysical)
 
337
{
 
338
    wxASSERT_MSG( IsResizing(), "shouldn't be called if we're not resizing" );
 
339
 
 
340
    EndDragging();
 
341
 
 
342
    ReleaseMouse();
 
343
 
 
344
    wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_RESIZE, GetId());
 
345
    event.SetEventObject(this);
 
346
    event.SetColumn(m_colBeingResized);
 
347
    event.SetWidth(ConstrainByMinWidth(m_colBeingResized, xPhysical));
 
348
 
 
349
    GetEventHandler()->ProcessEvent(event);
 
350
 
 
351
    m_colBeingResized = COL_NONE;
 
352
}
 
353
 
 
354
void wxHeaderCtrl::UpdateReorderingMarker(int xPhysical)
 
355
{
 
356
    wxClientDC dc(this);
 
357
 
 
358
    wxDCOverlay dcover(m_overlay, &dc);
 
359
    dcover.Clear();
 
360
 
 
361
    dc.SetPen(*wxBLUE);
 
362
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
 
363
 
 
364
    // draw the phantom position of the column being dragged
 
365
    int x = xPhysical - m_dragOffset;
 
366
    int y = GetClientSize().y;
 
367
    dc.DrawRectangle(x, 0,
 
368
                     GetColumn(m_colBeingReordered).GetWidth(), y);
 
369
 
 
370
    // and also a hint indicating where it is going to be inserted if it's
 
371
    // dropped now
 
372
    unsigned int col = FindColumnAtPoint(xPhysical);
 
373
    if ( col != COL_NONE )
 
374
    {
 
375
        static const int DROP_MARKER_WIDTH = 4;
 
376
 
 
377
        dc.SetBrush(*wxBLUE);
 
378
        dc.DrawRectangle(GetColEnd(col) - DROP_MARKER_WIDTH/2, 0,
 
379
                         DROP_MARKER_WIDTH, y);
 
380
    }
 
381
}
 
382
 
 
383
void wxHeaderCtrl::StartReordering(unsigned int col, int xPhysical)
 
384
{
 
385
    wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_BEGIN_REORDER, GetId());
 
386
    event.SetEventObject(this);
 
387
    event.SetColumn(col);
 
388
 
 
389
    if ( GetEventHandler()->ProcessEvent(event) && !event.IsAllowed() )
 
390
    {
 
391
        // don't start dragging it, nothing to do otherwise
 
392
        return;
 
393
    }
 
394
 
 
395
    m_dragOffset = xPhysical - GetColStart(col);
 
396
 
 
397
    m_colBeingReordered = col;
 
398
    SetCursor(wxCursor(wxCURSOR_HAND));
 
399
    CaptureMouse();
 
400
 
 
401
    // do not call UpdateReorderingMarker() here: we don't want to give
 
402
    // feedback for reordering until the user starts to really move the mouse
 
403
    // as he might want to just click on the column and not move it at all
 
404
}
 
405
 
 
406
bool wxHeaderCtrl::EndReordering(int xPhysical)
 
407
{
 
408
    wxASSERT_MSG( IsReordering(), "shouldn't be called if we're not reordering" );
 
409
 
 
410
    EndDragging();
 
411
 
 
412
    ReleaseMouse();
 
413
 
 
414
    const int colOld = m_colBeingReordered,
 
415
              colNew = FindColumnAtPoint(xPhysical);
 
416
 
 
417
    m_colBeingReordered = COL_NONE;
 
418
 
 
419
    if ( xPhysical - GetColStart(colOld) == m_dragOffset )
 
420
        return false;
 
421
 
 
422
    if ( colNew != colOld )
 
423
    {
 
424
        wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_REORDER, GetId());
 
425
        event.SetEventObject(this);
 
426
        event.SetColumn(colOld);
 
427
 
 
428
        const unsigned pos = GetColumnPos(FindColumnAtPoint(xPhysical));
 
429
        event.SetNewOrder(pos);
 
430
 
 
431
        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
 
432
        {
 
433
            // do reorder the columns
 
434
            DoMoveCol(colOld, pos);
 
435
        }
 
436
    }
 
437
 
 
438
    // whether we moved the column or not, the user did move the mouse and so
 
439
    // did try to do it so return true
 
440
    return true;
 
441
}
 
442
 
 
443
// ----------------------------------------------------------------------------
 
444
// wxHeaderCtrl column reordering
 
445
// ----------------------------------------------------------------------------
 
446
 
 
447
void wxHeaderCtrl::DoSetColumnsOrder(const wxArrayInt& order)
 
448
{
 
449
    m_colIndices = order;
 
450
    Refresh();
 
451
}
 
452
 
 
453
wxArrayInt wxHeaderCtrl::DoGetColumnsOrder() const
 
454
{
 
455
    return m_colIndices;
 
456
}
 
457
 
 
458
void wxHeaderCtrl::DoMoveCol(unsigned int idx, unsigned int pos)
 
459
{
 
460
    MoveColumnInOrderArray(m_colIndices, idx, pos);
 
461
 
 
462
    Refresh();
 
463
}
 
464
 
 
465
// ----------------------------------------------------------------------------
 
466
// wxHeaderCtrl event handlers
 
467
// ----------------------------------------------------------------------------
 
468
 
 
469
BEGIN_EVENT_TABLE(wxHeaderCtrl, wxHeaderCtrlBase)
 
470
    EVT_PAINT(wxHeaderCtrl::OnPaint)
 
471
 
 
472
    EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse)
 
473
 
 
474
    EVT_MOUSE_CAPTURE_LOST(wxHeaderCtrl::OnCaptureLost)
 
475
 
 
476
    EVT_KEY_DOWN(wxHeaderCtrl::OnKeyDown)
 
477
END_EVENT_TABLE()
 
478
 
 
479
void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
 
480
{
 
481
    int w, h;
 
482
    GetClientSize(&w, &h);
 
483
 
 
484
#ifdef __WXGTK__
 
485
//    int vw;
 
486
//    GetVirtualSize(&vw, NULL);
 
487
#endif
 
488
 
 
489
    wxAutoBufferedPaintDC dc(this);
 
490
 
 
491
    dc.SetBackground(GetBackgroundColour());
 
492
    dc.Clear();
 
493
 
 
494
    // account for the horizontal scrollbar offset in the parent window
 
495
    dc.SetDeviceOrigin(m_scrollOffset, 0);
 
496
 
 
497
    const unsigned int count = m_numColumns;
 
498
    int xpos = 0;
 
499
    for ( unsigned int i = 0; i < count; i++ )
 
500
    {
 
501
        const unsigned idx = m_colIndices[i];
 
502
        const wxHeaderColumn& col = GetColumn(idx);
 
503
        if ( col.IsHidden() )
 
504
            continue;
 
505
 
 
506
        int colWidth = col.GetWidth();
 
507
 
 
508
        wxHeaderSortIconType sortArrow;
 
509
        if ( col.IsSortKey() )
 
510
        {
 
511
            sortArrow = col.IsSortOrderAscending() ? wxHDR_SORT_ICON_UP
 
512
                                                   : wxHDR_SORT_ICON_DOWN;
 
513
        }
 
514
        else // not sorting by this column
 
515
        {
 
516
            sortArrow = wxHDR_SORT_ICON_NONE;
 
517
        }
 
518
 
 
519
        int state = 0;
 
520
        if ( IsEnabled() )
 
521
        {
 
522
            if ( idx == m_hover )
 
523
                state = wxCONTROL_CURRENT;
 
524
        }
 
525
        else // disabled
 
526
        {
 
527
            state = wxCONTROL_DISABLED;
 
528
        }
 
529
 
 
530
        if (i == 0)
 
531
           state |= wxCONTROL_SPECIAL;
 
532
 
 
533
        wxHeaderButtonParams params;
 
534
        params.m_labelText = col.GetTitle();
 
535
        params.m_labelBitmap = col.GetBitmap();
 
536
        params.m_labelAlignment = col.GetAlignment();
 
537
 
 
538
#ifdef __WXGTK__
 
539
        if (i == count-1)
 
540
        {
 
541
//            colWidth = wxMax( colWidth, vw - xpos );
 
542
            state |= wxCONTROL_DIRTY;
 
543
        }
 
544
#endif
 
545
 
 
546
        wxRendererNative::Get().DrawHeaderButton
 
547
                                (
 
548
                                    this,
 
549
                                    dc,
 
550
                                    wxRect(xpos, 0, colWidth, h),
 
551
                                    state,
 
552
                                    sortArrow,
 
553
                                    &params
 
554
                                );
 
555
 
 
556
        xpos += colWidth;
 
557
    }
 
558
}
 
559
 
 
560
void wxHeaderCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
 
561
{
 
562
    if ( IsDragging() )
 
563
        CancelDragging();
 
564
}
 
565
 
 
566
void wxHeaderCtrl::OnKeyDown(wxKeyEvent& event)
 
567
{
 
568
    if ( event.GetKeyCode() == WXK_ESCAPE )
 
569
    {
 
570
        if ( IsDragging() )
 
571
        {
 
572
            ReleaseMouse();
 
573
            CancelDragging();
 
574
 
 
575
            return;
 
576
        }
 
577
    }
 
578
 
 
579
    event.Skip();
 
580
}
 
581
 
 
582
void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
 
583
{
 
584
    // do this in advance to allow simply returning if we're not interested,
 
585
    // we'll undo it if we do handle the event below
 
586
    mevent.Skip();
 
587
 
 
588
 
 
589
    // account for the control displacement
 
590
    const int xPhysical = mevent.GetX();
 
591
    const int xLogical = xPhysical - m_scrollOffset;
 
592
 
 
593
    // first deal with the [continuation of any] dragging operations in
 
594
    // progress
 
595
    if ( IsResizing() )
 
596
    {
 
597
        if ( mevent.LeftUp() )
 
598
            EndResizing(xPhysical);
 
599
        else // update the live separator position
 
600
            StartOrContinueResizing(m_colBeingResized, xPhysical);
 
601
 
 
602
        return;
 
603
    }
 
604
 
 
605
    if ( IsReordering() )
 
606
    {
 
607
        if ( !mevent.LeftUp() )
 
608
        {
 
609
            // update the column position
 
610
            UpdateReorderingMarker(xPhysical);
 
611
 
 
612
            return;
 
613
        }
 
614
 
 
615
        // finish reordering and continue to generate a click event below if we
 
616
        // didn't really reorder anything
 
617
        if ( EndReordering(xPhysical) )
 
618
            return;
 
619
    }
 
620
 
 
621
 
 
622
    // find if the event is over a column at all
 
623
    bool onSeparator;
 
624
    const unsigned col = mevent.Leaving()
 
625
                            ? (onSeparator = false, COL_NONE)
 
626
                            : FindColumnAtPoint(xLogical, &onSeparator);
 
627
 
 
628
 
 
629
    // update the highlighted column if it changed
 
630
    if ( col != m_hover )
 
631
    {
 
632
        const unsigned hoverOld = m_hover;
 
633
        m_hover = col;
 
634
 
 
635
        RefreshColIfNotNone(hoverOld);
 
636
        RefreshColIfNotNone(m_hover);
 
637
    }
 
638
 
 
639
    // update mouse cursor as it moves around
 
640
    if ( mevent.Moving() )
 
641
    {
 
642
        SetCursor(onSeparator ? wxCursor(wxCURSOR_SIZEWE) : wxNullCursor);
 
643
        return;
 
644
    }
 
645
 
 
646
    // all the other events only make sense when they happen over a column
 
647
    if ( col == COL_NONE )
 
648
        return;
 
649
 
 
650
 
 
651
    // enter various dragging modes on left mouse press
 
652
    if ( mevent.LeftDown() )
 
653
    {
 
654
        if ( onSeparator )
 
655
        {
 
656
            // start resizing the column
 
657
            wxASSERT_MSG( !IsResizing(), "reentering column resize mode?" );
 
658
            StartOrContinueResizing(col, xPhysical);
 
659
        }
 
660
        else // on column itself
 
661
        {
 
662
            // start dragging the column
 
663
            wxASSERT_MSG( !IsReordering(), "reentering column move mode?" );
 
664
 
 
665
            StartReordering(col, xPhysical);
 
666
        }
 
667
 
 
668
        return;
 
669
    }
 
670
 
 
671
    // determine the type of header event corresponding to click events
 
672
    wxEventType evtType = wxEVT_NULL;
 
673
    const bool click = mevent.ButtonUp(),
 
674
               dblclk = mevent.ButtonDClick();
 
675
    if ( click || dblclk )
 
676
    {
 
677
        switch ( mevent.GetButton() )
 
678
        {
 
679
            case wxMOUSE_BTN_LEFT:
 
680
                // treat left double clicks on separator specially
 
681
                if ( onSeparator && dblclk )
 
682
                {
 
683
                    evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
 
684
                }
 
685
                else // not double click on separator
 
686
                {
 
687
                    evtType = click ? wxEVT_COMMAND_HEADER_CLICK
 
688
                                    : wxEVT_COMMAND_HEADER_DCLICK;
 
689
                }
 
690
                break;
 
691
 
 
692
            case wxMOUSE_BTN_RIGHT:
 
693
                evtType = click ? wxEVT_COMMAND_HEADER_RIGHT_CLICK
 
694
                                : wxEVT_COMMAND_HEADER_RIGHT_DCLICK;
 
695
                break;
 
696
 
 
697
            case wxMOUSE_BTN_MIDDLE:
 
698
                evtType = click ? wxEVT_COMMAND_HEADER_MIDDLE_CLICK
 
699
                                : wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
 
700
                break;
 
701
 
 
702
            default:
 
703
                // ignore clicks from other mouse buttons
 
704
                ;
 
705
        }
 
706
    }
 
707
 
 
708
    if ( evtType == wxEVT_NULL )
 
709
        return;
 
710
 
 
711
    wxHeaderCtrlEvent event(evtType, GetId());
 
712
    event.SetEventObject(this);
 
713
    event.SetColumn(col);
 
714
 
 
715
    if ( GetEventHandler()->ProcessEvent(event) )
 
716
        mevent.Skip(false);
 
717
}
 
718
 
 
719
#endif // wxHAS_GENERIC_HEADERCTRL
 
720
 
 
721
#endif // wxUSE_HEADERCTRL