diff options
| author | Teddy Wing | 2012-09-29 16:15:01 -0400 |
|---|---|---|
| committer | Teddy Wing | 2012-09-29 16:15:01 -0400 |
| commit | 033f9053ada0a7f2a9ef7e6652746cd3cbb8f300 (patch) | |
| tree | ee0a8c2127d189098e18e0078418359d40e41759 | |
| parent | d02256dc49356e6dc1769cc0fb4737a7f013cbed (diff) | |
| download | babblr-iOS-033f9053ada0a7f2a9ef7e6652746cd3cbb8f300.tar.bz2 | |
Integrated multi-line SMS-style text box for chat pane. Added a tableView for chat messages.
20 files changed, 1261 insertions, 3 deletions
diff --git a/Classes/ChatViewController.h b/Classes/ChatViewController.h new file mode 100644 index 0000000..ee52715 --- /dev/null +++ b/Classes/ChatViewController.h @@ -0,0 +1,23 @@ +// +// ChatViewController.h +// NearMe +// +// Created by TW on 9/29/12. +// Copyright 2012 __MyCompanyName__. All rights reserved. +// + +#import <UIKit/UIKit.h> +#import "HPGrowingTextView.h" + + +@interface ChatViewController : UIViewController <HPGrowingTextViewDelegate, UITableViewDelegate, UITableViewDataSource> { + UITableView *chatTableView; + UIView *containerView; + HPGrowingTextView *textView; +} + +@property (nonatomic, retain) UITableView *chatTableView; + +-(void)resignTextView; + +@end diff --git a/Classes/ChatViewController.m b/Classes/ChatViewController.m new file mode 100644 index 0000000..aee79c8 --- /dev/null +++ b/Classes/ChatViewController.m @@ -0,0 +1,210 @@ +// +// ChatViewController.m +// NearMe +// +// Created by TW on 9/29/12. +// Copyright 2012 __MyCompanyName__. All rights reserved. +// + +#import "ChatViewController.h" + + +@implementation ChatViewController + +@synthesize chatTableView = _chatTableView; + +-(id)init +{ + self = [super init]; + if(self){ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; + } + + return self; +} + + + +// Implement loadView to create a view hierarchy programmatically, without using a nib. +- (void)loadView { + self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]; + self.view.backgroundColor = [UIColor colorWithRed:219.0f/255.0f green:226.0f/255.0f blue:237.0f/255.0f alpha:1]; + + chatTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; + [self.view addSubview:chatTableView]; + + containerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 40, 320, 40)]; + + textView = [[HPGrowingTextView alloc] initWithFrame:CGRectMake(6, 3, 240, 40)]; + textView.contentInset = UIEdgeInsetsMake(0, 5, 0, 5); + + textView.minNumberOfLines = 1; + textView.maxNumberOfLines = 6; + textView.returnKeyType = UIReturnKeyGo; //just as an example + textView.font = [UIFont systemFontOfSize:15.0f]; + textView.delegate = self; + textView.internalTextView.scrollIndicatorInsets = UIEdgeInsetsMake(5, 0, 5, 0); + textView.backgroundColor = [UIColor whiteColor]; + + // textView.text = @"test\n\ntest"; + // textView.animateHeightChange = NO; //turns off animation + + [self.view addSubview:containerView]; + + UIImage *rawEntryBackground = [UIImage imageNamed:@"MessageEntryInputField.png"]; + UIImage *entryBackground = [rawEntryBackground stretchableImageWithLeftCapWidth:13 topCapHeight:22]; + UIImageView *entryImageView = [[[UIImageView alloc] initWithImage:entryBackground] autorelease]; + entryImageView.frame = CGRectMake(5, 0, 248, 40); + entryImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + UIImage *rawBackground = [UIImage imageNamed:@"MessageEntryBackground.png"]; + UIImage *background = [rawBackground stretchableImageWithLeftCapWidth:13 topCapHeight:22]; + UIImageView *imageView = [[[UIImageView alloc] initWithImage:background] autorelease]; + imageView.frame = CGRectMake(0, 0, containerView.frame.size.width, containerView.frame.size.height); + imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + textView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + // view hierachy + [containerView addSubview:imageView]; + [containerView addSubview:textView]; + [containerView addSubview:entryImageView]; + + UIImage *sendBtnBackground = [[UIImage imageNamed:@"MessageEntrySendButton.png"] stretchableImageWithLeftCapWidth:13 topCapHeight:0]; + UIImage *selectedSendBtnBackground = [[UIImage imageNamed:@"MessageEntrySendButton.png"] stretchableImageWithLeftCapWidth:13 topCapHeight:0]; + + UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + doneBtn.frame = CGRectMake(containerView.frame.size.width - 69, 8, 63, 27); + doneBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin; + [doneBtn setTitle:@"Done" forState:UIControlStateNormal]; + + [doneBtn setTitleShadowColor:[UIColor colorWithWhite:0 alpha:0.4] forState:UIControlStateNormal]; + doneBtn.titleLabel.shadowOffset = CGSizeMake (0.0, -1.0); + doneBtn.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f]; + + [doneBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [doneBtn addTarget:self action:@selector(resignTextView) forControlEvents:UIControlEventTouchUpInside]; + [doneBtn setBackgroundImage:sendBtnBackground forState:UIControlStateNormal]; + [doneBtn setBackgroundImage:selectedSendBtnBackground forState:UIControlStateSelected]; + [containerView addSubview:doneBtn]; + containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; +} + +-(void)resignTextView +{ + [textView resignFirstResponder]; +} + +//Code from Brett Schumann +-(void) keyboardWillShow:(NSNotification *)note{ + // get keyboard size and loctaion + CGRect keyboardBounds; + [[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds]; + NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; + NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey]; + + // Need to translate the bounds to account for rotation. + keyboardBounds = [self.view convertRect:keyboardBounds toView:nil]; + + // get a rect for the textView frame + CGRect containerFrame = containerView.frame; + containerFrame.origin.y = self.view.bounds.size.height - (keyboardBounds.size.height + containerFrame.size.height); + // animations settings + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationDuration:[duration doubleValue]]; + [UIView setAnimationCurve:[curve intValue]]; + + // set views with new info + containerView.frame = containerFrame; + + // commit animations + [UIView commitAnimations]; +} + +-(void) keyboardWillHide:(NSNotification *)note{ + NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; + NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey]; + + // get a rect for the textView frame + CGRect containerFrame = containerView.frame; + containerFrame.origin.y = self.view.bounds.size.height - containerFrame.size.height; + + // animations settings + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationDuration:[duration doubleValue]]; + [UIView setAnimationCurve:[curve intValue]]; + + // set views with new info + containerView.frame = containerFrame; + + // commit animations + [UIView commitAnimations]; +} + +- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height +{ + float diff = (growingTextView.frame.size.height - height); + + CGRect r = containerView.frame; + r.size.height -= diff; + r.origin.y += diff; + containerView.frame = r; +} + +-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +{ + return YES; +} + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + // Release any retained subviews of the main view. + // e.g. self.myOutlet = nil; +} + + +- (void)dealloc { + [chatTableView release]; + [textView release]; + [containerView release]; + [super dealloc]; +} + +# pragma mark UITableViewDelegate methods + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 5; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"ChatCell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; + } + + // Set up the cell... + NSString *cellValue = @"test"; + cell.textLabel.text = cellValue; + + return cell; +} + +@end diff --git a/Classes/ChatViewController.xib b/Classes/ChatViewController.xib new file mode 100644 index 0000000..909c93e --- /dev/null +++ b/Classes/ChatViewController.xib @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10"> + <data> + <int key="IBDocument.SystemTarget">784</int> + <string key="IBDocument.SystemVersion">10B500</string> + <string key="IBDocument.InterfaceBuilderVersion">732</string> + <string key="IBDocument.AppKitVersion">1038.2</string> + <string key="IBDocument.HIToolboxVersion">437.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> + <string key="NS.object.0">62</string> + </object> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="1"/> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys" id="0"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBProxyObject" id="372490531"> + <string key="IBProxiedObjectIdentifier">IBFilesOwner</string> + </object> + <object class="IBProxyObject" id="975951072"> + <string key="IBProxiedObjectIdentifier">IBFirstResponder</string> + </object> + <object class="IBUIView" id="191373211"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">274</int> + <string key="NSFrameSize">{320, 460}</string> + <reference key="NSSuperview"/> + <object class="NSColor" key="IBUIBackgroundColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + <object class="NSColorSpace" key="NSCustomColorSpace"> + <int key="NSID">2</int> + </object> + </object> + <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBCocoaTouchOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="372490531"/> + <reference key="destination" ref="191373211"/> + </object> + <int key="connectionID">3</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <reference key="object" ref="0"/> + <reference key="children" ref="1000"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">1</int> + <reference key="object" ref="191373211"/> + <reference key="parent" ref="0"/> + </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> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-1.CustomClassName</string> + <string>-2.CustomClassName</string> + <string>1.IBEditorWindowLastContentRect</string> + <string>1.IBPluginDependency</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>ChatViewController</string> + <string>UIResponder</string> + <string>{{556, 412}, {320, 480}}</string> + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="sourceID"/> + <int key="maxID">3</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">ChatViewController</string> + <string key="superclassName">UIViewController</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">ChatViewController.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string> + <integer value="3000" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <nil key="IBDocument.LastKnownRelativeProjectPath"/> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + <string key="IBCocoaTouchPluginVersion">3.1</string> + </data> +</archive> diff --git a/Classes/RootViewController.h b/Classes/RootViewController.h index 96d27bb..4125de9 100644 --- a/Classes/RootViewController.h +++ b/Classes/RootViewController.h @@ -9,7 +9,7 @@ #import <UIKit/UIKit.h> -@interface RootViewController : UIViewController { +@interface RootViewController : UIViewController <UIWebViewDelegate> { IBOutlet UIWebView *webView; } diff --git a/Classes/RootViewController.m b/Classes/RootViewController.m index 053242c..f647a5e 100644 --- a/Classes/RootViewController.m +++ b/Classes/RootViewController.m @@ -28,7 +28,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://google-developers.appspot.com/maps/documentation/javascript/examples/map-simple"]]]; + [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://google-developers.appspot.com/maps/documentation/javascript/examples/event-closure"]]]; } @@ -60,4 +60,16 @@ } +# pragma mark UIWebViewDelegate methods + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + if (navigationType == UIWebViewNavigationTypeLinkClicked) { + // Flip and open chat view + NSLog(@"UIWebView item clicked"); + } + + return YES; +} + + @end diff --git a/NearMe.xcodeproj/project.pbxproj b/NearMe.xcodeproj/project.pbxproj index ea7c93c..c9a22c2 100755 --- a/NearMe.xcodeproj/project.pbxproj +++ b/NearMe.xcodeproj/project.pbxproj @@ -17,6 +17,18 @@ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; D134D6E51617685C0098794B /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D134D6E31617685C0098794B /* RootViewController.m */; }; D134D6E61617685C0098794B /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D134D6E41617685C0098794B /* RootViewController.xib */; }; + D134D777161778790098794B /* ChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D134D775161778790098794B /* ChatViewController.m */; }; + D134D778161778790098794B /* ChatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D134D776161778790098794B /* ChatViewController.xib */; }; + D134D7D4161780390098794B /* HPGrowingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D134D7D1161780390098794B /* HPGrowingTextView.m */; }; + D134D7D5161780390098794B /* HPTextViewInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = D134D7D3161780390098794B /* HPTextViewInternal.m */; }; + D134D806161781F50098794B /* MessageEntryBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D7FE161781F50098794B /* MessageEntryBackground.png */; }; + D134D807161781F50098794B /* MessageEntryBackground@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D7FF161781F50098794B /* MessageEntryBackground@2x.png */; }; + D134D808161781F50098794B /* MessageEntryInputField.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D800161781F50098794B /* MessageEntryInputField.png */; }; + D134D809161781F50098794B /* MessageEntryInputField@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D801161781F50098794B /* MessageEntryInputField@2x.png */; }; + D134D80A161781F50098794B /* MessageEntrySendButton.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D802161781F50098794B /* MessageEntrySendButton.png */; }; + D134D80B161781F50098794B /* MessageEntrySendButton@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D803161781F50098794B /* MessageEntrySendButton@2x.png */; }; + D134D80C161781F50098794B /* MessageEntrySendButtonPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D804161781F50098794B /* MessageEntrySendButtonPressed.png */; }; + D134D80D161781F50098794B /* MessageEntrySendButtonPressed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D134D805161781F50098794B /* MessageEntrySendButtonPressed@2x.png */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -36,6 +48,21 @@ D134D6E21617685C0098794B /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RootViewController.h; path = Classes/RootViewController.h; sourceTree = "<group>"; }; D134D6E31617685C0098794B /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RootViewController.m; path = Classes/RootViewController.m; sourceTree = "<group>"; }; D134D6E41617685C0098794B /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = RootViewController.xib; path = Classes/RootViewController.xib; sourceTree = "<group>"; }; + D134D774161778790098794B /* ChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChatViewController.h; path = Classes/ChatViewController.h; sourceTree = "<group>"; }; + D134D775161778790098794B /* ChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ChatViewController.m; path = Classes/ChatViewController.m; sourceTree = "<group>"; }; + D134D776161778790098794B /* ChatViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ChatViewController.xib; path = Classes/ChatViewController.xib; sourceTree = "<group>"; }; + D134D7D0161780390098794B /* HPGrowingTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HPGrowingTextView.h; path = Vendor/HPGrowingTextView.h; sourceTree = "<group>"; }; + D134D7D1161780390098794B /* HPGrowingTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HPGrowingTextView.m; path = Vendor/HPGrowingTextView.m; sourceTree = "<group>"; }; + D134D7D2161780390098794B /* HPTextViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HPTextViewInternal.h; path = Vendor/HPTextViewInternal.h; sourceTree = "<group>"; }; + D134D7D3161780390098794B /* HPTextViewInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HPTextViewInternal.m; path = Vendor/HPTextViewInternal.m; sourceTree = "<group>"; }; + D134D7FE161781F50098794B /* MessageEntryBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MessageEntryBackground.png; sourceTree = "<group>"; }; + D134D7FF161781F50098794B /* MessageEntryBackground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MessageEntryBackground@2x.png"; sourceTree = "<group>"; }; + D134D800161781F50098794B /* MessageEntryInputField.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MessageEntryInputField.png; sourceTree = "<group>"; }; + D134D801161781F50098794B /* MessageEntryInputField@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MessageEntryInputField@2x.png"; sourceTree = "<group>"; }; + D134D802161781F50098794B /* MessageEntrySendButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MessageEntrySendButton.png; sourceTree = "<group>"; }; + D134D803161781F50098794B /* MessageEntrySendButton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MessageEntrySendButton@2x.png"; sourceTree = "<group>"; }; + D134D804161781F50098794B /* MessageEntrySendButtonPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MessageEntrySendButtonPressed.png; sourceTree = "<group>"; }; + D134D805161781F50098794B /* MessageEntrySendButtonPressed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MessageEntrySendButtonPressed@2x.png"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -99,6 +126,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, D134D6E91617687A0098794B /* xib */, + D134D7FD161781F50098794B /* Resources */, ); name = CustomTemplate; sourceTree = "<group>"; @@ -125,8 +153,11 @@ D134D6E8161768700098794B /* Classes */ = { isa = PBXGroup; children = ( + D134D774161778790098794B /* ChatViewController.h */, + D134D775161778790098794B /* ChatViewController.m */, D134D6E21617685C0098794B /* RootViewController.h */, D134D6E31617685C0098794B /* RootViewController.m */, + D134D7D61617803D0098794B /* Vendor */, ); name = Classes; sourceTree = "<group>"; @@ -134,11 +165,38 @@ D134D6E91617687A0098794B /* xib */ = { isa = PBXGroup; children = ( + D134D776161778790098794B /* ChatViewController.xib */, D134D6E41617685C0098794B /* RootViewController.xib */, ); name = xib; sourceTree = "<group>"; }; + D134D7D61617803D0098794B /* Vendor */ = { + isa = PBXGroup; + children = ( + D134D7D0161780390098794B /* HPGrowingTextView.h */, + D134D7D1161780390098794B /* HPGrowingTextView.m */, + D134D7D2161780390098794B /* HPTextViewInternal.h */, + D134D7D3161780390098794B /* HPTextViewInternal.m */, + ); + name = Vendor; + sourceTree = "<group>"; + }; + D134D7FD161781F50098794B /* Resources */ = { + isa = PBXGroup; + children = ( + D134D7FE161781F50098794B /* MessageEntryBackground.png */, + D134D7FF161781F50098794B /* MessageEntryBackground@2x.png */, + D134D800161781F50098794B /* MessageEntryInputField.png */, + D134D801161781F50098794B /* MessageEntryInputField@2x.png */, + D134D802161781F50098794B /* MessageEntrySendButton.png */, + D134D803161781F50098794B /* MessageEntrySendButton@2x.png */, + D134D804161781F50098794B /* MessageEntrySendButtonPressed.png */, + D134D805161781F50098794B /* MessageEntrySendButtonPressed@2x.png */, + ); + path = Resources; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -184,6 +242,15 @@ 2860E329111B887F00E27156 /* MainWindow_iPhone.xib in Resources */, 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */, D134D6E61617685C0098794B /* RootViewController.xib in Resources */, + D134D778161778790098794B /* ChatViewController.xib in Resources */, + D134D806161781F50098794B /* MessageEntryBackground.png in Resources */, + D134D807161781F50098794B /* MessageEntryBackground@2x.png in Resources */, + D134D808161781F50098794B /* MessageEntryInputField.png in Resources */, + D134D809161781F50098794B /* MessageEntryInputField@2x.png in Resources */, + D134D80A161781F50098794B /* MessageEntrySendButton.png in Resources */, + D134D80B161781F50098794B /* MessageEntrySendButton@2x.png in Resources */, + D134D80C161781F50098794B /* MessageEntrySendButtonPressed.png in Resources */, + D134D80D161781F50098794B /* MessageEntrySendButtonPressed@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -198,6 +265,9 @@ 2860E328111B887F00E27156 /* AppDelegate_iPhone.m in Sources */, 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */, D134D6E51617685C0098794B /* RootViewController.m in Sources */, + D134D777161778790098794B /* ChatViewController.m in Sources */, + D134D7D4161780390098794B /* HPGrowingTextView.m in Sources */, + D134D7D5161780390098794B /* HPTextViewInternal.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1,3 +1,4 @@ Babblr ====== +ws://poddb.com:9394/ diff --git a/Resources/MessageEntryBackground.png b/Resources/MessageEntryBackground.png Binary files differnew file mode 100644 index 0000000..1db2bce --- /dev/null +++ b/Resources/MessageEntryBackground.png diff --git a/Resources/MessageEntryBackground@2x.png b/Resources/MessageEntryBackground@2x.png Binary files differnew file mode 100644 index 0000000..53d805a --- /dev/null +++ b/Resources/MessageEntryBackground@2x.png diff --git a/Resources/MessageEntryInputField.png b/Resources/MessageEntryInputField.png Binary files differnew file mode 100644 index 0000000..f784561 --- /dev/null +++ b/Resources/MessageEntryInputField.png diff --git a/Resources/MessageEntryInputField@2x.png b/Resources/MessageEntryInputField@2x.png Binary files differnew file mode 100644 index 0000000..6841607 --- /dev/null +++ b/Resources/MessageEntryInputField@2x.png diff --git a/Resources/MessageEntrySendButton.png b/Resources/MessageEntrySendButton.png Binary files differnew file mode 100644 index 0000000..1c7d1d8 --- /dev/null +++ b/Resources/MessageEntrySendButton.png diff --git a/Resources/MessageEntrySendButton@2x.png b/Resources/MessageEntrySendButton@2x.png Binary files differnew file mode 100644 index 0000000..086083d --- /dev/null +++ b/Resources/MessageEntrySendButton@2x.png diff --git a/Resources/MessageEntrySendButtonPressed.png b/Resources/MessageEntrySendButtonPressed.png Binary files differnew file mode 100644 index 0000000..f7397d1 --- /dev/null +++ b/Resources/MessageEntrySendButtonPressed.png diff --git a/Resources/MessageEntrySendButtonPressed@2x.png b/Resources/MessageEntrySendButtonPressed@2x.png Binary files differnew file mode 100644 index 0000000..c9a662c --- /dev/null +++ b/Resources/MessageEntrySendButtonPressed@2x.png diff --git a/Vendor/HPGrowingTextView.h b/Vendor/HPGrowingTextView.h new file mode 100644 index 0000000..200b3e0 --- /dev/null +++ b/Vendor/HPGrowingTextView.h @@ -0,0 +1,107 @@ +// +// HPTextView.h +// +// Created by Hans Pinckaers on 29-06-10. +// +// MIT License +// +// Copyright (c) 2011 Hans Pinckaers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import <UIKit/UIKit.h> + +@class HPGrowingTextView; +@class HPTextViewInternal; + +@protocol HPGrowingTextViewDelegate + +@optional +- (BOOL)growingTextViewShouldBeginEditing:(HPGrowingTextView *)growingTextView; +- (BOOL)growingTextViewShouldEndEditing:(HPGrowingTextView *)growingTextView; + +- (void)growingTextViewDidBeginEditing:(HPGrowingTextView *)growingTextView; +- (void)growingTextViewDidEndEditing:(HPGrowingTextView *)growingTextView; + +- (BOOL)growingTextView:(HPGrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; +- (void)growingTextViewDidChange:(HPGrowingTextView *)growingTextView; + +- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height; +- (void)growingTextView:(HPGrowingTextView *)growingTextView didChangeHeight:(float)height; + +- (void)growingTextViewDidChangeSelection:(HPGrowingTextView *)growingTextView; +- (BOOL)growingTextViewShouldReturn:(HPGrowingTextView *)growingTextView; +@end + +@interface HPGrowingTextView : UIView <UITextViewDelegate> { + HPTextViewInternal *internalTextView; + + int minHeight; + int maxHeight; + + //class properties + int maxNumberOfLines; + int minNumberOfLines; + + BOOL animateHeightChange; + + //uitextview properties + NSObject <HPGrowingTextViewDelegate> *delegate; + NSString *text; + UIFont *font; + UIColor *textColor; + UITextAlignment textAlignment; + NSRange selectedRange; + BOOL editable; + UIDataDetectorTypes dataDetectorTypes; + UIReturnKeyType returnKeyType; + + UIEdgeInsets contentInset; +} + +//real class properties +@property int maxNumberOfLines; +@property int minNumberOfLines; +@property BOOL animateHeightChange; +@property (retain) UITextView *internalTextView; + + +//uitextview properties +@property(assign) NSObject<HPGrowingTextViewDelegate> *delegate; +@property(nonatomic,assign) NSString *text; +@property(nonatomic,assign) UIFont *font; +@property(nonatomic,assign) UIColor *textColor; +@property(nonatomic) UITextAlignment textAlignment; // default is UITextAlignmentLeft +@property(nonatomic) NSRange selectedRange; // only ranges of length 0 are supported +@property(nonatomic,getter=isEditable) BOOL editable; +@property(nonatomic) UIDataDetectorTypes dataDetectorTypes __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_0); +@property (nonatomic) UIReturnKeyType returnKeyType; +@property (assign) UIEdgeInsets contentInset; +@property(nonatomic) BOOL enablesReturnKeyAutomatically; + +//uitextview methods +//need others? use .internalTextView +- (BOOL)becomeFirstResponder; +- (BOOL)resignFirstResponder; +- (BOOL)isFirstResponder; + +- (BOOL)hasText; +- (void)scrollRangeToVisible:(NSRange)range; + +@end diff --git a/Vendor/HPGrowingTextView.m b/Vendor/HPGrowingTextView.m new file mode 100644 index 0000000..5904a4c --- /dev/null +++ b/Vendor/HPGrowingTextView.m @@ -0,0 +1,550 @@ +// +// HPTextView.m +// +// Created by Hans Pinckaers on 29-06-10. +// +// MIT License +// +// Copyright (c) 2011 Hans Pinckaers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "HPGrowingTextView.h" +#import "HPTextViewInternal.h" + +@interface HPGrowingTextView(private) +-(void)commonInitialiser; +-(void)resizeTextView:(NSInteger)newSizeH; +-(void)growDidStop; +@end + +@implementation HPGrowingTextView +@synthesize internalTextView; +@synthesize delegate; + +@synthesize font; +@synthesize textColor; +@synthesize textAlignment; +@synthesize selectedRange; +@synthesize editable; +@synthesize dataDetectorTypes; +@synthesize animateHeightChange; +@synthesize returnKeyType; + +// having initwithcoder allows us to use HPGrowingTextView in a Nib. -- aob, 9/2011 +- (id)initWithCoder:(NSCoder *)aDecoder +{ + if ((self = [super initWithCoder:aDecoder])) { + [self commonInitialiser]; + } + return self; +} + +- (id)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + [self commonInitialiser]; + } + return self; +} + +-(void)commonInitialiser +{ + // Initialization code + CGRect r = self.frame; + r.origin.y = 0; + r.origin.x = 0; + internalTextView = [[HPTextViewInternal alloc] initWithFrame:r]; + internalTextView.delegate = self; + internalTextView.scrollEnabled = NO; + internalTextView.font = [UIFont fontWithName:@"Helvetica" size:13]; + internalTextView.contentInset = UIEdgeInsetsZero; + internalTextView.showsHorizontalScrollIndicator = NO; + internalTextView.text = @"-"; + [self addSubview:internalTextView]; + + UIView *internal = (UIView*)[[internalTextView subviews] objectAtIndex:0]; + minHeight = internal.frame.size.height; + minNumberOfLines = 1; + + animateHeightChange = YES; + + internalTextView.text = @""; + + [self setMaxNumberOfLines:3]; +} + +-(void)sizeToFit +{ + CGRect r = self.frame; + + // check if the text is available in text view or not, if it is available, no need to set it to minimum lenth, it could vary as per the text length + // fix from Ankit Thakur + if ([self.text length] > 0) { + return; + } else { + r.size.height = minHeight; + self.frame = r; + } +} + +-(void)setFrame:(CGRect)aframe +{ + CGRect r = aframe; + r.origin.y = 0; + r.origin.x = contentInset.left; + r.size.width -= contentInset.left + contentInset.right; + + internalTextView.frame = r; + + [super setFrame:aframe]; +} + +-(void)setContentInset:(UIEdgeInsets)inset +{ + contentInset = inset; + + CGRect r = self.frame; + r.origin.y = inset.top - inset.bottom; + r.origin.x = inset.left; + r.size.width -= inset.left + inset.right; + + internalTextView.frame = r; + + [self setMaxNumberOfLines:maxNumberOfLines]; + [self setMinNumberOfLines:minNumberOfLines]; +} + +-(UIEdgeInsets)contentInset +{ + return contentInset; +} + +-(void)setMaxNumberOfLines:(int)n +{ + // Use internalTextView for height calculations, thanks to Gwynne <http://blog.darkrainfall.org/> + NSString *saveText = internalTextView.text, *newText = @"-"; + + internalTextView.delegate = nil; + internalTextView.hidden = YES; + + for (int i = 1; i < n; ++i) + newText = [newText stringByAppendingString:@"\n|W|"]; + + internalTextView.text = newText; + + maxHeight = internalTextView.contentSize.height; + + internalTextView.text = saveText; + internalTextView.hidden = NO; + internalTextView.delegate = self; + + [self sizeToFit]; + + maxNumberOfLines = n; +} + +-(int)maxNumberOfLines +{ + return maxNumberOfLines; +} + +-(void)setMinNumberOfLines:(int)m +{ + // Use internalTextView for height calculations, thanks to Gwynne <http://blog.darkrainfall.org/> + NSString *saveText = internalTextView.text, *newText = @"-"; + + internalTextView.delegate = nil; + internalTextView.hidden = YES; + + for (int i = 1; i < m; ++i) + newText = [newText stringByAppendingString:@"\n|W|"]; + + internalTextView.text = newText; + + minHeight = internalTextView.contentSize.height; + + internalTextView.text = saveText; + internalTextView.hidden = NO; + internalTextView.delegate = self; + + [self sizeToFit]; + + minNumberOfLines = m; +} + +-(int)minNumberOfLines +{ + return minNumberOfLines; +} + + +- (void)textViewDidChange:(UITextView *)textView +{ + //size of content, so we can set the frame of self + NSInteger newSizeH = internalTextView.contentSize.height; + if(newSizeH < minHeight || !internalTextView.hasText) newSizeH = minHeight; //not smalles than minHeight + if (internalTextView.frame.size.height > maxHeight) newSizeH = maxHeight; // not taller than maxHeight + + if (internalTextView.frame.size.height != newSizeH) + { + // [fixed] Pasting too much text into the view failed to fire the height change, + // thanks to Gwynne <http://blog.darkrainfall.org/> + + if (newSizeH > maxHeight && internalTextView.frame.size.height <= maxHeight) + { + newSizeH = maxHeight; + } + + if (newSizeH <= maxHeight) + { + if(animateHeightChange) { + + if ([UIView resolveClassMethod:@selector(animateWithDuration:animations:)]) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 + [UIView animateWithDuration:0.1f + delay:0 + options:(UIViewAnimationOptionAllowUserInteraction| + UIViewAnimationOptionBeginFromCurrentState) + animations:^(void) { + [self resizeTextView:newSizeH]; + } + completion:^(BOOL finished) { + if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { + [delegate growingTextView:self didChangeHeight:newSizeH]; + } + }]; +#endif + } else { + [UIView beginAnimations:@"" context:nil]; + [UIView setAnimationDuration:0.1f]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(growDidStop)]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [self resizeTextView:newSizeH]; + [UIView commitAnimations]; + } + } else { + [self resizeTextView:newSizeH]; + // [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes. + // thanks to Gwynne <http://blog.darkrainfall.org/> + + if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { + [delegate growingTextView:self didChangeHeight:newSizeH]; + } + } + } + + + // if our new height is greater than the maxHeight + // sets not set the height or move things + // around and enable scrolling + if (newSizeH >= maxHeight) + { + if(!internalTextView.scrollEnabled){ + internalTextView.scrollEnabled = YES; + [internalTextView flashScrollIndicators]; + } + + } else { + internalTextView.scrollEnabled = NO; + } + + } + + + if ([delegate respondsToSelector:@selector(growingTextViewDidChange:)]) { + [delegate growingTextViewDidChange:self]; + } + +} + +-(void)resizeTextView:(NSInteger)newSizeH +{ + if ([delegate respondsToSelector:@selector(growingTextView:willChangeHeight:)]) { + [delegate growingTextView:self willChangeHeight:newSizeH]; + } + + CGRect internalTextViewFrame = self.frame; + internalTextViewFrame.size.height = newSizeH; // + padding + self.frame = internalTextViewFrame; + + internalTextViewFrame.origin.y = contentInset.top - contentInset.bottom; + internalTextViewFrame.origin.x = contentInset.left; + internalTextViewFrame.size.width = internalTextView.contentSize.width; + + internalTextView.frame = internalTextViewFrame; +} + +-(void)growDidStop +{ + if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { + [delegate growingTextView:self didChangeHeight:self.frame.size.height]; + } + +} + +-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + [internalTextView becomeFirstResponder]; +} + +- (BOOL)becomeFirstResponder +{ + [super becomeFirstResponder]; + return [self.internalTextView becomeFirstResponder]; +} + +-(BOOL)resignFirstResponder +{ + [super resignFirstResponder]; + return [internalTextView resignFirstResponder]; +} + +-(BOOL)isFirstResponder +{ + return [self.internalTextView isFirstResponder]; +} + +- (void)dealloc { + [internalTextView release]; + [super dealloc]; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark UITextView properties +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setText:(NSString *)newText +{ + internalTextView.text = newText; + + // include this line to analyze the height of the textview. + // fix from Ankit Thakur + [self performSelector:@selector(textViewDidChange:) withObject:internalTextView]; +} + +-(NSString*) text +{ + return internalTextView.text; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setFont:(UIFont *)afont +{ + internalTextView.font= afont; + + [self setMaxNumberOfLines:maxNumberOfLines]; + [self setMinNumberOfLines:minNumberOfLines]; +} + +-(UIFont *)font +{ + return internalTextView.font; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setTextColor:(UIColor *)color +{ + internalTextView.textColor = color; +} + +-(UIColor*)textColor{ + return internalTextView.textColor; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setBackgroundColor:(UIColor *)backgroundColor +{ + [super setBackgroundColor:backgroundColor]; + internalTextView.backgroundColor = backgroundColor; +} + +-(UIColor*)backgroundColor +{ + return internalTextView.backgroundColor; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setTextAlignment:(UITextAlignment)aligment +{ + internalTextView.textAlignment = aligment; +} + +-(UITextAlignment)textAlignment +{ + return internalTextView.textAlignment; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setSelectedRange:(NSRange)range +{ + internalTextView.selectedRange = range; +} + +-(NSRange)selectedRange +{ + return internalTextView.selectedRange; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setEditable:(BOOL)beditable +{ + internalTextView.editable = beditable; +} + +-(BOOL)isEditable +{ + return internalTextView.editable; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setReturnKeyType:(UIReturnKeyType)keyType +{ + internalTextView.returnKeyType = keyType; +} + +-(UIReturnKeyType)returnKeyType +{ + return internalTextView.returnKeyType; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)setEnablesReturnKeyAutomatically:(BOOL)enablesReturnKeyAutomatically +{ + internalTextView.enablesReturnKeyAutomatically = enablesReturnKeyAutomatically; +} + +- (BOOL)enablesReturnKeyAutomatically +{ + return internalTextView.enablesReturnKeyAutomatically; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +-(void)setDataDetectorTypes:(UIDataDetectorTypes)datadetector +{ + internalTextView.dataDetectorTypes = datadetector; +} + +-(UIDataDetectorTypes)dataDetectorTypes +{ + return internalTextView.dataDetectorTypes; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +- (BOOL)hasText{ + return [internalTextView hasText]; +} + +- (void)scrollRangeToVisible:(NSRange)range +{ + [internalTextView scrollRangeToVisible:range]; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark UITextViewDelegate + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (BOOL)textViewShouldBeginEditing:(UITextView *)textView { + if ([delegate respondsToSelector:@selector(growingTextViewShouldBeginEditing:)]) { + return [delegate growingTextViewShouldBeginEditing:self]; + + } else { + return YES; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (BOOL)textViewShouldEndEditing:(UITextView *)textView { + if ([delegate respondsToSelector:@selector(growingTextViewShouldEndEditing:)]) { + return [delegate growingTextViewShouldEndEditing:self]; + + } else { + return YES; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)textViewDidBeginEditing:(UITextView *)textView { + if ([delegate respondsToSelector:@selector(growingTextViewDidBeginEditing:)]) { + [delegate growingTextViewDidBeginEditing:self]; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)textViewDidEndEditing:(UITextView *)textView { + if ([delegate respondsToSelector:@selector(growingTextViewDidEndEditing:)]) { + [delegate growingTextViewDidEndEditing:self]; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range + replacementText:(NSString *)atext { + + //weird 1 pixel bug when clicking backspace when textView is empty + if(![textView hasText] && [atext isEqualToString:@""]) return NO; + + //Added by bretdabaker: sometimes we want to handle this ourselves + if ([delegate respondsToSelector:@selector(growingTextView:shouldChangeTextInRange:replacementText:)]) + return [delegate growingTextView:self shouldChangeTextInRange:range replacementText:atext]; + + if ([atext isEqualToString:@"\n"]) { + if ([delegate respondsToSelector:@selector(growingTextViewShouldReturn:)]) { + if (![delegate performSelector:@selector(growingTextViewShouldReturn:) withObject:self]) { + return YES; + } else { + [textView resignFirstResponder]; + return NO; + } + } + } + + return YES; + + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)textViewDidChangeSelection:(UITextView *)textView { + if ([delegate respondsToSelector:@selector(growingTextViewDidChangeSelection:)]) { + [delegate growingTextViewDidChangeSelection:self]; + } +} + + + +@end diff --git a/Vendor/HPTextViewInternal.h b/Vendor/HPTextViewInternal.h new file mode 100644 index 0000000..c44ac63 --- /dev/null +++ b/Vendor/HPTextViewInternal.h @@ -0,0 +1,34 @@ +// +// HPTextViewInternal.h +// +// Created by Hans Pinckaers on 29-06-10. +// +// MIT License +// +// Copyright (c) 2011 Hans Pinckaers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import <UIKit/UIKit.h> + + +@interface HPTextViewInternal : UITextView { +} + +@end diff --git a/Vendor/HPTextViewInternal.m b/Vendor/HPTextViewInternal.m new file mode 100644 index 0000000..9b45702 --- /dev/null +++ b/Vendor/HPTextViewInternal.m @@ -0,0 +1,98 @@ +// +// HPTextViewInternal.m +// +// Created by Hans Pinckaers on 29-06-10. +// +// MIT License +// +// Copyright (c) 2011 Hans Pinckaers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "HPTextViewInternal.h" + + +@implementation HPTextViewInternal + +-(void)setText:(NSString *)text +{ + BOOL originalValue = self.scrollEnabled; + //If one of GrowingTextView's superviews is a scrollView, and self.scrollEnabled == NO, + //setting the text programatically will cause UIKit to search upwards until it finds a scrollView with scrollEnabled==yes + //then scroll it erratically. Setting scrollEnabled temporarily to YES prevents this. + [self setScrollEnabled:YES]; + [super setText:text]; + [self setScrollEnabled:originalValue]; +} + +-(void)setContentOffset:(CGPoint)s +{ + if(self.tracking || self.decelerating){ + //initiated by user... + + UIEdgeInsets insets = self.contentInset; + insets.bottom = 0; + insets.top = 0; + self.contentInset = insets; + + } else { + + float bottomOffset = (self.contentSize.height - self.frame.size.height + self.contentInset.bottom); + if(s.y < bottomOffset && self.scrollEnabled){ + UIEdgeInsets insets = self.contentInset; + insets.bottom = 8; + insets.top = 0; + self.contentInset = insets; + } + } + + [super setContentOffset:s]; +} + +-(void)setContentInset:(UIEdgeInsets)s +{ + UIEdgeInsets insets = s; + + if(s.bottom>8) insets.bottom = 0; + insets.top = 0; + + [super setContentInset:insets]; +} + +-(void)setContentSize:(CGSize)contentSize +{ + // is this an iOS5 bug? Need testing! + if(self.contentSize.height > contentSize.height) + { + UIEdgeInsets insets = self.contentInset; + insets.bottom = 0; + insets.top = 0; + self.contentInset = insets; + } + + [super setContentSize:contentSize]; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@end diff --git a/iPhone/AppDelegate_iPhone.m b/iPhone/AppDelegate_iPhone.m index 566b8cd..31a23e4 100644 --- a/iPhone/AppDelegate_iPhone.m +++ b/iPhone/AppDelegate_iPhone.m @@ -8,6 +8,7 @@ #import "AppDelegate_iPhone.h" #import "RootViewController.h" +#import "ChatViewController.h" @implementation AppDelegate_iPhone @@ -21,7 +22,9 @@ // Override point for customization after application launch. RootViewController *rootVC = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil]; - [window setRootViewController:rootVC]; + ChatViewController *chatVC = [[ChatViewController alloc] init]; +// [window setRootViewController:rootVC]; + [window addSubview:chatVC.view]; [window makeKeyAndVisible]; |
