Hiding/Removing/Fading CALayer erasing NSView contents - drawing

My situation:
I have a single window with a content view (NSView), which has several subviews (plain NSControl subclasses; not important, just for testing) scattered around it. For part of the end effect I am trying to achieve, I want to place a semi-transparent black CALayer overlaying the whole window's content view, and be able to make it invisible (either by hiding it or removing it, doesn't matter) when a certain event is triggered, revealing the NSViews in full clarity.
For testing purposes, I place a small semi-transparent black CALayer covering only some/parts of the subviews (the controls) in the main content view, like so:
(doh, had screenshots but can not post images as a new user. You'll have to use your imagination.)
Simple enough. So then all I tried to do was to check that it hides/removes itself properly. Then came the problem. Any attempt at hiding, removing or reducing the black layer or reducing its transparency to 0 causes all of the window's subviews to become erased, with a result looking like this:
(a window with a completely blank grey [the default window bg colour] content view)
Here's the meat of the code, in the main application call which has a reference to the main window:
// I set up my main view in a nib, which I load and will add
// to the app window as the main content view
NSViewController * controller = [[NSViewController alloc]
initWithNibName:#"InterfaceTesting" bundle:nil];
NSView * view = [controller view];
// enable layers, grab root
[view setWantsLayer:YES];
CALayer * rootLayer = [view layer];
// set up black square
CALayer * blackLayer = [CALayer layer];
[blackLayer setFrame:NSMakeRect(150, 150, 100, 100)];
[blackLayer setBackgroundColor:CGColorCreateGenericRGB(0,0,0,0.5)];
[rootLayer addSublayer:blackLayer];
// hide all sublayers of root (ie the black square)
for (CALayer * layer in [[view layer] sublayers])
[layer setHidden:YES];
// add to main window
[self.window setContentView:view];
As I mentioned before, replacing [layer setHidden:YES] with [layer setOpacity:0] has the same effect of erasing the content view, as does removing the blackLayer altogether (by calling removeFromSuperlayer and also by trying to set its superlayer to nil). More interesting still, if I set the opacity of the black sublayer square to something between 0 and 1 - 0.5, say - then all of the content view's subviews' opacities reduces accordingly.
So I'm rather baffled here, as I don't understand why hiding/removing or reducing opacity on the small black CALayer is affecting all the subviews in the view it is a part of, even those it doesn't cover. Any help is much appreciated.
Edit: Well I've discovered that the contentView's top layer in fact has a sublayer not only for the black square I manually added, but for every subview as well (whether originating from the nib or manually created by me after loading the view from the nib), hence why they were all fading/disappearing when I thought I was just operating on the black box. But what I still don't know is why there are layers for all the subviews, where they came from, and how to get rid of them (again, all attempts to remove them - via removeFromSuperlayer, setting to nil, etc - fail.

Subviews (controls) have layers which are set as sublayers of the parent view layer. So looping through all the sublayers also acts on these subview layers.

Related

Absolute positioning of child views in a Famo.us ScrollView

I've a ScrollView of images, while clicking on an image (read imageSurface), I would like that one to smoothy scale to an absolute location of the screen (for example a fullscreen) this independently of the scroll state. Here is an example of a similar behaviour.
In my understanding, I should find a way to retrieve the current imageSurface location and apply a modifier with an opposite location in order to virtually detach the surface from the ScrollView. Then I might apply the modifier I would like (for example a full screen modifier).
Another option would be to override the ScrollView's render() function but I'm not sure it is a good/safe idea.
Removing the image from the sequence to quickly add it somewhere else but attached to another modifier (not in the scrollview) is also an alternative but I fear having glitches and not being able to fade it back to the sequence correctly.
Any idea on how to achieve this ?

Overlay items in qtgraphicsscene

I would like to draw some dynamical overlay elements in a scene.
Usually I would go for the paintEvent in the view or foreground painting for doing overlays, but this time I need to interact with these elements: they are like every other item in the scene... Mostly, this choice comes from the fact that these items are somewhat complex, and they share the rendering with other QGraphicsItem(s).
The problem is that, being overlayed, they shall be treated a bit differently than any other element in the scene: rendered in view coord space, not in scene coord space, and ignore changes in the view rect, dragging, dropping, rubber band selection, and such.
The question is somewhat general: how could I use the scene for a thing like this? Is there a better option for doing overlays e.g. using multiple scenes and rendering them all, in some magic way, in a single view widget?

Cocos2d iPhone. Scrollayer contentSize. Layers

I want to set the contentsize of scrollayer.
I have a scrollayer, it's CCLayer type and moving is set by ccTouchMove. I have one schedule for smoothing. BUT.
Problem is that scrolling layer is big like the whole display. I want to set the contentsize of scrollayer. Content in this layer will be scroll and showing ONLY in this layer. Not taking up the whole display. Something like this
Scrolling just in gray CCLayer (scrollayer) ....NOT WHOLE SCREEN.
Can you help me?
P.S.: Setting CCLayerColor and initWithColor:Width:Height: is not working. It just makes some stupid color box and it's moving too.
ok, honestly i would put the window frame at a higher z than the scrolling object ... if you dont you may have to crop and change sprite on the fly for the window content, nasty (at least that is the one way i could do this, without further research).
so :
// initialize this logic somewhere useful
CCNode scrollableContent;
CCSprite windowFrame;
BOOL isScrollPossible;
[self addChild:scrollableContent z:0];
[self addChild:windowFrame z:1];
// and in the touch delegate methods
-(void) ccTouchBegan:{
check if the touch happened in the window, if yes, scrolling is possible
}
-(void) ccTouchMoved:{
if (isScrollPossible) {
compute displacement
compute nextPosition for scrollableContent node;
if ( nextPosition in window ) {
// make scrollableContent follow touch
scrollableContent.position=nextPosition;
} else {
// stop any further scrolling until the next 'touch began'
isScrollPossible=NO;
}
} else {
// scroll not possible, do nothing
}
}
This is the basic idea. You may need clamping logic to prevent the creeping of scrollableContent beyond the edges of the window.
Edited for typos.
After trying desperately with masking and GL_SCISSOR, I settled on cutting a hole in the foreground and only moving the background object when onTouchMoved updated.
To see it in action, have a look at the Stats page of Angry Gran.

Popover resizing erraticly

I have a UITabBarController inside a UIPopoverController, which I am displaying solely from one UIBarButtonItem. When shown I want the popover to take up the maximum vertical height allowed. It works fine if I tap to display it, then dismiss, and then rotate. However if I have the popover displayed in landscape, and then rotate to portrait, it no longer will fill the entire vertical distance. I have the tab bar controller's content size property set to 320 by 1000, and I have even tried resetting this every time the device rotates. Worse yet, when the user activates the search bar the popover shrinks up extremely small, and stays that way until the app is restarted.
http://cl.ly/3JdC to http://cl.ly/3JdC
Also http://cl.ly/3JVF
How can I stop this, and have the popover always fill up the max vertical size?
I was just having the same problem and found out that it only happens when I present the UIPopoverController using the method:
- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
but it works fine when I use:
- (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
Unfortunately UIBarButtonItem does not have a frame Rect you can use with this last method so my fix was to use the UIToolbar's frame and modify frame.origin.x and frame.size.width accordingly to make the popover appear on the right place next to the UIBarButtonItem.
Hopefully Apple will fix this in next releases of iOS.
Regards

Strange winAPI behaviour

I have sub classed a tab control to give it a background. I have used the clipping functions to clip the drawing area to the update region. This works, except for when I move the window of the screen and back again.
When it does this, it occasionally sets the clipping region to the whole screen. This is fine except that none of the controls redraw and end up hidden behind the background. How do I know whether or not to redraw the background when I get this update region. It would be 100x easier to develop this if I saw the source code for the tab control, but that isn't going to happen.
All help or suggestions welcome, but I really do need a straight-forward answer.
By "clipping region" I assume you mean the area that has to be redrawn that windows passes to you.
Try this: The paint message handler should bitblit the area of the background image that corresponds to the part of the window that needs to be refreshed (so you don't draw over things that don't need updating). Then let the base class handle the rest.
If it's setting the repaint region to the entire window the tab control code should redraw everything after you've painted the background.
Having code to look at would help