+#if wxUSE_LISTCTRL
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+
+ #include "wx/dynarray.h"
+
+ #include "wx/dcscreen.h"
+
+ #include "wx/textctrl.h"
+#endif
+
+// under Win32 we always use the native version and also may use the generic
+// one, however some things should be done only if we use only the generic
+// version
+#if defined(__WIN32__) && !defined(__WXUNIVERSAL__)
+ #define HAVE_NATIVE_LISTCTRL
+#endif
+
+// if we have the native control, wx/listctrl.h declares it and not this one
+#ifdef HAVE_NATIVE_LISTCTRL
+ #include "wx/generic/listctrl.h"
+#else // !HAVE_NATIVE_LISTCTRL
+ #include "wx/listctrl.h"
+
+ // if we have a native version, its implementation file does all this
+ IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
+ IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
+ IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
+
+ IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl)
+#endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL
+
+#include "wx/selstore.h"
+
+#include "wx/renderer.h"
+
+// ----------------------------------------------------------------------------
+// events
+// ----------------------------------------------------------------------------
+
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// the height of the header window (FIXME: should depend on its font!)
+static const int HEADER_HEIGHT = 23;
+
+// the scrollbar units
+static const int SCROLL_UNIT_X = 15;
+static const int SCROLL_UNIT_Y = 15;
+
+// the spacing between the lines (in report mode)
+static const int LINE_SPACING = 0;
+
+// extra margins around the text label
+static const int EXTRA_WIDTH = 3;
+static const int EXTRA_HEIGHT = 4;
+
+// offset for the header window
+static const int HEADER_OFFSET_X = 1;
+static const int HEADER_OFFSET_Y = 1;
+
+// when autosizing the columns, add some slack
+static const int AUTOSIZE_COL_MARGIN = 10;
+
+// default and minimal widths for the header columns
+static const int WIDTH_COL_DEFAULT = 80;
+static const int WIDTH_COL_MIN = 10;
+
+// the space between the image and the text in the report mode
+static const int IMAGE_MARGIN_IN_REPORT_MODE = 5;
+
+// ============================================================================
+// private classes
+// ============================================================================
+
+//-----------------------------------------------------------------------------
+// wxListItemData (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListItemData
+{
+public:
+ wxListItemData(wxListMainWindow *owner);
+ ~wxListItemData();
+
+ void SetItem( const wxListItem &info );
+ void SetImage( int image ) { m_image = image; }
+ void SetData( long data ) { m_data = data; }
+ void SetPosition( int x, int y );
+ void SetSize( int width, int height );
+
+ bool HasText() const { return !m_text.empty(); }
+ const wxString& GetText() const { return m_text; }
+ void SetText(const wxString& text) { m_text = text; }
+
+ // we can't use empty string for measuring the string width/height, so
+ // always return something
+ wxString GetTextForMeasuring() const
+ {
+ wxString s = GetText();
+ if ( s.empty() )
+ s = _T('H');
+
+ return s;
+ }
+
+ bool IsHit( int x, int y ) const;
+
+ int GetX() const;
+ int GetY() const;
+ int GetWidth() const;
+ int GetHeight() const;
+
+ int GetImage() const { return m_image; }
+ bool HasImage() const { return GetImage() != -1; }
+
+ void GetItem( wxListItem &info ) const;
+
+ void SetAttr(wxListItemAttr *attr) { m_attr = attr; }
+ wxListItemAttr *GetAttr() const { return m_attr; }
+
+public:
+ // the item image or -1
+ int m_image;
+
+ // user data associated with the item
+ long m_data;
+
+ // the item coordinates are not used in report mode, instead this pointer
+ // is NULL and the owner window is used to retrieve the item position and
+ // size
+ wxRect *m_rect;
+
+ // the list ctrl we are in
+ wxListMainWindow *m_owner;
+
+ // custom attributes or NULL
+ wxListItemAttr *m_attr;
+
+protected:
+ // common part of all ctors
+ void Init();
+
+ wxString m_text;
+};
+
+//-----------------------------------------------------------------------------
+// wxListHeaderData (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListHeaderData : public wxObject
+{
+public:
+ wxListHeaderData();
+ wxListHeaderData( const wxListItem &info );
+ void SetItem( const wxListItem &item );
+ void SetPosition( int x, int y );
+ void SetWidth( int w );
+ void SetFormat( int format );
+ void SetHeight( int h );
+ bool HasImage() const;
+
+ bool HasText() const { return !m_text.empty(); }
+ const wxString& GetText() const { return m_text; }
+ void SetText(const wxString& text) { m_text = text; }
+
+ void GetItem( wxListItem &item );
+
+ bool IsHit( int x, int y ) const;
+ int GetImage() const;
+ int GetWidth() const;
+ int GetFormat() const;
+
+protected:
+ long m_mask;
+ int m_image;
+ wxString m_text;
+ int m_format;
+ int m_width;
+ int m_xpos,
+ m_ypos;
+ int m_height;
+
+private:
+ void Init();
+};
+
+//-----------------------------------------------------------------------------
+// wxListLineData (internal)
+//-----------------------------------------------------------------------------
+
+WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
+#include "wx/listimpl.cpp"
+WX_DEFINE_LIST(wxListItemDataList);
+
+class wxListLineData
+{
+public:
+ // the list of subitems: only may have more than one item in report mode
+ wxListItemDataList m_items;
+
+ // this is not used in report view
+ struct GeometryInfo
+ {
+ // total item rect
+ wxRect m_rectAll;
+
+ // label only
+ wxRect m_rectLabel;
+
+ // icon only
+ wxRect m_rectIcon;
+
+ // the part to be highlighted
+ wxRect m_rectHighlight;
+ } *m_gi;
+
+ // is this item selected? [NB: not used in virtual mode]
+ bool m_highlighted;
+
+ // back pointer to the list ctrl
+ wxListMainWindow *m_owner;
+
+public:
+ wxListLineData(wxListMainWindow *owner);
+
+ ~wxListLineData()
+ {
+ WX_CLEAR_LIST(wxListItemDataList, m_items);
+ delete m_gi;
+ }
+
+ // are we in report mode?
+ inline bool InReportView() const;
+
+ // are we in virtual report mode?
+ inline bool IsVirtual() const;
+
+ // these 2 methods shouldn't be called for report view controls, in that
+ // case we determine our position/size ourselves
+
+ // calculate the size of the line
+ void CalculateSize( wxDC *dc, int spacing );
+
+ // remember the position this line appears at
+ void SetPosition( int x, int y, int window_width, int spacing );
+
+ // wxListCtrl API
+
+ void SetImage( int image ) { SetImage(0, image); }
+ int GetImage() const { return GetImage(0); }
+ bool HasImage() const { return GetImage() != -1; }
+ bool HasText() const { return !GetText(0).empty(); }
+
+ void SetItem( int index, const wxListItem &info );
+ void GetItem( int index, wxListItem &info );
+
+ wxString GetText(int index) const;
+ void SetText( int index, const wxString s );
+
+ wxListItemAttr *GetAttr() const;
+ void SetAttr(wxListItemAttr *attr);
+
+ // return true if the highlighting really changed
+ bool Highlight( bool on );
+
+ void ReverseHighlight();
+
+ bool IsHighlighted() const
+ {
+ wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
+
+ return m_highlighted;
+ }
+
+ // draw the line on the given DC in icon/list mode
+ void Draw( wxDC *dc );
+
+ // the same in report mode
+ void DrawInReportMode( wxDC *dc,
+ const wxRect& rect,
+ const wxRect& rectHL,
+ bool highlighted );
+
+private:
+ // set the line to contain num items (only can be > 1 in report mode)
+ void InitItems( int num );
+
+ // get the mode (i.e. style) of the list control
+ inline int GetMode() const;
+
+ // prepare the DC for drawing with these item's attributes, return true if
+ // we need to draw the items background to highlight it, false otherwise
+ bool SetAttributes(wxDC *dc,
+ const wxListItemAttr *attr,
+ bool highlight);
+
+ // draw the text on the DC with the correct justification; also add an
+ // ellipsis if the text is too large to fit in the current width
+ void DrawTextFormatted(wxDC *dc, const wxString &text, int col, int x, int y, int width);
+
+ // these are only used by GetImage/SetImage above, we don't support images
+ // with subitems at the public API level yet
+ void SetImage( int index, int image );
+ int GetImage( int index ) const;
+};
+
+WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
+#include "wx/arrimpl.cpp"
+WX_DEFINE_OBJARRAY(wxListLineDataArray);
+
+//-----------------------------------------------------------------------------
+// wxListHeaderWindow (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListHeaderWindow : public wxWindow
+{
+protected:
+ wxListMainWindow *m_owner;
+ wxCursor *m_currentCursor;
+ wxCursor *m_resizeCursor;
+ bool m_isDragging;
+
+ // column being resized or -1
+ int m_column;
+
+ // divider line position in logical (unscrolled) coords
+ int m_currentX;
+
+ // minimal position beyond which the divider line can't be dragged in
+ // logical coords
+ int m_minX;
+
+public:
+ wxListHeaderWindow();
+
+ wxListHeaderWindow( wxWindow *win,
+ wxWindowID id,
+ wxListMainWindow *owner,
+ const wxPoint &pos = wxDefaultPosition,
+ const wxSize &size = wxDefaultSize,
+ long style = 0,
+ const wxString &name = wxT("wxlistctrlcolumntitles") );
+
+ virtual ~wxListHeaderWindow();
+
+ void DrawCurrent();
+ void AdjustDC(wxDC& dc);
+
+ void OnPaint( wxPaintEvent &event );
+ void OnMouse( wxMouseEvent &event );
+ void OnSetFocus( wxFocusEvent &event );
+
+ // needs refresh
+ bool m_dirty;
+
+private:
+ // common part of all ctors
+ void Init();
+
+ // generate and process the list event of the given type, return true if
+ // it wasn't vetoed, i.e. if we should proceed
+ bool SendListEvent(wxEventType type, wxPoint pos);
+
+ DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
+ DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxListRenameTimer (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListRenameTimer: public wxTimer
+{
+private:
+ wxListMainWindow *m_owner;
+
+public:
+ wxListRenameTimer( wxListMainWindow *owner );
+ void Notify();
+};
+
+//-----------------------------------------------------------------------------
+// wxListTextCtrl (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl
+{
+public:
+ wxListTextCtrl(wxListMainWindow *owner, size_t itemEdit);
+
+protected:
+ void OnChar( wxKeyEvent &event );
+ void OnKeyUp( wxKeyEvent &event );
+ void OnKillFocus( wxFocusEvent &event );
+
+ bool AcceptChanges();
+ void Finish();
+
+private:
+ wxListMainWindow *m_owner;
+ wxString m_startValue;
+ size_t m_itemEdited;
+ bool m_finished;
+
+ DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxListMainWindow (internal)
+//-----------------------------------------------------------------------------
+
+WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
+#include "wx/listimpl.cpp"
+WX_DEFINE_LIST(wxListHeaderDataList);
+
+class wxListMainWindow : public wxScrolledWindow
+{
+public:
+ wxListMainWindow();
+ wxListMainWindow( wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0,
+ const wxString &name = _T("listctrlmainwindow") );
+
+ virtual ~wxListMainWindow();
+
+ bool HasFlag(int flag) const { return m_parent->HasFlag(flag); }
+
+ // return true if this is a virtual list control
+ bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL); }
+
+ // return true if the control is in report mode
+ bool InReportView() const { return HasFlag(wxLC_REPORT); }
+
+ // return true if we are in single selection mode, false if multi sel
+ bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL); }
+
+ // do we have a header window?
+ bool HasHeader() const
+ { return HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER); }
+
+ void HighlightAll( bool on );
+
+ // all these functions only do something if the line is currently visible