How to add a NSColorPicker to the application's main window? - macos

I'm building an application to generate an array of colors based on a color chosen by the user.
The default on Mac OS X for color selection is to open a NSColorPanel containing multiple NSColorPickers. But, as the color selection process is the main interaction the user will have with the app, it'd be better to avoid the extra clicks and panel-popping in favor of a more straightforward way.
So, is there any way to add a NSColorPicker object to a window?

I know this is an older question, but check out NSColorWell. From the docs:
NSColorWell is an NSControl for selecting and displaying a single color value.

Interresting Question.
I strongly doubt it (but would love to be proven wrong). NSColorPickers are not NSControls (nor NSCells) so there's no clean wrapper to insert into a window.
Even if you were to instanciate an NSColorPanel and get a reference to its contentView and copy it (with all that defines the color picking controls) to your own window... there's no obvious way of obtaining the color value. NSColorPickers are plug-ins so you can't forsee the controls of a colorPicker.
The only other way I can see (and that's a stretch) would be to manually load the NSColorPickers plug-ins directly. I don't know how successfull this would be.
File a bug report and request the feature?

Related

How to get correct background and control colors in property pages?

I'm trying to handle background color properly in a dynamically generated property sheet in dynamically generated property pages in win32 api using MFC (though I expect my question is general, and not restricted to MFC, but since my code and examples use it, it's germane to my question anyway).
So we have a:
CPropertySheet
containing multiple
CPropertyPage
I generate the contents of any given page dynamically - from file resources using a custom dialog definition language - all irrelevant other than to say - a list of controls and their coordinates is created within a given page, and the page is resized to accommodate them. This logic is working beautifully.
However, what doesn't work is that the controls and background of each page draws using the dialog default color/brush.
I've tried a number of ways to attempt to force it to draw using the white color/brush that a hard-coded property sheet / page would.
There are two important pieces to this:
Page Background
Control (on the page) background
For #1, I've tried:
acquire the background brush from parent window class (it's dialog bkgrd) (same is true if I do this and ask the tab control)
change the property page to use WS_EX_TRANSPARENT (PreCreateWindow is not called by the framework when generating a page viz PropertySheet::AddPage)
For #2, I've tried:
overriding OnWndMsg / WM_CTLCOLORSTATIC to forward that request to (A) the parent (sheet), and (B) to the tab control (which is what wants the white in the first place).
However, anytime I use any of the above "ask for the background / forward the request" up the chain to either the sheet or the tab control - I get the dialog background color, never the white I'd expect.
Using Spy64, I can see that for a fully hardcoded property sheet / page - that the only discernable differences I can see is that the dialog window created in AddPage (or its moral equivalent) has WS_CHILD instead of mine which has WS_POPUP (the rest of the styles appear to be the same, such as WS_VISIBLE|DS_3DLOOK|DS_FIXEDSYS|DS_SETFONT|DS_CONTROL and WS_EX_CONTROLPARENT.
So, other than the WS_CHILD, I see no significant differences from what I'm creating and from another property sheet that works properly from a standard resource (i.e. hard coded).
I'm also flummoxed as to how this works normally anyway - since forwarding things like the ctrlcolor message doesn't respond correctly - and asking for the windows background colors similar doesn't - then how is it in a standard case the background colors of controls and pages comes out as white, and not dialog background?
Any ideas or help would be appreciated - I'm kind of running out of ideas...
When Visual Styles were added in Windows XP they really wanted to show off this new feature so they made the tab background a gradient (really a stretched image) instead of a single color and this caused problems in old applications that did custom drawing with the dialog brush as the background.
Because of this, only applications with a comctl32 v6 manifest got the new look but there was a problem; old propertysheet shell extensions would load in new applications (including Explorer) and things would look wrong.
To work around this they also require you (or your UI framework) to call EnableThemeDialogTexture(.., ETDT_ENABLETAB) to get the correct tab page look.
As if things are not tricky enough, there is a undocumented requirement that you also need a button or a static control on the page!
If you have custom controls they have to call DrawThemeParentBackground when you draw if they are partially transparent.
Turns out my old code had defined an ON_WM_ERASEBKGND handler - and removing that (and all of my above attempts) makes it work.
So simply doing NOTHING is the correct answer. D'oh!!!
I'm leaving my shame here in case someone else trips on this! [Whoops!]
(Still interested if anyone has deeper insight into how this mechanism works under the hood)

MFC colored button with native win7 appearance

I am using MFC to create a dialog project and trying to impart color to the buttons.
I came to know that the only way you can do is to make the button owner draw. OnCtlColor() does not work for buttons.
I am able to color the button overriding OnDrawItem , but the problem is that , in the process the 3D cool look (with slightly rounded corner that you get in Win7) is lost.
Is there any way to retain the native look and color the button on top of that?
This is not a trivial task. As long as you are using themed controls (what you want), you cannot do more than the theme allows.
You would have to re-implement drawing of the button on your own, making use of the theme API as much as possible to retain themed look, yet sneak-in your color.
Though note that you can hardly achieve anything better than, what .NET WinForms do, when you set the Button.BackColor:
See also question how to set Button BackColor?
Disassembling the WinForms ButtonStandardAdapter.PaintWorker will give you some idea and API you need to use. Beware, you need to do lots of coding!
For C++/MFC code check out Vista themed Owner-Drawn and Full-Custom Push/Menu/Image Buttons on CodeProject. Which probably actually does, what you want already (the SetBackgroundColor method), so you might reuse it.

NSWindow keep in back of all windows/apps

So not really sure how to even google search this question... But, I'd like to make an NSWindow, reside in the back of all other windows/apps & I want it to be displayed on every Mission Control space (still in the back).
I've seen other applications that do this, so I know it's possible, just don't know how.
(I'm referring to Lion's function called Mission Control where you can switch through different spaces.)
Found the answer, there's a method/enum to make it so that the window will appear in all "spaces" (mission control).
[self.window setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
And a method to keep the window to the farthest back possible.
[self.window setLevel:kCGDesktopIconWindowLevelKey - 1];
All you have to do is use these two methods, and it'll do exactly what I requested. However, I wish there was a way to keep it from animating when coming down from Mission control (there is non to my knowledge).
You want to set the NSWindow's level and collectionBehavior properties.
The window level you'll want to use will depend on what behavior you're after from your window. You can find constants for the available window levels in CoreGraphics/CGWindowLevel.h. I'd suggest trying CGWindowLevelForKey(kCGDesktopIconWindowLevelKey) ± 1.
Which collection behavior you specify will also depend on what behavior you're after. The brief description in your question suggests that NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces may be a good starting point.

Colored iCal style checkboxes using Cocoa

Is there a way to get colored checkboxes like in iCal without using custom drawing?
I have looked through the documentation but can only find how to change the background and text color.
You can achieve something at least similar to the colored checkboxes in iCal by enabling Core Animation for the checkbox and adding a "Hue Adjust" (in "Color Adjustment") content filter. If the color is static, this can be done entirely within Interface Builder, no code needed.
Be careful, though, as sometimes enabling Core Animation for various views causes strange bugs (for example, WebViews don't play nice with Core Animation views).
If you want to do it programmatically, take a look at the documentation for CIFilter (that's a link), which you use with the NSView instance method setContentFilters: (also a link).
It's a bit dated (runs back on 10.3), but Matt Gemmell published a some code for doing colored checkboxes a few years back.
http://mattgemmell.com/source
Look for "iTableView."
I looked at the code when it was first available, but not since. There might be a better way to do it at this point.
I'm afraid not. I'm not sure if the AHIG forbids this sort of thing or not, (it probably does), but the reason iCal gets away with it is because, 'Hey! Why not?'. Also, it's an Apple application, so yeah.
It can still be done, of course, but not without custom drawing. Personally, I'd advise against it, and rather see if what you are trying to achieve could be achieved some other way. If not, you could possibly use some of the data files from iCal to build your checkbox. (Unsure of how kosher that would be, but 'Hey! Why not?'.)

Implementing "scrubby sliders" in Cocoa?

How would I go about implementing something along the lines of "scrubby sliders", like in Photoshop and quite a few other image-processing applications?
They are slightly hard to describe.. basically you have a regular numeric input-box, but you can click-and-hold the mouse button, and it functions like a slider (until you release). If you click in the box, you can select text, edit/paste/etc as usual.
The Photoshop docs describe it, and I put together a quick example video (an example of the sliders in Shake)
Another similar implementation would be the jog-wheel in Final Cut Pro, which functions similarly, without the numeric readout being underneath.
I can't seem to find any mention of implementing these, although there is probably alternative names for this. It is for a OS X 10.5 Cocoa application.
It is for a colour-grading application, where a user might need to make tiny adjustments (0.001, for example), to huge adjustments (say, -100 +100) on the same control. A regular slider isn't accurate enough over that range of value.
Copy-and-pasting values into the box would be a secondary concern to scrubbing the values, and the Photoshop/Shake setup really well. The unobviousness of the control is also of a low concern, as it's not a "regular desktop application"
I've encountered those. They suck, because they prevent the user from dragging to select the text of the number.
A better idea would be a miniature slider beneath the field that expands to a full-size slider when the user holds down the mouse button on it and collapses back to its miniature size when the user releases the mouse button. This way, the selection behavior is still available, but you also provide the slider—and in a more obvious way.
There's no built-in class in Cocoa for either one. You'll have to implement your own.
I doubt that this exists in Cocoa framework. As far as I remember it is not mentioned in the Apple Human Interface Guidelines.
You can develop one yourself by using a custom view and tracking mouse events (-mouseDown:, mouseUp:, -mouseDragged:).

Resources