macOS: Do not draw custom VLCHUDTextFieldCell on 10.10+
[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:0.749f green:0.761f blue:0.788f alpha:0.2f];
95     _selectionHighlightActiveColor = [NSColor darkGrayColor];
96     _selectionTextActiveColor = [NSColor whiteColor];
97     _selectionHighlightInActiveColor = [NSColor darkGrayColor];
98     _selectionTextInActiveColor = [NSColor whiteColor];
99     _placeholderTextColor = [NSColor grayColor];
100     _cellTextColor = [NSColor whiteColor];
101     _disabledStrokeColor = [NSColor colorWithDeviceRed:1 green:1 blue:1 alpha:0.2f];
102     _textFillColor = [NSColor colorWithDeviceRed:.224f green:.224f blue:.224f alpha:.95f];
103
104     // Init some properties
105     [self setTextColor:_cellTextColor];
106
107     if ([self drawsBackground]) {
108         fillsBackground = YES;
109     }
110
111     [self setDrawsBackground: NO];
112 }
113
114 - (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
115 {
116     if (OSX_YOSEMITE_AND_HIGHER) {
117         return [super setUpFieldEditorAttributes:textObj];
118     }
119
120     NSText *newText = [super setUpFieldEditorAttributes:textObj];
121     NSColor *textColor = _cellTextColor;
122     [(NSTextView *)newText setInsertionPointColor:textColor];
123     return newText;
124 }
125
126 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
127 {
128     if (OSX_YOSEMITE_AND_HIGHER) {
129         return [super drawWithFrame:cellFrame inView:controlView];
130     }
131
132     // Adjust Rect
133     cellFrame = NSInsetRect(cellFrame, 0.5f, 0.5f);
134
135     // Create Path
136     NSBezierPath *path = [NSBezierPath bezierPath];
137
138     if ([self bezelStyle] == NSTextFieldRoundedBezel) {
139
140         [path appendBezierPathWithArcWithCenter:NSMakePoint(cellFrame.origin.x + (cellFrame.size.height /2), cellFrame.origin.y + (cellFrame.size.height /2))
141                                          radius:cellFrame.size.height /2
142                                      startAngle:90
143                                        endAngle:270];
144
145         [path appendBezierPathWithArcWithCenter:NSMakePoint(cellFrame.origin.x + (cellFrame.size.width - (cellFrame.size.height /2)), cellFrame.origin.y + (cellFrame.size.height /2))
146                                          radius:cellFrame.size.height /2
147                                      startAngle:270
148                                        endAngle:90];
149
150         [path closePath];
151
152     } else {
153         [path appendBezierPathWithRoundedRect: cellFrame xRadius: 3.0f yRadius: 3.0f];
154     }
155
156     // Draw Background
157     if (fillsBackground) {
158         [_textFillColor set];
159         [path fill];
160     }
161
162     if ([self isBezeled] || [self isBordered]) {
163
164         [NSGraphicsContext saveGraphicsState];
165
166         if ([super showsFirstResponder] && [[[self controlView] window] isKeyWindow] &&
167            ([self focusRingType] == NSFocusRingTypeDefault ||
168             [self focusRingType] == NSFocusRingTypeExterior)) {
169                [_focusRing set];
170            }
171
172         // Check State
173         if ([self isEnabled]) {
174             [_strokeColor set];
175         } else {
176             [_disabledStrokeColor set];
177         }
178
179         [path setLineWidth:1.0f];
180         [path stroke];
181
182         [NSGraphicsContext restoreGraphicsState];
183     }
184
185     // Get TextView for this editor
186     NSTextView* view = (NSTextView*)[[controlView window] fieldEditor: NO forObject: controlView];
187
188     // If window/app is active draw the highlight/text in active colors
189     if (![self isHighlighted]) {
190
191         if ([view selectedRange].length > 0) {
192
193             // Get Attributes of the selected text
194             NSMutableDictionary *dict = [[view selectedTextAttributes] mutableCopy];
195
196             if ([[[self controlView] window] isKeyWindow]) {
197                 [dict setObject:_selectionHighlightActiveColor
198                          forKey:NSBackgroundColorAttributeName];
199
200                 [view setTextColor:_selectionTextActiveColor
201                              range:[view selectedRange]];
202             } else {
203                 [dict setObject:_selectionHighlightInActiveColor
204                          forKey:NSBackgroundColorAttributeName];
205
206                 [view setTextColor:_selectionTextInActiveColor
207                              range:[view selectedRange]];
208             }
209
210             [view setSelectedTextAttributes:dict];
211         } else {
212             // Only change color (marks view as dirty) if it had a selection at some point,
213             // thus changing the colors.
214             if ([view textColor] != _cellTextColor) {
215                 [self setTextColor:_cellTextColor];
216                 [view setTextColor:_cellTextColor];
217             }
218         }
219     } else {
220
221         if ([self isEnabled]) {
222             if ([self isHighlighted]) {
223                 if ([[[self controlView] window] isKeyWindow]){
224                     [self setTextColor:_selectionTextActiveColor];
225                 } else {
226                     [self setTextColor:_selectionTextInActiveColor];
227                 }
228             } else {
229                 [self setTextColor:_cellTextColor];
230             }
231         } else {
232             [self setTextColor:_disabledCellTextColor];
233         }
234     }
235
236     // Check to see if the attributed placeholder has been set or not
237     if (![self placeholderAttributedString] && [self placeholderString]) {
238
239         NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
240
241         // Set the paragraph style
242         [style setAlignment: [self alignment]];
243
244         // Attributed string doesn't exist lets create it
245         NSDictionary *attributes = @{
246                                      NSForegroundColorAttributeName : _placeholderTextColor,
247                                      NSParagraphStyleAttributeName  : style
248                                      };
249         NSAttributedString *attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholderString attributes:attributes];
250         [self setPlaceholderAttributedString:attributedPlaceholder];
251     } else if ([self placeholderAttributedString] && [[self placeholderAttributedString] length] > 0) {
252
253         // Check to see if the proper styles have been applied
254         if ([[[self placeholderAttributedString] attribute:NSParagraphStyleAttributeName atIndex:1 effectiveRange:nil] alignment] != [self alignment]) {
255
256             NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
257
258             // Set the paragraph style
259             [style setAlignment:[self alignment]];
260             
261             // Get current attr string
262             NSMutableAttributedString *adjPlaceholder = [[NSMutableAttributedString alloc] initWithAttributedString:[self placeholderAttributedString]];
263             
264             // Add style attr
265             [adjPlaceholder addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, [adjPlaceholder length])];
266             
267             // Reset Placeholder to correct placeholder
268             [self setPlaceholderAttributedString:adjPlaceholder];
269         }
270     }
271     
272     // Adjust Frame so Text Draws correctly
273     switch (self.controlSize) {
274         case NSRegularControlSize:
275             cellFrame.origin.y += (self.bezelStyle != NSTextFieldRoundedBezel) ? 1 : 0;
276             break;
277             
278         case NSSmallControlSize:
279             cellFrame.origin.y += (self.bezelStyle == NSTextFieldRoundedBezel) ? 1 : 0;
280             break;
281             
282         case NSMiniControlSize:
283             cellFrame.origin.x += (self.bezelStyle == NSTextFieldRoundedBezel) ? 1 : 0;
284             break;
285             
286         default:
287             break;
288     }
289
290     [self drawInteriorWithFrame: cellFrame inView: controlView];
291 }
292
293 - (void)_drawKeyboardFocusRingWithFrame:(NSRect)rect inView:(NSView*)view
294 {
295     if (OSX_YOSEMITE_AND_HIGHER) {
296         if ([super respondsToSelector:@selector(_drawKeyboardFocusRingWithFrame:inView:)]) {
297             [super _drawKeyboardFocusRingWithFrame:rect inView:view];
298         }
299     }
300
301     // Do nothing
302 }
303
304 @end