Use wxClientDataDictionary for client data.

Factored out common code into wxSizeKeeper.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18415 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Mattia Barbon 2002-12-24 18:41:42 +00:00
parent c13c9657a4
commit 99ab3e3f56
2 changed files with 100 additions and 172 deletions

View File

@ -17,6 +17,7 @@
#endif #endif
#include "wx/ctrlsub.h" #include "wx/ctrlsub.h"
#include "wx/clntdata.h"
WXDLLEXPORT_DATA(extern const char*) wxListBoxNameStr; WXDLLEXPORT_DATA(extern const char*) wxListBoxNameStr;
@ -38,8 +39,7 @@ public:
int n = 0, const wxString choices[] = NULL, int n = 0, const wxString choices[] = NULL,
long style = 0, long style = 0,
const wxValidator& validator = wxDefaultValidator, const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxListBoxNameStr): const wxString& name = wxListBoxNameStr)
m_clientDataList(wxKEY_INTEGER)
{ {
Create(parent, id, pos, size, n, choices, style, validator, name); Create(parent, id, pos, size, n, choices, style, validator, name);
} }
@ -57,10 +57,10 @@ public:
// implementation of wxControlWithItems // implementation of wxControlWithItems
virtual int GetCount() const; virtual int GetCount() const;
virtual int DoAppend(const wxString& item); virtual int DoAppend(const wxString& item);
virtual void DoSetItemClientData(int n, void* clientData); // virtual void DoSetItemClientData(int n, void* clientData);
virtual void* DoGetItemClientData(int n) const; // virtual void* DoGetItemClientData(int n) const;
virtual void DoSetItemClientObject(int n, wxClientData* clientData); // virtual void DoSetItemClientObject(int n, wxClientData* clientData);
virtual wxClientData* DoGetItemClientObject(int n) const; // virtual wxClientData* DoGetItemClientObject(int n) const;
virtual int GetSelection() const; virtual int GetSelection() const;
virtual void Delete(int n); virtual void Delete(int n);
virtual int FindString(const wxString& s) const; virtual int FindString(const wxString& s) const;
@ -80,7 +80,6 @@ public:
void Command(wxCommandEvent& event); void Command(wxCommandEvent& event);
// Implementation // Implementation
virtual void ChangeFont(bool keepOriginalSize = TRUE);
virtual void ChangeBackgroundColour(); virtual void ChangeBackgroundColour();
virtual void ChangeForegroundColour(); virtual void ChangeForegroundColour();
WXWidget GetTopWidget() const; WXWidget GetTopWidget() const;
@ -92,11 +91,9 @@ protected:
int m_noItems; int m_noItems;
// List mapping positions->client data // List mapping positions->client data
wxList m_clientDataList; wxClientDataDictionary m_clientDataDict;
private:
virtual void DoSetSize(int x, int y, void SetSelectionPolicy();
int width, int height,
int sizeFlags = wxSIZE_AUTO);
}; };
#endif #endif

View File

@ -39,12 +39,38 @@ static void wxListBoxCallback(Widget w,
XtPointer clientData, XtPointer clientData,
XmListCallbackStruct * cbs); XmListCallbackStruct * cbs);
// ----------------------------------------------------------------------------
// wxSizeKeeper
// ----------------------------------------------------------------------------
// helper class to reduce code duplication
class wxSizeKeeper
{
int m_x, m_y;
wxWindow* m_w;
public:
wxSizeKeeper( wxWindow* w )
: m_w( w )
{
m_w->GetSize( &m_x, &m_y );
}
void Restore()
{
int x, y;
m_w->GetSize( &x, &y );
if( x != m_x || y != m_y )
m_w->SetSize( -1, -1, m_x, m_y );
}
};
// ============================================================================ // ============================================================================
// list box control implementation // list box control implementation
// ============================================================================ // ============================================================================
// Listbox item // Listbox item
wxListBox::wxListBox() : m_clientDataList(wxKEY_INTEGER) wxListBox::wxListBox()
{ {
m_noItems = 0; m_noItems = 0;
} }
@ -57,37 +83,28 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id,
const wxValidator& validator, const wxValidator& validator,
const wxString& name) const wxString& name)
{ {
m_windowStyle = style; if( !wxControl::CreateControl( parent, id, pos, size, style,
validator, name ) )
return FALSE;
m_noItems = n; m_noItems = n;
// m_backgroundColour = parent->GetBackgroundColour();
m_backgroundColour = * wxWHITE; m_backgroundColour = * wxWHITE;
m_foregroundColour = parent->GetForegroundColour();
SetName(name);
SetValidator(validator);
if (parent) parent->AddChild(this);
m_windowId = ( id == -1 ) ? (int)NewControlId() : id;
Widget parentWidget = (Widget) parent->GetClientWidget(); Widget parentWidget = (Widget) parent->GetClientWidget();
Arg args[3]; Arg args[3];
int count; int count = 0;
XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); XtSetArg( args[0], XmNlistSizePolicy, XmCONSTANT ); ++count;
if (m_windowStyle & wxLB_MULTIPLE) XtSetArg( args[1], XmNselectionPolicy,
XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); ( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT :
else if (m_windowStyle & wxLB_EXTENDED) ( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT :
XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); XmBROWSE_SELECT );
else ++count;
XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); if( m_windowStyle & wxLB_ALWAYS_SB )
if (m_windowStyle & wxLB_ALWAYS_SB)
{ {
XtSetArg (args[2], XmNscrollBarDisplayPolicy, XmSTATIC); XtSetArg( args[2], XmNscrollBarDisplayPolicy, XmSTATIC );
count = 3; ++count;
} }
else
count = 2;
Widget listWidget = XmCreateScrolledList(parentWidget, Widget listWidget = XmCreateScrolledList(parentWidget,
(char*)name.c_str(), args, count); (char*)name.c_str(), args, count);
@ -122,7 +139,6 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id,
(XtCallbackProc) wxListBoxCallback, (XtCallbackProc) wxListBoxCallback,
(XtPointer) this); (XtPointer) this);
m_font = parent->GetFont();
ChangeFont(FALSE); ChangeFont(FALSE);
SetCanAddEventHandler(TRUE); SetCanAddEventHandler(TRUE);
@ -136,6 +152,23 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id,
wxListBox::~wxListBox() wxListBox::~wxListBox()
{ {
if( HasClientObjectData() )
m_clientDataDict.DestroyData();
}
void wxListBox::SetSelectionPolicy()
{
Widget listBox = (Widget)m_mainWidget;
Arg args[3];
XtSetArg( args[0], XmNlistSizePolicy, XmCONSTANT );
XtSetArg( args[1], XmNselectionPolicy,
( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT :
( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT :
XmBROWSE_SELECT );
XtSetValues( listBox, args, 2 );
} }
void wxListBox::DoSetFirstItem( int N ) void wxListBox::DoSetFirstItem( int N )
@ -155,10 +188,8 @@ void wxListBox::DoSetFirstItem( int N )
void wxListBox::Delete(int N) void wxListBox::Delete(int N)
{ {
int width1, height1; wxSizeKeeper sk( this );
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize (&width1, &height1);
bool managed = XtIsManaged(listBox); bool managed = XtIsManaged(listBox);
@ -170,35 +201,15 @@ void wxListBox::Delete(int N)
if (managed) if (managed)
XtManageChild (listBox); XtManageChild (listBox);
GetSize (&width2, &height2); sk.Restore();
// Correct for randomly resized listbox - bad boy, Motif! m_clientDataDict.Delete(N, HasClientObjectData());
if (width1 != width2 || height1 != height2)
SetSize (-1, -1, width1, height1);
// (JDH) need to add code here to take care of clientDataList
// get item from list
wxNode *node = m_clientDataList.Find((long)N);
// if existed then delete from list
if (node) m_clientDataList.DeleteNode(node);
// we now have to adjust all keys that are >=N+1
node = m_clientDataList.First();
while (node)
{
if (node->GetKeyInteger() >= (long)(N+1))
node->SetKeyInteger(node->GetKeyInteger() - 1);
node = node->Next();
}
m_noItems --; m_noItems --;
} }
int wxListBox::DoAppend(const wxString& item) int wxListBox::DoAppend(const wxString& item)
{ {
int width1, height1; wxSizeKeeper sk( this );
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize (&width1, &height1);
bool managed = XtIsManaged(listBox); bool managed = XtIsManaged(listBox);
@ -206,30 +217,18 @@ int wxListBox::DoAppend(const wxString& item)
XtUnmanageChild (listBox); XtUnmanageChild (listBox);
int n; int n;
XtVaGetValues (listBox, XmNitemCount, &n, NULL); XtVaGetValues (listBox, XmNitemCount, &n, NULL);
XmString text = XmStringCreateSimple ((char*) (const char*) item); wxXmString text( item );
// XmListAddItem(listBox, text, n + 1); // XmListAddItem(listBox, text, n + 1);
XmListAddItemUnselected (listBox, text, 0); XmListAddItemUnselected (listBox, text(), 0);
XmStringFree (text);
// It seems that if the list is cleared, we must re-ask for // It seems that if the list is cleared, we must re-ask for
// selection policy!! // selection policy!!
Arg args[3]; SetSelectionPolicy();
XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT);
if (m_windowStyle & wxLB_MULTIPLE)
XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT);
else if (m_windowStyle & wxLB_EXTENDED)
XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT);
else
XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT);
XtSetValues (listBox, args, 2);
if (managed) if (managed)
XtManageChild (listBox); XtManageChild (listBox);
GetSize (&width2, &height2); sk.Restore();
// Correct for randomly resized listbox - bad boy, Motif!
if (width1 != width2 || height1 != height2)
SetSize (-1, -1, width1, height1);
m_noItems ++; m_noItems ++;
return GetCount() - 1; return GetCount() - 1;
@ -237,12 +236,11 @@ int wxListBox::DoAppend(const wxString& item)
void wxListBox::DoSetItems(const wxArrayString& items, void** clientData) void wxListBox::DoSetItems(const wxArrayString& items, void** clientData)
{ {
m_clientDataList.Clear(); wxSizeKeeper sk( this );
int width1, height1;
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize (&width1, &height1);
if( HasClientObjectData() )
m_clientDataDict.DestroyData();
bool managed = XtIsManaged(listBox); bool managed = XtIsManaged(listBox);
@ -255,7 +253,7 @@ void wxListBox::DoSetItems(const wxArrayString& items, void** clientData)
if ( clientData ) if ( clientData )
for (i = 0; i < items.GetCount(); ++i) for (i = 0; i < items.GetCount(); ++i)
m_clientDataList.Append ((long) i, (wxObject *) clientData[i]); m_clientDataDict.Set(i, (wxClientData*)clientData[i], FALSE);
XmListAddItems (listBox, text, items.GetCount(), 0); XmListAddItems (listBox, text, items.GetCount(), 0);
for (i = 0; i < items.GetCount(); i++) for (i = 0; i < items.GetCount(); i++)
@ -264,35 +262,24 @@ void wxListBox::DoSetItems(const wxArrayString& items, void** clientData)
// It seems that if the list is cleared, we must re-ask for // It seems that if the list is cleared, we must re-ask for
// selection policy!! // selection policy!!
Arg args[3]; SetSelectionPolicy();
XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT);
if (m_windowStyle & wxLB_MULTIPLE)
XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT);
else if (m_windowStyle & wxLB_EXTENDED)
XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT);
else
XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT);
XtSetValues (listBox, args, 2);
if (managed) if (managed)
XtManageChild (listBox); XtManageChild (listBox);
GetSize (&width2, &height2); sk.Restore();
// Correct for randomly resized listbox - bad boy, Motif!
if (width1 != width2 || height1 != height2)
SetSize (-1, -1, width1, height1);
m_noItems = items.GetCount(); m_noItems = items.GetCount();
} }
int wxListBox::FindString(const wxString& s) const int wxListBox::FindString(const wxString& s) const
{ {
XmString str = XmStringCreateSimple ((char*) (const char*) s); wxXmString str( s );
int *positions = NULL; int *positions = NULL;
int no_positions = 0; int no_positions = 0;
bool success = XmListGetMatchPos ((Widget) m_mainWidget, str, bool success = XmListGetMatchPos ((Widget) m_mainWidget, str(),
&positions, &no_positions); &positions, &no_positions);
XmStringFree (str);
if (success) if (success)
{ {
int pos = positions[0]; int pos = positions[0];
@ -309,19 +296,14 @@ void wxListBox::Clear()
if (m_noItems <= 0) if (m_noItems <= 0)
return; return;
int width1, height1; wxSizeKeeper sk( this );
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize (&width1, &height1);
XmListDeleteAllItems (listBox); XmListDeleteAllItems (listBox);
m_clientDataList.Clear (); if( HasClientObjectData() )
GetSize (&width2, &height2); m_clientDataDict.DestroyData();
// Correct for randomly resized listbox - bad boy, Motif! sk.Restore();
if (width1 != width2 || height1 != height2)
SetSize (-1, -1, width1, height1);
m_noItems = 0; m_noItems = 0;
} }
@ -385,30 +367,22 @@ bool wxListBox::IsSelected(int N) const
void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData) void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
{ {
DoSetItemClientData(n, (void*) clientData); m_clientDataDict.Set(n, clientData, FALSE);
} }
wxClientData* wxListBox::DoGetItemClientObject(int n) const wxClientData* wxListBox::DoGetItemClientObject(int n) const
{ {
return (wxClientData*) DoGetItemClientData(n); return m_clientDataDict.Get(n);
} }
void *wxListBox::DoGetItemClientData(int N) const void *wxListBox::DoGetItemClientData(int N) const
{ {
wxNode *node = m_clientDataList.Find ((long) N); return (void*)m_clientDataDict.Get(N);
if (node)
return (void *) node->Data ();
else
return NULL;
} }
void wxListBox::DoSetItemClientData(int N, void *Client_data) void wxListBox::DoSetItemClientData(int N, void *Client_data)
{ {
wxNode *node = m_clientDataList.Find ((long) N); m_clientDataDict.Set(N, (wxClientData*)Client_data, FALSE);
if (node)
node->SetData ((wxObject *)Client_data);
else
node = m_clientDataList.Append((long) N, (wxObject*) Client_data);
} }
// Return number of selections and an array of selected integers // Return number of selections and an array of selected integers
@ -482,31 +456,11 @@ wxString wxListBox::GetString(int N) const
return wxEmptyString; return wxEmptyString;
} }
void wxListBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
// Check resulting size is correct
int tempW, tempH;
GetSize (&tempW, &tempH);
/*
if (tempW != width || tempH != height)
{
cout << "wxListBox::SetSize sizes not set correctly.");
}
*/
}
void wxListBox::DoInsertItems(const wxArrayString& items, int pos) void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
{ {
int width1, height1; wxSizeKeeper sk( this );
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize(&width1, &height1);
bool managed = XtIsManaged(listBox); bool managed = XtIsManaged(listBox);
if (managed) if (managed)
@ -535,47 +489,29 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
// It seems that if the list is cleared, we must re-ask for // It seems that if the list is cleared, we must re-ask for
// selection policy!! // selection policy!!
Arg args[3]; SetSelectionPolicy();
XtSetArg(args[0], XmNlistSizePolicy, XmCONSTANT);
if (m_windowStyle & wxLB_MULTIPLE)
XtSetArg(args[1], XmNselectionPolicy, XmMULTIPLE_SELECT);
else if (m_windowStyle & wxLB_EXTENDED)
XtSetArg(args[1], XmNselectionPolicy, XmEXTENDED_SELECT);
else XtSetArg(args[1], XmNselectionPolicy, XmBROWSE_SELECT);
XtSetValues(listBox,args,2) ;
if (managed) if (managed)
XtManageChild(listBox); XtManageChild(listBox);
GetSize(&width2, &height2); sk.Restore();
// Correct for randomly resized listbox - bad boy, Motif!
if (width1 != width2 /*|| height1 != height2*/)
SetSize(-1, -1, width1, height1);
m_noItems += items.GetCount(); m_noItems += items.GetCount();
} }
void wxListBox::SetString(int N, const wxString& s) void wxListBox::SetString(int N, const wxString& s)
{ {
int width1, height1; wxSizeKeeper sk( this );
int width2, height2;
Widget listBox = (Widget) m_mainWidget; Widget listBox = (Widget) m_mainWidget;
GetSize (&width1, &height1);
XmString text = XmStringCreateSimple ((char*) (const char*) s); wxXmString text( s );
// delete the item and add it again. // delete the item and add it again.
// FIXME isn't there a way to change it in place? // FIXME isn't there a way to change it in place?
XmListDeletePos (listBox, N+1); XmListDeletePos (listBox, N+1);
XmListAddItem (listBox, text, N+1); XmListAddItem (listBox, text(), N+1);
XmStringFree(text); sk.Restore();
GetSize (&width2, &height2);
// Correct for randomly resized listbox - bad boy, Motif!
if (width1 != width2 || height1 != height2)
SetSize (-1, -1, width1, height1);
} }
void wxListBox::Command (wxCommandEvent & event) void wxListBox::Command (wxCommandEvent & event)
@ -653,11 +589,6 @@ WXWidget wxListBox::GetTopWidget() const
return (WXWidget) XtParent( (Widget) m_mainWidget ); return (WXWidget) XtParent( (Widget) m_mainWidget );
} }
void wxListBox::ChangeFont(bool keepOriginalSize)
{
wxWindow::ChangeFont(keepOriginalSize);
}
void wxListBox::ChangeBackgroundColour() void wxListBox::ChangeBackgroundColour()
{ {
wxWindow::ChangeBackgroundColour(); wxWindow::ChangeBackgroundColour();