Add NinePath lib

Continue chat stuff
Fix viewWillAppear without viewDidLoad called with UICompositeController
This commit is contained in:
Yann Diorcet 2012-07-06 17:28:38 +02:00
parent 4b62c7970c
commit b634a50283
73 changed files with 5405 additions and 179 deletions

View file

@ -21,9 +21,16 @@
#import <UIKit/UIKit.h>
@interface ChatRoomTableViewController : UITableViewController {
@private
BOOL editMode;
NSArray *data;
NSString *remoteContact;
}
@property (nonatomic, retain) NSArray *data;
@property (nonatomic, retain) NSString *remoteContact;
- (void) toggleEditMode;
- (void) enterEditMode;
- (void) exitEditMode;
@end

View file

@ -18,22 +18,37 @@
*/
#import "ChatRoomTableViewController.h"
#import "UIChatCell.h"
#import "UIChatRoomCell.h"
#import "UIChatRoomHeader.h"
@implementation ChatRoomTableViewController
@synthesize data;
@synthesize remoteContact;
#pragma mark -
- (void)setData:(NSArray *)adata {
if(self->data != nil)
[self->data release];
self->data = [adata retain];
[[self tableView] reloadData];
- (void)reloadData {
if(data != nil)
[data release];
data = [[ChatModel listMessages:remoteContact] retain];
}
- (void) toggleEditMode {
editMode = !editMode;
[(UITableView*)[self view] reloadData];
}
- (void) enterEditMode {
if(!editMode) {
[self toggleEditMode];
}
}
- (void) exitEditMode {
if(editMode) {
[self toggleEditMode];
}
}
#pragma mark - UITableViewDataSource Functions
@ -42,19 +57,45 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
[self reloadData];
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIChatCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UIChatCell"];
UIChatRoomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UIChatRoomCell"];
if (cell == nil) {
cell = [[UIChatCell alloc] init];
cell = [[UIChatRoomCell alloc] initWithIdentifier:@"UIChatRoomCell"];
}
[cell setChat:[data objectAtIndex:[indexPath row]]];
if(editMode)
[cell enterEditMode];
else
[cell exitEditMode];
[cell update];
return cell;
}
#pragma mark - UITableViewelegate Functions
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIChatRoomHeader *headerController = [[UIChatRoomHeader alloc] init];
UIView *headerView = [headerController view];
[headerController setContact:remoteContact];
[headerController update];
[headerController release];
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return [UIChatRoomHeader height];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatModel *chat = [data objectAtIndex:[indexPath row]];
return [UIChatRoomCell height:chat];
}
@end

View file

@ -19,6 +19,7 @@
#import <UIKit/UIKit.h>
#import "UIToggleButton.h"
#import "UICompositeViewController.h"
#import "ChatRoomTableViewController.h"
#import "ChatModel.h"
@ -27,12 +28,14 @@
ChatRoomTableViewController *tableController;
UITextField *messageField;
UIButton *sendButton;
NSString *remoteContact;
UIToggleButton *editButton;
}
- (void) setRemoteContact:(NSString*)remoteContact;
@property (nonatomic, retain) IBOutlet ChatRoomTableViewController* tableController;
@property (nonatomic, retain) IBOutlet UIToggleButton *editButton;
@property (nonatomic, retain) IBOutlet UITextField* messageField;
@property (nonatomic, retain) IBOutlet UIButton* sendButton;

View file

@ -20,13 +20,15 @@
#import "ChatRoomViewController.h"
#import "PhoneMainView.h"
#import <NinePatch.h>
@implementation ChatRoomViewController
@synthesize tableController;
@synthesize sendButton;
@synthesize messageField;
@synthesize editButton;
#pragma mark - Lifecycle Functions
@ -36,7 +38,9 @@
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[tableController release];
[messageField release];
[sendButton release];
[super dealloc];
}
@ -56,8 +60,16 @@
#pragma mark - ViewController Functions
- (void)viewDidLoad {
// Set selected+over background: IB lack !
[editButton setImage:[UIImage imageNamed:@"chat_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewDidAppear:animated];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
@ -66,10 +78,13 @@
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceivedEvent:)
name:@"LinphoneTextReceived"
object:nil];
[tableController exitEditMode];
[editButton setOff];
[[tableController tableView] reloadData];
}
@ -81,13 +96,35 @@
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"LinphoneTextReceived"
object:nil];
}
-(void)didReceiveMemoryWarning {
[TUNinePatchCache flushCache]; // will remove any images cache (freeing any cached but unused images)
}
#pragma mark -
- (void)setRemoteContact:(NSString*)remoteContact {
[tableController setData:[ChatModel listMessages:remoteContact]];
- (void)setRemoteContact:(NSString*)aRemoteContact {
remoteContact = aRemoteContact;
[tableController setRemoteContact: remoteContact];
}
#pragma mark - Event Functions
- (void)textReceivedEvent:(NSNotification *)notif {
//LinphoneChatRoom *room = [[[notif userInfo] objectForKey:@"room"] pointerValue];
LinphoneAddress *from = [[[notif userInfo] objectForKey:@"from"] pointerValue];
//NSString *message = [[notif userInfo] objectForKey:@"message"];
if([[NSString stringWithUTF8String:linphone_address_get_username(from)]
caseInsensitiveCompare:remoteContact] == NSOrderedSame) {
[[tableController tableView] reloadData];
}
}
@ -142,7 +179,7 @@
}
- (IBAction)onEditClick:(id)event {
[tableController toggleEditMode];
}
- (IBAction)onSendClick:(id)event {

View file

@ -39,6 +39,21 @@
<reference key="NSNextResponder"/>
<int key="NSvFlags">292</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIImageView" id="521265930">
<reference key="NSNextResponder" ref="589117993"/>
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview" ref="589117993"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="333187864"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSCustomResource" key="IBUIImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">numpad_background.png</string>
</object>
</object>
<object class="IBUIView" id="333187864">
<reference key="NSNextResponder" ref="589117993"/>
<int key="NSvFlags">290</int>
@ -102,6 +117,10 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_edit_over.png</string>
</object>
<object class="NSCustomResource" key="IBUISelectedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_ok_default.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_edit_default.png</string>
@ -133,18 +152,19 @@
<reference key="NSNextKeyView" ref="833509359"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC45NDExNzY0NzA2IDAuOTY0NzA1ODgyNCAwLjk2NDcwNTg4MjQAA</bytes>
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MCAwAA</bytes>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIAlwaysBounceVertical">YES</bool>
<int key="IBUISeparatorStyle">1</int>
<int key="IBUIStyle">1</int>
<int key="IBUISeparatorStyle">2</int>
<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
<float key="IBUIRowHeight">44</float>
<float key="IBUISectionHeaderHeight">22</float>
<float key="IBUISectionFooterHeight">22</float>
<float key="IBUISectionHeaderHeight">10</float>
<float key="IBUISectionFooterHeight">10</float>
</object>
<object class="IBUIView" id="833509359">
<reference key="NSNextResponder" ref="589117993"/>
@ -250,7 +270,7 @@
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="333187864"/>
<reference key="NSNextKeyView" ref="521265930"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
@ -304,6 +324,14 @@
</object>
<int key="connectionID">32</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">editButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="602867427"/>
</object>
<int key="connectionID">35</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">dataSource</string>
@ -399,6 +427,7 @@
<reference ref="333187864"/>
<reference ref="879615756"/>
<reference ref="833509359"/>
<reference ref="521265930"/>
</array>
<reference key="parent" ref="0"/>
</object>
@ -466,6 +495,12 @@
<reference key="parent" ref="0"/>
<string key="objectName">tableController</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">34</int>
<reference key="object" ref="521265930"/>
<reference key="parent" ref="589117993"/>
<string key="objectName">background</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -473,6 +508,7 @@
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="10.CustomClassName">UIToggleButton</string>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="2" key="10.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@ -482,6 +518,7 @@
<string key="21.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="29.CustomClassName">ChatRoomTableViewController</string>
<string key="29.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="34.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@ -492,7 +529,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">33</int>
<int key="maxID">35</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -532,11 +569,16 @@
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="editButton">UIToggleButton</string>
<string key="messageField">UITextField</string>
<string key="sendButton">UIButton</string>
<string key="tableController">ChatRoomTableViewController</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="editButton">
<string key="name">editButton</string>
<string key="candidateClassName">UIToggleButton</string>
</object>
<object class="IBToOneOutletInfo" key="messageField">
<string key="name">messageField</string>
<string key="candidateClassName">UITextField</string>
@ -555,6 +597,14 @@
<string key="minorKey">./Classes/ChatRoomViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIToggleButton</string>
<string key="superclassName">UIButton</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/UIToggleButton.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
@ -571,9 +621,11 @@
<string key="chat_edit_default.png">{320, 117}</string>
<string key="chat_edit_over.png">{320, 117}</string>
<string key="chat_field.png">{500, 117}</string>
<string key="chat_ok_default.png">{320, 117}</string>
<string key="chat_send_default.png">{140, 117}</string>
<string key="chat_send_disabled.png">{140, 117}</string>
<string key="chat_send_over.png">{140, 117}</string>
<string key="numpad_background.png">{640, 523}</string>
</dictionary>
<string key="IBCocoaTouchPluginVersion">1181</string>
</data>

View file

@ -20,9 +20,13 @@
#import <UIKit/UIKit.h>
@interface ChatTableViewController : UITableViewController {
@private
BOOL editMode;
NSArray *data;
}
@property (nonatomic, retain) NSArray *data;
- (void) toggleEditMode;
- (void) enterEditMode;
- (void) exitEditMode;
@end

View file

@ -25,16 +25,46 @@
@implementation ChatTableViewController
@synthesize data;
#pragma mark - Lifecycle Functions
- (id)init {
if((self = [super init]) != nil) {
self->editMode = false;
}
return self;
}
- (void)dealloc {
if(data != nil)
[data release];
[super dealloc];
}
#pragma mark -
- (void)setData:(NSArray *)adata {
if(self->data != nil)
[self->data release];
self->data = [adata retain];
[[self tableView] reloadData];
- (void)reloadData {
if(data != nil)
[data release];
data = [[ChatModel listConversations] retain];
}
- (void) toggleEditMode {
editMode = !editMode;
[(UITableView*)[self view] reloadData];
}
- (void) enterEditMode {
if(!editMode) {
[self toggleEditMode];
}
}
- (void) exitEditMode {
if(editMode) {
[self toggleEditMode];
}
}
#pragma mark - UITableViewDataSource Functions
@ -46,6 +76,7 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
[self reloadData];
return [data count];
}
@ -53,10 +84,14 @@
{
UIChatCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UIChatCell"];
if (cell == nil) {
cell = [[UIChatCell alloc] init];
cell = [[UIChatCell alloc] initWithIdentifier:@"UIChatCell"];
}
[cell setChat:[data objectAtIndex:[indexPath row]]];
if(editMode)
[cell enterEditMode];
else
[cell exitEditMode];
[cell update];
return cell;

View file

@ -19,14 +19,18 @@
#import <UIKit/UIKit.h>
#import "UIToggleButton.h"
#import "ChatTableViewController.h"
#import "UICompositeViewController.h"
@interface ChatViewController : UIViewController<UICompositeViewDelegate> {
ChatTableViewController *tableController;
UIToggleButton *editButton;
}
@property (nonatomic, retain) IBOutlet ChatTableViewController* tableController;
@property (nonatomic, retain) IBOutlet UIToggleButton *editButton;
- (IBAction)onAddClick:(id) event;
- (IBAction)onEditClick:(id) event;

View file

@ -24,7 +24,7 @@
@implementation ChatViewController
@synthesize tableController;
@synthesize editButton;
#pragma mark - Lifecycle Functions
@ -33,11 +33,48 @@
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[tableController release];
[editButton release];
[super dealloc];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
// Set selected+over background: IB lack !
[editButton setImage:[UIImage imageNamed:@"chat_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[tableController setData:[ChatModel listConversations]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceivedEvent:)
name:@"LinphoneTextReceived"
object:nil];
[tableController exitEditMode];
[editButton setOff];
[[tableController tableView] reloadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"LinphoneTextReceived"
object:nil];
}
#pragma mark - Event Functions
- (void)textReceivedEvent:(NSNotification *)notif {
[[tableController tableView] reloadData];
}
@ -62,14 +99,7 @@
}
- (IBAction)onEditClick:(id)event {
ChatModel* line= [[ChatModel alloc] init];
line.localContact = @"";
line.remoteContact = @"truc";
line.message = @"blabla";
line.direction = [NSNumber numberWithInt:1];
line.time = [NSDate date];
[line create];
[tableController setData:[ChatModel listConversations]];
[tableController toggleEditMode];
}
@end

View file

@ -100,6 +100,10 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_edit_over.png</string>
</object>
<object class="NSCustomResource" key="IBUISelectedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_ok_default.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_edit_default.png</string>
@ -128,7 +132,6 @@
<string key="NSFrame">{{0, 58}, {320, 402}}</string>
<reference key="NSSuperview" ref="1010501960"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
@ -190,6 +193,14 @@
</object>
<int key="connectionID">18</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">editButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="1001279594"/>
</object>
<int key="connectionID">22</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
@ -309,6 +320,7 @@
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="9.CustomClassName">UIToggleButton</string>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="2" key="9.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
</dictionary>
@ -316,7 +328,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">21</int>
<int key="maxID">22</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -345,22 +357,33 @@
<string key="candidateClassName">id</string>
</object>
</dictionary>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">tableController</string>
<string key="NS.object.0">ChatTableViewController</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">tableController</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<dictionary class="NSMutableDictionary" key="outlets">
<string key="editButton">UIToggleButton</string>
<string key="tableController">ChatTableViewController</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="editButton">
<string key="name">editButton</string>
<string key="candidateClassName">UIToggleButton</string>
</object>
<object class="IBToOneOutletInfo" key="tableController">
<string key="name">tableController</string>
<string key="candidateClassName">ChatTableViewController</string>
</object>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/ChatViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIToggleButton</string>
<string key="superclassName">UIButton</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/UIToggleButton.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
@ -376,6 +399,7 @@
<string key="chat_add_over.png">{320, 117}</string>
<string key="chat_edit_default.png">{320, 117}</string>
<string key="chat_edit_over.png">{320, 117}</string>
<string key="chat_ok_default.png">{320, 117}</string>
</dictionary>
<string key="IBCocoaTouchPluginVersion">1181</string>
</data>

View file

@ -68,12 +68,11 @@ typedef enum _HistoryView {
#pragma mark - ViewController Functions
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self changeView: History_All];

View file

@ -115,12 +115,11 @@
selector:@selector(callUpdateEvent:)
name:@"LinphoneCallUpdate"
object:nil];
// Update on show
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];

View file

@ -68,15 +68,15 @@
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[usernameField setText:[[LinphoneManager instance].settingsStore objectForKey:@"username_preference"]];
[passwordField setText:[[LinphoneManager instance].settingsStore objectForKey:@"password_preference"]];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdateEvent:)
name:@"LinphoneRegistrationUpdate"
object:nil];
[usernameField setText:[[LinphoneManager instance].settingsStore objectForKey:@"username_preference"]];
[passwordField setText:[[LinphoneManager instance].settingsStore objectForKey:@"password_preference"]];
// Update on show
const MSList* list = linphone_core_get_proxy_config_list([LinphoneManager getLc]);
if(list != NULL) {

View file

@ -24,6 +24,7 @@
@implementation HistoryTableViewController
#pragma mark - Lifecycle Functions
- (id)init {

View file

@ -68,15 +68,11 @@ typedef enum _HistoryView {
#pragma mark - ViewController Functions
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.tableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[tableController exitEditMode];
[editButton setOff];
[self.tableView reloadData];
}
- (void)viewDidLoad {

View file

@ -195,28 +195,6 @@ enum TableSection {
#pragma mark - UITableViewDataSource Functions
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if(section == CallSection) {
return [[UIView alloc] initWithFrame:CGRectZero];
} else if(section == ConferenceSection) {
LinphoneCore* lc = [LinphoneManager getLc];
if(linphone_core_get_conference_size(lc) > 0){
UIConferenceHeader *headerController = [[UIConferenceHeader alloc] init];
[headerController update];
UIView *headerView = [headerController view];
[headerController release];
return headerView;
} else {
return [[UIView alloc] initWithFrame:CGRectZero];
}
}
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UICallCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UICallCell"];
if (cell == nil) {
@ -268,19 +246,39 @@ enum TableSection {
return 2;
}
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return @"";
}
- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return @"";
}
#pragma mark - UITableViewDelegate Functions
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if(section == CallSection) {
return [[UIView alloc] initWithFrame:CGRectZero];
} else if(section == ConferenceSection) {
LinphoneCore* lc = [LinphoneManager getLc];
if(linphone_core_get_conference_size(lc) > 0){
UIConferenceHeader *headerController = [[UIConferenceHeader alloc] init];
[headerController update];
UIView *headerView = [headerController view];
[headerController release];
return headerView;
} else {
return [[UIView alloc] initWithFrame:CGRectZero];
}
}
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
LinphoneCore* lc = [LinphoneManager getLc];
if(section == CallSection) {
@ -305,8 +303,7 @@ enum TableSection {
return 0.000001f; // Hack UITableView = 0
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
bool inConference = indexPath.section == ConferenceSection;
LinphoneCall* call = [InCallTableViewController retrieveCallAtIndex:indexPath.row inConference:inConference];
UICallCellData* data = [callCellData objectForKey:[NSValue valueWithPointer:call]];

View file

@ -101,10 +101,6 @@ const NSInteger SECURE_BUTTON_TAG=5;
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = YES;
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[callTableController viewDidAppear:NO];
}
}
- (void)viewWillDisappear:(BOOL)animated {
@ -143,6 +139,10 @@ const NSInteger SECURE_BUTTON_TAG=5;
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state];
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[callTableController viewDidAppear:NO];
}
}
- (void)viewDidDisappear:(BOOL)animated {

View file

@ -49,7 +49,6 @@
selector:@selector(callUpdateEvent:)
name:@"LinphoneCallUpdate"
object:nil];
[self callUpdate:call state:linphone_call_get_state(call)];
}

View file

@ -29,6 +29,7 @@
#import "LinphoneManager.h"
#import "FastAddressBook.h"
#import "LinphoneCoreSettingsStore.h"
#import "ChatModel.h"
#include "linphonecore_utils.h"
#include "lpconfig.h"
@ -355,6 +356,28 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
[(LinphoneManager*)linphone_core_get_user_data(lc) onRegister:lc cfg:cfg state:state message:message];
}
- (void)onTextReceived:(LinphoneCore *)lc room:(LinphoneChatRoom *)room from:(const LinphoneAddress *)from message:(const char *)message {
// Save message in database
ChatModel *chat = [[ChatModel alloc] init];
[chat setRemoteContact:[NSString stringWithUTF8String:linphone_address_get_username(from)]];
[chat setMessage:[NSString stringWithUTF8String:message]];
[chat setDirection:[NSNumber numberWithInt:1]];
[chat create];
// Post event
NSDictionary* dict = [[[NSDictionary alloc] initWithObjectsAndKeys:
[NSValue valueWithPointer:room], @"room",
[NSValue valueWithPointer:from], @"from",
[NSString stringWithUTF8String:message], @"message",
nil] autorelease];
[[NSNotificationCenter defaultCenter] postNotificationName:@"LinphoneTextReceived" object:self userInfo:dict];
}
static void linphone_iphone_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) {
[(LinphoneManager*)linphone_core_get_user_data(lc) onTextReceived:lc room:room from:from message:message];
}
static LinphoneCoreVTable linphonec_vtable = {
.show =NULL,
.call_state_changed =(LinphoneCallStateCb)linphone_iphone_call_state,
@ -366,7 +389,7 @@ static LinphoneCoreVTable linphonec_vtable = {
.display_message=linphone_iphone_log,
.display_warning=linphone_iphone_log,
.display_url=NULL,
.text_received=NULL,
.text_received=linphone_iphone_text_received,
.dtmf_received=NULL,
.transfer_state_changed=linphone_iphone_transfer_state_changed
};

View file

@ -159,7 +159,6 @@
selector:@selector(callUpdateEvent:)
name:@"LinphoneCallUpdate"
object:nil];
// Update on show
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;

View file

@ -42,7 +42,6 @@
<string key="NSFrame">{{0, 335}, {320, 125}}</string>
<reference key="NSSuperview" ref="931774220"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
@ -522,6 +521,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -558,6 +558,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -594,6 +595,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -626,6 +628,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -687,6 +690,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -715,6 +719,7 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<bool key="IBUIAdjustsImageWhenDisabled">NO</bool>
<reference key="IBUINormalTitleShadowColor" ref="838911807"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
@ -1140,7 +1145,7 @@
<int key="objectID">59</int>
<reference key="object" ref="1016105438"/>
<reference key="parent" ref="143533231"/>
<string key="objectName">waitView</string>
<string key="objectName">videoWaitView</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">73</int>
@ -1620,8 +1625,8 @@
<string key="options_default.png">{160, 134}</string>
<string key="options_disabled.png">{160, 134}</string>
<string key="options_over.png">{160, 134}</string>
<string key="options_transfer_default.png">{16, 16}</string>
<string key="options_transfer_over.png">{16, 16}</string>
<string key="options_transfer_default.png">{160, 134}</string>
<string key="options_transfer_over.png">{160, 134}</string>
<string key="pause_off_default.png">{209, 136}</string>
<string key="pause_off_over.png">{209, 136}</string>
<string key="pause_on_default.png">{209, 136}</string>

View file

@ -54,7 +54,7 @@
UICallCellData *data;
}
@property (weak) UICallCellData *data;
@property (retain) UICallCellData *data;
@property (nonatomic, retain) IBOutlet UIImageView* headerBackgroundImage;
@property (nonatomic, retain) IBOutlet UIImageView* headerBackgroundHightlightImage;

View file

@ -22,21 +22,28 @@
#import "ChatModel.h"
@interface UIChatCell : UITableViewCell {
UIImageView *avatarView;
UIImageView *avatarImage;
UILabel *displayNameLabel;
UILabel *chatContentLabel;
UIButton *detailsButton;
UIButton *deleteButton;
ChatModel *chat;
}
- (void)update;
@property (weak) ChatModel *chat;
@property (nonatomic, retain) IBOutlet UIImageView *avatarView;
@property (retain) ChatModel *chat;
@property (nonatomic, retain) IBOutlet UIImageView *avatarImage;
@property (nonatomic, retain) IBOutlet UILabel* displayNameLabel;
@property (nonatomic, retain) IBOutlet UILabel* chatContentLabel;
@property (nonatomic, retain) IBOutlet UIButton *detailsButton;
@property (nonatomic, retain) IBOutlet UIButton * deleteButton;
- (IBAction)onDetails:(id)event;
- (id)initWithIdentifier:(NSString*)identifier;
- (void)update;
- (void)enterEditMode;
- (void)exitEditMode;
- (IBAction)onDetailsClick:(id)event;
- (IBAction)onDeleteClick:(id)event;
@end

View file

@ -18,19 +18,23 @@
*/
#import "UIChatCell.h"
#import "PhoneMainView.h"
@implementation UIChatCell
@synthesize avatarView;
@synthesize avatarImage;
@synthesize displayNameLabel;
@synthesize chatContentLabel;
@synthesize detailsButton;
@synthesize deleteButton;
@synthesize chat;
#pragma mark - Lifecycle Functions
- (id)init {
if ((self = [super init]) != nil) {
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIChatCell"
owner:self
options:nil];
@ -45,6 +49,11 @@
- (void)dealloc {
[displayNameLabel release];
[chatContentLabel release];
[avatarImage release];
[detailsButton release];
[deleteButton release];
[chat release];
[super dealloc];
}
@ -52,10 +61,12 @@
#pragma mark -
- (void)update {
[avatarView setImage:[UIImage imageNamed:@"avatar_unknown_small.png"]];
[displayNameLabel setText:[chat remoteContact]];
[chatContentLabel setText:[chat message]];
if (chat != nil) {
[avatarImage setImage:[UIImage imageNamed:@"avatar_unknown_small.png"]];
[displayNameLabel setText:[chat remoteContact]];
[chatContentLabel setText:[chat message]];
}
//
// Adapt size
@ -80,11 +91,33 @@
[chatContentLabel setFrame: chatContentFrame];
}
- (void)enterEditMode {
[deleteButton setHidden:false];
[detailsButton setHidden:true];
}
- (void)exitEditMode {
[detailsButton setHidden:false];
[deleteButton setHidden:true];
}
#pragma mark - Action Functions
- (IBAction)onDetails: (id) event {
- (IBAction)onDetailsClick: (id) event {
// Go to dialer view
NSDictionary *dict = [[[NSDictionary alloc] initWithObjectsAndKeys:
[[[NSArray alloc] initWithObjects: [chat remoteContact], nil] autorelease]
, @"setRemoteContact:",
nil] autorelease];
[[PhoneMainView instance] changeView:PhoneView_ChatRoom dict:dict push:TRUE];
}
- (IBAction)onDeleteClick: (id) event {
if(chat != NULL) {
[ChatModel removeConversation:[chat remoteContact]];
UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];
}
}
@end

View file

@ -138,7 +138,7 @@
<double key="IBUIImageEdgeInsets.bottom">11</double>
<double key="IBUIImageEdgeInsets.left">11</double>
<double key="IBUIImageEdgeInsets.right">11</double>
<object class="NSColor" key="IBUINormalTitleShadowColor">
<object class="NSColor" key="IBUINormalTitleShadowColor" id="1067713114">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC41AA</bytes>
</object>
@ -150,16 +150,44 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">list_details_default.png</string>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<object class="IBUIFontDescription" key="IBUIFontDescription" id="339503299">
<int key="type">2</int>
<double key="pointSize">15</double>
</object>
<object class="NSFont" key="IBUIFont">
<object class="NSFont" key="IBUIFont" id="761635326">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">15</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUIButton" id="753878244">
<reference key="NSNextResponder" ref="316763236"/>
<int key="NSvFlags">-2147483356</int>
<string key="NSFrame">{{276, 0}, {44, 44}}</string>
<reference key="NSSuperview" ref="316763236"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<double key="IBUIImageEdgeInsets.top">11</double>
<double key="IBUIImageEdgeInsets.bottom">11</double>
<double key="IBUIImageEdgeInsets.left">11</double>
<double key="IBUIImageEdgeInsets.right">11</double>
<reference key="IBUINormalTitleShadowColor" ref="1067713114"/>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">list_delete_over.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">list_delete_default.png</string>
</object>
<reference key="IBUIFontDescription" ref="339503299"/>
<reference key="IBUIFont" ref="761635326"/>
</object>
</array>
<string key="NSFrameSize">{320, 44}</string>
<reference key="NSSuperview"/>
@ -218,14 +246,6 @@
</object>
<int key="connectionID">24</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">avatarView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="567463562"/>
</object>
<int key="connectionID">25</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">backgroundView</string>
@ -242,14 +262,47 @@
</object>
<int key="connectionID">29</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">avatarImage</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="567463562"/>
</object>
<int key="connectionID">30</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">deleteButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="753878244"/>
</object>
<int key="connectionID">34</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">detailsButton</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="162769001"/>
</object>
<int key="connectionID">35</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">onDetails:</string>
<string key="label">onDetailsClick:</string>
<reference key="source" ref="162769001"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">22</int>
<int key="connectionID">36</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">onDeleteClick:</string>
<reference key="source" ref="753878244"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">37</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
@ -279,6 +332,7 @@
<reference ref="567463562"/>
<reference ref="641729677"/>
<reference ref="394118737"/>
<reference ref="753878244"/>
</array>
<reference key="parent" ref="0"/>
</object>
@ -292,7 +346,7 @@
<int key="objectID">19</int>
<reference key="object" ref="567463562"/>
<reference key="parent" ref="316763236"/>
<string key="objectName">imageView</string>
<string key="objectName">avatarImage</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">20</int>
@ -318,6 +372,12 @@
<reference key="parent" ref="0"/>
<string key="objectName">background</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">32</int>
<reference key="object" ref="753878244"/>
<reference key="parent" ref="316763236"/>
<string key="objectName">deleteButton</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -334,12 +394,15 @@
<string key="21.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="27.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="32.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="2" key="32.IBUIButtonInspectorSelectedEdgeInsetMetadataKey"/>
<real value="1" key="32.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">29</int>
<int key="maxID">37</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -347,30 +410,40 @@
<string key="className">UIChatCell</string>
<string key="superclassName">UITableViewCell</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">onDetails:</string>
<string key="NS.key.0">onDetailsClick:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">onDetails:</string>
<string key="NS.key.0">onDetailsClick:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">onDetails:</string>
<string key="name">onDetailsClick:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="avatarView">UIImageView</string>
<string key="avatarImage">UIImageView</string>
<string key="chatContentLabel">UILabel</string>
<string key="deleteButton">UIButton</string>
<string key="detailsButton">UIButton</string>
<string key="displayNameLabel">UILabel</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="avatarView">
<string key="name">avatarView</string>
<object class="IBToOneOutletInfo" key="avatarImage">
<string key="name">avatarImage</string>
<string key="candidateClassName">UIImageView</string>
</object>
<object class="IBToOneOutletInfo" key="chatContentLabel">
<string key="name">chatContentLabel</string>
<string key="candidateClassName">UILabel</string>
</object>
<object class="IBToOneOutletInfo" key="deleteButton">
<string key="name">deleteButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="detailsButton">
<string key="name">detailsButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="displayNameLabel">
<string key="name">displayNameLabel</string>
<string key="candidateClassName">UILabel</string>
@ -393,6 +466,8 @@
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="avatar_unknown_small.png">{131, 131}</string>
<string key="list_delete_default.png">{45, 45}</string>
<string key="list_delete_over.png">{45, 45}</string>
<string key="list_details_default.png">{45, 45}</string>
<string key="list_details_over.png">{45, 45}</string>
<string key="list_hightlight.png">{640, 88}</string>

View file

@ -0,0 +1,49 @@
/* UIChatRoomCell.h
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <UIKit/UIKit.h>
#import "ChatModel.h"
@interface UIChatRoomCell : UITableViewCell {
UIImageView *backgroundImage;
UIView *contentView;
UILabel *messageLabel;
UIButton *deleteButton;
ChatModel *chat;
}
@property (retain) ChatModel *chat;
@property (nonatomic, retain) IBOutlet UIView *contentView;
@property (nonatomic, retain) IBOutlet UIImageView* backgroundImage;
@property (nonatomic, retain) IBOutlet UILabel *messageLabel;
@property (nonatomic, retain) IBOutlet UIButton *deleteButton;
- (id)initWithIdentifier:(NSString*)identifier;
+ (CGFloat)height:(ChatModel*)chat;
- (void)update;
- (void)enterEditMode;
- (void)exitEditMode;
- (IBAction)onDeleteClick:(id)event;
@end

View file

@ -0,0 +1,125 @@
/* UIChatRoomCell.m
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "UIChatRoomCell.h"
#import <NinePatch.h>
@implementation UIChatRoomCell
@synthesize contentView;
@synthesize backgroundImage;
@synthesize messageLabel;
@synthesize deleteButton;
@synthesize chat;
static const CGFloat CELL_MIN_HEIGHT = 65.0f;
static const CGFloat CELL_MESSAGE_MAX_WIDTH = 280.0f;
static const CGFloat CELL_FONT_SIZE = 17.0f;
static UIFont *CELL_FONT = nil;
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
[[NSBundle mainBundle] loadNibNamed:@"UIChatRoomCell"
owner:self
options:nil];
[self addSubview:contentView];
}
return self;
}
- (void)dealloc {
[backgroundImage release];
[contentView release];
[messageLabel release];
[deleteButton release];
[chat release];
[super dealloc];
}
#pragma mark -
- (void)update {
if(chat != nil) {
if([chat direction]) {
[backgroundImage setImage:[TUNinePatchCache imageOfSize:[backgroundImage bounds].size
forNinePatchNamed:@"chat_bubble_incoming"]];
} else {
[backgroundImage setImage:[TUNinePatchCache imageOfSize:[backgroundImage bounds].size
forNinePatchNamed:@"chat_bubble_outgoing"]];
}
[messageLabel setText:[chat message]];
}
CGRect frame = [messageLabel frame];
frame.size.height = [UIChatRoomCell messageHeight:[chat message]];
[messageLabel setFrame:frame];
}
+ (CGFloat)messageHeight:(NSString*)message {
if(CELL_FONT == nil) {
CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
}
CGSize messageSize = [message sizeWithFont: CELL_FONT
constrainedToSize: CGSizeMake(CELL_MESSAGE_MAX_WIDTH, 10000.0f)
lineBreakMode: UILineBreakModeTailTruncation];
return messageSize.height;
}
+ (CGFloat)height:(ChatModel*)chat {
CGFloat height = [UIChatRoomCell messageHeight:[chat message]];
height += 20;
if(height < CELL_MIN_HEIGHT)
height = CELL_MIN_HEIGHT;
return height;
}
- (void)enterEditMode {
[deleteButton setHidden:false];
}
- (void)exitEditMode {
[deleteButton setHidden:true];
}
#pragma mark - View Functions
- (void)layoutSubviews {
// Resize content
CGRect frame = [contentView frame];
frame.size = [self frame].size;
[contentView setFrame:frame];
}
#pragma mark - Action Functions
- (IBAction)onDeleteClick: (id) event {
if(chat != NULL) {
[chat delete];
UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];
}
}
@end

View file

@ -0,0 +1,389 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1296</int>
<string key="IBDocument.SystemVersion">11E53</string>
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
<string key="IBDocument.AppKitVersion">1138.47</string>
<string key="IBDocument.HIToolboxVersion">569.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1181</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBUIButton</string>
<string>IBUIImageView</string>
<string>IBUIView</string>
<string>IBUILabel</string>
<string>IBProxyObject</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="841351856">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="371349661">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="579600281">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIImageView" id="340144998">
<reference key="NSNextResponder" ref="579600281"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{10, 10}, {300, 120}}</string>
<reference key="NSSuperview" ref="579600281"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="456806949"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSCustomResource" key="IBUIImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">chat_bubble_incoming.png</string>
</object>
</object>
<object class="IBUIView" id="456806949">
<reference key="NSNextResponder" ref="579600281"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUILabel" id="281972462">
<reference key="NSNextResponder" ref="456806949"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{280, 100}</string>
<reference key="NSSuperview" ref="456806949"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="859609488"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">They who can give up essential liberty to obtain a little temporary safety, deserve neither liberty nor safety.</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC4zMzMzMzMzMzMzAA</bytes>
</object>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<int key="IBUINumberOfLines">100000</int>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">1</int>
<double key="pointSize">17</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica</string>
<double key="NSSize">17</double>
<int key="NSfFlags">16</int>
</object>
<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
</object>
<object class="IBUIButton" id="859609488">
<reference key="NSNextResponder" ref="456806949"/>
<int key="NSvFlags">-2147483351</int>
<string key="NSFrame">{{236, 28}, {44, 44}}</string>
<reference key="NSSuperview" ref="456806949"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<bool key="IBUIAdjustsImageWhenHighlighted">NO</bool>
<double key="IBUIImageEdgeInsets.top">11</double>
<double key="IBUIImageEdgeInsets.bottom">11</double>
<double key="IBUIImageEdgeInsets.left">11</double>
<double key="IBUIImageEdgeInsets.right">11</double>
<object class="NSColor" key="IBUINormalTitleShadowColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC41AA</bytes>
</object>
<object class="NSCustomResource" key="IBUIHighlightedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">list_delete_over.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">list_delete_default.png</string>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">2</int>
<double key="pointSize">15</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">15</double>
<int key="NSfFlags">16</int>
</object>
</object>
</array>
<string key="NSFrame">{{20, 25}, {280, 100}}</string>
<reference key="NSSuperview" ref="579600281"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="281972462"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor" id="765717609">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MCAwAA</bytes>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<string key="NSFrameSize">{320, 140}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="340144998"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="765717609"/>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUITag">10</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="369753676">
<reference key="NSNextResponder"/>
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{100, 100}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="765717609"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="111268450">
<reference key="NSNextResponder"/>
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{100, 100}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="765717609"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">backgroundView</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="369753676"/>
</object>
<int key="connectionID">10</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">backgroundImage</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="340144998"/>
</object>
<int key="connectionID">11</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">selectedBackgroundView</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="111268450"/>
</object>
<int key="connectionID">13</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">contentView</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="579600281"/>
</object>
<int key="connectionID">14</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">messageLabel</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="281972462"/>
</object>
<int key="connectionID">17</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">deleteButton</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="859609488"/>
</object>
<int key="connectionID">19</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">onDeleteClick:</string>
<reference key="source" ref="859609488"/>
<reference key="destination" ref="841351856"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">20</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="841351856"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="371349661"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="579600281"/>
<array class="NSMutableArray" key="children">
<reference ref="340144998"/>
<reference ref="456806949"/>
</array>
<reference key="parent" ref="0"/>
<string key="objectName">contentView</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="369753676"/>
<reference key="parent" ref="0"/>
<string key="objectName">backgroundView</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="111268450"/>
<reference key="parent" ref="0"/>
<string key="objectName">selectedBackgroundView</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">3</int>
<reference key="object" ref="340144998"/>
<reference key="parent" ref="579600281"/>
<string key="objectName">backgroundImage</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">16</int>
<reference key="object" ref="456806949"/>
<array class="NSMutableArray" key="children">
<reference ref="281972462"/>
<reference ref="859609488"/>
</array>
<reference key="parent" ref="579600281"/>
<string key="objectName">messageView</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">15</int>
<reference key="object" ref="281972462"/>
<reference key="parent" ref="456806949"/>
<string key="objectName">messageLabel</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">18</int>
<reference key="object" ref="859609488"/>
<reference key="parent" ref="456806949"/>
<string key="objectName">deleteButton</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">UIChatRoomCell</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="15.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="16.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="18.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="2" key="18.IBUIButtonInspectorSelectedEdgeInsetMetadataKey"/>
<real value="1" key="18.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="3.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">20</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">UIChatRoomCell</string>
<string key="superclassName">UITableViewCell</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">onDeleteClick:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">onDeleteClick:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">onDeleteClick:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="backgroundImage">UIImageView</string>
<string key="contentView">UIView</string>
<string key="deleteButton">UIButton</string>
<string key="messageLabel">UILabel</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="backgroundImage">
<string key="name">backgroundImage</string>
<string key="candidateClassName">UIImageView</string>
</object>
<object class="IBToOneOutletInfo" key="contentView">
<string key="name">contentView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="deleteButton">
<string key="name">deleteButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="messageLabel">
<string key="name">messageLabel</string>
<string key="candidateClassName">UILabel</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/UIChatRoomCell.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<real value="1296" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="chat_bubble_incoming.png">{71, 46}</string>
<string key="list_delete_default.png">{45, 45}</string>
<string key="list_delete_over.png">{45, 45}</string>
</dictionary>
<string key="IBCocoaTouchPluginVersion">1181</string>
</data>
</archive>

View file

@ -0,0 +1,39 @@
/* UIChatRoomHeader.h
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <UIKit/UIKit.h>
#import "ChatModel.h"
@interface UIChatRoomHeader : UIViewController {
UILabel *contactLabel;
UIImageView *avatarImage;
NSString *contact;
}
@property (copy) NSString *contact;
@property (nonatomic, retain) IBOutlet UILabel *contactLabel;
@property (nonatomic, retain) IBOutlet UIImageView *avatarImage;
+ (CGFloat)height;
- (void)update;
@end

View file

@ -0,0 +1,56 @@
/* UIChatRoomHeader.m
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "UIChatRoomHeader.h"
@implementation UIChatRoomHeader
@synthesize avatarImage;
@synthesize contactLabel;
@synthesize contact;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"UIChatRoomHeader" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[avatarImage release];
[contactLabel release];
[contact release];
[super dealloc];
}
#pragma mark -
- (void)update {
if(contact != nil) {
[avatarImage setImage:[UIImage imageNamed:@"avatar_unknown_small.png"]];
[contactLabel setText:contact];
}
}
+ (CGFloat)height {
return 80.0f;
}
@end

View file

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1296</int>
<string key="IBDocument.SystemVersion">11E53</string>
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
<string key="IBDocument.AppKitVersion">1138.47</string>
<string key="IBDocument.HIToolboxVersion">569.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1181</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBUIImageView</string>
<string>IBUIView</string>
<string>IBUILabel</string>
<string>IBProxyObject</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="975951072">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="1033790597">
<reference key="NSNextResponder"/>
<int key="NSvFlags">292</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIImageView" id="452773126">
<reference key="NSNextResponder" ref="1033790597"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{-13, -1}, {131, 107}}</string>
<reference key="NSSuperview" ref="1033790597"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="906825234"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSCustomResource" key="IBUIImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">avatar_shadow_small.png</string>
</object>
</object>
<object class="IBUIImageView" id="906825234">
<reference key="NSNextResponder" ref="1033790597"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{20, 10}, {65, 65}}</string>
<reference key="NSSuperview" ref="1033790597"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="683404399"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSCustomResource" key="IBUIImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">avatar_unknown_small.png</string>
</object>
</object>
<object class="IBUILabel" id="683404399">
<reference key="NSNextResponder" ref="1033790597"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{101, 31}, {199, 43}}</string>
<reference key="NSSuperview" ref="1033790597"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Contact1</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC4zMzMzMzMzMzMzAA</bytes>
</object>
<nil key="IBUIHighlightedColor"/>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">1</int>
<double key="pointSize">22</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica</string>
<double key="NSSize">22</double>
<int key="NSfFlags">16</int>
</object>
</object>
</array>
<string key="NSFrameSize">{320, 80}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="452773126"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MCAwAA</bytes>
</object>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="1033790597"/>
</object>
<int key="connectionID">5</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">avatarImage</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="906825234"/>
</object>
<int key="connectionID">9</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">contactLabel</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="683404399"/>
</object>
<int key="connectionID">11</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="975951072"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="1033790597"/>
<array class="NSMutableArray" key="children">
<reference ref="906825234"/>
<reference ref="452773126"/>
<reference ref="683404399"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="906825234"/>
<reference key="parent" ref="1033790597"/>
<string key="objectName">avatarImage</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="452773126"/>
<reference key="parent" ref="1033790597"/>
<string key="objectName">avatarShadowBackground</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="683404399"/>
<reference key="parent" ref="1033790597"/>
<string key="objectName">contactLabel</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">UIChatRoomHeader</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">11</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">UIChatRoomHeader</string>
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="avatarImage">UIImageView</string>
<string key="contactLabel">UILabel</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="avatarImage">
<string key="name">avatarImage</string>
<string key="candidateClassName">UIImageView</string>
</object>
<object class="IBToOneOutletInfo" key="contactLabel">
<string key="name">contactLabel</string>
<string key="candidateClassName">UILabel</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/UIChatRoomHeader.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<real value="1296" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="avatar_shadow_small.png">{262, 214}</string>
<string key="avatar_unknown_small.png">{131, 131}</string>
</dictionary>
<string key="IBCocoaTouchPluginVersion">1181</string>
</data>
</archive>

View file

@ -101,6 +101,7 @@
+ (void)addSubView:(UIViewController*)controller view:(UIView*)view {
if(controller != nil) {
[controller view]; // Load the view
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[controller viewWillAppear:NO];
}

View file

@ -61,7 +61,7 @@
#pragma mark -
- (void)update {
[self view];
[self view]; // Force view load
[stateImage setHidden:true];
[pauseButton update];
}

View file

@ -51,7 +51,6 @@ NSTimer *callQualityTimer;
[super viewWillAppear:animated];
// Set callQualityTimer
[callQualityImage setHidden: true];
callQualityTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(callQualityUpdate)
@ -64,6 +63,9 @@ NSTimer *callQualityTimer;
name:@"LinphoneRegistrationUpdate"
object:nil];
[callQualityImage setHidden: true];
// Update to default state
LinphoneProxyConfig* config = NULL;
if([LinphoneManager isLcReady])

View file

@ -24,7 +24,7 @@
NSNumber *chatId;
NSString *localContact;
NSString *remoteContact;
NSNumber *direction;
NSNumber *direction; //0 outgoing 1 incoming
NSString *message;
NSDate *time;
}
@ -43,5 +43,6 @@
+ (NSArray *) listConversations;
+ (NSArray *) listMessages:(NSString *)contact;
+ (void) removeConversation:(NSString *)contact;
@end

View file

@ -139,7 +139,7 @@
return;
}
const char *sql = [[NSString stringWithFormat:@"DELETE chat WHERE id=%@",
const char *sql = [[NSString stringWithFormat:@"DELETE FROM chat WHERE id=%@",
chatId] UTF8String];
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
@ -226,4 +226,28 @@
return fArray;
}
+ (void) removeConversation:(NSString *)contact {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
NSLog(@"Database not ready");
return;
}
const char *sql = [[NSString stringWithFormat:@"DELETE FROM chat WHERE remoteContact=\"%@\"",
contact] UTF8String];
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
NSLog(@"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database));
return;
}
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
NSLog(@"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database));
sqlite3_finalize(sqlStatement);
return;
}
sqlite3_finalize(sqlStatement);
}
@end

View file

@ -43,6 +43,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{320, 394}</string>
<reference key="NSSuperview" ref="770392660"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="844572400"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -57,6 +58,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{320, 394}</string>
<reference key="NSSuperview" ref="770392660"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1057285194"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor" id="981989056">
@ -75,6 +77,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{160, 77}</string>
<reference key="NSSuperview" ref="1057285194"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="237722854"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -91,6 +94,10 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_cancel_over.png</string>
</object>
<object class="NSCustomResource" key="IBUISelectedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_cancel_disabled.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_cancel_default.png</string>
@ -110,6 +117,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{160, 0}, {160, 77}}</string>
<reference key="NSSuperview" ref="1057285194"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="483101671"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -123,6 +131,10 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_start_over.png</string>
</object>
<object class="NSCustomResource" key="IBUISelectedImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_start_disabled.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_start_default.png</string>
@ -135,6 +147,8 @@
<int key="NSvFlags">-2147483356</int>
<string key="NSFrame">{{160, 0}, {160, 77}}</string>
<reference key="NSSuperview" ref="1057285194"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
@ -147,6 +161,10 @@
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_back_over.png</string>
</object>
<object class="NSCustomResource" key="IBUIDisabledImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_back_disabled.png</string>
</object>
<object class="NSCustomResource" key="IBUINormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">setup_back_default.png</string>
@ -157,6 +175,7 @@
</array>
<string key="NSFrame">{{0, 383}, {320, 77}}</string>
<reference key="NSSuperview" ref="770392660"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="954353386"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -165,6 +184,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="57178294"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
@ -185,6 +205,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrame">{{60, 80}, {201, 129}}</string>
<reference key="NSSuperview" ref="741268807"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="265601557"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -199,6 +220,8 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{40, 313}, {240, 44}}</string>
<reference key="NSSuperview" ref="741268807"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
@ -228,6 +251,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="462684684"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -242,6 +266,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrame">{{31, 50}, {258, 24}}</string>
<reference key="NSSuperview" ref="361414027"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="480353232"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -256,6 +281,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 141}, {255, 50}}</string>
<reference key="NSSuperview" ref="361414027"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="406896406"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -289,6 +315,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 205}, {255, 50}}</string>
<reference key="NSSuperview" ref="361414027"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="505877593"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -309,6 +336,8 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 269}, {255, 50}}</string>
<reference key="NSSuperview" ref="361414027"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
@ -326,6 +355,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="649000156"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -340,6 +370,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrame">{{31, 50}, {258, 24}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="696113137"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -351,6 +382,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{39, 80}, {240, 44}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="832238181"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -374,6 +406,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 140}, {255, 31}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="659911482"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -412,6 +445,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 185}, {255, 31}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="71471916"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -441,6 +475,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 230}, {255, 31}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="131114733"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -470,6 +505,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 275}, {255, 31}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="354411721"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -498,6 +534,8 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 330}, {255, 50}}</string>
<reference key="NSSuperview" ref="183617546"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
@ -522,6 +560,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="226477992"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -536,6 +575,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrame">{{31, 50}, {258, 24}}</string>
<reference key="NSSuperview" ref="101753691"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="391450353"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -547,6 +587,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{40, 80}, {240, 44}}</string>
<reference key="NSSuperview" ref="101753691"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="280076734"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -570,6 +611,8 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 330}, {255, 50}}</string>
<reference key="NSSuperview" ref="101753691"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
@ -589,6 +632,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 185}, {255, 31}}</string>
<reference key="NSSuperview" ref="101753691"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="432867973"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -618,6 +662,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{32, 140}, {255, 31}}</string>
<reference key="NSSuperview" ref="101753691"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="664779559"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -644,6 +689,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="516333334"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -658,6 +704,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrame">{{31, 50}, {258, 24}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="923226743"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIUserInteractionEnabled">NO</bool>
@ -669,6 +716,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{40, 80}, {240, 44}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="709333986"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -692,6 +740,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 140}, {255, 31}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="63757284"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -720,6 +769,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 185}, {255, 31}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="717187070"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -749,6 +799,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{33, 230}, {255, 31}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="616473368"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
@ -777,6 +828,8 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{34, 330}, {255, 50}}</string>
<reference key="NSSuperview" ref="71390966"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
@ -794,6 +847,7 @@
</array>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="732522673"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<reference key="IBUIBackgroundColor" ref="981989056"/>
@ -1292,11 +1346,11 @@
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="15.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="16.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="1" key="16.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<real value="2" key="16.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="1" key="17.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<real value="3" key="17.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="18.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="1" key="18.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<real value="2" key="18.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="19.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="21.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@ -1339,7 +1393,96 @@
<nil key="sourceID"/>
<int key="maxID">88</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">WizardViewController</string>
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="onBackClick:">id</string>
<string key="onCancelClick:">id</string>
<string key="onConnectAccountClick:">id</string>
<string key="onCreateAccountClick:">id</string>
<string key="onExternalAccountClick:">id</string>
<string key="onStartClick:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="onBackClick:">
<string key="name">onBackClick:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="onCancelClick:">
<string key="name">onCancelClick:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="onConnectAccountClick:">
<string key="name">onConnectAccountClick:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="onCreateAccountClick:">
<string key="name">onCreateAccountClick:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="onExternalAccountClick:">
<string key="name">onExternalAccountClick:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="onStartClick:">
<string key="name">onStartClick:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="backButton">UIButton</string>
<string key="choiceView">UIView</string>
<string key="connectAccountView">UIView</string>
<string key="contentView">UIView</string>
<string key="createAccountView">UIView</string>
<string key="externalAccountView">UIView</string>
<string key="startButton">UIButton</string>
<string key="welcomeView">UIView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="backButton">
<string key="name">backButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="choiceView">
<string key="name">choiceView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="connectAccountView">
<string key="name">connectAccountView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="contentView">
<string key="name">contentView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="createAccountView">
<string key="name">createAccountView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="externalAccountView">
<string key="name">externalAccountView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="startButton">
<string key="name">startButton</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="welcomeView">
<string key="name">welcomeView</string>
<string key="candidateClassName">UIView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/WizardViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
@ -1353,11 +1496,14 @@
<string key="button_background_over.png">{550, 101}</string>
<string key="numpad_background.png">{640, 523}</string>
<string key="setup_back_default.png">{320, 154}</string>
<string key="setup_back_disabled.png">{320, 154}</string>
<string key="setup_back_over.png">{320, 154}</string>
<string key="setup_cancel_default.png">{320, 154}</string>
<string key="setup_cancel_disabled.png">{320, 154}</string>
<string key="setup_cancel_over.png">{320, 154}</string>
<string key="setup_label.png">{542, 88}</string>
<string key="setup_start_default.png">{320, 154}</string>
<string key="setup_start_disabled.png">{320, 154}</string>
<string key="setup_start_over.png">{320, 154}</string>
<string key="setup_title_assistant.png">{516, 48}</string>
<string key="setup_welcome_logo.png">{402, 258}</string>

15
NinePatch/NinePatch.h Executable file
View file

@ -0,0 +1,15 @@
/*
* NinePatch.h
* NinePatch
*
* Copyright 2010 Tortuga 22, Inc. All rights reserved.
*
*/
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatchProtocols.h"
#import "TUNinePatch.h"
#import "TUNinePatchCache.h"
#import "TUDebugLoggingAssistant.h"

View file

@ -0,0 +1,461 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
324A2926111CC27800CC0BF0 /* TUNinePatchCachingCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 324A2924111CC27800CC0BF0 /* TUNinePatchCachingCategories.h */; };
324A2927111CC27800CC0BF0 /* TUNinePatchCachingCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 324A2925111CC27800CC0BF0 /* TUNinePatchCachingCategories.m */; };
324A2930111CC2CB00CC0BF0 /* TUCachingNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 324A292E111CC2CB00CC0BF0 /* TUCachingNinePatch.h */; };
324A2931111CC2CB00CC0BF0 /* TUCachingNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 324A292F111CC2CB00CC0BF0 /* TUCachingNinePatch.m */; };
324A2940111CE12C00CC0BF0 /* TUNinePatchCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 324A293E111CE12C00CC0BF0 /* TUNinePatchCache.h */; };
324A2941111CE12C00CC0BF0 /* TUNinePatchCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 324A293F111CE12C00CC0BF0 /* TUNinePatchCache.m */; };
325B80EF11B001C300B86EA1 /* TUDebugLoggingAssistant.h in Headers */ = {isa = PBXBuildFile; fileRef = 325B80ED11B001C300B86EA1 /* TUDebugLoggingAssistant.h */; };
325B80F011B001C300B86EA1 /* TUDebugLoggingAssistant.m in Sources */ = {isa = PBXBuildFile; fileRef = 325B80EE11B001C300B86EA1 /* TUDebugLoggingAssistant.m */; };
325B80F811B00C9800B86EA1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 325B80F711B00C9800B86EA1 /* CoreFoundation.framework */; };
325B821F11B317E400B86EA1 /* NinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 325B821E11B317E400B86EA1 /* NinePatch.h */; };
32BBFEFF10E95B5700F57FBC /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32BBFEFE10E95B5700F57FBC /* CoreGraphics.framework */; };
32BBFF0610E95B6E00F57FBC /* TUNinePatchProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF0510E95B6E00F57FBC /* TUNinePatchProtocols.h */; };
32BBFF2710E95BCF00F57FBC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32BBFF2610E95BCF00F57FBC /* UIKit.framework */; };
32BBFF2C10E95BF900F57FBC /* TUNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF2A10E95BF900F57FBC /* TUNinePatch.h */; };
32BBFF2D10E95BF900F57FBC /* TUNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBFF2B10E95BF900F57FBC /* TUNinePatch.m */; };
32BBFF3510E95CA700F57FBC /* TUHorizontalNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF3310E95CA700F57FBC /* TUHorizontalNinePatch.h */; };
32BBFF3610E95CA700F57FBC /* TUHorizontalNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBFF3410E95CA700F57FBC /* TUHorizontalNinePatch.m */; };
32BBFF3910E95CD600F57FBC /* TUVerticalNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF3710E95CD600F57FBC /* TUVerticalNinePatch.h */; };
32BBFF3A10E95CD600F57FBC /* TUVerticalNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBFF3810E95CD600F57FBC /* TUVerticalNinePatch.m */; };
32BBFF3D10E95D3800F57FBC /* TUFullNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF3B10E95D3800F57FBC /* TUFullNinePatch.h */; };
32BBFF3E10E95D3800F57FBC /* TUFullNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBFF3C10E95D3800F57FBC /* TUFullNinePatch.m */; };
32BBFF4310E9605300F57FBC /* UIImage-TUNinePatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBFF4110E9605300F57FBC /* UIImage-TUNinePatch.h */; };
32BBFF4410E9605300F57FBC /* UIImage-TUNinePatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBFF4210E9605300F57FBC /* UIImage-TUNinePatch.m */; };
AA747D9F0F9514B9006C5449 /* NinePatch_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* NinePatch_Prefix.pch */; };
AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
324A2924111CC27800CC0BF0 /* TUNinePatchCachingCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUNinePatchCachingCategories.h; sourceTree = "<group>"; };
324A2925111CC27800CC0BF0 /* TUNinePatchCachingCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUNinePatchCachingCategories.m; sourceTree = "<group>"; };
324A292E111CC2CB00CC0BF0 /* TUCachingNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUCachingNinePatch.h; sourceTree = "<group>"; };
324A292F111CC2CB00CC0BF0 /* TUCachingNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUCachingNinePatch.m; sourceTree = "<group>"; };
324A293E111CE12C00CC0BF0 /* TUNinePatchCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUNinePatchCache.h; sourceTree = "<group>"; };
324A293F111CE12C00CC0BF0 /* TUNinePatchCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUNinePatchCache.m; sourceTree = "<group>"; };
325B80ED11B001C300B86EA1 /* TUDebugLoggingAssistant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUDebugLoggingAssistant.h; sourceTree = "<group>"; };
325B80EE11B001C300B86EA1 /* TUDebugLoggingAssistant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUDebugLoggingAssistant.m; sourceTree = "<group>"; };
325B80F711B00C9800B86EA1 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
325B821E11B317E400B86EA1 /* NinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NinePatch.h; sourceTree = "<group>"; };
32BBFEFE10E95B5700F57FBC /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
32BBFF0510E95B6E00F57FBC /* TUNinePatchProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUNinePatchProtocols.h; sourceTree = "<group>"; };
32BBFF2610E95BCF00F57FBC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
32BBFF2A10E95BF900F57FBC /* TUNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUNinePatch.h; sourceTree = "<group>"; };
32BBFF2B10E95BF900F57FBC /* TUNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUNinePatch.m; sourceTree = "<group>"; };
32BBFF3310E95CA700F57FBC /* TUHorizontalNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUHorizontalNinePatch.h; sourceTree = "<group>"; };
32BBFF3410E95CA700F57FBC /* TUHorizontalNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUHorizontalNinePatch.m; sourceTree = "<group>"; };
32BBFF3710E95CD600F57FBC /* TUVerticalNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUVerticalNinePatch.h; sourceTree = "<group>"; };
32BBFF3810E95CD600F57FBC /* TUVerticalNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUVerticalNinePatch.m; sourceTree = "<group>"; };
32BBFF3B10E95D3800F57FBC /* TUFullNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUFullNinePatch.h; sourceTree = "<group>"; };
32BBFF3C10E95D3800F57FBC /* TUFullNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUFullNinePatch.m; sourceTree = "<group>"; };
32BBFF4110E9605300F57FBC /* UIImage-TUNinePatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage-TUNinePatch.h"; sourceTree = "<group>"; };
32BBFF4210E9605300F57FBC /* UIImage-TUNinePatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage-TUNinePatch.m"; sourceTree = "<group>"; };
AA747D9E0F9514B9006C5449 /* NinePatch_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NinePatch_Prefix.pch; sourceTree = SOURCE_ROOT; };
AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D2AAC07E0554694100DB518D /* libNinePatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNinePatch.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D2AAC07C0554694100DB518D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */,
32BBFEFF10E95B5700F57FBC /* CoreGraphics.framework in Frameworks */,
32BBFF2710E95BCF00F57FBC /* UIKit.framework in Frameworks */,
325B80F811B00C9800B86EA1 /* CoreFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
D2AAC07E0554694100DB518D /* libNinePatch.a */,
);
name = Products;
sourceTree = "<group>";
};
0867D691FE84028FC02AAC07 /* NinePatch */ = {
isa = PBXGroup;
children = (
08FB77AEFE84172EC02AAC07 /* Classes */,
32C88DFF0371C24200C91783 /* Other Sources */,
0867D69AFE84028FC02AAC07 /* Frameworks */,
034768DFFF38A50411DB9C8B /* Products */,
32BBFF2610E95BCF00F57FBC /* UIKit.framework */,
325B80F711B00C9800B86EA1 /* CoreFoundation.framework */,
325B821E11B317E400B86EA1 /* NinePatch.h */,
);
name = NinePatch;
sourceTree = "<group>";
};
0867D69AFE84028FC02AAC07 /* Frameworks */ = {
isa = PBXGroup;
children = (
32BBFEFE10E95B5700F57FBC /* CoreGraphics.framework */,
AACBBE490F95108600F1A2B1 /* Foundation.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
08FB77AEFE84172EC02AAC07 /* Classes */ = {
isa = PBXGroup;
children = (
325B80EC11B0019B00B86EA1 /* Debugging Utilities */,
324A292C111CC2C100CC0BF0 /* Caching */,
32BBFF4010E9604300F57FBC /* Categories */,
32BBFF3F10E9603E00F57FBC /* NinePatch */,
);
name = Classes;
sourceTree = "<group>";
};
324A292C111CC2C100CC0BF0 /* Caching */ = {
isa = PBXGroup;
children = (
324A292E111CC2CB00CC0BF0 /* TUCachingNinePatch.h */,
324A292F111CC2CB00CC0BF0 /* TUCachingNinePatch.m */,
324A293E111CE12C00CC0BF0 /* TUNinePatchCache.h */,
324A293F111CE12C00CC0BF0 /* TUNinePatchCache.m */,
);
name = Caching;
sourceTree = "<group>";
};
325B80EC11B0019B00B86EA1 /* Debugging Utilities */ = {
isa = PBXGroup;
children = (
325B80ED11B001C300B86EA1 /* TUDebugLoggingAssistant.h */,
325B80EE11B001C300B86EA1 /* TUDebugLoggingAssistant.m */,
);
name = "Debugging Utilities";
sourceTree = "<group>";
};
32BBFF3F10E9603E00F57FBC /* NinePatch */ = {
isa = PBXGroup;
children = (
32BBFF0510E95B6E00F57FBC /* TUNinePatchProtocols.h */,
32BBFF2A10E95BF900F57FBC /* TUNinePatch.h */,
32BBFF2B10E95BF900F57FBC /* TUNinePatch.m */,
32BBFF3310E95CA700F57FBC /* TUHorizontalNinePatch.h */,
32BBFF3410E95CA700F57FBC /* TUHorizontalNinePatch.m */,
32BBFF3710E95CD600F57FBC /* TUVerticalNinePatch.h */,
32BBFF3810E95CD600F57FBC /* TUVerticalNinePatch.m */,
32BBFF3B10E95D3800F57FBC /* TUFullNinePatch.h */,
32BBFF3C10E95D3800F57FBC /* TUFullNinePatch.m */,
);
name = NinePatch;
sourceTree = "<group>";
};
32BBFF4010E9604300F57FBC /* Categories */ = {
isa = PBXGroup;
children = (
32BBFF4110E9605300F57FBC /* UIImage-TUNinePatch.h */,
32BBFF4210E9605300F57FBC /* UIImage-TUNinePatch.m */,
324A2924111CC27800CC0BF0 /* TUNinePatchCachingCategories.h */,
324A2925111CC27800CC0BF0 /* TUNinePatchCachingCategories.m */,
);
name = Categories;
sourceTree = "<group>";
};
32C88DFF0371C24200C91783 /* Other Sources */ = {
isa = PBXGroup;
children = (
AA747D9E0F9514B9006C5449 /* NinePatch_Prefix.pch */,
);
name = "Other Sources";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D2AAC07A0554694100DB518D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
AA747D9F0F9514B9006C5449 /* NinePatch_Prefix.pch in Headers */,
32BBFF0610E95B6E00F57FBC /* TUNinePatchProtocols.h in Headers */,
32BBFF2C10E95BF900F57FBC /* TUNinePatch.h in Headers */,
32BBFF3510E95CA700F57FBC /* TUHorizontalNinePatch.h in Headers */,
32BBFF3910E95CD600F57FBC /* TUVerticalNinePatch.h in Headers */,
32BBFF3D10E95D3800F57FBC /* TUFullNinePatch.h in Headers */,
32BBFF4310E9605300F57FBC /* UIImage-TUNinePatch.h in Headers */,
324A2926111CC27800CC0BF0 /* TUNinePatchCachingCategories.h in Headers */,
324A2930111CC2CB00CC0BF0 /* TUCachingNinePatch.h in Headers */,
324A2940111CE12C00CC0BF0 /* TUNinePatchCache.h in Headers */,
325B80EF11B001C300B86EA1 /* TUDebugLoggingAssistant.h in Headers */,
325B821F11B317E400B86EA1 /* NinePatch.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D2AAC07D0554694100DB518D /* NinePatch */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "NinePatch" */;
buildPhases = (
D2AAC07A0554694100DB518D /* Headers */,
D2AAC07B0554694100DB518D /* Sources */,
D2AAC07C0554694100DB518D /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = NinePatch;
productName = NinePatch;
productReference = D2AAC07E0554694100DB518D /* libNinePatch.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
};
buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "NinePatch" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 0867D691FE84028FC02AAC07 /* NinePatch */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D2AAC07D0554694100DB518D /* NinePatch */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
D2AAC07B0554694100DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32BBFF2D10E95BF900F57FBC /* TUNinePatch.m in Sources */,
32BBFF3610E95CA700F57FBC /* TUHorizontalNinePatch.m in Sources */,
32BBFF3A10E95CD600F57FBC /* TUVerticalNinePatch.m in Sources */,
32BBFF3E10E95D3800F57FBC /* TUFullNinePatch.m in Sources */,
32BBFF4410E9605300F57FBC /* UIImage-TUNinePatch.m in Sources */,
324A2927111CC27800CC0BF0 /* TUNinePatchCachingCategories.m in Sources */,
324A2931111CC2CB00CC0BF0 /* TUCachingNinePatch.m in Sources */,
324A2941111CE12C00CC0BF0 /* TUNinePatchCache.m in Sources */,
325B80F011B001C300B86EA1 /* TUDebugLoggingAssistant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1DEB921F08733DC00010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv6,
"$(ARCHS_STANDARD_32_BIT)",
);
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/NinePatch.dst;
GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = NinePatch_Prefix.pch;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/local/lib;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = NinePatch;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
1DEB922008733DC00010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv6,
"$(ARCHS_STANDARD_32_BIT)",
);
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/NinePatch.dst;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = s;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = NinePatch_Prefix.pch;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/local/lib;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = NinePatch;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
1DEB922308733DC00010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "Don't Code Sign";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
};
name = Debug;
};
1DEB922408733DC00010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "Don't Code Sign";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
};
name = Release;
};
D3D14E7E15A72BD10074A527 /* Distribution */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "Don't Code Sign";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
};
name = Distribution;
};
D3D14E7F15A72BD10074A527 /* Distribution */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv6,
"$(ARCHS_STANDARD_32_BIT)",
);
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/NinePatch.dst;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = s;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = NinePatch_Prefix.pch;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/local/lib;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = NinePatch;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Distribution;
};
D3D14E8015A72BD70074A527 /* DistributionAdhoc */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "Don't Code Sign";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
};
name = DistributionAdhoc;
};
D3D14E8115A72BD70074A527 /* DistributionAdhoc */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv6,
"$(ARCHS_STANDARD_32_BIT)",
);
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/NinePatch.dst;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = s;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = NinePatch_Prefix.pch;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/local/lib;
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = NinePatch;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = DistributionAdhoc;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "NinePatch" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB921F08733DC00010E9CD /* Debug */,
1DEB922008733DC00010E9CD /* Release */,
D3D14E7F15A72BD10074A527 /* Distribution */,
D3D14E8115A72BD70074A527 /* DistributionAdhoc */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "NinePatch" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB922308733DC00010E9CD /* Debug */,
1DEB922408733DC00010E9CD /* Release */,
D3D14E7E15A72BD10074A527 /* Distribution */,
D3D14E8015A72BD70074A527 /* DistributionAdhoc */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}

157
NinePatch/NinePatch_Prefix.pch Executable file
View file

@ -0,0 +1,157 @@
//
// Prefix header for all source files of the 'CocoaTouchStaticLibrary' target in the 'CocoaTouchStaticLibrary' project.
//
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
/**
This struct is used for doing pixel-tasting. We get CoreGraphics to create a bitmap context wherein the memory representation looks like this struct, then we cast the pointer to that memory to be of this struct's type. Pretty self-explanatory.
*/
typedef struct _TURGBAPixel {
UInt8 red;
UInt8 green;
UInt8 blue;
UInt8 alpha;
} TURGBAPixel;
/**
Defined here, used as part of the pixel-tasting code. Helps make sure the memory representation of the bitmap context is made up of stuff that looks just like TURGBAPixel.
*/
#define TURGBABytesPerPixel (4)
/**
This tests if a pixel is black. Here "black" means alpha isn't at zero (AKA: it's at least partially opaque) and r == g == b == 0.
*/
#define TURGBAPixelIsBlack(PIXEL) (((PIXEL.red == 0) && (PIXEL.green == 0) && (PIXEL.blue == 0) && (PIXEL.alpha != 0))?(YES):(NO))
#define TUNotFoundRange (NSMakeRange(NSNotFound,0))
#define TUIsNotFoundRange(RANGE) (NSEqualRanges(RANGE, TUNotFoundRange))
#define TUTruncateBelow(VALUE, FLOOR) ((( VALUE ) < ( FLOOR ))?(( FLOOR )):(( VALUE )))
#define TUTruncateAbove(VALUE, CEILING) ((( VALUE ) > ( CEILING ))?(( CEILING )):(( VALUE )))
#define TUTruncateWithin(VALUE, FLOOR, CEILING) ((( VALUE ) < ( FLOOR ))?(( FLOOR )):((( VALUE ) > ( CEILING ))?(( CEILING )):(( VALUE ))))
#define TUTruncateAtZero(VALUE) TUTruncateBelow(VALUE, 0.0f)
#define TUForceYesOrNo(ABOOL) ((ABOOL)?(YES):(NO))
#define TUYesOrNoString(ABOOL) ((( ABOOL ))?(@"YES"):(@"NO"))
#define TUWithinEpsilon(EPSILON, X, Y) TUForceYesOrNo((((X-Y) > (-1.0f * EPSILON)) || ((X-Y) < EPSILON)))
//#define DEBUG
//#define NP_ASSERTION_CHECKING
//#define IMAGEDEBUG
// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(@"%@", aStringVariable);
#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LLog(STR) DLog(@"%@",STR)
#define NPLogException(E) DLog(@"Caught '%@' < '%@', '%@' >.",[E name],[E reason],[E userInfo])
#define NPLogError(E) DLog(@"Error: '%@', '%@', '%@'.",[E localizedDescription],[E localizedFailureReason],[E localizedRecoveryOptions]);
#ifdef NP_ASSERTION_CHECKING
#define NPLogExceptionRethrowIfAssertionFailure(E) { \
NPLogException(E); \
if (E && [[E name] isEqualToString:NSInternalInconsistencyException]) { \
@throw E; \
}}
#else
#define NPLogExceptionRethrowIfAssertionFailure(E) NPLogException(E)
#endif
#ifdef NP_OUTPUT_LOGGING
#define NPFOutputLog(AFLOAT) DLog(@"returning %s: '%f'.",#AFLOAT,AFLOAT)
#define NPDOutputLog(ANINT) DLog(@"returning %s: '%d'.",#ANINT,ANINT)
#define NPOOutputLog(ANOBJ) DLog(@"returning %s: '%@'.",#ANOBJ,ANOBJ)
#define NPBOutputLog(ABOOL) DLog(@"returning %s: '%@'.",#ABOOL,TUYesOrNoString(ABOOL))
#define NPCGROutputLog(ARECT) DLog(@"returning %s: '%@'.",#ARECT,NSStringFromCGRect(ARECT))
#define NPCGSOutputLog(ASIZE) DLog(@"returning %s: '%@'.",#ASIZE,NSStringFromCGSize(ASIZE))
#define NPCGPOutputLog(APOINT) DLog(@"returning %s: '%@'.",#APOINT,NSStringFromCGPoint(APOINT))
#define NPNSROutputLog(ARANGE) DLog(@"returning %s: '%@'.",#ARANGE,NSStringFromRange(ARANGE))
#else
#define NPFOutputLog(...)
#define NPDOutputLog(...)
#define NPOOutputLog(...)
#define NPBOutputLog(...)
#define NPCGROutputLog(...)
#define NPCGSOutputLog(...)
#define NPCGPOutputLog(...)
#define NPNSROutputLog(...)
#endif
#ifdef NP_INPUT_LOGGING
#define NPAInputLog(...) DLog(##__VA_ARGS__)
// convenience input loggers for single-argument messages
#define NPAFInputLog(AFLOAT) DLog(@"%s: '%f'",#AFLOAT,AFLOAT)
#define NPADInputLog(ANINT) DLog(@"%s: '%d'",#ANINT,ANINT)
#define NPAOInputLog(ANOBJ) DLog(@"%s: '%@'",#ANOBJ,ANOBJ)
#define NPABInputLog(ABOOL) DLog(@"%s: '%@'",#ABOOL,TUYesOrNoString(ABOOL))
#else
#define NPAInputLog(...)
#define NPAFInputLog(AFLOAT)
#define NPADInputLog(ANINT)
#define NPAOInputLog(ANOBJ)
#define NPABInputLog(ABOOL)
#endif
#ifdef NP_ASSERTION_CHECKING
#define NPParameterAssert(COND) NSParameterAssert(COND)
#define NPCParameterAssert(COND) NSCParameterAssert(COND)
#define NPAssert(COND,DESC) NSAssert(COND,DESC)
#define NPCAssert(COND,DESC) NSCAssert(COND,DESC)
#else
#define NPParameterAssert(...)
#define NPCParameterAssert(...)
#define NPAssert(...)
#define NPCAssert(...)
#endif
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
#define PASSTHROUGH(X) X
#define NPOBJCStringOfToken(TOKEN) PASSTHROUGH(PASTE( PASSTHROUGH(@), PASSTHROUGH(STRINGIFY(TOKEN))))
#define NPSelfProperty(PROP)
//#define NPSelfProperty(PROP) (self.PROP)
//#define NPSelfProperty(PROP) ([self PROP])
#define NPAssertPropertyNonNil(PROP) NPAssert((NPSelfProperty(PROP) != nil), ([NSString stringWithFormat:@"self.%s should never be nil.",( (#PROP) )]))
#define NPParameterAssertNotNilConformsToProtocol(OBJ,PROT) NPParameterAssert((OBJ != nil) && ([OBJ conformsToProtocol:@protocol(PROT)]))
#define NPParameterAssertNotNilIsKindOfClass(OBJ,CLASS) NPParameterAssert((OBJ != nil) && ([OBJ isKindOfClass:[CLASS class]]))
#define NPAssertNilOrConformsToProtocol(OBJ,PROT) NPAssert(((OBJ == nil) || ((OBJ != nil) && [OBJ conformsToProtocol:@protocol(PROT)])),([NSString stringWithFormat:@"Variable %s must either be nil or conform to %s protocol.", ( (#OBJ) ), ( (#PROT) )]))
#define NPAssertNilOrIsKindOfClass(OBJ,CLASS) NPAssert(((OBJ == nil) || ((OBJ != nil) && [OBJ isKindOfClass:[CLASS class]])), ([NSString stringWithFormat:@"Variable %s must either be nil or be kind of %s class.", (#OBJ), (#CLASS)]))
#define NPAssertWithinEpsilon(EPSILON,X,Y) NPAssert( (((X-Y) > (-1.0f * EPSILON)) || ((X-Y) < EPSILON)),([NSString stringWithFormat:@"Should have (%s,%s) within %f but instead (%f,%f).",#X,#Y,EPSILON,X,Y]))
#define NPAssertWithinOne(X,Y) NPAssertWithinEpsilon(1.0f,X,Y)
#define NPAssertThreeSubSizesSumCorrectlyOnOneAxis(AXIS,MASTERSIZE,SIZE_ONE,SIZE_TWO,SIZE_THREE) NPAssertWithinOne(MASTERSIZE.AXIS,( SIZE_ONE.AXIS + SIZE_TWO.AXIS + SIZE_THREE.AXIS ))
#define NPAssertCorrectSubsizeWidthDecomposition(MASTER,SIZE_ONE,SIZE_TWO,SIZE_THREE) NPAssertThreeSubSizesSumCorrectlyOnOneAxis(width, MASTER, SIZE_ONE, SIZE_TWO, SIZE_THREE)
#define NPAssertCorrectSubsizeHeightDecomposition(MASTER,SIZE_ONE,SIZE_TWO,SIZE_THREE) NPAssertThreeSubSizesSumCorrectlyOnOneAxis(height, MASTER, SIZE_ONE, SIZE_TWO, SIZE_THREE)
#define NPAssertCorrectSubimageWidthDecomposition(MASTER,IMAGE_ONE,IMAGE_TWO,IMAGE_THREE) NPAssertCorrectSubsizeWidthDecomposition([MASTER size],[IMAGE_ONE size],[IMAGE_TWO size],[IMAGE_THREE size])
#define NPAssertCorrectSubimageHeightDecomposition(MASTER,IMAGE_ONE,IMAGE_TWO,IMAGE_THREE) NPAssertCorrectSubsizeWidthDecomposition([MASTER size],[IMAGE_ONE size],[IMAGE_TWO size],[IMAGE_THREE size])
#ifdef IMAGEDEBUG
#define IMLog(IMAGE, IMAGENAME) TUImageLog(IMAGE,[[NSString stringWithFormat:@"debugImage.%.0f.%u.",[NSDate timeIntervalSinceReferenceDate],((NSUInteger) rand())] stringByAppendingString:( IMAGENAME )])
#else
#define IMLog(IMAGE, IMAGENAME)
#endif

51
NinePatch/TUCachingNinePatch.h Executable file
View file

@ -0,0 +1,51 @@
//
// TUCachingNinePatch.h
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TUNinePatchProtocols.h"
@interface TUCachingNinePatch : NSObject < NSCoding, NSCopying > {
id < TUNinePatch > _ninePatch;
NSMutableDictionary *_ninePatchImageCache;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) id < TUNinePatch > ninePatch;
@property(nonatomic, retain, readonly) NSMutableDictionary *ninePatchImageCache;
// Init + Dealloc
-(id)initWithNinePatchNamed:(NSString *)ninePatchName;
-(id)initWithNinePatch:(id < TUNinePatch >)ninePatch;
+(id)ninePatchCacheWithNinePatchNamed:(NSString *)ninePatchName;
+(id)ninePatchCacheWithNinePatch:(id < TUNinePatch >)ninePatch;
-(void)dealloc;
// NSCoding
-(id)initWithCoder:(NSCoder *)aDecoder;
-(void)encodeWithCoder:(NSCoder *)anEncoder;
// NSCopying
-(id)copyWithZone:(NSZone *)zone;
// Nib
-(void)awakeFromNib;
// Cache Management
-(void)flushCachedImages;
// Image Access - Utility Accessors
-(UIImage *)imageOfSize:(CGSize)size;
// Cache Access
-(void)cacheImage:(UIImage *)image ofSize:(CGSize)size;
-(UIImage *)cachedImageOfSize:(CGSize)size;
// Image Construction
-(UIImage *)constructImageOfSize:(CGSize)size;
@end

125
NinePatch/TUCachingNinePatch.m Executable file
View file

@ -0,0 +1,125 @@
//
// TUCachingNinePatch.m
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import "TUCachingNinePatch.h"
#import "TUNinePatch.h"
#import "TUNinePatchCachingCategories.h"
@interface TUCachingNinePatch ()
// Synthesized Properties
@property(nonatomic, retain, readwrite) id < TUNinePatch > ninePatch;
@property(nonatomic, retain, readwrite) NSMutableDictionary *ninePatchImageCache;
@end
@implementation TUCachingNinePatch
#pragma mark Synthesized Properties
@synthesize ninePatch = _ninePatch;
@synthesize ninePatchImageCache = _ninePatchImageCache;
#pragma mark Init + Dealloc
-(id)initWithNinePatchNamed:(NSString *)ninePatchName {
return [self initWithNinePatch:[TUNinePatch ninePatchNamed:ninePatchName]];
}
-(id)initWithNinePatch:(id < TUNinePatch >)ninePatch {
if (self = [super init]) {
self.ninePatch = ninePatch;
self.ninePatchImageCache = [NSMutableDictionary dictionaryWithCapacity:5];
}
return self;
}
#pragma mark -
+(id)ninePatchCacheWithNinePatchNamed:(NSString *)ninePatchName {
return [[[self alloc] initWithNinePatchNamed:ninePatchName] autorelease];
}
+(id)ninePatchCacheWithNinePatch:(id < TUNinePatch >)ninePatch {
return [[[self alloc] initWithNinePatch:ninePatch] autorelease];
}
#pragma mark -
-(void)dealloc {
self.ninePatch = nil;
self.ninePatchImageCache = nil;
[super dealloc];
}
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)aDecoder {
NSParameterAssert(aDecoder != nil);
if (self = [super init]) {
self.ninePatch = [aDecoder decodeObjectForKey:@"ninePatch"];
self.ninePatchImageCache = [aDecoder decodeObjectForKey:@"ninePatchImageCache"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)anEncoder {
NSParameterAssert(anEncoder != nil);
[anEncoder encodeObject:self.ninePatch
forKey:@"ninePatch"];
[anEncoder encodeObject:self.ninePatchImageCache
forKey:@"ninePatchImageCache"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] alloc] initWithNinePatch:self.ninePatch];
}
#pragma mark Nib
-(void)awakeFromNib {
[super awakeFromNib];
if (!self.ninePatchImageCache) {
self.ninePatchImageCache = [NSMutableDictionary dictionaryWithCapacity:5];
};
}
#pragma mark Cache Management
-(void)flushCachedImages {
NPAssertPropertyNonNil(ninePatchImageCache);
[self.ninePatchImageCache removeAllObjects];
}
#pragma mark Image Access - Utility Accessors
-(UIImage *)imageOfSize:(CGSize)size {
UIImage *imageOfSize = [self cachedImageOfSize:size];
if (!imageOfSize) {
imageOfSize = [self constructImageOfSize:size];
if (imageOfSize) {
[self cacheImage:imageOfSize
ofSize:size];
}
}
return imageOfSize;
}
#pragma mark Cache Access
-(void)cacheImage:(UIImage *)image ofSize:(CGSize)size {
NPParameterAssertNotNilIsKindOfClass(image,UIImage);
NPAssertPropertyNonNil(self.ninePatchImageCache);
return [self.ninePatchImageCache setObject:image
forSize:size];
}
-(UIImage *)cachedImageOfSize:(CGSize)size {
NPAssertPropertyNonNil(ninePatchImageCache);
return [self.ninePatchImageCache objectForSize:size];
}
#pragma mark Image Construction
-(UIImage *)constructImageOfSize:(CGSize)size {
NPAssertPropertyNonNil(ninePatch);
return (!self.ninePatch)?(nil):([self.ninePatch imageOfSize:size]);
}
@end

View file

@ -0,0 +1,56 @@
//
// TUDebugLoggingAssistant.h
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
@interface TUDebugLoggingAssistant : NSObject {
NSString *_sessionIdentifier;
NSMutableSet *_activatedLoggingTags;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) NSString *sessionIdentifier;
@property(nonatomic, retain, readonly) NSMutableSet *activatedLoggingTags;
// Init + Dealloc
-(id)init;
-(void)dealloc;
// Managing Logging
-(void)startLoggingTag:(NSString *)loggingTag;
-(void)stopLoggingTag:(NSString *)loggingTag;
-(void)startLoggingTags:(NSString *)loggingTag,...;
-(void)stopLoggingTags:(NSString *)loggingTag,...;
-(void)startLoggingTagsFromArray:(NSArray *)loggingTags;
-(void)stopLoggingTagsFromArray:(NSArray *)loggingTags;
// Formatting
-(NSString *)formattedImageLogFilenameForTimestamp:(NSTimeInterval)timestamp specifiedFileName:(NSString *)specifiedFileName;
// Log-Checking
-(BOOL)shouldLogLineWithTag:(NSString *)tag;
// Singleton Access
+(id)shared;
// Managing Logging
+(void)startLoggingTag:(NSString *)loggingTag;
+(void)stopLoggingTag:(NSString *)loggingTag;
+(void)startLoggingTags:(NSString *)loggingTag,...;
+(void)stopLoggingTags:(NSString *)loggingTag,...;
+(void)startLoggingTagsFromArray:(NSArray *)loggingTags;
+(void)stopLoggingTagsFromArray:(NSArray *)loggingTags;
// Formatting
+(NSString *)formattedImageLogFilenameForTimestamp:(NSTimeInterval)timestamp specifiedFileName:(NSString *)specifiedFileName;
// Log-Checking
+(BOOL)shouldLogLineWithTag:(NSString *)tag;
@end

View file

@ -0,0 +1,362 @@
//
// TUDebugLoggingAssistant.m
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import "TUDebugLoggingAssistant.h"
@interface TUDebugLoggingAssistant ()
@property(nonatomic, retain, readwrite) NSString *sessionIdentifier;
@property(nonatomic, retain, readwrite) NSMutableSet *activatedLoggingTags;
@end
@implementation TUDebugLoggingAssistant
#pragma mark Synthesized Properties
@synthesize sessionIdentifier = _sessionIdentifier;
@synthesize activatedLoggingTags = _activatedLoggingTags;
#pragma mark Init + Dealloc
-(id)init {
if (self = [super init]) {
self.activatedLoggingTags = [NSMutableSet set];
NSString *uuidString = @"UUID_ERROR_ENCOUNTERED";
@try {
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
if (uuid) {
@try {
uuidString = ((NSString *) CFUUIDCreateString(kCFAllocatorDefault, uuid));
}
@catch (NSException * e) {
NPLogException(e);
if (uuidString) {
@try {
CFRelease(uuidString);
}
@catch (NSException * ee) {
NPLogException(ee);
}
@finally {
uuidString = @"UUID_ERROR_ENCOUNTERED";
}
}
}
@finally {
@try {
CFRelease(uuid);
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
if (uuidString) {
self.sessionIdentifier = uuidString;
[self.sessionIdentifier release]; // drops retain count back to 1
}
}
}
return self;
}
#pragma mark -
-(void)dealloc {
self.sessionIdentifier = nil;
self.activatedLoggingTags = nil;
[super dealloc];
}
#pragma mark Managing Logging
-(void)startLoggingTag:(NSString *)loggingTag {
NPAOInputLog(loggingTag);
NPParameterAssertNotNilIsKindOfClass(loggingTag,NSString);
NPAssertPropertyNonNil(activatedLoggingTags);
if (loggingTag) {
@try {
[self.activatedLoggingTags addObject:loggingTag];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
-(void)stopLoggingTag:(NSString *)loggingTag {
NPAOInputLog(loggingTag);
NPParameterAssertNotNilIsKindOfClass(loggingTag,NSString);
NPAssertPropertyNonNil(activatedLoggingTags);
if (loggingTag) {
@try {
[self.activatedLoggingTags removeObject:loggingTag];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
-(void)startLoggingTags:(NSString *)loggingTag,... {
id eachObject;
va_list argumentList;
if (loggingTag) {
NSMutableArray *workingArray = [NSMutableArray arrayWithObject:loggingTag];
va_start(argumentList, loggingTag);
@try {
while ((eachObject = va_arg(argumentList, id))) {
@try {
[workingArray addObject:eachObject];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
@try {
va_end(argumentList);
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
if (workingArray) {
[self startLoggingTagsFromArray:workingArray];
}
}
}
}
}
-(void)stopLoggingTags:(NSString *)loggingTag,... {
id eachObject;
va_list argumentList;
if (loggingTag) {
NSMutableArray *workingArray = [NSMutableArray arrayWithObject:loggingTag];
va_start(argumentList, loggingTag);
@try {
while ((eachObject = va_arg(argumentList, id))) {
@try {
[workingArray addObject:eachObject];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
@try {
va_end(argumentList);
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
if (workingArray) {
[self stopLoggingTagsFromArray:workingArray];
}
}
}
}
}
-(void)startLoggingTagsFromArray:(NSArray *)loggingTags {
NPAOInputLog(loggingTags);
NPParameterAssertNotNilIsKindOfClass(loggingTags,NSArray);
NPAssertPropertyNonNil(activatedLoggingTags);
if (loggingTags) {
// N.B.: we're not shooting for speed here
// b/c if you're even instantiating an instance of this
// class it means you're in a debug frenzy and have other
// issues.
//
// So here we break out the for loop and insert objects
// individually so that the asserts in the [self startLoggingTag:tag]
// will get noticed if you're smuggling non-string logging tags in
// by passing them in as part of an array.
//
// No point having type-induced errors in your debugging assistant.
for (NSString *loggingTag in loggingTags) {
[self startLoggingTag:loggingTag];
}
}
}
-(void)stopLoggingTagsFromArray:(NSArray *)loggingTags {
NPAOInputLog(loggingTags);
NPParameterAssertNotNilIsKindOfClass(loggingTags,NSArray);
NPAssertPropertyNonNil(activatedLoggingTags);
if (loggingTags) {
// CF comment in startLoggingTagsFromArray
// for some context here
for (NSString *loggingTag in loggingTags) {
[self stopLoggingTag:loggingTag];
}
}
}
#pragma mark Formatting
-(NSString *)formattedImageLogFilenameForTimestamp:(NSTimeInterval)timestamp specifiedFileName:(NSString *)specifiedFileName {
NPAInputLog(@"formattedImageLogFilenameForTimestamp:'%f' specifiedFileName:'%@'",timestamp,specifiedFileName);
NPParameterAssertNotNilIsKindOfClass(specifiedFileName,NSString);
NPAssertPropertyNonNil(sessionIdentifier);
NSString *outString = nil;
@try {
if (specifiedFileName) {
outString = [NSString stringWithFormat:@"%@_%@_%.0f.png",self.sessionIdentifier,specifiedFileName,timestamp];
} else {
outString = [NSString stringWithFormat:@"%@_%.0f.png",self.sessionIdentifier,timestamp];
}
}
@catch (NSException * e) {
NPLogException(e);
}
NPOOutputLog(outString);
return outString;
}
#pragma mark Log-Checking
-(BOOL)shouldLogLineWithTag:(NSString *)tag {
NPAInputLog(@"shouldLogLineWithTag:'%@'",tag);
NPParameterAssertNotNilIsKindOfClass(tag,NSString);
NPAssertPropertyNonNil(activatedLoggingTags);
BOOL shouldLogLineWithTag = NO;
if (tag) {
@try {
shouldLogLineWithTag = [self.activatedLoggingTags containsObject:tag];
}
@catch (NSException * e) {
NPLogException(e);
shouldLogLineWithTag = NO;
}
}
NPBOutputLog(shouldLogLineWithTag);
return shouldLogLineWithTag;
}
#pragma mark Singleton Access
+(id)shared {
static id shared;
if (!shared) {
shared = [[[self class] alloc] init];
}
NPAssertNilOrIsKindOfClass(shared,TUDebugLoggingAssistant);
return shared;
}
#pragma mark Managing Logging
+(void)startLoggingTag:(NSString *)loggingTag {
[[self shared] startLoggingTag:loggingTag];
}
+(void)stopLoggingTag:(NSString *)loggingTag {
[[self shared] stopLoggingTag:loggingTag];
}
#pragma mark -
+(void)startLoggingTags:(NSString *)loggingTag,... {
id eachObject;
va_list argumentList;
if (loggingTag) {
NSMutableArray *workingArray = [NSMutableArray arrayWithObject:loggingTag];
va_start(argumentList, loggingTag);
@try {
while ((eachObject = va_arg(argumentList, id))) {
@try {
[workingArray addObject:eachObject];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
@try {
va_end(argumentList);
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
if (workingArray) {
[self startLoggingTagsFromArray:workingArray];
}
}
}
}
}
+(void)stopLoggingTags:(NSString *)loggingTag,... {
id eachObject;
va_list argumentList;
if (loggingTag) {
NSMutableArray *workingArray = [NSMutableArray arrayWithObject:loggingTag];
va_start(argumentList, loggingTag);
@try {
while ((eachObject = va_arg(argumentList, id))) {
@try {
[workingArray addObject:eachObject];
}
@catch (NSException * e) {
NPLogException(e);
}
}
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
@try {
va_end(argumentList);
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
if (workingArray) {
[self stopLoggingTagsFromArray:workingArray];
}
}
}
}
}
#pragma mark -
+(void)startLoggingTagsFromArray:(NSArray *)loggingTags {
[[self shared] startLoggingTagsFromArray:loggingTags];
}
+(void)stopLoggingTagsFromArray:(NSArray *)loggingTags {
[[self shared] stopLoggingTagsFromArray:loggingTags];
}
#pragma mark Formatting
+(NSString *)formattedImageLogFilenameForTimestamp:(NSTimeInterval)timestamp specifiedFileName:(NSString *)specifiedFileName {
return [[self shared] formattedImageLogFilenameForTimestamp:timestamp
specifiedFileName:specifiedFileName];
}
#pragma mark Log-Checking
+(BOOL)shouldLogLineWithTag:(NSString *)tag {
return [[self shared] shouldLogLineWithTag:tag];
}
@end

56
NinePatch/TUFullNinePatch.h Executable file
View file

@ -0,0 +1,56 @@
//
// TUFullNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatch.h"
#import "TUNinePatchProtocols.h"
/**
Concrete TUNinePatch instance. Handles NinePatches that stretch horizontally and vertically. Only instantiate directly if you know what you're doing.
*/
@interface TUFullNinePatch : TUNinePatch < TUNinePatch > {
UIImage *_upperEdge;
UIImage *_lowerEdge;
UIImage *_leftEdge;
UIImage *_rightEdge;
UIImage *_upperLeftCorner;
UIImage *_lowerLeftCorner;
UIImage *_upperRightCorner;
UIImage *_lowerRightCorner;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) UIImage *upperEdge;
@property(nonatomic, retain, readonly) UIImage *lowerEdge;
@property(nonatomic, retain, readonly) UIImage *leftEdge;
@property(nonatomic, retain, readonly) UIImage *rightEdge;
@property(nonatomic, retain, readonly) UIImage *upperLeftCorner;
@property(nonatomic, retain, readonly) UIImage *lowerLeftCorner;
@property(nonatomic, retain, readonly) UIImage *upperRightCorner;
@property(nonatomic, retain, readonly) UIImage *lowerRightCorner;
// Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally upperLeftCorner:(UIImage *)upperLeftCorner upperRightCorner:(UIImage *)upperRightCorner lowerLeftCorner:(UIImage *)lowerLeftCorner lowerRightCorner:(UIImage *)lowerRightCorner leftEdge:(UIImage *)leftEdge rightEdge:(UIImage *)rightEdge upperEdge:(UIImage *)upperEdge lowerEdge:(UIImage *)lowerEdge;
-(void)dealloc;
// Sanity-Checking Tools
-(BOOL)checkSizeSanityAgainstOriginalImage:(UIImage *)originalImage;
// TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect;
-(CGFloat)leftEdgeWidth;
-(CGFloat)rightEdgeWidth;
-(CGFloat)upperEdgeHeight;
-(CGFloat)lowerEdgeHeight;
// Image Logging
-(void)logExplodedImage;
@end

318
NinePatch/TUFullNinePatch.m Executable file
View file

@ -0,0 +1,318 @@
//
// TUFullNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "TUFullNinePatch.h"
#import "TUNinePatchProtocols.h"
#import "UIImage-TUNinePatch.h"
@interface TUFullNinePatch ()
// Synthesized Properties
@property(nonatomic, retain, readwrite) UIImage *upperEdge;
@property(nonatomic, retain, readwrite) UIImage *lowerEdge;
@property(nonatomic, retain, readwrite) UIImage *leftEdge;
@property(nonatomic, retain, readwrite) UIImage *rightEdge;
@property(nonatomic, retain, readwrite) UIImage *upperLeftCorner;
@property(nonatomic, retain, readwrite) UIImage *lowerLeftCorner;
@property(nonatomic, retain, readwrite) UIImage *upperRightCorner;
@property(nonatomic, retain, readwrite) UIImage *lowerRightCorner;
@end
@implementation TUFullNinePatch
#pragma mark Synthesized Properties
@synthesize upperEdge = _upperEdge;
@synthesize lowerEdge = _lowerEdge;
@synthesize leftEdge = _leftEdge;
@synthesize rightEdge = _rightEdge;
@synthesize upperLeftCorner = _upperLeftCorner;
@synthesize lowerLeftCorner = _lowerLeftCorner;
@synthesize upperRightCorner = _upperRightCorner;
@synthesize lowerRightCorner = _lowerRightCorner;
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
self.upperEdge = (UIImage *) [coder decodeObjectForKey:@"upperEdge"];
self.lowerEdge = (UIImage *) [coder decodeObjectForKey:@"lowerEdge"];
self.leftEdge = (UIImage *) [coder decodeObjectForKey:@"leftEdge"];
self.rightEdge = (UIImage *) [coder decodeObjectForKey:@"rightEdge"];
self.upperLeftCorner = (UIImage *) [coder decodeObjectForKey:@"upperLeftCorner"];
self.lowerLeftCorner = (UIImage *) [coder decodeObjectForKey:@"lowerLeftCorner"];
self.upperRightCorner = (UIImage *) [coder decodeObjectForKey:@"upperRightCorner"];
self.lowerRightCorner = (UIImage *) [coder decodeObjectForKey:@"lowerRightCorner"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.upperEdge
forKey:@"upperEdge"];
[coder encodeObject:self.lowerEdge
forKey:@"lowerEdge"];
[coder encodeObject:self.leftEdge
forKey:@"leftEdge"];
[coder encodeObject:self.rightEdge
forKey:@"rightEdge"];
[coder encodeObject:self.upperLeftCorner
forKey:@"upperLeftCorner"];
[coder encodeObject:self.lowerLeftCorner
forKey:@"lowerLeftCorner"];
[coder encodeObject:self.upperRightCorner
forKey:@"upperRightCorner"];
[coder encodeObject:self.lowerRightCorner
forKey:@"lowerRightCorner"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithCenter:self.center
contentRegion:self.contentRegion
tileCenterVertically:self.tileCenterVertically
tileCenterHorizontally:self.tileCenterHorizontally
upperLeftCorner:self.upperLeftCorner
upperRightCorner:self.upperRightCorner
lowerLeftCorner:self.lowerLeftCorner
lowerRightCorner:self.lowerRightCorner
leftEdge:self.leftEdge
rightEdge:self.rightEdge
upperEdge:self.upperEdge
lowerEdge:self.lowerEdge];
}
#pragma mark Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally upperLeftCorner:(UIImage *)upperLeftCorner upperRightCorner:(UIImage *)upperRightCorner lowerLeftCorner:(UIImage *)lowerLeftCorner lowerRightCorner:(UIImage *)lowerRightCorner leftEdge:(UIImage *)leftEdge rightEdge:(UIImage *)rightEdge upperEdge:(UIImage *)upperEdge lowerEdge:(UIImage *)lowerEdge {
NPParameterAssertNotNilIsKindOfClass(upperLeftCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerLeftCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(upperRightCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerRightCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(leftEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(rightEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(upperEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerEdge,UIImage);
if (self = [super initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally]) {
self.upperEdge = upperEdge;
self.lowerEdge = lowerEdge;
self.leftEdge = leftEdge;
self.rightEdge = rightEdge;
self.upperLeftCorner = upperLeftCorner;
self.lowerLeftCorner = lowerLeftCorner;
self.upperRightCorner = upperRightCorner;
self.lowerRightCorner = lowerRightCorner;
}
return self;
}
#pragma mark
-(void)dealloc {
self.upperEdge = nil;
self.lowerEdge = nil;
self.leftEdge = nil;
self.rightEdge = nil;
self.upperLeftCorner = nil;
self.lowerLeftCorner = nil;
self.upperRightCorner = nil;
self.lowerRightCorner = nil;
[super dealloc];
}
#pragma mark Sanity-Checking Tools
-(BOOL)checkSizeSanityAgainstOriginalImage:(UIImage *)originalImage {
CGSize os = [originalImage size];
CGFloat ow = os.width;
CGFloat oh = os.height;
CGFloat tr = ([[self upperEdge] size].width + [[self upperLeftCorner] size].width + [[self upperRightCorner] size].width);
CGFloat mr = ([[self center] size].width + [[self leftEdge] size].width + [[self rightEdge] size].width);
CGFloat lr = ([[self lowerEdge] size].width + [[self lowerLeftCorner] size].width + [[self lowerRightCorner] size].width);
BOOL topRow = TUWithinEpsilon(1.0f,ow,tr);
BOOL midRow = TUWithinEpsilon(1.0f,ow,mr);
BOOL lowRow = TUWithinEpsilon(1.0f,ow,lr);
CGFloat lc = ([[self upperLeftCorner] size].height + [[self lowerLeftCorner] size].height + [[self leftEdge] size].height);
CGFloat mc = ([[self center] size].height + [[self upperEdge] size].height + [[self lowerEdge] size].height);
CGFloat rc = ([[self upperRightCorner] size].height + [[self lowerRightCorner] size].height + [[self rightEdge] size].height);
BOOL lCol = TUWithinEpsilon(1.0f,oh,lc);
BOOL mCol = TUWithinEpsilon(1.0f,oh,mc);
BOOL rCol = TUWithinEpsilon(1.0f,oh,rc);
BOOL sizesMatch = TUForceYesOrNo(midRow && topRow && lowRow && mCol && lCol && rCol);
DLog(@"SANITY sizesMatch: '%@.'",TUYesOrNoString(sizesMatch));
DLog(@"SANITY topRow: '%@', midRow:'%@, lowRow:'%@'.", TUYesOrNoString(topRow),TUYesOrNoString(midRow),TUYesOrNoString(lowRow));
DLog(@"SANITY lCol: '%@', mCol:'%@, rCol:'%@'.", TUYesOrNoString(lCol),TUYesOrNoString(mCol),TUYesOrNoString(rCol));
DLog(@"SANITY <ow: '%.1f', tr: '%.1f', mr: '%.1f', lr: '%.1f'>",ow,tr,mr,lr);
DLog(@"SANITY <oh: '%.1f', lc: '%.1f', mc: '%.1f', lc: '%.1f'>",oh,lc,mc,rc);
return sizesMatch;
}
#pragma mark TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect {
NPSelfProperty(center);
NPSelfProperty(leftEdge);
NPSelfProperty(rightEdge);
NPSelfProperty(lowerEdge);
NPSelfProperty(upperEdge);
NPSelfProperty(upperLeftCorner);
NPSelfProperty(upperRightCorner);
NPSelfProperty(lowerLeftCorner);
NPSelfProperty(lowerRightCorner);
CGFloat leftEdgeWidth = [self leftEdgeWidth];
CGFloat rightEdgeWidth = [self rightEdgeWidth];
BOOL hasLeftEdge = (leftEdgeWidth > 0.0f)?(YES):(NO);
BOOL hasRightEdge = (rightEdgeWidth > 0.0f)?(YES):(NO);
CGFloat upperEdgeHeight = [self upperEdgeHeight];
CGFloat lowerEdgeHeight = [self lowerEdgeHeight];
BOOL hasUpperEdge = (upperEdgeHeight > 0.0f)?(YES):(NO);
BOOL hasLowerEdge = (lowerEdgeHeight > 0.0f)?(YES):(NO);
BOOL hasUpperLeftCorner = (hasLeftEdge && hasUpperEdge)?(YES):(NO);
BOOL hasUpperRightCorner = (hasRightEdge && hasUpperEdge)?(YES):(NO);
BOOL hasLowerLeftCorner = (hasLeftEdge && hasLowerEdge)?(YES):(NO);
BOOL hasLowerRightCorner = (hasRightEdge && hasLowerEdge)?(YES):(NO);
CGFloat contentWidth = TUTruncateAtZero(rect.size.width - (leftEdgeWidth + rightEdgeWidth));
CGFloat contentHeight = TUTruncateAtZero(rect.size.height - (upperEdgeHeight + lowerEdgeHeight));
BOOL hasContentWidth = (contentWidth > 0.0f)?(YES):(NO);
BOOL hasContentHeight = (contentWidth > 0.0f)?(YES):(NO);
if (hasContentWidth && hasContentHeight) {
[self.center drawInRect:CGRectMake(CGRectGetMinX(rect) + leftEdgeWidth, CGRectGetMinY(rect) + upperEdgeHeight, contentWidth, contentHeight)];
}
if (hasContentWidth) {
if (hasUpperEdge) {
[self.upperEdge drawInRect:CGRectMake(
CGRectGetMinX(rect) + leftEdgeWidth,
CGRectGetMinY(rect),
contentWidth,
upperEdgeHeight)];
}
if (hasLowerEdge) {
[self.lowerEdge drawInRect:CGRectMake(
CGRectGetMinX(rect) + leftEdgeWidth,
CGRectGetMaxY(rect) - lowerEdgeHeight,
contentWidth,
lowerEdgeHeight)];
}
}
if (hasContentHeight) {
if (hasLeftEdge) {
[self.leftEdge drawInRect:CGRectMake(
CGRectGetMinX(rect),
CGRectGetMinY(rect) + upperEdgeHeight,
leftEdgeWidth,
contentHeight)];
}
if (hasRightEdge) {
[self.rightEdge drawInRect:CGRectMake(
CGRectGetMaxX(rect) - rightEdgeWidth,
CGRectGetMinY(rect) + upperEdgeHeight,
rightEdgeWidth,
contentHeight)];
}
}
if (hasUpperLeftCorner && self.upperLeftCorner) {
[self.upperLeftCorner drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))];
}
if (hasUpperRightCorner && self.upperRightCorner) {
[self.upperRightCorner drawAtPoint:CGPointMake(CGRectGetMaxX(rect) - rightEdgeWidth, CGRectGetMinY(rect))];
}
if (hasLowerLeftCorner && self.lowerLeftCorner) {
[self.lowerLeftCorner drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect) - lowerEdgeHeight)];
}
if (hasLowerRightCorner && self.lowerRightCorner) {
[self.lowerRightCorner drawAtPoint:CGPointMake(CGRectGetMaxX(rect) - rightEdgeWidth, CGRectGetMaxY(rect) - lowerEdgeHeight)];
}
}
#pragma mark -
-(CGFloat)leftEdgeWidth {
return ((self.upperLeftCorner)?
([self.upperLeftCorner size].width):
(((self.lowerLeftCorner)?
([self.lowerLeftCorner size].width):(0.0f))));
}
-(CGFloat)rightEdgeWidth {
return ((self.upperRightCorner)?
([self.upperRightCorner size].width)
:(((self.lowerRightCorner)?
([self.lowerRightCorner size].width):(0.0f))));
}
-(CGFloat)upperEdgeHeight {
return ((self.upperLeftCorner)?
([self.upperLeftCorner size].height)
:(((self.upperRightCorner)?
([self.upperRightCorner size].height):(0.0f))));
}
-(CGFloat)lowerEdgeHeight {
return ((self.lowerLeftCorner)?
([self.lowerLeftCorner size].height)
:(((self.lowerRightCorner)?
([self.lowerRightCorner size].height):(0.0f))));
}
#pragma mark Customized Description Overrides
-(NSString *)descriptionPostfix {
return [NSString stringWithFormat:@"%@, self.upperEdge:<'%@'>, self.lowerEdge:<'%@'>, self.leftEdge:<'%@'>, self.rightEdge:<'%@'>, self.upperLeftCorner:<'%@'>, self.lowerLeftCorner:<'%@'>, self.upperRightCorner:<'%@'>, self.lowerRightCorner:<'%@'>",
[super descriptionPostfix],
self.upperEdge,
self.lowerEdge,
self.leftEdge,
self.rightEdge,
self.upperLeftCorner,
self.lowerLeftCorner,
self.upperRightCorner,
self.lowerRightCorner];
}
#pragma mark Image Logging
-(void)logExplodedImage {
CGFloat centerWidth = ((self.center)?(self.center.size.width):(0.0f));
CGFloat centerHeight = ((self.center)?(self.center.size.height):(0.0f));
CGSize mySize = CGSizeMake(
4.0f + (centerWidth + ([self leftEdgeWidth]) + ([self rightEdgeWidth])),
4.0f + (centerHeight + ([self upperEdgeHeight]) + ([self lowerEdgeHeight]))
);
UIGraphicsBeginImageContext(mySize);
[self.center drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 2.0f + [self upperEdgeHeight])];
[self.upperLeftCorner drawAtPoint:CGPointMake(0.0f, 0.0f)];
[self.leftEdge drawAtPoint:CGPointMake(0.0f, [self upperEdgeHeight] + 2.0f)];
[self.lowerLeftCorner drawAtPoint:CGPointMake(0.0f, [self upperEdgeHeight] + 4.0f + centerHeight)];
[self.upperEdge drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 0.0f)];
[self.upperRightCorner drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 0.0f)];
[self.rightEdge drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 2.0f + [self upperEdgeHeight])];
[self.lowerRightCorner drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 4.0f + [self upperEdgeHeight] + centerHeight)];
[self.lowerEdge drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 4.0f + [self upperEdgeHeight] + centerHeight)];
IMLog(UIGraphicsGetImageFromCurrentImageContext(), @"explodedNinePatchImage");
UIGraphicsEndImageContext();
}
@end

View file

@ -0,0 +1,37 @@
//
// TUHorizontalNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatch.h"
#import "TUNinePatchProtocols.h"
/**
Concrete TUNinePatch instance. Handles NinePatches that stretch horizontally but not vertically. Only instantiate directly if you know what you're doing.
*/
@interface TUHorizontalNinePatch : TUNinePatch < TUNinePatch > {
UIImage *_leftEdge;
UIImage *_rightEdge;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) UIImage *leftEdge;
@property(nonatomic, retain, readonly) UIImage *rightEdge;
// Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally leftEdge:(UIImage *)leftEdge rightEdge:(UIImage *)rightEdge;
-(void)dealloc;
// TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect;
-(BOOL)stretchesVertically;
-(CGSize)sizeForContentOfSize:(CGSize)contentSize;
-(CGFloat)leftEdgeWidth;
-(CGFloat)rightEdgeWidth;
@end

124
NinePatch/TUHorizontalNinePatch.m Executable file
View file

@ -0,0 +1,124 @@
//
// TUHorizontalNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "TUHorizontalNinePatch.h"
@interface TUHorizontalNinePatch ()
// Synthesized Properties
@property(nonatomic, retain, readwrite) UIImage *leftEdge;
@property(nonatomic, retain, readwrite) UIImage *rightEdge;
@end
@implementation TUHorizontalNinePatch
#pragma mark Synthesized Properties
@synthesize leftEdge = _leftEdge;
@synthesize rightEdge = _rightEdge;
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
self.leftEdge = (UIImage *)[coder decodeObjectForKey:@"leftEdge"];
self.rightEdge = (UIImage *)[coder decodeObjectForKey:@"rightEdge"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.leftEdge
forKey:@"leftEdge"];
[coder encodeObject:self.rightEdge
forKey:@"rightEdge"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithCenter:self.center
contentRegion:self.contentRegion
tileCenterVertically:self.tileCenterVertically
tileCenterHorizontally:self.tileCenterHorizontally
leftEdge:self.leftEdge
rightEdge:self.rightEdge];
}
#pragma mark Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally leftEdge:(UIImage *)leftEdge rightEdge:(UIImage *)rightEdge {
NPParameterAssertNotNilIsKindOfClass(leftEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(rightEdge,UIImage);
if (self = [super initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally]) {
self.leftEdge = leftEdge;
self.rightEdge = rightEdge;
}
return self;
}
#pragma mark -
-(void)dealloc {
self.leftEdge = nil;
self.rightEdge = nil;
[super dealloc];
}
#pragma mark TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect {
CGFloat height = [self minimumHeight];
[self.center drawInRect:CGRectMake(CGRectGetMinX(rect) + [self leftEdgeWidth], CGRectGetMinY(rect), CGRectGetWidth(rect) - ([self leftEdgeWidth] + [self rightEdgeWidth]), height)];
if (self.leftEdge) {
[self.leftEdge drawAtPoint:CGPointMake(CGRectGetMinX(rect),CGRectGetMinY(rect))];
}
if (self.rightEdge) {
[self.rightEdge drawAtPoint:CGPointMake(CGRectGetMaxX(rect) - [self rightEdgeWidth], CGRectGetMinY(rect))];
}
}
#pragma mark -
-(BOOL)stretchesVertically {
return NO;
}
#pragma mark -
-(CGSize)sizeForContentOfSize:(CGSize)contentSize {
CGSize outSize = [super sizeForContentOfSize:contentSize];
outSize.height = [self minimumHeight];
return outSize;
}
#pragma mark -
-(CGFloat)leftEdgeWidth {
CGFloat leftEdgeWidth = 0.0f;
if (self.leftEdge) {
leftEdgeWidth = [self.leftEdge size].width;
}
return leftEdgeWidth;
}
-(CGFloat)rightEdgeWidth {
CGFloat rightEdgeWidth = 0.0f;
if (self.leftEdge) {
rightEdgeWidth = [self.rightEdge size].width;
}
return rightEdgeWidth;
}
#pragma mark Customized Description Overrides
-(NSString *)descriptionPostfix {
return [NSString stringWithFormat:@"%@, self.leftEdge:<'%@'>, self.rightEdge:<'%@'>",
[super descriptionPostfix],
self.leftEdge,
self.rightEdge];
}
@end

125
NinePatch/TUNinePatch.h Executable file
View file

@ -0,0 +1,125 @@
//
// TUNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatchProtocols.h"
/**
Abstract base class for concrete NinePatches; this is the public interface into the TUNinePatch class cluster. Note particularly that TUNinePatch itself doesn't actually implement the TUNinePatch protocol, but its convenience methods promise to supply objects that do implement TUNinePatch. You should really only be using the classlevel convenience methods on this class unless you know what you're doing. If a method isn't documented it's probably not really for public use yet.
*/
@interface TUNinePatch : NSObject < NSCoding, NSCopying > {
UIImage *_center;
CGRect _contentRegion;
BOOL _tileCenterVertically;
BOOL _tileCenterHorizontally;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) UIImage *center;
@property(nonatomic, assign, readonly) CGRect contentRegion;
@property(nonatomic, assign, readonly) BOOL tileCenterVertically;
@property(nonatomic, assign, readonly) BOOL tileCenterHorizontally;
// NSCoding
-(id)initWithCoder:(NSCoder *)coder;
-(void)encodeWithCoder:(NSCoder *)coder;
// NSCopying
-(id)copyWithZone:(NSZone *)zone;
// Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion;
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally;
-(void)dealloc;
// Convenience Constructors
/**
This parses ninePatchImage and instantiates an instance of the appropriate TUNinePatch subclass.
@param ninePatchImage A non-nil UIImage object containing the contents of a .9.png file (eg: it still contains the 1px border containing the scaling information).
@returns An autoreleased object implementing the TUNinePatch protocol, loaded with the contents of ninePatchImage. Can be nil if errors encountered.
*/
+(id < TUNinePatch >)ninePatchWithNinePatchImage:(UIImage *)ninePatchImage;
/**
Calls through to ninePatchWithImage:stretchableRegion:contentRegion:tileCenterVertically:tileCenterHorizontally with contentRegion=CGRectZero and NO on the tiling params. Will probably get made private or protected soon.
*/
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion;
/**
Creates a NinePatch using the passed-in image and the passed-in scaling information. This method may go protected soon, leaving only the ninePatchWithNinePatchImage: as a public convenience (possibly with the addition of ninePatchNamed: method as well). The argument for goign protected or private is that if this library winds up expanding discontinuous stretchable regions (as is done on Android) then there would be a separate interface for passing in 4 stretchable regions, making the public interface cmoplicated and "multiple ways in".
@param image A non-nil UIImage object that contains the displayable content. This is contents of .9.png file AFTER removing the 1px border.
@param stretchableRegion Rect specifying the bounds of the central stretchable region. In the .9.png this is specified on the left and top margins.
@param contentRegion Rect specifying the bounds of the content region, EG the box into which associated content might fit. In the .9.png this is specified on the bottom and right margins.
@param tileCenterVertically (Currently unsupported) is intended to specify whether or not the center scales by resizing or scales by tiling. Not fully supported at this time, only use if you know what you're doing.
@param tileCenterHorizontally (Currently unsupported) is intended to specify whether or not the center scales by resizing or scales by tiling. Not fully supported at this time, only use if you know what you're doing.
@returns An object implementing the TUNinePatch protocol. Can be nil if problems were encountered.
*/
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally;
// Bundle Loading
/**
Creates a ninepatch in two steps: it takes filename, and tries to load @"filename.9.png" from the main bundle. If that loads it then attempts to construct a NinePatch from that image file's contents. Differs from UIImage's analogous method in that no caching is done.
@param filename A non-nil NSString containing the filename of the source image but NOT including ".9.png".
@returns An object implementing the TUNinePatch protocol. Can be nil if problems encountered.
*/
+(id < TUNinePatch >)ninePatchNamed:(NSString *)filename;
// Nine Patch Image Manipulation - High Level
+(CGRect)rectFromHorizontalRange:(NSRange)horizontalRange verticalRange:(NSRange)verticalRange;
+(CGRect)stretchableRegionOfNinePatchImage:(UIImage *)ninePatchImage;
+(CGRect)contentRegionOfNinePatchImage:(UIImage *)ninePatchImage;
+(BOOL)shouldTileCenterHorizontallyForNinePatchImage:(UIImage *)ninePatchImage;
+(BOOL)shouldTileCenterVerticallyForNinePatchImage:(UIImage *)ninePatchImage;
// Drawing Utility
-(void)drawInRect:(CGRect)rect;
// Diagnostic Utilities
-(UIImage *)upperEdge;
-(UIImage *)lowerEdge;
-(UIImage *)leftEdge;
-(UIImage *)rightEdge;
-(UIImage *)upperLeftCorner;
-(UIImage *)lowerLeftCorner;
-(UIImage *)upperRightCorner;
-(UIImage *)lowerRightCorner;
// TUNinePatch Protocol Methods - Drawing
-(void)inContext:(CGContextRef)context drawAtPoint:(CGPoint)point forContentOfSize:(CGSize)contentSize;
-(void)inContext:(CGContextRef)context drawCenteredInRect:(CGRect)rect forContentOfSize:(CGSize)contentSize;
-(void)inContext:(CGContextRef)context drawInRect:(CGRect)rect;
// TUNinePatch Protocol Methods - Image Construction
-(UIImage *)imageOfSize:(CGSize)size;
// TUNinePatch Protocol Methods - Sizing
-(BOOL)stretchesHorizontally;
-(BOOL)stretchesVertically;
-(CGFloat)minimumWidth;
-(CGFloat)minimumHeight;
-(CGSize)minimumSize;
-(CGSize)sizeForContentOfSize:(CGSize)contentSize;
-(CGPoint)upperLeftCornerForContentWhenDrawnAtPoint:(CGPoint)point;
// TUNinePatch Protocol Methods - Geometry
-(CGFloat)leftEdgeWidth;
-(CGFloat)rightEdgeWidth;
-(CGFloat)upperEdgeHeight;
-(CGFloat)lowerEdgeHeight;
// Customized Description
-(NSString *)description;
-(NSString *)descriptionPostfix;
@end

514
NinePatch/TUNinePatch.m Executable file
View file

@ -0,0 +1,514 @@
//
// TUNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "TUNinePatch.h"
#import "TUVerticalNinePatch.h"
#import "TUHorizontalNinePatch.h"
#import "TUFullNinePatch.h"
#import "UIImage-TUNinePatch.h"
@interface TUNinePatch ()
@property(nonatomic, retain, readwrite) UIImage *center;
@property(nonatomic, assign, readwrite) CGRect contentRegion;
@property(nonatomic, assign, readwrite) BOOL tileCenterVertically;
@property(nonatomic, assign, readwrite) BOOL tileCenterHorizontally;
@end
@implementation TUNinePatch
#pragma mark Synthesized Properties
@synthesize center = _center;
@synthesize contentRegion = _contentRegion;
@synthesize tileCenterVertically = _tileCenterVertically;
@synthesize tileCenterHorizontally = _tileCenterHorizontally;
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)coder {
NPAOInputLog(coder);
if (self = [super init]) {
self.center = (UIImage *)[coder decodeObjectForKey:@"center"];
self.contentRegion = [coder decodeCGRectForKey:@"contentRegion"];
self.tileCenterVertically = [coder decodeBoolForKey:@"tileCenterVertically"];
self.tileCenterHorizontally = [coder decodeBoolForKey:@"tileCenterHorizontally"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
NPAOInputLog(coder);
[coder encodeObject:self.center
forKey:@"center"];
[coder encodeCGRect:self.contentRegion
forKey:@"contentRegion"];
[coder encodeBool:self.tileCenterVertically
forKey:@"tileCenterVertically"];
[coder encodeBool:self.tileCenterHorizontally
forKey:@"tileCenterHorizontally"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithCenter:self.center
contentRegion:self.contentRegion
tileCenterVertically:self.tileCenterVertically
tileCenterHorizontally:self.tileCenterHorizontally];
}
#pragma mark Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion {
return [self initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:NO
tileCenterHorizontally:NO];
}
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally {
NPAInputLog(@"[%@:<0x%x> initWithCenter:%@ contentRegion:%@ tileCenterVertically:%d tileCenterHorizontally:%d]", [self class], ((NSUInteger) self), center, NSStringFromCGRect(contentRegion), tileCenterVertically, tileCenterHorizontally);
NPParameterAssertNotNilIsKindOfClass(center, UIImage);
if (self = [super init]) {
self.center = center;
self.contentRegion = contentRegion;
self.tileCenterVertically = tileCenterVertically;
self.tileCenterHorizontally = tileCenterHorizontally;
}
return self;
}
#pragma mark -
-(void)dealloc {
self.center = nil;
[super dealloc];
}
#pragma mark Convenience Constructors
+(id < TUNinePatch >)ninePatchWithNinePatchImage:(UIImage *)ninePatchImage {
NPAInputLog(@"ninePatchWithNinePatchImage:'%@'",ninePatchImage);
id < TUNinePatch > outPatch = nil;
if (ninePatchImage) {
@try {
outPatch = [self ninePatchWithImage:[ninePatchImage imageAsNinePatchImage]
stretchableRegion:[self stretchableRegionOfNinePatchImage:ninePatchImage]
contentRegion:[self contentRegionOfNinePatchImage:ninePatchImage]
tileCenterVertically:[self shouldTileCenterVerticallyForNinePatchImage:ninePatchImage]
tileCenterHorizontally:[self shouldTileCenterHorizontallyForNinePatchImage:ninePatchImage]];
}
@catch (NSException * e) {
NPLogException(e);
outPatch = nil;
}
}
NPAssertNilOrConformsToProtocol(outPatch,TUNinePatch);
NPOOutputLog(outPatch);
return outPatch;
}
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"ninePatchWithImage:'%@' stretchableRegion:'%@'",image,NSStringFromCGRect(stretchableRegion));
NPParameterAssertNotNilIsKindOfClass(image,UIImage);
return [self ninePatchWithImage:image
stretchableRegion:stretchableRegion
contentRegion:CGRectZero
tileCenterVertically:NO
tileCenterHorizontally:NO];
}
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally {
NPAInputLog(@"ninePatchWithImage:'%@' stretchableRegion:'%@' contentRegion:'%@' tileCenterVertically:'%@' tileCenterHorizontally:'%@'",image,NSStringFromCGRect(stretchableRegion),NSStringFromCGRect(contentRegion),TUYesOrNoString(tileCenterVertically),TUYesOrNoString(tileCenterHorizontally));
NPParameterAssertNotNilIsKindOfClass(image,UIImage);
NPParameterAssert(stretchableRegion.origin.x >= 0.0f);
NPParameterAssert(stretchableRegion.origin.y >= 0.0f);
NPParameterAssert([image size].width >= stretchableRegion.origin.x + stretchableRegion.size.width);
NPParameterAssert([image size].height >= stretchableRegion.origin.y + stretchableRegion.size.height);
id < TUNinePatch > ninePatch = nil;
if (image) {
CGFloat imageWidth = [image size].width;
CGFloat imageHeight = [image size].height;
CGRect fixedStretchableRegion = stretchableRegion;
CGFloat stretchableRegionMinX = CGRectGetMinX(fixedStretchableRegion);
CGFloat stretchableRegionMinY = CGRectGetMinY(fixedStretchableRegion);
CGFloat stretchableRegionMaxX = CGRectGetMaxX(fixedStretchableRegion);
CGFloat stretchableRegionMaxY = CGRectGetMaxY(fixedStretchableRegion);
BOOL stretchesOnLeft = (stretchableRegionMinX > 0.0f)?(YES):(NO);
BOOL stretchesOnRight = (stretchableRegionMaxX < imageWidth)?(YES):(NO);
BOOL stretchesOnTop = (stretchableRegionMinY > 0.0f)?(YES):(NO);
BOOL stretchesOnBottom = (stretchableRegionMaxY < imageHeight)?(YES):(NO);
BOOL stretchesHorizontally = (stretchesOnLeft || stretchesOnRight)?(YES):(NO);
BOOL stretchesVertically = (stretchesOnTop || stretchesOnBottom)?(YES):(NO);
if (stretchesVertically && stretchesHorizontally) {
LLog(@"...the specified stretchable region stretches horizontally and vertically.");
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
UIImage *upperLeftCorner = [image extractUpperLeftCornerForStretchableRegion:fixedStretchableRegion];
UIImage *upperRightCorner = [image extractUpperRightCornerForStretchableRegion:fixedStretchableRegion];
UIImage *lowerLeftCorner = [image extractLowerLeftCornerForStretchableRegion:fixedStretchableRegion];
UIImage *lowerRightCorner = [image extractLowerRightCornerForStretchableRegion:fixedStretchableRegion];
UIImage *leftEdge = [image extractLeftEdgeForStretchableRegion:fixedStretchableRegion];
UIImage *rightEdge = [image extractRightEdgeForStretchableRegion:fixedStretchableRegion];
UIImage *lowerEdge = [image extractLowerEdgeForStretchableRegion:fixedStretchableRegion];
UIImage *upperEdge = [image extractUpperEdgeForStretchableRegion:fixedStretchableRegion];
// Mega-Block of size sanity checking
// Given that the only major bug encountered while developing this library
// proved to be a difficult-to-track-down source of off-by-one errors in
// the sizes of the slices, you can understand the paranoia here.
//
// Just remember to build with the assertion-checking off.
NPAssertCorrectSubimageWidthDecomposition(image, upperLeftCorner, upperEdge, upperRightCorner);
NPAssertCorrectSubimageWidthDecomposition(image, leftEdge, upperEdge, rightEdge);
NPAssertCorrectSubimageWidthDecomposition(image, lowerLeftCorner, lowerEdge, lowerRightCorner);
NPAssertCorrectSubimageHeightDecomposition(image, upperLeftCorner, leftEdge, lowerLeftCorner);
NPAssertCorrectSubimageHeightDecomposition(image, upperEdge, center, lowerEdge);
NPAssertCorrectSubimageHeightDecomposition(image, upperRightCorner, rightEdge, lowerRightCorner);
NPAssertWithinOne(([upperLeftCorner size].height), ([upperRightCorner size].height));
NPAssertWithinOne(([upperLeftCorner size].height), ([upperEdge size].height));
NPAssertWithinOne(([upperEdge size].height), ([upperRightCorner size].height));
NPAssertWithinOne(([leftEdge size].height), ([center size].height));
NPAssertWithinOne(([center size].height), ([rightEdge size].height));
NPAssertWithinOne(([rightEdge size].height), ([leftEdge size].height));
NPAssertWithinOne(([lowerLeftCorner size].height), ([lowerRightCorner size].height));
NPAssertWithinOne(([lowerRightCorner size].height), ([lowerEdge size].height));
NPAssertWithinOne(([lowerEdge size].height), ([lowerLeftCorner size].height));
NPAssertWithinOne(([upperLeftCorner size].width), ([leftEdge size].width));
NPAssertWithinOne(([leftEdge size].width), ([lowerLeftCorner size].width));
NPAssertWithinOne(([upperLeftCorner size].width), ([lowerLeftCorner size].width));
NPAssertWithinOne(([upperEdge size].width), ([center size].width));
NPAssertWithinOne(([center size].width), ([lowerEdge size].width));
NPAssertWithinOne(([upperEdge size].width), ([lowerEdge size].width));
NPAssertWithinOne(([upperRightCorner size].width), ([rightEdge size].width));
NPAssertWithinOne(([rightEdge size].width), ([lowerRightCorner size].width));
NPAssertWithinOne(([lowerRightCorner size].width), ([upperRightCorner size].width));
ninePatch = [[[TUFullNinePatch alloc] initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally
upperLeftCorner:upperLeftCorner
upperRightCorner:upperRightCorner
lowerLeftCorner:lowerLeftCorner
lowerRightCorner:lowerRightCorner
leftEdge:leftEdge
rightEdge:rightEdge
upperEdge:upperEdge
lowerEdge:lowerEdge] autorelease];
} else if (stretchesVertically) {
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
UIImage *upperEdge = [image extractUpperEdgeForStretchableRegion:fixedStretchableRegion];
UIImage *lowerEdge = [image extractLowerEdgeForStretchableRegion:fixedStretchableRegion];
NPAssertCorrectSubimageHeightDecomposition(image,center,upperEdge,lowerEdge);
NPAssertWithinOne(([center size].width),([upperEdge size].width));
NPAssertWithinOne(([lowerEdge size].width),([upperEdge size].width));
NPAssertWithinOne(([center size].width),([lowerEdge size].width));
ninePatch = [[[TUVerticalNinePatch alloc] initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally
upperEdge:upperEdge
lowerEdge:lowerEdge] autorelease];
} else if (stretchesHorizontally) {
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
UIImage *leftEdge = [image extractLeftEdgeForStretchableRegion:fixedStretchableRegion];
UIImage *rightEdge = [image extractRightEdgeForStretchableRegion:fixedStretchableRegion];
NPAssertCorrectSubimageWidthDecomposition(image, leftEdge, center, rightEdge);
NPAssertWithinOne(([center size].height),([leftEdge size].height));
NPAssertWithinOne(([center size].height),([rightEdge size].height));
NPAssertWithinOne(([leftEdge size].height),([rightEdge size].height));
ninePatch = [[[TUHorizontalNinePatch alloc] initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally
leftEdge:leftEdge
rightEdge:rightEdge] autorelease];
} else {
ninePatch = [[[self alloc] initWithCenter:image
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally] autorelease];
}
}
NPAssertNilOrConformsToProtocol(ninePatch,TUNinePatch);
NPOOutputLog(ninePatch);
return ninePatch;
}
#pragma mark Bundle Loading
+(id < TUNinePatch >)ninePatchNamed:(NSString *)filename {
NPParameterAssertNotNilIsKindOfClass(filename,NSString);
id < TUNinePatch > outPatch = nil;
if (filename) {
NSBundle *mainBundle = [NSBundle mainBundle];
if (mainBundle) {
NSString *filePath = [mainBundle pathForResource:[NSString stringWithFormat:@"%@.9",filename]
ofType:@"png"];
if (filePath) {
UIImage *ninepatch = [[UIImage alloc] initWithContentsOfFile:filePath];
if (ninepatch) {
@try {
outPatch = [self ninePatchWithNinePatchImage:ninepatch];
}
@catch (NSException * e) {
NPLogException(e);
outPatch = nil;
}
@finally {
[ninepatch release];
}
}
}
}
}
NPAssertNilOrConformsToProtocol(outPatch,TUNinePatch);
NPOOutputLog(outPatch);
return outPatch;
}
#pragma mark Nine Patch Image Manipulation - High Level
+(CGRect)rectFromHorizontalRange:(NSRange)horizontalRange verticalRange:(NSRange)verticalRange {
NPAInputLog(@"rectFromHorizontalRange:'%@' verticalRange:'%@'",NSStringFromRange(horizontalRange),NSStringFromRange(verticalRange));
CGFloat minX = (TUIsNotFoundRange(horizontalRange))?(0.0f):((CGFloat) horizontalRange.location);
CGFloat width = (TUIsNotFoundRange(horizontalRange))?(0.0f):((CGFloat) horizontalRange.length);
CGFloat minY = (TUIsNotFoundRange(verticalRange)?(0.0f):((CGFloat) verticalRange.location));
CGFloat height = (TUIsNotFoundRange(verticalRange)?(0.0f):((CGFloat) verticalRange.length));
CGRect outRect = CGRectMake(minX,minY,width,height);
NPCGROutputLog(outRect);
return outRect;
}
+(CGRect)stretchableRegionOfNinePatchImage:(UIImage *)ninePatchImage {
NPAInputLog(@"stretchableRegionOfNinePatchImage:'%@'",ninePatchImage);
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
CGRect outRect = CGRectZero;
if (ninePatchImage) {
outRect = [self rectFromHorizontalRange:[ninePatchImage blackPixelRangeInUpperStrip]
verticalRange:[ninePatchImage blackPixelRangeInLeftStrip]];
}
NPCGROutputLog(outRect);
return outRect;
}
+(CGRect)contentRegionOfNinePatchImage:(UIImage *)ninePatchImage {
NPAInputLog(@"contentRegionOfNinePatchImage:'%@'",ninePatchImage);
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
CGRect outRect = CGRectZero;
if (ninePatchImage) {
outRect = [self rectFromHorizontalRange:[ninePatchImage blackPixelRangeInLowerStrip]
verticalRange:[ninePatchImage blackPixelRangeInRightStrip]];
}
NPCGROutputLog(outRect);
return outRect;
}
+(BOOL)shouldTileCenterHorizontallyForNinePatchImage:(UIImage *)ninePatchImage {
NPAInputLog(@"shouldTileCenterHorizontallyForNinePatchImage:'%@'",ninePatchImage);
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
BOOL shouldTileCenterHorizontallyForNinePatchImage = NO;
if (ninePatchImage) {
shouldTileCenterHorizontallyForNinePatchImage = [ninePatchImage upperLeftCornerIsBlackPixel];
}
NPBOutputLog(shouldTileCenterHorizontallyForNinePatchImage);
return shouldTileCenterHorizontallyForNinePatchImage;
}
+(BOOL)shouldTileCenterVerticallyForNinePatchImage:(UIImage *)ninePatchImage {
NPAInputLog(@"shouldTileCenterHorizontallyForNinePatchImage:'%@'",ninePatchImage);
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
BOOL shouldTileCenterVerticallyForNinePatchImage = NO;
if (ninePatchImage) {
shouldTileCenterVerticallyForNinePatchImage = [ninePatchImage lowerLeftCornerIsBlackPixel];
}
NPBOutputLog(shouldTileCenterVerticallyForNinePatchImage);
return shouldTileCenterVerticallyForNinePatchImage;
}
#pragma mark Drawing Utility
-(void)drawInRect:(CGRect)rect {
if (self.center) {
if (self.tileCenterHorizontally && self.tileCenterVertically) {
[self.center drawAsPatternInRect:rect];
} else {
// NB: this behavior is not 100% accurate
// in that it only works right for tiling on and off
// half-tiling has to wait
[self.center drawInRect:rect];
}
}
}
#pragma mark Diagnostic Utilities
-(UIImage *)upperEdge {
return nil;
}
-(UIImage *)lowerEdge {
return nil;
}
-(UIImage *)leftEdge {
return nil;
}
-(UIImage *)rightEdge {
return nil;
}
-(UIImage *)upperLeftCorner {
return nil;
}
-(UIImage *)lowerLeftCorner {
return nil;
}
-(UIImage *)upperRightCorner {
return nil;
}
-(UIImage *)lowerRightCorner {
return nil;
}
#pragma mark TUNinePatch Protocol Methods - Drawing
-(void)inContext:(CGContextRef)context drawAtPoint:(CGPoint)point forContentOfSize:(CGSize)contentSize {
NPParameterAssert(context != nil);
NPAInputLog(@"inContext:'%@' drawAtPoint:'%@' forContentOfSize:'%@'",context,NSStringFromCGPoint(point),NSStringFromCGSize(contentSize));
CGSize size = [self sizeForContentOfSize:contentSize];
[self inContext:context
drawInRect:CGRectMake(point.x, point.y, size.width, size.height)];
}
-(void)inContext:(CGContextRef)context drawCenteredInRect:(CGRect)rect forContentOfSize:(CGSize)contentSize {
NPParameterAssert(context != nil);
NPAInputLog(@"inContext:'%@' drawCenteredInRect:'%@' forContentOfSize:'%@'",context,NSStringFromCGRect(rect),NSStringFromCGSize(contentSize));
CGSize size = [self sizeForContentOfSize:contentSize];
CGFloat xStart = floorf((CGRectGetWidth(rect) - size.width) * 0.5f);
CGFloat yStart = floorf((CGRectGetHeight(rect) - size.height) * 0.5f);
[self inContext:context
drawInRect:CGRectMake(xStart, yStart, size.width, size.height)];
}
-(void)inContext:(CGContextRef)context drawInRect:(CGRect)rect {
if (context) {
CGContextSaveGState(context);
CGContextBeginTransparencyLayer(context, nil);
@try {
[self drawInRect:rect];
}
@catch (NSException * e) {
NPLogException(e);
}
@finally {
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);
}
}
}
#pragma mark TUNinePatch Protocol Methods - Image Construction
-(UIImage *)imageOfSize:(CGSize)size {
UIImage *image = nil;
UIGraphicsBeginImageContext(size);
[self drawInRect:CGRectMake(0.0f,0.0f,size.width,size.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
#pragma mark TUNinePatch Protocol Methods - Sizing
-(BOOL)stretchesHorizontally {
return YES;
}
-(BOOL)stretchesVertically {
return YES;
}
#pragma mark -
-(CGFloat)minimumWidth {
CGFloat minimumWidth = 0.0f;
if (self.center) {
minimumWidth = [self.center size].width + self.rightEdgeWidth + self.leftEdgeWidth;
}
return minimumWidth;
}
-(CGFloat)minimumHeight {
CGFloat minimumHeight = 0.0f;
if (self.center) {
minimumHeight = [self.center size].height + self.upperEdgeHeight + self.lowerEdgeHeight;
}
return minimumHeight;
}
-(CGSize)minimumSize {
return CGSizeMake([self minimumWidth], [self minimumHeight]);
}
-(CGSize)sizeForContentOfSize:(CGSize)contentSize {
CGSize outSize = [self minimumSize];
CGFloat contentRegionWidth = CGRectGetWidth(self.contentRegion);
CGFloat contentRegionHeight = CGRectGetHeight(self.contentRegion);
if ((contentRegionWidth > 0.0f) || (contentRegionHeight > 0.0f)) {
// WE HAVE CONTENT REGION
outSize.width += (contentSize.width > contentRegionWidth)?(contentSize.width - contentRegionWidth):(0.0f);
outSize.height += (contentSize.height > contentRegionHeight)?(contentSize.height - contentRegionHeight):(0.0f);
} else {
// WE ONLY NEED A SIMPLE "WHICH IS BIGGER?" CHECK
outSize.width = (contentSize.width > outSize.width)?(contentSize.width):(outSize.width);
outSize.height = (contentSize.height > outSize.height)?(contentSize.height):(outSize.height);
}
return outSize;
}
-(CGPoint)upperLeftCornerForContentWhenDrawnAtPoint:(CGPoint)point {
return CGPointMake(point.x + CGRectGetMinX(self.contentRegion), point.y + CGRectGetMinY(self.contentRegion));
}
#pragma mark TUNinePatch Protocol Methods - Geometry
-(CGFloat)leftEdgeWidth {
return 0.0f;
}
-(CGFloat)rightEdgeWidth {
return 0.0f;
}
-(CGFloat)upperEdgeHeight {
return 0.0f;
}
-(CGFloat)lowerEdgeHeight {
return 0.0f;
}
#pragma mark Customized Description
-(NSString *)description {
return [NSString stringWithFormat:@"<%@>:( %@ )",[super description],[self descriptionPostfix]];
}
-(NSString *)descriptionPostfix {
return [NSString stringWithFormat:@"center:<'%@'>, contentRegion:<'%@'>", self.center, NSStringFromCGRect(self.contentRegion)];
}
@end

99
NinePatch/TUNinePatchCache.h Executable file
View file

@ -0,0 +1,99 @@
//
// TUNinePatchCache.h
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TUNinePatchProtocols.h"
@class TUCachingNinePatch;
/**
This class is included to make it easy to work with NinePatches if (1) all you want are static images (you don't care much about drawing into CGContextRefs) and (2) . Its semantics are probably non-optimal but are very straightforward: it caches every single request you make to it (both NinePatches and the rendered images). If you're only generating a handful of images and/or you're not super memory-constrained you should probably use this class. It has functionality for flushing the cache with various levels of granularity if you need such functionality.
One thing that's maybe not so obvious is that the methods on this class span two levels of abstraction and caching. Briefly:
- an instance of TUCachingNinePatch has a ninePatch property (that is a TUNinePatch-implementing object)
- TUCachingNinePatch caches all images it generates
- TUNinePatchCache generates and caches instance of TUCachingNinePatch (which in turn cache images)
Where the danger zone emerges is ninePatchNamed: this constructs a TUCachingNinePatch (which as part of its construction constructs an object implementing TUNinePatch), caches the TUCachingNinePatch instance, and returns that instance's ninePatch property (which is what actually implements the TUNinePatch protocol). This is in fact the behavior we wanted when we made this library, but it is a little subtle.
*/
@interface TUNinePatchCache : NSObject {
NSMutableDictionary *_ninePatchCache;
}
// Synthesized Properties
/**
This is where the NinePatches get cached. You should pretty much never look at or manipulate this directly. If I believed in private instance variables this's be private. Maybe I'll make it private soon.
*/
@property(nonatomic, retain, readonly) NSMutableDictionary *ninePatchCache;
-(id)init;
/**
Gets at the application's shared instance, creating it if it doesn't exist.
*/
+(id)shared;
// Getting Ninepatches Directly
/**
Use this method to get at the actual NinePatch you want to interact with (if eg you're using this cache but need finer-grained control than just generating images). Will load the NinePatch (from the app's main bundle) if it doesn't exist yet.
@param ninePatchName The name of the NinePatch you're trying to get at.
@returns The NinePatch object you wanted. Can return nil if problems were encountered.
*/
-(id < TUNinePatch >)ninePatchNamed:(NSString *)ninePachName;
// These methods should be private, if I believed in private methods
-(TUCachingNinePatch *)cachingNinePatchNamed:(NSString *)ninePatchName;
-(void)cacheCachingNinePatch:(TUCachingNinePatch *)cachingNinePatch named:(NSString *)ninePatchName;
-(TUCachingNinePatch *)cachedCachingNinePatchNamed:(NSString *)ninePatchName;
-(TUCachingNinePatch *)constructCachingNinePatchNamed:(NSString *)ninePatchName;
// Getting Images Directly
/**
This method renders the image at the requested size using the NinePatch with the passed-in name. Tries to use a cached image and/or NinePatch as possible, otherwise loading from scratch. Any NinePatch or image it loads is subsequently cached.
@param size The size the output image should be rendered at.
@param ninePatchName the name of the NinePatch you want to use to render the image. Don't include @".9.png" in the name.
@returns An image rendered from the specified ninePatchName at the requested size. Can return nil if difficulties were encountered. Image should be retained if it is important it be held onto by the recipient, but should not be released by the recipient.
*/
-(UIImage *)imageOfSize:(CGSize)size forNinePatchNamed:(NSString *)ninePatchName;
// Getting Ninepatches - Convenience
/**
Semantics same as instance-level method of same name, but calls through to the singleton instance.
*/
+(id < TUNinePatch >)ninePatchNamed:(NSString *)ninePatchName;
// Getting Images - Convenience
/**
This is a convenience method; calls instance method of the same name on the singleton. Easiest way to use this in your code.
*/
+(UIImage *)imageOfSize:(CGSize)size forNinePatchNamed:(NSString *)ninePatchName;
// Cache Management - Direct
/**
Flushes all cached content (NinePatches AND their cached rendered images, if any).
*/
-(void)flushCache;
/**
Flushes only the content for the NinePatch with the passed-in name. Won't complain if there's no cached NinePatch with the passed-in name.
*/
-(void)flushCacheForNinePatchNamed:(NSString *)name;
// Cache Management - Convenience
/**
Flushes all cached content from the singleton.
*/
+(void)flushCache;
/**
Flushes the NinePatch with the passed-in name from the singleton (which also flushes any cached images).
*/
+(void)flushCacheForNinePatchNamed:(NSString *)name;
@end

133
NinePatch/TUNinePatchCache.m Executable file
View file

@ -0,0 +1,133 @@
//
// TUNinePatchCache.m
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import "TUNinePatchCache.h"
#import "TUCachingNinePatch.h"
#import "TUNinePatch.h"
@interface TUNinePatchCache ()
@property(nonatomic, retain, readwrite) NSMutableDictionary *ninePatchCache;
@end
@implementation TUNinePatchCache
#pragma mark Synthesized Properties
@synthesize ninePatchCache = _ninePatchCache;
#pragma mark Init + Dealloc
-(id)init {
if (self = [super init]) {
self.ninePatchCache = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark -
+(id)shared {
static TUNinePatchCache *shared;
if (!shared) {
shared = [[self alloc] init];
}
return shared;
}
#pragma mark -
-(void)dealloc {
self.ninePatchCache = nil;
[super dealloc];
}
#pragma mark Getting Ninepatches Directly
// Getting Ninepatches Directly
-(id < TUNinePatch >)ninePatchNamed:(NSString *)ninePatchName {
TUCachingNinePatch *cachingNinePatch = [self cachingNinePatchNamed:ninePatchName];
NPAssertNilOrIsKindOfClass(cachingNinePatch,TUCachingNinePatch);
return (!cachingNinePatch)?(nil):([cachingNinePatch ninePatch]);
}
-(TUCachingNinePatch *)cachingNinePatchNamed:(NSString *)ninePatchName {
TUCachingNinePatch *cachingNinePatch = [self cachedCachingNinePatchNamed:ninePatchName];
NPAssertNilOrIsKindOfClass(cachingNinePatch,TUCachingNinePatch);
if (!cachingNinePatch) {
cachingNinePatch = [self constructCachingNinePatchNamed:ninePatchName];
NPAssertNilOrIsKindOfClass(cachingNinePatch,TUCachingNinePatch);
if (cachingNinePatch) {
[self cacheCachingNinePatch:cachingNinePatch
named:ninePatchName];
}
}
return cachingNinePatch;
}
-(void)cacheCachingNinePatch:(TUCachingNinePatch *)cachingNinePatch named:(NSString *)ninePatchName {
NPAssertPropertyNonNil(ninePatchCache);
if (cachingNinePatch && ninePatchName) {
[self.ninePatchCache setObject:cachingNinePatch
forKey:ninePatchName];
}
}
-(TUCachingNinePatch *)cachedCachingNinePatchNamed:(NSString *)ninePatchName {
return (!ninePatchName)?(nil):([self.ninePatchCache objectForKey:ninePatchName]);
}
-(TUCachingNinePatch *)constructCachingNinePatchNamed:(NSString *)ninePatchName {
return (!ninePatchName)?(nil):([TUCachingNinePatch ninePatchCacheWithNinePatchNamed:ninePatchName]);
}
#pragma mark Getting Images Directly
-(UIImage *)imageOfSize:(CGSize)size forNinePatchNamed:(NSString *)ninePatchName {
NPParameterAssertNotNilIsKindOfClass(ninePatchName,NSString);
UIImage *image = nil;
TUCachingNinePatch *cachingNinePatch = [self cachingNinePatchNamed:ninePatchName];
if (cachingNinePatch) {
image = [cachingNinePatch imageOfSize:size];
}
return image;
}
#pragma mark Getting Ninepatches - Convenience
+(TUCachingNinePatch *)cachingNinePatchNamed:(NSString *)ninePatchName {
return [[self shared] ninePatchNamed:ninePatchName];
}
+(id < TUNinePatch >)ninePatchNamed:(NSString *)ninePatchName {
TUCachingNinePatch *cachingNinePatch = [[self shared] cachingNinePatchNamed:ninePatchName];
NPAssertNilOrIsKindOfClass(cachingNinePatch,TUCachingNinePatch);
return (!cachingNinePatch)?(nil):([cachingNinePatch ninePatch]);
}
#pragma mark Getting Images - Convenience
+(UIImage *)imageOfSize:(CGSize)size forNinePatchNamed:(NSString *)ninePatchName {
return [[self shared] imageOfSize:size
forNinePatchNamed:ninePatchName];
}
#pragma mark Cache Management - Direct
-(void)flushCache {
[self.ninePatchCache removeAllObjects];
}
-(void)flushCacheForNinePatchNamed:(NSString *)name {
if (name) {
[self.ninePatchCache removeObjectForKey:name];
}
}
#pragma mark Cache Management - Convenience
+(void)flushCache {
[[self shared] flushCache];
}
+(void)flushCacheForNinePatchNamed:(NSString *)name {
[[self shared] flushCacheForNinePatchNamed:name];
}
@end

View file

@ -0,0 +1,28 @@
//
// TUNinePatchCachingCategories.h
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
@interface NSString (NinePatchCaching)
+(NSString *)ninePatchKeyStringForSize:(CGSize)size;
@end
@interface NSDictionary (NinePatchCaching)
-(id)objectForSize:(CGSize)size;
@end
@interface NSMutableDictionary (NinePatchCaching)
-(void)setObject:(id)object forSize:(CGSize)size;
@end

View file

@ -0,0 +1,52 @@
//
// TUNinePatchCachingCategories.m
// NinePatch
//
// Copyright 2010 Tortuga 22, Inc. All rights reserved.
//
#import "TUNinePatchCachingCategories.h"
@implementation NSString (NinePatchCaching)
/**
It's not clear we can't just use NSStringFromCGSize. This might get cut in a future revision.
*/
+(NSString *)ninePatchKeyStringForSize:(CGSize)size {
return [NSString stringWithFormat:@"ninePatchKeyString.%#.0f.%#.0f",size.width,size.height];
}
@end
@implementation NSDictionary (NinePatchCaching)
/**
Convenience method to make it a little less annoying to pull objects out of the caches keyed by their size.
*/
-(id)objectForSize:(CGSize)size {
id object = nil;
NSString *key = [NSString ninePatchKeyStringForSize:size];
if (key) {
object = [self objectForKey:key];
}
return object;
}
@end
@implementation NSMutableDictionary (NinePatchCaching)
/**
Convenience method to make it a little less annoying to put objects in the caches keyed by their size.
*/
-(void)setObject:(id)object forSize:(CGSize)size {
if (object) {
NSString *key = [NSString ninePatchKeyStringForSize:size];
if (key) {
[self setObject:object
forKey:key];
}
}
}
@end

121
NinePatch/TUNinePatchProtocols.h Executable file
View file

@ -0,0 +1,121 @@
//
// TUNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
/**
Defines the methods shared by all concrete NinePatch classes. Expect many of these methods to be removed from the
protocol as the library is improved.
*/
@protocol TUNinePatch < NSObject, NSCoding, NSCopying >
// TUNinePatch Protocol Methods - Drawing
/**
This draws the NinePatch with its upper-left corner at a specified location in a specified context, scaled to fit content of the size. This is a good method to use when drawing NinePatches that use the content bounds. This method will probably be improved in the future to return the upper-left corner for the content to be drawn.
@param context A non-nil CGContextRef into which NinePatch will be drawn.
@param point The upper left corner the NinePatch will be drawn at.
@param size The size of the content the NinePatch will be sized to contain.
*/
-(void)inContext:(CGContextRef)context drawAtPoint:(CGPoint)point forContentOfSize:(CGSize)size;
/**
This draws the NinePatch centered (horizontally and vertically) inside the containmentRect in the specified context, sized to fit content of the passed-in size. This is essentially a convenience method wrapping inContext:drawAtPoint:forContentOfSize:. Like its cousin it'll probably be modified to return information about where the content should be drawn. Will let the NinePatch overflow the containmentRect if the necessary size is sufficiently large; it'll be centered, just too big.
@param context A non-nil CGContextRef into which NinePatch will be drawn.
@param containmentRect the rect in which the NinePatch will be centered.
@param size The size of the content the NinePatch will be sized to contain.
*/
-(void)inContext:(CGContextRef)context drawCenteredInRect:(CGRect)containmentRect forContentOfSize:(CGSize)size;
/**
This method draws the NinePatch into the passed-in context filling the passed-in rect. In all current implementations of TUNinePatch the other drawing utilities eventually call through this method to do their actual drawing.
@param context A non-nil CGContextRef into which NinePatch will be drawn.
@param rect The rect into which the NinePatch will be drawn. NinePatch is scaled to fill the rect.
*/
-(void)inContext:(CGContextRef)context drawInRect:(CGRect)rect;
// TUNinePatch Protocol Methods - Image Construction
/**
Renders the NinePatch into an image of the requested size. Implementations vary in their memory management here -- to guarantee the returned image hangs around you should retain it.
@param size The size the output UIImage should be.
@returns A UIImage rendering of the NinePatch scaled like the passed-in size.
*/
-(UIImage *)imageOfSize:(CGSize)size;
// TUNinePatch Protocol Methods - Sizing
/**
Returns YES if the NinePatch scales horizontally, NO otherwise. May be removed from protocol in future.
*/
-(BOOL)stretchesHorizontally;
/**
Returns YES if the NinePatch scales vertically, NO otherwise. May be removed from protocol in future.
*/
-(BOOL)stretchesVertically;
/**
Returns smallest horizontal size you scan scale NinePatch down to. This is usually equal to the leftEdge + the rightEdge (sending central column width -> 0). May be removed from protocol in future.
@returns minimumWidth the smallest width NinePatch will render at.
*/
-(CGFloat)minimumWidth;
/**
Returns smallest vertical size you scan scale NinePatch down to. This is usually equal to the topEdge + bottomEdge (sending central row height -> 0). May be removed from protocol in future.
@returns minimumHeight the smallest height NinePatch will render at.
*/
-(CGFloat)minimumHeight;
/**
Returns CGSize created from minimumWidth and minimumHeight in the obvious way.
*/
-(CGSize)minimumSize;
/**
This is used for layout. Recall that NinePatch allows you to specify a "content region" (into which the content must fit) as a way of standardizing the amount of padding you do when using a particular NinePatch. This method returns the size the NinePatch needs to be drawn at to correctly accommodate content of the passed-in size. Note that for NinePatches that don't specify anything wrt content size this is the identity function.
@param contentSize The size of the content you're using the NinePatch to display.
@returns The size you need to draw the NinePatch at to accommodate the content.
*/
-(CGSize)sizeForContentOfSize:(CGSize)contentSize;
/**
This is used for layout. This is basically a convenience function to calculate the offset for where "content" starts. It's the identity function when the NinePatch doesn't specify anything for the content region.
@param point The point at which you're planning to place the upper left corner of the NinePatch when you draw it.
@returns The point at which you need to place the upper left corner of the content you're going to draw.
*/
-(CGPoint)upperLeftCornerForContentWhenDrawnAtPoint:(CGPoint)point;
// TUNinePatch Protocol Methods - Geometry
/**
The width of the left column. This geometric property lookup is probably going to get removed from the protocol.
*/
-(CGFloat)leftEdgeWidth;
/**
The width of the right column. This geometric property lookup is probably going to get removed from the protocol.
*/
-(CGFloat)rightEdgeWidth;
/**
The width of the upper row. This geometric property lookup is probably going to get removed from the protocol.
*/
-(CGFloat)upperEdgeHeight;
/**
The width of the lower column. This geometric property lookup is probably going to get removed from the protocol.
*/
-(CGFloat)lowerEdgeHeight;
@end

36
NinePatch/TUVerticalNinePatch.h Executable file
View file

@ -0,0 +1,36 @@
//
// TUVerticalNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatch.h"
#import "TUNinePatchProtocols.h"
/**
Concrete TUNinePatch instance. Handles NinePatches that only stretch vertically. Only instantiate directly if you know what you're doing.
*/
@interface TUVerticalNinePatch : TUNinePatch < TUNinePatch > {
UIImage *_upperEdge;
UIImage *_lowerEdge;
}
// Synthesized Properties
@property(nonatomic, retain, readonly) UIImage *upperEdge;
@property(nonatomic, retain, readonly) UIImage *lowerEdge;
// Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally upperEdge:(UIImage *)upperEdge lowerEdge:(UIImage *)lowerEdge;
-(void)dealloc;
// TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect;
-(BOOL)stretchesHorizontally;
-(CGSize)sizeForContentOfSize:(CGSize)contentSize;
-(CGFloat)upperEdgeHeight;
-(CGFloat)lowerEdgeHeight;
@end

132
NinePatch/TUVerticalNinePatch.m Executable file
View file

@ -0,0 +1,132 @@
//
// TUVerticalNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "TUVerticalNinePatch.h"
@interface TUVerticalNinePatch ()
// Synthesized Properties
@property(nonatomic, retain, readwrite) UIImage *upperEdge;
@property(nonatomic, retain, readwrite) UIImage *lowerEdge;
@end
@implementation TUVerticalNinePatch
#pragma mark Synthesized Properties
@synthesize upperEdge = _upperEdge;
@synthesize lowerEdge = _lowerEdge;
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
self.upperEdge = (UIImage *)[coder decodeObjectForKey:@"upperEdge"];
self.lowerEdge = (UIImage *)[coder decodeObjectForKey:@"lowerEdge"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.upperEdge
forKey:@"upperEdge"];
[coder encodeObject:self.lowerEdge
forKey:@"lowerEdge"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithCenter:self.center
contentRegion:self.contentRegion
tileCenterVertically:self.tileCenterVertically
tileCenterHorizontally:self.tileCenterHorizontally
upperEdge:self.upperEdge
lowerEdge:self.lowerEdge];
}
#pragma mark Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally upperEdge:(UIImage *)upperEdge lowerEdge:(UIImage *)lowerEdge {
NPParameterAssertNotNilIsKindOfClass(upperEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerEdge,UIImage);
if (self = [super initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally]) {
self.upperEdge = upperEdge;
self.lowerEdge = lowerEdge;
}
return self;
}
#pragma mark -
-(void)dealloc {
self.upperEdge = nil;
self.lowerEdge = nil;
[super dealloc];
}
#pragma mark TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect {
NPSelfProperty(center);
NPSelfProperty(upperEdge);
NPSelfProperty(lowerEdge);
CGFloat width = [self minimumWidth];
[self.center drawInRect:CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect) + [self upperEdgeHeight], width, CGRectGetHeight(rect) - ([self upperEdgeHeight] + [self lowerEdgeHeight]))];
if (self.upperEdge) {
[self.upperEdge drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))];
}
if (self.lowerEdge) {
[self.lowerEdge drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect) - [self lowerEdgeHeight])];
}
}
#pragma mark -
-(BOOL)stretchesHorizontally {
return NO;
}
-(CGSize)sizeForContentOfSize:(CGSize)contentSize {
NPAInputLog(@"sizeForContentOfSize:'%@'",NSStringFromCGSize(contentSize));
CGSize outSize = [super sizeForContentOfSize:contentSize];
outSize.width = [self minimumWidth];
NPCGSOutputLog(outSize);
return outSize;
}
#pragma mark -
-(CGFloat)upperEdgeHeight {
NPSelfProperty(upperEdge);
CGFloat upperEdgeHeight = 0.0f;
if (self.upperEdge) {
upperEdgeHeight = [self.upperEdge size].height;
}
NPFOutputLog(upperEdgeHeight);
return upperEdgeHeight;
}
-(CGFloat)lowerEdgeHeight {
NPSelfProperty(lowerEdge);
CGFloat lowerEdgeHeight = 0.0f;
if (self.lowerEdge) {
lowerEdgeHeight = [self.lowerEdge size].height;
}
NPFOutputLog(lowerEdgeHeight);
return lowerEdgeHeight;
}
#pragma mark Customized Description Overrides
-(NSString *)descriptionPostfix {
return [NSString stringWithFormat:@"%@, self.upperEdge:<'%@'>, self.lowerEdge:<'%@'>",
[super descriptionPostfix],
self.upperEdge,
self.lowerEdge];
}
@end

77
NinePatch/UIImage-TUNinePatch.h Executable file
View file

@ -0,0 +1,77 @@
//
// UIImage-TUNinePatch.h
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import "TUNinePatchProtocols.h"
void TUImageLog(UIImage *image, NSString *imageName);
/**
This category implements all the image-slicing, pixel-tasting, and similar image-manipulation and image-analysis functions. These are only used in methods that'll probably become private real soon now, so maybe a "not much to see here" sign is called for.
*/
@interface UIImage (TUNinePatch)
// Black Pixel Searching - Corners
-(BOOL)upperLeftCornerIsBlackPixel;
-(BOOL)upperRightCornerIsBlackPixel;
-(BOOL)lowerLeftCornerIsBlackPixel;
-(BOOL)lowerRightCornerIsBlackPixel;
// Pixel Tasting - Single Pixel
-(BOOL)isBlackPixel;
// Black Pixel Searching - Strips
-(NSRange)blackPixelRangeInUpperStrip;
-(NSRange)blackPixelRangeInLowerStrip;
-(NSRange)blackPixelRangeInLeftStrip;
-(NSRange)blackPixelRangeInRightStrip;
// Pixel Tasting - Strips
-(NSRange)blackPixelRangeAsVerticalStrip;
-(NSRange)blackPixelRangeAsHorizontalStrip;
// Corners - Rects
-(CGRect)upperLeftCornerRect;
-(CGRect)lowerLeftCornerRect;
-(CGRect)upperRightCornerRect;
-(CGRect)lowerRightCornerRect;
// Corners - Slicing
-(UIImage *)upperLeftCorner;
-(UIImage *)lowerLeftCorner;
-(UIImage *)upperRightCorner;
-(UIImage *)lowerRightCorner;
// Strips - Sizing
-(CGRect)upperStripRect;
-(CGRect)lowerStripRect;
-(CGRect)leftStripRect;
-(CGRect)rightStripRect;
// Strips - Slicing
-(UIImage *)upperStrip;
-(UIImage *)lowerStrip;
-(UIImage *)leftStrip;
-(UIImage *)rightStrip;
// Subimage Slicing
-(UIImage *)subImageInRect:(CGRect)rect;
// Nine-Patch Content Extraction
-(UIImage *)imageAsNinePatchImage;
-(UIImage *)extractUpperLeftCornerForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractUpperRightCornerForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractLowerLeftCornerForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractLowerRightCornerForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractLeftEdgeForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractRightEdgeForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractUpperEdgeForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractLowerEdgeForStretchableRegion:(CGRect)stretchableRegion;
-(UIImage *)extractCenterForStretchableRegion:(CGRect)stretchableRegion;
@end

539
NinePatch/UIImage-TUNinePatch.m Executable file
View file

@ -0,0 +1,539 @@
//
// UIImage-TUNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "UIImage-TUNinePatch.h"
#import "TUNinePatchProtocols.h"
void TUImageLog(UIImage *image, NSString *imageName) {
if (image && imageName) {
NSString *fullFileName = [imageName stringByAppendingString:@".png"];
if (fullFileName) {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
if (documentsDirectory) {
NSString *fullFilePath = [documentsDirectory stringByAppendingPathComponent:fullFileName];
if (fullFilePath) {
NSData *pngData = UIImagePNGRepresentation(image);
if (pngData) {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (fileManager) {
BOOL succeeded = [fileManager createFileAtPath:fullFilePath contents:pngData attributes:nil];
if (succeeded) {
DLog(@"Seemingly successfully wrote image to file at: '%@'.",fullFilePath);
} else {
DLog(@"Seemingly failed to write image to file at: '%@'.",fullFilePath);
}
} else {
LLog(@"Couldn't get default fileManager, aborting imagelog.");
}
} else {
LLog(@"Couldn't get PNGRepresentation, aborting imagelog.");
}
} else {
LLog(@"Couldn't get fullFilePath, aborting imagelog.");
}
} else {
LLog(@"Couldn't get fullFilePath, aborting imagelog.");
}
} else {
DLog(@"Could't get fullFileName, aborting imageLog.");
}
} else {
DLog(@"Can't log image: '%@', imageName: '%@', as one or both are nil.",image, imageName);
}
}
@implementation UIImage (TUNinePatch)
#pragma mark Black Pixel Searching - Corners
-(BOOL)upperLeftCornerIsBlackPixel {
BOOL upperLeftCornerIsBlackPixel = NO;
UIImage *upperLeftCorner = [self upperLeftCorner];
if (upperLeftCorner) {
upperLeftCornerIsBlackPixel = [upperLeftCorner isBlackPixel];
}
NPBOutputLog(upperLeftCornerIsBlackPixel);
return upperLeftCornerIsBlackPixel;
}
-(BOOL)upperRightCornerIsBlackPixel {
BOOL upperRightCornerIsBlackPixel = NO;
UIImage *upperRightCorner = [self upperRightCorner];
if (upperRightCorner) {
upperRightCornerIsBlackPixel = [upperRightCorner isBlackPixel];
}
NPBOutputLog(upperRightCornerIsBlackPixel);
return upperRightCornerIsBlackPixel;
}
-(BOOL)lowerLeftCornerIsBlackPixel {
BOOL lowerLeftCornerIsBlackPixel = NO;
UIImage *lowerLeftCorner = [self lowerLeftCorner];
if (lowerLeftCorner) {
lowerLeftCornerIsBlackPixel = [lowerLeftCorner isBlackPixel];
}
NPBOutputLog(lowerLeftCornerIsBlackPixel);
return lowerLeftCornerIsBlackPixel;
}
-(BOOL)lowerRightCornerIsBlackPixel {
BOOL lowerRightCornerIsBlackPixel = NO;
UIImage *lowerRightCorner = [self lowerRightCorner];
if (lowerRightCorner) {
lowerRightCornerIsBlackPixel = [lowerRightCorner isBlackPixel];
}
NPBOutputLog(lowerRightCornerIsBlackPixel);
return lowerRightCornerIsBlackPixel;
}
#pragma mark Pixel Tasting - Single Pixel
-(BOOL)isBlackPixel {
NPAssert(([self size].width > 0.0f), @"Should have width > 0.0f");
NPAssert(([self size].height > 0.0f), @"Should have height > 0.0f");
BOOL isBlackPixel = NO;
if (([self size].width > 0.0f) && ([self size].height > 0.0f)) {
CGImageRef cgImage = [self CGImage];
NSUInteger width = CGImageGetWidth(cgImage);
NSUInteger height = CGImageGetHeight(cgImage);
NSUInteger bytesPerRow = width * TURGBABytesPerPixel;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 *pixelByteData = malloc(width * height * TURGBABytesPerPixel);
CGContextRef context = CGBitmapContextCreate(
(void *)pixelByteData,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0.0f,0.0f,1.0f,1.0f), cgImage);
TURGBAPixel *pixelData = (TURGBAPixel *) CGBitmapContextGetData(context);
if (pixelData) {
isBlackPixel = TURGBAPixelIsBlack(pixelData[0]);
}
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixelByteData);
}
NPBOutputLog(isBlackPixel);
return isBlackPixel;
}
#pragma mark Black Pixel Searching - Strips
-(NSRange)blackPixelRangeInUpperStrip {
NSRange blackPixelRangeInUpperStrip = TUNotFoundRange;
UIImage *upperStrip = [self upperStrip];
if (upperStrip) {
blackPixelRangeInUpperStrip = [upperStrip blackPixelRangeAsHorizontalStrip];
}
NPNSROutputLog(blackPixelRangeInUpperStrip);
return blackPixelRangeInUpperStrip;
}
-(NSRange)blackPixelRangeInLowerStrip {
NSRange blackPixelRangeInLowerStrip = TUNotFoundRange;
UIImage *lowerStrip = [self lowerStrip];
if (lowerStrip) {
blackPixelRangeInLowerStrip = [lowerStrip blackPixelRangeAsHorizontalStrip];
}
NPNSROutputLog(blackPixelRangeInLowerStrip);
return blackPixelRangeInLowerStrip;
}
-(NSRange)blackPixelRangeInLeftStrip {
NSRange blackPixelRangeInLeftStrip = TUNotFoundRange;
UIImage *leftStrip = [self leftStrip];
if (leftStrip) {
blackPixelRangeInLeftStrip = [leftStrip blackPixelRangeAsVerticalStrip];
}
NPNSROutputLog(blackPixelRangeInLeftStrip);
return blackPixelRangeInLeftStrip;
}
-(NSRange)blackPixelRangeInRightStrip {
NSRange blackPixelRangeInRightStrip = TUNotFoundRange;
UIImage *rightStrip = [self rightStrip];
if (rightStrip) {
blackPixelRangeInRightStrip = [rightStrip blackPixelRangeAsVerticalStrip];
}
NPNSROutputLog(blackPixelRangeInRightStrip);
return blackPixelRangeInRightStrip;
}
#pragma mark Pixel Tasting - Strips
-(NSRange)blackPixelRangeAsVerticalStrip {
NPAssert([self size].width == 1.0f, @"This method assumes the image has width == 1.0f");
NSRange blackPixelRangeAsVerticalStrip = TUNotFoundRange;
NSUInteger firstBlackPixel = NSNotFound;
NSUInteger lastBlackPixel = NSNotFound;
if ([self size].height > 0.0f) {
CGImageRef cgImage = [self CGImage];
NSUInteger width = CGImageGetWidth(cgImage);
NSUInteger height = CGImageGetHeight(cgImage);
NSUInteger bytesPerRow = width * TURGBABytesPerPixel;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 *pixelByteData = malloc(width * height * TURGBABytesPerPixel);
CGContextRef context = CGBitmapContextCreate(
(void *)pixelByteData,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
// NEW: seeing nondetermnistic errors where sometimes the image is parsed right
// and sometimes not parsed right. The followthing three lines paint the context
// to solid white, then paste the image over it, so this ought to normalize the
// outcome a bit more.
CGRect contextBounds = CGRectMake(0.0f, 0.0f, width, height);
CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]);
CGContextFillRect(context, contextBounds);
// Having normalized the context we now paint the image
CGContextDrawImage(context, contextBounds, cgImage);
TURGBAPixel *pixelData = (TURGBAPixel *) CGBitmapContextGetData(context);
if (pixelData) {
// CF note in the AsHorizontal method below
for (NSUInteger i = 0; i < height; i++) {
if (TURGBAPixelIsBlack(pixelData[((height - 1) - i)])) {
firstBlackPixel = ((height - 1) - i);
}
if (TURGBAPixelIsBlack(pixelData[i])) {
lastBlackPixel = i;
}
}
if ((firstBlackPixel != NSNotFound) && (lastBlackPixel != NSNotFound)) {
NPAssert(lastBlackPixel >= firstBlackPixel, ([NSString stringWithFormat:@"Got firstBlackPixel:'%d' and lastBlackPixel:'%d'.",firstBlackPixel,lastBlackPixel]));
blackPixelRangeAsVerticalStrip.location = TUTruncateWithin(firstBlackPixel, 0, height - 1) / self.scale;
// We can't just use TUTruncateAtZero on lastBlackPixel - firstBlackPixel here.
// The semantics of pixel coordinates are such that a zero difference between lastBlackPixel and firstBlackPixel is ok
// but < 0 is obv. very bad.
// Thus 1 + TUTruncateAtZero(lastBlackPixel - firstBlackPixel) won't work.
// and fixing the expression s.t. it does work is more complicated than
// just breaking it down like so.
NSInteger length = lastBlackPixel - firstBlackPixel;
if (length >= 0) {
length += 1;
} else {
length = 0;
}
blackPixelRangeAsVerticalStrip.length = length/self.scale;
}
}
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixelByteData);
}
NPNSROutputLog(blackPixelRangeAsVerticalStrip);
return blackPixelRangeAsVerticalStrip;
}
-(NSRange)blackPixelRangeAsHorizontalStrip {
NPAssert([self size].height == 1.0f, @"This method assumes the image has height == 1.0f");
NSRange blackPixelRangeAsHorizontalStrip = TUNotFoundRange;
NSUInteger firstBlackPixel = NSNotFound;
NSUInteger lastBlackPixel = NSNotFound;
if ([self size].width > 0.0f) {
CGImageRef cgImage = [self CGImage];
NSUInteger width = CGImageGetWidth(cgImage);
NSUInteger height = CGImageGetHeight(cgImage);
NSUInteger bytesPerRow = width * TURGBABytesPerPixel;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 *pixelByteData = malloc(width * height * TURGBABytesPerPixel);
CGContextRef context = CGBitmapContextCreate(
(void *)pixelByteData,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
// NEW: seeing nondetermnistic errors where sometimes the image is parsed right
// and sometimes not parsed right. The followthing three lines paint the context
// to solid white, then paste the image over it, so this ought to normalize the
// outcome a bit more.
CGRect contextBounds = CGRectMake(0.0f, 0.0f, width, height);
CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]);
CGContextFillRect(context, contextBounds);
// Having normalized the context we now paint the image
CGContextDrawImage(context, contextBounds, cgImage);
TURGBAPixel *pixelData = (TURGBAPixel *) CGBitmapContextGetData(context);
if (pixelData) {
// The for loop below is walking the strip from both ends.
// Basically you could do this check a bunch of ways, with a
// bunch of trade-offs in terms of how fast it is and how robust it
// is and how any "format errors" in your nine patch manifest.
//
// What I have found is that ninepatch is a fussy format, with a
// common failure mode being that you painted a pixel "black" but
// either got the alpha wrong, or it wasn't quite black, or it
// didn't composite to black, etc., and thus get invalid ninepatches.
//
// What I do here is just look for the highest and lowest black pixels,
// and treat anything in between as also black. EG:
//
// - if X == black and O == not-black
// - then these square brackes - [ and ] - enclose the "black" region
//
// - then: OOOOXXXXXOOOOO -> OOOO[XXXXX]OOOOO
// - but also: OOOXXOOXXOOO -> OOO[XXOOXX]OOO
// - and even: OXOOOOOOOXO -> O[XOOOOOOOX]O
//
// This is a judgement call on my part, in that the approach I can take to
// accomplish this is straightforward without any complicated state tracking,
// and the behavior it has in the face of "invalid" nine-patches is generally
// what I meant, anyways.
//
// The actual implementation is straightforward but suboptimal.
// I look through the array once, iterating i from 0->(width -1).
// On each iteration I taste the pixel @ i and at (width - 1) -1,
// and if the pixel @ i is black I set the "lastBlackPixel" == i
// and if the pixel @ (width - 1) - i is black I set the "firstBlackPixel"
// to (width - 1) - i.
//
// Once the loop is done the values in the lastBlackPixel and firstBlackPixel
// contain what they ought to have.
//
// Given the continual risk of hard-to-spot off-by-one errors throughout this
// library I've opted to keep it dumb and suboptimal in places like this one,
// so that I can be more comfortable that what problems there are are elsewhere.
//
// If you subseqently do add an improved loop please wrap it in ifdefs like
// #ifdef CLEVERNESS YOUR-CODE #else DUMB-CODE #endif
//
for (NSUInteger i = 0; i < width; i++) {
if (TURGBAPixelIsBlack(pixelData[((width - 1) - i)])) {
firstBlackPixel = ((width - 1) - i);
}
if (TURGBAPixelIsBlack(pixelData[i])) {
lastBlackPixel = i;
}
}
if ((firstBlackPixel != NSNotFound) && (lastBlackPixel != NSNotFound)) {
NPAssert(lastBlackPixel >= firstBlackPixel, ([NSString stringWithFormat:@"Got firstBlackPixel:'%d' and lastBlackPixel:'%d'.",firstBlackPixel,lastBlackPixel]));
blackPixelRangeAsHorizontalStrip.location = TUTruncateWithin(firstBlackPixel, 0, width - 1) / self.scale;
// We can't just use TUTruncateAtZero on lastBlackPixel - firstBlackPixel here.
// The semantics of pixel coordinates are such that a zero difference between lastBlackPixel and firstBlackPixel is ok
// but < 0 is obv. very bad.
// Thus 1 + TUTruncateAtZero(lastBlackPixel - firstBlackPixel) won't work.
// and fixing the expression s.t. it does work is more complicated than
// just breaking it down like so.
NSInteger length = lastBlackPixel - firstBlackPixel;
if (length >= 0) {
length += 1;
} else {
length = 0;
}
blackPixelRangeAsHorizontalStrip.length = length / self.scale;
}
}
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixelByteData);
}
NPNSROutputLog(blackPixelRangeAsHorizontalStrip);
return blackPixelRangeAsHorizontalStrip;
}
#pragma mark Corners - Rects
-(CGRect)upperLeftCornerRect {
return CGRectMake(0.0f, 0.0f, 1.0f/self.scale, 1.0f/self.scale);
}
-(CGRect)lowerLeftCornerRect {
return CGRectMake(0.0f, [self size].height - (1.0f/self.scale), 1.0f/self.scale, 1.0f/self.scale);
}
-(CGRect)upperRightCornerRect {
return CGRectMake([self size].width - (1.0f/self.scale), 0.0f, 1.0f/self.scale, 1.0f/self.scale);
}
-(CGRect)lowerRightCornerRect {
return CGRectMake([self size].width - 1.0f, [self size].height - (1.0f/self.scale), 1.0f/self.scale, 1.0f/self.scale);
}
#pragma mark Corners - Slicing
-(UIImage *)upperLeftCorner {
return [self subImageInRect:[self upperLeftCornerRect]];
}
-(UIImage *)lowerLeftCorner {
return [self subImageInRect:[self lowerLeftCornerRect]];
}
-(UIImage *)upperRightCorner {
return [self subImageInRect:[self upperRightCornerRect]];
}
-(UIImage *)lowerRightCorner {
return [self subImageInRect:[self lowerRightCornerRect]];
}
#pragma mark Strips - Sizing
-(CGRect)upperStripRect {
CGSize selfSize = [self size];
CGFloat stripWidth = TUTruncateAtZero(selfSize.width - (2.0f/self.scale));
return CGRectMake((1.0f/self.scale), 0.0f, stripWidth, 1.0f/self.scale);
}
-(CGRect)lowerStripRect {
CGSize selfSize = [self size];
CGFloat stripWidth = TUTruncateAtZero(selfSize.width - (2.0f/self.scale));
return CGRectMake(1.0f/self.scale, selfSize.height - (1.0f/self.scale), stripWidth, 1.0f/self.scale);
}
-(CGRect)leftStripRect {
CGSize selfSize = [self size];
CGFloat stripHeight = TUTruncateAtZero(selfSize.height - (2.0f/self.scale));
return CGRectMake(0.0f, 1.0f/self.scale, 1.0f/self.scale, stripHeight);
}
-(CGRect)rightStripRect {
CGSize selfSize = [self size];
CGFloat stripHeight = TUTruncateAtZero(selfSize.height - (2.0f/self.scale));
return CGRectMake(selfSize.width - (1.0f/self.scale), 1.0f/self.scale, 1.0f/self.scale, stripHeight);
}
#pragma mark Strips - Slicing
-(UIImage *)upperStrip {
return [self subImageInRect:[self upperStripRect]];
}
-(UIImage *)lowerStrip {
return [self subImageInRect:[self lowerStripRect]];
}
-(UIImage *)leftStrip {
return [self subImageInRect:[self leftStripRect]];
}
-(UIImage *)rightStrip {
return [self subImageInRect:[self rightStripRect]];
}
-(UIImage *)subImageInRect:(CGRect)rect {
NPAInputLog(@"subImageInRect:'%@'",NSStringFromCGRect(rect));
UIImage *subImage = nil;
CGImageRef cir = [self CGImage];
if (cir) {
rect.origin.x *= self.scale;
rect.origin.y *= self.scale;
rect.size.width *= self.scale;
rect.size.height *= self.scale;
CGImageRef subCGImage = CGImageCreateWithImageInRect(cir, rect);
if (subCGImage) {
subImage = [UIImage imageWithCGImage:subCGImage scale:self.scale orientation:self.imageOrientation];
CGImageRelease(subCGImage);
NPAssertNilOrIsKindOfClass(subImage,UIImage);
NPAssert((CGSizeEqualToSize([subImage size], rect.size)), @"Shouldn't get unequal subimage and requested sizes.");
} else {
DLog(@"Couldn't create subImage in rect: '%@'.", NSStringFromCGRect(rect));
}
} else {
LLog(@"self.CGImage is somehow nil.");
}
//DLog(@"[%@:<0x%x> subImageInRect:%@] yielded subImage: '%@' of size: '%@'", [self class], ((NSUInteger) self), NSStringFromCGRect(rect), subImage, NSStringFromCGSize([subImage size]));
//IMLog(self, @"subImageInRectSourceImage");
//IMLog(subImage, @"subImageInRect");
NPOOutputLog(subImage);
return subImage;
}
#pragma mark Nine-Patch Content Extraction
-(UIImage *)imageAsNinePatchImage {
UIImage *imageOfNinePatchImage = nil;
CGFloat width = [self size].width - (2.0f/self.scale);
CGFloat height = [self size].height - (2.0f/self.scale);
if (width > 0.0f && height > 0.0f) {
imageOfNinePatchImage = [self subImageInRect:CGRectMake((1.0f/self.scale), (1.0f/self.scale), width, height)];
}
NPOOutputLog(imageOfNinePatchImage);
return imageOfNinePatchImage;
}
#pragma mark -
-(UIImage *)extractUpperLeftCornerForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractUpperLeftCornerForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *upperLeftCorner = [self subImageInRect:CGRectMake(0.0f, 0.0f, CGRectGetMinX(stretchableRegion), CGRectGetMinY(stretchableRegion))];
NPOOutputLog(upperLeftCorner);
return upperLeftCorner;
}
-(UIImage *)extractUpperRightCornerForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractUpperRightCornerForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *upperRightCorner = [self subImageInRect:CGRectMake(CGRectGetMaxX(stretchableRegion), 0.0f, [self size].width - CGRectGetMaxX(stretchableRegion), CGRectGetMinY(stretchableRegion))];
NPOOutputLog(upperRightCorner);
return upperRightCorner;
}
-(UIImage *)extractLowerLeftCornerForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractUpperRightCornerForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *lowerLeftCorner = [self subImageInRect:CGRectMake(0.0f, CGRectGetMaxY(stretchableRegion), CGRectGetMinX(stretchableRegion), [self size].height - CGRectGetMaxY(stretchableRegion))];
NPOOutputLog(lowerLeftCorner);
return lowerLeftCorner;
}
-(UIImage *)extractLowerRightCornerForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractLowerRightCornerForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *lowerRightCorner = [self subImageInRect:CGRectMake(CGRectGetMaxX(stretchableRegion), CGRectGetMaxY(stretchableRegion), [self size].width - CGRectGetMaxX(stretchableRegion), [self size].height - CGRectGetMaxY(stretchableRegion))];
NPOOutputLog(lowerRightCorner);
return lowerRightCorner;
}
#pragma mark -
-(UIImage *)extractLeftEdgeForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractLeftEdgeForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *leftEdge = [self subImageInRect:CGRectMake(0.0f, CGRectGetMinY(stretchableRegion), CGRectGetMinX(stretchableRegion), CGRectGetHeight(stretchableRegion))];
NPOOutputLog(leftEdge);
return leftEdge;
}
-(UIImage *)extractRightEdgeForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractRightEdgeForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *rightEdge = [self subImageInRect:CGRectMake(CGRectGetMaxX(stretchableRegion), CGRectGetMinY(stretchableRegion), [self size].width - CGRectGetMaxX(stretchableRegion), CGRectGetHeight(stretchableRegion))];
NPOOutputLog(rightEdge);
return rightEdge;
}
-(UIImage *)extractUpperEdgeForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractUpperEdgeForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *upperEdge = [self subImageInRect:CGRectMake(CGRectGetMinX(stretchableRegion), 0.0f, CGRectGetWidth(stretchableRegion), CGRectGetMinY(stretchableRegion))];
NPOOutputLog(upperEdge);
return upperEdge;
}
-(UIImage *)extractLowerEdgeForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractLowerEdgeForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *lowerEdge = [self subImageInRect:CGRectMake(CGRectGetMinX(stretchableRegion), CGRectGetMaxY(stretchableRegion), CGRectGetWidth(stretchableRegion), [self size].height - CGRectGetMaxY(stretchableRegion))];
NPOOutputLog(center);
return lowerEdge;
}
#pragma mark -
-(UIImage *)extractCenterForStretchableRegion:(CGRect)stretchableRegion {
NPAInputLog(@"extractCenterForStretchableRegion:'%@'",NSStringFromCGRect(stretchableRegion));
UIImage *center = [self subImageInRect:stretchableRegion];
NPOOutputLog(center);
return center;
}
@end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -209,10 +209,6 @@
D32409C4158B49A600C8C119 /* UILongTouchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D32409C2158B49A600C8C119 /* UILongTouchButton.m */; };
D32460E6159D9AAD00BA7F3A /* UIPassView.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460E5159D9AAD00BA7F3A /* UIPassView.m */; };
D32460E7159D9AAD00BA7F3A /* UIPassView.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460E5159D9AAD00BA7F3A /* UIPassView.m */; };
D32460ED159DA47700BA7F3A /* CPAnimationSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460EA159DA47700BA7F3A /* CPAnimationSequence.m */; };
D32460EE159DA47700BA7F3A /* CPAnimationSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460EA159DA47700BA7F3A /* CPAnimationSequence.m */; };
D32460EF159DA47700BA7F3A /* CPAnimationStep.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460EC159DA47700BA7F3A /* CPAnimationStep.m */; };
D32460F0159DA47700BA7F3A /* CPAnimationStep.m in Sources */ = {isa = PBXBuildFile; fileRef = D32460EC159DA47700BA7F3A /* CPAnimationStep.m */; };
D326483815887D5200930C67 /* OrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = D326483715887D5200930C67 /* OrderedDictionary.m */; };
D326483915887D5200930C67 /* OrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = D326483715887D5200930C67 /* OrderedDictionary.m */; };
D326483E1588950F00930C67 /* UICallBar.m in Sources */ = {isa = PBXBuildFile; fileRef = D326483C1588950F00930C67 /* UICallBar.m */; };
@ -424,6 +420,15 @@
D3832801158100E400FA0D23 /* history_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D38327FD158100E400FA0D23 /* history_over.png */; };
D3832802158100E400FA0D23 /* settings_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D38327FE158100E400FA0D23 /* settings_over.png */; };
D3832803158100E400FA0D23 /* chat_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D38327FF158100E400FA0D23 /* chat_over.png */; };
D389362615A6D19800A3A3AA /* CPAnimationSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D389362315A6D19800A3A3AA /* CPAnimationSequence.m */; };
D389362715A6D19800A3A3AA /* CPAnimationSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = D389362315A6D19800A3A3AA /* CPAnimationSequence.m */; };
D389362815A6D19800A3A3AA /* CPAnimationStep.m in Sources */ = {isa = PBXBuildFile; fileRef = D389362515A6D19800A3A3AA /* CPAnimationStep.m */; };
D389362915A6D19800A3A3AA /* CPAnimationStep.m in Sources */ = {isa = PBXBuildFile; fileRef = D389362515A6D19800A3A3AA /* CPAnimationStep.m */; };
D389363515A6D40000A3A3AA /* libNinePatch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D389363215A6D3C500A3A3AA /* libNinePatch.a */; };
D389363915A6D53200A3A3AA /* chat_bubble_incoming.9.png in Resources */ = {isa = PBXBuildFile; fileRef = D389363715A6D53200A3A3AA /* chat_bubble_incoming.9.png */; };
D389363A15A6D53200A3A3AA /* chat_bubble_incoming.9.png in Resources */ = {isa = PBXBuildFile; fileRef = D389363715A6D53200A3A3AA /* chat_bubble_incoming.9.png */; };
D389363B15A6D53200A3A3AA /* chat_bubble_outgoing.9.png in Resources */ = {isa = PBXBuildFile; fileRef = D389363815A6D53200A3A3AA /* chat_bubble_outgoing.9.png */; };
D389363C15A6D53200A3A3AA /* chat_bubble_outgoing.9.png in Resources */ = {isa = PBXBuildFile; fileRef = D389363815A6D53200A3A3AA /* chat_bubble_outgoing.9.png */; };
D38D14AF15A30B3D008497E8 /* cell_call_first_hightlight.png in Resources */ = {isa = PBXBuildFile; fileRef = D38D14AD15A30B3D008497E8 /* cell_call_first_hightlight.png */; };
D38D14B015A30B3D008497E8 /* cell_call_first_hightlight.png in Resources */ = {isa = PBXBuildFile; fileRef = D38D14AD15A30B3D008497E8 /* cell_call_first_hightlight.png */; };
D38D14B115A30B3D008497E8 /* cell_call_hightlight.png in Resources */ = {isa = PBXBuildFile; fileRef = D38D14AE15A30B3D008497E8 /* cell_call_hightlight.png */; };
@ -432,6 +437,20 @@
D3A55FBD15877E5E003FD403 /* UIContactCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D3A55FBB15877E5E003FD403 /* UIContactCell.m */; };
D3A55FBF15877E69003FD403 /* UIContactCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3A55FBE15877E69003FD403 /* UIContactCell.xib */; };
D3A55FC015877E69003FD403 /* UIContactCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3A55FBE15877E69003FD403 /* UIContactCell.xib */; };
D3A8BB7015A6C7D500F96BE5 /* UIChatRoomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D3A8BB6F15A6C7D500F96BE5 /* UIChatRoomCell.m */; };
D3A8BB7115A6C7D500F96BE5 /* UIChatRoomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D3A8BB6F15A6C7D500F96BE5 /* UIChatRoomCell.m */; };
D3A8BB7415A6C81A00F96BE5 /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7315A6C81A00F96BE5 /* UIChatRoomCell.xib */; };
D3A8BB7515A6C81A00F96BE5 /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7315A6C81A00F96BE5 /* UIChatRoomCell.xib */; };
D3A8BB7B15A6CC3200F96BE5 /* chat_bubble_outgoing.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7615A6CC3200F96BE5 /* chat_bubble_outgoing.png */; };
D3A8BB7C15A6CC3200F96BE5 /* chat_bubble_outgoing.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7615A6CC3200F96BE5 /* chat_bubble_outgoing.png */; };
D3A8BB7D15A6CC3200F96BE5 /* chat_bubble_incoming.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7715A6CC3200F96BE5 /* chat_bubble_incoming.png */; };
D3A8BB7E15A6CC3200F96BE5 /* chat_bubble_incoming.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7715A6CC3200F96BE5 /* chat_bubble_incoming.png */; };
D3A8BB7F15A6CC3200F96BE5 /* setup_back_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7815A6CC3200F96BE5 /* setup_back_disabled.png */; };
D3A8BB8015A6CC3200F96BE5 /* setup_back_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7815A6CC3200F96BE5 /* setup_back_disabled.png */; };
D3A8BB8115A6CC3200F96BE5 /* setup_cancel_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7915A6CC3200F96BE5 /* setup_cancel_disabled.png */; };
D3A8BB8215A6CC3200F96BE5 /* setup_cancel_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7915A6CC3200F96BE5 /* setup_cancel_disabled.png */; };
D3A8BB8315A6CC3200F96BE5 /* setup_start_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7A15A6CC3200F96BE5 /* setup_start_disabled.png */; };
D3A8BB8415A6CC3200F96BE5 /* setup_start_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3A8BB7A15A6CC3200F96BE5 /* setup_start_disabled.png */; };
D3B9A3DF15A58C450096EA4E /* chat_field.png in Resources */ = {isa = PBXBuildFile; fileRef = D3B9A3DA15A58C440096EA4E /* chat_field.png */; };
D3B9A3E015A58C450096EA4E /* chat_field.png in Resources */ = {isa = PBXBuildFile; fileRef = D3B9A3DA15A58C440096EA4E /* chat_field.png */; };
D3B9A3E115A58C450096EA4E /* chat_ok_default.png in Resources */ = {isa = PBXBuildFile; fileRef = D3B9A3DB15A58C440096EA4E /* chat_ok_default.png */; };
@ -448,6 +467,12 @@
D3C2815315A2D64A0098AA42 /* numpad_star_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D3C2815115A2D64A0098AA42 /* numpad_star_over.png */; };
D3C714B3159DB84400705B8E /* toy-mono.wav in Resources */ = {isa = PBXBuildFile; fileRef = D3C714B2159DB84400705B8E /* toy-mono.wav */; };
D3C714B4159DB84400705B8E /* toy-mono.wav in Resources */ = {isa = PBXBuildFile; fileRef = D3C714B2159DB84400705B8E /* toy-mono.wav */; };
D3D14E7715A70EE30074A527 /* UIChatRoomHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D14E7515A70EE20074A527 /* UIChatRoomHeader.m */; };
D3D14E7815A70EE30074A527 /* UIChatRoomHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D14E7515A70EE20074A527 /* UIChatRoomHeader.m */; };
D3D14E7915A70EE30074A527 /* UIChatRoomHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3D14E7615A70EE30074A527 /* UIChatRoomHeader.xib */; };
D3D14E7A15A70EE30074A527 /* UIChatRoomHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = D3D14E7615A70EE30074A527 /* UIChatRoomHeader.xib */; };
D3D14E7C15A711700074A527 /* avatar_shadow_small.png in Resources */ = {isa = PBXBuildFile; fileRef = D3D14E7B15A711700074A527 /* avatar_shadow_small.png */; };
D3D14E7D15A711700074A527 /* avatar_shadow_small.png in Resources */ = {isa = PBXBuildFile; fileRef = D3D14E7B15A711700074A527 /* avatar_shadow_small.png */; };
D3D6A39E159B0EEF005F692C /* add_call_default.png in Resources */ = {isa = PBXBuildFile; fileRef = D3D6A39B159B0EEF005F692C /* add_call_default.png */; };
D3D6A39F159B0EEF005F692C /* add_call_default.png in Resources */ = {isa = PBXBuildFile; fileRef = D3D6A39B159B0EEF005F692C /* add_call_default.png */; };
D3D6A3A0159B0EEF005F692C /* add_call_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D3D6A39C159B0EEF005F692C /* add_call_disabled.png */; };
@ -654,6 +679,23 @@
F476004C147AAF4600FFF19B /* libmediastreamer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2211DB8F147555C800DEE054 /* libmediastreamer.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D389363115A6D3C500A3A3AA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D389362A15A6D3C500A3A3AA /* NinePatch.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = D2AAC07E0554694100DB518D;
remoteInfo = NinePatch;
};
D389363315A6D3EB00A3A3AA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D389362A15A6D3C500A3A3AA /* NinePatch.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = D2AAC07D0554694100DB518D;
remoteInfo = NinePatch;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
2247673A129C3B9C002B94B4 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
@ -994,10 +1036,6 @@
D32409C2158B49A600C8C119 /* UILongTouchButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UILongTouchButton.m; sourceTree = "<group>"; };
D32460E4159D9AAD00BA7F3A /* UIPassView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIPassView.h; sourceTree = "<group>"; };
D32460E5159D9AAD00BA7F3A /* UIPassView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIPassView.m; sourceTree = "<group>"; };
D32460E9159DA47700BA7F3A /* CPAnimationSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPAnimationSequence.h; path = Utils/CPAnimationSequence.h; sourceTree = "<group>"; };
D32460EA159DA47700BA7F3A /* CPAnimationSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPAnimationSequence.m; path = Utils/CPAnimationSequence.m; sourceTree = "<group>"; };
D32460EB159DA47700BA7F3A /* CPAnimationStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPAnimationStep.h; path = Utils/CPAnimationStep.h; sourceTree = "<group>"; };
D32460EC159DA47700BA7F3A /* CPAnimationStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPAnimationStep.m; path = Utils/CPAnimationStep.m; sourceTree = "<group>"; };
D326483615887D5200930C67 /* OrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OrderedDictionary.h; path = Utils/OrderedDictionary.h; sourceTree = "<group>"; };
D326483715887D5200930C67 /* OrderedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OrderedDictionary.m; path = Utils/OrderedDictionary.m; sourceTree = "<group>"; };
D326483B1588950F00930C67 /* UICallBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UICallBar.h; sourceTree = "<group>"; };
@ -1011,7 +1049,7 @@
D32B6E2815A5BC430033019F /* ChatRoomTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChatRoomTableViewController.m; sourceTree = "<group>"; };
D32B6E2B15A5C0800033019F /* database.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; name = database.sqlite; path = Resources/database.sqlite; sourceTree = "<group>"; };
D32B6E2E15A5C0AC0033019F /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
D32B6E3615A5C2430033019F /* ChatModel.h */ = {isa = PBXFileReference; fileEncoding = 4; name = ChatModel.h; path = Model/ChatModel.h; sourceTree = "<group>"; };
D32B6E3615A5C2430033019F /* ChatModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChatModel.h; path = Model/ChatModel.h; sourceTree = "<group>"; };
D32B6E3715A5C2430033019F /* ChatModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ChatModel.m; path = Model/ChatModel.m; sourceTree = "<group>"; };
D32B9DFA15A2F131000B6DEC /* FastAddressBook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FastAddressBook.h; path = Utils/FastAddressBook.h; sourceTree = "<group>"; };
D32B9DFB15A2F131000B6DEC /* FastAddressBook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FastAddressBook.m; path = Utils/FastAddressBook.m; sourceTree = "<group>"; };
@ -1144,11 +1182,26 @@
D38327FD158100E400FA0D23 /* history_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = history_over.png; path = Resources/history_over.png; sourceTree = "<group>"; };
D38327FE158100E400FA0D23 /* settings_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = settings_over.png; path = Resources/settings_over.png; sourceTree = "<group>"; };
D38327FF158100E400FA0D23 /* chat_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_over.png; path = Resources/chat_over.png; sourceTree = "<group>"; };
D389362215A6D19800A3A3AA /* CPAnimationSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPAnimationSequence.h; path = Utils/CPAnimation/CPAnimationSequence.h; sourceTree = "<group>"; };
D389362315A6D19800A3A3AA /* CPAnimationSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPAnimationSequence.m; path = Utils/CPAnimation/CPAnimationSequence.m; sourceTree = "<group>"; };
D389362415A6D19800A3A3AA /* CPAnimationStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPAnimationStep.h; path = Utils/CPAnimation/CPAnimationStep.h; sourceTree = "<group>"; };
D389362515A6D19800A3A3AA /* CPAnimationStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPAnimationStep.m; path = Utils/CPAnimation/CPAnimationStep.m; sourceTree = "<group>"; };
D389362A15A6D3C500A3A3AA /* NinePatch.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NinePatch.xcodeproj; path = NinePatch/NinePatch.xcodeproj; sourceTree = "<group>"; };
D389363715A6D53200A3A3AA /* chat_bubble_incoming.9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_bubble_incoming.9.png; path = Resources/chat_bubble_incoming.9.png; sourceTree = "<group>"; };
D389363815A6D53200A3A3AA /* chat_bubble_outgoing.9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_bubble_outgoing.9.png; path = Resources/chat_bubble_outgoing.9.png; sourceTree = "<group>"; };
D38D14AD15A30B3D008497E8 /* cell_call_first_hightlight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = cell_call_first_hightlight.png; path = Resources/cell_call_first_hightlight.png; sourceTree = "<group>"; };
D38D14AE15A30B3D008497E8 /* cell_call_hightlight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = cell_call_hightlight.png; path = Resources/cell_call_hightlight.png; sourceTree = "<group>"; };
D3A55FBA15877E5E003FD403 /* UIContactCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIContactCell.h; sourceTree = "<group>"; };
D3A55FBB15877E5E003FD403 /* UIContactCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIContactCell.m; sourceTree = "<group>"; };
D3A55FBE15877E69003FD403 /* UIContactCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UIContactCell.xib; sourceTree = "<group>"; };
D3A8BB6E15A6C7D500F96BE5 /* UIChatRoomCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIChatRoomCell.h; sourceTree = "<group>"; };
D3A8BB6F15A6C7D500F96BE5 /* UIChatRoomCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIChatRoomCell.m; sourceTree = "<group>"; };
D3A8BB7315A6C81A00F96BE5 /* UIChatRoomCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UIChatRoomCell.xib; sourceTree = "<group>"; };
D3A8BB7615A6CC3200F96BE5 /* chat_bubble_outgoing.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_bubble_outgoing.png; path = Resources/chat_bubble_outgoing.png; sourceTree = "<group>"; };
D3A8BB7715A6CC3200F96BE5 /* chat_bubble_incoming.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_bubble_incoming.png; path = Resources/chat_bubble_incoming.png; sourceTree = "<group>"; };
D3A8BB7815A6CC3200F96BE5 /* setup_back_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = setup_back_disabled.png; path = Resources/setup_back_disabled.png; sourceTree = "<group>"; };
D3A8BB7915A6CC3200F96BE5 /* setup_cancel_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = setup_cancel_disabled.png; path = Resources/setup_cancel_disabled.png; sourceTree = "<group>"; };
D3A8BB7A15A6CC3200F96BE5 /* setup_start_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = setup_start_disabled.png; path = Resources/setup_start_disabled.png; sourceTree = "<group>"; };
D3B9A3DA15A58C440096EA4E /* chat_field.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_field.png; path = Resources/chat_field.png; sourceTree = "<group>"; };
D3B9A3DB15A58C440096EA4E /* chat_ok_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_ok_default.png; path = Resources/chat_ok_default.png; sourceTree = "<group>"; };
D3B9A3DC15A58C440096EA4E /* chat_ok_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = chat_ok_over.png; path = Resources/chat_ok_over.png; sourceTree = "<group>"; };
@ -1157,6 +1210,10 @@
D3C2814A15A2D38D0098AA42 /* dialer_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dialer_selected.png; path = Resources/dialer_selected.png; sourceTree = "<group>"; };
D3C2815115A2D64A0098AA42 /* numpad_star_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = numpad_star_over.png; path = Resources/numpad_star_over.png; sourceTree = "<group>"; };
D3C714B2159DB84400705B8E /* toy-mono.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = "toy-mono.wav"; path = "Resources/toy-mono.wav"; sourceTree = "<group>"; };
D3D14E7415A70EE20074A527 /* UIChatRoomHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIChatRoomHeader.h; sourceTree = "<group>"; };
D3D14E7515A70EE20074A527 /* UIChatRoomHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIChatRoomHeader.m; sourceTree = "<group>"; };
D3D14E7615A70EE30074A527 /* UIChatRoomHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UIChatRoomHeader.xib; sourceTree = "<group>"; };
D3D14E7B15A711700074A527 /* avatar_shadow_small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = avatar_shadow_small.png; path = Resources/avatar_shadow_small.png; sourceTree = "<group>"; };
D3D6A39B159B0EEF005F692C /* add_call_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = add_call_default.png; path = Resources/add_call_default.png; sourceTree = "<group>"; };
D3D6A39C159B0EEF005F692C /* add_call_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = add_call_disabled.png; path = Resources/add_call_disabled.png; sourceTree = "<group>"; };
D3D6A39D159B0EEF005F692C /* add_call_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = add_call_over.png; path = Resources/add_call_over.png; sourceTree = "<group>"; };
@ -1277,6 +1334,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D389363515A6D40000A3A3AA /* libNinePatch.a in Frameworks */,
D32B6E2F15A5C0AC0033019F /* libsqlite3.dylib in Frameworks */,
D37DC7181594AF3400B2A5EB /* MessageUI.framework in Frameworks */,
340751971506459A00B89C47 /* CoreTelephony.framework in Frameworks */,
@ -1376,7 +1434,6 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
D32B6E3515A5C2200033019F /* Model */,
340751E4150E4D0200B89C47 /* CallDelegate.h */,
2211DBBB14769C8200DEE054 /* CallDelegate.m */,
D32B6E2715A5BC430033019F /* ChatRoomTableViewController.h */,
@ -1425,6 +1482,7 @@
D3EA53FB159850E80037DC6B /* LinphoneManager.h */,
D3EA53FC159850E80037DC6B /* LinphoneManager.m */,
2214EB7012F84668002A5394 /* LinphoneUI */,
D32B6E3515A5C2200033019F /* Model */,
22E0A81D111C44E100B04932 /* MoreViewController.h */,
22E0A81C111C44E100B04932 /* MoreViewController.m */,
22E0A81B111C44E100B04932 /* MoreViewController.xib */,
@ -1671,6 +1729,12 @@
D3EA540F159853750037DC6B /* UIChatCell.h */,
D3EA5410159853750037DC6B /* UIChatCell.m */,
D3EA5413159853C90037DC6B /* UIChatCell.xib */,
D3A8BB6E15A6C7D500F96BE5 /* UIChatRoomCell.h */,
D3A8BB6F15A6C7D500F96BE5 /* UIChatRoomCell.m */,
D3A8BB7315A6C81A00F96BE5 /* UIChatRoomCell.xib */,
D3D14E7415A70EE20074A527 /* UIChatRoomHeader.h */,
D3D14E7515A70EE20074A527 /* UIChatRoomHeader.m */,
D3D14E7615A70EE30074A527 /* UIChatRoomHeader.xib */,
D31B4B1E159876C0002E6C72 /* UICompositeViewController.h */,
D31B4B1F159876C0002E6C72 /* UICompositeViewController.m */,
D31B4B20159876C0002E6C72 /* UICompositeViewController.xib */,
@ -1709,10 +1773,10 @@
D35498201587716B000081D8 /* UIStateBar.xib */,
D32648421588F6FA00930C67 /* UIToggleButton.h */,
D32648431588F6FB00930C67 /* UIToggleButton.m */,
340751E5150F38FC00B89C47 /* UIVideoButton.h */,
340751E6150F38FD00B89C47 /* UIVideoButton.m */,
D3196D3C15A32BD7007FEEBA /* UITransferButton.h */,
D3196D3D15A32BD8007FEEBA /* UITransferButton.m */,
340751E5150F38FC00B89C47 /* UIVideoButton.h */,
340751E6150F38FD00B89C47 /* UIVideoButton.m */,
);
path = LinphoneUI;
sourceTree = "<group>";
@ -1798,7 +1862,6 @@
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
isa = PBXGroup;
children = (
D32B6E2E15A5C0AC0033019F /* libsqlite3.dylib */,
2258633C11410BAC00C5A737 /* README */,
22276E8013C73D3100210156 /* libavcodec.a */,
22276E8113C73D3100210156 /* libavutil.a */,
@ -1830,6 +1893,7 @@
344ABDE71484E723007420B6 /* libzrtpcpp.a */,
344ABDEF14850AE9007420B6 /* libc++.1.dylib */,
22D1B68012A3E0BE001AE361 /* libresolv.dylib */,
D32B6E2E15A5C0AC0033019F /* libsqlite3.dylib */,
344ABDF014850AE9007420B6 /* libstdc++.6.dylib */,
22B5F03410CE6B2F00777D97 /* AddressBook.framework */,
22B5EFA210CE50BD00777D97 /* AddressBookUI.framework */,
@ -1847,6 +1911,7 @@
22744043106F33FC006EC466 /* Security.framework */,
2264B6D111200342002C2C53 /* SystemConfiguration.framework */,
22F51EF5107FA66500F98953 /* untitled.plist */,
D389362A15A6D3C500A3A3AA /* NinePatch.xcodeproj */,
080E96DDFE201D6D7F000001 /* Classes */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
D37DC6C31594AE5600B2A5EB /* InAppSettingsKit */,
@ -1873,6 +1938,7 @@
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
D3D14E7B15A711700074A527 /* avatar_shadow_small.png */,
D3F83F741582253100336684 /* accept_default.png */,
D3F83F751582253100336684 /* accept_over.png */,
D3D6A39B159B0EEF005F692C /* add_call_default.png */,
@ -1921,6 +1987,10 @@
D3EA5402159852080037DC6B /* chat_add_over.png */,
D3F795DB15A5831C0077328B /* chat_back_default.png */,
D3F795DC15A5831C0077328B /* chat_back_over.png */,
D389363715A6D53200A3A3AA /* chat_bubble_incoming.9.png */,
D3A8BB7715A6CC3200F96BE5 /* chat_bubble_incoming.png */,
D389363815A6D53200A3A3AA /* chat_bubble_outgoing.9.png */,
D3A8BB7615A6CC3200F96BE5 /* chat_bubble_outgoing.png */,
D38327F11580FE3A00FA0D23 /* chat_default.png */,
D3EA53FF159852080037DC6B /* chat_edit_default.png */,
D3EA5400159852080037DC6B /* chat_edit_over.png */,
@ -2035,11 +2105,14 @@
D38327FE158100E400FA0D23 /* settings_over.png */,
D38327F01580FE3A00FA0D23 /* settings_selected.png */,
D350F21315A43D3400149E54 /* setup_back_default.png */,
D3A8BB7815A6CC3200F96BE5 /* setup_back_disabled.png */,
D350F21415A43D3400149E54 /* setup_back_over.png */,
D350F21515A43D3400149E54 /* setup_cancel_default.png */,
D3A8BB7915A6CC3200F96BE5 /* setup_cancel_disabled.png */,
D350F21615A43D3400149E54 /* setup_cancel_over.png */,
D350F21715A43D3400149E54 /* setup_label.png */,
D350F21815A43D3400149E54 /* setup_start_default.png */,
D3A8BB7A15A6CC3200F96BE5 /* setup_start_disabled.png */,
D350F21915A43D3400149E54 /* setup_start_over.png */,
D350F21A15A43D3400149E54 /* setup_title_assistant.png */,
D350F21B15A43D3400149E54 /* setup_welcome_logo.png */,
@ -2076,12 +2149,9 @@
D326483415887D4400930C67 /* Utils */ = {
isa = PBXGroup;
children = (
D38935F715A6D06800A3A3AA /* CPAnimation */,
D3F26BEA159869A6005F9CAB /* AbstractCall.h */,
D3F26BEB159869A6005F9CAB /* AbstractCall.m */,
D32460E9159DA47700BA7F3A /* CPAnimationSequence.h */,
D32460EA159DA47700BA7F3A /* CPAnimationSequence.m */,
D32460EB159DA47700BA7F3A /* CPAnimationStep.h */,
D32460EC159DA47700BA7F3A /* CPAnimationStep.m */,
D32B9DFA15A2F131000B6DEC /* FastAddressBook.h */,
D32B9DFB15A2F131000B6DEC /* FastAddressBook.m */,
D326483615887D5200930C67 /* OrderedDictionary.h */,
@ -2179,6 +2249,25 @@
path = InAppSettingsKit/Xibs;
sourceTree = "<group>";
};
D38935F715A6D06800A3A3AA /* CPAnimation */ = {
isa = PBXGroup;
children = (
D389362215A6D19800A3A3AA /* CPAnimationSequence.h */,
D389362315A6D19800A3A3AA /* CPAnimationSequence.m */,
D389362415A6D19800A3A3AA /* CPAnimationStep.h */,
D389362515A6D19800A3A3AA /* CPAnimationStep.m */,
);
name = CPAnimation;
sourceTree = "<group>";
};
D389362B15A6D3C500A3A3AA /* Products */ = {
isa = PBXGroup;
children = (
D389363215A6D3C500A3A3AA /* libNinePatch.a */,
);
name = Products;
sourceTree = "<group>";
};
D398D3031594B0FB00FD553C /* Settings */ = {
isa = PBXGroup;
children = (
@ -2202,6 +2291,7 @@
buildRules = (
);
dependencies = (
D389363415A6D3EB00A3A3AA /* PBXTargetDependency */,
);
name = linphone;
productName = linphone;
@ -2247,6 +2337,12 @@
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = D389362B15A6D3C500A3A3AA /* Products */;
ProjectRef = D389362A15A6D3C500A3A3AA /* NinePatch.xcodeproj */;
},
);
projectRoot = "";
targets = (
1D6058900D05DD3D006BFB54 /* linphone */,
@ -2255,6 +2351,16 @@
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
D389363215A6D3C500A3A3AA /* libNinePatch.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libNinePatch.a;
remoteRef = D389363115A6D3C500A3A3AA /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
1D60588D0D05DD3D006BFB54 /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -2479,6 +2585,16 @@
D3B9A3E715A58C450096EA4E /* chat_send_over.png in Resources */,
D32B6E2415A5B2020033019F /* chat_send_disabled.png in Resources */,
D32B6E2C15A5C0800033019F /* database.sqlite in Resources */,
D3A8BB7415A6C81A00F96BE5 /* UIChatRoomCell.xib in Resources */,
D3A8BB7B15A6CC3200F96BE5 /* chat_bubble_outgoing.png in Resources */,
D3A8BB7D15A6CC3200F96BE5 /* chat_bubble_incoming.png in Resources */,
D3A8BB7F15A6CC3200F96BE5 /* setup_back_disabled.png in Resources */,
D3A8BB8115A6CC3200F96BE5 /* setup_cancel_disabled.png in Resources */,
D3A8BB8315A6CC3200F96BE5 /* setup_start_disabled.png in Resources */,
D389363915A6D53200A3A3AA /* chat_bubble_incoming.9.png in Resources */,
D389363B15A6D53200A3A3AA /* chat_bubble_outgoing.9.png in Resources */,
D3D14E7915A70EE30074A527 /* UIChatRoomHeader.xib in Resources */,
D3D14E7C15A711700074A527 /* avatar_shadow_small.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2689,6 +2805,16 @@
D3B9A3E815A58C450096EA4E /* chat_send_over.png in Resources */,
D32B6E2515A5B2020033019F /* chat_send_disabled.png in Resources */,
D32B6E2D15A5C0800033019F /* database.sqlite in Resources */,
D3A8BB7515A6C81A00F96BE5 /* UIChatRoomCell.xib in Resources */,
D3A8BB7C15A6CC3200F96BE5 /* chat_bubble_outgoing.png in Resources */,
D3A8BB7E15A6CC3200F96BE5 /* chat_bubble_incoming.png in Resources */,
D3A8BB8015A6CC3200F96BE5 /* setup_back_disabled.png in Resources */,
D3A8BB8215A6CC3200F96BE5 /* setup_cancel_disabled.png in Resources */,
D3A8BB8415A6CC3200F96BE5 /* setup_start_disabled.png in Resources */,
D389363A15A6D53200A3A3AA /* chat_bubble_incoming.9.png in Resources */,
D389363C15A6D53200A3A3AA /* chat_bubble_outgoing.9.png in Resources */,
D3D14E7A15A70EE30074A527 /* UIChatRoomHeader.xib in Resources */,
D3D14E7D15A711700074A527 /* avatar_shadow_small.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2761,14 +2887,16 @@
D31AAF5E159B3919002C6B02 /* InCallTableViewController.m in Sources */,
D3211BB0159C4EF10098460B /* UIConferenceHeader.m in Sources */,
D32460E6159D9AAD00BA7F3A /* UIPassView.m in Sources */,
D32460ED159DA47700BA7F3A /* CPAnimationSequence.m in Sources */,
D32460EF159DA47700BA7F3A /* CPAnimationStep.m in Sources */,
D32B9DFC15A2F131000B6DEC /* FastAddressBook.m in Sources */,
D3196D3E15A32BD8007FEEBA /* UITransferButton.m in Sources */,
D350F20E15A43BB100149E54 /* WizardViewController.m in Sources */,
D3F795D615A582810077328B /* ChatRoomViewController.m in Sources */,
D32B6E2915A5BC440033019F /* ChatRoomTableViewController.m in Sources */,
D32B6E3815A5C2430033019F /* ChatModel.m in Sources */,
D3A8BB7015A6C7D500F96BE5 /* UIChatRoomCell.m in Sources */,
D389362615A6D19800A3A3AA /* CPAnimationSequence.m in Sources */,
D389362815A6D19800A3A3AA /* CPAnimationStep.m in Sources */,
D3D14E7715A70EE30074A527 /* UIChatRoomHeader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2838,19 +2966,29 @@
D31AAF5F159B3919002C6B02 /* InCallTableViewController.m in Sources */,
D3211BB1159C4EF10098460B /* UIConferenceHeader.m in Sources */,
D32460E7159D9AAD00BA7F3A /* UIPassView.m in Sources */,
D32460EE159DA47700BA7F3A /* CPAnimationSequence.m in Sources */,
D32460F0159DA47700BA7F3A /* CPAnimationStep.m in Sources */,
D32B9DFD15A2F131000B6DEC /* FastAddressBook.m in Sources */,
D3196D3F15A32BD8007FEEBA /* UITransferButton.m in Sources */,
D350F20F15A43BB100149E54 /* WizardViewController.m in Sources */,
D3F795D715A582810077328B /* ChatRoomViewController.m in Sources */,
D32B6E2A15A5BC440033019F /* ChatRoomTableViewController.m in Sources */,
D32B6E3915A5C2430033019F /* ChatModel.m in Sources */,
D3A8BB7115A6C7D500F96BE5 /* UIChatRoomCell.m in Sources */,
D389362715A6D19800A3A3AA /* CPAnimationSequence.m in Sources */,
D389362915A6D19800A3A3AA /* CPAnimationStep.m in Sources */,
D3D14E7815A70EE30074A527 /* UIChatRoomHeader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D389363415A6D3EB00A3A3AA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = NinePatch;
targetProxy = D389363315A6D3EB00A3A3AA /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
2214783B1386A2030020F8B8 /* Localizable.strings */ = {
isa = PBXVariantGroup;
@ -2894,6 +3032,7 @@
submodules/externals/osip/include,
submodules/externals/exosip/include,
submodules/externals/speex/include,
"NinePatch//**",
);
INFOPLIST_FILE = "linphone-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
@ -2903,9 +3042,14 @@
"\"$(SRCROOT)/liblinphone-sdk/apple-darwin/lib\"",
);
ORDER_FILE = "";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = (
"-force_load",
"$(BUILT_PRODUCTS_DIR)/libNinePatch.a",
"-Objc",
);
PRODUCT_NAME = linphone;
SDKROOT = iphoneos;
SKIP_INSTALL = NO;
STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -2960,6 +3104,7 @@
submodules/externals/osip/include,
submodules/externals/exosip/include,
submodules/externals/speex/include,
"NinePatch//**",
);
INFOPLIST_FILE = "linphone-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
@ -2969,9 +3114,14 @@
"\"$(SRCROOT)/liblinphone-sdk/apple-darwin/lib\"",
);
ORDER_FILE = "";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = (
"-force_load",
"$(BUILT_PRODUCTS_DIR)/libNinePatch.a",
"-Objc",
);
PRODUCT_NAME = linphone;
SDKROOT = iphoneos;
SKIP_INSTALL = NO;
STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -3236,6 +3386,7 @@
submodules/externals/osip/include,
submodules/externals/exosip/include,
submodules/externals/speex/include,
"NinePatch//**",
);
INFOPLIST_FILE = "linphone-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
@ -3245,10 +3396,15 @@
"\"$(SRCROOT)/liblinphone-sdk/apple-darwin/lib\"",
);
ORDER_FILE = "";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = (
"-force_load",
"$(BUILT_PRODUCTS_DIR)/libNinePatch.a",
"-Objc",
);
PRODUCT_NAME = linphone;
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
SKIP_INSTALL = NO;
STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -3303,6 +3459,7 @@
submodules/externals/osip/include,
submodules/externals/exosip/include,
submodules/externals/speex/include,
"NinePatch//**",
);
INFOPLIST_FILE = "linphone-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
@ -3312,9 +3469,14 @@
"\"$(SRCROOT)/liblinphone-sdk/apple-darwin/lib\"",
);
ORDER_FILE = "";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = (
"-force_load",
"$(BUILT_PRODUCTS_DIR)/libNinePatch.a",
"-Objc",
);
PRODUCT_NAME = linphone;
SDKROOT = iphoneos;
SKIP_INSTALL = NO;
STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic;
TARGETED_DEVICE_FAMILY = "1,2";
};