addSubview not showing up in NSView Objective C Cocoa - objective-c

When I addSubview: nothing shows up. I set text and color to see it. Also if I manually add the view to the custom view in the UI bulder in xcode it shows up just fine with the text and color.
.m file
- (void)displayString:(NSString *)title {
NSRect frame = NSMakeRect(10, 10, 200, 17);
NSTextfield *newfield = [[NSTextField alloc] initWithFrame:frame];
[newfield setBezeled:NO];
[newfield setDrawsBackground:NO];
[newfield setEditable:NO];
[newfield setSelectable:NO];
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
if([test.subviews containsObject:newfield]){
NSLog(#"view there"); // i get this message
}
if([newfield isHidden]){
NSLog(#"view hidden"); //i dont get this message
}
NSLog(#"view set");
}
test is a NSView (Custom view is what xcode calls it) that I have properly linked in.
So when I create the text field and add it to the NSView manually and then run that same code by adding text and color all works fine, this issue arrises when I try programmatically setting the view. Also I made sure it wasn't my creating of the view, as I have tried creating the view in the builder and not placing it in the NSView and then trying addSubview: but that also does not work. Let me know if you need more code.
DEVELOPMENT:
If the nsview (custom view) has an element already in it (manually added and can be anything) and I add the text field it works (I get both views in the nsview)? The subview is tested for and there, just cant see it.

You have to call initWithFrame: instead of just init
- (void)displayString:(NSString *)title {
NSRect frame = NSMakeRect(10, 10, 200, 200);
NSTextField *newfield = [[NSTextField alloc] initWithFrame:frame];
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
NSLog(#"view set");
}

What type of view is test? Also you need to do a:
newfield.frame = CGRectMake(x,y,width,height)
in order to specify the look of the view

Turns out I set the view too early. I was under the impression that whatever you do to the view after its been set will be reflected on the view, but that seemed to be the issue. After altering the view to be exactly they way I want then set the view of the NSStatuditem.
so I get
[newfield setStringValue:title];
[newfield setTextColor:[NSColor blueColor]];
[test addSubview:newfield];
[statusItem setView:test];//this is the key, setting it after he changes.

Related

NSTextField bug with FocusRingType: None

There seems to be a bug in NSTextField. When the application launches it all draws correctly. But as soon as I click in the textField the view gets all messed up. To more specific, whenever I type drawRect: gets called but with a smaller rect causing all the problems.
When I select the text it draws correctly again. The only solution is to set the FocusRingType to visible (example: NSFocusRingTypeDefault). But I would like to have it without the ring. Is this possible?
Here is the code I am using:
-(id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if(self)
{
// Add a label
NSTextField *textField = [[NSTextField alloc] initWithFrame:CGRectMake(0, 0, frameRect.size.width, frameRect.size.height)];
[[textField cell] setPlaceholderString:#"URL or search term..."];
[textField setTextColor:[NSColor greyColor]];
[textField setBackgroundColor:[NSColor clearColor]];
[textField setFont:[NSFont fontWithName:#"Open Sans" size:20]];
[textField setDrawsBackground:FALSE];
[textField setBordered:FALSE];
[textField setFocusRingType:NSFocusRingTypeNone];
[self addSubview:textField];
}
return self;
}
-(void)drawRect:(NSRect)dirtyRect
{
NSInteger borderWdith = 2;
// Create the path to the button
NSBezierPath *aPath = [NSBezierPath bezierPathWithRoundedRect:CGRectMake(borderWdith, borderWdith,
dirtyRect.size.width-(borderWdith*2),
dirtyRect.size.height-(borderWdith*2))
xRadius:3 yRadius:3];
// Fill the button with white
[[NSColor whiteColor] set];
[aPath fill];
}
Tricks like setting editable to TRUE/FALSE in drawRect did not work. Also setting to different focusRingTypes in the method failed.
Okay, so I managed to sort of fix this drawing problem. In the view init method I set a global CGRect variable which was set to the initial frame.
Each time -(void)drawRect:(CGRect)dirtyRect was called, I overwrote dirtyRect with the global variable.
Hope this helps anyone. I guess this isn't the best solution, but works :)

Subview of TableView removed - Tableview not visible

For the first time working with CorePlot (after a couple of hours trying to set it up :P )
on my view, i have a tableview. when a certain IBAction is called i want to show another view (a graph) instead of the tableview.
my approach was to add a subview with the same size to the tableview. it works fine to display the graph, but when i remove the graphs view from [table subviews] the tableview does not reappear.
note:
expenseTable: my tableView
hasSubView: (BOOL) that indicates if a graph is shown right now or not
code
-(IBAction)displayDayBalanceGraph:(id)sender{
if (hasSubView) {
[[expenseTable subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
NSLog(#"%#",expenseTable.subviews);
}
else{
[self initializeMonthArray];
CPTGraphHostingView *host = [self buildGraphView];
[expenseTable addSubview:host];
CPTXYGraph *graph = [[CPTXYGraph alloc ]initWithFrame:host.frame];
host.hostedGraph = graph;
CPTScatterPlot *plot = [[CPTScatterPlot alloc]init ];
plot.dataSource = self;
[graph addPlot:plot];
[expenseTable reloadData];
hasSubView = !hasSubView;
}
}
-(CPTGraphHostingView *)buildGraphView{
CPTGraphHostingView *view = [[CPTGraphHostingView alloc]initWithFrame:CGRectMake(0, 0, 312, 260)];
[view setBackgroundColor:[self grayColor]];
return view;
}
1st Screenshot: TableView displayed
2nd Screenshot: GraphView displayed
sidenote: this is a sampleplot =)
3rd Screenshot: GraphView dismissed
has anyone an idea what i missed? (or messed ;) )
It's not generally a good idea to add views as subviews of UITableView.
Instead, you could either remove the table view and replace it with the Core Plot view:
[tableView removeFromSuperview];
[containerView addSubview:corePlotView];
Make sure you have a reference to the table view somewhere or it will be released.

UIView size is not as expected to be

I can't figure out why that view takes the entire screen.
In AppDelegate file
...
self.viewController = [[[ViewController alloc]init]autorelease];
[self.window setRootViewController:self.viewController];
self.window.backgroundColor = [UIColor whiteColor];
..
In ViewController.m
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(30, 30, 30, 30)];
[view setBackgroundColor:[UIColor greenColor]];
self.view = view;
When I run the app the screen is entirely green instead of having just a square in green.
What is wrong here ?
The erroneous line is here:
self.view = view;
When you set a view of a UIViewController that is the root controller, it is guaranteed to fill the screen. Instead, add it as a subview:
[self.view addSubview:view];
And you should be fine.
The view controller automatically manages the size of its root view (self.view), so even if you initialize it with a smaller size it will later get resized to fill the screen. This resizing conveniently also happens when the interface orientation changes (see the answer this question).
As suggested by Richard's answer, you can add your green view as a subview to the controller's root view. The crash you get is probably because the root view does not exist yet when you try to access it. Try the following:
- (void) loadView
{
[super loadView]; // creates the root view
UIView* subView = [[UIView alloc] initWithFrame:CGRectMake(30, 30, 30, 30)];
[subView setBackgroundColor:[UIColor greenColor]];
// because you don't set any autoresizingMask, subView will stay the same size
[self.view addSubview:subView];
}

Change cursor for full screen NSWindow

I am trying to make an overlay window that will allow drawing at the ShieldingWindowLevel, however when the window appears the cursor is still the default pointer. I would like to change it to the crosshairs. Having controller NSCursors before I am baffled why resetCursorRects is not ever called.
I manually create the window as follows (in my AppController class):
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Create the window
NSRect frame = [[NSScreen mainScreen] frame];
// Provide a small area on the right to move the cursor in-and-out of the window.
frame.size.width = frame.size.width - 20;
self.window = [[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[self.window setAcceptsMouseMovedEvents:YES];
[self.window setOpaque:NO];
[self.window setLevel:CGShieldingWindowLevel()];
[self.window setBackgroundColor:[NSColor colorWithDeviceRed:0.0 green:0.0 blue:1.0 alpha:0.2]];
// Create the subview
ScreenOverlayView *subview = [[ScreenOverlayView alloc] initWithFrame:NSZeroRect];
[[self.window contentView] addSubview:subview];
// Add subview and show window
[self.window setContentView:subview];
[self.window makeFirstResponder:subview];
[self.window orderFrontRegardless];
}
With the following NSView subclass:
#implementation ScreenOverlayView
- (void) resetCursorRects {
[super resetCursorRects];
[self addCursorRect: [self bounds]
cursor: [NSCursor crosshairCursor]];
}
// ...
#end
I created a sample project to show this case and posted it to github, the most interesting files are ScreenOverlayView.m and AppDelegate.m.
I should point out that I have also spent a good deal of time trying to get this working with an NSTrackingArea, as you can see in the sample project. Tracking Area works if the mouse enters the view after it has appeared, but not if it is inside to start with. Using MouseEnter and MouseLeave would be fine if I had some way to set the initial cursor, but it will only change for a split second before changing back.
How can I get resetCursorRects to be invoked -OR- how can I set the cursor when I move it to the superview?
The key is that you really need to create a custom subclass of NSWindow, in order to counteract some of the default behavior that borderless windows (NSBorderlessWindowMask) have.
An updated version of your sample project is at http://www.markdouma.com/developer/full-screen-overlay.zip.
In it, I created a custom MDScreenOverlayWindow class that overrides NSWindow's canBecomeKeyWindow method like below:
// Windows created with NSBorderlessWindowMask normally can't be key,
but we want ours to be
- (BOOL)canBecomeKeyWindow {
return YES;
}
This will allow your view to become key and basically all your other stuff to work properly.
The other thing that may be of note is the drawRect: method. (It looks like you may be coming from iOS). You might want to look into NSBezierPath, as it could potentially simplify some of your drawing code. For example, I believe the drawing code you had could be consolidated into the following:
- (void)drawRect:(NSRect)rect {
// the color should probably be "pre-multiplied" by the alpha
// premultiplied version:
[[NSColor colorWithCalibratedRed:0.8 green:0.0 blue:0.0 alpha:0.8] set];
[NSBezierPath setDefaultLineWidth:2.0];
[NSBezierPath strokeLineFromPoint:currentLocation toPoint:downLocation];
}

ipad: popover is not appearing at appropriate place

I have a situation here please help me out in this,
1) I have a Table with custom cells
2) Each cell has 2 search bars and 2 lables.
what I was attempting is suppose a user beginEditing a searchBar a popover should appear pointing that search bar.
I have implemented this but popover is not appearing over the desired searchBar moreover height of popover is also too long sometime
if (searchBar.tag==10) {
NSLog(#"Display date popover");
CGRect pickerFrame = CGRectMake(0,0,300,200);
UIViewController *tempDateViewController=[[UIViewController alloc] init];
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:pickerFrame];
[datePicker addTarget:self action:#selector(pickerChanged:) forControlEvents:UIControlEventValueChanged];
[tempDateViewController.view addSubview:datePicker];
if(!currentPopover)
{
currentPopover=[[UIPopoverController alloc] initWithContentViewController:tempDateViewController];
}
else {
[currentPopover setContentViewController:tempDateViewController animated:YES];
}
tempDateViewController.contentSizeForViewInPopover=CGSizeMake(320, 300);
[datePicker release];
[tempDateViewController release];
[currentPopover presentPopoverFromRect:searchBar.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Please help me to solve this one.
Thanx in advance.
The searchBar is inside a cell which is in a table view (which may be in some other view depending on your layout). The problem most likely is that self.view is not the direct parent of searchBar where you are calling this. So using the frame of the searchBar in self.view will give unexpected results.
Instead of using self.view and trying to figure out where the searchBar is relative to that, you can use the searchBar itself for the "inView" and for the "rect", use the searchBar's bounds:
[currentPopover presentPopoverFromRect:searchBar.bounds inView:searchBar
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Next, to fix the height of the popover, try setting the popover's popoverContentSize instead of the view controller's contentSizeForViewInPopover:
//tempDateViewController.contentSizeForViewInPopover=CGSizeMake(320, 300);
currentPopover.popoverContentSize = CGSizeMake(320, 300);
Finally, a separate issue but, the minimum height for a datepicker should be 216, not 200:
CGRect pickerFrame = CGRectMake(0,0,300,216);