macOS: Adjust stroke color of VLCHUDTextFieldCell
[vlc.git] / modules / gui / macosx / VLCHUDTextFieldCell.m
1 //
2 //  VLCHUDTextFieldCell.m
3 //  BGHUDAppKit
4 //
5 //  Created by BinaryGod on 6/2/08.
6 //
7 //              Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
8 //  All rights reserved.
9 //
10 //              Redistribution and use in source and binary forms, with or without modification,
11 //  are permitted provided that the following conditions are met:
12 //
13 //              Redistributions of source code must retain the above copyright notice, this
14 //      list of conditions and the following disclaimer.
15 //
16 //              Redistributions in binary form must reproduce the above copyright notice,
17 //      this list of conditions and the following disclaimer in the documentation and/or
18 //      other materials provided with the distribution.
19 //
20 //              Neither the name of the BinaryMethod.com nor the names of its contributors
21 //      may be used to endorse or promote products derived from this software without
22 //      specific prior written permission.
23 //
24 //      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
25 //      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 //      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 //      IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 //      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 //      BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
30 //      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 //      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 //      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 //      POSSIBILITY OF SUCH DAMAGE.
34 //
35 //  History
36 //
37 //              8/30/2010 - Fixed placeholder alignment not rendering while in design view,
38 //                                      provided by [tylerb](GitHub).
39
40 #import "VLCHUDTextFieldCell.h"
41 #import "CompatibilityFixes.h"
42
43 @interface NSTextFieldCell (Private)
44
45 - (void)_drawKeyboardFocusRingWithFrame:(NSRect)rect inView:(NSView*)view;
46
47 @end
48
49 @interface VLCHUDTextFieldCell () {
50     bool fillsBackground;
51 }
52
53 @end
54
55 @implementation VLCHUDTextFieldCell
56
57 #pragma mark Drawing Functions
58
59 - (instancetype)initTextCell:(NSString *)aString
60 {
61     self = [super initTextCell: aString];
62
63     if (self) {
64         [self commonInit];
65     }
66
67     return self;
68 }
69
70 - (instancetype)initWithCoder:(NSCoder *)decoder
71 {
72     self = [super initWithCoder:decoder];
73
74     if (self) {
75         [self commonInit];
76     }
77
78     return self;
79 }
80
81 - (void)commonInit
82 {
83     if (OSX_YOSEMITE_AND_HIGHER) {
84         return;
85     }
86
87     // Init colors
88     _focusRing = [[NSShadow alloc] init];
89     [_focusRing setShadowColor:NSColor.whiteColor];
90     [_focusRing setShadowBlurRadius:3];
91     [_focusRing setShadowOffset:NSMakeSize(0, 0)];
92
93     _strokeColor = [NSColor colorWithDeviceRed:0.749f green:0.761f blue:0.788f alpha:1.0f];
94     _disabledStrokeColor = [NSColor colorWithDeviceRed:1 green:1 blue:1 alpha:0.2f];
95
96     _selectionHighlightActiveColor = [NSColor darkGrayColor];
97     _selectionTextActiveColor = [NSColor whiteColor];
98     _selectionHighlightInActiveColor = [NSColor darkGrayColor];
99     _selectionTextInActiveColor = [NSColor whiteColor];
100
101     _placeholderTextColor = [NSColor grayColor];
102     _cellTextColor = [NSColor whiteColor];
103     _textFillColor = [NSColor colorWithDeviceRed:.224f green:.224f blue:.224f alpha:.95f];
104
105     // Init some properties
106     [self setTextColor:_cellTextColor];
107
108     if ([self drawsBackground]) {
109         fillsBackground = YES;
110     }
111
112     [self setDrawsBackground: NO];
113 }
114
115 - (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
116 {
117     if (OSX_YOSEMITE_AND_HIGHER) {
118         return [super setUpFieldEditorAttributes:textObj];
119     }
120
121     NSText *newText = [super setUpFieldEditorAttributes:textObj];
122     NSColor *textColor = _cellTextColor;
123     [(NSTextView *)newText setInsertionPointColor:textColor];
124     return newText;
125 }
126
127 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
128 {
129     if (OSX_YOSEMITE_AND_HIGHER) {
130         return [super drawWithFrame:cellFrame inView:controlView];
131     }
132
133     // Adjust Rect
134     cellFrame = NSInsetRect(cellFrame, 0.5f, 0.5f);
135
136     // Create Path
137     NSBezierPath *path = [NSBezierPath bezierPath];
138
139     if ([self bezelStyle] == NSTextFieldRoundedBezel) {
140
141         [path appendBezierPathWithArcWithCenter:NSMakePoint(cellFrame.origin.x + (cellFrame.size.height /2), cellFrame.origin.y + (cellFrame.size.height /2))
142                                          radius:cellFrame.size.height /2
143                                      startAngle:90
144                                        endAngle:270];
145
146         [path appendBezierPathWithArcWithCenter:NSMakePoint(cellFrame.origin.x + (cellFrame.size.width - (cellFrame.size.height /2)), cellFrame.origin.y + (cellFrame.size.height /2))
147                                          radius:cellFrame.size.height /2
148                                      startAngle:270
149                                        endAngle:90];
150
151         [path closePath];
152
153     } else {
154         [path appendBezierPathWithRoundedRect: cellFrame xRadius: 3.0f yRadius: 3.0f];
155     }
156
157     // Draw Background
158     if (fillsBackground) {
159         [_textFillColor set];
160         [path fill];
161     }
162
163     if ([self isBezeled] || [self isBordered]) {
164
165         [NSGraphicsContext saveGraphicsState];
166
167         if ([super showsFirstResponder] && [[[self controlView] window] isKeyWindow] &&
168            ([self focusRingType] == NSFocusRingTypeDefault ||
169             [self focusRingType] == NSFocusRingTypeExterior)) {
170                [_focusRing set];
171            }
172
173         // Check State
174         if ([self isEnabled]) {
175             [_strokeColor set];
176         } else {
177             [_disabledStrokeColor set];
178         }
179
180         [path setLineWidth:1.0f];
181         [path stroke];
182
183         [NSGraphicsContext restoreGraphicsState];
184     }
185
186     // Get TextView for this editor
187     NSTextView* view = (NSTextView*)[[controlView window] fieldEditor: NO forObject: controlView];
188
189     // If window/app is active draw the highlight/text in active colors
190     if (![self isHighlighted]) {
191
192         if ([view selectedRange].length > 0) {
193
194             // Get Attributes of the selected text
195             NSMutableDictionary *dict = [[view selectedTextAttributes] mutableCopy];
196
197             if ([[[self controlView] window] isKeyWindow]) {
198                 [dict setObject:_selectionHighlightActiveColor
199                          forKey:NSBackgroundColorAttributeName];
200
201                 [view setTextColor:_selectionTextActiveColor
202                              range:[view selectedRange]];
203             } else {
204                 [dict setObject:_selectionHighlightInActiveColor
205                          forKey:NSBackgroundColorAttributeName];
206
207                 [view setTextColor:_selectionTextInActiveColor
208                              range:[view selectedRange]];
209             }
210
211             [view setSelectedTextAttributes:dict];
212         } else {
213             // Only change color (marks view as dirty) if it had a selection at some point,
214             // thus changing the colors.
215             if ([view textColor] != _cellTextColor) {
216                 [self setTextColor:_cellTextColor];
217                 [view setTextColor:_cellTextColor];
218             }
219         }
220     } else {
221
222         if ([self isEnabled]) {
223             if ([self isHighlighted]) {
224                 if ([[[self controlView] window] isKeyWindow]){
225                     [self setTextColor:_selectionTextActiveColor];
226                 } else {
227                     [self setTextColor:_selectionTextInActiveColor];
228                 }
229             } else {
230                 [self setTextColor:_cellTextColor];
231             }
232         } else {
233             [self setTextColor:_disabledCellTextColor];
234         }
235     }
236
237     // Check to see if the attributed placeholder has been set or not
238     if (![self placeholderAttributedString] && [self placeholderString]) {
239
240         NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
241
242         // Set the paragraph style
243         [style setAlignment: [self alignment]];
244
245         // Attributed string doesn't exist lets create it
246         NSDictionary *attributes = @{
247                                      NSForegroundColorAttributeName : _placeholderTextColor,
248                                      NSParagraphStyleAttributeName  : style
249                                      };
250         NSAttributedString *attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholderString attributes:attributes];
251         [self setPlaceholderAttributedString:attributedPlaceholder];
252     } else if ([self placeholderAttributedString] && [[self placeholderAttributedString] length] > 0) {
253
254         // Check to see if the proper styles have been applied
255         if ([[[self placeholderAttributedString] attribute:NSParagraphStyleAttributeName atIndex:1 effectiveRange:nil] alignment] != [self alignment]) {
256
257             NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
258
259             // Set the paragraph style
260             [style setAlignment:[self alignment]];
261             
262             // Get current attr string
263             NSMutableAttributedString *adjPlaceholder = [[NSMutableAttributedString alloc] initWithAttributedString:[self placeholderAttributedString]];
264             
265             // Add style attr
266             [adjPlaceholder addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, [adjPlaceholder length])];
267             
268             // Reset Placeholder to correct placeholder
269             [self setPlaceholderAttributedString:adjPlaceholder];
270         }
271     }
272     
273     // Adjust Frame so Text Draws correctly
274     switch (self.controlSize) {
275         case NSRegularControlSize:
276             cellFrame.origin.y += (self.bezelStyle != NSTextFieldRoundedBezel) ? 1 : 0;
277             break;
278             
279         case NSSmallControlSize:
280             cellFrame.origin.y += (self.bezelStyle == NSTextFieldRoundedBezel) ? 1 : 0;
281             break;
282             
283         case NSMiniControlSize:
284             cellFrame.origin.x += (self.bezelStyle == NSTextFieldRoundedBezel) ? 1 : 0;
285             break;
286             
287         default:
288             break;
289     }
290
291     [self drawInteriorWithFrame: cellFrame inView: controlView];
292 }
293
294 - (void)_drawKeyboardFocusRingWithFrame:(NSRect)rect inView:(NSView*)view
295 {
296     if (OSX_YOSEMITE_AND_HIGHER) {
297         if ([super respondsToSelector:@selector(_drawKeyboardFocusRingWithFrame:inView:)]) {
298             [super _drawKeyboardFocusRingWithFrame:rect inView:view];
299         }
300     }
301
302     // Do nothing
303 }
304
305 @end