For example, the initial status is all images selected
when I clicked one, I hope it unselected, but the current status is no response for the action
Is there some settings? Thanks for any help.
At last, I found the solution. add the following code in the same file of your IKImageBrowserView.
#interface IKImageBrowserView (event)
- (void)mouseDown:(NSEvent *)theEvent ;
#end
#implementation IKImageBrowserView (event)
- (void)mouseDown:(NSEvent *)theEvent
{
NSPoint pt = [self convertPoint: theEvent.locationInWindow fromView: nil];
NSInteger index = [self indexOfItemAtPoint:pt] ;
if ( index != NSNotFound )
{
NSUInteger ge ;
NSUInteger le ;
NSIndexSet* set = [self selectionIndexes] ;
NSMutableIndexSet* mutableSet = [[NSMutableIndexSet alloc] init] ;
[mutableSet addIndexes:set] ;
ge = [mutableSet indexGreaterThanOrEqualToIndex:index] ;
le = [mutableSet indexLessThanOrEqualToIndex:index] ;
if ( (ge == le) && (ge != NSNotFound) )
{
[mutableSet removeIndex:index] ;
}
else
{
[mutableSet addIndex:index] ;
}
[self setSelectionIndexes:mutableSet byExtendingSelection:NO] ;
// [ mutableSet release ];
}
}
#end
Related
Wondering if anyone could give an example of how to dowload files for use with this PDF Reader code? I am very new and have been hacking away at it but I think it's time for some experienced eyes. thanks!
//
// ReaderViewController.m
// Reader v2.6.0
/////////////////////////////
#import "ReaderConstants.h"
#import "ReaderViewController.h"
#import "ThumbsViewController.h"
#import "ReaderMainToolbar.h"
#import "ReaderMainPagebar.h"
#import "ReaderContentView.h"
#import "ReaderThumbCache.h"
#import "ReaderThumbQueue.h"
#import <MessageUI/MessageUI.h>
#interface ReaderViewController () <UIScrollViewDelegate, UIGestureRecognizerDelegate, MFMailComposeViewControllerDelegate,
ReaderMainToolbarDelegate, ReaderMainPagebarDelegate, ReaderContentViewDelegate, ThumbsViewControllerDelegate>
#end
#implementation ReaderViewController
{
ReaderDocument *document;
UIScrollView *theScrollView;
ReaderMainToolbar *mainToolbar;
ReaderMainPagebar *mainPagebar;
NSMutableDictionary *contentViews;
UIPrintInteractionController *printInteraction;
NSInteger currentPage;
CGSize lastAppearSize;
NSDate *lastHideTime;
BOOL isVisible;
}
#pragma mark Constants
#define PAGING_VIEWS 3
#define TOOLBAR_HEIGHT 44.0f
#define PAGEBAR_HEIGHT 48.0f
#define TAP_AREA_SIZE 48.0f
#pragma mark Properties
#synthesize delegate;
#pragma mark Support methods
- (void)updateScrollViewContentSize
{
NSInteger count = [document.pageCount integerValue];
if (count > PAGING_VIEWS) count = PAGING_VIEWS; // Limit
CGFloat contentHeight = theScrollView.bounds.size.height;
CGFloat contentWidth = (theScrollView.bounds.size.width * count);
theScrollView.contentSize = CGSizeMake(contentWidth, contentHeight);
}
- (void)updateScrollViewContentViews
{
[self updateScrollViewContentSize]; // Update the content size
NSMutableIndexSet *pageSet = [NSMutableIndexSet indexSet]; // Page set
[contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
^(id key, id object, BOOL *stop)
{
ReaderContentView *contentView = object; [pageSet addIndex:contentView.tag];
}
];
__block CGRect viewRect = CGRectZero; viewRect.size = theScrollView.bounds.size;
__block CGPoint contentOffset = CGPointZero; NSInteger page = [document.pageNumber integerValue];
[pageSet enumerateIndexesUsingBlock: // Enumerate page number set
^(NSUInteger number, BOOL *stop)
{
NSNumber *key = [NSNumber numberWithInteger:number]; // # key
ReaderContentView *contentView = [contentViews objectForKey:key];
contentView.frame = viewRect; if (page == number) contentOffset = viewRect.origin;
viewRect.origin.x += viewRect.size.width; // Next view frame position
}
];
if (CGPointEqualToPoint(theScrollView.contentOffset, contentOffset) == false)
{
theScrollView.contentOffset = contentOffset; // Update content offset
}
}
- (void)updateToolbarBookmarkIcon
{
NSInteger page = [document.pageNumber integerValue];
BOOL bookmarked = [document.bookmarks containsIndex:page];
[mainToolbar setBookmarkState:bookmarked]; // Update
}
- (void)showDocumentPage:(NSInteger)page
{
if (page != currentPage) // Only if different
{
NSInteger minValue; NSInteger maxValue;
NSInteger maxPage = [document.pageCount integerValue];
NSInteger minPage = 1;
if ((page < minPage) || (page > maxPage)) return;
if (maxPage <= PAGING_VIEWS) // Few pages
{
minValue = minPage;
maxValue = maxPage;
}
else // Handle more pages
{
minValue = (page - 1);
maxValue = (page + 1);
if (minValue < minPage)
{minValue++; maxValue++;}
else
if (maxValue > maxPage)
{minValue--; maxValue--;}
}
NSMutableIndexSet *newPageSet = [NSMutableIndexSet new];
NSMutableDictionary *unusedViews = [contentViews mutableCopy];
CGRect viewRect = CGRectZero; viewRect.size = theScrollView.bounds.size;
for (NSInteger number = minValue; number <= maxValue; number++)
{
NSNumber *key = [NSNumber numberWithInteger:number]; // # key
ReaderContentView *contentView = [contentViews objectForKey:key];
if (contentView == nil) // Create a brand new document content view
{
NSURL *fileURL = document.fileURL; NSString *phrase = document.password; // Document properties
contentView = [[ReaderContentView alloc] initWithFrame:viewRect fileURL:fileURL page:number password:phrase];
[theScrollView addSubview:contentView]; [contentViews setObject:contentView forKey:key];
contentView.message = self; [newPageSet addIndex:number];
}
else // Reposition the existing content view
{
contentView.frame = viewRect; [contentView zoomReset];
[unusedViews removeObjectForKey:key];
}
viewRect.origin.x += viewRect.size.width;
}
[unusedViews enumerateKeysAndObjectsUsingBlock: // Remove unused views
^(id key, id object, BOOL *stop)
{
[contentViews removeObjectForKey:key];
ReaderContentView *contentView = object;
[contentView removeFromSuperview];
}
];
unusedViews = nil; // Release unused views
CGFloat viewWidthX1 = viewRect.size.width;
CGFloat viewWidthX2 = (viewWidthX1 * 2.0f);
CGPoint contentOffset = CGPointZero;
if (maxPage >= PAGING_VIEWS)
{
if (page == maxPage)
contentOffset.x = viewWidthX2;
else
if (page != minPage)
contentOffset.x = viewWidthX1;
}
else
if (page == (PAGING_VIEWS - 1))
contentOffset.x = viewWidthX1;
if (CGPointEqualToPoint(theScrollView.contentOffset, contentOffset) == false)
{
theScrollView.contentOffset = contentOffset; // Update content offset
}
if ([document.pageNumber integerValue] != page) // Only if different
{
document.pageNumber = [NSNumber numberWithInteger:page]; // Update page number
}
NSURL *fileURL = document.fileURL; NSString *phrase = document.password; NSString *guid = document.guid;
if ([newPageSet containsIndex:page] == YES) // Preview visible page first
{
NSNumber *key = [NSNumber numberWithInteger:page]; // # key
ReaderContentView *targetView = [contentViews objectForKey:key];
[targetView showPageThumb:fileURL page:page password:phrase guid:guid];
[newPageSet removeIndex:page]; // Remove visible page from set
}
[newPageSet enumerateIndexesWithOptions:NSEnumerationReverse usingBlock: // Show previews
^(NSUInteger number, BOOL *stop)
{
NSNumber *key = [NSNumber numberWithInteger:number]; // # key
ReaderContentView *targetView = [contentViews objectForKey:key];
[targetView showPageThumb:fileURL page:number password:phrase guid:guid];
}
];
newPageSet = nil; // Release new page set
[mainPagebar updatePagebar]; // Update the pagebar display
[self updateToolbarBookmarkIcon]; // Update bookmark
currentPage = page; // Track current page number
}
}
- (void)showDocument:(id)object
{
[self updateScrollViewContentSize]; // Set content size
[self showDocumentPage:[document.pageNumber integerValue]];
document.lastOpen = [NSDate date]; // Update last opened date
isVisible = YES; // iOS present modal bodge
}
#pragma mark UIViewController methods
- (id)initWithReaderDocument:(ReaderDocument *)object
{
id reader = nil; // ReaderViewController object
if ((object != nil) && ([object isKindOfClass:[ReaderDocument class]]))
{
if ((self = [super initWithNibName:nil bundle:nil])) // Designated initializer
{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:#selector(applicationWill:) name:UIApplicationWillTerminateNotification object:nil];
[notificationCenter addObserver:self selector:#selector(applicationWill:) name:UIApplicationWillResignActiveNotification object:nil];
[object updateProperties]; document = object; // Retain the supplied ReaderDocument object for our use
[ReaderThumbCache touchThumbCacheWithGUID:object.guid]; // Touch the document thumb cache directory
reader = self; // Return an initialized ReaderViewController object
}
}
return reader;
}
- (void)viewDidLoad
{
[super viewDidLoad];
assert(document != nil); // Must have a valid ReaderDocument
self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
CGRect viewRect = self.view.bounds; // View controller's view bounds
theScrollView = [[UIScrollView alloc] initWithFrame:viewRect]; // All
theScrollView.scrollsToTop = NO;
theScrollView.pagingEnabled = YES;
theScrollView.delaysContentTouches = NO;
theScrollView.showsVerticalScrollIndicator = NO;
theScrollView.showsHorizontalScrollIndicator = NO;
theScrollView.contentMode = UIViewContentModeRedraw;
theScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theScrollView.backgroundColor = [UIColor clearColor];
theScrollView.userInteractionEnabled = YES;
theScrollView.autoresizesSubviews = NO;
theScrollView.delegate = self;
[self.view addSubview:theScrollView];
CGRect toolbarRect = viewRect;
toolbarRect.size.height = TOOLBAR_HEIGHT;
mainToolbar = [[ReaderMainToolbar alloc] initWithFrame:toolbarRect document:document]; // At top
mainToolbar.delegate = self;
[self.view addSubview:mainToolbar];
CGRect pagebarRect = viewRect;
pagebarRect.size.height = PAGEBAR_HEIGHT;
pagebarRect.origin.y = (viewRect.size.height - PAGEBAR_HEIGHT);
mainPagebar = [[ReaderMainPagebar alloc] initWithFrame:pagebarRect document:document]; // At bottom
mainPagebar.delegate = self;
[self.view addSubview:mainPagebar];
UITapGestureRecognizer *singleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleTapOne.numberOfTouchesRequired = 1; singleTapOne.numberOfTapsRequired = 1; singleTapOne.delegate = self;
[self.view addGestureRecognizer:singleTapOne];
UITapGestureRecognizer *doubleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
doubleTapOne.numberOfTouchesRequired = 1; doubleTapOne.numberOfTapsRequired = 2; doubleTapOne.delegate = self;
[self.view addGestureRecognizer:doubleTapOne];
UITapGestureRecognizer *doubleTapTwo = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
doubleTapTwo.numberOfTouchesRequired = 2; doubleTapTwo.numberOfTapsRequired = 2; doubleTapTwo.delegate = self;
[self.view addGestureRecognizer:doubleTapTwo];
[singleTapOne requireGestureRecognizerToFail:doubleTapOne]; // Single tap requires double tap to fail
contentViews = [NSMutableDictionary new]; lastHideTime = [NSDate date];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (CGSizeEqualToSize(lastAppearSize, CGSizeZero) == false)
{
if (CGSizeEqualToSize(lastAppearSize, self.view.bounds.size) == false)
{
[self updateScrollViewContentViews]; // Update content views
}
lastAppearSize = CGSizeZero; // Reset view size tracking
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (CGSizeEqualToSize(theScrollView.contentSize, CGSizeZero)) // First time
{
[self performSelector:#selector(showDocument:) withObject:nil afterDelay:0.02];
}
#if (READER_DISABLE_IDLE == TRUE) // Option
[UIApplication sharedApplication].idleTimerDisabled = YES;
#endif // end of READER_DISABLE_IDLE Option
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
lastAppearSize = self.view.bounds.size; // Track view size
#if (READER_DISABLE_IDLE == TRUE) // Option
[UIApplication sharedApplication].idleTimerDisabled = NO;
#endif // end of READER_DISABLE_IDLE Option
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (void)viewDidUnload
{
#ifdef DEBUG
NSLog(#"%s", __FUNCTION__);
#endif
mainToolbar = nil; mainPagebar = nil;
theScrollView = nil; contentViews = nil; lastHideTime = nil;
lastAppearSize = CGSizeZero; currentPage = 0;
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (isVisible == NO) return; // iOS present modal bodge
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
if (printInteraction != nil) [printInteraction dismissAnimated:NO];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
if (isVisible == NO) return; // iOS present modal bodge
[self updateScrollViewContentViews]; // Update content views
lastAppearSize = CGSizeZero; // Reset view size tracking
}
/*
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
//if (isVisible == NO) return; // iOS present modal bodge
//if (fromInterfaceOrientation == self.interfaceOrientation) return;
}
*/
- (void)didReceiveMemoryWarning
{
#ifdef DEBUG
NSLog(#"%s", __FUNCTION__);
#endif
[super didReceiveMemoryWarning];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark UIScrollViewDelegate methods
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
__block NSInteger page = 0;
CGFloat contentOffsetX = scrollView.contentOffset.x;
[contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
^(id key, id object, BOOL *stop)
{
ReaderContentView *contentView = object;
if (contentView.frame.origin.x == contentOffsetX)
{
page = contentView.tag; *stop = YES;
}
}
];
if (page != 0) [self showDocumentPage:page]; // Show the page
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[self showDocumentPage:theScrollView.tag]; // Show page
theScrollView.tag = 0; // Clear page number tag
}
#pragma mark UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIScrollView class]]) return YES;
return NO;
}
#pragma mark UIGestureRecognizer action methods
- (void)decrementPageNumber
{
if (theScrollView.tag == 0) // Scroll view did end
{
NSInteger page = [document.pageNumber integerValue];
NSInteger maxPage = [document.pageCount integerValue];
NSInteger minPage = 1; // Minimum
if ((maxPage > minPage) && (page != minPage))
{
CGPoint contentOffset = theScrollView.contentOffset;
contentOffset.x -= theScrollView.bounds.size.width; // -= 1
[theScrollView setContentOffset:contentOffset animated:YES];
theScrollView.tag = (page - 1); // Decrement page number
}
}
}
- (void)incrementPageNumber
{
if (theScrollView.tag == 0) // Scroll view did end
{
NSInteger page = [document.pageNumber integerValue];
NSInteger maxPage = [document.pageCount integerValue];
NSInteger minPage = 1; // Minimum
if ((maxPage > minPage) && (page != maxPage))
{
CGPoint contentOffset = theScrollView.contentOffset;
contentOffset.x += theScrollView.bounds.size.width; // += 1
[theScrollView setContentOffset:contentOffset animated:YES];
theScrollView.tag = (page + 1); // Increment page number
}
}
}
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateRecognized)
{
CGRect viewRect = recognizer.view.bounds; // View bounds
CGPoint point = [recognizer locationInView:recognizer.view];
CGRect areaRect = CGRectInset(viewRect, TAP_AREA_SIZE, 0.0f); // Area
if (CGRectContainsPoint(areaRect, point)) // Single tap is inside the area
{
NSInteger page = [document.pageNumber integerValue]; // Current page #
NSNumber *key = [NSNumber numberWithInteger:page]; // Page number key
ReaderContentView *targetView = [contentViews objectForKey:key];
id target = [targetView processSingleTap:recognizer]; // Target
if (target != nil) // Handle the returned target object
{
if ([target isKindOfClass:[NSURL class]]) // Open a URL
{
NSURL *url = (NSURL *)target; // Cast to a NSURL object
if (url.scheme == nil) // Handle a missing URL scheme
{
NSString *www = url.absoluteString; // Get URL string
if ([www hasPrefix:#"www"] == YES) // Check for 'www' prefix
{
NSString *http = [NSString stringWithFormat:#"http://%#", www];
url = [NSURL URLWithString:http]; // Proper http-based URL
}
}
if ([[UIApplication sharedApplication] openURL:url] == NO)
{
#ifdef DEBUG
NSLog(#"%s '%#'", __FUNCTION__, url); // Bad or unknown URL
#endif
}
}
else // Not a URL, so check for other possible object type
{
if ([target isKindOfClass:[NSNumber class]]) // Goto page
{
NSInteger value = [target integerValue]; // Number
[self showDocumentPage:value]; // Show the page
}
}
}
else // Nothing active tapped in the target content view
{
if ([lastHideTime timeIntervalSinceNow] < -0.75) // Delay since hide
{
if ((mainToolbar.hidden == YES) || (mainPagebar.hidden == YES))
{
[mainToolbar showToolbar]; [mainPagebar showPagebar]; // Show
}
}
}
return;
}
CGRect nextPageRect = viewRect;
nextPageRect.size.width = TAP_AREA_SIZE;
nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);
if (CGRectContainsPoint(nextPageRect, point)) // page++ area
{
[self incrementPageNumber]; return;
}
CGRect prevPageRect = viewRect;
prevPageRect.size.width = TAP_AREA_SIZE;
if (CGRectContainsPoint(prevPageRect, point)) // page-- area
{
[self decrementPageNumber]; return;
}
}
}
- (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateRecognized)
{
CGRect viewRect = recognizer.view.bounds; // View bounds
CGPoint point = [recognizer locationInView:recognizer.view];
CGRect zoomArea = CGRectInset(viewRect, TAP_AREA_SIZE, TAP_AREA_SIZE);
if (CGRectContainsPoint(zoomArea, point)) // Double tap is in the zoom area
{
NSInteger page = [document.pageNumber integerValue]; // Current page #
NSNumber *key = [NSNumber numberWithInteger:page]; // Page number key
ReaderContentView *targetView = [contentViews objectForKey:key];
switch (recognizer.numberOfTouchesRequired) // Touches count
{
case 1: // One finger double tap: zoom ++
{
[targetView zoomIncrement]; break;
}
case 2: // Two finger double tap: zoom --
{
[targetView zoomDecrement]; break;
}
}
return;
}
CGRect nextPageRect = viewRect;
nextPageRect.size.width = TAP_AREA_SIZE;
nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);
if (CGRectContainsPoint(nextPageRect, point)) // page++ area
{
[self incrementPageNumber]; return;
}
CGRect prevPageRect = viewRect;
prevPageRect.size.width = TAP_AREA_SIZE;
if (CGRectContainsPoint(prevPageRect, point)) // page-- area
{
[self decrementPageNumber]; return;
}
}
}
#pragma mark ReaderContentViewDelegate methods
- (void)contentView:(ReaderContentView *)contentView touchesBegan:(NSSet *)touches
{
if ((mainToolbar.hidden == NO) || (mainPagebar.hidden == NO))
{
if (touches.count == 1) // Single touches only
{
UITouch *touch = [touches anyObject]; // Touch info
CGPoint point = [touch locationInView:self.view]; // Touch location
CGRect areaRect = CGRectInset(self.view.bounds, TAP_AREA_SIZE, TAP_AREA_SIZE);
if (CGRectContainsPoint(areaRect, point) == false) return;
}
[mainToolbar hideToolbar]; [mainPagebar hidePagebar]; // Hide
lastHideTime = [NSDate date];
}
}
#pragma mark ReaderMainToolbarDelegate methods
- (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)button
{
#if (READER_STANDALONE == FALSE) // Option
[document saveReaderDocument]; // Save any ReaderDocument object changes
[[ReaderThumbQueue sharedInstance] cancelOperationsWithGUID:document.guid];
[[ReaderThumbCache sharedInstance] removeAllObjects]; // Empty the thumb cache
if (printInteraction != nil) [printInteraction dismissAnimated:NO]; // Dismiss
if ([delegate respondsToSelector:#selector(dismissReaderViewController:)] == YES)
{
[delegate dismissReaderViewController:self]; // Dismiss the ReaderViewController
}
else // We have a "Delegate must respond to -dismissReaderViewController: error"
{
NSAssert(NO, #"Delegate must respond to -dismissReaderViewController:");
}
#endif // end of READER_STANDALONE Option
}
is it possible to provide draggable NSTabViewItem,
Basically what i want, if i down L Button on the label of NSTabViewITem and Move, i should allow to drag the TabView item,
I want to do it for Moving of NSTabView Item and have one more feature, if user drag a Label of NSTabView Item and move it to a perticular region, then i should allow to remove that NSTabView Item,
I could able to find only one way of having PSMTab bar, but i have other features also on NSTabView Item that i will be missing if i go with that approach.
Thanks for looking into it,
Somehow i could able to do it.... posting some important piece of code...
1 -- Have to have Custom TabView class for Handling mouse events.
// Interface posted below,
#import <Cocoa/Cocoa.h>
typedef enum __itemDragState{
itemNotDragging = 0,
itemDragStatNormal = 0,
itemDragging = 1,
itemDropped = 2
} ItemDragStat;
#protocol CustomTabViewDelegate <NSObject>
#required
-(bool)allowDrag;
-(bool)allowDrop;
-(void)dragEnter;
-(void)acceptDrop;
-(void)draggingCancelled;
-(void)itemDropped:(id)draggedTabViewItem;
-(void)itemDroppedCompleted:(id)droppedTabViewItem;
#end
#interface CustomTab : NSTabView{
ItemDragStat eItemDragStat;
id draggedItem;
}
#property(assign)id draggedItem;
#end
Now some of the important implementation
#import "CustomTab.h"
#include "Log.h"
#implementation CustomTab
#synthesize draggedItem;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
# if 0
// don't delete it, might need later on
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
# endif
- (void)mouseUp:(NSEvent *)theEvent{
log(" Mouse up ");
NSPoint location = [self convertPoint: [theEvent locationInWindow]
fromView: nil];
NSTabViewItem *anItem = [self tabViewItemAtPoint: location];
if ( anItem == nil ) {
// if its mouse up else where, reject dragging regardless
eItemDragStat = itemDragStatNormal;
log("Item will not be dropped");
return;
}
if ( ![anItem isEqual:[self selectedTabViewItem]]){
log("Mouse up is in nonselected item");
if ( eItemDragStat == itemDragging){
log("Item will be dropped into this ");
id droppedTabViewItem = anItem;
if ( droppedTabViewItem && [droppedTabViewItem respondsToSelector:#selector(itemDropped:)]){
id selectedTabViewItem = [self selectedTabViewItem];
[droppedTabViewItem performSelector:#selector(itemDropped:) withObject:selectedTabViewItem];
}
}
}
eItemDragStat = itemDragStatNormal;
// return;
// [super mouseUp:theEvent];
}
- (void)mouseDown:(NSEvent *)theEvent{
NSPoint location = [self convertPoint: [theEvent locationInWindow]
fromView: nil];
draggedItem = [self tabViewItemAtPoint:location];
NSTabViewItem *anItem = [self tabViewItemAtPoint: location];
if (anItem != nil && ![anItem isEqual: [self selectedTabViewItem]])
{
[self selectTabViewItem: anItem];
}
}
- (void)mouseDragged:(NSEvent *)theEvent{
NSPoint location = [self convertPoint: [theEvent locationInWindow]
fromView: nil];
id tabViewItemId = [self tabViewItemAtPoint:location];
NSTabViewItem *anItem = [self tabViewItemAtPoint: location];
if (anItem){
if (![anItem isEqual:draggedItem]){
if (tabViewItemId && [tabViewItemId respondsToSelector:#selector(allowDrag)]){
eItemDragStat = itemDragging;
}else{
// drag will be cancelled now.
// tell client item to stop dragging
if (eItemDragStat == itemDragging){
if ( draggedItem && [ draggedItem respondsToSelector:#selector(draggingCancelled)]){
[draggedItem performSelector:#selector(draggingCancelled)];
draggedItem = nil;
}
}
eItemDragStat = itemNotDragging;
// if we have +cursor then it should be reset
}
}else{
log(" Mouse dragged");
}
}else{
// dragging went elsewhere, lets close this dragging operation
if ( draggedItem && [ draggedItem respondsToSelector:#selector(draggingCancelled)]){
[draggedItem performSelector:#selector(draggingCancelled)];
draggedItem = nil;
}
// here reset the mouse pointer
eItemDragStat = itemNotDragging;
}
}
#end
It needs some more fine tuning and its going on....
Hi guys I really need some help, I have been stuck in this part of my game for over a week now and I can't seem to get past this issue, So have look at my code below,
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
CCSprite *mole1 = [CCSprite spriteWithFile:#"lightsabericonblue.png"];
[self starCreateCurrentLevel:mole1];
}
return self;
}
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:mole1];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:1];
}
- (void)tryPopMoles:(ccTime)dt {
if(moles.count != 0){
for (CCSprite *mole in moles) {
if (arc4random() % moles.count == 0) {
if (mole.numberOfRunningActions == 0) {
[self popMole:mole];
}
}
}
}else if(moles.count == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)mole {
mole.position = ccp(150, 150);
[self addChild:mole];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end
When I run this code i get the following error, * Assertion failure in -[HelloWorldLayer addChild:z:tag:], /Users/....../libs/cocos2d/CCNode.m:335.
I when i add the child in the init method its fine but I don't want to do that, I want to be able to call the try pop mole which will then call the pop mole based on if there is anymore sprites left in the array, I have a feeling I am missing something or doing something wrong.
UPDATE -
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
CGSize winSize;
int enemyX;
int enemyY;
int randomAngleY;
int randomAngleX;
int winSizeX;
int winSizeY;
int minDuration = 1;
int maxDuration = 4.0;
int rangeDuration;
int actualDuration;
int starCountCurrentLevel;
int test = 0;
#implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
[self starCreateCurrentLevel];
}
return self;
}
-(void)starCreateCurrentLevel{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:3];
}
- (void)tryPopMoles:(ccTime)dt {
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:moles];
for (int randomIndex = tempArray.count -1; randomIndex < tempArray.count; randomIndex--) {
CCSprite * sprite = (CCSprite *)[tempArray objectAtIndex:randomIndex];
//CCSprite *sprite = [tempArray objectAtIndex:randomIndex];
[self popMole:sprite];
NSLog(#"Enemy Added");
[tempArray removeObject:sprite];
}
if([tempArray count] == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)sprite {
winSizeX = winSize.width - sprite.contentSize.width + 25;
winSizeY = winSize.height - 25 - sprite.contentSize.height + 17;
randomAngleX = arc4random() % winSizeX;
randomAngleY = arc4random() % winSizeY;
enemyX = arc4random() % winSizeX ;
enemyY = arc4random() % winSizeY;
rangeDuration = maxDuration - minDuration;
actualDuration = (arc4random() % rangeDuration) + minDuration;
sprite.position = ccp(enemyX, enemyY);
[self addChild:sprite];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end
You're only creating the sprite once, but trying to add it several times. (Remember, these are pointers to objects, so you're always referring to exactly the same sprite.) If you want 10 versions of the same sprite (at different positions, scales, speeds, whatever), you'll need to create the sprite (via the creator method) 10 times. You can do a copy on the original one, or just create it on the fly:
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
//[moles addObject:mole1];
// ^^ You're adding the same sprite (meaning same pointer reference) again and again. Try this instead:
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
Of course, now you don't need to pass mole1 into your method. You may (depending on your need) consider passing in a spriteFrameName or something.
I was foolish and didn't test continually as I programmed, so now I'm not sure where the error has crept in. Am working on a programmable calculator. When I run, it crashes before displaying anything and gives me this message:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<CalculatorViewController 0x6a405a0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description.'
I'd use NSLog to look for the bug, but I don't know where to try it when the crash happens before anything shows up. Thoughts on what I'm doing wrong?
Here's CalculatorViewController.m, with some extra property declarations for unfinished, commented-out code I've omitted:
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic) BOOL userIsEnteringNumber;
#property (nonatomic) BOOL numberIsNegative;
#property (nonatomic,strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize descriptionLabel = _descriptionLabel;
#synthesize userIsEnteringNumber = _userIsEnteringNumber;
#synthesize numberIsNegative;
#synthesize brain = _brain;
-(CalculatorBrain *)brain
{
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
//This adds a pressed digit to the display label.
- (IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = sender.currentTitle;
//Enter digit if it wouldn't create a two-decimal-point case.
NSRange range = [self.display.text rangeOfString:#"."];
if (range.location==NSNotFound || (![digit isEqualToString:#"."]))
if (self.userIsEnteringNumber)
{
self.display.text = [self.display.text stringByAppendingString:digit];
self.descriptionLabel.text = [self.display.text stringByAppendingString:#" "];
}
else
{
self.descriptionLabel.text = [self.descriptionLabel.text stringByAppendingString:digit];
self.descriptionLabel.text = [self.descriptionLabel.text stringByAppendingString:#" "];
if (![sender.currentTitle isEqualToString:#"."])
{
self.display.text = digit;
}
else
{
self.display.text = #"0.";
}
self.userIsEnteringNumber = YES;
}
}
//This sets up an operation.
- (IBAction)operationPressed:(UIButton *)sender
{
if (self.userIsEnteringNumber) [self enterPressed];
NSString *operation = sender.currentTitle;
double result = [self.brain performOperation:operation];
self.display.text = [NSString stringWithFormat:#"%g",result];
{
NSString *descr = [self.brain description];
self.descriptionLabel.text = descr;
}
}
- (IBAction)enterPressed
{
NSCharacterSet *set = [NSCharacterSet decimalDigitCharacterSet];
NSRange range = [self.display.text rangeOfCharacterFromSet:set];
if (range.location==NSNotFound)
{
[self.brain pushOperandAsVariable:self.display.text];
}
else
{
[self.brain pushOperand:[self.display.text doubleValue]];
}
self.userIsEnteringNumber = NO;
}
#end
And here's CalculatorBrain.m:
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray *programStack;
#property (nonatomic,strong)NSDictionary *variableValues;
#end
#implementation CalculatorBrain
#synthesize programStack = _programStack;
#synthesize variableValues = _variableValues;
- (NSMutableArray *)programStack
{
if (!_programStack) _programStack = [[NSMutableArray alloc] init];
return _programStack;
}
- (id)program
{
return [self.programStack copy];
}
//Here are the two types of pushes that the ViewController can implement. First, operand pushes . . .
- (void)pushOperand:(double)operand
{
[self.programStack addObject:[NSNumber numberWithDouble:operand]];
}
//. . . and then variable pushes.
- (void) pushOperandAsVariable:(NSString *)variable
{
//Create dictionary
//Move this later on to ViewController but for now leave where it is....
NSMutableArray *variablesUsed = [[NSMutableArray alloc] init];
NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithDouble:3],[NSNumber numberWithDouble:4.1],[NSNumber numberWithDouble:-6],[NSNumber numberWithDouble:4.5298], [NSNumber numberWithDouble:3.14159], nil];
NSArray *keys = [[NSArray alloc] initWithObjects:#"x",#"y",#"z",#"foo", #"π", nil];
NSDictionary *variableValues = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
//Check program for keys
NSNumber *operand;
for (int i=0; i<keys.count; i++)
{
if ([[keys objectAtIndex:i] isEqual:variable])
[variablesUsed addObject:variable];
operand = [variableValues objectForKey:variable];
}
[self.programStack addObject:operand];
}
- (double)performOperation:(NSString *)operation
{
[self.programStack addObject:operation];
return [[self class] runProgram:self.program];
}
+ (double)popOffStack:(NSMutableArray *)stack
{
double result = 0;
id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
if ([topOfStack isKindOfClass:[NSNumber class]])
{
result = [topOfStack doubleValue];
}
//Here are the results for various operations.
else if ([topOfStack isKindOfClass:[NSString class]])
{
NSString *operation = topOfStack;
if ([operation isEqualToString:#"+"])
{
result = [self popOffStack:stack] +
[self popOffStack:stack];
}
else if ([#"*" isEqualToString:operation])
{
result = [self popOffStack:stack] *
[self popOffStack:stack];
}
else if ([operation isEqualToString:#"-"])
{
double subtrahend = [self popOffStack:stack];
result = [self popOffStack:stack] - subtrahend;
}
else if ([operation isEqualToString:#"/"])
{
double divisor = [self popOffStack:stack];
if (divisor) result = [self popOffStack:stack] / divisor;
}
else if ([operation isEqualToString:#"sin"])
{
result = sin([self popOffStack:stack]);
}
else if ([operation isEqualToString:#"cos"])
{
result = cos([self popOffStack:stack]);
}
else if ([operation isEqualToString:#"√"])
{
result = sqrt([self popOffStack:stack]);
}
else if ([operation isEqualToString:#"π"])
{
result = M_PI;
}
}
return result;
}
+ (double)runProgram:(id)program
{
//Run program.
NSMutableArray *mutableCopyOfProgram;
if ([program isKindOfClass:[NSArray class]])
{
mutableCopyOfProgram = [program mutableCopy];
return [self popOffStack:mutableCopyOfProgram];
}
else return 0;
}
#end
As always, thanks for your help.
The most common cause of this is that you have a CalculatorViewController object defined in a storyboard or xib file and something in the graphical interface has a link to an outlet on it called "description". Meanwhile, you no longer have a description outlet in the code for that class.
This will usually be fixed by tracking down the stray reference in interface builder and getting rid of it.
Is there anyway in ios app to adjust the linespacing between the multiple lines in CCLabelTTF in cocos2d? Thanks
The answer to you question is no. You can't adjust a CCLabelTTF linespacing. But hey! I will share with you my solution for this ;)
This is the .h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface CCLabelTTFLineSpaced : CCLayer {
}
+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space;
- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space;
#end
And this is the .m
#import "CCLabelTTFLineSpaced.h"
#implementation CCLabelTTFLineSpaced
+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space{
return [[[self alloc] initWithString: string dimensions:dimensions alignment:alignment fontName:name fontSize:size lineSpace:(CGFloat)space]autorelease];
}
- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space{
if( (self=[super init]) ) {
anchorPoint_ = ccp(0.5f, 0.5f);
[self setContentSize:dimensions];
self.isRelativeAnchorPoint = NO;
int pos = 0;
int i = 0;
while (pos<[str length]) {
int end = 0;
int lastCut = -1;
bool finished=NO;
while (finished==NO) {
CGSize actualSize = [[str substringWithRange:NSMakeRange(pos, end)] sizeWithFont:[UIFont fontWithName:name size:size]];
if (actualSize.width > dimensions.width || pos+end == [str length]) {
if (pos+end == [str length] && actualSize.width <= dimensions.width) lastCut = end;
finished=YES;
}
else {
if ([[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#" "] || [[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#"."] || [[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#","]) {
lastCut = end;
}
end++;
}
}
NSString * strLine = [str substringWithRange:NSMakeRange(pos, lastCut)];
CCLabelTTF * line = [CCLabelTTF labelWithString:strLine dimensions:CGSizeMake(dimensions.width, size*2) alignment:alignment fontName:name fontSize:size];
[line setAnchorPoint:ccp(0,1)];
[line setPosition:ccp(0,-i*space)];
[self addChild:line];
pos=pos+lastCut;
i++;
}
}
return self;
}
#end
Easy to use ;) I have to complete the class with getters, setters and all stuff. I know that this is a "homemade" solution, but hey! It works!
For those with Cocos 2d 2.x, I changed #Hardschool code to fix the deprecated methods and it's working awesome!
in the .h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface CCLabelTTFLineSpaced : CCLayer {
}
+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions hAlignment: (CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space;
- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space;
#end
in the .m file
#import "CCLabelTTFLineSpaced.h"
#implementation CCLabelTTFLineSpaced
+ (id) labelWithString:(NSString*)string dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space{
return [[[self alloc] initWithString: string dimensions:dimensions hAlignment:alignment fontName:name fontSize:size lineSpace:(CGFloat)space]autorelease];
}
- (id) initWithString:(NSString*)str dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size lineSpace:(CGFloat)space{
if( (self=[super init]) ) {
anchorPoint_ = ccp(0.5f, 0.5f);
[self setContentSize:dimensions];
self.ignoreAnchorPointForPosition = YES;
int pos = 0;
int i = 0;
while (pos<[str length]) {
int end = 0;
int lastCut = -1;
bool finished=NO;
while (finished==NO) {
CGSize actualSize = [[str substringWithRange:NSMakeRange(pos, end)] sizeWithFont:[UIFont fontWithName:name size:size]];
if (actualSize.width > dimensions.width || pos+end == [str length]) {
if (pos+end == [str length] && actualSize.width <= dimensions.width) lastCut = end;
finished=YES;
}
else {
if ([[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#" "] || [[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#"."] || [[str substringWithRange:NSMakeRange(pos+end, 1)] isEqualToString:#","]) {
lastCut = end;
}
end++;
}
}
NSString * strLine = [str substringWithRange:NSMakeRange(pos, lastCut)];
CCLabelTTF * line = [CCLabelTTF labelWithString:strLine dimensions:CGSizeMake(dimensions.width, size*2) hAlignment:alignment fontName:name fontSize:size];
[line setAnchorPoint:ccp(0,1)];
[line setPosition:ccp(0,-i*space)];
[self addChild:line];
pos=pos+lastCut;
i++;
}
}
return self;
}
#end
That's it, thanks #Hardschool!
gmogames, here is setColor for example
void CCLabelTTFLineSpaced::setColor(ccColor3B color)
{
for (int i = 0; i < getChildren()->count(); i ++)
{
CCLabelTTF* child = (CCLabelTTF*)getChildren()->objectAtIndex(i);
child->setColor(color);
}
}
I think this is an Issue were many Cocos2d Developers stumbled upon. So to improve readability and collaboration on this class I was creating an repository on Github for it.
Here is the link
I startet at the Version of #gmoagames (and #Hardschool), added the setColor: Method from #Alex and added a Method to fade the opacity.
Feel free to send me any merge requests if you have some more improvements.
And many thanks for all the code that was shared here.