Stopping transparent drawing going all the way through NSViews - objective-c

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.

Related

NSScrollView with fixed background texture

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];

NSImage problems

Trying to draw a pattern inside a NSView subclass. I am trying to draw this using NSColor and its method colorWithPatternImage, however when I draw that on the screen the texture keeps moving when resizing the window.
The following code is associated with my custom drawing:
[[NSColor colorWithPatternImage:[NSImage imageNamed:#"texture"]] set];
NSRectFillUsingOperation([self bounds],NSCompositeSourceOver);
I have only tested this on 10.7.
thanks

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].

Cocoa drawing glitches when window loses then regains main status

Various things, including (perhaps most notably) the window losing its main status and then being brought back into focus, cause some of my custom views to develop rendering glitches until I do something (such as resize the window) to cause these custom views to redraw. I assume this is due to some sort of caching bug in AppKit, and I'm sure I'm not the only one getting this behaviour, so does anyone know how to work around it?
Here's an example:
Notice the weird dark line at the left of the view's background? This is drawn even without the subviews in the view. I get other similar bugs in some of my other views.
Here's the code that does the drawing:
void EDDrawGlossEffectInRect(NSRect dirtyRect) {
NSRect topRect, bottomRect;
NSDivideRect(dirtyRect, &topRect, &bottomRect, (dirtyRect.size.height / 2), NSMaxYEdge);
[EDLightChromeColor set];
NSRectFill(topRect);
[EDMidChromeColor set];
NSRectFill(bottomRect);
}
and
-(void)drawRect:(NSRect)dirtyRect {
EDDrawGlossEffectInRect(dirtyRect);
NSBezierPath *path = [NSBezierPath bezierPath];
[path setLineWidth:1.0];
NSPoint startPoint = {0, dirtyRect.size.height};
NSPoint endPoint = {dirtyRect.size.width, dirtyRect.size.height};
[path moveToPoint:startPoint];
[path lineToPoint:endPoint];
[[NSColor colorWithCalibratedWhite:0.7 alpha:1] set];
[path stroke];
}
The view is created programatically, not with Interface Builder, which I'm not using for this project.
dirtyRect will not necessarily cover your view's visible rect, so you might want to see which part of your view's bounds intersect with the dirtyRect and just repaint that. Otherwise, just repaint the bounds of the view. Resizing the window can cause the entire bounds to be dirty (usually), which is probably why you're seeing full repaints at that point.

Custom NSScrollers having weird effect from Core Animation

I am making custom NSScrollers for use in NSScrollView. But when any of the superviews of the NSScroller gets Core Animation enabled. I get this drawing issue that's a huge nuisance. Whenever i scroll into the corners of the scroll view the scrollers clip. But if a scroller starts out drawing in the corner, the scroller part stays in that corner. What could be causing this problem? I have too much code to show on here. But here is my drawing code:
NSRect knobRect = [self rectForPart:NSScrollerKnob];
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:knobRect
xRadius:CornerRadius
yRadius:CornerRadius];
[path setLineWidth:2];
[[NSColor colorWithDeviceRed:0.114 green:0.114 blue:0.114 alpha:0.3] set];
[path fill];
[[NSColor colorWithDeviceWhite:1.0
alpha:0.100] set];
// Clip drawing to this path; draw nothing outwith the path.
[path addClip];
[path stroke];
I already tried to get rid of everything except the fill but it didnt work. This issue goes away if I call setNeedsDisplay:YES on the super view when setFloatValue is called.
Clipping Issue http://idkz.org/b814ee5c875c9f44cc2d1345e4489420
it seems that the answer to the problem seems to be to call:
[self setArrowsPosition:NSScrollerArrowsNone];
And it magically works :D
Edit, but I get a similar effect when I drag the scrollbar. :'( Is there anyway to clear the graphics without redrawing the scrollview itself? :(
You probably found this out by know, but in your case, the following piece should solve your drawing issue:
-(BOOL)isOpaque {
return NO;
}