X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/da175b2ce4dc35cc4c0baa8bbdc16bf4de6c7684..2ada746fb47bf68c9f2dab6399a6cd5510320984:/src/motif/choice.cpp diff --git a/src/motif/choice.cpp b/src/motif/choice.cpp index 528d0607f0..0405533162 100644 --- a/src/motif/choice.cpp +++ b/src/motif/choice.cpp @@ -1,42 +1,63 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: choice.cpp +// Name: src/motif/choice.cpp // Purpose: wxChoice // Author: Julian Smart // Modified by: // Created: 17/09/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "choice.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#if wxUSE_CHOICE + +#ifdef __VMS +#define XtDisplay XTDISPLAY +#define XtParent XTPARENT #endif -// For compilers that support precompilation, includes "wx.h". #include "wx/choice.h" -#include "wx/utils.h" +#ifndef WX_PRECOMP + #include "wx/utils.h" + #include "wx/arrstr.h" +#endif + +#ifdef __VMS__ +#pragma message disable nosimpint +#endif #include #include #include #include +#ifdef __VMS__ +#pragma message enable nosimpint +#endif #include "wx/motif/private.h" -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl) -#endif +#define WIDTH_OVERHEAD 48 +#define WIDTH_OVERHEAD_SUBTRACT 40 +#define HEIGHT_OVERHEAD 15 + +IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControlWithItems) void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer ptr); wxChoice::wxChoice() +{ + Init(); +} + +void wxChoice::Init() { m_noStrings = 0; m_buttonWidget = (WXWidget) 0; m_menuWidget = (WXWidget) 0; - m_widgetList = (WXWidget*) 0; m_formWidget = (WXWidget) 0; } @@ -48,69 +69,54 @@ bool wxChoice::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { - SetName(name); - SetValidator(validator); - m_noStrings = 0; // Starts off with none, incremented in Append - m_windowStyle = style; - m_buttonWidget = (WXWidget) 0; - m_menuWidget = (WXWidget) 0; - m_widgetList = (WXWidget*) 0; - m_formWidget = (WXWidget) 0; - - if (parent) parent->AddChild(this); - - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; - - m_backgroundColour = parent->GetBackgroundColour(); - m_foregroundColour = parent->GetForegroundColour(); - m_font = parent->GetFont(); - + if ( !CreateControl(parent, id, pos, size, style, validator, name) ) + return false; + PreCreation(); + Widget parentWidget = (Widget) parent->GetClientWidget(); - - m_formWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name, + + m_formWidget = (WXWidget) XtVaCreateManagedWidget(name.c_str(), xmRowColumnWidgetClass, parentWidget, XmNmarginHeight, 0, XmNmarginWidth, 0, XmNpacking, XmPACK_TIGHT, XmNorientation, XmHORIZONTAL, + XmNresizeWidth, False, + XmNresizeHeight, False, NULL); - + XtVaSetValues ((Widget) m_formWidget, XmNspacing, 0, NULL); - + /* * Create the popup menu */ - m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, "choiceMenu", NULL, 0); - - // int i; + m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, + wxMOTIF_STR("choiceMenu"), + NULL, 0); + if (n > 0) { int i; for (i = 0; i < n; i++) Append (choices[i]); } - + /* * Create button */ Arg args[10]; Cardinal argcnt = 0; - - XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget); - argcnt++; - XtSetArg (args[argcnt], XmNmarginWidth, 0); - argcnt++; - XtSetArg (args[argcnt], XmNmarginHeight, 0); - argcnt++; - XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT); - argcnt++; - m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, "choiceButton", args, argcnt); - + + XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget); ++argcnt; + XtSetArg (args[argcnt], XmNmarginWidth, 0); ++argcnt; + XtSetArg (args[argcnt], XmNmarginHeight, 0); ++argcnt; + XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT); ++argcnt; + m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, + wxMOTIF_STR("choiceButton"), + args, argcnt); + m_mainWidget = m_buttonWidget; - + XtManageChild ((Widget) m_buttonWidget); // New code from Roland Haenel (roland_haenel@ac.cybercity.de) @@ -119,22 +125,38 @@ bool wxChoice::Create(wxWindow *parent, wxWindowID id, // that I have found the code responsible for this behaviour. #if XmVersion >= 1002 #if XmVersion < 2000 - Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget); // JACS, 24/1/99: this seems to cause a malloc crash later on, e.g. // in controls sample. - // XtUnmanageChild (optionLabel); + // + // Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget); + // XtUnmanageChild (optionLabel); #endif #endif + wxSize bestSize = GetBestSize(); + if( size.x > 0 ) bestSize.x = size.x; + if( size.y > 0 ) bestSize.y = size.y; + XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL); - - ChangeFont(FALSE); - - AttachWidget (parent, m_buttonWidget, m_formWidget, pos.x, pos.y, size.x, size.y); - - ChangeBackgroundColour(); - - return TRUE; + + PostCreation(); + AttachWidget (parent, m_buttonWidget, m_formWidget, + pos.x, pos.y, bestSize.x, bestSize.y); + + return true; +} + +bool wxChoice::Create(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) +{ + wxCArrayString chs(choices); + return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(), + style, validator, name); } wxChoice::~wxChoice() @@ -144,182 +166,187 @@ wxChoice::~wxChoice() // be deleted implicitly by deleting the parent form // anyway. // XtDestroyWidget (menuWidget); - if (m_widgetList) - delete[] m_widgetList; - + if (GetMainWidget()) { DetachWidget(GetMainWidget()); // Removes event handlers DetachWidget(m_formWidget); - + XtDestroyWidget((Widget) m_formWidget); m_formWidget = (WXWidget) 0; - + // Presumably the other widgets have been deleted now, via the form m_mainWidget = (WXWidget) 0; m_buttonWidget = (WXWidget) 0; } } -void wxChoice::Append(const wxString& item) +static inline wxChar* MYcopystring(const wxChar* s) +{ + wxChar* copy = new wxChar[wxStrlen(s) + 1]; + return wxStrcpy(copy, s); +} + +// TODO auto-sorting is not supported by the code +int wxChoice::DoInsertItems(const wxArrayStringsAdapter& items, + unsigned int pos, + void **clientData, wxClientDataType type) { - wxStripMenuCodes ((char *)(const char *)item, wxBuffer); - Widget w = XtVaCreateManagedWidget (wxBuffer, -#if USE_GADGETS - xmPushButtonGadgetClass, (Widget) m_menuWidget, +#ifndef XmNpositionIndex + wxCHECK_MSG( pos == GetCount(), -1, wxT("insert not implemented")); +#endif + + const unsigned int numItems = items.GetCount(); + AllocClientData(numItems); + for( unsigned int i = 0; i < numItems; ++i, ++pos ) + { + Widget w = XtVaCreateManagedWidget (GetLabelText(items[i]), +#if wxUSE_GADGETS + xmPushButtonGadgetClass, (Widget) m_menuWidget, #else - xmPushButtonWidgetClass, (Widget) m_menuWidget, + xmPushButtonWidgetClass, (Widget) m_menuWidget, #endif - NULL); - - DoChangeBackgroundColour((WXWidget) w, m_backgroundColour); - - if (m_font.Ok()) - XtVaSetValues (w, - XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_formWidget)), - NULL); - - WXWidget *new_widgetList = new WXWidget[m_noStrings + 1]; - int i; - if (m_widgetList) - for (i = 0; i < m_noStrings; i++) - new_widgetList[i] = m_widgetList[i]; - - new_widgetList[m_noStrings] = (WXWidget) w; - - if (m_widgetList) - delete[] m_widgetList; - m_widgetList = new_widgetList; - - char mnem = wxFindMnemonic ((char*) (const char*) item); +#ifdef XmNpositionIndex + XmNpositionIndex, pos, +#endif + NULL); + + wxDoChangeBackgroundColour((WXWidget) w, m_backgroundColour); + + if( m_font.Ok() ) + wxDoChangeFont( w, m_font ); + + m_widgetArray.Insert(w, pos); + + char mnem = wxFindMnemonic (items[i]); if (mnem != 0) XtVaSetValues (w, XmNmnemonic, mnem, NULL); - - XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this); - + + XtAddCallback (w, XmNactivateCallback, + (XtCallbackProc) wxChoiceCallback, + (XtPointer) this); + if (m_noStrings == 0 && m_buttonWidget) { XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL); Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); - XmString text = XmStringCreateSimple ((char*) (const char*) item); + wxXmString text( items[i] ); XtVaSetValues (label, - XmNlabelString, text, + XmNlabelString, text(), NULL); - XmStringFree (text); } - wxNode *node = m_stringList.Add (item); - XtVaSetValues (w, XmNuserData, node->Data (), NULL); - + // need to ditch wxStringList for wxArrayString + m_stringList.Insert(pos, MYcopystring(items[i])); m_noStrings ++; + + InsertNewItemClientData(pos, clientData, i, type); + } + + return pos - 1; } -void wxChoice::Delete(int WXUNUSED(n)) +void wxChoice::DoDeleteOneItem(unsigned int n) { - wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" ); - - // What should we do -- remove the callback for this button widget, - // delete the m_stringList entry, delete the button widget, construct a new widget list - // (see Append) - - // TODO - m_noStrings --; + Widget w = (Widget)m_widgetArray[n]; + XtRemoveCallback(w, XmNactivateCallback, (XtCallbackProc)wxChoiceCallback, + (XtPointer)this); + m_stringList.Erase(m_stringList.Item(n)); + m_widgetArray.RemoveAt(size_t(n)); + wxChoiceBase::DoDeleteOneItem(n); + + XtDestroyWidget(w); + m_noStrings--; } -void wxChoice::Clear() +void wxChoice::DoClear() { m_stringList.Clear (); - int i; + unsigned int i; for (i = 0; i < m_noStrings; i++) { - XtUnmanageChild ((Widget) m_widgetList[i]); - XtDestroyWidget ((Widget) m_widgetList[i]); + XtRemoveCallback((Widget) m_widgetArray[i], + XmNactivateCallback, (XtCallbackProc)wxChoiceCallback, + (XtPointer)this); + XtUnmanageChild ((Widget) m_widgetArray[i]); + XtDestroyWidget ((Widget) m_widgetArray[i]); } - if (m_noStrings) - delete[] m_widgetList; - m_widgetList = (WXWidget*) NULL; + m_widgetArray.Clear(); if (m_buttonWidget) - XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL); + XtVaSetValues ((Widget) m_buttonWidget, + XmNmenuHistory, (Widget) NULL, + NULL); + + wxChoiceBase::DoClear(); + m_noStrings = 0; } int wxChoice::GetSelection() const { XmString text; - char *s; Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); XtVaGetValues (label, XmNlabelString, &text, NULL); - - if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s)) + wxXmString freeMe(text); + wxString s = wxXmStringToString( text ); + + if (!s.empty()) { int i = 0; - for (wxNode * node = m_stringList.First (); node; node = node->Next ()) + for (wxStringList::compatibility_iterator node = m_stringList.GetFirst (); + node; node = node->GetNext ()) { - char *s1 = (char *) node->Data (); - if (s1 == s || strcmp (s1, s) == 0) + if (wxStrcmp(node->GetData(), s.c_str()) == 0) { - XmStringFree(text) ; - XtFree (s); return i; } else i++; } // for() - - XmStringFree(text) ; - XtFree (s); + return -1; } - XmStringFree(text) ; return -1; } void wxChoice::SetSelection(int n) { - m_inSetValue = TRUE; - - wxNode *node = m_stringList.Nth (n); + m_inSetValue = true; + + wxStringList::compatibility_iterator node = m_stringList.Item(n); if (node) { +#if 0 Dimension selectionWidth, selectionHeight; - - char *s = (char *) node->Data (); - XmString text = XmStringCreateSimple (s); - XtVaGetValues ((Widget) m_widgetList[n], XmNwidth, &selectionWidth, XmNheight, &selectionHeight, NULL); +#endif + wxXmString text( node->GetData() ); +// MBN: this seems silly, at best, and causes wxChoices to be clipped: +// will remove "soon" +#if 0 + XtVaGetValues ((Widget) m_widgetArray[n], + XmNwidth, &selectionWidth, + XmNheight, &selectionHeight, + NULL); +#endif Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); XtVaSetValues (label, - XmNlabelString, text, + XmNlabelString, text(), NULL); - XmStringFree (text); +#if 0 XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, selectionWidth, XmNheight, selectionHeight, - XmNmenuHistory, (Widget) m_widgetList[n], NULL); - } - m_inSetValue = FALSE; -} - -int wxChoice::FindString(const wxString& s) const -{ - int i = 0; - for (wxNode * node = m_stringList.First (); node; node = node->Next ()) - { - char *s1 = (char *) node->Data (); - if (s == s1) - { - return i; - } - else - i++; + XmNmenuHistory, (Widget) m_widgetArray[n], NULL); +#endif } - return -1; + m_inSetValue = false; } -wxString wxChoice::GetString(int n) const +wxString wxChoice::GetString(unsigned int n) const { - wxNode *node = m_stringList.Nth (n); + wxStringList::compatibility_iterator node = m_stringList.Item(n); if (node) - return wxString((char *) node->Data ()); + return node->GetData(); else return wxEmptyString; } @@ -327,10 +354,10 @@ wxString wxChoice::GetString(int n) const void wxChoice::SetColumns(int n) { if (n<1) n = 1 ; - - short numColumns = n ; + + short numColumns = (short)n ; Arg args[3]; - + XtSetArg(args[0], XmNnumColumns, numColumns); XtSetArg(args[1], XmNpacking, XmPACK_COLUMN); XtSetValues((Widget) m_menuWidget,args,2) ; @@ -339,7 +366,7 @@ void wxChoice::SetColumns(int n) int wxChoice::GetColumns(void) const { short numColumns ; - + XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ; return numColumns ; } @@ -353,55 +380,41 @@ void wxChoice::DoSetSize(int x, int y, int width, int height, int sizeFlags) { XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL); bool managed = XtIsManaged((Widget) m_formWidget); - + if (managed) XtUnmanageChild ((Widget) m_formWidget); - - int actualWidth = width, actualHeight = height; - + + int actualWidth = width - WIDTH_OVERHEAD_SUBTRACT, + actualHeight = height - HEIGHT_OVERHEAD; + if (width > -1) { - int i; + unsigned int i; for (i = 0; i < m_noStrings; i++) - XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL); + XtVaSetValues ((Widget) m_widgetArray[i], + XmNwidth, actualWidth, + NULL); XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth, NULL); } if (height > -1) { - int i; +#if 0 + unsigned int i; for (i = 0; i < m_noStrings; i++) - XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL); + XtVaSetValues ((Widget) m_widgetArray[i], + XmNheight, actualHeight, + NULL); +#endif XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight, NULL); } - + if (managed) XtManageChild ((Widget) m_formWidget); XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL); - - wxControl::DoSetSize (x, y, width, height, sizeFlags); -} - -wxString wxChoice::GetStringSelection () const -{ - int sel = GetSelection (); - if (sel > -1) - return wxString(this->GetString (sel)); - else - return wxEmptyString; -} -bool wxChoice::SetStringSelection (const wxString& s) -{ - int sel = FindString (s); - if (sel > -1) - { - SetSelection (sel); - return TRUE; - } - else - return FALSE; + wxControl::DoSetSize (x, y, width, height, sizeFlags); } void wxChoice::Command(wxCommandEvent & event) @@ -417,15 +430,18 @@ void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr)) { if (item->InSetValue()) return; - - char *s = NULL; - XtVaGetValues (w, XmNuserData, &s, NULL); - if (s) + + int n = item->GetWidgets().Index(w); + if (n != wxNOT_FOUND) { - wxCommandEvent event (wxEVT_COMMAND_CHOICE_SELECTED, item->GetId()); + wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, item->GetId()); event.SetEventObject(item); - event.m_commandInt = item->FindString (s); - // event.m_commandString = s; + event.SetInt(n); + event.SetString( item->GetStrings().Item(n)->GetData() ); + if ( item->HasClientObjectData() ) + event.SetClientObject( item->GetClientObject(n) ); + else if ( item->HasClientUntypedData() ) + event.SetClientData( item->GetClientData(n) ); item->ProcessCommand (event); } } @@ -436,44 +452,89 @@ void wxChoice::ChangeFont(bool keepOriginalSize) // Note that this causes the widget to be resized back // to its original size! We therefore have to set the size // back again. TODO: a better way in Motif? - if (m_font.Ok()) + if (m_mainWidget && m_font.Ok()) { + Display* dpy = XtDisplay((Widget) m_mainWidget); int width, height, width1, height1; GetSize(& width, & height); - - XmFontList fontList = (XmFontList) m_font.GetFontList(1.0, XtDisplay((Widget) m_mainWidget)); - XtVaSetValues ((Widget) m_mainWidget, XmNfontList, fontList, NULL); - XtVaSetValues ((Widget) m_buttonWidget, XmNfontList, fontList, NULL); - - /* TODO: why does this cause a crash in XtWidgetToApplicationContext? - int i; - for (i = 0; i < m_noStrings; i++) - XtVaSetValues ((Widget) m_widgetList[i], XmNfontList, fontList, NULL); - */ + + WXString fontTag = wxFont::GetFontTag(); + + XtVaSetValues ((Widget) m_formWidget, + fontTag, m_font.GetFontTypeC(dpy), + NULL); + XtVaSetValues ((Widget) m_buttonWidget, + fontTag, m_font.GetFontTypeC(dpy), + NULL); + + for( unsigned int i = 0; i < m_noStrings; ++i ) + XtVaSetValues( (Widget)m_widgetArray[i], + fontTag, m_font.GetFontTypeC(dpy), + NULL ); + GetSize(& width1, & height1); if (keepOriginalSize && (width != width1 || height != height1)) { - SetSize(-1, -1, width, height); + SetSize(wxDefaultCoord, wxDefaultCoord, width, height); } } } void wxChoice::ChangeBackgroundColour() { - DoChangeBackgroundColour(m_formWidget, m_backgroundColour); - DoChangeBackgroundColour(m_buttonWidget, m_backgroundColour); - DoChangeBackgroundColour(m_menuWidget, m_backgroundColour); - int i; + wxDoChangeBackgroundColour(m_formWidget, m_backgroundColour); + wxDoChangeBackgroundColour(m_buttonWidget, m_backgroundColour); + wxDoChangeBackgroundColour(m_menuWidget, m_backgroundColour); + unsigned int i; for (i = 0; i < m_noStrings; i++) - DoChangeBackgroundColour(m_widgetList[i], m_backgroundColour); + wxDoChangeBackgroundColour(m_widgetArray[i], m_backgroundColour); } void wxChoice::ChangeForegroundColour() { - DoChangeForegroundColour(m_formWidget, m_foregroundColour); - DoChangeForegroundColour(m_buttonWidget, m_foregroundColour); - DoChangeForegroundColour(m_menuWidget, m_foregroundColour); - int i; + wxDoChangeForegroundColour(m_formWidget, m_foregroundColour); + wxDoChangeForegroundColour(m_buttonWidget, m_foregroundColour); + wxDoChangeForegroundColour(m_menuWidget, m_foregroundColour); + unsigned int i; for (i = 0; i < m_noStrings; i++) - DoChangeForegroundColour(m_widgetList[i], m_foregroundColour); + wxDoChangeForegroundColour(m_widgetArray[i], m_foregroundColour); +} + +unsigned int wxChoice::GetCount() const +{ + return m_noStrings; } + +void wxChoice::SetString(unsigned int WXUNUSED(n), const wxString& WXUNUSED(s)) +{ + wxFAIL_MSG( wxT("wxChoice::SetString not implemented") ); +} + +wxSize wxChoice::GetItemsSize() const +{ + int x, y, mx = 0, my = 0; + + // get my + GetTextExtent( "|", &x, &my ); + + wxStringList::compatibility_iterator curr = m_stringList.GetFirst(); + while( curr ) + { + GetTextExtent( curr->GetData(), &x, &y ); + mx = wxMax( mx, x ); + my = wxMax( my, y ); + curr = curr->GetNext(); + } + + return wxSize( mx, my ); +} + +wxSize wxChoice::DoGetBestSize() const +{ + wxSize items = GetItemsSize(); + // FIXME arbitrary constants + return wxSize( ( items.x ? items.x + WIDTH_OVERHEAD : 120 ), + items.y + HEIGHT_OVERHEAD ); +} + +#endif // wxUSE_CHOICE