Skip to content
Browse files

import classes

  • Loading branch information...
1 parent d3734fd commit fb6112b292a133eaa8040e8fb3ba9ed6b2b44fe8 @oscardelben committed Jan 16, 2011
Showing with 17,600 additions and 1,624 deletions.
  1. +0 −2 .gitignore
  2. +92 −0 Classes/FlurryLib/FlurryAPI.h
  3. +34 −0 Classes/FlurryLib/FlurryAdDelegate.h
  4. BIN Classes/FlurryLib/libFlurry.a
  5. +14 −0 Classes/RootViewController+FetchedController.h
  6. +141 −0 Classes/RootViewController+FetchedController.m
  7. +0 −137 Classes/RootViewController.m
  8. +81 −0 Classes/Sensible TableView/LICENSE AGREEMENT.rtf
  9. +52 −0 Classes/Sensible TableView/SCBadgeView.h
  10. +124 −0 Classes/Sensible TableView/SCBadgeView.m
  11. +733 −0 Classes/Sensible TableView/SCClassDefinition.h
  12. +891 −0 Classes/Sensible TableView/SCClassDefinition.m
  13. +114 −0 Classes/Sensible TableView/SCGlobals.h
  14. +104 −0 Classes/Sensible TableView/SCGlobals.m
  15. +618 −0 Classes/Sensible TableView/SCPropertyAttributes.h
  16. +579 −0 Classes/Sensible TableView/SCPropertyAttributes.m
  17. +1,815 −0 Classes/Sensible TableView/SCTableViewCell.h
  18. +4,657 −0 Classes/Sensible TableView/SCTableViewCell.m
  19. +183 −0 Classes/Sensible TableView/SCTableViewController.h
  20. +340 −0 Classes/Sensible TableView/SCTableViewController.m
  21. +1,197 −0 Classes/Sensible TableView/SCTableViewModel.h
  22. +1,753 −0 Classes/Sensible TableView/SCTableViewModel.m
  23. +920 −0 Classes/Sensible TableView/SCTableViewSection.h
  24. +2,409 −0 Classes/Sensible TableView/SCTableViewSection.m
  25. +175 −0 Classes/Sensible TableView/SCViewController.h
  26. +323 −0 Classes/Sensible TableView/SCViewController.m
  27. +19 −24 GreenBoardPro.xcodeproj/oscardelben.mode1v3
  28. +226 −1,461 GreenBoardPro.xcodeproj/oscardelben.pbxuser
  29. +6 −0 GreenBoardPro.xcodeproj/project.pbxproj
View
2 .gitignore
@@ -1,4 +1,2 @@
-Classes/Sensible TableView
-Classes/FlurryLib
build/
.DS_Store
View
92 Classes/FlurryLib/FlurryAPI.h
@@ -0,0 +1,92 @@
+//
+// FlurryAPI.h
+// Flurry iPhone Analytics Agent
+//
+// Copyright 2009 Flurry, Inc. All rights reserved.
+//
+#import <UIKit/UIKit.h>
+
+@class CLLocationManager;
+@class CLLocation;
+
+@interface FlurryAPI : NSObject {
+}
+
+/*
+ optional sdk settings that should be called before start session
+ */
++ (void)setAppVersion:(NSString *)version; // override the app version
++ (NSString *)getFlurryAgentVersion; // get the Flurry Agent version number
++ (void)setAppCircleEnabled:(BOOL)value; // default is NO
++ (void)setShowErrorInLogEnabled:(BOOL)value; // default is NO
++ (void)unlockDebugMode:(NSString*)debugModeKey apiKey:(NSString *)apiKey; // generate debug logs for Flurry support
++ (void)setPauseSecondsBeforeStartingNewSession:(int)seconds; // default is 10 seconds
+
+/*
+ start session, attempt to send saved sessions to server
+ */
++ (void)startSession:(NSString *)apiKey;
+
+/*
+ log events or errors after session has started
+ */
++ (void)logEvent:(NSString *)eventName;
++ (void)logEvent:(NSString *)eventName withParameters:(NSDictionary *)parameters;
++ (void)logError:(NSString *)errorID message:(NSString *)message exception:(NSException *)exception;
++ (void)logError:(NSString *)errorID message:(NSString *)message error:(NSError *)error;
+
+/*
+ start or end timed events
+ */
++ (void)logEvent:(NSString *)eventName timed:(BOOL)timed;
++ (void)logEvent:(NSString *)eventName withParameters:(NSDictionary *)parameters timed:(BOOL)timed;
++ (void)endTimedEvent:(NSString *)eventName withParameters:(NSDictionary *)parameters; // non-nil parameters will update the parameters
+
+/*
+ count page views
+ */
++ (void)countPageViews:(id)target; // automatically track page view on UINavigationController or UITabBarController
++ (void)countPageView; // manually increment page view by 1
+
+/*
+ set user info
+ */
++ (void)setUserID:(NSString *)userID; // user's id in your system
++ (void)setAge:(int)age; // user's age in years
++ (void)setGender:(NSString *)gender; // user's gender m or f
+
+/*
+ optional session settings that can be changed after start session
+ */
++ (void)setSessionReportsOnCloseEnabled:(BOOL)sendSessionReportsOnClose; // default is YES
++ (void)setSessionReportsOnPauseEnabled:(BOOL)setSessionReportsOnPauseEnabled; // default is YES
++ (void)setEventLoggingEnabled:(BOOL)value; // default is YES
+
+/*
+ create an AppCircle banner on a hook and a view parent
+ subsequent calls will return the same banner for the same hook and parent until removed with the API
+ */
++ (UIView *)getHook:(NSString *)hook xLoc:(int)x yLoc:(int)y view:(UIView *)view;
+/*
+ create an AppCircle banner on a hook and view parent using optional parameters
+ */
++ (UIView *)getHook:(NSString *)hook xLoc:(int)x yLoc:(int)y view:(UIView *)view attachToView:(BOOL)attachToView orientation:(NSString *)orientation canvasOrientation:(NSString *)canvasOrientation autoRefresh:(BOOL)refresh canvasAnimated:(BOOL)canvasAnimated;
+/*
+ update an existing AppCircle banner with a new ad
+ */
++ (void)updateHook:(UIView *)banner;
+/*
+ remove an existing AppCircle banner from its hook and parent
+ a new banner can be created on the same hook and parent after the existing banner is removed
+ */
++ (void)removeHook:(UIView *)banner;
+/*
+ open the canvas without using a banner
+ */
++ (void)openCatalog:(NSString *)hook canvasOrientation:(NSString *)canvasOrientation canvasAnimated:(BOOL)canvasAnimated;
+/*
+ refer to FlurryAdDelegate.h for delegate details
+ */
++ (void)setAppCircleDelegate:(id)delegate;
+
+@end
View
34 Classes/FlurryLib/FlurryAdDelegate.h
@@ -0,0 +1,34 @@
+//
+// FlurryAdDelegate.h
+// FlurryAnalytics
+//
+// Created by chunhao on 3/2/10.
+// Copyright 2010 Flurry Inc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+
+@protocol FlurryAdDelegate <NSObject>
+
+@optional
+/*
+ called after data is received
+ */
+- (void)dataAvailable;
+/*
+ called after data is determined to be unavailable
+ */
+- (void)dataUnavailable;
+/*
+ called before canvas displays
+ code to pause app states can be set here
+ */
+- (void)canvasWillDisplay:(NSString *)hook;
+/*
+ called before canvas closes
+ code to resume app states can be set here
+ */
+- (void)canvasWillClose;
+
+@end
View
BIN Classes/FlurryLib/libFlurry.a
Binary file not shown.
View
14 Classes/RootViewController+FetchedController.h
@@ -0,0 +1,14 @@
+//
+// RootViewController+FetchedController.h
+// GreenBoardPro
+//
+// Created by Oscar Del Ben on 1/13/11.
+// Copyright 2011 Dibi Store di Del Ben Oscar. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "RootViewController.h"
+
+@interface RootViewController (FetchedController)
+
+@end
View
141 Classes/RootViewController+FetchedController.m
@@ -0,0 +1,141 @@
+//
+// RootViewController+FetchedController.m
+// GreenBoardPro
+//
+// Created by Oscar Del Ben on 1/13/11.
+// Copyright 2011 Dibi Store di Del Ben Oscar. All rights reserved.
+//
+
+#import "RootViewController+FetchedController.h"
+#import "ApplicationHelper.h"
+
+@implementation RootViewController (FetchedController)
+
+
+#pragma mark -
+#pragma mark Fetched results controller
+
+- (NSFetchedResultsController *)fetchedResultsController {
+
+ if (fetchedResultsController_ != nil) {
+ return fetchedResultsController_;
+ }
+
+ /*
+ Set up the fetched results controller.
+ */
+ // Create the fetch request for the entity.
+ NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
+ // Edit the entity name as appropriate.
+ NSEntityDescription *entity = [NSEntityDescription entityForName:@"Idea" inManagedObjectContext:self.managedObjectContext];
+ [fetchRequest setEntity:entity];
+
+ // Set the batch size to a suitable number.
+ [fetchRequest setFetchBatchSize:20];
+
+ // Edit the sort key as appropriate.
+ NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:YES];
+ NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
+
+ [fetchRequest setSortDescriptors:sortDescriptors];
+
+ // Filter for parent_id
+ NSPredicate *predicate;
+
+ if (selectedIdea) {
+ predicate = [NSPredicate predicateWithFormat:@"parent == %@", selectedIdea];
+ } else {
+ predicate = [NSPredicate predicateWithFormat:@"parent == %@", [NSNull null]];
+ }
+
+
+ [fetchRequest setPredicate:predicate];
+
+ // Edit the section name key path and cache name if appropriate.
+ // nil for section name key path means "no sections".
+
+ // For now I'm setting cacheName to nil as I don't think it will impact performances
+ NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
+ initWithFetchRequest:fetchRequest
+ managedObjectContext:self.managedObjectContext
+ sectionNameKeyPath:nil
+ cacheName:nil];
+
+ aFetchedResultsController.delegate = self;
+ self.fetchedResultsController = aFetchedResultsController;
+
+ [aFetchedResultsController release];
+ [fetchRequest release];
+ [sortDescriptor release];
+ [sortDescriptors release];
+
+ NSError *error = nil;
+ if (![fetchedResultsController_ performFetch:&error]) {
+ NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
+
+ [ApplicationHelper showApplicationError];
+ }
+
+ return fetchedResultsController_;
+}
+
+
+#pragma mark -
+#pragma mark Fetched results controller delegate
+
+
+- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
+ [self.tableView beginUpdates];
+}
+
+
+- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
+ atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
+
+ switch(type) {
+ case NSFetchedResultsChangeInsert:
+ [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
+ break;
+
+ case NSFetchedResultsChangeDelete:
+ [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
+ break;
+ }
+}
+
+
+- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
+ atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
+ newIndexPath:(NSIndexPath *)newIndexPath {
+
+ UITableView *tableView = self.tableView;
+
+ switch(type) {
+
+ case NSFetchedResultsChangeInsert:
+ [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
+ break;
+
+ case NSFetchedResultsChangeDelete:
+ [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
+ [self updateTitle]; // reload title after deletion
+ break;
+
+ case NSFetchedResultsChangeUpdate:
+ [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
+ break;
+
+ case NSFetchedResultsChangeMove:
+ [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
+ [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
+ break;
+ }
+}
+
+
+- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
+ [self.tableView endUpdates];
+}
+
+
+@end
View
137 Classes/RootViewController.m
@@ -444,143 +444,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
}
-
-#pragma mark -
-#pragma mark Fetched results controller
-
-- (NSFetchedResultsController *)fetchedResultsController {
-
- if (fetchedResultsController_ != nil) {
- return fetchedResultsController_;
- }
-
- /*
- Set up the fetched results controller.
- */
- // Create the fetch request for the entity.
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- // Edit the entity name as appropriate.
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Idea" inManagedObjectContext:self.managedObjectContext];
- [fetchRequest setEntity:entity];
-
- // Set the batch size to a suitable number.
- [fetchRequest setFetchBatchSize:20];
-
- // Edit the sort key as appropriate.
- NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:YES];
- NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
-
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- // Filter for parent_id
- NSPredicate *predicate;
-
- if (selectedIdea) {
- predicate = [NSPredicate predicateWithFormat:@"parent == %@", selectedIdea];
- } else {
- predicate = [NSPredicate predicateWithFormat:@"parent == %@", [NSNull null]];
- }
-
-
- [fetchRequest setPredicate:predicate];
-
- // Edit the section name key path and cache name if appropriate.
- // nil for section name key path means "no sections".
-
- // For now I'm setting cacheName to nil as I don't think it will impact performances
- NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
- initWithFetchRequest:fetchRequest
- managedObjectContext:self.managedObjectContext
- sectionNameKeyPath:nil
- cacheName:nil];
-
- aFetchedResultsController.delegate = self;
- self.fetchedResultsController = aFetchedResultsController;
-
- [aFetchedResultsController release];
- [fetchRequest release];
- [sortDescriptor release];
- [sortDescriptors release];
-
- NSError *error = nil;
- if (![fetchedResultsController_ performFetch:&error]) {
- NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
-
- [ApplicationHelper showApplicationError];
- }
-
- return fetchedResultsController_;
-}
-
-
-#pragma mark -
-#pragma mark Fetched results controller delegate
-
-
-- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
- [self.tableView beginUpdates];
-}
-
-
-- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
- atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
- NSLog(@"Foo");
- switch(type) {
- case NSFetchedResultsChangeInsert:
- [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
- break;
-
- case NSFetchedResultsChangeDelete:
- [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
- break;
- }
-}
-
-
-- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
- atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
- newIndexPath:(NSIndexPath *)newIndexPath {
-
- UITableView *tableView = self.tableView;
-
- switch(type) {
-
- case NSFetchedResultsChangeInsert:
- [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
- break;
-
- case NSFetchedResultsChangeDelete:
- [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
- [self updateTitle]; // reload title after deletion
- break;
-
- case NSFetchedResultsChangeUpdate:
- [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
- break;
-
- case NSFetchedResultsChangeMove:
- [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
- [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
- break;
- }
-}
-
-
-- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
- [self.tableView endUpdates];
-}
-
-
-/*
-// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed.
-
- - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
- // In the simplest, most efficient, case, reload the table view.
- [self.tableView reloadData];
-}
- */
-
-
#pragma mark -
#pragma mark Memory management
View
81 Classes/Sensible TableView/LICENSE AGREEMENT.rtf
@@ -0,0 +1,81 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320
+{\fonttbl\f0\froman\fcharset0 Times-Roman;}
+{\colortbl;\red255\green255\blue255;}
+\paperw12240\paperh15840\vieww9000\viewh8400\viewkind0
+\deftab720
+\pard\pardeftab720\sa240\ql\qnatural
+
+\f0\b\fs24 \cf0 \
+IMPORTANT \'97 READ CAREFULLY:
+\b0 This license agreement ("LICENSE") is a legal agreement between you (either an individual or a single entity, also referred to as "LICENSEE", "YOU") and Sensible Cocoa, ("Sensible Cocoa"), for the use of Sensible Cocoa's product "Sensible TableView", which may contain source code, associated media, and "online" or electronic documentation (collectively referred to as "SOFTWARE").\
+Any earlier license we may have granted to you for the use of earlier versions of the SOFTWARE is replaced by this LICENSE.\
+The SOFTWARE is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties and contains confidential information and trade secrets. Sensible Cocoa retains all rights not expressly granted to you in this LICENSE.\
+\'a0\
+I.
+\b GRANT OF LICENSE
+\b0 \
+Sensible Cocoa hereby grants to you, and you accept, a non\'96exclusive, non\'96transferable license to install, copy, use and modify the SOFTWARE only as authorized below. \'a0\
+ 1. DEVELOPER LICENSE\
+ The SOFTWARE is licensed per Developer seat. This means that each individual using or otherwise accessing the SOFTWARE for development purposes must obtain the right to do so by purchasing an individual product license.\
+ You may make copies on more than one computer, as long as the use of the SOFTWARE is by the same licensed developer. The SOFTWARE is in "use" on a computer when it is loaded into temporary memory (i.e. RAM) or installed into permanent memory (e.g. hard disk or other storage device) of that computer for development purposes. If you install the SOFTWARE on a network server for the sole purpose of internal distribution among licensed developers this is not considered "use" of the SOFTWARE, so long as each individual developer has purchased a license.\
+ 1\'961. Redistribution rights:\'a0\
+ You may distribute the SOFTWARE (or, where applicable, the run\'96time portion of the SOFTWARE) provided that:\'a0\
+\'a0 You distribute the SOFTWARE, in compiled form only, as part of solutions for internal company use, or commercial solutions deployed at end\'96users\'92 devices or shrink\'96wrapped software (PACKAGED PRODUCTS) in which the SOFTWARE is integrated.\'a0\
+ You ensure that the SOFTWARE is not distributed in any form that allows it to be reused by any application other than your solution.\
+ You duly inform your customers that they are not allowed to use the SOFTWARE independently from your solution. For use of the SOFTWARE, your customers need to purchase the appropriate number of Developer Licenses from Sensible Cocoa.\'a0\
+ You assume full responsibility for your customer\'92s use of the SOFTWARE and must ensure that Sensible Cocoa has no obligation to such customer or liability for such customer\'92s use of the SOFTWARE.\'a0\
+ All product licenses granted by you to your end user customers in accordance with the terms of this agreement are perpetual and royalty\'96free.\
+\'a0 1-2. Source Code Modification:\
+ You are allowed to modify and/or extend the provided source code for your internal use only, and in accordance with the license limitations provided below.\
+ 1\'963. Standard Support:\
+ As part of your Developer License you are entitled to Sensible Cocoa\'92s "Standard" Support Package for a period of ninety (90) days, which guarantees an initial response to (but not necessarily a complete resolution of) your issue within forty eight (48) hours during business days. \
+\
+
+\b II. LICENSE LIMITATIONS
+\b0 \
+\'95 At no time may the SOFTWARE be used for development purposes by individuals other than the licensed developer(s).\'a0\
+\'95 The SOFTWARE may not be distributed for use with solutions or PACKAGED PRODUCTS other than those developed by you.\'a0\
+\'95 The SOFTWARE may not be distributed as part of products that have the same or substantially the same primary functionality as the SOFTWARE.\
+\'95 You are not allowed to resell, transfer, rent, lease, or sublicense the SOFTWARE and your associated rights, other than to sublicense to end users the nonsublicensable, nontransferable right to use the SOFTWARE in object code form as part of your solution. Under no circumstances shall you grant further redistribution rights to the end\'96users of your solution.\'a0\
+\'95 You may not use the Sensible Cocoa product names, logos or trademarks to market your software.\'a0\
+\'95 You are not allowed to reverse engineer or to disassemble, decompile or "unlock", decode or otherwise reverse translate or attempt in any manner to reconstruct or discover any source code or underlying algorithms of SOFTWARE provided in compiled form only, subject to applicable law to the contrary.\'a0\
+\'95 You are not allowed to use, copy, modify, or merge copies of the SOFTWARE or any accompanying documents except as permitted in this LICENSE.\'a0\
+\'95 As a condition to the exercise or your redistribution rights, you agree to indemnify, hold harmless, and defend Sensible Cocoa and its resellers from and against any and all claims or lawsuits including attorney's fees that arise or result from the use or distribution of your software.\'a0\
+\'a0\
+
+\b III. DELIVERY
+\b0 \
+Sensible Cocoa shall deliver to LICENSEE a master copy of the SOFTWARE licensed hereunder in electronic format only. Documentation shall also be provided in electronic format.\
+\'a0\'a0\
+
+\b IV. TERMINATION
+\b0 \
+This LICENSE shall last as long as you use the SOFTWARE in compliance with this LICENSE. Sensible Cocoa may terminate this LICENSE if you fail to comply with any of the terms and conditions herein. In such event you agree to remove and destroy all copies of the SOFTWARE and any applicable source code.\
+\'a0\
+Sensible Cocoa reserves the right to discontinue at any time any product, whether it is offered individually or as a part of a product suite. However, Sensible Cocoa will fulfill any contractual obligations to provide support for discontinued products that exist as of the date of discontinuation.\
+\'a0\
+
+\b V. COPYRIGHT
+\b0 \
+All title and copyrights in and to the SOFTWARE (including but not limited to any images, photographs, animations, video, audio, music, text, incorporated into the SOFTWARE), the accompanying printed materials, and any copies of the SOFTWARE, and any trademarks or service marks of Sensible Cocoa are owned by Sensible Cocoa or its licensors unless explicitly stated otherwise. All title and intellectual property rights in and to the content that may be accessed through use of the SOFTWARE is the property of the respective content owner and may be protected by applicable copyright or other intellectual property laws and treaties. This LICENSE grants you no rights to use such content.\
+\'a0\
+
+\b VI. LIMITED WARRANTY
+\b0 \
+Sensible Cocoa warrants solely that the SOFTWARE will perform substantially in accordance with the accompanying user documentation a period of ninety (90) days. Sensible Cocoa does not warrant the use of the SOFTWARE will be uninterrupted or error free at all times and in all circumstances, nor that program errors will be corrected. This limited warranty shall not apply to any error or failure resulting from (i) machine error, (ii) LICENSEE's failure to follow operating instructions, (iii) negligence or accident, or (iv) modifications to the SOFTWARE by any person or entity other than Sensible Cocoa. In the event of a breach of warranty, LICENSEE 's sole and exclusive remedy, is repair of all or any portion of the SOFTWARE. If such remedy fails of its essential purpose, LICENSEE 's sole remedy and Sensible Cocoa's maximum liability shall be a refund of the paid purchase price for the defective SOFTWARE only. This limited warranty is only valid if Sensible Cocoa receives written notice of breach of warranty no later than thirty (30) days after the warranty period expires. EXCEPT FOR THE EXPRESS WARRANTIES SET FORTH IN THIS LICENSE, SENSIBLE COCOA DISCLAIMS ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF TITLE, NONINFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\
+\'a0\
+
+\b VII. LIMITATION OF LIABILITY
+\b0 \
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL SENSIBLE COCOA BE LIABLE FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF OR INABILITY TO USE THE PRODUCT, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED. IN ANY CASE, SENSIBLE COCOA'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS AGREEMENT SHALL NOT EXCEED IN THE AGGREGATE THE SUM OF THE LICENSE FEES LICENSEE PAID TO SENSIBLE COCOA FOR THE PRODUCT GIVING RISE TO SUCH DAMAGES, NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT BE APPLICABLE. SENSIBLE COCOA IS NOT RESPONSIBLE FOR ANY LIABILITY ARISING OUT OF CONTENT PROVIDED BY LICENSEE OR A THIRD PARTY THAT IS ACCESSED THROUGH THE PRODUCT AND/OR ANY MATERIAL LINKED THROUGH SUCH CONTENT. ANY DATA INCLUDED IN A PRODUCT UPON SHIPMENT FROM SENSIBLE COCOA IS FOR TESTING USE ONLY AND SENSIBLE COCOA HEREBY DISCLAIMS ANY AND ALL LIABILITY ARISING THEREFROM. THE EXTENT OF SENSIBLE COCOA'S LIABILITY FOR THE LIMITED WARRANTY SECTION SHALL BE AS SET FORTH THEREIN.\
+\'a0\
+
+\b VIII. MISCELLANEOUS
+\b0 \
+This License will be governed by the law of the state of New York, U.S.A., without regard to the conflict of laws principles thereof. The Uniform Computer Information Transactions Act and the United Nations Convention on the International Sale of Goods shall not apply to this Agreement. If any provision of this LICENSE is to be held unenforceable, such holding will not affect the validity of the other provisions hereof. Failure of a party to enforce any provision of this LICENSE shall not constitute or be construed as a waiver of such provision or of the right to enforce such provision.\
+\'a0\
+This License represents the entire understanding between the parties with respect to its subject matter.\
+\'a0\
+YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, THAT YOU UNDERSTAND THIS AGREEMENT, AND UNDERSTAND THAT BY USING OF SOFTWARE PRODUCT, BY LOADING OR RUNNING THE SOFTWARE PRODUCT, OR BY PLACING OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU AGREE TO BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU FURTHER AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN SENSIBLE COCOA AND YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE RIGHTS AND LIABILITIES OF THE PARTIES.\
+\
+}
View
52 Classes/Sensible TableView/SCBadgeView.h
@@ -0,0 +1,52 @@
+/*
+ * SCBadgeView.h
+ * Sensible TableView
+ *
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY UNITED STATES
+ * INTELLECTUAL PROPERTY LAW AND INTERNATIONAL TREATIES. UNAUTHORIZED REPRODUCTION OR
+ * DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. YOU SHALL NOT DEVELOP NOR
+ * MAKE AVAILABLE ANY WORK THAT COMPETES WITH A SENSIBLE COCOA PRODUCT DERIVED FROM THIS
+ * SOURCE CODE. THIS SOURCE CODE MAY NOT BE RESOLD OR REDISTRIBUTED ON A STAND ALONE BASIS.
+ *
+ * USAGE OF THIS SOURCE CODE IS BOUND BY THE LICENSE AGREEMENT PROVIDED WITH THE
+ * DOWNLOADED PRODUCT.
+ *
+ * Copyright 2010 Sensible Cocoa. All rights reserved.
+ *
+ *
+ * This notice may not be removed from this file.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+
+/****************************************************************************************/
+/* class SCBadgeView */
+/****************************************************************************************/
+/*!
+ * This class functions as a badge similar to the one used by iPhone's mail application to
+ * display the number of messages in an inbox. %SCBadgeView is most commonly used by SCTableViewCell.
+ */
+@interface SCBadgeView : UIView
+{
+ UIColor *color;
+ NSString *text;
+ UIFont *font;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Configuration
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! The color of the badge. */
+@property (nonatomic, retain) UIColor *color;
+
+/*! The text displayed by the badge. */
+@property (nonatomic, copy) NSString *text;
+
+/*! The font of the text. */
+@property (nonatomic, retain) UIFont *font;
+
+@end
View
124 Classes/Sensible TableView/SCBadgeView.m
@@ -0,0 +1,124 @@
+/*
+ * SCBadgeView.m
+ * Sensible TableView
+ *
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY UNITED STATES
+ * INTELLECTUAL PROPERTY LAW AND INTERNATIONAL TREATIES. UNAUTHORIZED REPRODUCTION OR
+ * DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. YOU SHALL NOT DEVELOP NOR
+ * MAKE AVAILABLE ANY WORK THAT COMPETES WITH A SENSIBLE COCOA PRODUCT DERIVED FROM THIS
+ * SOURCE CODE. THIS SOURCE CODE MAY NOT BE RESOLD OR REDISTRIBUTED ON A STAND ALONE BASIS.
+ *
+ * USAGE OF THIS SOURCE CODE IS BOUND BY THE LICENSE AGREEMENT PROVIDED WITH THE
+ * DOWNLOADED PRODUCT.
+ *
+ * Copyright 2010 Sensible Cocoa. All rights reserved.
+ *
+ *
+ * This notice may not be removed from this file.
+ *
+ */
+
+#import "SCBadgeView.h"
+
+
+@implementation SCBadgeView
+
+@synthesize text;
+@synthesize font;
+@synthesize color;
+
+- (id)initWithFrame:(CGRect)aRect
+{
+ if( (self = [super initWithFrame:aRect]) )
+ {
+ text = nil;
+ font = [[UIFont boldSystemFontOfSize: 16] retain];
+ color = [[UIColor colorWithRed:140.0f/255 green:153.0f/255 blue:180.0f/255 alpha:1] retain];
+
+ self.backgroundColor = [UIColor clearColor];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [text release];
+ [font release];
+ [color release];
+
+ [super dealloc];
+}
+
+// overrides superclass
+- (void)drawRect:(CGRect)rect
+{
+ if(!self.text)
+ return;
+
+ UIColor *badgeColor = self.color;
+ UIView *spview = self.superview;
+ while (spview)
+ {
+ if([spview isKindOfClass:[UITableViewCell class]])
+ {
+ UITableViewCell *ownerCell = (UITableViewCell *)spview;
+
+ if(ownerCell.highlighted || ownerCell.selected)
+ badgeColor = [UIColor whiteColor];
+
+ break;
+ }
+
+ spview = spview.superview;
+ }
+
+
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextSaveGState(context);
+ CGContextSetFillColorWithColor(context, [badgeColor CGColor]);
+ CGContextBeginPath(context);
+ CGFloat radius = self.bounds.size.height / 2.0;
+ CGContextAddArc(context, radius, radius, radius, M_PI/2 , 3*M_PI/2, NO);
+ CGContextAddArc(context, self.bounds.size.width - radius, radius, radius, 3*M_PI/2, M_PI/2, NO);
+ CGContextClosePath(context);
+ CGContextFillPath(context);
+ CGContextRestoreGState(context);
+
+ CGContextSetBlendMode(context, kCGBlendModeClear);
+
+ CGSize textSize = CGSizeMake(0, 0);
+ if(self.text)
+ textSize = [self.text sizeWithFont:self.font];
+ CGRect textBounds = CGRectMake(round((self.bounds.size.width-textSize.width)/2),
+ round((self.bounds.size.height-textSize.height)/2),
+ textSize.width, textSize.height);
+ [self.text drawInRect:textBounds withFont:self.font];
+}
+
+- (void)setColor:(UIColor *)_color
+{
+ [color release];
+ color = [_color copy];
+
+ [self setNeedsDisplay];
+}
+
+- (void)setText:(NSString *)_text
+{
+ [text release];
+ text = [_text copy];
+
+ [self setNeedsDisplay];
+}
+
+- (void)setFont:(UIFont *)_font
+{
+ [font release];
+ font = [_font retain];
+
+ [self setNeedsDisplay];
+}
+
+@end
View
733 Classes/Sensible TableView/SCClassDefinition.h
@@ -0,0 +1,733 @@
+/*
+ * SCClassDefinition.h
+ * Sensible TableView
+ *
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY UNITED STATES
+ * INTELLECTUAL PROPERTY LAW AND INTERNATIONAL TREATIES. UNAUTHORIZED REPRODUCTION OR
+ * DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. YOU SHALL NOT DEVELOP NOR
+ * MAKE AVAILABLE ANY WORK THAT COMPETES WITH A SENSIBLE COCOA PRODUCT DERIVED FROM THIS
+ * SOURCE CODE. THIS SOURCE CODE MAY NOT BE RESOLD OR REDISTRIBUTED ON A STAND ALONE BASIS.
+ *
+ * USAGE OF THIS SOURCE CODE IS BOUND BY THE LICENSE AGREEMENT PROVIDED WITH THE
+ * DOWNLOADED PRODUCT.
+ *
+ * Copyright 2010 Sensible Cocoa. All rights reserved.
+ *
+ *
+ * This notice may not be removed from this file.
+ *
+ */
+
+
+#import <Foundation/Foundation.h>
+#import "SCPropertyAttributes.h"
+
+
+@class SCTableViewCell;
+
+
+typedef enum
+{
+ SCPropertyDataTypeNSString,
+ SCPropertyDataTypeNSNumber,
+ SCPropertyDataTypeNSDate,
+ SCPropertyDataTypeNSMutableSet,
+ SCPropertyDataTypeNSMutableArray,
+ SCPropertyDataTypeNSObject,
+ SCPropertyDataTypeDictionaryItem,
+ SCPropertyDataTypeTransformable,
+ SCPropertyDataTypeOther
+} SCPropertyDataType;
+
+
+/*! The types of an SCPropertyDefinition */
+typedef enum
+{
+ /*! The object bound to the property will detect the best user interface element to generate. */
+ SCPropertyTypeAutoDetect,
+ /*! The object bound to the property will generate an SCLabelCell interface element */
+ SCPropertyTypeLabel,
+ /*! The object bound to the property will generate an SCTextViewCell interface element */
+ SCPropertyTypeTextView,
+ /*! The object bound to the property will generate an SCTextFieldCell interface element */
+ SCPropertyTypeTextField,
+ /*! The object bound to the property will generate an SCNumericTextFieldCell interface element */
+ SCPropertyTypeNumericTextField,
+ /*! The object bound to the property will generate an SCSliderCell interface element */
+ SCPropertyTypeSlider,
+ /*! The object bound to the property will generate an SCSegmentedCell interface element */
+ SCPropertyTypeSegmented,
+ /*! The object bound to the property will generate an SCSwitchCell interface element */
+ SCPropertyTypeSwitch,
+ /*! The object bound to the property will generate an SCDateCell interface element */
+ SCPropertyTypeDate,
+ /*! The object bound to the property will generate an SCImagePickerCell interface element */
+ SCPropertyTypeImagePicker,
+ /*! The object bound to the property will generate an SCSelectionCell interface element */
+ SCPropertyTypeSelection,
+ /*! The object bound to the property will generate an SCObjectSelectionCell interface element */
+ SCPropertyTypeObjectSelection,
+ /*! The object bound to the property will generate an SCObjectCell interface element */
+ SCPropertyTypeObject,
+ /*! The object bound to the property will generate an SCArrayOfObjectsCell interface element */
+ SCPropertyTypeArrayOfObjects,
+ /*! The object bound to the property will not generate an interface element */
+ SCPropertyTypeNone
+
+} SCPropertyType;
+
+
+/****************************************************************************************/
+/* class SCPropertyDefinition */
+/****************************************************************************************/
+/*!
+ * This class functions as a property definition for SCClassDefinition. Every property
+ * definition should set a property type that determines which user interface element
+ * should be generated for the property. In addition, the generated user interface element
+ * can be further customized using the property's attributes.
+ *
+ * See also: SCPropertyType, SCPropertyAttributes, SCClassDefinition.
+ *
+ */
+@interface SCPropertyDefinition : NSObject
+{
+ SCPropertyDataType dataType;
+ BOOL dataReadOnly;
+ NSString *name;
+ NSString *title;
+ SCPropertyType type;
+ BOOL required;
+ BOOL autoValidate;
+ SCPropertyAttributes *attributes;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Creation and Initialization
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! Allocates and returns an initialized %SCPropertyDefinition given a property name.
+ *
+ * @param propertyName The name of the property.
+ */
++ (id)definitionWithName:(NSString *)propertyName;
+
+/*! Allocates and returns an initialized %SCPropertyDefinition given a property name,
+ * title, and type.
+ *
+ * @param propertyName The name of the property.
+ * @param propertyTitle The title of the property. Property titles are used by user
+ * interface elements to generate labels associated with the generated controls.
+ * @param propertyType The property type determines which user interface element will
+ * be generated for the property.
+ */
++ (id)definitionWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType;
+
+/*! Returns an initialized %SCPropertyDefinition given a property name.
+ *
+ * @param propertyName The name of the property.
+ */
+- (id)initWithName:(NSString *)propertyName;
+
+/*! Returns an initialized %SCPropertyDefinition given a property name,
+ * title, and type.
+ *
+ * @param propertyName The name of the property.
+ * @param propertyTitle The title of the property. Property titles are used by user
+ * interface elements to generate labels associated with the generated controls.
+ * @param propertyType The property type determines which user interface element will
+ * be generated for the property.
+ */
+- (id)initWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Configuration
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! The name of the property associated with the property definition. */
+@property (nonatomic, readonly) NSString *name;
+
+/*! The title of the property. Property titles are used by user
+ * interface elements to generate labels associated with the generated controls.*/
+@property (nonatomic, copy) NSString *title;
+
+/*! The type of the property. Property types determines which user interface element will
+ * be generated for the property. */
+@property (nonatomic, readwrite) SCPropertyType type;
+
+/*! The attibutes set of the property. Property attributes gives the user the ability
+ * to further customize the user interface element that will be generated for the property. */
+@property (nonatomic, retain) SCPropertyAttributes *attributes;
+
+/*! Set to TRUE if property is a required property. Default: FALSE. */
+@property (nonatomic, readwrite) BOOL required;
+
+/*! Set to TRUE if the property value should be automatically validated by the user interface element
+ * before commiting it to the property. If the user chooses to provide custom validation
+ * using either the cell's SCTableViewCellDelegate, or the model's SCTableViewModelDelegate, they should
+ * set this property to FALSE. Default: TRUE. */
+@property (nonatomic, readwrite) BOOL autoValidate;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Internal
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! This property is automatically set by the framework and should never be assigned a
+ * value directly. */
+@property (nonatomic, readwrite) SCPropertyDataType dataType;
+
+/*! This property is automatically set by the framework and should never be assigned a
+ * value directly. */
+@property (nonatomic, readwrite) BOOL dataReadOnly;
+
+@end
+
+
+
+
+
+/****************************************************************************************/
+/* class SCCustomPropertyDefinition */
+/****************************************************************************************/
+/*!
+ * This class functions as a property definition for SCClassDefinition that will generate
+ * a custom user inteface element (e.g.: custom cell). %SCCustomPropertyDefinition does not have
+ * to represent a property that actually exists in its class (unlike an SCPropertyDefiniton),
+ * and is often used in a class definition as a placeholder for custom user
+ * interface element generation.
+ *
+ * See also: SCPropertyDefinition, SCClassDefinition.
+ *
+ */
+@interface SCCustomPropertyDefinition : SCPropertyDefinition
+{
+ NSObject *uiElement;
+ NSDictionary *objectBindings;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Creation and Initialization
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! Allocates and returns an initialized %SCCustomPropertyDefinition given a property name and
+ * a custom user interface element to generate.
+ *
+ * @param propertyName The name of the property.
+ * @param element The custom user interface element that will be generated.
+ * @param bindings This dictionary specifies how each
+ * of the uiElement's custom controls binds itself to the class definition's properties.
+ * Each dictionary key
+ * should be the tag string value of one of the uiElement's custom controls, and the value should be the
+ * name of the class definition's property that is bound to that control.
+ * IMPORTANT: All control tags must be greater than zero.
+ */
++ (id)definitionWithName:(NSString *)propertyName
+ withuiElement:(NSObject *)element
+ withObjectBindings:(NSDictionary *)bindings;
+
+/*! Allocates and returns an initialized %SCCustomPropertyDefinition given a property name and
+ * the name of the nib file containing the custom user interface element to generate.
+ *
+ * @param propertyName The name of the property.
+ * @param elementNibName The name of the nib file containing the custom user interface element
+ * that will be generated.
+ * @param bindings This dictionary specifies how each
+ * of the uiElement's custom controls binds itself to the class definition's properties.
+ * Each dictionary key
+ * should be the tag string value of one of the uiElement's custom controls, and the value should be the
+ * name of the class definition's property that is bound to that control.
+ * IMPORTANT: All control tags must be greater than zero.
+ */
++ (id)definitionWithName:(NSString *)propertyName
+ withuiElementNibName:(NSString *)elementNibName
+ withObjectBindings:(NSDictionary *)bindings;
+
+/*! Returns an initialized %SCCustomPropertyDefinition given a property name and
+ * a custom user interface element to generate.
+ *
+ * @param propertyName The name of the property.
+ * @param element The custom user interface element that will be generated.
+ * @param bindings This dictionary specifies how each
+ * of the uiElement's custom controls binds itself to the class definition's properties.
+ * Each dictionary key
+ * should be the tag string value of one of the uiElement's custom controls, and the value should be the
+ * name of the class definition's property that is bound to that control.
+ * IMPORTANT: All control tags must be greater than zero.
+ */
+- (id)initWithName:(NSString *)propertyName
+ withuiElement:(NSObject *)element
+withObjectBindings:(NSDictionary *)bindings;
+
+/*! Returns an initialized %SCCustomPropertyDefinition given a property name and
+ * the name of the nib file containing the custom user interface element to generate.
+ *
+ * @param propertyName The name of the property.
+ * @param elementNibName The name of the nib file containing the custom user interface element
+ * that will be generated.
+ * @param bindings This dictionary specifies how each
+ * of the uiElement's custom controls binds itself to the class definition's properties.
+ * Each dictionary key
+ * should be the tag string value of one of the uiElement's custom controls, and the value should be the
+ * name of the class definition's property that is bound to that control.
+ * IMPORTANT: All control tags must be greater than zero.
+ */
+- (id)initWithName:(NSString *)propertyName
+ withuiElementNibName:(NSString *)elementNibName
+ withObjectBindings:(NSDictionary *)bindings;
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Configuration
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! The custom user interface element the property will generate. */
+@property (nonatomic, readonly) NSObject *uiElement;
+
+/*! This dictionary specifies how each
+ * of the uiElement's custom controls binds itself to the class definition's properties.
+ * Each dictionary key
+ * should be the tag string value of one of the uiElement's custom controls, and the value should be the
+ * name of the class definition's property that is bound to that control.
+ * IMPORTANT: All control tags must be greater than zero.
+ */
+@property (nonatomic, retain) NSDictionary *objectBindings;
+
+@end
+
+
+
+
+
+
+
+
+/****************************************************************************************/
+/* class SCClassDefinition */
+/****************************************************************************************/
+/*!
+ * This class functions as a means to further extend the definition of user-defined classes.
+ * Using class definitions, classes like SCObjectCell and SCObjectSection
+ * will be able to better generate user interface elements that truly represent the
+ * properties of their bound objects.
+ *
+ * %SCClassDefinition mainly consists of one or more property definitions of type SCPropertyDefinition.
+ * Upon creation, %SCClassDefinition will (optionally) automatically generate all the
+ * property definitions for the given class. From there, the user will be able to customize
+ * the generated property definitions, add new definitions, or remove generated definitions.
+ *
+ * See also: SCPropertyDefinition.
+ */
+@interface SCClassDefinition : NSObject
+{
+ Class cls;
+
+#ifdef _COREDATADEFINES_H
+ NSEntityDescription *entity;
+ NSManagedObjectContext *managedObjectContext;
+#endif
+
+ NSMutableArray *propertyDefinitions;
+ NSString *keyPropertyName;
+ NSString *titlePropertyName;
+ NSString *titlePropertyNameDelimiter;
+ NSString *descriptionPropertyName;
+ id uiElementDelegate;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Creation and Initialization
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class and the option to
+ * auto generate property definitions for the given class.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the generated properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param autoGenerate If TRUE, %SCClassDefinition will automatically
+ * generate all the property definitions for the given class.
+ */
++ (id)definitionWithClass:(Class)_cls autoGeneratePropertyDefinitions:(BOOL)autoGenerate;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class and an array of
+ * the property names to generate property definitions from.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the given properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ */
++ (id)definitionWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class, an array of
+ * the property names to generate property definitions from, and array of titles
+ * for these properties.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ * @param propertyTitles An array of titles to the properties in propertyNames. All array
+ * elements must be of type NSString.
+ */
++ (id)definitionWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class and the option to
+ * auto generate property definitions for the given class.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the generated properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param autoGenerate If TRUE, %SCClassDefinition will automatically
+ * generate all the property definitions for the given class.
+ */
+- (id)initWithClass:(Class)_cls autoGeneratePropertyDefinitions:(BOOL)autoGenerate;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class and an array of
+ * the property names to generate property definitions from.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the given properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ */
+- (id)initWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a class, an array of
+ * the property names to generate property definitions from, and array of titles
+ * for these properties.
+ *
+ * @param _cls A class for which the definition will be extended.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ * @param propertyTitles An array of titles to the properties in propertyNames. All array
+ * elements must be of type NSString.
+ */
+- (id)initWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles;
+
+
+#ifdef _COREDATADEFINES_H
+
+/*! Allocates and returns an initialized %SCClassDefinition given a Core Data entity name and the option to
+ * auto generate property definitions for the given entity's properties.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the generated properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param autoGenerate If TRUE, %SCClassDefinition will automatically
+ * generate all the property definitions for the given entity's attributes.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ autoGeneratePropertyDefinitions:(BOOL)autoGenerate;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a Core Data entity name and an array of
+ * the property names to generate property definitions for.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the given properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames;
+
+/*! Allocates and returns an initialized %SCClassDefinition given a Core Data entity name, an array of
+ * the property names to generate property definitions for, and array of titles
+ * for these properties.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ * @param propertyTitles An array of titles to the properties in propertyNames. All array
+ * elements must be of type NSString.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles;
+
+/*! Returns an initialized %SCClassDefinition given a Core Data entity name and the option to
+ * auto generate property definitions for the given entity's properties.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the generated properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param autoGenerate If TRUE, %SCClassDefinition will automatically
+ * generate all the property definitions for the given entity's attributes.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
+- (id)initWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ autoGeneratePropertyDefinitions:(BOOL)autoGenerate;
+
+/*! Returns an initialized %SCClassDefinition given a Core Data entity name and an array of
+ * the property names to generate property definitions for.
+ *
+ * The method will also generate user friendly property titles from the names of
+ * the given properties. These titles can be modified by the user later as part of
+ * the property definition customization.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
+- (id)initWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames;
+
+/*! Returns an initialized %SCClassDefinition given a Core Data entity name, an array of
+ * the property names to generate property definitions for, and array of titles
+ * for these properties.
+ *
+ * @param entityName The name of the entity for which the definition will be extended.
+ * @param context The managed object context of the entity.
+ * @param propertyNames An array of the names of properties to be generated. All array
+ * elements must be of type NSString.
+ * @param propertyTitles An array of titles to the properties in propertyNames. All array
+ * elements must be of type NSString.
+ *
+ * Note: This method is used when creating an extended class definition for Core Data's managed object.
+ */
+- (id)initWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles;
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Configuration
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! The class associated with the definition. Note: Only applicable with class definition is
+ * initialized with a class. */
+@property (nonatomic, readonly) Class cls;
+
+#ifdef _COREDATADEFINES_H
+/*! The entity associated with the definition. Note: Only applicable when class definition is
+ * initialized with an entity name. */
+@property (nonatomic, readonly, retain) NSEntityDescription *entity;
+
+/*! The managed object context of the entity associated with the definition. Note: Only
+ * applicable when class definition is initialized with an entity name. */
+@property (nonatomic, readonly, retain) NSManagedObjectContext *managedObjectContext;
+#endif
+
+/*! The string name of cls or entity */
+@property (nonatomic, readonly) NSString *className;
+
+/*! The key of the entity associated with the definition. The key is usually used when
+ * a set of entities is sorted. By default, %SCClassDefinition sets this property to the name of the
+ * first property in the entity. Note: Only applicable when class definition is
+ * initialized with an entity name. */
+@property (nonatomic, copy) NSString *keyPropertyName;
+
+/*! The name of the title property for the class or entity. Title properties are used in user
+ * interface elements to display title information based on the value of the property
+ * named here. By default, %SCClassDefinition sets this property to the name of the
+ * first property in cls or entity. Note: To have the title set to more than one property value,
+ * separate the property names by a semi-colon (e.g.: @"firstName;lastName"). When displayed, the
+ * titles will be separated by the value of the titlePropertyNameDelimiter property. */
+@property (nonatomic, copy) NSString *titlePropertyName;
+
+/*! The delimiter used to separate the titles specified in titlePropertyName. Default: @" ". */
+@property (nonatomic, copy) NSString *titlePropertyNameDelimiter;
+
+/*! The name of the description property for the class or entity. Description properties are used in user
+ * interface elements to display description information based on the value of the property
+ * named here. */
+@property (nonatomic, copy) NSString *descriptionPropertyName;
+
+/*! The delegate for the user interface elements that will be generated for the property definitions. */
+@property (nonatomic, assign) id uiElementDelegate;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Managing Property Definitions
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! The number of property definitions. */
+@property (nonatomic, readonly) NSUInteger propertyDefinitionCount;
+
+/*! Methods adds a new property definition.
+ * @param propertyName The name of the property.
+ * @param propertyTitle The title of the property. If no value is provided,
+ * the method automatically generates a user friendly name for the property.
+ * @param propertyType The property type.
+ * @return Returns TRUE if adding the definition was successful. The main reason for
+ * addition failure is if the property name does not match an existing property in cls.
+ */
+- (BOOL)addPropertyDefinitionWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType;
+
+/*! Methods adds a new property definition.
+ * @param propertyDefinition The property definition to be added.
+ * @return Returns TRUE if adding the definition was successful. The main reason for
+ * addition failure is if the property name does not match an existing property in cls
+ * (not required if property definition is an SCCustomPropertyDefinition).
+ */
+- (BOOL)addPropertyDefinition:(SCPropertyDefinition *)propertyDefinition;
+
+/*! Methods inserts a new property definition at the given index.
+ * @param propertyDefinition The property definition to be added.
+ * @param index The index to insert the property definition at. Must be less than propertyDefinitionCount.
+ * @return Returns TRUE if inserting the definition was successful. The main reason for
+ * insertion failure is if the property name does not match an existing property in cls
+ * (not required if property definition is an SCCustomPropertyDefinition).
+ */
+- (BOOL)insertPropertyDefinition:(SCPropertyDefinition *)propertyDefinition
+ atIndex:(NSInteger)index;
+
+/*! Removes the property definition at the given index.
+ * @param index Must be less than the total number of property definitions. */
+- (void)removePropertyDefinitionAtIndex:(NSUInteger)index;
+
+/*! Removes the property definition with the given name.
+ * @param propertyName The name of the property to be removed. */
+- (void)removePropertyDefinitionWithName:(NSString *)propertyName;
+
+/*! Returns the property definition at the given index.
+ * @param index Must be less than the total number of property definitions. */
+- (SCPropertyDefinition *)propertyDefinitionAtIndex:(NSUInteger)index;
+
+/*! Returns the property definition with the given name.
+ * @param propertyName The name of the property who's definition to be returned. */
+- (SCPropertyDefinition *)propertyDefinitionWithName:(NSString *)propertyName;
+
+/*! Returns the index for the property definition with the given name.
+ * @param propertyName The name of the property who's index to be returned. */
+- (NSUInteger)indexOfPropertyDefinitionWithName:(NSString *)propertyName;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Other
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*! Returns the property data type of any property given its name and its object. */
++ (SCPropertyDataType)propertyDataTypeForPropertyWithName:(NSString *)propertyName inObject:(NSObject *)object;
+
+/*! Returns TRUE if propertyName is valid. A propertyName is valid if it exists within the associated
+ * class or entity.
+ * @param propertyName The name of the property who's validity is to be checked. */
+- (BOOL)isValidPropertyName:(NSString *)propertyName;
+
+/*! Returns the title string value for the given object. The title value is determined
+ * based on the value of the titlePropertyName property. Note: object must be an instance
+ * of the same class or entity defined in the class definition. */
+- (NSString *)titleValueForObject:(NSObject *)object;
+
+@end
+
+
+
+
+
+
+
+
+/****************************************************************************************/
+/* class SCDictionaryDefinition */
+/****************************************************************************************/
+/*!
+ * This class functions as a means to further extend the key definitions of an NSMutableDictionary.
+ * Using dictionary definitions, classes like SCObjectCell and SCObjectSection
+ * will be able to better generate user interface elements that truly represent the
+ * keys of their bound mutable dictionaries.
+ *
+ * %SCDictionaryDefinition directly decends from SCClassDefinition.
+ *
+ * See also: SCPropertyDefinition.
+ */
+@interface SCDictionaryDefinition : SCClassDefinition
+{
+}
+
+/*! Allocates and returns an initialized %SCDictionaryDefinition given the key names
+ * of the mutable dictionary to be defined. By default, all property definitions generated
+ * for the given keyNames will have a type of SCPropertyTypeTextField. This can be fully customized
+ * after initialization.
+ *
+ * @param keyNames An array of the dictionary key names. All array
+ * elements must be of type NSString.
+ */
++ (id)definitionWithDictionaryKeyNames:(NSArray *)keyNames;
+
+/*! Allocates and returns an initialized %SCDictionaryDefinition given the key names
+ * and titles of the mutable dictionary to be defined. By default, all property definitions generated
+ * for the given keyNames will have a type of SCPropertyTypeTextField. This can be fully customized
+ * after initialization.
+ *
+ * @param keyNames An array of the dictionary key names. All array
+ * elements must be of type NSString.
+ * @param keyTitles An array of titles to the keys in keyNames. All array
+ * elements must be of type NSString.
+ */
++ (id)definitionWithDictionaryKeyNames:(NSArray *)keyNames
+ withKeyTitles:(NSArray *)keyTitles;
+
+/*! Returns an initialized %SCDictionaryDefinition given the key names
+ * of the mutable dictionary to be defined. By default, all property definitions generated
+ * for the given keyNames will have a type of SCPropertyTypeTextField. This can be fully customized
+ * after initialization.
+ *
+ * @param keyNames An array of the dictionary key names. All array
+ * elements must be of type NSString.
+ */
+- (id)initWithDictionaryKeyNames:(NSArray *)keyNames;
+
+/*! Returns an initialized %SCDictionaryDefinition given the key names
+ * and titles of the mutable dictionary to be defined. By default, all property definitions generated
+ * for the given keyNames will have a type of SCPropertyTypeTextField. This can be fully customized
+ * after initialization.
+ *
+ * @param keyNames An array of the dictionary key names. All array
+ * elements must be of type NSString.
+ * @param keyTitles An array of titles to the keys in keyNames. All array
+ * elements must be of type NSString.
+ */
+- (id)initWithDictionaryKeyNames:(NSArray *)keyNames
+ withKeyTitles:(NSArray *)keyTitles;
+
+@end
+
+
+
+
View
891 Classes/Sensible TableView/SCClassDefinition.m
@@ -0,0 +1,891 @@
+/*
+ * SCClassDefinition.m
+ * Sensible TableView
+ *
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY UNITED STATES
+ * INTELLECTUAL PROPERTY LAW AND INTERNATIONAL TREATIES. UNAUTHORIZED REPRODUCTION OR
+ * DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. YOU SHALL NOT DEVELOP NOR
+ * MAKE AVAILABLE ANY WORK THAT COMPETES WITH A SENSIBLE COCOA PRODUCT DERIVED FROM THIS
+ * SOURCE CODE. THIS SOURCE CODE MAY NOT BE RESOLD OR REDISTRIBUTED ON A STAND ALONE BASIS.
+ *
+ * USAGE OF THIS SOURCE CODE IS BOUND BY THE LICENSE AGREEMENT PROVIDED WITH THE
+ * DOWNLOADED PRODUCT.
+ *
+ * Copyright 2010 Sensible Cocoa. All rights reserved.
+ *
+ *
+ * This notice may not be removed from this file.
+ *
+ */
+
+#import "SCClassDefinition.h"
+#import "SCGlobals.h"
+#import <objc/runtime.h>
+
+@implementation SCPropertyDefinition
+
+@synthesize dataType;
+@synthesize dataReadOnly;
+@synthesize name;
+@synthesize title;
+@synthesize type;
+@synthesize required;
+@synthesize autoValidate;
+@synthesize attributes;
+
++ (id)definitionWithName:(NSString *)propertyName
+{
+ return [[[[self class] alloc] initWithName:propertyName] autorelease];
+}
+
++ (id)definitionWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType
+{
+ return [[[[self class] alloc] initWithName:propertyName
+ title:propertyTitle
+ type:propertyType] autorelease];
+}
+
+- (id)initWithName:(NSString *)propertyName
+{
+ return [self initWithName:propertyName title:nil type:SCPropertyTypeAutoDetect];
+}
+
+- (id)initWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType
+{
+ if( (self=[super init]) )
+ {
+ dataType = SCPropertyDataTypeOther;
+ dataReadOnly = FALSE;
+
+ name = [propertyName copy];
+ self.title = propertyTitle;
+ self.type = propertyType;
+ self.required = FALSE;
+ self.autoValidate = TRUE;
+ self.attributes = nil;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [name release];
+ [title release];
+ [attributes release];
+
+ [super dealloc];
+}
+
+@end
+
+
+
+
+
+
+@implementation SCCustomPropertyDefinition
+
+@synthesize uiElement;
+@synthesize objectBindings;
+
++ (id)definitionWithName:(NSString *)propertyName
+ withuiElement:(NSObject *)element
+ withObjectBindings:(NSDictionary *)bindings
+{
+ return [[[[self class] alloc] initWithName:propertyName
+ withuiElement:element
+ withObjectBindings:bindings] autorelease];
+}
+
++ (id)definitionWithName:(NSString *)propertyName
+ withuiElementNibName:(NSString *)elementNibName
+ withObjectBindings:(NSDictionary *)bindings
+{
+ return [[[[self class] alloc] initWithName:propertyName
+ withuiElementNibName:elementNibName
+ withObjectBindings:bindings] autorelease];
+}
+
+- (id)initWithName:(NSString *)propertyName
+ withuiElement:(NSObject *)element
+withObjectBindings:(NSDictionary *)bindings
+{
+ if( (self = [super initWithName:propertyName]) )
+ {
+ uiElement = [element retain];
+ self.objectBindings = bindings;
+ }
+
+ return self;
+}
+
+- (id)initWithName:(NSString *)propertyName
+ withuiElementNibName:(NSString *)elementNibName
+ withObjectBindings:(NSDictionary *)bindings
+{
+ if( (self = [super initWithName:propertyName]) )
+ {
+ uiElement = [[SCHelper getFirstNodeInNibWithName:elementNibName] retain];
+ self.objectBindings = bindings;
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [uiElement release];
+ [objectBindings release];
+
+ [super dealloc];
+}
+
+@end
+
+
+
+
+
+
+
+
+@interface SCClassDefinition ()
+
+- (NSString *)getUserFriendlyPropertyTitleFromName:(NSString *)propertyName;
+
+@end
+
+
+@implementation SCClassDefinition
+
+@synthesize cls;
+
+#ifdef _COREDATADEFINES_H
+@synthesize entity;
+@synthesize managedObjectContext;
+#endif
+
+@synthesize keyPropertyName;
+@synthesize titlePropertyName;
+@synthesize titlePropertyNameDelimiter;
+@synthesize descriptionPropertyName;
+@synthesize uiElementDelegate;
+
+
++ (id) definitionWithClass:(Class)_cls autoGeneratePropertyDefinitions:(BOOL)autoGenerate
+{
+ return [[[[self class] alloc] initWithClass:_cls
+ autoGeneratePropertyDefinitions:autoGenerate] autorelease];
+}
+
++ (id) definitionWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+{
+ return [[[[self class] alloc] initWithClass:_cls
+ withPropertyNames:propertyNames] autorelease];
+}
+
++ (id) definitionWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles
+{
+ return [[[[self class] alloc] initWithClass:_cls
+ withPropertyNames:propertyNames
+ withPropertyTitles:propertyTitles] autorelease];
+}
+
+
+#ifdef _COREDATADEFINES_H
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ autoGeneratePropertyDefinitions:(BOOL)autoGenerate
+{
+ return [[[[self class] alloc] initWithEntityName:entityName
+ withManagedObjectContext:context
+ autoGeneratePropertyDefinitions:autoGenerate] autorelease];
+}
+
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+{
+ return [[[[self class] alloc] initWithEntityName:entityName
+ withManagedObjectContext:context
+ withPropertyNames:propertyNames] autorelease];
+}
+
++ (id)definitionWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles
+{
+ return [[[[self class] alloc] initWithEntityName:entityName
+ withManagedObjectContext:context
+ withPropertyNames:propertyNames
+ withPropertyTitles:propertyTitles] autorelease];
+}
+#endif
+
++ (SCPropertyDataType)propertyDataTypeForPropertyWithName:(NSString *)propertyName inObject:(NSObject *)object
+{
+ SCPropertyDataType dataType = SCPropertyDataTypeOther;
+
+#ifdef _COREDATADEFINES_H
+ if([object isKindOfClass:[NSManagedObject class]])
+ {
+ NSEntityDescription *entity = [(NSManagedObject *)object entity];
+ NSPropertyDescription *propertyDescription = [[entity propertiesByName] valueForKey:propertyName];
+
+ if(propertyDescription)
+ {
+ if([propertyDescription isKindOfClass:[NSAttributeDescription class]])
+ {
+ NSAttributeDescription *attribute = (NSAttributeDescription *)propertyDescription;
+ switch ([attribute attributeType])
+ {
+ case NSInteger16AttributeType:
+ case NSInteger32AttributeType:
+ case NSInteger64AttributeType:
+ dataType = SCPropertyDataTypeNSNumber;
+ break;
+
+ case NSDecimalAttributeType:
+ case NSDoubleAttributeType:
+ case NSFloatAttributeType:
+ dataType = SCPropertyDataTypeNSNumber;
+ break;
+
+ case NSStringAttributeType:
+ dataType = SCPropertyDataTypeNSString;
+ break;
+
+ case NSBooleanAttributeType:
+ dataType = SCPropertyDataTypeNSNumber;
+ break;
+
+ case NSDateAttributeType:
+ dataType = SCPropertyDataTypeNSDate;
+ break;
+
+ case NSTransformableAttributeType:
+ dataType = SCPropertyDataTypeTransformable;
+ break;
+
+ default:
+ dataType = SCPropertyDataTypeOther;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+#endif
+ objc_property_t property = class_getProperty([object class], [propertyName UTF8String]);
+ if(!property)
+ return SCPropertyDataTypeOther;
+ NSArray *attributesArray = [[NSString stringWithUTF8String: property_getAttributes(property)]
+ componentsSeparatedByString:@","];
+ NSSet *attributesSet = [NSSet setWithArray:attributesArray];
+
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSString class])]]])
+ dataType = SCPropertyDataTypeNSString;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSNumber class])]]])
+ dataType = SCPropertyDataTypeNSNumber;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSDate class])]]])
+ dataType = SCPropertyDataTypeNSDate;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSMutableSet class])]]])
+ dataType = SCPropertyDataTypeNSMutableSet;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSMutableArray class])]]])
+ dataType = SCPropertyDataTypeNSMutableArray;
+#ifdef _COREDATADEFINES_H
+ }
+#endif
+
+ return dataType;
+}
+
+
+- (id) init
+{
+ if( (self = [super init]) )
+ {
+#ifdef _COREDATADEFINES_H
+ entity = nil;
+ managedObjectContext = nil;
+#endif
+
+ propertyDefinitions = [[NSMutableArray alloc] init];
+ keyPropertyName = nil;
+ titlePropertyName = nil;
+ titlePropertyNameDelimiter = @" ";
+ descriptionPropertyName = nil;
+ uiElementDelegate = nil;
+ }
+ return self;
+}
+
+- (id) initWithClass:(Class)_cls autoGeneratePropertyDefinitions:(BOOL)autoGenerate
+{
+ if([self init])
+ {
+ cls = _cls;
+
+ if(autoGenerate)
+ {
+ unsigned int count = 0;
+ objc_property_t *properties = class_copyPropertyList(self.cls, &count);
+ for (unsigned int i = 0; i < count; i++ )
+ {
+ NSString *propertyName = [NSString stringWithUTF8String: property_getName(properties[i])];
+ [self addPropertyDefinitionWithName:propertyName
+ title:[self getUserFriendlyPropertyTitleFromName:propertyName]
+ type:SCPropertyTypeAutoDetect];
+ }
+ free(properties);
+ }
+
+ // Set self.titlePropertyName to the first property
+ if(self.propertyDefinitionCount)
+ self.titlePropertyName = [self propertyDefinitionAtIndex:0].name;
+ }
+
+ return self;
+}
+
+- (id) initWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+{
+ return [self initWithClass:_cls withPropertyNames:propertyNames withPropertyTitles:nil];
+}
+
+- (id) initWithClass:(Class)_cls withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles
+{
+ if([self initWithClass:_cls autoGeneratePropertyDefinitions:NO])
+ {
+ for(int i=0; i<propertyNames.count; i++)
+ {
+ NSString *propertyName = [propertyNames objectAtIndex:i];
+ NSString *propertyTitle;
+ if(i < propertyTitles.count)
+ propertyTitle = [propertyTitles objectAtIndex:i];
+ else
+ propertyTitle = [self getUserFriendlyPropertyTitleFromName:propertyName];
+ [self addPropertyDefinitionWithName:propertyName
+ title:propertyTitle
+ type:SCPropertyTypeAutoDetect];
+ }
+
+ // Set self.titlePropertyName to the first property
+ if(self.propertyDefinitionCount)
+ self.titlePropertyName = [self propertyDefinitionAtIndex:0].name;
+
+ self.descriptionPropertyName = nil;
+ }
+
+ return self;
+}
+
+
+#ifdef _COREDATADEFINES_H
+- (id)initWithEntityName:(NSString *)entityName
+ withManagedObjectContext:(NSManagedObjectContext *)context
+ autoGeneratePropertyDefinitions:(BOOL)autoGenerate
+{
+ NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName
+ inManagedObjectContext:context];
+
+ if(!autoGenerate)
+ {
+ [self init];
+ managedObjectContext = [context retain];
+ entity = [entityDescription retain];
+ return self;
+ }
+ //else
+
+ NSMutableArray *propertyNames = [NSMutableArray arrayWithCapacity:entityDescription.properties.count];
+ for(NSPropertyDescription *propertyDescription in entityDescription.properties)
+ {
+ [propertyNames addObject:[propertyDescription name]];
+ }
+ return [self initWithEntityName:entityName withManagedObjectContext:context
+ withPropertyNames:propertyNames];
+}
+
+- (id)initWithEntityName:(NSString *)entityName
+withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+{
+ return [self initWithEntityName:entityName withManagedObjectContext:context
+ withPropertyNames:propertyNames withPropertyTitles:nil];
+}
+
+- (id)initWithEntityName:(NSString *)entityName
+withManagedObjectContext:(NSManagedObjectContext *)context
+ withPropertyNames:(NSArray *)propertyNames
+ withPropertyTitles:(NSArray *)propertyTitles
+{
+ if( (self = [self init]) )
+ {
+ managedObjectContext = [context retain];
+ entity = [[NSEntityDescription entityForName:entityName
+ inManagedObjectContext:self.managedObjectContext] retain];
+
+ for(int i=0; i<propertyNames.count; i++)
+ {
+ NSString *propertyName = [propertyNames objectAtIndex:i];
+ NSString *propertyTitle;
+ if(i < propertyTitles.count)
+ propertyTitle = [propertyTitles objectAtIndex:i];
+ else
+ propertyTitle = [self getUserFriendlyPropertyTitleFromName:propertyName];
+ NSPropertyDescription *propertyDescription =
+ [[self.entity propertiesByName] valueForKey:propertyName];
+
+ if(propertyDescription)
+ {
+ SCPropertyDefinition *propertyDef = [SCPropertyDefinition
+ definitionWithName:propertyName
+ title:propertyTitle
+ type:SCPropertyTypeNone];
+ propertyDef.required = ![propertyDescription isOptional];
+
+ if([propertyDescription isKindOfClass:[NSAttributeDescription class]])
+ {
+ NSAttributeDescription *attribute = (NSAttributeDescription *)propertyDescription;
+ switch ([attribute attributeType])
+ {
+ case NSInteger16AttributeType:
+ case NSInteger32AttributeType:
+ case NSInteger64AttributeType:
+ propertyDef.dataType = SCPropertyDataTypeNSNumber;
+ propertyDef.type = SCPropertyTypeNumericTextField;
+ propertyDef.attributes = [SCNumericTextFieldAttributes
+ attributesWithMinimumValue:nil
+ maximumValue:nil
+ allowFloatValue:FALSE];
+ break;
+
+ case NSDecimalAttributeType:
+ case NSDoubleAttributeType:
+ case NSFloatAttributeType:
+ propertyDef.dataType = SCPropertyDataTypeNSNumber;
+ propertyDef.type = SCPropertyTypeNumericTextField;
+ break;
+
+ case NSStringAttributeType:
+ propertyDef.dataType = SCPropertyDataTypeNSString;
+ propertyDef.type = SCPropertyTypeTextField;
+ break;
+
+ case NSBooleanAttributeType:
+ propertyDef.dataType = SCPropertyDataTypeNSNumber;
+ propertyDef.type = SCPropertyTypeSwitch;
+ break;
+
+ case NSDateAttributeType:
+ propertyDef.dataType = SCPropertyDataTypeNSDate;
+ propertyDef.type = SCPropertyTypeDate;
+ break;
+
+
+ default:
+ propertyDef.type = SCPropertyTypeNone;
+ break;
+ }
+ }
+ else
+ if([propertyDescription isKindOfClass:[NSRelationshipDescription class]])
+ {
+ NSRelationshipDescription *relationship = (NSRelationshipDescription *)propertyDescription;
+
+ if([relationship isToMany])
+ {
+ propertyDef.dataType = SCPropertyDataTypeNSMutableSet;
+ propertyDef.type = SCPropertyTypeArrayOfObjects;
+ }
+ else
+ {
+ propertyDef.dataType = SCPropertyDataTypeNSObject;
+ propertyDef.type = SCPropertyTypeObject;
+ }
+ }
+ else
+ if([propertyDescription isKindOfClass:[NSFetchedPropertyDescription class]])
+ {
+ propertyDef.dataType = SCPropertyDataTypeNSMutableSet;
+ propertyDef.type = SCPropertyTypeArrayOfObjects;
+ propertyDef.attributes = [SCArrayOfObjectsAttributes
+ attributesWithObjectClassDefinition:nil
+ allowAddingItems:NO
+ allowDeletingItems:NO
+ allowMovingItems:NO];
+ }
+
+ [self addPropertyDefinition:propertyDef];
+ }
+ }
+
+ // Set self.keyPropertyName & self.titlePropertyName to the first property
+ if(self.propertyDefinitionCount)
+ {
+ self.keyPropertyName = [self propertyDefinitionAtIndex:0].name;
+ self.titlePropertyName = [self propertyDefinitionAtIndex:0].name;
+ }
+ }
+
+ return self;
+}
+#endif
+
+
+- (void)dealloc
+{
+#ifdef _COREDATADEFINES_H
+ [managedObjectContext release];
+ [entity release];
+#endif
+
+ [propertyDefinitions release];
+ [keyPropertyName release];
+ [titlePropertyName release];
+ [titlePropertyNameDelimiter release];
+ [descriptionPropertyName release];
+
+ [super dealloc];
+}
+
+- (NSString *)getUserFriendlyPropertyTitleFromName:(NSString *)propertyName
+{
+ NSMutableString *UFName = [[[NSMutableString string] retain] autorelease];
+
+ if(![propertyName length])
+ return UFName;
+
+ // Capitalize & append the 1st character
+ [UFName appendString:[[propertyName substringToIndex:1] uppercaseString]];
+
+ // Leave a space for every capital letter
+ NSCharacterSet *uppercaseSet = [NSCharacterSet uppercaseLetterCharacterSet];
+ for(int i=1; i<[propertyName length]; i++)
+ {
+ unichar chr = [propertyName characterAtIndex:i];
+ if([uppercaseSet characterIsMember:chr])
+ [UFName appendString:[NSString stringWithFormat:@" %c", chr]];
+ else
+ [UFName appendString:[NSString stringWithFormat:@"%c", chr]];
+ }
+
+ return UFName;
+}
+
+- (NSString *)className
+{
+#ifdef _COREDATADEFINES_H
+ if(self.entity)
+ return [self.entity name];
+#endif
+ //else
+ return [NSString stringWithFormat:@"%s", class_getName(self.cls)];
+}
+
+- (void)setKeyPropertyName:(NSString *)propertyName
+{
+ if([self isValidPropertyName:propertyName])
+ {
+ [keyPropertyName release];
+ keyPropertyName = [propertyName copy];
+ }
+}
+
+- (NSUInteger)propertyDefinitionCount
+{
+ return propertyDefinitions.count;
+}
+
+- (BOOL)addPropertyDefinitionWithName:(NSString *)propertyName
+ title:(NSString *)propertyTitle
+ type:(SCPropertyType)propertyType
+{
+ SCPropertyDefinition *propertyDefinition =
+ [[SCPropertyDefinition alloc] initWithName:propertyName
+ title:propertyTitle
+ type:propertyType];
+ BOOL success = [self addPropertyDefinition:propertyDefinition];
+ [propertyDefinition release];
+
+ return success;
+}
+
+- (BOOL)addPropertyDefinition:(SCPropertyDefinition *)propertyDefinition
+{
+ NSInteger index = self.propertyDefinitionCount;
+
+ return [self insertPropertyDefinition:propertyDefinition atIndex:index];
+}
+
+- (BOOL)insertPropertyDefinition:(SCPropertyDefinition *)propertyDefinition
+ atIndex:(NSInteger)index
+{
+ if([propertyDefinition isKindOfClass:[SCCustomPropertyDefinition class]])
+ {
+ [propertyDefinitions insertObject:propertyDefinition atIndex:index];
+ return TRUE;
+ }
+ //else
+ if([self isValidPropertyName:propertyDefinition.name])
+ {
+ BOOL coreDataDefinition = FALSE;
+#ifdef _COREDATADEFINES_H
+ if(self.entity)
+ coreDataDefinition = TRUE;
+#endif
+ if(!coreDataDefinition)
+ {
+ // Set property's dataType & dataReadOnly properties
+ objc_property_t property = class_getProperty(self.cls, [propertyDefinition.name UTF8String]);
+ if(!property)
+ return FALSE;
+ NSArray *attributesArray = [[NSString stringWithUTF8String: property_getAttributes(property)]
+ componentsSeparatedByString:@","];
+ NSSet *attributesSet = [NSSet setWithArray:attributesArray];
+
+ propertyDefinition.dataReadOnly = [attributesSet containsObject:@"R"];
+
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSString class])]]])
+ propertyDefinition.dataType = SCPropertyDataTypeNSString;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSNumber class])]]])
+ propertyDefinition.dataType = SCPropertyDataTypeNSNumber;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSDate class])]]])
+ propertyDefinition.dataType = SCPropertyDataTypeNSDate;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSMutableSet class])]]])
+ propertyDefinition.dataType = SCPropertyDataTypeNSMutableSet;
+ else
+ if([attributesSet containsObject:[NSString stringWithFormat:@"T@\"%@\"",
+ [NSString stringWithUTF8String:class_getName([NSMutableArray class])]]])
+ propertyDefinition.dataType = SCPropertyDataTypeNSMutableArray;
+ }
+
+ [propertyDefinitions insertObject:propertyDefinition atIndex:index];
+ return TRUE;
+ }
+ //else
+ return FALSE;
+}
+
+- (void)removePropertyDefinitionAtIndex:(NSUInteger)index
+{
+ [propertyDefinitions removeObjectAtIndex:index];
+}
+
+- (void)removePropertyDefinitionWithName:(NSString *)propertyName
+{
+ NSUInteger index = [self indexOfPropertyDefinitionWithName:propertyName];
+ if(index != -1)
+ [propertyDefinitions removeObjectAtIndex:index];
+}
+
+- (SCPropertyDefinition *)propertyDefinitionAtIndex:(NSUInteger)index
+{
+ return [propertyDefinitions objectAtIndex:index];
+}
+
+- (SCPropertyDefinition *)propertyDefinitionWithName:(NSString *)propertyName
+{
+ NSUInteger index = [self indexOfPropertyDefinitionWithName:propertyName];
+ if(index != -1)
+ return [propertyDefinitions objectAtIndex:index];
+ //else
+ return nil;
+}
+
+- (NSUInteger)indexOfPropertyDefinitionWithName:(NSString *)propertyName
+{
+ for(NSUInteger i=0; i<propertyDefinitions.count; i++)
+ {
+ SCPropertyDefinition *propertyDefinition = [propertyDefinitions objectAtIndex:i];
+ if([propertyDefinition.name isEqualToString:propertyName])
+ return i;
+ }
+ return -1;
+}
+
+- (BOOL)isValidPropertyName:(NSString *)propertyName
+{
+ BOOL propertyValid = FALSE;
+
+#ifdef _COREDATADEFINES_H
+ if(self.entity)
+ {
+ propertyValid = ([[self.entity propertiesByName] valueForKey:propertyName] != nil);
+ }
+ else
+ {
+#endif
+ objc_property_t property = class_getProperty(self.cls, [propertyName UTF8String]);
+
+ if(property)
+ {
+ // Property must be an NSObject decendant to be allowed
+ NSArray *attributesArray = [[NSString stringWithUTF8String: property_getAttributes(property)]
+ componentsSeparatedByString:@","];
+ NSString *classAttribute = [attributesArray objectAtIndex:0];
+ NSRange classStringRange = [classAttribute rangeOfString:@"T@\""];
+ if(classStringRange.location != NSNotFound)
+ {
+ propertyValid = TRUE;
+ }
+ }
+#ifdef _COREDATADEFINES_H
+ }
+#endif
+
+ return propertyValid;
+}
+
+- (NSString *)titleValueForObject:(NSObject *)object
+{
+ if(!self.titlePropertyName)
+ return nil;
+
+ NSMutableString *titleValue = [NSMutableString string];
+
+ NSArray *titleNames = [self.titlePropertyName componentsSeparatedByString:@";"];
+#ifdef _COREDATADEFINES_H
+ if([object isKindOfClass:[NSManagedObject class]])
+ {
+ for(int i=0; i<titleNames.count; i++)
+ {
+ id value = [(NSManagedObject *)object valueForKeyPath:[titleNames objectAtIndex:i]];
+ if(value)
+ {
+ if(i!=0)
+ [titleValue appendString:self.titlePropertyNameDelimiter];
+ [titleValue appendString:[NSString stringWithFormat:@"%@", value]];
+ }
+ }
+ }
+ else
+ {
+ for(int i=0; i<titleNames.count; i++)
+ {
+ id value = [object valueForKey:[titleNames objectAtIndex:i]];
+ if(value)
+ {
+ if(i!=0)
+ [titleValue appendString:self.titlePropertyNameDelimiter];
+ [titleValue appendString:[NSString stringWithFormat:@"%@", value]];
+ }
+ }
+ }
+#else
+ for(int i=0; i<titleNames.count; i++)
+ {
+ id value = [object valueForKey:[titleNames objectAtIndex:i]];
+ if(value)
+ {
+ if(i!=0)
+ [titleValue appendString:self.titlePropertyNameDelimiter];
+ [titleValue appendString:[NSString stringWithFormat:@"%@", value]];
+ }
+ }
+#endif
+
+ return titleValue;
+}
+
+@end
+
+
+
+
+
+
+@implementation SCDictionaryDefinition
+
++ (id)definitionWithDictionaryKeyNames:(NSArray *)keyNames
+{
+ return [[[[self class] alloc] initWithDictionaryKeyNames:keyNames] autorelease];
+}
+
++ (id)definitionWithDictionaryKeyNames:(NSArray *)keyNames
+ withKeyTitles:(NSArray *)keyTitles
+{
+ return [[[[self class] alloc] initWithDictionaryKeyNames:keyNames
+ withKeyTitles:keyTitles] autorelease];
+}
+
+- (id)initWithDictionaryKeyNames:(NSArray *)keyNames
+{
+ return [self initWithDictionaryKeyNames:keyNames withKeyTitles:nil];
+}
+
+- (id)initWithDictionaryKeyNames:(NSArray *)keyNames
+ withKeyTitles:(NSArray *)keyTitles
+{
+ if([self init])
+ {
+ for(int i=0; i<keyNames.count; i++)
+ {
+ NSString *keyName = [keyNames objectAtIndex:i];
+ NSString *keyTitle;
+ if(i < keyTitles.count)
+ keyTitle = [keyTitles objectAtIndex:i];
+ else
+ keyTitle = [self getUserFriendlyPropertyTitleFromName:keyName];
+ [self addPropertyDefinitionWithName:keyName
+ title:keyTitle
+ type:SCPropertyTypeTextField];
+ }
+
+ // Set self.titlePropertyName to the first property
+ if(self.propertyDefinitionCount)
+ self.titlePropertyName = [self propertyDefinitionAtIndex:0].name;
+ }
+ return self;
+}
+
+// override superclass
+- (BOOL)isValidPropertyName:(NSString *)propertyName
+{
+ return TRUE; // Should accept any key name as a valid property name
+}
+
+// override superclass
+- (BOOL)addPropertyDefinition:(SCPropertyDefinition *)propertyDefinition
+{
+ propertyDefinition.dataType = SCPropertyDataTypeDictionaryItem;
+ [propertyDefinitions addObject:propertyDefinition];
+
+ return TRUE;
+}
+
+// override superclass
+- (NSString *)className
+{
+ return @"__NSCFDictionary";
+}
+
+@end
+
+
View
114 Classes/Sensible TableView/SCGlobals.h
@@ -0,0 +1,114 @@
+/*
+ * SCGlobals.h
+ * Sensible TableView
+ *
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY UNITED STATES
+ * INTELLECTUAL PROPERTY LAW AND INTERNATIONAL TREATIES. UNAUTHORIZED REPRODUCTION OR
+ * DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. YOU SHALL NOT DEVELOP NOR
+ * MAKE AVAILABLE ANY WORK THAT COMPETES WITH A SENSIBLE COCOA PRODUCT DERIVED FROM THIS
+ * SOURCE CODE. THIS SOURCE CODE MAY NOT BE RESOLD OR REDISTRIBUTED ON A STAND ALONE BASIS.
+ *
+ * USAGE OF THIS SOURCE CODE IS BOUND BY THE LICENSE AGREEMENT PROVIDED WITH THE
+ * DOWNLOADED PRODUCT.
+ *
+ * Copyright 2010 Sensible Cocoa. All rights reserved.
+ *
+ *
+ * This notice may not be removed from this file.
+ *
+ */
+
+
+/* Uncomment the following line if you want to deploy your project to a device that is
+ * running an OS prior to 3.2. Note: When you do that, it is normal to get several compiler
+ * wanrning messages regarding the use of deprecated symbols. */
+
+// #define DEPLOYMENT_OS_PRIOR_TO_3_2
+
+
+
+/*
+ * The following defines global Sesible TableView defaults. You are very much discouraged from
+ * modifying the content of these values, mainly for your product to remain forward compatable
+ * with future versions of Sensible TableView. If you think you need to change any of these
+ * values, please consider either modifying the respective property of the Sensible TableView
+ * object, or subclassing it.
+ */
+/**********************************************************************************/
+#ifdef DEPLOYMENT_OS_PRIOR_TO_3_2
+ #define SC_DefaultCellStyle UITableViewCellStyleDefault
+#else
+ #define SC_DefaultCellStyle UITableViewCellStyleSubtitle
+#endif
+
+
+#define SC_DefaultMaxTextLabelWidth 200 // Default maximum width of SCTableViewCell textLabel
+#define SC_DefaultControlMargin 10 // Default margin between different controls
+#define SC_DefaultControlHeight 22 // Default control height
+#define SC_DefaultControlIndentation 120 // Default control indentation from table left border
+#define SC_DefaultTextViewFontSize 17 // Default font size of UITextView
+#define SC_DefaultTextFieldHeight 31 // Default height of UITextField
+#define SC_DefaultSegmentedControlHeight 29 // Default height of UISegmentedControl
+/**********************************************************************************/
+
+
+
+/*! The types of navigation bars used in SCViewController and SCTableViewController. */
+typedef enum
+{
+ /*! Navigation bar with no buttons. */
+ SCNavigationBarTypeNone,
+ /*! Navigation bar with an Add button on the left. */
+ SCNavigationBarTypeAddLeft,
+ /*! Navigation bar with an Add button on the right. */
+ SCNavigationBarTypeAddRight,
+ /*! Navigation bar with an Edit button on the left. */
+ SCNavigationBarTypeEditLeft,
+ /*! Navigation bar with an Edit button on the right. */
+ SCNavigationBarTypeEditRight,
+ /*! Navigation bar with an Add button on the right and an Edit button on the left. */
+ SCNavigationBarTypeAddRightEditLeft,
+ /*! Navigation bar with an Add button on the left and an Edit button on the right. */
+ SCNavigationBarTypeAddLeftEditRight,
+ /*! Navigation bar with a Done button on the left. */
+ SCNavigationBarTypeDoneLeft,
+ /*! Navigation bar with a Done button on the right. */
+ SCNavigationBarTypeDoneRight,
+ /*! Navigation bar with a Done button on the left and a Cancel button on the right. */
+ SCNavigationBarTypeDoneLeftCancelRight,
+ /*! Navigation bar with a Done button on the right and a Cancel button on the left. */
+ SCNavigationBarTypeDoneRightCancelLeft,
+ /*! Navigation bar with both an Add and Edit buttons on the right. */
+ SCNavigationBarTypeAddEditRight
+
+} SCNavigationBarType;
+
+
+
+
+/* This class defines a set of internal helper methods */
+@interface SCHelper : NSObject
+{
+}
+
+/* Method determines the system version */
++ (double)systemVersion;
+
+/* Method determines if code is being run on an iPad */
++ (BOOL)is_iPad;
+
+/* Method determines if the given view is inside a popover view */
++ (BOOL)isViewInsidePopover:(UIView *)view;
+
++ (NSObject *)getFirstNodeInNibWithName:(NSString *)nibName;
+
+@end
+
+
+
+/* This class implements a transparent toolbar */
+@interface SCTransparentToolbar : UIToolbar
+@end
+
+
View
104 Classes/Sensible TableView/SCGlobals.m