forked from scrod/nv
-
Notifications
You must be signed in to change notification settings - Fork 1
/
LabelsListController.m
executable file
·134 lines (96 loc) · 4.9 KB
/
LabelsListController.m
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
//
// LabelsListController.m
// Notation
//
// Created by Zachary Schneirov on 1/10/06.
/*Copyright (c) 2010, Zachary Schneirov. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials provided with
the distribution.
- Neither the name of Notational Velocity nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission. */
#import "LabelsListController.h"
#import "LabelObject.h"
#import "NoteObject.h"
#import "NSCollection_utils.h"
@implementation LabelsListController
- (id)init {
if ([super init]) {
allLabels = [[NSCountedSet alloc] init]; //authoritative
//for faster(?) filtering during search
filteredLabels = [[NSCountedSet alloc] init];
removeIndicies = NULL;
}
return self;
}
- (void)unfilterLabels {
[filteredLabels setSet:allLabels];
if ([filteredLabels count] > count) {
count = [filteredLabels count];
objects = (id*)realloc(objects, count * sizeof(id));
}
[filteredLabels getObjects:objects];
}
- (void)filterLabelSet:(NSSet*)labelSet {
[filteredLabels minusSet:labelSet];
}
- (void)recomputeListFromFilteredSet {
//we can ignore our objectsArray here as we never use it and just sort directly on our C-array
[filteredLabels getObjects:objects];
count = [filteredLabels count];
//cfstringcompare here; strings always sorted alphabetically
mergesort((void *)objects, (size_t)count, sizeof(id), (int (*)(const void *, const void *))compareLabel);
}
//NotationController will probably want to filter these further if there is already a search in progress
- (NSSet*)notesAtFilteredIndex:(int)labelIndex {
return [objects[labelIndex] noteSet];
}
//figure out which notes to display given some selected labels
- (NSSet*)notesAtFilteredIndexes:(NSIndexSet*)anIndexSet {
NSUInteger i, numLabels = [anIndexSet count];
NSUInteger *labelsBuffer = malloc(numLabels * sizeof(NSUInteger));
NSRange range = NSMakeRange([anIndexSet firstIndex], ([anIndexSet lastIndex]-[anIndexSet firstIndex]) + 1);
[anIndexSet getIndexes:labelsBuffer maxCount:numLabels inIndexRange:&range];
NSMutableSet *notesOfLabels = [[NSMutableSet alloc] init];
for (i=0; i<numLabels; i++) {
int labelIndex = labelsBuffer[i];
[notesOfLabels unionSet:[objects[labelIndex] noteSet]];
}
return [notesOfLabels autorelease];
}
/* these next two methods do NOT sync. object counts with the corresponding LabelObject(s) in allLabels;
it's up to the sender to ensure that any given note is not added or removed from a label unnecessarily */
//called when deleting labels in a note
- (void)removeLabelSet:(NSSet*)labelSet fromNote:(NoteObject*)note {
//labelSet in this case is probably not the prototype labelSet, so all that may be necessary is to call removeNote: on it
//HOWEVER, don't know this for sure, assuming this API is to remain non-permeable
[allLabels minusSet:labelSet];
//we narrow down the set to make sure that we operate on the actual objects within it, and note the objects used as prototypes
//these will be any labels that were shared by notes other than this one
NSMutableSet *existingLabels = [allLabels setIntersectedWithSet:labelSet];
[existingLabels makeObjectsPerformSelector:@selector(removeNote:) withObject:note];
}
//called for labels added to a note
- (void)addLabelSet:(NSSet*)labelSet toNote:(NoteObject*)note {
[allLabels unionSet:labelSet];
NSMutableSet *existingLabels = [allLabels setIntersectedWithSet:labelSet];
[existingLabels makeObjectsPerformSelector:@selector(addNote:) withObject:note];
[note replaceMatchingLabelSet:existingLabels]; //link back for the existing note, so that it knows about the other notes in this label
}
//useful for moving groups of notes from one label to another
- (void)removeLabelSet:(NSSet*)labelSet fromNoteSet:(NSSet*)notes {
[allLabels minusSet:labelSet];
NSMutableSet *existingLabels = [allLabels setIntersectedWithSet:labelSet];
[existingLabels makeObjectsPerformSelector:@selector(removeNoteSet:) withObject:notes];
}
- (void)addLabelSet:(NSSet*)labelSet toNoteSet:(NSSet*)notes {
[allLabels unionSet:labelSet];
NSMutableSet *existingLabels = [allLabels setIntersectedWithSet:labelSet];
[existingLabels makeObjectsPerformSelector:@selector(addNoteSet:) withObject:notes];
[notes makeObjectsPerformSelector:@selector(replaceMatchingLabelSet:) withObject:existingLabels];
}
@end