mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-07 17:38:02 +00:00
New: Support modern Cocoa behavior regarding radio buttons groups. (#2941)
This commit is contained in:
1 parent
c1543d4a2f
commit
ef779c346e
2 files changed
+137
No files matched your search
@@ -67,6 +67,18 @@ CPRadioImageOffset = 4.0;
|
||||
[[button1 radioGroup] selectedRadio] returns the currently selected
|
||||
option.
|
||||
|
||||
UPDATE 09/2020 : Implementation of modern Cocoa behavior :
|
||||
|
||||
As in Cocoa, radio buttons grouping is now automatic.
|
||||
|
||||
To be associated in a common group (and so being mutually exclusive),
|
||||
radio buttons must combine 2 criteria :
|
||||
|
||||
- same superview (enclosing view)
|
||||
- same action
|
||||
|
||||
TODO: This first implementation uses "as is" CPRadioGroup. This could
|
||||
be simplified (no more need for radio group action, for example)
|
||||
*/
|
||||
@implementation CPRadio : CPButton
|
||||
{
|
||||
@@ -160,6 +172,63 @@ CPRadioImageOffset = 4.0;
|
||||
[CPApp sendAction:[_radioGroup action] to:[_radioGroup target] from:_radioGroup];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToSuperview
|
||||
{
|
||||
[self _setRadioGroup];
|
||||
[super viewDidMoveToSuperview];
|
||||
}
|
||||
|
||||
- (void)setAction:(SEL)anAction
|
||||
{
|
||||
if (anAction === _action)
|
||||
return;
|
||||
|
||||
[super setAction:anAction];
|
||||
[self _setRadioGroup];
|
||||
}
|
||||
|
||||
#pragma mark Private methods
|
||||
|
||||
- (void)_setRadioGroup
|
||||
{
|
||||
// Implementation of modern Cocoa behavior : automatic radio group
|
||||
|
||||
// If no action is set or no superview, no grouping can be done.
|
||||
if (![self action] || ![self superview])
|
||||
{
|
||||
// If I'm in a group (size > 1), remove me.
|
||||
if ([[self radioGroup] size] > 1)
|
||||
[self setRadioGroup:[CPRadioGroup new]];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Search in superview subviews for other radio buttons having the same action.
|
||||
// Take the one with the radio group having the greatest number of members.
|
||||
|
||||
var radioGroup;
|
||||
|
||||
for (var i = 0, superviewSubviews = [[self superview] subviews], count = [superviewSubviews count], aSubview, myAction = [self action], radioGroupSize = -1; (i < count); i++)
|
||||
{
|
||||
aSubview = superviewSubviews[i];
|
||||
|
||||
if ([aSubview isKindOfClass:CPRadio] && (aSubview !== self) && ([aSubview action] === myAction) && ([[aSubview radioGroup] size] > radioGroupSize))
|
||||
{
|
||||
radioGroup = [aSubview radioGroup];
|
||||
radioGroupSize = [radioGroup size];
|
||||
}
|
||||
}
|
||||
|
||||
if (radioGroup)
|
||||
[self setRadioGroup:radioGroup];
|
||||
else
|
||||
// No other radio buttons to group with found.
|
||||
// It may be because this radio button was in a radio group and its action was changed.
|
||||
// If this is the case, we must reisolate it in a new radio group.
|
||||
if ([_radioGroup size] > 1)
|
||||
[self setRadioGroup:[CPRadioGroup new]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
@@ -320,6 +389,11 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
return _radios;
|
||||
}
|
||||
|
||||
- (int)size
|
||||
{
|
||||
return [_radios count];
|
||||
}
|
||||
|
||||
- (void)setEnabled:(BOOL)enabled
|
||||
{
|
||||
[_radios makeObjectsPerformSelector:@selector(setEnabled:) withObject:enabled];
|
||||
|
||||
@@ -190,6 +190,69 @@
|
||||
[self assertTrue:wasClicked message:@"a user click on a radio button should fire the group action"];
|
||||
}
|
||||
|
||||
- (void)testAutomaticRadioGroup
|
||||
{
|
||||
var radioButton1 = [CPRadio radioWithTitle:@"Radio 1"],
|
||||
radioButton2 = [CPRadio radioWithTitle:@"Radio 2"],
|
||||
radioButton3 = [CPRadio radioWithTitle:@"Radio 3"],
|
||||
simpleView1 = [[CPView alloc] initWithFrame:CGRectMakeZero()],
|
||||
simpleView2 = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
// Initially, buttons are isolated
|
||||
[self assertFalse:([radioButton1 radioGroup] === [radioButton2 radioGroup]) message:@"initially, buttons should be isolated"];
|
||||
|
||||
[simpleView1 addSubview:radioButton1];
|
||||
[simpleView1 addSubview:radioButton2];
|
||||
|
||||
// As no actions are defined, buttons are still isolated
|
||||
[self assertFalse:([radioButton1 radioGroup] === [radioButton2 radioGroup]) message:@"no actions defined, buttons should be isolated"];
|
||||
|
||||
[radioButton1 setAction:@selector(dummyAction1:)];
|
||||
[radioButton2 setAction:@selector(dummyAction2:)];
|
||||
|
||||
// As different actions are defined, buttons are still isolatdd
|
||||
[self assertFalse:([radioButton1 radioGroup] === [radioButton2 radioGroup]) message:@"different actions defined, buttons should be isolated"];
|
||||
|
||||
[radioButton2 setAction:@selector(dummyAction1:)];
|
||||
|
||||
// As the same action is defined, buttons must be grouped
|
||||
[self assertTrue:([radioButton1 radioGroup] === [radioButton2 radioGroup]) message:@"same action defined, buttons should be grouped"];
|
||||
|
||||
[radioButton3 setAction:@selector(dummyAction1:)];
|
||||
|
||||
// As radioButton3 is not inserted in a view, it's isolated
|
||||
[self assertTrue:([[radioButton3 radioGroup] size] === 1) message:@"not in a view, button should be isolated"];
|
||||
|
||||
[simpleView2 addSubview:radioButton3];
|
||||
|
||||
// As radioButton3 is in another view, it's isolated from radioButton1 & 2
|
||||
[self assertTrue:([[radioButton3 radioGroup] size] === 1) message:@"alone in a view, button should be isolated"];
|
||||
|
||||
[simpleView1 addSubview:radioButton3];
|
||||
|
||||
// As all 3 buttons are in the same view, with the same action, they are grouped
|
||||
[self assertTrue:([[radioButton3 radioGroup] size] === 3) message:@"after moving to the same view, buttons should be grouped"];
|
||||
|
||||
[radioButton3 setAction:@selector(dummyAction2:)];
|
||||
|
||||
// As the action of button 3 is now different, it's isolated
|
||||
[self assertTrue:([[radioButton3 radioGroup] size] === 1) message:@"after changing the action, button 3 should be isolated"];
|
||||
|
||||
// And buttons 1 & 2 are still grouped
|
||||
[self assertTrue:([radioButton1 radioGroup] === [radioButton2 radioGroup]) message:@"buttons 1 & 2 should remain grouped"];
|
||||
[self assertTrue:([[radioButton1 radioGroup] size] === 2) message:@"radio group should contain only buttons 1 & 2"];
|
||||
}
|
||||
|
||||
- (IBAction)dummyAction1:(id)sender
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (IBAction)dummyAction2:(id)sender
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)testTypeMasks
|
||||
{
|
||||
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
Reference in new issue
Block a user