Commit 2609901e authored by David Fuhrmann's avatar David Fuhrmann

macosx: TextfieldPanel: change result handling from delegate to block

The former delegate approach had some drawbacks as one class could
be only delegate for one panel. This commit replaces it with a
completion handler block which moves the result handling code
closer to the actual creation of the dialog.

Also fixes crash for eq panels.
parent b5acac3b
...@@ -366,10 +366,50 @@ ...@@ -366,10 +366,50 @@
[_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")];
[_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")];
[_textfieldPanel setOKButtonLabel: _NS("Save")]; [_textfieldPanel setOKButtonLabel: _NS("Save")];
[_textfieldPanel setTarget:self];
b_genericAudioProfileInInteraction = YES;
[_textfieldPanel runModalForWindow:self.window]; __weak typeof(self) _self = self;
[_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (returnCode != NSOKButton) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
return;
}
NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
// duplicate names are not allowed in the popup control
if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
NSAlert *alert = [[NSAlert alloc] init];
[alert setAlertStyle:NSCriticalAlertStyle];
[alert setMessageText:_NS("Please enter a unique name for the new profile.")];
[alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")];
[alert beginSheetModalForWindow:_self.window
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
return;
}
NSString *newProfile = [_self generateProfileString];
/* add string to user defaults as well as a label */
NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
[workArray addObject:newProfile];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
[defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
[workArray addObject:resultingText];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
/* save defaults */
[defaults synchronize];
[_self resetProfileSelector];
}];
} }
- (void)removeAudioEffectsProfile:(id)sender - (void)removeAudioEffectsProfile:(id)sender
...@@ -601,93 +641,45 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf, ...@@ -601,93 +641,45 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
- (IBAction)addPresetAction:(id)sender - (IBAction)addPresetAction:(id)sender
{ {
/* show panel */ /* show panel */
VLCTextfieldPanelController *panel = [[VLCTextfieldPanelController alloc] init]; [_textfieldPanel setTitle: _NS("Save current selection as new preset")];
[panel setTitle: _NS("Save current selection as new preset")]; [_textfieldPanel setSubTitle: _NS("Enter a name for the new preset:")];
[panel setSubTitle: _NS("Enter a name for the new preset:")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")];
[panel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setOKButtonLabel: _NS("Save")];
[panel setOKButtonLabel: _NS("Save")];
[panel setTarget:self];
b_genericAudioProfileInInteraction = NO;
[panel runModalForWindow:self.window];
}
- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// EQ settings
if (!b_genericAudioProfileInInteraction) {
if (value == NSOKButton && [text length] > 0) {
NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
[workArray addObject:[self generatePresetString]];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
[workArray addObject:text];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
[workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
[workArray addObject:[text decomposedStringWithCanonicalMapping]];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
[defaults synchronize];
/* update VLC internals */
audio_output_t *p_aout = getAout();
if (p_aout) {
var_SetString(p_aout, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
vlc_object_release(p_aout);
}
config_PutPsz(VLCIntf, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
/* update UI */ __weak typeof(self) _self = self;
[self updatePresetSelector]; [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
} NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// profile settings // EQ settings
} else { if (returnCode != NSOKButton || [resultingText length] == 0)
if (value != NSOKButton) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
return; return;
}
NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
// duplicate names are not allowed in the popup control
if ([text length] == 0 || [profileNames containsObject:text]) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
NSAlert *alert = [[NSAlert alloc] init]; NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
[alert setAlertStyle:NSCriticalAlertStyle]; [workArray addObject:[self generatePresetString]];
[alert setMessageText:_NS("Please enter a unique name for the new profile.")]; [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
[alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
[workArray addObject:resultingText];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
[workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
[workArray addObject:[resultingText decomposedStringWithCanonicalMapping]];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
[defaults synchronize];
[alert beginSheetModalForWindow:self.window /* update VLC internals */
modalDelegate:nil audio_output_t *p_aout = getAout();
didEndSelector:nil if (p_aout) {
contextInfo:nil]; var_SetString(p_aout, "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]);
return; vlc_object_release(p_aout);
} }
NSString *newProfile = [self generateProfileString];
/* add string to user defaults as well as a label */ config_PutPsz(VLCIntf, "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
[workArray addObject:newProfile];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
[defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
[workArray addObject:text];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
/* save defaults */ /* update UI */
[defaults synchronize]; [_self updatePresetSelector];
[self resetProfileSelector]; }];
}
} }
- (IBAction)deletePresetAction:(id)sender - (IBAction)deletePresetAction:(id)sender
......
...@@ -166,7 +166,6 @@ ...@@ -166,7 +166,6 @@
- (IBAction)streamAnnouncementToggle:(id)sender; - (IBAction)streamAnnouncementToggle:(id)sender;
- (IBAction)sdpFileLocationSelector:(id)sender; - (IBAction)sdpFileLocationSelector:(id)sender;
- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text;
- (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item; - (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item;
@end @end
...@@ -452,9 +452,32 @@ ...@@ -452,9 +452,32 @@
[_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")];
[_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")];
[_textfieldPanel setOKButtonLabel: _NS("Save")]; [_textfieldPanel setOKButtonLabel: _NS("Save")];
[_textfieldPanel setTarget:self];
[_textfieldPanel runModalForWindow:_customizePanel]; __weak typeof(self) _self = self;
[_textfieldPanel runModalForWindow:_customizePanel completionHandler:^(NSInteger returnCode, NSString *resultingText) {
if (returnCode != NSOKButton || [resultingText length] == 0)
return;
/* prepare current data */
[_self updateCurrentProfile];
/* add profile to arrays */
NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:self.profileNames];
[workArray addObject:resultingText];
[_self setProfileNames:[[NSArray alloc] initWithArray:workArray]];
workArray = [[NSMutableArray alloc] initWithArray:self.profileValueList];
[workArray addObject:[self.currentProfile componentsJoinedByString:@";"]];
[_self setProfileValueList:[[NSArray alloc] initWithArray:workArray]];
/* update UI */
[_self recreateProfilePopup];
[_profilePopup selectItemWithTitle:resultingText];
/* update internals */
[_self switchProfile:self];
[_self storeProfilesOnDisk];
}];
} }
#pragma mark - #pragma mark -
...@@ -605,33 +628,6 @@ ...@@ -605,33 +628,6 @@
return NO; return NO;
} }
- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text
{
if (value == NSOKButton) {
if ([text length] > 0) {
/* prepare current data */
[self updateCurrentProfile];
/* add profile to arrays */
NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:self.profileNames];
[workArray addObject:text];
[self setProfileNames:[[NSArray alloc] initWithArray:workArray]];
workArray = [[NSMutableArray alloc] initWithArray:self.profileValueList];
[workArray addObject:[self.currentProfile componentsJoinedByString:@";"]];
[self setProfileValueList:[[NSArray alloc] initWithArray:workArray]];
/* update UI */
[self recreateProfilePopup];
[_profilePopup selectItemWithTitle:text];
/* update internals */
[self switchProfile:self];
[self storeProfilesOnDisk];
}
}
}
- (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item - (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item
{ {
if (value == NSOKButton) { if (value == NSOKButton) {
......
...@@ -35,19 +35,25 @@ ...@@ -35,19 +35,25 @@
@property (readwrite, assign) NSString *subTitle; @property (readwrite, assign) NSString *subTitle;
@property (readwrite, assign) NSString *OKButtonLabel; @property (readwrite, assign) NSString *OKButtonLabel;
@property (readwrite, assign) NSString *CancelButtonLabel; @property (readwrite, assign) NSString *CancelButtonLabel;
@property (readwrite, assign) id target;
@property (readonly) NSString *enteredText;
- (void)runModalForWindow:(NSWindow *)window; /**
* Completion handler for textfield panel
* \param returnCode Result from panel. Can be NSOKButton or NSCancelButton.
* \param resultingText Resulting text string entered in panel.
*/
typedef void(^TextfieldPanelCompletionBlock)(NSInteger returnCode, NSString *resultingText);
/**
* Shows the panel as a modal dialog with window as its owner.
* \param window Parent window for the dialog.
* \param handler Completion block.
*/
- (void)runModalForWindow:(NSWindow *)window completionHandler:(TextfieldPanelCompletionBlock)handler;
- (IBAction)windowElementAction:(id)sender; - (IBAction)windowElementAction:(id)sender;
@end @end
@protocol VLCTextfieldPanelController <NSObject>
@optional
- (void)panel:(VLCTextfieldPanelController *)view returnValue:(NSUInteger)value text:(NSString *)text;
@end
@interface VLCPopupPanelController : NSWindowController @interface VLCPopupPanelController : NSWindowController
......
...@@ -23,6 +23,13 @@ ...@@ -23,6 +23,13 @@
#import "SharedDialogs.h" #import "SharedDialogs.h"
@interface VLCTextfieldPanelController()
{
TextfieldPanelCompletionBlock _completionBlock;
}
@end
@implementation VLCTextfieldPanelController @implementation VLCTextfieldPanelController
...@@ -38,17 +45,11 @@ ...@@ -38,17 +45,11 @@
[self.window orderOut:sender]; [self.window orderOut:sender];
[NSApp endSheet: self.window]; [NSApp endSheet: self.window];
if (self.target) { if (_completionBlock)
if ([self.target respondsToSelector:@selector(panel:returnValue:text:)]) { _completionBlock(sender == _okButton ? NSOKButton : NSCancelButton, [_textField stringValue]);
if (sender == _cancelButton)
[self.target panel:self returnValue:NSCancelButton text:NULL];
else
[self.target panel:self returnValue:NSOKButton text:self.enteredText];
}
}
} }
- (void)runModalForWindow:(NSWindow *)window - (void)runModalForWindow:(NSWindow *)window completionHandler:(TextfieldPanelCompletionBlock)handler;
{ {
[self window]; [self window];
...@@ -58,12 +59,9 @@ ...@@ -58,12 +59,9 @@
[_okButton setTitle:self.OKButtonLabel]; [_okButton setTitle:self.OKButtonLabel];
[_textField setStringValue:@""]; [_textField setStringValue:@""];
[NSApp beginSheet:self.window modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil]; _completionBlock = [handler copy];
}
- (NSString *)enteredText [NSApp beginSheet:self.window modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil];
{
return [_textField stringValue];
} }
@end @end
......
...@@ -673,57 +673,55 @@ ...@@ -673,57 +673,55 @@
[_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")];
[_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")];
[_textfieldPanel setOKButtonLabel: _NS("Save")]; [_textfieldPanel setOKButtonLabel: _NS("Save")];
[_textfieldPanel setTarget:self];
[_textfieldPanel runModalForWindow:self.window]; __weak typeof(self) _self = self;
} [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (value != NSOKButton) { if (returnCode != NSOKButton) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
return; return;
} }
NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"]; NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"];
// duplicate names are not allowed in the popup control // duplicate names are not allowed in the popup control
if ([text length] == 0 || [profileNames containsObject:text]) { if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) {
[_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
NSAlert *alert = [[NSAlert alloc] init]; NSAlert *alert = [[NSAlert alloc] init];
[alert setAlertStyle:NSCriticalAlertStyle]; [alert setAlertStyle:NSCriticalAlertStyle];
[alert setMessageText:_NS("Please enter a unique name for the new profile.")]; [alert setMessageText:_NS("Please enter a unique name for the new profile.")];
[alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")];
[alert beginSheetModalForWindow:self.window [alert beginSheetModalForWindow:_self.window
modalDelegate:nil modalDelegate:nil
didEndSelector:nil didEndSelector:nil
contextInfo:nil]; contextInfo:nil];
return; return;
} }
/* fetch all the current settings in a uniform string */ /* fetch all the current settings in a uniform string */
NSString *newProfile = [self generateProfileString]; NSString *newProfile = [_self generateProfileString];
/* add string to user defaults as well as a label */ /* add string to user defaults as well as a label */
NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]]; NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]];
[workArray addObject:newProfile]; [workArray addObject:newProfile];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"]; [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"];
[defaults setInteger:[workArray count] - 1 forKey:@"VideoEffectSelectedProfile"]; [defaults setInteger:[workArray count] - 1 forKey:@"VideoEffectSelectedProfile"];
workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfileNames"]]; workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfileNames"]];
[workArray addObject:text]; [workArray addObject:resultingText];
[defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"]; [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"];
/* save defaults */ /* save defaults */
[defaults synchronize]; [defaults synchronize];
/* refresh UI */ /* refresh UI */
[self resetProfileSelector]; [_self resetProfileSelector];
}];
} }
- (void)removeProfile:(id)sender - (void)removeProfile:(id)sender
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment