Files
wxWidgets/src/motif/choice.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

515 lines
14 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/motif/choice.cpp
// Purpose: wxChoice
// Author: Julian Smart
// Modified by:
// Created: 17/09/98
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_CHOICE
#include "wx/choice.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/arrstr.h"
#endif
#ifdef __VMS__
#pragma message disable nosimpint
#endif
#include <Xm/Xm.h>
#include <Xm/PushBG.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#ifdef __VMS__
#pragma message enable nosimpint
#endif
#include "wx/motif/private.h"
#define WIDTH_OVERHEAD 48
#define WIDTH_OVERHEAD_SUBTRACT 40
#define HEIGHT_OVERHEAD 15
void wxChoiceCallback (Widget w, XtPointer clientData,
XtPointer ptr);
wxChoice::wxChoice()
{
Init();
}
void wxChoice::Init()
{
m_buttonWidget = (WXWidget) 0;
m_menuWidget = (WXWidget) 0;
m_formWidget = (WXWidget) 0;
}
bool wxChoice::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos,
const wxSize& size,
int n, const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !CreateControl(parent, id, pos, size, style, validator, name) )
return false;
PreCreation();
Widget parentWidget = (Widget) parent->GetClientWidget();
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,
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,
wxMOTIF_STR("choiceButton"),
args, argcnt);
m_mainWidget = m_buttonWidget;
XtManageChild ((Widget) m_buttonWidget);
// New code from Roland Haenel (roland_haenel@ac.cybercity.de)
// Some time ago, I reported a problem with wxChoice-items under
// Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems
// that I have found the code responsible for this behaviour.
#if XmVersion >= 1002
#if XmVersion < 2000
// JACS, 24/1/99: this seems to cause a malloc crash later on, e.g.
// in controls sample.
//
// 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);
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()
{
// For some reason destroying the menuWidget
// can cause crashes on some machines. It will
// be deleted implicitly by deleting the parent form
// anyway.
// XtDestroyWidget (menuWidget);
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;
}
}
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)
{
#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,
#endif
#ifdef XmNpositionIndex
XmNpositionIndex, pos,
#endif
NULL);
wxDoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
if( m_font.IsOk() )
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);
if (m_stringArray.GetCount() == 0 && m_buttonWidget)
{
XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
wxXmString text( items[i] );
XtVaSetValues (label,
XmNlabelString, text(),
NULL);
}
m_stringArray.Insert(items[i], pos);
InsertNewItemClientData(pos, clientData, i, type);
}
return pos - 1;
}
void wxChoice::DoDeleteOneItem(unsigned int n)
{
Widget w = (Widget)m_widgetArray[n];
XtRemoveCallback(w, XmNactivateCallback, (XtCallbackProc)wxChoiceCallback,
(XtPointer)this);
m_stringArray.RemoveAt(size_t(n));
m_widgetArray.RemoveAt(size_t(n));
wxChoiceBase::DoDeleteOneItem(n);
XtDestroyWidget(w);
}
void wxChoice::DoClear()
{
m_stringArray.Clear();
unsigned int i;
for (i = 0; i < m_stringArray.GetCount(); i++)
{
XtRemoveCallback((Widget) m_widgetArray[i],
XmNactivateCallback, (XtCallbackProc)wxChoiceCallback,
(XtPointer)this);
XtUnmanageChild ((Widget) m_widgetArray[i]);
XtDestroyWidget ((Widget) m_widgetArray[i]);
}
m_widgetArray.Clear();
if (m_buttonWidget)
XtVaSetValues ((Widget) m_buttonWidget,
XmNmenuHistory, (Widget) NULL,
NULL);
wxChoiceBase::DoClear();
}
int wxChoice::GetSelection() const
{
XmString text;
Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
XtVaGetValues (label,
XmNlabelString, &text,
NULL);
wxXmString freeMe(text);
wxString s = wxXmStringToString( text );
if (!s.empty())
{
for (size_t i=0; i<m_stringArray.GetCount(); i++)
if (m_stringArray[i] == s)
return i;
return wxNOT_FOUND;
}
return wxNOT_FOUND;
}
void wxChoice::SetSelection(int n)
{
m_inSetValue = true;
#if 0
Dimension selectionWidth, selectionHeight;
#endif
wxXmString text( m_stringArray[n] );
// 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(),
NULL);
#if 0
XtVaSetValues ((Widget) m_buttonWidget,
XmNwidth, selectionWidth, XmNheight, selectionHeight,
XmNmenuHistory, (Widget) m_widgetArray[n], NULL);
#endif
m_inSetValue = false;
}
wxString wxChoice::GetString(unsigned int n) const
{
return m_stringArray[n];
}
void wxChoice::SetColumns(int n)
{
if (n<1) n = 1 ;
short numColumns = (short)n ;
Arg args[3];
XtSetArg(args[0], XmNnumColumns, numColumns);
XtSetArg(args[1], XmNpacking, XmPACK_COLUMN);
XtSetValues((Widget) m_menuWidget,args,2) ;
}
int wxChoice::GetColumns(void) const
{
short numColumns ;
XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ;
return numColumns ;
}
void wxChoice::SetFocus()
{
XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT);
}
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 - WIDTH_OVERHEAD_SUBTRACT,
actualHeight = height - HEIGHT_OVERHEAD;
if (width > -1)
{
unsigned int i;
for (i = 0; i < m_stringArray.GetCount(); i++)
XtVaSetValues ((Widget) m_widgetArray[i],
XmNwidth, actualWidth,
NULL);
XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth,
NULL);
}
if (height > -1)
{
#if 0
unsigned int i;
for (i = 0; i < m_stringArray.GetCount(); i++)
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);
}
void wxChoice::Command(wxCommandEvent & event)
{
SetSelection (event.GetInt());
ProcessCommand (event);
}
void wxChoiceCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
{
wxChoice *item = (wxChoice *) clientData;
if (item)
{
if (item->InSetValue())
return;
int n = item->GetWidgets().Index(w);
if (n != wxNOT_FOUND)
{
wxCommandEvent event(wxEVT_CHOICE, item->GetId());
event.SetEventObject(item);
event.SetInt(n);
event.SetString( item->GetStrings().Item(n) );
if ( item->HasClientObjectData() )
event.SetClientObject( item->GetClientObject(n) );
else if ( item->HasClientUntypedData() )
event.SetClientData( item->GetClientData(n) );
item->ProcessCommand (event);
}
}
}
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_mainWidget && m_font.IsOk())
{
Display* dpy = XtDisplay((Widget) m_mainWidget);
int width, height, width1, height1;
GetSize(& width, & height);
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_stringArray.GetCount(); ++i )
XtVaSetValues( (Widget)m_widgetArray[i],
fontTag, m_font.GetFontTypeC(dpy),
NULL );
GetSize(& width1, & height1);
if (keepOriginalSize && (width != width1 || height != height1))
{
SetSize(wxDefaultCoord, wxDefaultCoord, width, height);
}
}
}
void wxChoice::ChangeBackgroundColour()
{
wxDoChangeBackgroundColour(m_formWidget, m_backgroundColour);
wxDoChangeBackgroundColour(m_buttonWidget, m_backgroundColour);
wxDoChangeBackgroundColour(m_menuWidget, m_backgroundColour);
unsigned int i;
for (i = 0; i < m_stringArray.GetCount(); i++)
wxDoChangeBackgroundColour(m_widgetArray[i], m_backgroundColour);
}
void wxChoice::ChangeForegroundColour()
{
wxDoChangeForegroundColour(m_formWidget, m_foregroundColour);
wxDoChangeForegroundColour(m_buttonWidget, m_foregroundColour);
wxDoChangeForegroundColour(m_menuWidget, m_foregroundColour);
unsigned int i;
for (i = 0; i < m_stringArray.GetCount(); i++)
wxDoChangeForegroundColour(m_widgetArray[i], m_foregroundColour);
}
unsigned int wxChoice::GetCount() const
{
return m_stringArray.GetCount();
}
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 );
for (size_t i=0; i<m_stringArray.GetCount(); i++)
{
GetTextExtent( m_stringArray[i], &x, &y );
mx = wxMax( mx, x );
my = wxMax( my, y );
}
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