From: Vadim Zeitlin Date: Fri, 5 Dec 2008 22:44:54 +0000 (+0000) Subject: generic implementation of wxHeaderCtrl API so far X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/b63f9a33301b1cead8b9ccbb16e2f50b0d82bbe9 generic implementation of wxHeaderCtrl API so far git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57136 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/headercolg.h b/include/wx/generic/headercolg.h new file mode 100644 index 0000000000..d0abd6936a --- /dev/null +++ b/include/wx/generic/headercolg.h @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/generic/headercolg.h +// Purpose: Generic wxHeaderColumn implementation +// Author: Vadim Zeitlin +// Created: 2008-12-04 +// RCS-ID: $Id$ +// Copyright: (c) 2008 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_GENERIC_HEADERCOLG_H_ +#define _WX_GENERIC_HEADERCOLG_H_ + +// ---------------------------------------------------------------------------- +// wxHeaderColumn: trivial generic implementation of wxHeaderColumnBase +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxHeaderColumn : public wxHeaderColumnBase +{ +public: + // ctors and dtor + wxHeaderColumn(const wxString& title, + int width = wxCOL_WIDTH_DEFAULT, + wxAlignment align = wxALIGN_NOT, + int flags = wxCOL_DEFAULT_FLAGS) + : m_title(title), + m_width(width), + m_align(align), + m_flags(flags) + { + Init(); + } + + wxHeaderColumn(const wxBitmap& bitmap, + int width = wxCOL_WIDTH_DEFAULT, + wxAlignment align = wxALIGN_CENTER, + int flags = wxCOL_DEFAULT_FLAGS) + : m_bitmap(bitmap), + m_width(width), + m_align(align), + m_flags(flags) + { + Init(); + } + + // implement base class pure virtuals + virtual void SetTitle(const wxString& title) { m_title = title; } + virtual wxString GetTitle() const { return m_title; } + + virtual void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; } + wxBitmap GetBitmap() const { return m_bitmap; } + + virtual void SetWidth(int width) { m_width = width; } + virtual int GetWidth() const { return m_width; } + + virtual void SetMinWidth(int minWidth) { m_minWidth = minWidth; } + virtual int GetMinWidth() const { return m_minWidth; } + + virtual void SetAlignment(wxAlignment align) { m_align = align; } + virtual wxAlignment GetAlignment() const { return m_align; } + + virtual void SetFlags(int flags) { m_flags = flags; } + virtual int GetFlags() const { return m_flags; } + + virtual void SetSortOrder(bool ascending) { m_sortAscending = ascending; } + virtual bool IsSortOrderAscending() const { return m_sortAscending; } + +private: + // common part of all ctors + void Init() + { + m_minWidth = 0; + m_sortAscending = true; + } + + wxString m_title; + wxBitmap m_bitmap; + int m_width, + m_minWidth; + wxAlignment m_align; + int m_flags; + bool m_sortAscending; +}; +#endif // _WX_GENERIC_HEADERCOLG_H_ + diff --git a/include/wx/generic/headerctrlg.h b/include/wx/generic/headerctrlg.h new file mode 100644 index 0000000000..78f8c42a0d --- /dev/null +++ b/include/wx/generic/headerctrlg.h @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/generic/headerctrlg.h +// Purpose: Generic wxHeaderCtrl implementation +// Author: Vadim Zeitlin +// Created: 2008-12-01 +// RCS-ID: $Id$ +// Copyright: (c) 2008 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_GENERIC_HEADERCTRLG_H_ +#define _WX_GENERIC_HEADERCTRLG_H_ + +#include "wx/event.h" +#include "wx/vector.h" + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxHeaderCtrl : public wxHeaderCtrlBase +{ +public: + wxHeaderCtrl() + { + Init(); + } + + wxHeaderCtrl(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxHD_DEFAULT_STYLE, + const wxString& name = wxHeaderCtrlNameStr) + { + Init(); + + Create(parent, id, pos, size, style, name); + } + + bool Create(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxHD_DEFAULT_STYLE, + const wxString& name = wxHeaderCtrlNameStr); + + virtual ~wxHeaderCtrl(); + +private: + // implement base class pure virtuals + virtual unsigned int DoGetCount() const; + virtual void DoInsert(const wxHeaderColumn& col, unsigned int idx); + virtual void DoDelete(unsigned int idx); + virtual void DoShowColumn(unsigned int idx, bool show); + virtual void DoShowSortIndicator(unsigned int idx, int sortOrder); + virtual void DoScrollHorz(int dx); + + // override wxWindow methods which must be implemented by a new control + virtual wxSize DoGetBestSize() const; + + // common part of all ctors + void Init(); + + // event handlers + void OnPaint(wxPaintEvent& event); + void OnMouse(wxMouseEvent& event); + + // return the horizontal start position of the given column + int GetColStart(unsigned int idx) const; + + // refresh the given column [only] + void RefreshCol(unsigned int idx); + + // refresh all the controls starting from (and including) the given one + void RefreshColsAfter(unsigned int idx); + + // all our current columns + typedef wxVector Columns; + Columns m_cols; + + // sorting indicators for the columns: our API is such that it allows using + // multiple columns for sorting, and even if this is not used anywhere in + // practice right now, still support this + // + // the values are interpreted in the same way as ShowSortIndicator() + // sortOrder parameter: true/false for ascending/descending sort if the + // corresponding column is used for sorting or -1 otherwise + wxVector m_sortOrders; + + // index of the column under mouse or -1 if none + unsigned int m_hover; + + // the horizontal scroll offset + int m_scrollOffset; + + + DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxHeaderCtrl) +}; + +#endif // _WX_GENERIC_HEADERCTRLG_H_ + diff --git a/include/wx/headercol.h b/include/wx/headercol.h index 00bd30ebd1..de5d1b0481 100644 --- a/include/wx/headercol.h +++ b/include/wx/headercol.h @@ -165,7 +165,7 @@ protected: #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) #include "wx/msw/headercol.h" -#elif 0 // TODO +#else #define wxHAS_GENERIC_HEADERCOL #include "wx/generic/headercolg.h" #endif diff --git a/include/wx/headerctrl.h b/include/wx/headerctrl.h index 3d0773f097..026cca9c1d 100644 --- a/include/wx/headerctrl.h +++ b/include/wx/headerctrl.h @@ -160,7 +160,7 @@ private: #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) #include "wx/msw/headerctrl.h" -#elif 0 // TODO +#else #define wxHAS_GENERIC_HEADERCTRL #include "wx/generic/headerctrlg.h" #endif // platform diff --git a/src/generic/headerctrlg.cpp b/src/generic/headerctrlg.cpp index 307a8a6e8d..d42a3f8ac8 100644 --- a/src/generic/headerctrlg.cpp +++ b/src/generic/headerctrlg.cpp @@ -30,8 +30,249 @@ #ifdef wxHAS_GENERIC_HEADERCTRL +#include "wx/dcbuffer.h" +#include "wx/renderer.h" + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +namespace +{ + +const unsigned NO_SORT = (unsigned)-1; + +const unsigned COL_NONE = (unsigned)-1; + +} // anonymous namespace + // ============================================================================ -// implementation +// wxHeaderCtrl implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxHeaderCtrl creation +// ---------------------------------------------------------------------------- + +void wxHeaderCtrl::Init() +{ + m_hover = COL_NONE; + m_scrollOffset = 0; +} + +bool wxHeaderCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) +{ + if ( !wxHeaderCtrlBase::Create(parent, id, pos, size, + style, wxDefaultValidator, name) ) + return false; + + // tell the system to not paint the background at all to avoid flicker as + // we paint the entire window area in our OnPaint() + SetBackgroundStyle(wxBG_STYLE_CUSTOM); + + return true; +} + +wxHeaderCtrl::~wxHeaderCtrl() +{ +} + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl columns manipulation +// ---------------------------------------------------------------------------- + +unsigned int wxHeaderCtrl::DoGetCount() const +{ + return m_cols.size(); +} + +void wxHeaderCtrl::DoInsert(const wxHeaderColumn& col, unsigned int idx) +{ + m_cols.insert(m_cols.begin() + idx, col); + m_sortOrders.insert(m_sortOrders.begin() + idx, -1); + + if ( m_cols[idx].IsShown() ) + RefreshColsAfter(idx); +} + +void wxHeaderCtrl::DoDelete(unsigned int idx) +{ + m_cols.erase(m_cols.begin() + idx); + m_sortOrders.erase(m_sortOrders.begin() + idx); + + RefreshColsAfter(idx); +} + +void wxHeaderCtrl::DoShowColumn(unsigned int idx, bool show) +{ + if ( show != m_cols[idx].IsShown() ) + { + m_cols[idx].SetHidden(!show); + + RefreshColsAfter(idx); + } +} + +void wxHeaderCtrl::DoShowSortIndicator(unsigned int idx, int sortOrder) +{ + if ( sortOrder != m_sortOrders[idx] ) + { + m_sortOrders[idx] = sortOrder; + + RefreshCol(idx); + } +} + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl scrolling +// ---------------------------------------------------------------------------- + +void wxHeaderCtrl::DoScrollHorz(int dx) +{ + m_scrollOffset += dx; + + // don't call our own version which calls this function! + wxControl::ScrollWindow(dx, 0); +} + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl geometry +// ---------------------------------------------------------------------------- + +wxSize wxHeaderCtrl::DoGetBestSize() const +{ + // the vertical size is rather arbitrary but it looks better if we leave + // some space around the text + return wxSize(GetColStart(GetColumnCount()), (7*GetCharHeight())/4); +} + +int wxHeaderCtrl::GetColStart(unsigned int idx) const +{ + int pos = 0; + for ( unsigned n = 0; n < idx; n++ ) + { + const wxHeaderColumn& col = m_cols[n]; + if ( col.IsShown() ) + pos += col.GetWidth(); + } + + return pos; +} + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl repainting +// ---------------------------------------------------------------------------- + +void wxHeaderCtrl::RefreshCol(unsigned int idx) +{ + wxRect rect = GetClientRect(); + rect.x += GetColStart(idx); + rect.width = m_cols[idx].GetWidth(); + + RefreshRect(rect); +} + +void wxHeaderCtrl::RefreshColsAfter(unsigned int idx) +{ + wxRect rect = GetClientRect(); + const int ofs = GetColStart(idx); + rect.x += ofs; + rect.width -= ofs; + + RefreshRect(rect); +} + +// ---------------------------------------------------------------------------- +// wxHeaderCtrl event handlers +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(wxHeaderCtrl, wxControl) + EVT_PAINT(wxHeaderCtrl::OnPaint) + + EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse) +END_EVENT_TABLE() + +void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + + wxAutoBufferedPaintDC dc(this); + + dc.SetBackground(GetBackgroundColour()); + dc.Clear(); + + // account for the horizontal scrollbar offset in the parent window + dc.SetDeviceOrigin(m_scrollOffset, 0); + + const unsigned int count = m_cols.size(); + int xpos = 0; + for ( unsigned int i = 0; i < count; i++ ) + { + const wxHeaderColumn& col = m_cols[i]; + if ( col.IsHidden() ) + continue; + + const int colWidth = col.GetWidth(); + + wxHeaderSortIconType sortArrow; + switch ( m_sortOrders[i] ) + { + default: + wxFAIL_MSG( "wrong sort order value" ); + // fall through + + case -1: + sortArrow = wxHDR_SORT_ICON_NONE; + break; + + case 0: + sortArrow = wxHDR_SORT_ICON_DOWN; + break; + + case 1: + sortArrow = wxHDR_SORT_ICON_UP; + break; + } + + int state = 0; + if ( IsEnabled() ) + { + if ( i == m_hover ) + state = wxCONTROL_CURRENT; + } + else // disabled + { + state = wxCONTROL_DISABLED; + } + + wxHeaderButtonParams params; + params.m_labelText = col.GetTitle(); + params.m_labelBitmap = col.GetBitmap(); + params.m_labelAlignment = col.GetAlignment(); + + wxRendererNative::Get().DrawHeaderButton + ( + this, + dc, + wxRect(xpos, 0, colWidth, h), + state, + sortArrow, + ¶ms + ); + + xpos += colWidth; + } +} + +void wxHeaderCtrl::OnMouse(wxMouseEvent& event) +{ + event.Skip(); +} + #endif // wxHAS_GENERIC_HEADERCTRL