Get list element bounds or frame on scrolling - objective-c

this question is related to Get scroll bar position of an NSScroller on the fly
But now i would like to know how to get current position of list element (green rect) on scrolling.
[self bounds] or [self frame] or [[self enclosingScrollView] ...] won't work for this kind of thing or i'm using it in wrong way.
EDIT
Inside frame of [[NSScrollView enclosingScrollView] contentView]] we see list of NSBox's.
When i click on triangle of NSBox which is list element, instance of that NSBox is stored in -activeTicketRow, i've thought that i can then get NSBox coordinates inside NSScrollView frame when [[NSScrollView enclosingScrollView] contentView]] bounds changes, but after reading "View Programming Guide" i guess not.
I've added observer in NSScrollView
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(updateConvMenu:)
name:NSViewBoundsDidChangeNotification
object:[[self enclosingScrollView] contentView]
];
​
and in -updateConvMenu i get coordinates of [[self enclosingScrollView] contentView], so that's good.
QUESTION
No i would like to store NSBox (which triangle was clicked) from [[self enclosingScrollView] contentView] inside -activeTicketRow so i can then get it's frame coordinates in -updateConvMenu when [[self enclosingScrollView] contentView] bounds changes.
I think now this question is more readable.

Views are in a hierarchy. Ask yourself "position relative to what view/window/screen?" Then use NSView's various -convertRect:... or NSWindow's -convert... methods.

You can get the position of the content view by observing the NSClipViews (the scroll view's contentView) bounds by setting - (void)setPostsBoundsChangedNotifications:YES. Then just translate the coordinates to the view you want, when the notification occurs.
For the translation have a look at the docs Josh did already post View Programming Guide

When scrolling through the list, i'm calculating whether the horizontal center of the selected item in the list does not go after a specific bounds, which overlaps on [NSScrollView frame].

Related

How to make detail view scrollable in master detail app

I have only been working in iOS for a few months but I have been banging my head against the wall for hours and hours for something that seems like it should be pretty straightforward. I used the master detail template in Xcode for an iPad app. I want the detail portion to be scrollable to show content below what is visible in the frame, in either orientation. I have tried numerous combinations of adding scrollviews in the DetailViewController in viewWillAppear, viewDidLoad, loadView...and the best I can come up with is what looks like a scrollable view on the top layer as it does show scroll bars and shows me that I did the scrollView.contentSize correctly as I can pan around, but the actual view with the fields and stuff doesn't move and the fields are unable to be edited. Here is my viewDidAppear as it stands at the moment. As you can see in the NSLogs I am trying to understand the view stack. If I uncomment the line before the logs, I lose the scroll bars altogether.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
scrollView.contentSize = CGSizeMake(2048, 2048);
UIView *parentView = [[UIView alloc] init];
parentView = [[self view] superview];
[[parentView superview] addSubview:scrollView];
//[scrollView addSubview:[self view]];
NSLog(#"%#", [parentView superview]);
NSLog(#"%#", parentView);
NSLog(#"%#", [super view]);
NSLog(#"%#", [self view]);
[scrollView setDelegate:self];
}
I would sincerely appreciate any guidance or tips on how to properly implement UIScrollView for this scenario.
You should add the UIScrollView in IB. Be sure to move all of your existing views and controls to be subviews of the scroll view. And you'll have to link the scroll view to an IBOutlet so you can set the content size in your view controller.
Instead of trying to wrap a uiscrollview around your main view's superview (which you have incorrectly tried to take ownership of (it should be NULL anyways)), why not herd your UI elements into a full-sized subview and wrap the scrollview around that? It would be much much easier.
Your hierarchy would look like this:
Self.view -> ScrollView (with contentSize set) -> UIView containing elements that need to be scrolled -> various UI elements

add UIImageView that covers navigation bar

I think I'm missing something simple here. I need to create a semi-transparent UIImageView that covers the entire screen including the navigation toolbar. How do I do this?
This is what I'm trying to do ...
This is a possible solution:
UIImage *image=[UIImage imageNamed:#"whatever.png"];
UIImageView *overlay=[[UIImageView alloc] initWithImage:image];
overlay.alpha=0.5;
[[[[UIApplication sharedApplication] delegate] window] addSubview:overlay];
EDIT:
It is likely that you would not be setting the alpha value for the overlay, but rather use a transparent PNG with embedded transparence levels. Still, it's a possibility.
When not using ARC, you should [overlay release].
To focus the above answer a little bit, you just need to be clear on how views clip to what parts of the device's screen that they "own".
The key point is that in a navigation view, the Navigation bar itself is not part of your [myController view] - your view controller's view is everything below the bar and anything you do in that view clips to the rectangle below that bar.
The bar is, however, part of your [myAppDelegate window]. The window is essentially the entire screen of your device, while the views are sub portions responsible for managing their specific bounds. So calling [[myAppDelegate window] addSubView:] will display above the bar where [[myViewController view] addSubView:] will not.

location of a button/textfield in a view in cocoa

I'm sorry to ask such a question, but I can't seem to find the answer for it from the wild web.
I want to find out the location of a NSTextField in my custom view, so I can add other textfields under it programmatically.
The reason I don't just add other textfields in IB, is because I need to be able to dynamically create them.
The NSTextField is linked to an IBOutlet.
So the main question is: How do I find out the location of a NSTextField (or NSButton, it doesn't really matter atm) in a custom view (I need to get the coordinates of the item)?
Make an instance Variable with the NSTextField and then call these methods on it to get the four values you want.
NSRect textFieldFrame = [textField frame];
NSPoint textFieldLocation = textFieldFrame.origin;
NSSize textFieldSize = textFieldFrame.size;
NSInteger x = textFieldLocation.x;
NSInteger y = textFieldLocation.y;
NSInteger width = textFieldSize.width;
NSInteger height = textFieldSize.height;
Every kind of view or control (like NSButton, NSTextField, etc.) that inherits from NSView has a -frame method that contains the positioning information.
If your custom view has an IBOutlet connected up to the NSTextField, you could do the following:
NSRect textFieldFrame = [textField frame];
That NSRect contains all of the information for where the text field is positioned.
See the following 2 guides for more information:
View Programming Guide: Understanding a View's Frame and Bounds
Cocoa Drawing Guide: Coordinate Systems and Transforms
Any view has both a bounds and a frame property. bounds is the rectangle that encloses the view in that view's own coordinate space; frame is the enclosing rectangle in the superview's coordinate space. In this case, you want the text view's frame, i.e. its location and size in the view that contains it, so that you can locate other text views in the same superview.

Drawing a Window at Coordinates or Drawing outside of NSStatus Item

I am trying to display something off the side of a NSStatusItem. I think I could do this in two ways:
Display a transparent window with the image I need at the coordinates of the mouse cursor.
OR
Use a custom NSStatusItem and move the controls/images in the view to the left so they are actually off the status item
The problem is, setting the NSRect frame negative (-200,0,100,50) doesn't seem to actually work. So, how can I render things outside of the bounds of the status item (think the CSS overflow property) or render a transparent window at specific coordinates?
The system will prevent you from drawing outside the status item, but using a transparent window will work.
NSRect rect; //The location of the window
NSWindow *win = [[NSWindow alloc] initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[win setOpaque:NO];
[win setBackgroundColor:[NSColor clearColor]];
//or
[win setContentView:myView];
Here, myView is a custom view which will be the background of the window. In order for the window to be transparent, you either have to set the background color to clear or use a custom content view which only draws where it is not transparent. You will probably want to use a floating window so that it stays on top. Be careful not to cover up something important because your window could intercept events intended for something underneath it.

Custom NSView Fill Paints Over Bottom Bar

I have a window which has a custom NSView and has a bottom bar with controls on it, one of which is an NSColorWheel.
For simplicity sake the Window is 332px high, with the custom NSView being 300px high and the bottom bar being 32px high.
The bottom bar is created as part of my awakeFromNib when the app loads the window using the following code:
[[self window] setAutorecalculatesContentBorderThickness:YES forEdge:NSMinYEdge];
[[self window] setContentBorderThickness: 32.0 forEdge: NSMinYEdge];
In my custom NSView class I fill the rectangle with color. Everything works fine when the app loads using the following in my NSView class:
- (void)drawRect:(NSRect)dirtyRect
{
dirtyRect = [self bounds];
NSColor * mNewColor = [NSColor blackColor];
[mNewColor set];
[NSBezierPath fillRect:dirtyRect];
}
However, if I subsequently call a method that changes the color of the custom NSView when a color wheel in the bottom bar is changed, the bottom bar gets overwritten with the color. The following code illustrates this method (this code is in the custom NSView class:
- (void)changeBackgroundColor:(NSNotification *)notification
{
NSLog(#"Changed background color");
NSRect mRect = [self bounds];
NSColor * mNewColor = [theColorWell color];
[mNewColor set];
[NSBezierPath fillRect:mRect];
[self setNeedsDisplay:YES];
}
Resizing the window instantly corrects the problem, but obviously I don't want the user to have to resize the window for an obvious bug!
What I don't understand is why my bounds appear to be mapping to the parent window and not the custom NSView when I call setNeedsDisplay and yet the bound correctly adjust when I resize the window using the mouse (even if just by 1 pixel).
Do I somehow need to account for the bottom bar on the redraw?
Any and all help much appreciated.
You should do all your drawing in the drawRect: method of your custom NSView. Cocoa automatically sets up the graphics context for you when it calls this method - things may not draw correctly if you perform drawing operations in other methods.
Your code in drawRect: could set the colour to the the current background colour as specified by your NSColorWell and fill the dirtyRect rectangle with this.
Then in the other method just call [self setNeedsDisplay:YES]; and then drawRect: will automatically be called to redraw the view.
See here for more information: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CocoaViewsGuide/SubclassingNSView/SubclassingNSView.html#//apple_ref/doc/uid/TP40002978-CH7-SW4 (in particular the Drawing View Content section)