Changing the color of NSProgressIndicator? - objective-c

What is the best way to change the color of NSProgressIndicator, is there an easier way than just to subclass it and then draw the whole component by myself?
Basically what I want to do is to have a similar component but with the ability to change the color of the bar.
I tried to google this but all the questions were quite outdated and didn't really concern the 10.10 OS X version that I am working on. Also checked cocoa controls and did only find 1 component that was for outdated OS X version.

You can use Quartz filters (e.g. hue adjust) for this directly in Interface Builder. This works better than expected.
It's in the Effects Inspector. Under "Content Filters" you can add "Hue Adjust"

Use "CIFalseColor" filter to get white color and more.
let colorFilter = CIFilter(name: "CIFalseColor")!
colorFilter.setDefaults()
colorFilter.setValue(color1, forKey: "inputColor0")
colorFilter.setValue(color2, forKey: "inputColor1")
proggressBar?.contentFilters = [colorFilter]

To change color of NSProgressIndicator use setControlTint: method. If you want to set custom color you have to draw such control manually. However, you should use the system color to keep this kind of control consistent across the system.

For Swift the method name is controlTint.
progressIndicator = NSProgressIndicator(frame: .......
progressIndicator.controlTint = .blueControlTint

you can use proggressBar.appearance = NSAppearance(named: .vibrantLight) // this is light or vibrantDark for "black" indictor

Based on Paxos' answer on the Interface builder, this is how I was able to do it programmatically:
let progress = NSProgressIndicator()
progress.contentFilters = [CIFilter(name: "CIHueAdjust", parameters: ["inputAngle": 4])!]
This would turn the bar green. I got this from looking at the Main.storyboard diff:
<progressIndicator maxValue="100" doubleValue="50" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="NIr-vo-obX">
<rect key="frame" x="3" y="22" width="210" height="20"/>
+ <contentFilters>
+ <ciFilter name="CIHueAdjust">
+ <configuration>
+ <real key="inputAngle" value="4"/>
+ <null key="inputImage"/>
+ </configuration>
+ </ciFilter>
+ </contentFilters>
</progressIndicator>

I was trying to change de Hue as seen in most answers, but I was getting a lot of issues to get the right specific color I wanted.
What did worked for me, and seems to be the most direct way to get a specific color, was using the CIColorMonochrome filter, where You can set any RGB color you want:
let myCustomColor: CIColor(red: 10, green: 10, blue: 10)
if let colorMonochrome = CIFilter(name: "CIColorMonochrome", parameters: [kCIInputColorKey: myCustomColor]) {
progressIndicator.contentFilters.append(colorMonochrome)
}

Based on the answer from KamyFC I found out that CIColor was required for the filter named "CIFalseColor".
Here is the Objective-C solution to make the progress bar whatever NSColor, in this example orange.
Don't forget to add #import Quartz; to your file.
// Create color:
CIColor *color = [[CIColor alloc] initWithColor:[NSColor orangeColor]];
// Create filter:
CIFilter *colorFilter = [CIFilter filterWithName:#"CIFalseColor"
withInputParameters:#{#"inputColor0" : color,
#"inputColor1" : color}];
// Assign to bar:
_progressBar.contentFilters = #[colorFilter];

Related

NSTextBlock backgroundColor is not drawn

I have an NSTextBlock subclass that has a specific backgroundColor set. Now when I add a custom paragraph style to a range of text like this
let block = MyTextBlock()
block.backgroundColor = myBackgroundColor
let pstyle = NSMutableParagraphStyle()
pstyle.textBlocks = [block]
attributedText.addAttribute(.paragraphStyle, value: pstyle, range: textRange)
// Append the attributed string to the text views textStorage ...
the text block is shown without a background color. I know that the text blocks works, because rectForLayout gets called, but when I try to override drawBackground it never gets called.
Do I have to do something else for NSTextBlocks to draw their background?
PS: Borders also seem to be ignored. I also tried to find a sample on Github, but that also doesn't draw any backgrounds, despite having a background color set.
After trying everything, I finally managed to get the background to show up, by setting
setValue(100, type: .percentageValueType, for: .width)
It seems that the drawing logic expects some value for the content size. Really nice documentation job there. This requirement is nowhere to be found.

CreateJs Drawing with alpha

I implemented a little drawing function into my app with CreateJS like so:
var currentPosition = this.posOnStage(event);
var drawing = container.getChildByName('drawing');
drawing.graphics.ss(this.brushSize, "round").s(this.brushColor);
drawing.graphics.mt(this._lastMousePosition.x, this._lastMousePosition.y);
drawing.graphics.lt(currentPosition.x, currentPosition.y);
drawing.alpha = this.brushAlpha;
container.updateCache(this.enableErasing ? "destination-out" : "source-over");
drawing.graphics.clear();
this._lastMousePosition = this.posOnStage(event);
As you can see, the alpha value of this drawing can change. Sadly you can draw over a point you once did draw, so when you draw over a point multiple times the alpha effect will go away. Any idea how to solve this ?
Thanks :)
EDIT:
I tried it like gskinner and Lanny 7 proposed, but it didn't work. I attached a image so you can see the problem.
As suggested by Lanny, apply the alpha to the actual stroke, not to the Shape. You can use Graphics methods to help with this.
For example:
// set the brush color to red with the current brush alpha:
this.brushColor = createjs.Graphics.getRGB(255, 0, 0, this.brushAlpha);

SpriteKit displaying variable number

What is the best way to display some value (that changes as the game runs) on the screen in iPhone SpriteKit? The only way I can think of is SKLabelNode, but it's probably not meant to be used like this and also I can't find any way to measure its width, which makes me unable to position it correctly (I want it to be in the bottom right corner). Thanks in advance :).
#Edit
My attempt at doing this:
SKLabelNode *someLabel = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
someLabel.text = some_string;
someLabel.fontSize = 30;
someLabel.fontColor = [SKColor blackColor];
someLabel.position = CGPointMake(some_int, 15);
[self addChild:someLabel];
The values of some_string and some_int change as the game runs, so someLabel is removed, someLabel.text and someLabel.position are re-assigned, and the label is added again. Yes, I am aware that this is a bad way to do this...
Unfortunately, SKLabelNode is your simplest bet, it's just not the most robust tool.
You just want to update its text and its position when you need to. Your code is correct, and if you want to get its actual size, then you would get the width of its frame.
update text:
someLabel.text = theNewText;
update position:
someLabel.position = theNewPosition;
get relative width
float widthOfLabelFrame = someLabel.frame.size.width;
additional alignment settings that might help (vertical baseline is the default):
someLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
someLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeBaseline;

monotouch dialog cell sizing and section caption color

I am using monotouch dialog to generate a view. I managed to change the background color by subclassing DialogViewController, but the contrast with the section caption makes the text hard to read. How do I change the section caption color?
I am also using a StyledStringElement as a button in the same view. I cant seem to figure out how to shrink this element so that it looks more like a button. Please provide examples. Your help is appreciated.
To solve this issue I used a glassbutton with the it's HandleTapped handler as below.
var butt = new GlassButton(new RectangleF(80,150,150,50))
{
Font = UIFont.BoldSystemFontOfSize(22),
NormalColor = UIColor.Red,
};
void HandleTapped (GlassButton obj)
{
}
as for the colors, I used miguel's solution here. Hope this helps someone down the road.

Zooming in an NSView

I have an NSView in which the user can draw circles. These circles are stored as an array of NSBezierPaths, and in drawRect:, I loop through the array and call -stroke on each of the paths. How do I add a button to zoom in and out the NSView? Just change the bounds of the view?
Thanks.
Send your view a scaleUnitSquareToSize: message.
You might also find this informative:
https://developer.apple.com/library/content/qa/qa1346/_index.html
The code in that document lets you add a "scale" property to a view.
The above answers didn't work for my scenario but led me to a solution.
The updated link to #Peter's answer was helpful: scaleUnitSquareToSize
I have found two soultions for zooming:
Cropping the bounds manually
Scalling the bounds with scaleUnitSquareToSize
I have created a small test project. Both solutions can be found on my GitHub repo : BoundsAndFramesCroppingAndScalling
To understand bounds vs frames read this SO article: difference-between-the-frame-and-the-bounds.
Swift scalling code:
let scaleSize = NSSize(width: 0.5, height: 0.5)
// 0.5 - Half the size
// 1.0 - No calling
// 2.0 - double the size , ... etc
myView?.scaleUnitSquare(to: scaleSize)
myView?.needsDisplay = true