FavoritesDrawerController.m
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:17k
源码类别:

OpenGL

开发平台:

Visual C++

  1. #import "FavoritesDrawerController.h"
  2. #import "CelestiaFavorite.h"
  3. #import "CelestiaFavorites.h"
  4. #define SAFENODE(node) ((MyTree*)((node == nil) ? [CelestiaFavorites sharedFavorites] : node))
  5. #define DragDropSimplePboardType @"CelestiaFavoriteOutlineViewPboardType"
  6. /*
  7. @implementation NSMenuItem(DebuggingAPI)
  8. -(NSString*)description
  9. {
  10.     return [NSString stringWithFormat:@"<MenuItem: 0x%x %@ enabled:%@ target:%@ representedObject:%@>",self,[self title],[self isEnabled]?@"YES":@"NO",[self target],[self representedObject]];
  11. }
  12. @end
  13. */
  14. @implementation CelestiaFavorite(ViewAPI)
  15. -(NSMenuItem*)favoriteMenuItem
  16. {
  17.     NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle:[self name] action:([self isFolder] ? nil : @selector(activate)) keyEquivalent:@""] autorelease];
  18.     return [self setupFavoriteMenuItem:menuItem];
  19. }
  20. -(NSMenuItem*)setupFavoriteMenuItem:(NSMenuItem*)menuItem
  21. {
  22.     [menuItem setTarget:self];
  23.     [menuItem setAction:([self isFolder] ? nil : @selector(activate))];
  24.     [menuItem setTitle:[self name]];
  25.     [menuItem setRepresentedObject:self];
  26.     [menuItem setKeyEquivalent:@""];
  27.     [menuItem setEnabled:YES];
  28.     return menuItem;
  29. }
  30. @end
  31. @implementation CelestiaFavorites(ViewAPI)
  32. -(NSArray*)favoriteMenuItems
  33. {
  34.     NSEnumerator *enumerator = [[self children] objectEnumerator];
  35.     MyTree* node = nil;
  36.     NSMutableArray* menuItems = [NSMutableArray arrayWithCapacity:[[self children] count]];
  37.     //NSLog(@"[CelestiaFavorites favoriteMenuItems]");
  38.     while ((node = [enumerator nextObject]) != nil)
  39.         [menuItems addObject:[node favoriteMenuItem]];
  40.     return (NSArray*)menuItems;
  41. }
  42. @end
  43. @implementation MyTree(ViewAPI)
  44. -(void)activate
  45. {
  46.     [(CelestiaFavorite*)[self nodeValue] activate];
  47. }
  48. -(NSMenuItem*)favoriteMenuItem
  49. {
  50.     NSEnumerator* enumerator = nil;
  51.     NSMenu* subMenu = nil;
  52.     NSMenuItem* menuItem = [[self nodeValue] favoriteMenuItem];
  53.     MyTree* node = nil;
  54.     //NSLog(@"[MyTree favoriteMenuItem]");
  55.     if ([self isLeaf])
  56.         return menuItem;
  57.     enumerator = [[self children] objectEnumerator];
  58.     subMenu = [[[NSMenu alloc] initWithTitle:[[self nodeValue] name]] autorelease];
  59.     while ((node = [enumerator nextObject]) != nil)
  60.         [subMenu addItem:[node favoriteMenuItem]];
  61.     [menuItem setSubmenu:subMenu];
  62.     [menuItem setTarget:menuItem];
  63.     [menuItem setAction:@selector(submenuAction:)];
  64.     return menuItem;
  65. }
  66. @end
  67. @implementation FavoritesDrawerController
  68. -(NSArray*)selectedNodes
  69. {
  70.     return [outlineView allSelectedItems];
  71. }
  72. -(NSArray*)draggedNodes
  73. {
  74.     return draggedNodes;
  75. }
  76. -(void)activateFavorite:(CelestiaFavorite*)fav
  77. {
  78.     id menuItem = fav;
  79.     if ([menuItem isKindOfClass:[NSMenuItem class]])
  80.         fav = [(NSMenuItem*)menuItem representedObject];
  81.     [fav activate];
  82.     [outlineView deselectAll:self];
  83. }
  84. -(void)awakeFromNib
  85. {
  86.     draggedNodes = nil;
  87.     [outlineView setVerticalMotionCanBeginDrag: YES];
  88.     [outlineView setTarget:self];
  89.     [outlineView setDoubleAction:@selector(doubleClick:)];
  90.     [outlineView registerForDraggedTypes:[NSArray arrayWithObjects:DragDropSimplePboardType, nil]];
  91.     [favoritesMenu setAutoenablesItems:NO];
  92. }
  93. -(IBAction)addNewFavorite:(id)sender
  94. {
  95.     CelestiaFavorites* favs = [CelestiaFavorites sharedFavorites];
  96.     MyTree* node = nil;
  97.     //NSLog(@"[FavoritesDrawerController addNewFavorite:%@]",sender);
  98.     node = [favs addNewFavorite:nil];
  99.     // kludge to fix name
  100.     {
  101.     CelestiaAppCore* appCore = [CelestiaAppCore sharedAppCore];
  102.     NSString* newName  = [ [ [appCore simulation] selection ] briefName ];
  103.     [((CelestiaFavorite*)[node nodeValue]) setName: newName];
  104.     }
  105.     [[CelestiaFavorites sharedFavorites] synchronize];
  106. //    [self outlineView:outlineView editItem:node];
  107. }
  108. -(IBAction)addNewFolder:(id)sender
  109. {
  110.     CelestiaFavorites* favs = [CelestiaFavorites sharedFavorites];
  111.     MyTree* node = nil;
  112.     //NSLog(@"[FavoritesDrawerController addNewFavorite:%@]",sender);
  113.     node = [favs addNewFolder:NSLocalizedString(@"untitled folder",@"")];
  114.     [[CelestiaFavorites sharedFavorites] synchronize];
  115.     [self outlineView:outlineView editItem:node];
  116. }
  117. -(IBAction)doubleClick:(id)sender
  118. {
  119.     //NSLog(@"[FavoritesDrawerController doubleClick:%@]",sender);
  120.     if ([outlineView numberOfSelectedRows]==1)
  121.     {
  122.         // Make sure item is not a folder
  123.         id theItem = [outlineView itemAtRow:[outlineView selectedRow]];
  124.         if (![outlineView isExpandable: theItem])
  125.             [self activateFavorite:[theItem nodeValue]];
  126.     }
  127. }
  128. -(void)synchronizeFavoritesMenu
  129. {
  130.     NSEnumerator *enumerator = [[[CelestiaFavorites sharedFavorites] favoriteMenuItems] objectEnumerator];
  131.     NSMenuItem *menuItem = nil;
  132.     // remove old menu items
  133.     while ([favoritesMenu numberOfItems]>3)
  134.         [favoritesMenu removeItemAtIndex:[favoritesMenu numberOfItems]-1];
  135.     while ((menuItem = [enumerator nextObject]) != nil)
  136.         [favoritesMenu addItem:menuItem];
  137.     [outlineView reloadData];
  138. }
  139. -(id)outlineView:(NSOutlineView*)olv child:(int)index ofItem:(id)item
  140. {
  141.     id rval;
  142.     //NSLog(@"[FavoritesDrawerController outlineview:%@ child:%d ofItem:%@]",olv,index,item);
  143.     rval = [SAFENODE(item) childAtIndex:index];
  144.     //NSLog(@"rval = %@",rval);
  145.     return rval;
  146. }
  147. -(BOOL)outlineView:(NSOutlineView*)olv isItemExpandable:(id)item 
  148. {
  149.     //NSLog(@"[FavoritesDrawerController outlineview:%@ itemIsExpandable:%@]",olv,item);
  150.     return ![SAFENODE(item) isLeaf];
  151. }
  152. -(int)outlineView:(NSOutlineView *)olv numberOfChildrenOfItem:(id)item 
  153. {
  154.     int rval;
  155.     //NSLog(@"[FavoritesDrawerController outlineview:%@ numberOfChildrenOfItem:%@]",olv,item);
  156.     rval = [SAFENODE(item) numberOfChildren];
  157.     //NSLog(@"rval = %d",rval);
  158.     return rval;
  159. }
  160. -(id)outlineView:(NSOutlineView *)olv objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item 
  161. {
  162.     id objectValue = nil;
  163.     //NSLog(@"[FavoritesDrawerController outlineview:%@ objectValueForTableColumn:%@ byItem:%@]",olv,tableColumn,item);
  164.     if([[tableColumn identifier] isEqualToString: @"NAME"]) {
  165. objectValue = [(CelestiaFavorite*)[SAFENODE(item) nodeValue] name];
  166.     } else if([[tableColumn identifier] isEqualToString: @"SELECTION"] && [SAFENODE(item) isLeaf]) {
  167. objectValue = [(CelestiaFavorite*)[SAFENODE(item) nodeValue] selectionName];
  168.     }
  169.     //NSLog(@"rval = %@",objectValue);
  170.     return objectValue;
  171. }
  172. // Optional method: needed to allow editing.
  173. -(void)outlineView:(NSOutlineView *)olv setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item  
  174. {
  175.     //NSLog(@"[FavoritesDrawerController outlineview:%@ setObjectValue:%@ forTableColumn:%@ byItem:%@]",olv,object,tableColumn,item);
  176.     if([[tableColumn identifier] isEqualToString: @"NAME"]) {
  177.         [(CelestiaFavorite*)[SAFENODE(item) nodeValue] setName: object];
  178.         [[CelestiaFavorites sharedFavorites] synchronize];
  179.         [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:(CelestiaFavorite*)[SAFENODE(item) nodeValue]];
  180.     }
  181. }
  182. // ================================================================
  183. //  NSOutlineView delegate methods.
  184. // ================================================================
  185. - (NSMenu *)outlineView:(NSOutlineView *)olv 
  186. contextMenuForItem:(id)item
  187. {
  188.     MyTree* node = SAFENODE(item);
  189.     NSMenu* contextMenu = [favoritesContextMenu copy];
  190.     NSInvocation* editInv = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(outlineView:editItem:)]];
  191.     NSInvocation* delInv = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(outlineView:deleteItem:)]];
  192.     NSMenuItem* editItem = [contextMenu itemAtIndex:3];
  193.     NSMenuItem* delItem = [contextMenu itemAtIndex:4];
  194.     NSMutableArray* arr = nil;
  195.     
  196.     BOOL multipleItems = NO;
  197.     //NSLog(@"[FavoritesDrawerController outlineView:%@ contextMenuForItem:%@]",olv,item);
  198.     //NSLog(@"row = %d",[olv rowForItem:item]);
  199.     //[olv selectRow:[olv rowForItem:item] byExtendingSelection:NO];
  200.     if ([olv numberOfSelectedRows]>1 || [olv rowForItem:item]!=[olv selectedRow]) {
  201.         id nextItem = nil;
  202.         NSEnumerator* rowEnum = [olv selectedRowEnumerator];
  203.         arr = [NSMutableArray arrayWithCapacity:[olv numberOfSelectedRows]];
  204.         while ((nextItem = [rowEnum nextObject]) != nil) {
  205.             nextItem = [olv itemAtRow:[nextItem intValue]];
  206.             if (nextItem == nil)
  207.                 continue;
  208.             if ([item isEqual:nextItem])
  209.                 multipleItems = YES;
  210.             [arr addObject:nextItem];
  211.         }
  212.     }
  213.     if (multipleItems)
  214.         item = arr;
  215.     else
  216.         [olv selectRow:[olv rowForItem:item] byExtendingSelection:NO];
  217.     if (![node isLeaf] || multipleItems) {
  218.         [contextMenu removeItemAtIndex:0];
  219.         [contextMenu removeItemAtIndex:0];
  220.         [contextMenu removeItemAtIndex:0];
  221.     } else {
  222.         NSMenuItem* navItem = [contextMenu itemAtIndex:0];
  223.         NSString* title = [navItem title];
  224.         NSMenuItem* showItem = [contextMenu itemAtIndex:1];
  225.         [showItem setTarget:favoriteInfoWindowController];
  226.         [showItem setAction:@selector(showWindow:)];
  227.         [(CelestiaFavorite*)[node nodeValue] setupFavoriteMenuItem:navItem];
  228.         [navItem setTarget:self];
  229.         [navItem setTitle:title];
  230.         [navItem setAction:@selector(activateFavorite:)];
  231.     }
  232.     if (multipleItems) {
  233.         [contextMenu removeItemAtIndex:0];
  234.     } else {
  235.         [editInv setTarget:self];
  236.         [editInv setSelector:@selector(outlineView:editItem:)];
  237.         [editInv setArgument:&olv atIndex:2];
  238.         [editInv setArgument:&item atIndex:3];
  239.         [editItem setTarget:editInv];
  240.         [editItem setAction:@selector(invoke)];
  241.     }
  242.     [delInv setTarget:self];
  243.     [delInv setSelector:@selector(outlineView:deleteItem:)];
  244.     [delInv setArgument:&olv atIndex:2];
  245.     [delInv setArgument:&item atIndex:3];
  246.     [delItem setTarget:delInv];
  247.     [delItem setAction:@selector(invoke)];
  248.     return contextMenu;
  249. }
  250. - (void)outlineView:(NSOutlineView*)olv editItem:(id)item
  251. {
  252.     int row = [olv rowForItem:item];
  253.     //NSLog(@"[FavoritesDrawerController outlineView:%@ editItem:%@]",olv,item);
  254.     //NSLog(@"row = %d",row); // -1 ??
  255.     if (row<0) {
  256.         NSLog(@"row is -1");
  257.         return;
  258.     }
  259.     [olv selectRow:row byExtendingSelection:NO];
  260.     [olv editColumn:[olv columnWithIdentifier:@"NAME"] row:row withEvent:nil select:YES];
  261. }
  262. - (void)outlineView:(NSOutlineView*)olv deleteItem:(id)item
  263. {
  264.     //NSLog(@"[FavoritesDrawerController outlineView:%@ deleteItem:%@]",olv,item);
  265.     if ([item isKindOfClass:[MyTree class]])
  266.         [item removeFromParent];
  267.     else
  268.         [(NSArray*)item makeObjectsPerformSelector:@selector(removeFromParent)];
  269.     [[CelestiaFavorites sharedFavorites] synchronize];
  270.     [olv deselectAll:self];
  271.     [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:nil];
  272. }
  273. -(void)outlineViewSelectionDidChange:(NSNotification*)notification
  274. {
  275.     NSOutlineView* olv = [notification object];
  276.     if ([olv numberOfSelectedRows]==1) {
  277.         [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:[[olv itemAtRow:[olv selectedRow]] nodeValue]];
  278.     } else {
  279.         [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:nil];
  280.     }
  281. }
  282. /*
  283. - (BOOL)outlineView:(NSOutlineView *)olv shouldExpandItem:(id)item 
  284. {
  285.     BOOL rval;
  286.     NSLog(@"[FavoritesDrawerController outlineview:%@ shouldExpandItem:%@]",olv,item);
  287.     rval = ![SAFENODE(item) isLeaf];
  288.     NSLog(@"rval = %@",((rval)?@"YES":@"NO"));
  289.     return rval;
  290. }
  291. */
  292. /*
  293. - (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item 
  294. {    
  295.     // NSLog(@"[FavoritesDrawerController outlineview:%@ willDisplayCell:%@ forTableColumn:%@ item:0x%X]",olv,cell,tableColumn,item);
  296.     if ([[tableColumn identifier] isEqualToString: @"NAME"]) {
  297. [cell setStringValue: [(CelestiaFavorite*)item name]];
  298.     } else if ([[tableColumn identifier] isEqualToString: @"SELECTION"]) {
  299. if ([(CelestiaFavorite*)item isFolder])
  300.             [cell setStringValue:@""];
  301.         else
  302.             [cell setStringValue:[(CelestiaFavorite*)item selectionName]];
  303.     }
  304. }
  305. */
  306. // ================================================================
  307. //  NSOutlineView data source methods. (dragging related)
  308. // ================================================================
  309. - (BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard 
  310. {
  311.     //NSLog(@"[FavoritesDrawerController outlineView:%@ writeItems:%@ toPasteboard:%@]",olv,items,pboard);
  312.     draggedNodes = items; // Don't retain since this is just holding temporaral drag information, and it is only used during a drag!  We could put this in the pboard actually.
  313.     
  314.     // Provide data for our custom type, and simple NSStrings.
  315.     [pboard declareTypes:[NSArray arrayWithObjects: DragDropSimplePboardType, NSStringPboardType, nil] owner:self];
  316.     
  317.     // the actual data doesn't matter since DragDropSimplePboardType drags aren't recognized by anyone but us!.
  318.     [pboard setData:[NSData data] forType:DragDropSimplePboardType]; 
  319.     
  320.     // Put string data on the pboard... notice you candrag into TextEdit!
  321.     [pboard setString: [draggedNodes description] forType: NSStringPboardType];
  322.     return YES;
  323. }
  324. - (unsigned int)outlineView:(NSOutlineView*)olv validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)childIndex {
  325.     // This method validates whether or not the proposal is a valid one. Returns NO if the drop should not be allowed.
  326.     MyTree *targetNode = item;
  327.     BOOL targetNodeIsValid = YES;
  328.     BOOL isOnDropTypeProposal = childIndex==NSOutlineViewDropOnItemIndex;
  329.     //NSLog(@"[FavoritesDrawerController outlineView:%@ validateDrop:%@ proposedItem:%@ proposedChildIndex:%d]",olv,info,item,childIndex);
  330.     // Refuse if: dropping "on" the view itself unless we have no data in the view.
  331.     /*
  332.      if (targetNode==nil && isOnDropTypeProposal==YES && [self outlineView:olv numberOfChildrenOfItem:nil]!=0) 
  333.         targetNodeIsValid = NO;
  334.     */
  335.     if (targetNode==nil && isOnDropTypeProposal==YES)// && [self allowOnDropOnLeaf]==NO)
  336.         targetNodeIsValid = NO;
  337.     if (targetNodeIsValid && [targetNode isLeaf])
  338.         targetNodeIsValid = NO;
  339.     if (isOnDropTypeProposal)
  340.         targetNodeIsValid = NO;
  341.     
  342.     // Check to make sure we don't allow a node to be inserted into one of its descendants!
  343.     if (targetNodeIsValid && ([info draggingSource]==outlineView) && [[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject: DragDropSimplePboardType]] != nil) {
  344.         NSArray* _draggedNodes = [[[info draggingSource] dataSource] draggedNodes];
  345.         //NSEnumerator* enumerator = [_draggedNodes objectEnumerator];
  346.         //MyTree* node = nil;
  347.         targetNodeIsValid = ![targetNode isDescendantOfNodeInArray: _draggedNodes];
  348.         /*
  349.          while ((node = [enumerator nextObject]) != nil)
  350.             if ([[node parent] isEqualTo:SAFENODE(item)] && !isOnDropTypeProposal && childIndex >= [SAFENODE(item) numberOfChildren]) {
  351.                 targetNodeIsValid = NO;
  352.                 break;
  353.             }
  354.          */
  355.     }
  356.     
  357.     // Set the item and child index in case we computed a retargeted one.
  358.     [outlineView setDropItem:targetNode dropChildIndex:childIndex];
  359.     
  360.     return targetNodeIsValid ? NSDragOperationGeneric : NSDragOperationNone;
  361. }
  362. - (void)_performDropOperation:(id <NSDraggingInfo>)info onNode:(id)pnode atIndex:(int)childIndex {
  363.     // Helper method to insert dropped data into the model. 
  364.     NSPasteboard* pboard = [info draggingPasteboard];
  365.     NSMutableArray* itemsToSelect = nil;
  366.     MyTree* parentNode = SAFENODE(pnode);
  367.     //NSLog(@"[FavoritesDrawerController _performDropOperation:%@ onNode:%@ atIndex:%d]",info,pnode,childIndex);
  368.     //NSLog(@"parentNode = %@",parentNode);
  369.     if ([pboard availableTypeFromArray:[NSArray arrayWithObjects:DragDropSimplePboardType, nil]] != nil) {
  370.         FavoritesDrawerController *dragDataSource = [[info draggingSource] dataSource];
  371.         NSArray *_draggedNodes = [MyTree minimumNodeCoverFromNodesInArray: [dragDataSource draggedNodes]];
  372.         NSEnumerator *draggedNodesEnum = [_draggedNodes objectEnumerator];
  373.         MyTree *_draggedNode = nil, *_draggedNodeParent = nil;
  374.         //MyTree* favs = [CelestiaFavorites sharedFavorites];
  375. itemsToSelect = [NSMutableArray arrayWithArray:[self selectedNodes]];
  376.         /*
  377.         NSLog(@"dragDataSource = %@",dragDataSource);
  378.         NSLog(@"_draggedNodes = %@",_draggedNodes);
  379.         NSLog(@"itemsToSelect = %@",itemsToSelect);
  380.          */
  381.         while ((_draggedNode = [draggedNodesEnum nextObject])) {
  382.             _draggedNodeParent = [_draggedNode parent];
  383.             if (parentNode==_draggedNodeParent && [parentNode indexOfChild: _draggedNode]<childIndex) childIndex--;
  384.             [_draggedNodeParent removeChild: _draggedNode];
  385.         }
  386.         [parentNode insertChildren: _draggedNodes atIndex: childIndex];
  387.     } 
  388.     [[CelestiaFavorites sharedFavorites] synchronize];
  389.     [outlineView selectItems: itemsToSelect byExtendingSelection: NO];
  390. }
  391. - (BOOL)outlineView:(NSOutlineView*)olv acceptDrop:(id <NSDraggingInfo>)info item:(id)targetItem childIndex:(int)childIndex {
  392.     MyTree *  parentNode = nil;
  393.     //NSLog(@"[FavoritesDrawerController outlineView:%@ acceptDrop:%@ item:%@ childIndex:%d]",olv,info,targetItem,childIndex);
  394.     // Determine the parent to insert into and the child index to insert at.
  395.     parentNode = (MyTree*)(targetItem ? targetItem : [CelestiaFavorites sharedFavorites]);//SAFENODE(targetItem);
  396.     childIndex = (childIndex==NSOutlineViewDropOnItemIndex ? 0 : childIndex);
  397.     [self _performDropOperation:info onNode:parentNode atIndex:childIndex];        
  398.     return YES;
  399. }
  400. @end