Files
baRSS/baRSS/Preferences/ModalSheet.m
2022-10-01 15:39:20 +02:00

90 lines
3.5 KiB
Objective-C

#import "ModalSheet.h"
#import "UserPrefs.h"
#import "NSView+Ext.h"
@interface ModalSheet()
@property (assign) BOOL respondToShouldClose;
@end
@implementation ModalSheet
/// Designated initializer. 'Done' and 'Cancel' buttons will be added automatically.
- (instancetype)initWithView:(NSView*)content {
static NSInteger const minWidth = 320;
static NSInteger const maxWidth = 1200;
static CGFloat const contentOffsetY = PAD_WIN + HEIGHT_BUTTON + PAD_L;
NSInteger w = UserPrefsInt(Pref_modalSheetWidth);
if (w < minWidth) w = minWidth;
else if (w > maxWidth) w = maxWidth;
CGFloat h = NSHeight(content.frame);
[content setFrameSize: NSMakeSize(w, h)];
// after content size, increase to window size
w += 2 * (NSInteger)PAD_WIN;
h += PAD_WIN + contentOffsetY; // the second PAD_WIN is already in contentOffsetY
NSWindowStyleMask style = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskFullSizeContentView;
self = [super initWithContentRect:NSMakeRect(0, 0, w, h) styleMask:style backing:NSBackingStoreBuffered defer:NO];
[content placeIn:self.contentView x:PAD_WIN y:contentOffsetY];
// Restrict resizing to width only
self.minSize = NSMakeSize(minWidth + 2 * PAD_WIN, h);
self.maxSize = NSMakeSize(maxWidth + 2 * PAD_WIN, h);
// Add default interaction buttons
NSButton *btnDone = [self createButton:NSLocalizedString(@"Done", nil) atX:PAD_WIN];
NSButton *btnCancel = [self createButton:NSLocalizedString(@"Cancel", nil) atX:w - NSMinX(btnDone.frame) + PAD_M];
btnDone.tag = 42; // mark 'Done' button
btnDone.keyEquivalent = @"\r"; // Enter / Return
btnCancel.keyEquivalent = [NSString stringWithFormat:@"%c", 0x1b]; // ESC
return self;
}
/// Helper method to create bottom-right aligned button.
- (NSButton*)createButton:(NSString*)text atX:(CGFloat)x {
return [[[NSView button:text] action:@selector(didTapButton:) target:self] placeIn:self.contentView xRight:x y:PAD_WIN];
}
/// Manually disable 'Done' button if a task is still running.
- (void)setDoneEnabled:(BOOL)accept {
((NSButton*)[self.contentView viewWithTag:42]).enabled = accept;
}
/// Sets bool for future usage
- (void)setDelegate:(id<NSWindowDelegate>)delegate {
[super setDelegate:delegate];
self.respondToShouldClose = [delegate respondsToSelector:@selector(windowShouldClose:)];
}
/**
Called after user has clicked the 'Done' (Return) or 'Cancel' (Esc) button.
In the later case set @c .didTapCancel @c = @c YES
*/
- (void)didTapButton:(NSButton*)sender {
BOOL successful = (sender.tag == 42); // 'Done' button
_didTapCancel = !successful;
if (self.respondToShouldClose && ![self.delegate windowShouldClose:self]) {
return;
}
// Save modal view width for next time
NSInteger width = (NSInteger)(NSWidth(self.contentView.frame) - 2 * PAD_WIN);
if (UserPrefsInt(Pref_modalSheetWidth) != width)
UserPrefsSetInt(Pref_modalSheetWidth, width);
// Remove subviews to avoid _NSKeyboardFocusClipView issues
[self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.sheetParent endSheet:self returnCode:(successful ? NSModalResponseOK : NSModalResponseCancel)];
}
/// Resize modal window by @c dy. Makes room for additional content. Use negative values to shrink window.
- (void)extendContentViewBy:(CGFloat)dy {
self.minSize = NSMakeSize(self.minSize.width, self.minSize.height + dy);
self.maxSize = NSMakeSize(self.maxSize.width, self.maxSize.height + dy);
NSRect r = self.frame;
r.size.height += dy;
[self setFrame:r display:YES animate:YES];
}
@end