2014-09-30 5 views
5

के लिए प्रासंगिक मेनू को कार्यान्वित करने के लिए कैसे करें मेरे ओएसएक्स ऐप में मेरे पास संग्रह संग्रह है जो NSCollectionView का उप-वर्ग है।NSCollectionView

मैं संतुष्ट हूं कि चीजें प्रासंगिक मेनू को छोड़कर कैसे हैं, जिन्हें मैं अभी तक नहीं समझ सकता।

तो क्या मैं चाहता हूँ है:

  • एक संग्रह को देखने आइटम पर राइट क्लिक करें आइटम पर लागू होने वाली प्रासंगिक मेनू
  • विकल्प मेनू (हटाने के लिए, संपादित करें, आदि) से उठाया को लाता है कि क्लिक पर किया गया था।

मुझे पता है कि NSOutlineView या NSTableView के लिए इसे कैसे करें, लेकिन संग्रह दृश्य के लिए नहीं।

मैं यह नहीं समझ सकता कि आइटम के सूचकांक को कैसे प्राप्त किया जाए।

क्या किसी के पास कोई विचार है कि मैं इसे कैसे कार्यान्वित कर सकता हूं?

किसी भी प्रकार की सहायता की अत्यधिक सराहना की जाती है!

उत्तर

4

एक दृष्टिकोण जिसका मैंने उपयोग किया है, प्रासंगिक मेनू क्रियाओं को उस विशिष्ट आइटम पर लागू करने का प्रयास नहीं करना है जिसे क्लिक किया गया था लेकिन चयनित आइटम पर। और मैं क्लिक-ऑन आइटम को स्वयं चयन में जोड़ता हूं।

मैंने संग्रह आइटम दृश्य के लिए एक कस्टम दृश्य का उपयोग किया। कस्टम व्यू क्लास में आउटलेट, item है, जो अपने स्वयं के संग्रह दृश्य आइटम पर है, जिसे मैं एनआईबी में जोड़ता हूं। यह भी -rightMouseDown: ओवरराइड करता है आइटम चयन करने के लिए अपने आप को जोड़ने के लिए:

- (void) rightMouseDown:(NSEvent*)event 
{ 
    NSCollectionView* parent = self.item.collectionView; 
    NSUInteger index = NSNotFound; 
    NSUInteger count = parent.content.count; 
    for (NSUInteger i = 0; i < count; i++) 
    { 
     if ([parent itemAtIndex:i] == self.item) 
     { 
      index = i; 
      break; 
     } 
    } 

    NSMutableIndexSet* selectionIndexes = [[parent.selectionIndexes mutableCopy] autorelease]; 
    if (index != NSNotFound && ![selectionIndexes containsIndex:index]) 
    { 
     [selectionIndexes addIndex:index]; 
     parent.selectionIndexes = selectionIndexes; 
    } 

    return [super rightMouseDown:event]; 
} 

यदि आप चाहें, बल्कि चयन में आइटम जोड़ने की तुलना में, आप देख सकते हैं कि यह चयन में पहले है। यदि ऐसा है, तो चयन को संशोधित न करें। यदि ऐसा नहीं है, को केवल आइटम के साथ चयन (इसे केवल एकमात्र चयनित आइटम) के साथ बदलें।

वैकल्पिक रूप से, आप संग्रह दृश्य के बजाय आइटम दृश्यों पर एक प्रासंगिक मेनू सेट कर सकते हैं। फिर, मेनू आइटम आइटम दृश्य या संग्रह दृश्य आइटम को लक्षित कर सकते हैं।

आखिरकार, आप NSCollectionView उपखंड कर सकते हैं और -menuForEvent: ओवरराइड कर सकते हैं। आप अभी भी super पर कॉल करेंगे और मेनू लौटाएंगे, लेकिन आप ईवेंट और/या आइटम को अपने स्थान पर रिकॉर्ड करने का अवसर ले सकते हैं।

- (NSMenu*) menuForEvent:(NSEvent*)event 
{ 
    _clickedItemIndex = NSNotFound; 
    NSPoint point = [self convertPoint:event.locationInWindow fromView:nil]; 
    NSUInteger count = self.content.count; 
    for (NSUInteger i = 0; i < count; i++) 
    { 
     NSRect itemFrame = [self frameForItemAtIndex:i]; 
     if (NSMouseInRect(point, itemFrame, self.isFlipped)) 
     { 
      _clickedItemIndex = i; 
      break; 
     } 
    } 

    return [super menuForEvent:event]; 
} 
+0

सुंदर !!! आपको बहुत - बहुत धन्यवाद! –

+1

इस तरह से बहुत जटिल है। क्या आपने अपने संग्रह दृश्य के मेनू आउटलेट को अपनी निब फ़ाइल से मेनू में सेट करने का प्रयास किया है? मेनू के लिए प्रतिनिधि के रूप में अपने नियंत्रक ऑब्जेक्ट को सेट करें। प्रत्येक बार मेनू को बुलाया जाता है, संग्रह दृश्य में चयन के अनुसार अपना मेनू अपडेट करें। – iljawascoding

+0

मुझे वास्तव में 'एनएससीओलेक्शन व्यू' उप-वर्ग दृष्टिकोण पसंद है - 'एनएसटीबल व्यू' के साथ व्यवहार की अच्छी स्थिरता देता है। –

3

यहाँ एक NSCollectionView उपवर्ग स्विफ्ट में लागू में menuForEvent: ओवरराइड करने के लिए Ken's idea है: कि निर्धारित करने के लिए, आप कुछ पसंद है था

// MARK: - Properties 

/** 
The index of the item the user clicked. 
*/ 
var clickedItemIndex: Int = NSNotFound 

// MARK: - Menu override methods 

override func menuForEvent(event: NSEvent) -> NSMenu? 
{ 
    self.clickedItemIndex = NSNotFound 

    let point = self.convertPoint(event.locationInWindow, fromView:nil) 
    let count = self.content.count 

    for index in 0 ..< count 
    { 
     let itemFrame = self.frameForItemAtIndex(index) 
     if NSMouseInRect(point, itemFrame, self.flipped) 
     { 
      self.clickedItemIndex = index 
      break 
     } 
    } 

    return super.menuForEvent(event) 
} 
0

इस समाधान के लिए धन्यवाद। मैं इसे एक NSCollectionView उपवर्ग में लपेटा:

#import <Cocoa/Cocoa.h> 

@interface TAClickableCollectionViewItem : NSCollectionViewItem 
@property (nonatomic, assign) BOOL isClicked; 
@end 



@interface TAClickableCollectionView : NSCollectionView <NSMenuDelegate> 
@property (nonatomic, readonly) id clickedObject; 
@property (nonatomic, readonly) TAClickableCollectionViewItem *clickedItem; 
@end 

तो तुम क्लिक किया आइटम को उजागर करने के साथ-साथ इंटरफेस बिल्डर में बाइंडिंग का उपयोग कर सकते हैं।

#import "TAClickableCollectionView.h" 

@implementation TAClickableCollectionViewItem 
@end 



@implementation TAClickableCollectionView 

- (NSMenu*) menuForEvent:(NSEvent*)event 
{ 
    NSInteger _clickedItemIndex = NSNotFound; 
    NSPoint point = [self convertPoint:event.locationInWindow fromView:nil]; 
    NSUInteger count = self.content.count; 
    for (NSUInteger i = 0; i < count; i++) 
    { 


    NSRect itemFrame = [self frameForItemAtIndex:i]; 
     if (NSMouseInRect(point, itemFrame, self.isFlipped)) 
      { 
      _clickedItemIndex = i; 
      break; 
      } 
     } 

    if(_clickedItemIndex < self.content.count) { 
     id obj = [self.content objectAtIndex:_clickedItemIndex]; 
     TAClickableCollectionViewItem *item = (TAClickableCollectionViewItem *)[self itemAtIndex:_clickedItemIndex]; 

     if(item != _clickedItem) { 
      [self willChangeValueForKey:@"clickedObject"]; 
      _clickedItem.isClicked = NO; 
      _clickedItem = item; 
      [self didChangeValueForKey:@"clickedObject"]; 
     } 

     item.isClicked = YES; 

     if(obj != _clickedObject) { 
      [self willChangeValueForKey:@"clickedObject"]; 
      _clickedObject = obj; 
      [self didChangeValueForKey:@"clickedObject"]; 
     } 
    } 

    return [super menuForEvent:event]; 
} 

- (void)menuDidClose:(NSMenu *)menu { 
    _clickedItem.isClicked = NO; 
} 
@end 
1

असल में, हमारे समाधान के सभी आवश्यकताओं को संबोधित करने में सक्षम हैं, लेकिन मैं swift3 +, जो मुझे लगता है कि एक पूर्ण समाधान है के लिए एक पूरक बनाने के लिए करना चाहते हैं।

/// 扩展NSCollectionView功能,增加常用委托 
class ANCollectionView: NSCollectionView { 
    // 扩展委托方式 
    weak open var ANDelegate: ANCollectionViewDelegate? 

    override func menu(for event: NSEvent) -> NSMenu? { 
     var menu = super.menu(for: event); 
     let point = self.convert(event.locationInWindow, from: nil) 
     let indexPath = self.indexPathForItem(at: point); 
     if ANDelegate != nil{ 
      menu = ANDelegate?.collectionView(self, menu: menu, at: indexPath); 
     } 
     return menu; 
    } 
} 

/// 扩展NSCollectionView的委托 
protocol ANCollectionViewDelegate : NSObjectProtocol { 
    func collectionView(_ collectionView:NSCollectionView, menu:NSMenu?, at indexPath: IndexPath?) -> NSMenu? 
} 

यही वह है जिसे मैंने एक विस्तार लिखा था, और मैं सभी की मदद करने की आशा करता हूं।