Skip to content

Instantly share code, notes, and snippets.

@RandomEtc
Created August 9, 2011 23:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RandomEtc/1135534 to your computer and use it in GitHub Desktop.
Save RandomEtc/1135534 to your computer and use it in GitHub Desktop.
UITextField wrapper for Cinder
//
// TextField.h
//
// Created by Tom Carden on 8/9/11.
// Copyright 2011 Bloom Studio, Inc. All rights reserved.
//
#pragma once
#include <string>
#include "cinder/Function.h"
class TextFieldImpl;
class TextField {
public:
TextField(): textFieldImpl(NULL) {};
~TextField();
void setup();
template<typename T>
ci::CallbackId registerTextChanged( T *obj, bool (T::*callback)(TextField*) )
{
return mCbTextChanged.registerCb(std::bind1st(std::mem_fun(callback), obj));
}
template<typename T>
ci::CallbackId registerTextDone( T *obj, bool (T::*callback)(TextField*) )
{
return mCbTextDone.registerCb(std::bind1st(std::mem_fun(callback), obj));
}
std::string getText();
void setHidden( bool hidden = true );
bool isHidden();
protected:
friend class TextFieldImpl; // to save too much indirection firing callbacks
TextFieldImpl *textFieldImpl; // to save from setting everything that touches this header as an objective-c++ file
ci::CallbackMgr<bool(TextField*)> mCbTextChanged, mCbTextDone;
};
//
// TextField.mm
//
// Created by Tom Carden on 8/9/11.
// Copyright 2011 Bloom Studio, Inc. All rights reserved.
//
#include "TextField.h"
#import <UIKit/UIKit.h>
class TextFieldImpl {
public:
~TextFieldImpl();
UITextField *uiTextField; // cocoa touch
TextField *mTextField; // cinder
TextFieldImpl( TextField *textField );
void textChanged();
void textDone();
void setHidden( bool hidden );
bool isHidden();
std::string getText();
};
@interface TFDelegate : NSObject <UITextFieldDelegate> {
@public
UITextField *activeTextField;
TextFieldImpl *mTextFieldImpl;
}
@end
@implementation TFDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
activeTextField = textField;
return YES;
}
//- (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString *) string
//{
// mTextFieldImpl->textChanged(); // FIXME, will be missing the new character until we return YES ... use notification instead?
// return YES;
//}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
mTextFieldImpl->textDone();
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
activeTextField = nil;
[textField resignFirstResponder];
return YES;
}
- (void)textFieldDidChange:(NSNotification*)notification
{
mTextFieldImpl->textChanged();
}
@end
TextFieldImpl::TextFieldImpl( TextField *textField )
{
mTextField = textField;
TFDelegate *tfDelegate = [[TFDelegate alloc] init];
tfDelegate->mTextFieldImpl = this; // to send textChanged, textDone
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
// TODO: getter/setters for all the basic attributes of UITextField, position, etc.
uiTextField = [[UITextField alloc] initWithFrame:CGRectMake(25, 35, 300, 31)];
uiTextField.borderStyle = UITextBorderStyleRoundedRect; // or maybe UISearchBar instead?
uiTextField.delegate = tfDelegate;
uiTextField.keyboardType = UIKeyboardTypeDefault;
uiTextField.returnKeyType = UIReturnKeyDone;
uiTextField.textAlignment = UITextAlignmentLeft;
// uiTextField.placeholder = @"Username\n";
uiTextField.autocorrectionType = UITextAutocorrectionTypeNo;
uiTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
[[NSNotificationCenter defaultCenter] addObserver:tfDelegate
selector:@selector(textFieldDidChange:)
name:@"UITextFieldTextDidChangeNotification"
object:uiTextField];
[window addSubview: uiTextField];
}
TextFieldImpl::~TextFieldImpl()
{
[[NSNotificationCenter defaultCenter] removeObserver:uiTextField.delegate
name:@"UITextFieldTextDidChangeNotification"
object:uiTextField];
mTextField = NULL;
// UIWindow *window = [[UIApplication sharedApplication] keyWindow];
// [window removeSubview: uiTextField]; // FIXME: how to remove?
[uiTextField.delegate release];
[uiTextField release];
}
std::string TextFieldImpl::getText()
{
return std::string([uiTextField.text UTF8String]);
}
void TextFieldImpl::setHidden( bool hidden )
{
uiTextField.hidden = hidden;
}
bool TextFieldImpl::isHidden()
{
return uiTextField.hidden;
}
void TextFieldImpl::textChanged()
{
mTextField->mCbTextChanged.call( mTextField );
}
void TextFieldImpl::textDone()
{
mTextField->mCbTextDone.call( mTextField );
}
TextField::~TextField()
{
delete textFieldImpl;
}
void TextField::setup()
{
textFieldImpl = new TextFieldImpl( this );
}
std::string TextField::getText()
{
return textFieldImpl->getText();
}
void TextField::setHidden( bool hidden )
{
textFieldImpl->setHidden( hidden );
}
bool TextField::isHidden()
{
return textFieldImpl->isHidden();
}
#include "TextField.h"
// etc.
using namespace std;
// etc.
class YourApp /* not a real Cinder app */
{
public:
void setup();
// etc.
bool onTextDone( Textfield* );
bool onTextChanged( Textfield* );
private:
TextField mTextField;
// etc.
};
void YourApp::setup()
{
mTextField.setup();
mTextField.registerTextDone( this, &YourApp::onTextDone );
mTextField.registerTextChanged( this, &YourApp::onTextChanged );
}
bool YourApp::onTextDone( TextField *textField )
{
string text = textField->getText();
}
bool YourApp::onTextChanged( TextField *textField )
{
string text = textField->getText();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment