Created
October 14, 2014 19:51
-
-
Save cwhitney/fc0fe70ec513568e1641 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CiTextField.h | |
// CinderText | |
// | |
// Created by Charlie Whitney on 10/13/14. | |
// | |
// | |
#pragma once | |
#include "cinder/app/AppNative.h" | |
#include "cinder/gl/TextureFont.h" | |
class CiTextField { | |
public: | |
CiTextField( std::string text, ci::Rectf bounds, ci::Font font ); | |
~CiTextField(); | |
void setText( std::string text ); | |
void setBounds( ci::Rectf bounds ); | |
void draw(); | |
bool bUseScissorTest; | |
private: | |
void onMouseDown( ci::app::MouseEvent event ); | |
void onMouseDrag( ci::app::MouseEvent event ); | |
void onMouseUp( ci::app::MouseEvent event ); | |
void onKeyDown( ci::app::KeyEvent event ); | |
void onKeyUp( ci::app::KeyEvent event ); | |
int getCursorIndex( ci::Vec2f pos ); | |
bool bDragging; | |
bool bActive; | |
bool bHighlighted; | |
ci::Vec2f mCursorPos; | |
int mCaratIndex, mCaratStart; | |
ci::Color mColorStroke, mColorFill, mColorText, mColorHighlight; | |
std::string mText; | |
ci::Rectf mBounds; | |
ci::Vec2f emSize; | |
ci::Font mFont; | |
ci::gl::TextureFontRef tFont; | |
// mouse events | |
boost::signals2::scoped_connection mMouseDownCb, | |
mMouseDragCb, | |
mMouseUpCb, | |
mKeyDownCb, | |
mKeyUpCb; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CiTextField.cpp | |
// CinderText | |
// | |
// Created by Charlie Whitney on 10/13/14. | |
// | |
// | |
#include "CiTextField.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
CiTextField::~CiTextField(){ | |
mMouseDownCb.disconnect(); | |
mMouseDragCb.disconnect(); | |
} | |
CiTextField::CiTextField( std::string text, ci::Rectf bounds, ci::Font font ){ | |
setText(text); | |
setBounds(bounds); | |
mColorStroke = Color(1,1,1); | |
mColorFill = Color::gray(0.2); | |
mColorText = Color(1,1,1); | |
mColorHighlight = Color::hex(0xb6d6fd); | |
mFont = font; | |
if( mFont ){ | |
tFont = gl::TextureFont::create( mFont ); | |
emSize = tFont->measureString("M"); | |
} | |
ci::app::WindowRef window = cinder::app::getWindow(); | |
mMouseDownCb = window->getSignalMouseDown().connect( std::bind(&CiTextField::onMouseDown, this, std::placeholders::_1) ); | |
mMouseDragCb = window->getSignalMouseDrag().connect( std::bind(&CiTextField::onMouseDrag, this, std::placeholders::_1) ); | |
mMouseUpCb = window->getSignalMouseUp().connect( std::bind(&CiTextField::onMouseUp, this, std::placeholders::_1) ); | |
mKeyDownCb = window->getSignalKeyDown().connect( std::bind(&CiTextField::onKeyDown, this, std::placeholders::_1) ); | |
mKeyUpCb = window->getSignalKeyUp().connect( std::bind(&CiTextField::onKeyUp, this, std::placeholders::_1) ); | |
bDragging = false; | |
bActive = false; | |
bHighlighted = false; | |
bUseScissorTest = true; | |
mCaratIndex = mText.size(); | |
} | |
void CiTextField::setBounds( ci::Rectf bounds ){ | |
mBounds = bounds; | |
} | |
void CiTextField::setText(std::string text){ | |
mText = text; | |
} | |
void CiTextField::onKeyDown(KeyEvent event){ | |
if( !bActive ){ | |
return; | |
} | |
if( event.getCode() == KeyEvent::KEY_LEFT ){ | |
bDragging = false; | |
mCaratIndex = max(mCaratIndex - 1, 0); | |
}else if( event.getCode() == KeyEvent::KEY_RIGHT ){ | |
bDragging = false; | |
mCaratIndex = min(mCaratIndex + 1, (int)mText.size()); | |
} | |
else if( event.getCode() == KeyEvent::KEY_DELETE ){ | |
if( bHighlighted ){ | |
int s = min(mCaratStart, mCaratIndex); | |
int e = max(mCaratStart, mCaratIndex); | |
mText.erase(s, e-s); | |
mCaratIndex = s; | |
}else{ | |
mText.erase(mCaratIndex, 1); | |
} | |
} | |
else if( event.getCode() == KeyEvent::KEY_BACKSPACE ){ | |
if( bHighlighted ){ | |
int s = min(mCaratStart, mCaratIndex); | |
int e = max(mCaratStart, mCaratIndex); | |
mText.erase(s, e-s); | |
mCaratIndex = s; | |
}else{ | |
mText.erase(mCaratIndex-1, 1); | |
mCaratIndex--; | |
} | |
} | |
else if (event.getCode() > 31 && event.getCode() < 272){ // delete is in here, but we handle it above | |
if( bHighlighted ){ | |
int s = min(mCaratStart, mCaratIndex); | |
int e = max(mCaratStart, mCaratIndex); | |
mText.erase(s, e-s); | |
mText.insert(s, 1, event.getChar() ); | |
mCaratIndex = s+1; | |
bHighlighted = false; | |
}else{ | |
mText.insert(mCaratIndex, 1, event.getChar() ); | |
++mCaratIndex; | |
} | |
} | |
bHighlighted = false; | |
} | |
void CiTextField::onKeyUp(KeyEvent event){ | |
} | |
void CiTextField::onMouseDown( ci::app::MouseEvent event ){ | |
bHighlighted = false; | |
bDragging = false; | |
bActive = false; | |
if( mBounds.contains(event.getPos()) ){ | |
bDragging = true; | |
bActive = true; | |
mCaratStart = mCaratIndex = getCursorIndex( event.getPos() - mBounds.getUpperLeft() ); // pass in the local pos | |
mCaratIndex = mCaratStart; | |
} | |
} | |
void CiTextField::onMouseDrag( ci::app::MouseEvent event ){ | |
if( bDragging ){ | |
mCaratIndex = getCursorIndex( event.getPos() - mBounds.getUpperLeft() ); | |
} | |
} | |
void CiTextField::onMouseUp( ci::app::MouseEvent event ){ | |
if( bDragging ){ | |
bActive = true; | |
mCaratIndex = getCursorIndex( event.getPos() - mBounds.getUpperLeft() ); | |
if( mCaratStart != mCaratIndex ){ | |
bHighlighted = true; | |
} | |
}else{ | |
bActive = false; | |
bHighlighted = false; | |
} | |
bDragging = false; | |
} | |
int CiTextField::getCursorIndex( ci::Vec2f localPos ){ | |
int i=0; | |
for( ; i<mText.size()+1; i++){ | |
Vec2f sm = tFont->measureString( mText.substr(0,i) ); | |
if( sm.x > localPos.x ){ | |
if(i>1){ | |
return i-1; | |
}else{ | |
return 0; | |
} | |
break; | |
} | |
} | |
// We didn't find it, so put the cursor at the end | |
if( i == mText.size()+1 ){ | |
return mText.size(); | |
} | |
return mCaratIndex; | |
} | |
void CiTextField::draw(){ | |
if( !tFont ){ | |
if( !mFont ) | |
return; | |
tFont = gl::TextureFont::create( mFont ); | |
emSize = tFont->measureString("M"); | |
} | |
if( bUseScissorTest ){ | |
glEnable(GL_SCISSOR_TEST); | |
glScissor( mBounds.x1, getWindowHeight() - mBounds.y1 - mBounds.getHeight(), mBounds.getWidth(), mBounds.getHeight() ); | |
} | |
gl::color( mColorFill ); | |
gl::drawSolidRect( mBounds ); | |
gl::color( mColorStroke ); | |
gl::drawStrokedRect( mBounds ); | |
// draw our cursor line | |
if( bActive ){ | |
mCursorPos.x = tFont->measureString( mText.substr(0, mCaratIndex) ).x + mBounds.x1; | |
gl::color( mColorHighlight ); | |
gl::pushMatrices();{ | |
gl::translate( 0, mBounds.y1 + emSize.y*0.1); | |
gl::drawLine( mCursorPos, mCursorPos + Vec2f(0, emSize.y) ); | |
}gl::popMatrices(); | |
if( bDragging || bHighlighted ) { | |
gl::color( mColorHighlight ); | |
Vec2f UL( tFont->measureString( mText.substr(0, mCaratStart) ).x, 0); | |
Vec2f LR( tFont->measureString( mText.substr(0, mCaratIndex) ).x, emSize.y); | |
Rectf highlighRect(UL, LR); | |
highlighRect.offset( mBounds.getUpperLeft() + Vec2f(0, emSize.y *0.1) ); | |
gl::drawSolidRect( highlighRect ); | |
} | |
} | |
gl::color( mColorText ); | |
tFont->drawString(mText, Vec2f(mBounds.x1,mBounds.y1 + emSize.y) ); | |
if( bUseScissorTest ){ | |
glDisable(GL_SCISSOR_TEST); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/app/AppNative.h" | |
#include "cinder/gl/gl.h" | |
#include "CiTextField.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
class CinderTextApp : public AppNative { | |
public: | |
void setup(); | |
void mouseDown( MouseEvent event ); | |
void update(); | |
void draw(); | |
CiTextField *tf1; | |
CiTextField *tf2; | |
}; | |
void CinderTextApp::setup() { | |
ci::Font fontOne("Helvetica", 40); | |
ci::Font fontTwo("Times New Roman", 16); | |
tf1 = new CiTextField("Booya", Rectf(100,100,300, 150), fontOne ); | |
tf2 = new CiTextField("Hellooo", Rectf(100,200,300, 225), fontTwo ); | |
} | |
void CinderTextApp::mouseDown( MouseEvent event ){ | |
} | |
void CinderTextApp::update(){ | |
} | |
void CinderTextApp::draw() { | |
gl::enableAlphaBlending(); | |
// clear out the window with black | |
gl::clear( Color( 0, 0, 0 ) ); | |
tf1->draw(); | |
tf2->draw(); | |
} | |
CINDER_APP_NATIVE( CinderTextApp, RendererGl ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment