So I've been burned by this a few times. I'm trying to create an NSTextView that can be scrolled.
The only way I've gotten it to work is by having a Xib—but right now that stopped working after I added a Stack View in an adjacent Split View for God-knows-what-reason.
So what have I done?
I have code for code copied down the Apple Docs like for Text in Scroll View like so:
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html
BOOL deviateFromAppleScrollDoc = NO;
_scrollView = [[NSScrollView alloc]
initWithFrame:[[self view] frame]];
// Apple Has
// [[theWindow contentView] frame]];
// but we are in a sub-View-Controller
NSSize contentSize = [_scrollView contentSize];
[_scrollView setBorderType:NSNoBorder];
[_scrollView setHasVerticalScroller:YES];
[_scrollView setHasHorizontalScroller:NO];
[_scrollView setAutoresizingMask:NSViewWidthSizable |
NSViewHeightSizable];
_editorView = [[EditorView alloc]
initWithFrame:NSMakeRect(
0, 0,
contentSize.width, contentSize.height)];
[_editorView setMinSize:NSMakeSize(0.0, contentSize.height)];
[_editorView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[_editorView setVerticallyResizable:YES];
[_editorView setHorizontallyResizable:NO];
if (deviateFromAppleScrollDoc)
{
[_editorView setAutoresizesSubviews:YES];
[_editorView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
}
else
{
[_editorView setAutoresizingMask:NSViewWidthSizable];
}
[[_editorView textContainer]
setContainerSize:NSMakeSize(contentSize.width, FLT_MAX)];
[[_editorView textContainer] setWidthTracksTextView:YES];
if (deviateFromAppleScrollDoc)
{
[[_editorView textContainer] setHeightTracksTextView:YES];
}
if (deviateFromAppleScrollDoc)
{
NSClipView *clipView = [[NSClipView alloc] init];
[clipView setDocumentView:_editorView];
[_scrollView setContentView:clipView];
}
else
{
[_scrollView setDocumentView:_editorView];
}
[[self view] addSubview:_scrollView];
What does that get me?
As you can tell, there is an NSTextView. It does not fill the Container as I would like it to.
There is also a Scroll View and I can tell it is active. You can pull down and get a rebound effect—but it does not scroll the document as I would like. This text is cut off mid-sentence and when I add to it, the View does not scroll with my typing—and even if I scroll I can't get to it.
The Scroll View is "stuck".
I can make it fill the entire window if I change the Autoresizing mask to inlcude NSViewHeightSizable like so:
[_editorView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
See here:
Unfortunatley, it still does not scroll and the "Scroll View" is still "Stuck".
I don't know what to change.
I have tried to add a "NSClipView" and set the Content View instead like so:
NSClipView *clipView = [[NSClipView alloc] init];
[clipView setDocumentView:_editorView];
[_scrollView setContentView:clipView];
This does not work either.
Moreover it does something funky to the width and some of the letters get cut off. Not acceptable. No solution yet.
What am I missing?
What do I need to try / set / do?
Thank you!
UPDATE:
The Scroll View does scroll the document when I activate the find menu in the NSTextView.
Still mystified.
See here:
Related
I'm creating a window containing an NSButton (both window content view & button have wantsLayer = YES), and setting the NSButton's shadowColor, shadowRadius, shadowOpacity and shadowOffset. But my shadow gets clipped to the rect of the NSView. How do I fix this?
NSRect wdBox = NSMakeRect(0,0,100,100);
NSWindow * theWindow = [[[NSWindow alloc] initWithContentRect: wdBox styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing: NSBackingStoreBuffered defer: NO] autorelease];
NSView* cv = [[[NSView alloc] initWithFrame: wdBox] autorelease];
cv.wantsLayer = YES;
[cv setLayerUsesCoreImageFilters: YES];
theWindow.contentView = cv;
[theWindow setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
[theWindow setTitle: #"foo"];
NSButton* mView = [[NSButton alloc] initWithFrame: NSMakeRect(10, 10, 100, 80)];
[mView setLayerUsesCoreImageFilters: YES];
[mView setWantsLayer: YES];
mView.layer.masksToBounds = NO;
[mView.layer setShadowColor: [NSColor.redColor CGColor]];
[mView.layer setShadowOffset: CGSizeMake(4, 4)];
[mView.layer setShadowRadius: 8];
[mView.layer setShadowOpacity: 1.0];
[mView setBezelStyle: NSRoundRectBezelStyle];
[mView setTitle: #"bar"];
[theWindow.contentView addSubview: mView];
Here's a picture:
I had similar code before and it used to work until 10.9, but the shadow suddenly got clipped to the view, so I rewrote it to this simple case, but it's still clipped.
There is a bug in Mavericks. If you create an NSButton in XIB and give it a layer and set its shadow it works fine, but if you create one programmatically it clips its shadow.
I suspect the AppKit team did some crazy hacks when they made buttons do fast layer compositing in Mavericks (they won't redraw their backgrounds unless necessary now, for instance), because they tried to make it all happen magically, which is always always a bad idea.
Note that if you make an NSTextField the shadow code works as you'd expect. It's just NSButtons (so far) that I've found have this issue.
Please file a radar.
I have an NSTextField in a container:
[textField setFrameOrigin:NSMakePoint(0, -t.frame.size.height)];
content = [[NSView alloc] init];
[content setWantLayer:YES]
content.layer=[CALayer layer];
[content addSubview:textField];
[content scaleUnitSquareToSize:NSMakeSize(1, -1)];
content.frame=textField.frame;
content.layer.backgroundColor=textBGColor.CGColor;
The container itself is located in a view with
[view scaleUnitSquareToSize:NSMakeSize(1, -1)];
This is all for obtaining a top left origin for the TextField and it works great, the only problem consist in the InsertionPoint not drawing (at least not in the visible frame).
I presume the InsertionPoint is either not Scaled or translated with the TextField. Other possibility is that InsertionPoint can't be drawn in a layer backed View.
Is there a way to display the InsertionPoint cursor ?
EDIT
After trying all the possibilities out, it seems the InsertionPoint (and the focusRing) are not drawing because of its frame being positioned out of the superviews bounds and its dirtyDrawRect. Is there a way to remove the clipping of an NSView ? I need to be able to place my TextField on every absolute position possible.
I found a way through: implementing the drawing myself.
1) giving a custom TextView as Editor for the window.
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject
{
if (!myCustomFieldEditor) {
myCustomFieldEditor = [[TextView alloc] init];
[myCustomFieldEditor setFieldEditor:YES];
}
return myCustomFieldEditor;
}
2) Overiding the drawInsertionPoint method in the custom TextView class.
-(void)drawInsertionPointInRect:(NSRect)rect color:(NSColor *)color turnedOn:(BOOL)flag{
[color set];
NSRectFill(rect);
[super drawInsertionPointInRect:rect color:color turnedOn:flag];
}
For insertion point just make your textfield to first responder.
[myTextField becomeFirstResponder];
I'd like to add a close button to an NSWindow programmatically. I can get the button to display, but there are no mouse-over or mouse-down effects. My "selector" never seems to get called when i click the button. I'm not really sure whats wrong and why this is so annoying.
Here is what I've been messing with:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
NSRect c = [themeFrame frame]; // c for "container"
NSRect aV = [closeButton frame]; // aV for "accessory view"
NSRect newFrame = NSMakeRect( c.size.width - aV.size.width - 5, // x position c.size.height - aV.size.height - 5, // y position aV.size.width, // width aV.size.height); // height
[closeButton setFrame:newFrame];
[themeFrame addSubview:closeButton];
[closeButton setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[closeButton setEnabled:YES];
[closeButton setTarget:self];
[closeButton setAction:NSSelectorFromString(#"testClick:") ];
Where "testClick" is just a memeber function of my class and is defined as such:
- (void)testClick:(id)sender
The problem seems to be the call to:
[themeFrame addSubview:closeButton];
where the themeFrame is: [[self contentView] superview] Just adding the button to [self contentView] works, but I'd like it added to the titlebar.
No Interface Builder please...
Potential issue # 1)
The way you're calling "NSSelectorFromString" seems incorrect to me. I don't think you can pass parameters via this way in Objective C.
Try this:
[closeButton setAction: #selector(closeWindow:)];
and create a new "closeWindow:" action that looks like:
- (void) closeWindow: (id) sender;
which closes the window.
Potential issue # 2)
Instead of:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
Why not use:
NSWindow * parentWindow = [[self contentView] window];
if(parentWindow)
{
closeButton = [parentWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
}
I want to make transparent NSTableView.
I am using WindowController class here.
I was trying this:
- (void)windowDidLoad
{
[super windowDidLoad];
[[self enclosingScrollView] setDrawsBackground: NO];
[[self enclosingScrollView] setBorderType:NSNoBorder];
}
- (BOOL)isOpaque {
return NO;
}
- (void)drawRect:(NSRect)drawRect
{
[super drawRect: drawRect];
}
But when i was writing this code i can't found enclosingScrollView in help window.
you can see here..
Any help?? Please remember me or correct me if i am doing something wrong.
Thank you.
If you have an NSScrollView enclosing your NSTableView, you can set the scroll view's drawsBackground property to NO like this:
yourScrollView.drawsBackground = NO;
Got Answer..!!! I just tried this
[tableview setBackgroundColor:[NSColor clearColor]];
[tableview setHeaderView:nil];
and its working fine.. – – Snehal
Copied from comment in question, as its a bit buried...
If your app needs to display a transparent table view, set the background color of the table view to be clear and set the enclosing scroll view to not draw its background. The following code snippet shows one way to display a transparent table:
Swift:
yourTableView.backgroundColor = NSColor.clear
yourTableView.enclosingScrollView?.drawsBackground = false
Objective-C
[theTableView setBackgroundColor:[NSColor clearColor];
[[theTableView enclosingScrollView] setDrawsBackground:NO];
Apple - Modifying a Table’s Visual Attributes
Hey everyone, I have a iPhone App I am creating. It uses a uitableview and that goes to a detail view.
Now on the detail view I have a scroll view, and all the data (XML) comes into it fine, each time, no issues.
My UILabels in my scrollview do update with the correct data, but, they keep adding subviews on top of each other to keep adding label after label and it all looks mumbo jumbo.
I have tried everything to try and remove the subviews such as:
for(UIView *subview in [scrollView subviews]) {
[subview removeFromSuperview];
}
AND
[[scrollView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
So I am stumped, I got no idea what is happening. Any help? I have been searching Google for ages and agesm, but keep finding the same answers that don't work :(
Any direction to sites that might help that you know of will be greatly appreciated.
Thanks!
Here is what I have in my controller that loads all the scrollview and labels:
- (void)viewDidAppear:(BOOL)animated {
// Create the scroll view for this view
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
scrollView.contentSize = CGSizeMake(320, 270);
[scrollView setFrame:CGRectMake(0, 198, 320, 170)];
// Do the labels for the text
UILabel *dates = [[UILabel alloc] initWithFrame:scrollView.bounds];
dates.textColor = [UIColor whiteColor];
dates.font = [UIFont boldSystemFontOfSize:12];
dates.text = round_date;
dates.tag = 1;
[dates setBackgroundColor:[UIColor clearColor]];
[dates setFrame:CGRectMake(10, 10, 280, 22)];
[scrollView addSubview:dates];
[dates release];
// Add the content to the main scrollview
[self.view addSubview:scrollView];
[scrollView release];
}
Ok, the reason for this is that viewDidAppear will get called every time you present the view.
If you do this is
-(void) viewDidLoad;
instead.
To make sure you can access them later you might want to keep a reference to them in your UIViewController
-(void) viewDidLoad {
scrollView = [[UIScrollView alloc] initWithFrame];
[self.view addSubview:scrollView];
}
and define it in your header file with:
UIScrollView *scrollView;