Custom NSControl of AppKit/Cocoa emulating style - macos

I am developing a custom slider to support color selection functionality.
This is a screenshot of the current development so far:
The background coloring is very flexible and also offers to use the standard background coloring as implemented in NSSlider using system colors.
The implementation is realized by overriding a NSView rather than NSSlider, since I also want to support flexible sizes of the cells:
I am currently struggling with the shadowing of the knobs. The color sliders should be positioned right next to standard NSSliders. However, if I am not carefully replicated the shadow style of the standard NSSlider, it will look a bit awkward.
Is there any documentation on how the shadow styles (radius, offset, opacity, etc) in the standard controls are designed?

To put it simply: nope.
The control styles are always subject to change, and have never ever been documented. They are what they are and it's up to you to figure it out and mimic them if you need to.

Related

What's the relationship between NSAppearance, NSEffectView.Material, and "Vibrancy"

As in the question title, what's the relationship between NSAppearance, NSEffectView.Material, and "vibrancy"? I've found through experimentation that, for some materials, the choice of NSAppearance can change how the material appears (e.g. NSEffectView.Material.titlebar will be light or dark depending on the active NSAppearance), while other materials (e.g. .light) don't seem to care.
I suspect that materials like .titlebar are proxies which select from .dark, .ultradark, .light, and .mediumLight depending on the NSAppearance, but then that would seem to be the role of .appearanceBased. I also see in the description for NSAppearance.Name.vibrantLight...
This should only be set on an NSVisualEffectView or one of its subviews.
...which somewhat contradicts a statement from the NSEffectView documentation...
The view’s effective appearance must allow vibrancy... in most cases you set the appearance on the window or on the visual effect view—subviews then inherit the appearance.
...suggesting that it could be correct to set vibrantLight as the NSAppearance of an entire window (if that's the look you wanted).
Finally, I'm confused as to what exactly "vibrancy" is; if someone could explain it, that would be great.
So an NSAppearance generally describes the styling of controls, colors, etc for a view hierarchy that the appearance is set against.
NSVisualEffectView provides a way to achieve two effects: translucency and vibrancy. The former is the more obvious, with the translucent sidebars or titlebars. And the documentation has a really nice description of vibrancy:
Vibrancy is associated with translucency. It describes a compositing mode that does special blending such as Plus Lighter, Plus Darker, Color Dodge, or Color Burn.
Basically describing how the content (text, images, etc) within the visual effect view are composited against the translucency.
So how do these all relate?
Material
Material describes the look of the translucency effect. As you pointed out, some are affected by NSAppearance, some are not. The ones that are semantically describe their usage so that custom UI can resemble that effect regardless of appearance (.appearanceBased, .titlebar, .menu, .popover, .sidebar, .selection) whereas others allow for specific control over the resulting translucency (.light, .dark, .mediumLight, .ultraDark) but should be used in conjunction with their associated NSAppearance so that the content within the visual effect view can match the translucency effect. Unless you need specific control over the material, using appearance-sensitive / semantic ones can result for more standard UI.
Vibrancy
So in order to get the content vibrancy effects that NSVisualEffectView can provide, it needs to be used in conjunction with a vibrant appearance: .vibrantLight or .vibrantDark. Without setting a "vibrant" appearance, NSVisualEffectView will only provide the translucency effect in the background, and the content within it will look plain and not have the special blending modes like you see in sidebars or titlebars.

How to Add Disclosure Triangle to Gradient Button?

I have a Gradient Button with the NSAction template. In Apple's apps, this is almost never the way in which configuration options are represented. Rather, the NSAction glyph is used in conjunction with the Disclosure Triangle glyph, in the same Gradient Button. For instance, in System Preferences > Network:
I can't figure out how to add the Disclosure Triangle glyph. How would I do this?
Also, yes, I have already seen this answer. I want to know if there is any official capacity in which to do this, either using Interface Builder, or programmatically with Swift, as is recommended by the Apple Human Interface Guidelines:
When possible, use system-provided images, such as the Action and the Add images, because their meaning is familiar to users.
It should work to just set the type to Pull Down while the style is set to Gradient:

JavaFX - How to create simple custom drawed controls?

I've got the task to program a graphical network editor application as a university project. For that I need three types of items/controls. A circle shape, a rectangular shape and arrows to connect the other shapes (the whole thing works somewhat like MS Visio in some ways). The shapes/controls need some additional features like moving, scaling a context menu etc. Also I need to have full control over the graphical representation of these objects i.e. I want to 'draw' them myself or at least be able to modify them as I need.
I am using JavaFX and have little to no experience with it. So I was wondering, what would be the best way to implement these custom controls. It is required to use JDK 7, so using SkinBase and BehaviourBase is not an option, since they are private before JDK 8.
I was thinking about subclassing Path or Canvas to use as my controls. But I know too little about the implications to make an informed decision.
Could someone give me some advice, which base classes to consider and what implications that might have?
Thx alot.
This answer is just going to be advice, there is no real right or wrong answer here. Advice is necessarily opinionated and not applicable to all situations, if you don't agree with it, or it doesn't apply to your situation, just ignore it.
Sorry for the length, but the question is open-ended and the potential answer is complicated.
I was thinking about subclassing Path or Canvas to use as my controls.
Don't. Favor composition over inheritance. Have a control class which implements the functional interface of the control and works regardless of whatever UI technology is behind it. Provide the control class a reference to a skin class which is the UI representation of the control. The skin will specify how to render the control in a given state (getting the control state from the associated control object). Also, the skin will be the thing which responds to user manipulations, such as a mouse presses and instructs the control to change its state based upon the mouse press - so the skin knows what control it is associated with and vice versa. In the control class have bindable properties to represent the control state.
A simple example of this is the Square and SquareSkin from this tic-tac-toe game implementation.
For example, imagine a checkbox control. The bindable property of control might be an enum with states of (checked, unchecked, undetermined). A skin might render the checkbox as a square box with a tick mark to represent the checked state. Or maybe the skin will render a rounded edge with an X. The skin could use whatever technology you want to render the checkbox, e.g. a canvas or a collection of nodes. The skin registers listeners for mouse clicks, key presses, etc. and tells the checkbox control to set its check state. It also has a listener on the check state and will choose whether to render the check tick based on that state.
The key thing is that the API interface to the checkbox is just a checkbox control class with a check state. The way the UI is handled is abstracted away from the checkbox API, so you can swap the UI implementation in and out however you want without changing any other code.
Subclassing Path is quite different from subclassing Canvas. For the situation subscribe, I would definitely favor subclassing a Shape node (or Region) as opposed to a Canvas. Using Nodes, you automatically have a really rich UI rendering and event model, bindable property set and and painting framework which you won't get with a Canvas. If you don't use Nodes, you will likely end up trying to re-create and build some parts of the Node functionality in some sub-standard way. Canvas is great for things like porting 2D games or graphing engines from other frameworks or building things that are pixel manipulators like a particle system, but otherwise avoid it.
Consider using a Layout Pane for your control skin, e.g. a StackPane or something like that. The layout panes are containers, so you can place stuff inside them and use aggregation and composition to build up more complex controls. Layout panes can also help with laying out your nodes.
Anything which subclasses a region like a Pane can be styled via CSS into arbitrary shapes and colors. This is actually how the in-built checkbox (and other controls) in JavaFX work. The checkbox is a stack of two regions, one the box and the other the check. Both are styled in CSS - search for .check-box in the modena.css stylesheet for JavaFX. Note how -fx-shape is used to get the tick shape by specifying an svg path (which you can create in an svg editor such as inkscape). Also note how background layering is used to get things like focus rings. The advantage of using CSS for style is that you can stylistically change your controls without touching your Java code.
so using SkinBase and BehaviourBase is not an option
Even though you have decided to not use these base classes (which I think is an OK decision even if you are targeting only Java 8+), I think it is worthwhile studying the design of the controls in JavaFX source. Study button or checkbox, so you can see how the experts do these kind of things. Also note that such implementations may be overkill for your application because you aren't building a reusable control library. You just need something which will work well and simply within the confines of your application (this is the reason I don't necessarily recommend extending SkinBase for all applications).
As a minimum read up on Controls on the open-jfx wiki.
It is required to use JDK 7
IMO, there is not much point in developing a new JavaFX application to target Java 7. There were many bug fixes for Java 8, plus new and useful features added. In general, Java 7 is a sub-optimal target platform for JavaFX applications. If you package your application as a self-contained application, then you can ship whatever Java platform you want with your application, so the target platform doesn't matter.
IMO deployment technologies such as WebStart or browser embedded applications (applets), which can make use of pre-installed java runtimes on a system, are legacy deployment modes which are best avoided for most applications.
Still, there might be a situation where you absolutely must have Java 7 due to some constraints outside your control, so I guess just evaluate carefully against your situation. If you have such constraints and must build on a stable, legacy UI toolkit which works with runtimes released years ago, you could always use Swing.
From oracle, the Path class represents a simple shape and provides facilities required for basic construction and management of a geometric path while Canvas is an image that can be drawn on using a set of graphics commands provided by a GraphicsContext.
Which means the user can use canvas to draw the required shapes as the user wants.
On of the basic ways I can say would be as follows:
Use canvas as it will help and allow for custom user "drawing". Creating menu buttons for the circles, rectangles, arrows etc. like in MS Paint. Onclick drag function on the canvas can be used for "drawing".
Circle and Rectangle are available in the libraries which you can use
You can use arrows like the way used here.
I think its the same example as you want to create.
Custom controllers and context menus can be created too docs.oracle.com
Scaling and Moving can be done by binding drag function to a scale
or translate animation. Mousepressed and Mousereleased can be used to track the coords to draw the shape in.
This is my advice, you can use the control prototype.Or an application or design tool which can provide you the targeted control or a icon with circle shape, a rectangular shape and arrows. I don't know how my advice work. You can try it.

Windows Vista/7 glass completely broken?

I'm trying to get the media player glass effect for an application, but I'm facing roadblocks all around. Is it me, or is it the API?
I started by calling:
MARGINS margins = { -1, -1, -1, -1 };
HRESULT result = ::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
And erasing the background to black on:
OnEraseBkgnd
Everything was fine until I added an edit box. With EditBox, places where black text appears are replaced with glass. The problem is blown out of proportion with more advanced controls like ComboBoxEx and that like. Those start to look like mess.
The bright side with this approach is that the alpha blended images look alright. And are gradually blended into the glass.
The solution for edit boxes seems to be using WS_EX_LAYERED with LWA_COLORKEY and using some awful color for glass masking, and erasing the background to that color. Unfortunately this breaks other things. The alpha blending on icons looks super ugly with shadows blended to radioactive green, and the glass itself becomes click-throughable, even though I don't have a WS_EX_TRANSPARENT style on the window.
The third suggestion is sort of custom composition with GDI+, but that seems to be a bad approach, since GDI+ is a software fallback, and I can't find a way how to render EditBox or ComboBoxEx to an image that I could use for composition later.
Am I missing something?
The sources at SO also seem to face the same problems:
link1
link2
Kenny Kerr wrote an excellent article on displaying controls on glass, using edit controls as an example:
http://weblogs.asp.net/kennykerr/archive/2007/01/23/controls-and-the-desktop-window-manager.aspx
The simple answer is, you cannot do this.
All the standard controls render themselves with normal GDI calls. Normal GDI calls are alpha unaware and mostly set the alpha channel to zero.
The more complicated answer is, you can: There are some samples on the net where standard controls are mixed with aero glass. They fall into two basic categories:
WinForms (.NET) samples. WinForms don't actually use the native controls - the WinForms controls are all rewritten versions that, amongst other features, blit using alpha aware routines. This example is depressingly simple and makes me realize how much Microsoft hate native developers.
Subclassed samples: The only way to get the regular/native controls to paint on aero glass is to sublclass the controls, catch WM_PAINT messages to create a DIBBitmap, call WM_PRINT to render the controls content onto it. Use the DWM functions to repair the alpha channel data. Paint the resulting alpha'd bitap yourself using AlphaBlend.
This article on CodeProject contains a reference implementation that subclasses most of the standard controls rather well.
Try changing your text/foreground color on controls like the edit box to something "almost black" (like #010101). Then you should be able to skip the other rendering issues except alpha transparency for images/icons.
Edit: Drawing other stuff - might be some weird approaches to handle compatibility, but then again classic apps aren't glass themed by default ... don't know. Just try to avoid drawing stuff yourself, if possible.

Glow around Button

How can I draw a slight white 'glow' around a button or label in 10.5 and later? I have seen some apps do it, but I am still confused how I should do this.
See NSShadow. You'd create and set a shadow (saving your graphics context beforehand), then draw the basic shape of your button, unset it (by restoring your graphics context), then continue drawing as usual.
In the case of a ready-made control like NSButton, you will need to subclass and override its cell drawing (and possibly make the host NSButton control itself a bit larger to accommodate the larger area needed to encompass the "glow" of the cell).
You might be able to avoid this with a label by setting its font shadow, but I don't think IB lets you do this, so you'd programmatically give the label an attributed string (via its -setAttributedString: method). The attributes would include the NSShadow (configured as desired) as the NSShadowAttributeName.

Resources