summaryrefslogtreecommitdiff
path: root/platform/macos/app/FeatureAttributePredicateEditorRowTemplate.m
blob: 0d19bd16352647d5568a34ca496a102313ca7186 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#import "FeatureAttributePredicateEditorRowTemplate.h"

#import <Mapbox/Mapbox.h>

@implementation MGLStyleLayer (MBXAdditions)

- (NSPredicate *)predicate {
    return nil;
}

- (void)setPredicate:(NSPredicate *)predicate {
}

@end

@implementation FeatureAttributePredicateEditorRowTemplate {
    NSTextField *_keyPathTextField;
    NSPopUpButton *_operatorPopUpButton;
    NSTextField *_valueTextField;
    NSTokenField *_valueTokenField;
}

- (double)matchForPredicate:(NSComparisonPredicate *)predicate {
    if (![predicate isKindOfClass:[NSComparisonPredicate class]]) {
        return 0;
    }
    
    id constantValue = predicate.rightExpression.constantValue;
    if ([constantValue isKindOfClass:[NSArray class]]) {
        constantValue = [[constantValue firstObject] constantValue];
    }
    switch (self.rightExpressionAttributeType) {
        case NSBooleanAttributeType:
            return ([constantValue isKindOfClass:[NSNumber class]]
                    && (strcmp([constantValue objCType], @encode(char)) == 0
                        || strcmp([constantValue objCType], @encode(BOOL)) == 0)) ? 1 : 0;
            
        case NSDoubleAttributeType:
        case NSFloatAttributeType:
            return ([constantValue isKindOfClass:[NSNumber class]]
                    && (strcmp([constantValue objCType], @encode(double)) == 0
                        || strcmp([constantValue objCType], @encode(float)) == 0)) ? 1 : 0;
            
        case NSInteger16AttributeType:
        case NSInteger32AttributeType:
        case NSInteger64AttributeType:
            return ([constantValue isKindOfClass:[NSNumber class]]
                    && strcmp([constantValue objCType], @encode(double)) != 0
                    && strcmp([constantValue objCType], @encode(float)) != 0
                    && strcmp([constantValue objCType], @encode(char)) != 0
                    && strcmp([constantValue objCType], @encode(BOOL)) != 0) ? 1 : 0;
            
        case NSStringAttributeType:
            return [constantValue isKindOfClass:[NSString class]] ? 0.8 : 0;
            
        default:
            return [super matchForPredicate:predicate];
    }
}

- (NS_ARRAY_OF(NSView *) *)templateViews {
    NSMutableArray *views = super.templateViews.mutableCopy;
    views[0] = self.keyPathTextField;
    _operatorPopUpButton = views[1];
    _valueTextField = views[2];
    
    BOOL isInPredicate = [_operatorPopUpButton.selectedItem.representedObject unsignedIntegerValue] == NSInPredicateOperatorType;
    if (isInPredicate) {
        [views insertObject:self.valueTokenField atIndex:2];
    } else {
        [views addObject:self.valueTokenField];
    }
    [views[2] setHidden:NO];
    [views[3] setHidden:YES];
    
    return views;
}

- (NSTextField *)keyPathTextField {
    if (!_keyPathTextField) {
        _keyPathTextField = [[NSTextField alloc] initWithFrame:NSZeroRect];
        _keyPathTextField.editable = NO;
        _keyPathTextField.bordered = NO;
        _keyPathTextField.backgroundColor = nil;
        _keyPathTextField.font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
    }
    [_keyPathTextField sizeToFit];
    return _keyPathTextField;
}

- (NSTokenField *)valueTokenField {
    if (!_valueTokenField) {
        _valueTokenField = [[NSTokenField alloc] initWithFrame:NSZeroRect];
        _valueTokenField.font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
    }
    [_valueTokenField sizeToFit];
    NSRect frame = _valueTokenField.frame;
    frame.size.width = _valueTextField.frame.size.width;
    _valueTokenField.frame = frame;
    return _valueTokenField;
}

- (NSPredicate *)predicateWithSubpredicates:(NS_ARRAY_OF(NSPredicate *) *)subpredicates {
    NSComparisonPredicate *predicate = (NSComparisonPredicate *)[super predicateWithSubpredicates:subpredicates];
    NSAssert([predicate isKindOfClass:[NSComparisonPredicate class]], @"FeatureAttributePredicateEditorRowTemplate only works with comparison predicates.");
    
    NSExpression *leftExpression = [NSExpression expressionForKeyPath:self.keyPathTextField.stringValue];
    NSExpression *rightExpression = predicate.rightExpression;
    if (predicate.predicateOperatorType == NSInPredicateOperatorType) {
        rightExpression = [NSExpression expressionForAggregate:
                           [_valueTokenField.stringValue componentsSeparatedByString:@","]];
    }
    return [NSComparisonPredicate predicateWithLeftExpression:leftExpression
                                              rightExpression:rightExpression
                                                     modifier:predicate.comparisonPredicateModifier
                                                         type:predicate.predicateOperatorType
                                                      options:predicate.options];
}

- (void)setPredicate:(NSComparisonPredicate *)predicate {
    NSAssert([predicate isKindOfClass:[NSComparisonPredicate class]], @"FeatureAttributePredicateEditorRowTemplate only works with comparison predicates.");
    
    self.keyPathTextField.stringValue = predicate.leftExpression.keyPath;
    [self.keyPathTextField sizeToFit];
    
    BOOL isInPredicate = predicate.predicateOperatorType == NSInPredicateOperatorType;
    _operatorPopUpButton.enabled = !isInPredicate;
    _valueTextField.hidden = isInPredicate;
    self.valueTokenField.hidden = !isInPredicate;
    NSExpression *rightExpression = predicate.rightExpression;
    if (isInPredicate) {
        NSArray *values = [rightExpression.constantValue valueForKeyPath:@"constantValue"];
        self.valueTokenField.stringValue = [values componentsJoinedByString:@","];
        rightExpression = [NSExpression expressionForConstantValue:nil];
    } else {
        self.valueTokenField.stringValue = @"";
    }
    
    predicate = [NSComparisonPredicate predicateWithLeftExpression:self.leftExpressions.firstObject
                                                   rightExpression:rightExpression
                                                          modifier:predicate.comparisonPredicateModifier
                                                              type:predicate.predicateOperatorType
                                                           options:predicate.options];
    [super setPredicate:predicate];
}

@end