WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / macosx / HBLanguagesSelection.m
blobd9d5a9b1ea0de4406a229afd3bb63ee861b6a7f9
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"
8 #include "lang.h"
10 @implementation HBLang
12 - (instancetype)init
14     @throw nil;
17 - (instancetype)initWithLanguage:(NSString *)value iso639_2code:(NSString *)code
19     self = [super init];
20     if (self)
21     {
22         _language = value;
23         _iso639_2 = code;
24     }
25     return self;
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;
36     return lang;
39 - (NSString *)description
41     return self.language;
44 @end
46 @implementation HBLanguagesSelection
48 - (instancetype)init
50     self = [self initWithLanguages:nil];
51     return self;
54 - (instancetype)initWithLanguages:(NSArray *)languages
56     self = [super init];
57     if (self)
58     {
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))
64         {
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])
70             {
71                 item.isSelected = YES;
72                 [selected addObject:item];
73             }
74             else
75             {
76                 [internal addObject:item];
77             }
78             
79         }
81         // Add the (Any) item.
82         HBLang *item = [[HBLang alloc] initWithLanguage:@"(Any)"
83                                             iso639_2code:@"und"];
84         if ([languages containsObject:item.iso639_2])
85         {
86             item.isSelected = YES;
87         }
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]];
94         }];
96         [internal insertObjects:selected
97                       atIndexes:[NSIndexSet indexSetWithIndexesInRange:(NSMakeRange(1, selected.count))]];
99         _languagesArray = internal;
100     }
102     return self;
105 - (NSArray *)selectedLanguages
107     NSMutableArray *selected = [[NSMutableArray alloc] init];
108     for (HBLang *lang in self.languagesArray)
109     {
110         if (lang.isSelected)
111         {
112             [selected addObject:lang.iso639_2];
113         }
114     }
116     return [selected copy];
120 @end
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];
136     }
138     // Returns a filtered array with only the selected items
139     NSMutableArray *filteredObjects = [NSMutableArray arrayWithCapacity:[objects count]];
140     for (id item in objects)
141     {
142         if ([[item valueForKeyPath:@"isSelected"] boolValue])
143         {
144             [filteredObjects addObject:item];
145         }
146     }
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
160                     row:(NSInteger)row
162     if ([[tableColumn identifier] isEqualToString:@"name"])
163     {
164         NSUInteger tableColumnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
165         return [[tableView preparedCellAtColumn:tableColumnIndex
166                                             row:row] stringValue];
167     }
168     return nil;
171 - (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
173     if (self.isDragginEnabled)
174         {
175         NSData *data = nil;
176         if (self.showSelectedOnly)
177         {
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)
188             {
189                 NSUInteger newIndex = [unfilteredArray indexOfObject:filteredArray[currentIndex]];
190                 [unfilteredIndexes addIndex:newIndex];
191                 currentIndex = [rowIndexes indexGreaterThanIndex:currentIndex];
192             }
194             data = [NSKeyedArchiver archivedDataWithRootObject:unfilteredIndexes];
195         }
196         else
197         {
198             data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
199         }
201         [pboard declareTypes:@[kHBLanguagesDragRowsType] owner:self];
202         [pboard setData:data forType:kHBLanguagesDragRowsType];
203     }
204     
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)
217         {
218                 // At a minimum, allow move
219                 dragOp =  NSDragOperationMove;
220     }
222     [view setDropRow:row dropOperation:NSTableViewDropAbove];
224     return dragOp;
227 - (BOOL)tableView:(NSTableView *)view acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
229     if (([info draggingSourceOperationMask] == NSDragOperationCopy))
230     {
231         return NO;
232     }
234     if ([info draggingSource] == view)
235     {
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.
246         row -= i;
247         NSIndexSet *selectionSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, [indexSet count])];
248         [view selectRowIndexes:selectionSet byExtendingSelection:NO];
250                 return YES;
251     }
253     return 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)
265         {
266                 if (thisIndex >= insertIndex)
267                 {
268                         removeIndex = thisIndex + aboveInsertIndexCount;
269                         aboveInsertIndexCount += 1;
270                 }
271                 else
272                 {
273                         removeIndex = thisIndex;
274                         insertIndex -= 1;
275                 }
277                 // Get the object we're moving
278                 id object = objects[removeIndex];
280                 // Move the object
281                 [self removeObjectAtArrangedObjectIndex:removeIndex];
282                 [self insertObject:object atArrangedObjectIndex:insertIndex];
284                 thisIndex = [indexSet indexLessThanIndex:thisIndex];
285     }
288 @end