Reputation: 21880
I'm experienced with iOS development, but I'm trying my hand at MacOS development tonight.
Is there a way to constrain my window to certain proportions? I don't mind if the user wants to make the window larger or smaller, I just want to make sure that it always has the same height/width ratio.
EDIT:
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
float ratio = self.window.frame.size.height / self.window.frame.size.width;
NSSize newSize = NSMakeSize(frameSize.width, frameSize.height / ratio);
return newSize;
}
Upvotes: 0
Views: 864
Reputation: 26558
The easiest way to constrain a window to a given ratio is to use either -[NSWindow setAspectRatio:]
or -[NSWindow setContentAspectRatio:]
.
Upvotes: 4
Reputation: 22569
I stumbled upon this question, and it was exactly my needs .. However, the answer wasn't clear enough for a 1 sec realization ^^;
Here is the code you would want:
If you have the ratio of the whole window (including the title bar)
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
frameSize.width = frameSize.height * 1.333;
return frameSize;
}
If you (like me) want to constrain the window size without considering the title bar.
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
NSSize contentSize = [sender contentRectForFrameRect:NSMakeRect(0, 0, frameSize.width, frameSize.height)].size;
contentSize.height = contentSize.width * 0.75;
return [sender frameRectForContentRect:NSMakeRect(0, 0, contentSize.width, contentSize.height)].size;
}
Replace the width/height ratio you want instead of 1.333, and the height/width ration instead of 0.75
My Case:
I needed the iPad ratio 1024/768 = 1.333 ...
Upvotes: 3
Reputation: 1050
Here's a solution for a window that is always 100px wider than it is tall. You can imagine easily replacing the logic so that it maintains a constant ratio instead.
The key thing in this implementation is that it takes notice of which edge is resizing the window, for systems like Lion that allow resizing from any window edge. In this example the resize edge stays clamped as the master value.
I don't know if there's a standard method to determine which edge is resizing the window. But it can be easily detected using the logic demonstrated here.
// Track resizing based on how it starts
typedef enum MyResizeType {
resizeNone,
resizeWidth,
resizeHeight,
resizeBoth
} MyResizeType;
static MyResizeType resizeType = resizeNone;
- (void)windowDidEndLiveResize:(NSNotification *)notification {
resizeType = resizeNone;
}
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
// Width should always be 100 bigger than the Height...
CGSize currSize = sender.frame.size;
BOOL wdiff = currSize.width != frameSize.width,
hdiff = currSize.height != frameSize.height;
if (resizeType == resizeNone) {
if (wdiff || hdiff) {
if (wdiff && hdiff) {
resizeType = resizeBoth;
}
else if (hdiff) {
resizeType = resizeHeight;
}
else {
resizeType = resizeWidth;
}
}
}
CGFloat newHeight;
switch (resizeType) {
case resizeWidth:
newHeight = frameSize.width - 100.0;
if (hdiff) resizeType = resizeBoth;
break;
case resizeHeight:
newHeight = frameSize.height;
if (wdiff) resizeType = resizeBoth;
break;
case resizeBoth:
newHeight = MAX(frameSize.height, frameSize.width - 100.0);
break;
default:
newHeight = frameSize.height; // this will never happen, but best to set it
break;
}
NSSize newSize = { newHeight + 100.0, newHeight };
return newSize;
}
Upvotes: 1
Reputation: 13622
Assign a delegate to your window if you haven't already, and implement the -windowWillResize:toSize: delegate method. The requested size is passed as the second argument; you can modify that and return a different size that matches the ratio you want.
Upvotes: 2