Resizing views dynamically osx - macos

I have two views and a button at the top, i want one be hidden/shown when the button is pressed and for the other views to resize to the edge of the window.
The button on the top left links to an IBAction that hides the lower view with this mainscroll.hidden = true. I can not figure out how to resize/move the other views so the textbox/button are at the bottom of the window, ie no visible gray space at the bottom. I would like to do this programmatically.
http://imgur.com/a/FGH7i

Here is how you can adjust the topView programmatically:
float aHeight = [mainscroll frame].size.height;
NSRect aRect = [topView frame];
aRect.size.height += aHeight;
aRect.origin.y -= aHeight;
[topView setFrame:aRect];

Related

NSButton corner radius and NSPopover

I'm using an NSPopover and I'm putting a NSViewController inside to be displayed as a custom view from a NSStatusItem. Most of the view controller displays correctly except for the NSButton that have a corner radius on them. There is some extra white leaking out where the rounded corners are being applied. Displaying the buttons within the actual app, this problem doesn't occur.
I feel it has to do something with the NSPopover appearance which I have set to "NSAppearanceNameAqua".
The NSButtons are within a NSView which are displayed in a NSTableView and are set to this style.
self.createdButton.wantsLayer = true
self.createdButton.layer?.backgroundColor = Utils.blackColor().CGColor
self.createdButton.layer?.masksToBounds = true
self.createdButton.layer?.cornerRadius = 5
The top image is when the actual app is open.
The bottom image is when the view controller is being shown within a NSPopover.
create corner radius using bezier path i.e.
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:view.bounds xRadius:3 yRadius:3];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = view.bounds;
maskLayer.path = path.toCGPath;
self.containerView.layer.mask = maskLayer;

How to make a text Field on user's click

I want my application to make a text box where ever a user clicks. So how do i synthesize a text box on demand. Kind of like in OneNote.
So how do i synthesize a text box on demand.
You create a text view or text field, and then you add it to your view wherever you want it. Assuming that you have the click event in event and you know the width and height of the text view you want to create, do this:
NSPoint *p = [myContainerView convertPoint:[event locationInWindow] fromView:nil];
NSRect frame = NSMakeRect(p.x, p.y, width, height);
NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
[myContainerView addSubview:tv];
For detecting mouse event
NSUInteger pmb = [NSEvent pressedMouseButtons];
/*
A return value of 1 << 0 corresponds to the left mouse button, 1 << 1 corresponds to the right mouse button, 1<< n, n >=2 correspond to other mouse buttons.
*/
NSPoint mouseLocation = [NSEvent mouseLocation];
/*
Reports the current mouse position in screen coordinates.
*/

NSScrollView scroll bars are of the wrong length

I have a Cocoa window, whose content view contains an NSScrollView that, in turns, contains a fixed-size NSView.
Upon launching the program, the scroll bars displayed initially are too small, as if the content size was much larger than it actually is:
When I start playing with, e.g., the vertical scroll bar, and bring it back to the original position at the top, it gets resized to its expected size (which corresponds to the ratio of scroll view and content view sizes):
(Notice the horizontal bar, which still has incorrect size. If I then play with it, and bring it back to its leftmost position, it gets resized to the correct size.)
I also encountered the same problem, I have searched everywhere but it seems no one else experiences this problem. Fortunately I found a hack which solves the problem.
What I did notice was that when the window is resized or maximized the scrollbars resize to the expected size (autoresizing has to be enabled). This is because when the window resizes so does the scrollview and the length of the scroll bars gets recalculated and is calculated correctly. Possibly due to some bug the scroll bar lengths are not calculated correctly on initialization. Anyway to fix the problem, in your application delegate create an outlet to your window. Override the "applicationDidFinishLaunching" method and inside it call the method "frame" on the window outlet, which returns the current NSRect of the window. Using the returned value add one to the size.width and size.height. The call the method setFrame with display set to YES. This will resize the window and force the size of the scrollbars to be recalculated.
Here is the code for applicationDidFinishLaunching Below
(void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Get the current rect
NSRect windowRect = [_window frame];`
// add one to the width and height to resize window
windowRect.size.width += 1;
windowRect.size.height += 1;
// resize window with display:YES to redraw window subviews
[_window setFrame:windowSize display:YES];
}
I encountered this issue when modifying an NSTextView textContainer size to toggle line wrapping. Resizing the enclosing view does cause the correct scroll view height to be used, however its a brutal solution.
NSScrollView supports -reflectScrolledClipView. Calling this directly in my case had no effect except when delayed on the runloop:
[textScrollView performSelector:#selector(reflectScrolledClipView:) withObject:textScrollView.contentView afterDelay:0];
The scroller position is correct but there is a scroller redraw. So it looks as if part of the view geometry is calculated when drawing. A better solution is therefore:
NSDisableScreenUpdates();
[textScrollView display];
[textScrollView reflectScrolledClipView:textScrollView.contentView];
[textScrollView display];
NSEnableScreenUpdates();
Building on the answer from jstuxx above, if you don't want the window to visibly resize, try:
NSRect windowRect = [[[self view] window] frame];
windowRect.size.width += 1;
windowRect.size.height += 1;
[[[self view] window] setFrame:windowRect display:YES];
windowRect.size.width -= 1;
windowRect.size.height -= 1;
[[[self view] window] setFrame:windowRect display:YES];
I had to put this code after where I was programmatically adding the scroll view to my interface.

Animating simultaneously window and view frame in Cocoa

I need to animate a view frame size adding 100px of height, but I need the window grow up simultaneously with the view.
I tried with this code :
//resize Window
NSRect winsize = [window frame];
winsize.size.height += 100;
[self.window setFrame:winsize display:YES animate:YES];
//resize View
NSRect viewsize = [myview frame];
viewsize.size.height += 100;
[[myview animator] setFrame:viewsize];
It works but I obtain an ugly effect, Window and View had some delay in resize. Thus, I get the Window frame resizing before than the View frame.
How can I modify my code to make them resizing simultaneously ?
add:
I found this answer but it tdoesn't seems to work for me:
Simultaneously modify window frame and view frame
I found a good solution: using autoresizingMask to mantain min and max Y Margin and allow height resize.
[myview setAutoresizingMask:NSViewHeightSizable];

Reposition an NSBox in the top pane of a horizontal NSSplitView

I the issue I'm having has to do with the coordinate system in Cocoa but I really don't know. This is all happening in the top pane of a horizontal NSSplitView.
Very simply, I'm trying to position one NSBox right below a second one (I load custom views into the boxes - that all works fine). The top box's top-left corner is at the top-left corner of the pane and never changes. If the height of the top NSBox shrinks I want the top of the second NSBox to slide right up below it. Conversely, if the top NSBox's height increases I want the bottom NSBox to slide down.
This code gets called twice. Box is correct (first time top box, second time bottom box) and v is correct (this is the view I'm loading into the box - this works fine and it is what is causing the height to change in the top box).
NSSize destBoxSize = [[box contentView] frame].size; //the size of the box in the view to load the view into
NSSize newViewSize = [v frame].size; // the size of the view to be loaded
float deltaWidth = [horizSplitView frame].size.width - destBoxSize.width;
float deltaHeight = newViewSize.height - destBoxSize.height;
NSRect boxFrame = [box frame];
boxFrame.size.height += deltaHeight;
boxFrame.size.width += deltaWidth;
boxFrame.origin.y -= deltaHeight;
NSLog(#"vc=%# boxFrame x%f y%f h%f w%f", nibName, boxFrame.origin.x, boxFrame.origin.y, boxFrame.size.height, boxFrame.size.width);
// Clear the box for resizing
[box setContentView:nil];
[box setContentView:v];
[box setFrame:boxFrame];
What you want to do is not so hard, but it will need some subclassing. First of all, you need to subclass NSSplitView and either and override either -(void)init or -(void)awakeFromNib to add this line:
[self setAutoresizesSubviews:YES]; //
Then you need to subclass the two boxes and set their auto resizing masks, either in -(void)init or in - (void)viewWillMoveToSuperview:(NSView *)newSuperView.
For the first box you'll probably want:
[newInstance setAutoresizingMask:NSViewNotSizable];
For the second bbox you'll probably want:
[newInstance setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
See also NSView. It takes a bit of experimenting to get the right combination, but then it works quite nicely.

Resources