1 /* HBLanguagesSelection.m $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
7 #import "HBLanguagesSelection.h"
10 @implementation HBLang
17 - (instancetype)initWithLanguage:(NSString *)value iso639_2code:(NSString *)code
28 - (instancetype)copyWithZone:(NSZone *)zone
30 HBLang *lang = [[self class] allocWithZone:zone];
32 lang->_isSelected = self.isSelected;
33 lang->_language = self.language;
34 lang->_iso639_2 = self.iso639_2;
39 - (NSString *)description
46 @implementation HBLanguagesSelection
50 self = [self initWithLanguages:nil];
54 - (instancetype)initWithLanguages:(NSArray *)languages
59 NSMutableArray *internal = [[NSMutableArray alloc] init];
60 NSMutableArray *selected = [[NSMutableArray alloc] init];
62 const iso639_lang_t *lang = lang_get_next(NULL);
63 for (lang = lang_get_next(lang); lang != NULL; lang = lang_get_next(lang))
65 NSString *nativeLanguage = strlen(lang->native_name) ? @(lang->native_name) : @(lang->eng_name);
67 HBLang *item = [[HBLang alloc] initWithLanguage:nativeLanguage
68 iso639_2code:@(lang->iso639_2)];
69 if ([languages containsObject:item.iso639_2])
71 item.isSelected = YES;
72 [selected addObject:item];
76 [internal addObject:item];
81 // Add the (Any) item.
82 HBLang *item = [[HBLang alloc] initWithLanguage:@"(Any)"
84 if ([languages containsObject:item.iso639_2])
86 item.isSelected = YES;
88 [internal insertObject:item atIndex:0];
90 // Insert the selected items
91 // in the original order.
92 [selected sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
93 return [languages indexOfObject:[obj1 iso639_2]] - [languages indexOfObject:[obj2 iso639_2]];
96 [internal insertObjects:selected
97 atIndexes:[NSIndexSet indexSetWithIndexesInRange:(NSMakeRange(1, selected.count))]];
99 _languagesArray = internal;
105 - (NSArray *)selectedLanguages
107 NSMutableArray *selected = [[NSMutableArray alloc] init];
108 for (HBLang *lang in self.languagesArray)
112 [selected addObject:lang.iso639_2];
116 return [selected copy];
122 NSString *kHBLanguagesDragRowsType = @"kHBLanguagesDragRowsType";
124 @implementation HBLanguageArrayController
126 - (void)setShowSelectedOnly:(BOOL)showSelectedOnly
128 _showSelectedOnly = showSelectedOnly;
129 [self rearrangeObjects];
132 - (NSArray *)arrangeObjects:(NSArray *)objects
134 if (!self.showSelectedOnly) {
135 return [super arrangeObjects:objects];
138 // Returns a filtered array with only the selected items
139 NSMutableArray *filteredObjects = [NSMutableArray arrayWithCapacity:[objects count]];
140 for (id item in objects)
142 if ([[item valueForKeyPath:@"isSelected"] boolValue])
144 [filteredObjects addObject:item];
148 return [super arrangeObjects:filteredObjects];
151 - (void) awakeFromNib
153 [self.tableView registerForDraggedTypes:@[kHBLanguagesDragRowsType]];
154 self.isDragginEnabled = YES;
157 #pragma mark - NSTableView Delegate
159 - (NSString *)tableView:(NSTableView *)tableView typeSelectStringForTableColumn:(NSTableColumn *)tableColumn
162 if ([[tableColumn identifier] isEqualToString:@"name"])
164 NSUInteger tableColumnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
165 return [[tableView preparedCellAtColumn:tableColumnIndex
166 row:row] stringValue];
171 - (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
173 if (self.isDragginEnabled)
176 if (self.showSelectedOnly)
178 // If the show selected only filter
179 // is enabled, we need to modify the rowIndexes
180 // to match the position of the elements in the unfiltered array
181 NSArray *filteredArray = [[self arrangedObjects] copy];
182 self.showSelectedOnly = NO;
183 NSArray *unfilteredArray = [self arrangedObjects];
185 NSMutableIndexSet *unfilteredIndexes = [NSMutableIndexSet indexSet];
186 NSUInteger currentIndex = [rowIndexes firstIndex];
187 while (currentIndex != NSNotFound)
189 NSUInteger newIndex = [unfilteredArray indexOfObject:filteredArray[currentIndex]];
190 [unfilteredIndexes addIndex:newIndex];
191 currentIndex = [rowIndexes indexGreaterThanIndex:currentIndex];
194 data = [NSKeyedArchiver archivedDataWithRootObject:unfilteredIndexes];
198 data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
201 [pboard declareTypes:@[kHBLanguagesDragRowsType] owner:self];
202 [pboard setData:data forType:kHBLanguagesDragRowsType];
205 return self.isDragginEnabled;
208 - (NSDragOperation)tableView:(NSTableView *)view
209 validateDrop:(id <NSDraggingInfo>)info
210 proposedRow:(NSInteger)row
211 proposedDropOperation:(NSTableViewDropOperation)operation
213 NSDragOperation dragOp = NSDragOperationNone;
215 // if drag source is our own table view, it's a move or a copy
216 if ([info draggingSource] == view)
218 // At a minimum, allow move
219 dragOp = NSDragOperationMove;
222 [view setDropRow:row dropOperation:NSTableViewDropAbove];
227 - (BOOL)tableView:(NSTableView *)view acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
229 if (([info draggingSourceOperationMask] == NSDragOperationCopy))
234 if ([info draggingSource] == view)
236 // Get the index set from the pasteBoard.
237 NSData *rowData = [[info draggingPasteboard] dataForType:kHBLanguagesDragRowsType];
238 NSIndexSet *indexSet = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];
240 NSUInteger i = [indexSet countOfIndexesInRange:NSMakeRange(0, row)];
242 // Rearrage the objects.
243 [self moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:row];
245 // Update the selection.
247 NSIndexSet *selectionSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, [indexSet count])];
248 [view selectRowIndexes:selectionSet byExtendingSelection:NO];
256 - (void)moveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
258 NSArray *objects = [self arrangedObjects];
260 NSInteger aboveInsertIndexCount = 0;
261 NSInteger removeIndex;
263 NSUInteger thisIndex = [indexSet lastIndex];
264 while (thisIndex != NSNotFound)
266 if (thisIndex >= insertIndex)
268 removeIndex = thisIndex + aboveInsertIndexCount;
269 aboveInsertIndexCount += 1;
273 removeIndex = thisIndex;
277 // Get the object we're moving
278 id object = objects[removeIndex];
281 [self removeObjectAtArrangedObjectIndex:removeIndex];
282 [self insertObject:object atArrangedObjectIndex:insertIndex];
284 thisIndex = [indexSet indexLessThanIndex:thisIndex];