Enable just small portion of NSWindow? - objective-c

I must achievement somenthing tricky in my application for MAC OS, and because it's not easy to explain I will put an image: custom window
I created the NSWindow from image but the problema is how can create the NSView (the blue one) which is over and which have the purpose to block other action from user and just left small portion to be active. Any suggestion?

You can create a Custom NSView and draw clear color for enbaled rect area and disabled color for rest of the area. Capture the mouseDown event for the custom view and discard all the mouse events outside enabled rect area and if the mouse down in enabled area then call the mouse down event to the control behind the enabled area.

Wouldn't it be better to put up a sheet with a dialog to ask the user for the required information (and prevent interaction with the rest of the window) instead of mimicking a very un-Mac-like UI?
For example, consider the UI when creating a new project or adding a file to a project in Xcode.
If you really must attempt this, don't use a view to cover the window. Use another window. Make it borderless. Set its backgroundColor to [NSColor clearColor] and its opaque property to NO. Set its hasShadow property to NO. Set its frame to match the content rect of the window you want to block (or maybe its frame if you need to prevent interaction with its title bar).
Attach your overlay window to the main window as a child, using -addChildWindow:ordered:.
For the contentView of the overlay window, create a view that will draw the semi-transparent color everywhere except for over the control you want to leave accessible. To get that rect in the main window's coordinate system, you would use something like [specialView convertRect:specialView.bounds toView:nil].

Related

Objective C image click action

I have seen this in other programs and am trying to replicate it.
I have an image on one of my forms that someone can drag-and-drop an image into. I would like to allow the user to click on that image to pop up another dialog that they could instead select a "stock" image if they choose to.
I don't see an outlet I can use for the click and putting a transparent button over the top would defeat my ability to drag and drop an image on to it.
I realize I could just change the image to a button instead but I prefer to use an image if possible.
How can I make an image clickable?
This is OSX by the way, not IOS.
Quoting from another question:
By default, NSImageView doesn't react to -mouseDown:, or -mouseUp: like other NSControl subclasses (namely NSButton) do.
The solution is given in an answer elsewhere - subclass NSImageView and appropriately handle the click event (as linked).
Drag in the standard NSButton.
Uncheck the Bordered checkbox.
Clear the Title text.
Set the Image (and optionally, the alternate image).
Also, if you are using layout constraints to set button size to image view size, don't forget to set vertical hugging/compression resistance priorities to low values (say 1).

What Cocoa Views and Controls Will Create Something like Part of the Network Prefs Display (Mac OS)? [duplicate]

This question already has an answer here:
NSTableView with +/- buttons like in System Preferences using only Interface Builder
(1 answer)
Closed 7 years ago.
I'm building an OSX app and want to create a set of controls similar to what's found at bottom of the standard Network Preferences configuration panel. I'm running into some layout problems that I wouldn't have expected.
These are my specific questions:
What contains the 3 buttons so there's similar shading all they way across the row where the buttons are positioned? In particular, what's causing the area without buttons to have shading?
How do you do this without getting a double border where the row of buttons meets up with the table?
I want to do this with an xib file. This may be incredibly simple, but I'm missing something I guess.
I find that if you make a button with style "Gradient" and type "Momentary Change", then it looks like the other buttons but does not respond to clicks, so you can use that as the area after the last button. (The NSMomentaryChangeButton is documented as changing the image and title when clicked, so if you don't use an image or title, nothing should change.)
If you check Refuses First Responder in the attributes inspector, then it will not be possible to highlight this blank button using Full Keyboard Access.
Ken Thomases also brings up the issue of the blank button being shown as a button to Accessibility. One can fix that by using a subclass of NSButtonCell that has just one method:
- (BOOL)accessibilityIsIgnored
{
return YES;
}
I think that's easier than writing a custom view.
As d00dle says, avoid double borders by slightly overlapping things.
Since you want the slack space to have the same background as the buttons, and since the buttons can change appearance from release to release of the OS, the best thing to do is to get the frameworks to draw it like it would the buttons.
Rather than using an actual button as JWWalker suggests, I have used a custom view that leverages NSButtonCell to draw the background. The advantage is that you can be sure there's no chance of getting undesirable behavior. For example, a button could get focus (for users who have All Controls selected in System Preferences > Keyboard > Shortcuts > Full Keyboard Access) so that the user could Tab to it. Accessibility will report the presence of the button through VoiceOver. Etc.
Configure the button cell just like the buttons (set buttonType and bezelStyle). In the view's -drawRect: call [buttonCell drawWithFrame:rect inView:self];, where rect is similar to the frames of the buttons. Since one way to avoid double borders is to make the buttons larger than the view's bounds, you may need to do the same for rect. For example, you might want to use NSInsetRect(self.bounds, -1, -1).
The buttons are buttons... This can be accomplished with a custom view drawing border and the background "shading".
To avoid the double border where the table and the custom view meet you simply align it so they overlap by 1 point (pixel) or avoid drawing the top border in your custom view.
I don't know of any standard object capable of doing this.

How do you use the dark vibrancy on an NSWindow?

What is the correct way to use the Vibrant Dark (NSAppearanceNameVibrantDark) or Vibrant Light (NSAppearanceNameVibrantLight) modes with an NSWindow?
I'm building an application and would like to offer the new Vibrant Dark appearance as an option for the main application's NSWindow. The window itself is a pretty straight forward window with an NSToolbar across the top and a scroll view as the main content area.
There's plenty of information from Apple on using the new vibrancy appearances in conjunction with an NSVisualEffectsView, but I'm looking for clarification on how to use those appearances on an NSWindow.
In the NSAppearance.h header file, there's a comment that states that the vibrant appearances should only be set on an NSVisualEffectsView. There's no mention of it being supported on NSWindow.
The WWDC videos talk about making sure that you're using layer-backed views and that you're allowing vibrancy on your subviews when using the new vibrant appearances, but again, no mention of using them on an NSWindow.
The VisualEffectsPlayground sample code does have an example of a Facetime-like application that uses the dark vibrancy mode, but it doesn't have a toolbar and it uses the full-content mask.
From that information, I'm doing the following in my NSWindowController's windowDidLoad method:
[self.window.contentView setWantsLayer:YES];
self.window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark];
And, sure enough, I get a black NSToolbar with a black window title bar. So it looks like it's working properly, but when my scrollview scrolls its content (thumbnails of images) the standard translucency under the NSToolbar and the window's title bar is either not present or is randomly present. There doesn't seem to be any pattern. Sometimes when I scroll the scrollview, the content is shown in the "blurred" state under the toolbar and title bar. Other times when I scroll, the toolbar and titlebar are just an opaque black. (The title bar and toolbar still draw their titles and buttons.)
When I don't request a layer for the window's content view, then I get more a gray titlebar and window title rather than a "pure" black one. (My scrollview's background color can be either white, dark gray or black.)
Any help or clarification on how to properly configure an NSWindow (that contains an NSToolbar and an NSScollView) to use the new vibrancy appearances would be much appreciated.
This will make a dark mode window. Subsequently, everything in the window (including titlebar, toolbar and even dialogue sheets) will become dark.
let USE_DARK_MODE = true
if USE_DARK_MODE {
window.appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
window.invalidateShadow()
}
invalidateShadow doesn't seem required, but sometimes shadow does not work properly if lacked. (OS X 10.10)
I figured that you can subclass NSWindowController. Set the class for your Window Controller in IB to your custom NSWindowController. After that in the windowDidLoad function
self.window?.titlebarAppearsTransparent = true
Also set "Full Size Content View" in the Attribute inspector for the NSWindow.

How can I remove the "blur" effect that Cocoa adds to transparent sheets?

By default, Cocoa adds a background blur effect to transparent and semitransparent modal sheets when they are applied to a window. I would like to disable the blur effect. How would I go about doing it?
I have created a custom sheet (a subclass of NSWindow with a transparent background and some controls in it). I am able to display it using the standard beginSheet method as follows:
[NSApp beginSheet:myCustomSheet
modalForWindow:mainWindow
modalDelegate:self
didEndSelector:...];
The sheet displays fine, but everything behind it is blurred.
Note 1: I am writing a completely customized user interface for a touch screen / kiosk type app, so none of the usual Apple user interface guidelines apply.
Note 2: I do want to see what is underneath the sheet. As SirRatty pointed out, it is possible to block out the blurred portion by filling in the background. In my case, I want to have the background show through, just without appearing blurred.
There's a private API call that can be used to set a CI filter on the background of a window:
http://www.mail-archive.com/cocoa-dev#lists.apple.com/msg16280.html
There's also a CGSRemoveWindowFilter:
extern CGError CGSRemoveWindowFilter(CGSConnectionID cid, CGSWindowID wid, CGSWindowFilterRef filter);
Just be aware that the usual private API caveats apply (might go away or change in the future, etc.).
What I've done:
In IB, add a window-sized custom NSView to the window, at the bottom of the content view hierarchy. Set the object's class to MySolidView (or whatever.)
In Xcode, the MySolidView class does just one thing: on -drawRect it will fill the view with a solid color. (e.g. light grey).
You could write your own sheet animation routines that display your own NSWindow and fill the background of the window with a semitransparent colour. I'm not sure whether setAlphaValue: for NSWindow will also affect the child elements' opacity. If it does affect them, you could use setBackgroundColor: and provide the default window background colour but with an alpha component, this should not affect the child elements.
I suppose one of the problems of developing/designing your own user interface is when you have to reimplement the wheel just for a minor customisation. At least, if you write it yourself, you'll have more control over its customisation in the future.

IKImageView zooming controlled by an NSSlider

What's the best practice for setting zoom factor of an image within IKImageView via NSSlider?
I was able to bind a slider either to zoom in OR zoom out action of an IKImageView.
Obviously, what I'd rather see is a single slider controlling both those actions.
Best, if image is refreshed after each change of the slider (continuously, even if a mouse button is not released yet).
This demo explains a lot: ImageKitDemo
In particular, this snippet is what I was looking for:
- (IBAction) zoomSliderDidChange:(id)sender
{
[addProductPhotoImageView setZoomFactor:[sender floatValue]];
}
The Bindings way would be to bind both the Zoom Factor of the IK image view and the Value of the slider to the same property of your controller. When the slider changes the value of the property, the image view will be notified, and will go get the new value from your controller.
One advantage of this way is that you can add more ways of zooming in and out and the value in the slider won't go stale. For one example, if IKImageView adds pinch-zooming (or if it has it already—I don't have multi-touch on my Mac), the user can zoom that way and the slider will update automatically. That won't happen with the IBAction solution.
Another example would be Zoom In and Zoom Out menu commands (perhaps with ⌘+ and ⌘- keyboard shortcuts) that send action messages to your controller. Your controller would respond by increasing or decreasing the value of the property (using a setter method it implements). With Bindings, both the image view and the slider will update for free. Without Bindings, you would have to explicitly talk to both the image view and the slider, telling one to update its zoom factor and the other to update its slider.
A third example would be a “Zoom factor: X%” display in a corner of your window. With Bindings, this can update for free no matter how the user zooms the image: moving the slider thumb, pinching/unpinching the image, or pressing a menu item. Without Bindings, this would be yet another thing you have to talk to in your (at least three) change-the-zoom-value action methods.