NSScrollView with fixed background texture - objective-c

I have an IKImageBrowserView that is the document view of an NSScrollView. How can I set a background image (a texture) so that the background remains fixed when the user scrolls.
I have tried a variety of things but either they just don't work or it doesn't remain fixed.
I have tried making the IKImageBrowserView and NSScrollView transparent, but this doesn't work, the background is black.
I have tried adding the texture as the background layer of the image browser:
NSColor* browserBackgroundColor = [NSColor colorWithPatternImage:[NSImage imageNamed:#"linenTile"]];
CALayer *layer = [CALayer layer];
[layer setBackgroundColor:[browserBackgroundColor CGColor]];
[self.imageBrowserView setBackgroundLayer:layer];
It remains fixed when scrolling down, but when scrolling up. This is the closest I have got it.

If your scrollView is full screen, you can just set you image to be the background of your self.view, and then set the background of your scrollView transparent.
Or you can just add a separate NSView beneath your scrollView, make it cover the same area as your scrollView, and set its background.

Finally got the combination correct.
Subclass NSScrollView and draw the pattern image in drawRect:
- (void)drawRect:(NSRect)rect {
[[NSColor colorWithPatternImage:[NSImage imageNamed:#"linenTile"]] set];
NSRectFill(rect);
}
Set the background of the document view to clear (for IKImageBrowserView like this):
[self.imageBrowserView setValue:[NSColor clearColor] forKey:IKImageBrowserBackgroundColorKey];
And also the Draw Background check box in interface builder on the scroll view must be unchecked. Or set the value to NO in code.
If you want the pattern to scroll with the content. Don't subclass the NSScrollView and just set the background color of the scrollview to the pattern, and the background color of the document view to clear.

Subclassing and -drawRect: is unnecessary, simply use the backgroundColor property of NSScrollView. The docs say "This color is used to paint areas inside the content view that aren’t covered by the document view."
scollView.backgroundColor = [[NSColor colorWithPatternImage:[NSImage imageNamed:#"linenTile"]] set];

Related

How to make a view transparent without transparent subview on that

I have a probem like this. We know we can make transparent an UIView by changing Alpha value of that view. But I dont want to make transparent buttons which are inside that view. My problem is when I set the parent view alpha, button also get transparent and button title not visible clearly. How can I overcome this problem.
Set the background color of the UIView with variable alpha, like this:
view.backgroundColor = [[UIColor white] colorWithAlphaComponent:0.5f];

UITableViewCell's backgroundView overlapping contentView

I am trying to set the backgroundView parameter of a UITableViewCell, but the backgroundView is overlapping the bounds of the cell. I have tried setting masksToBounds to YES, but that doesn't seem to make a difference. Please can you tell me where I am going wrong?
Here is an image showing my problem:
Here is my code:
UIImageView *iv = [[[UIImageView alloc] initWithFrame:cell.frame] autorelease];
[iv setImage:[UIImage imageNamed:#"paper"]];
[iv.layer setMasksToBounds:YES];
[cell.layer setMasksToBounds:YES];
[cell.contentView.layer setMasksToBounds:YES];
[cell setBackgroundView:iv];
Using masksToBounds doesn't work because the bounds of the cell are a rectangle.
Even if the corners of the cell are rounded, they're still part of the cell (but they contain transparent pixels). When a cell is displayed in a grouped table view, its background view (and its selected background view) is drawn in regard of its position in its section (middle, top, bottom, single).
So, if you want to provide a custom background view, you need to compute the position of the cell in its section and provide the adequate background :
either by using 4 different images
or by using the mask property of the background image's layer
or by subclassing UIView and implementing drawRect: so the graphic context is clipped before the image is drawn.
Are you setting every cell that background view, if so why don't you just set it to the table view background.

Drawing Transparent Images

I created a custom view to a button, as I need to implement some highlighting when the mouse is over. The class is very simple, and I already implemented mouseEntered: as well as mouseExited:. The view was registered for tracking in the init method (not sure if it's the best place).
The problem is drawing. I keep an ivar mouseOver, set to YES on mouse enter and NO on mouse exited. The other ivar is for the image, called image. The difference between mouse over or not when it comes to drawing, is the transparency. Here is my drawRect::
- (void)drawRect:(NSRect)dirtyRect
{
[image drawAtPoint:NSMakePoint(0.0,0.0)
fromRect:dirtyRect
operation:NSCompositeCopy
fraction:((mouseOver) ? 1.0 : 0.0)];
}
It works nicely, but only when the mouse first entered, apparently. I guess the problem is that the view is not cleared before drawing the other image. I tried adding:
[[NSColor clearColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeClear);
But without success. How can I fix this?
[NSColor clearColor] is a purely transparent color. You probably want to fill using a color with some opacity, like, say, [NSColor whiteColor].

Stopping transparent drawing going all the way through NSViews

I'm doing some simple drawing in my NSView's drawRect with code like this
[[NSColor colorWithCalibratedWhite:0.250 alpha:0.700] set];
NSRectFill(dRect);
This drawing is being done in a nested view and I'm finding that the transparency goes all the way through the parent view and window showing some of the screen beneath it.
How do I get it so the transparency only goes through to the parent view (or any drawing that was done in that frame before it?
Thanks!
You really shouldn't be using NSRectFill to draw a transparent color. A call to
NSRectFill(rect);
is really just a shortcut to
NSRectFillUsingOperation(rect, NSCompositeCopy);
NSCompositeCopy doesn't perform compositing, so you can get unexpected results when a transparent NSColor is set.
Try using this instead:
[[NSColor colorWithCalibratedWhite:0.250 alpha:0.700] set];
[NSBezierPath fillRect:rect];
That should draw the transparency properly, with the underlying drawing visible.

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)