Files
wxWidgets/src/cocoa/radiobox.mm
Vadim Zeitlin ce7fe42e84 Provide shorter synonyms for wxEVT_XXX constants.
Use the same short names as are used by the event table macros for the event
type constants themselves. This makes them much more comfortable to use, e.g.
Bind(wxEVT_BUTTON) compared to Bind(wxEVT_COMMAND_BUTTON_CLICKED).

The old long names are still kept for backwards compatibility and shouldn't be
removed as it doesn't really cost anything to continue providing them, but all
new event types should only use the short versions.

Closes #10661.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73850 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-04-25 10:11:03 +00:00

278 lines
8.5 KiB
Plaintext

/////////////////////////////////////////////////////////////////////////////
// Name: src/cocoa/radiobox.mm
// Purpose: wxRadioBox
// Author: David Elliott
// Modified by:
// Created: 2003/02/15
// RCS-ID: $Id$
// Copyright: (c) 2003 David Elliott
// (c) 2007 Software 2000 Ltd.
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_RADIOBOX
#include "wx/radiobox.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/arrstr.h"
#endif //WX_PRECOMP
#include "wx/cocoa/string.h"
#include "wx/cocoa/autorelease.h"
#import <Foundation/NSArray.h>
#include "wx/cocoa/objc/NSView.h"
#import <AppKit/NSButton.h>
#import <AppKit/NSBox.h>
#import <AppKit/NSMatrix.h>
IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
BEGIN_EVENT_TABLE(wxRadioBox, wxControl)
END_EVENT_TABLE()
void wxRadioBox::AssociateNSBox(WX_NSBox cocoaObjcClass)
{
NSMatrix *radioBox = [(WX_NSBox)cocoaObjcClass contentView];
// Associate the NSMatrix (the NSBox's contentView) with the wxCocoaNSControl MI base class.
AssociateNSControl(radioBox);
// Set the target/action.. we don't really need to unset these
[radioBox setTarget:wxCocoaNSControl::sm_cocoaTarget];
[radioBox setAction:@selector(wxNSControlAction:)];
}
void wxRadioBox::DisassociateNSBox(WX_NSBox cocoaObjcClass)
{
DisassociateNSControl([(WX_NSBox)cocoaObjcClass contentView]);
}
WX_IMPLEMENT_COCOA_OWNER(wxRadioBox,NSBox,NSView,NSView)
bool wxRadioBox::Create(wxWindow *parent, wxWindowID winid,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
int majorDim,
long style, const wxValidator& validator,
const wxString& name)
{
wxCArrayString chs(choices);
return Create(parent, winid, title, pos, size, chs.GetCount(),
chs.GetStrings(), majorDim, style, validator, name);
}
bool wxRadioBox::Create(wxWindow *parent, wxWindowID winid,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
int n, const wxString choices[],
int majorDim,
long style, const wxValidator& validator,
const wxString& name)
{
// We autorelease heavily so we want our own pool
wxAutoNSAutoreleasePool pool;
if(!CreateControl(parent,winid,pos,size,style,validator,name))
return false;
majorDim = majorDim == 0 ? n : majorDim;
// TODO: Don't forget to call SetMajorDim
// We can't yet as we can't implement GetCount() until after
// we make the NSMatrix.
int minorDim = (n + majorDim - 1) / majorDim;
// Create a prototype cell for use with the NSMatrix build
NSCell *currCell = [[NSButtonCell alloc] initTextCell:@""];
[(NSButtonCell*)currCell setButtonType:NSRadioButton];
// Build up an array of all cells plus any extra empty cells
NSMutableArray *allCells = [NSMutableArray arrayWithCapacity:n];
for(int i=0; i<n; ++i)
{
CocoaSetLabelForObject(choices[i], currCell);
[allCells addObject: currCell];
[currCell release];
// NOTE: We can still safely message currCell as the array has retained it.
currCell = [currCell copy];
}
[currCell release];
// NOTE: Although an image cell with no image is documented to return NSZeroSize from
// the cellSize method, the documentation is WRONG. It will actually return a huge size
// (thousands) which makes every cell in the matrix that big. Not good.
// Be safe and initialize a text cell with an empty string. That always works.
currCell = [[NSCell alloc] initTextCell:@""];
[currCell setEnabled:NO]; // Don't allow user to select this cell
for(int i=n; i < majorDim * minorDim; ++i)
{
[allCells addObject: currCell];
// NOTE: Use the same instance.. this should work and save some heap allocations.
#if 0
[currCell release];
currCell = [currCell copy];
#endif
}
[currCell release];
currCell = NULL;
// Although the documentation on addColumnWithCells:/addRowWithCells: explicitly
// states that it will determine the initial dimension upon the first call if
// the initial size is 0x0 it LIES. It will fail an assertion in the code
// if you use the simpler initWithFrame: initializer.
// Therefore, we specify the major dimension and leave the minor dimension as 0
// so that we can add the rows/columns without failing the assertion.
NSMatrix* radioBox = [[NSMatrix alloc]
initWithFrame:NSZeroRect
mode:NSRadioModeMatrix
cellClass:nil
numberOfRows:style&wxRA_SPECIFY_COLS?0:majorDim
numberOfColumns:style&wxRA_SPECIFY_COLS?majorDim:0
];
SEL addMajorWithCellsSelector;
// If column count is the major dimension then we add by row
if( style & wxRA_SPECIFY_COLS )
addMajorWithCellsSelector = @selector(addRowWithCells:);
// If row count is the major dimension then we add by column
else
addMajorWithCellsSelector = @selector(addColumnWithCells:);
for(int i=0; i<minorDim; ++i)
{
[radioBox
performSelector:addMajorWithCellsSelector
withObject:[allCells subarrayWithRange:NSMakeRange(i*majorDim, majorDim)]];
}
NSBox *theBox = [[NSBox alloc] initWithFrame:MakeDefaultNSRect(size)];
// Replace the box's content view with the NSMatrix we just created
// IMPORTANT: This must be done before calling SetNSBox.
[theBox setContentView:radioBox];
[radioBox release]; // The NSBox retains it for us.
SetNSBox(theBox);
[theBox release];
CocoaSetLabelForObject(title, GetNSBox());
// [GetNSBox() setBorderType:NSLineBorder]; // why??
SetMajorDim(majorDim, style);
// Set the selection to the first item if we have any items.
// This is for parity with other wx ports which do the same thing.
if(n > 0)
SetSelection(0);
if(m_parent)
m_parent->CocoaAddChild(this);
// Do the sizer dance
[GetNSBox() sizeToFit];
SetInitialFrameRect(pos, size);
return true;
}
wxRadioBox::~wxRadioBox()
{
DisassociateNSBox(GetNSBox());
}
WX_NSMatrix wxRadioBox::GetNSMatrix() const
{
return (NSMatrix*)[(NSBox*)m_cocoaNSView contentView];
}
// selection
void wxRadioBox::SetSelection(int n)
{
int r = GetRowForIndex(n);
int c = GetColumnForIndex(n);
[GetNSMatrix() selectCellAtRow:r column:c];
}
int wxRadioBox::GetSelection() const
{
NSMatrix *radioBox = GetNSMatrix();
NSInteger r = [radioBox selectedRow];
NSInteger c = [radioBox selectedColumn];
if(m_windowStyle & wxRA_SPECIFY_COLS)
return r * GetMajorDim() + c;
else
return c * GetMajorDim() + r;
}
// string access
unsigned int wxRadioBox::GetCount() const
{
NSMatrix *radioBox = GetNSMatrix();
NSInteger rowCount, columnCount;
[radioBox getNumberOfRows:&rowCount columns:&columnCount];
// FIXME: This is wrong if padding cells were made
return rowCount * columnCount;
}
wxString wxRadioBox::GetString(unsigned int n) const
{
int r = GetRowForIndex(n);
int c = GetColumnForIndex(n);
// FIXME: Cocoa stores the mnemonic-stripped title.
return wxStringWithNSString([[GetNSMatrix() cellAtRow:r column:c] title]);
}
void wxRadioBox::SetString(unsigned int n, const wxString& label)
{
int r = GetRowForIndex(n);
int c = GetColumnForIndex(n);
CocoaSetLabelForObject(label, [GetNSMatrix() cellAtRow:r column:c]);
}
// change the individual radio button state
bool wxRadioBox::Enable(unsigned int n, bool enable)
{
int r = GetRowForIndex(n);
int c = GetColumnForIndex(n);
NSCell *cell = [GetNSMatrix() cellAtRow:r column:c];
if(cell == nil)
return false;
bool wasEnabled = [cell isEnabled];
[cell setEnabled:enable];
return (wasEnabled && !enable) || (!wasEnabled && enable);
}
bool wxRadioBox::Show(unsigned int n, bool show)
{
// TODO
// NOTE: Cocoa has no visible state for cells so we'd need to replace the
// cell with a dummy one to hide it or alternatively subclass NSButtonCell
// and add the behaviour.
return false;
}
wxSize wxRadioBox::DoGetBestSize() const
{
// The NSBox responds to sizeToFit by sending sizeToFit to its contentView
// which is the NSMatrix and does the right thing.
return wxControl::DoGetBestSize();
}
void wxRadioBox::CocoaTarget_action(void)
{
wxCommandEvent event(wxEVT_RADIOBOX, GetId());
InitCommandEvent(event);
event.SetInt(GetSelection()); // i.e. SetSelection.
Command(event);
}
#endif