I can use NSColorWell as button to change the color of selected text. Since NSColorWell is object of an NSControl it has target and action. I guess, the action is implementing the code to change the color of the selected text in NSTextView. Where can I find this code for NSColorWell action? I would like to change it in away that I can use NSColorWell to change the background of the selected text, and ultimately to have in ToolBar two NSColorWell buttons: one to change text's foreground color and second one for text's background color.
NSColorWell is just a rectangular control to change a color.
You can either create an IBAction and connect it to the action of the color well in the Connections Inspector (⌥⌘6) of Interface Builder
#IBAction func changeColor(_ sender : NSColorWell)
{
let color = sender.color
// do something with the color
}
Or bind the value in Bindings Inspector (⌥⌘7) of Interface Builder to a dynamic property, this example will set the color well to a default value of green.
dynamic var color : NSColor = .green {
didSet {
// do something with the color
}
}
Related
I created a basic NSTextView, I selected the following options in Interface Builder:
Editable
Selectable
Field Editor
Rich Text
Undo
Graphics
Non-contiguous Layout
Font Panel
Ruler
Inspector Bar
I set the NSViewController to be the delegate of the NSTextView and the only other custom thing I've done for this NSTextView is to enable inserting tabs and new lines (by accepting First responder):
func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if commandSelector == #selector(insertNewline(_:)) {
textView.insertNewlineIgnoringFieldEditor(self)
return true
} else if commandSelector == #selector(insertTab(_:)) {
textView.insertTabIgnoringFieldEditor(self)
return true
} //else if commandSelector == #selector(changeColor(_:)) {
//textView.setTextColor(NSFontPanel.colo, range: <#T##NSRange#>)
//}
return false
}
When I try to use the commands from the Font Panel + Inspector Bar, All the commands work fine except changing Font size or colour, is there anything that could be wrong? Or do I need to do extra binding/delegates, etc for this to work?
It is strange because if I change the Font itself (of a selected text) or the weight, it works fine (no coding was needed).
Update
I've found the root of the problem causing this. I'm displaying the TextView in a ViewController that is displayed using a Modal segue. If I change from Modal to Show, the size and colour work fine. There's also no need for the extra commands for insert new line and tab.
Is there any reason why this is the case? Is there any customisation that should be done to the segue to avoid this? And, why is the view controller presentation affecting the behaviour of the font panel?
NSFontPanel has a 'worksWhenModal' property which sounds as if it might be set to 'false'.
A Boolean that indicates whether the receiver allows fonts to be changed in modal windows and panels.
Documentation:
I am making an app which allows users to change the theme, eg. changing the background colour. Assuming I have a button, when click, toggles the change in background colour.
Eg. in code:
#IBAction func floodLightAction(sender: AnyObject) {
previousFloodlightOption = loadFloodlightOption()
if previousFloodlightOption {
print("OFF")
saveFloodlightOption(false)
// configure theme for themeViewController:
UIApplication.sharedApplication().statusBarStyle = .Default
setNeedsStatusBarAppearanceUpdate()
configureFloodlight(false)
} else {
print("ONN")
saveFloodlightOption(true)
// configure theme for themeViewController:
UIApplication.sharedApplication().statusBarStyle = .LightContent
setNeedsStatusBarAppearanceUpdate()
configureFloodlight(true)
}
However, setNeedsStatusBarAppearanceUpdate() does not seem to update the status bar style when the button is pressed. I have a few custom functions which are explained below.
My custom save func:
saveFloodlightOption(bool: Bool)
This saves a boolean value using NSUserDefaults.
My theme configuration func:
configureFloodLight(bool: Bool)
This just change objects' colour in the view controller based on the theme picked.
I hope I gave enough information, thanks!
Have you set View Controller Based Status bar appearance to false in your info.plist?
View Controller Based status bar appearance
I have setup a NSColorPanel which I use to change the background color of a window. In the window there is also a NSTextView with some text in. The problem is that is that when I change the color of the background, the text color gets changed to into the same. I've tried finding ways to prevent this but with no success.
Override the NSTextView changeColor: method and in that method, keep a outlet to the backgeoundView and instead of changing the textView's own color send it to the outlet:
IBOutlet NSView *changeColorTarget;
...
- (IBAction)changeColor:(id)sender {
if(self.changeColorTarget) {
[NSApp sendAction:#selector(changeColor:) target:self.changeColorTarget forEvent:nil];
} else {
[super changeColor:sender];
}
}
--> that way the textview retains its original functionality except if you set the outlet
I have an NSTableView in which I'm changing the colour of the text in a particular column, but when a row is selected, the text does not change to a more appropriate colour so that it's readable.
Finder's Date Modified, Size, and Kind columns have grey text, and when you select a file/folder row, the grey text changes to white (so that it's readable within the blue highlight).
I can't find a magic checkbox on XCode to enable this behaviour by default, so does anybody know how I might achieve the same effect?
I'm using Swift in XCode 6.3.
Thanks.
You don't say what view or view hierarchy you're using for your cells. You also don't say how or where you're setting the text fields' color or to what color, specifically.
When a row is selected, the row automatically computes its interiorBackgroundStyle. It also sets the backgroundStyle of the cell view if it responds to -setBackgroundStyle: or is an NSControl with a cell which responds to that.
If your cell view is an instance of NSTableCellView, it forwards the background style to all of its subviews which meet the same criteria. If you use a different container view as your cell view and you want the background style forwarded along like this, you would have to implement that yourself in your view class.
An NSTextField's cell (an NSTextFieldCell) responds to -setBackgroundStyle: and so has its background style set automatically by the above mechanisms. The text field cell will automatically change its text color to white if its textColor is one of the standard control colors (e.g. NSColor.controlTextColor()), but won't do so if you assign a non-standard color. So, if you're setting a specific color for your text, you are responsible for changing that when the background style changes.
You can use a subclass of NSTableCellView and add a property observer (didSet) for the backgroundStyle property. That can change the text field's textColor depending on the style that was set. For example, you can use your custom color if the background style is not .Dark or use the normal text field color NSColor.controlTextColor() if it is .Dark (so that the text field will actually display it as white).
You could also use a subclass of NSTextFieldCell for your text field and do the same sort of thing. Or override drawInteriorWithFrame(_:inView:) to draw with a different text color depending on the background style.
With the help of Ken's response (above) I was able to get it to work. Here's a rough draft that does what I want it to:
import Cocoa
class CustomTextFieldCell: NSTextFieldCell {
// When the background changes (as a result of selection/deselection) switch appropriate colours
override var backgroundStyle: NSBackgroundStyle {
didSet {
if (backgroundStyle == NSBackgroundStyle.Dark) {
if self.textColor == NSColor.redColor() {
self.textColor = NSColor.yellowColor()
}
} else if (backgroundStyle == NSBackgroundStyle.Light) {
if (self.textColor == NSColor.yellowColor()) {
self.textColor = NSColor.redColor()
}
}
}
}
// When the colour changes, switch to a better alternative for the cell's current background
override var textColor: NSColor? {
didSet {
if let colour = self.textColor {
if backgroundStyle == NSBackgroundStyle.Dark {
if self.textColor == NSColor.redColor() {
self.textColor = NSColor.yellowColor()
}
} else if backgroundStyle == NSBackgroundStyle.Light {
if (self.textColor == NSColor.yellowColor()) {
self.textColor = NSColor.redColor()
}
}
}
}
}
}
If I set my CustomTextFieldCell as the custom class for my table view cell in the identity inspector, it works. I needed to add a property observer for textColor as well so that rows which are currently highlighted get the same treatment. I may alter it now so that it's not hard coded but this demonstrates the concept.
Thanks Ken.
If you use system colors like NSColor.labelColor, the text color invertion will happen automatically for selected cells. If you want to use another color for unselected text, you can use code like this in your custom NSTableCellView class:
override var backgroundStyle: NSView.BackgroundStyle {
willSet {
textField.textColor = newValue == .emphasized ? .labelColor : .secondaryLabelColor
}
}
In this Swift example, the selected text color is .labelColor, otherwise it is .secondaryLabelColor.
I'm using a view-based table view and don't want it to draw NSTextFields with white text color when it is selected.
I was not able to find a working solution. So any help is very appreciated.
Here is my problem:
I want the "Selection is white" text also be drawn in the default text color.
So far I figured out that
Setting attributes in tableView:viewForTableColumn:item: does not really help
Setting NSTextField color to a custom color, which is something different than the control default color, will prevent from drawing in white but it still looses font style (bold, italic, etc).
Setting NSTableView's selectionHighlightStyle attribute to NSTableViewSelectionHighlightStyleNone does the trick but it will not redraw NSTableRowView. Also the select style is not what I want. I want the first click to select the row and the second click to edit the text field. When you use NSTableViewSelectionHighlightStyleNone your first click starts editing the text field.
The text color does not change if the NSTextField is bordered. But I don't want bordered text fields (As shown in the screenshot. The text fields are editable)
I couldn't figure out 'how' the text field gets the white color. I have overridden setTextColor: and realized that it is never called when selection is changed. So I guess an NSAttributedString is built somewhere inside the NSTableView drawing/selecting routine.
Any help is very much appreciated.
I found the answer. I had to subclass NSTableCellView and override setBackgroundStyle:. That's all!
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
[super setBackgroundStyle: NSBackgroundStyleLight];
}
Instead of overriding NSTableCellView's backgroundStyle, I found it more convenient to override viewWillDraw() in NSTableRowView instead. This is actually the method that by default changes your cell view's background style during selection.
You would disable this behavior by:
class TableViewDelegate: NSObject, NSTableViewDelegate {
func tableView(tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
return TableRowView(frame: NSRect.zero)
}
}
class TableRowView : NSTableRowView {
private override func viewWillDraw() {
// By do nothing we prevent the super method to be called. It would otherwise change the selected cell view's backgroundStyle property.
}
}
I set cell colour in my table view delegate's -tableView:willDisplayCell:forTableColumn:row: method.
-(void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if(tableView==<table view id of interest>)
{
...
[cell setTextColor:<colour appropriate for this cell>];
...
}
...
}
This does not affect font size or styling.