x11simpletextcontrol.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 636 行

CPP
636
字号
//X11SimpleTextControl.cpp/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include "vcf/ApplicationKit/ApplicationKit.h"#include "vcf/ApplicationKit/ApplicationKitPrivate.h"#include "vcf/ApplicationKit/X11UIToolkit.h"#include "vcf/ApplicationKit/X11SimpleTextControl.h"#include "vcf/ApplicationKit/TextControl.h"using namespace VCF;X11SimpleTextControl::X11SimpleTextControl( TextControl* component, const bool& isMultiLineControl ):	X11Control( component ),	currentLinePos_(0),	selectionStart_(0),	selectionEnd_(0),	enabledSetTextOnControl_(true),	leftMargin_(5.0),	rightMargin_(5.0){	TextModelEventHandler<X11SimpleTextControl>* tml =			new TextModelEventHandler<X11SimpleTextControl>( this, &X11SimpleTextControl::onTextModelTextChanged, "onTextModelTextChanged" );	TextModel* tm = component->getTextModel();	tm->addTextModelChangedHandler( tml );}X11SimpleTextControl::~X11SimpleTextControl(){}void X11SimpleTextControl::handleEvent( XEvent* x11Event ){	switch ( x11Event->type ) {		case KeyPress :  {			int keyCode = x11Event->xkey.keycode;			KeySym keySym;			memset(&keySym, 0, sizeof(KeySym) );			char keyBuffer[100];			memset( keyBuffer, 0, sizeof(keyBuffer) );			int count = XLookupString( &x11Event->xkey, keyBuffer, 100-1, &keySym, 0 );			X11UIToolkit* toolkit = reinterpret_cast<X11UIToolkit*>( UIToolkit::getDefaultUIToolkit() );			VirtualKeyCode code = toolkit->translateKeyCode( keySym );			switch ( code ) {				case vkLeftArrow : {					if ( selectionStart_ > 0 ) {						selectionStart_ -= 1;						repaint();					}				}				break;				case vkRightArrow : {					if ( selectionStart_ < text_.size() ) {						selectionStart_ += 1;						repaint();					}				}				break;				case vkBackSpace : {					if ( selectionStart_ > 0 ) {						selectionStart_ -= 1;						TextControl* tc = reinterpret_cast<TextControl*>( control_ );						TextModel* tm = tc->getTextModel();						String text = tm->getText();						text.erase( selectionStart_, 1 );						tm->setText( text );					}				}				break;				case vkDelete : {					TextControl* tc = reinterpret_cast<TextControl*>( control_ );					TextModel* tm = tc->getTextModel();					String text = tm->getText();					text.erase( selectionStart_, 1 );					selectionStart_ = minVal<ulong32>( selectionStart_, text.size() );					tm->setText( text );				}				break;				default : {					if ( ((code >= vkNumber0) && (code <= vkLetterZ)) || (code == vkSpaceBar) || (code == vkReturn) ) {						TextControl* tc = reinterpret_cast<TextControl*>( control_ );						TextModel* tm = tc->getTextModel();						String text = tm->getText();						if ( code == vkReturn ) {							text.insert( selectionStart_, "\n" );						}						else {							text.insert( selectionStart_, 1, keyBuffer[0] );						}						selectionStart_ += 1;						tm->setText( text );					}				}				break;			}			X11Control::handleEvent( x11Event );		}		break;		case KeyRelease : {			X11Control::handleEvent( x11Event );		}		break;		case ButtonPress : {			VCF::Point pt( x11Event->xbutton.x, x11Event->xbutton.y );			selectionStart_ = getCharIndexFromPosition( &pt );			X11Control::handleEvent( x11Event );		}		break;		case ButtonRelease : {			X11Control::handleEvent( x11Event );		}		break;		case MotionNotify : {			X11Control::handleEvent( x11Event );		}		break;		case FocusIn : {			X11Control::handleEvent( x11Event );		}		break;		case FocusOut : {			X11Control::handleEvent( x11Event );		}		break;		case SelectionClear : {		}		break;		case SelectionRequest : {		}		break;		case SelectionNotify : {		}		break;		default : {			X11Control::handleEvent( x11Event );		}	}}String X11SimpleTextControl::getText(){	return text_;}void X11SimpleTextControl::setText( const String& text ){	text_ = text;	repaint();}void X11SimpleTextControl::setRightMargin( const double & rightMargin ){	rightMargin_ = rightMargin;	repaint();}void X11SimpleTextControl::setLeftMargin( const double & leftMargin ){	leftMargin_ = leftMargin;	repaint();}unsigned long X11SimpleTextControl::getLineCount(){	unsigned long result = 0;	const VCFChar* P = text_.c_str();	const VCFChar* start = P;	const VCFChar* line = P;	int textSize = text_.size();	while ( (P-start) < textSize ) {		if ( (*P == '\n') || ((*P == '\r') && (*(P+1) == '\n')) ) {			result ++;			//process the new line			if ( *(P+1) == '\n' ) {				P++;			}			line = P;			line ++;		}		P++;	}	if ( (line < P) && ((start-line) < textSize) ) {		result ++;	}	return result;}unsigned long X11SimpleTextControl::getCurrentLinePosition(){	return currentLinePos_;}double X11SimpleTextControl::getLeftMargin(){	return leftMargin_;}double X11SimpleTextControl::getRightMargin(){	return rightMargin_;}Point* X11SimpleTextControl::getPositionFromCharIndex( const unsigned long& index ){	GraphicsContext* gc = control_->getContext();	Rect clientRect = *control_->getClientBounds();	gc->getPeer()->setContextID(wndHandle_);	clientRect.left_ += leftMargin_;	clientRect.right_ -= rightMargin_;	clientRect.normalize();	if ( clientRect.getWidth() > 0.0 ) {		ulong32 pos = 0;		const VCFChar* P = text_.c_str();		const VCFChar* start = P;		int size = text_.size();		Rect glyphRect;		glyphRect.setRect( clientRect.left_, 0,								clientRect.left_, gc->getTextHeight( "EM" ) );		String lineOfText;		while ( ((P-start) < size) && (glyphRect.top_ < clientRect.getHeight()) ) {			if ( !((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				lineOfText.append( 1, *P );			}			glyphRect.right_ = gc->getTextWidth( lineOfText ) + clientRect.left_;			if ( (glyphRect.right_ >= clientRect.getWidth()) || ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				//scootch back				if ( (*P != ' ') && (*P != '\n') && (*P != '\r') ){					const VCFChar* tmp = P;					while ( (*P != ' ') && (*P != '\n') && (*P != '\r') && (P > start) ) {						P--;						pos --;					}					lineOfText.erase( lineOfText.size()-(tmp-P), tmp-P );					glyphRect.right_ = gc->getTextWidth( lineOfText ) + clientRect.left_;				}				glyphRect.top_ += gc->getTextHeight( lineOfText );				glyphRect.bottom_ = glyphRect.top_ + gc->getTextHeight( "EM" );				glyphRect.left_ = clientRect.left_;				if ( ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {					if ( (*P == '\r') && (*(P+1) == '\n') ) {						P++;						pos ++;					}				}				lineOfText = "";			}			else if ( index == pos ) {				posAtChar_.x_ = glyphRect.left_;				posAtChar_.y_ = glyphRect.top_;				break;			}			pos ++;			P++;			glyphRect.left_ = glyphRect.right_;		}	}	else {		return NULL;	}	return &posAtChar_;}unsigned long X11SimpleTextControl::getCharIndexFromPosition( Point* point ){	ulong32 result = 0;	GraphicsContext* gc = control_->getContext();	Rect clientRect = *control_->getClientBounds();	gc->getPeer()->setContextID(wndHandle_);	clientRect.left_ += leftMargin_;	clientRect.right_ -= rightMargin_;	clientRect.normalize();	if ( clientRect.getWidth() > 0.0 ) {		const VCFChar* P = text_.c_str();		const VCFChar* start = P;		int size = text_.size();		Rect glyphRect;		glyphRect.setRect( clientRect.left_, 0,								clientRect.left_, gc->getTextHeight( "EM" ) );		String lineOfText;		while ( ((P-start) < size) && (glyphRect.top_ < clientRect.getHeight()) ) {			if ( !((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				lineOfText.append( 1, *P );			}			glyphRect.right_ = gc->getTextWidth( lineOfText ) + clientRect.left_;			if ( (glyphRect.right_ >= clientRect.getWidth()) || ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				//scootch back				if ( (*P != ' ') && (*P != '\n') && (*P != '\r') ){					const VCFChar* tmp = P;					while ( (*P != ' ') && (*P != '\n') && (*P != '\r') && (P > start) ) {						P--;						result --;					}					lineOfText.erase( lineOfText.size()-(tmp-P), tmp-P );					glyphRect.right_ = gc->getTextWidth( lineOfText ) + clientRect.left_;				}				glyphRect.top_ += gc->getTextHeight( lineOfText );				glyphRect.bottom_ = glyphRect.top_ + gc->getTextHeight( "EM" );				glyphRect.left_ = clientRect.left_;				if ( ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {					if ( (*P == '\r') && (*(P+1) == '\n') ) {						P++;						result ++;					}				}				lineOfText = "";			}			else if ( glyphRect.containsPt( point ) ) {				break;			}			result ++;			P++;			glyphRect.left_ = glyphRect.right_;		}	}	return result;}unsigned long X11SimpleTextControl::getCaretPosition(){	return selectionStart_;}void X11SimpleTextControl::setCaretPosition( const unsigned long& caretPos ){	selectionStart_ = caretPos;	selectionEnd_ = selectionStart_;}unsigned long X11SimpleTextControl::getSelectionStart(){	return selectionStart_;}unsigned long X11SimpleTextControl::getSelectionCount(){	return selectionEnd_ - selectionStart_;}void X11SimpleTextControl::setSelectionMark( const unsigned long& start, const unsigned long& count ){	selectionStart_ = start;	selectionEnd_ = selectionStart_ + count;}void X11SimpleTextControl::setSelectionFont( Font* font ){}void X11SimpleTextControl::setParagraphAlignment( const TextAlignmentType& alignment ){}void X11SimpleTextControl::scrollToLine( const ulong32& lineIndex ){}void X11SimpleTextControl::handlePaintEvent(){	Point* caret = getPositionFromCharIndex( selectionStart_ );	GraphicsContext* gc = control_->getContext();	if ( updateRects_.empty() ) {		return;	}	std::vector<Rect>::iterator it = updateRects_.begin();	Rect clipBounds = updateRects_.front();	while ( it != updateRects_.end() ) {		Rect& r = *it;		clipBounds.left_ = minVal<double>( clipBounds.left_, r.left_ );		clipBounds.top_ = minVal<double>( clipBounds.top_, r.top_ );		clipBounds.right_ = maxVal<double>( clipBounds.right_, r.right_ );		clipBounds.bottom_ = maxVal<double>( clipBounds.bottom_, r.bottom_ );		it ++;	}	clipBounds.normalize();	if ( (clipBounds.getHeight() <= 0.0) || (clipBounds.getWidth() <= 0.0) ) {		return;	}	Rect clientRect = *control_->getClientBounds();	gc->getPeer()->setContextID(wndHandle_);	gc->setColor( control_->getColor() );	gc->rectangle( &clientRect );	gc->fillPath();	gc->setCurrentFont( control_->getFont() );	clientRect.left_ += leftMargin_;	clientRect.right_ -= rightMargin_;	clientRect.normalize();	if ( clientRect.getWidth() > 0.0 ) {		const VCFChar* P = text_.c_str();		const VCFChar* start = P;		const VCFChar* line = P;		int size = text_.size();		double y = 0;		double x = clientRect.left_;		String lineOfText;		while ( ((P-start) < size) && (y < clientRect.getHeight()) ) {			if ( !((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				lineOfText.append( 1, *P );			}			x = gc->getTextWidth( lineOfText ) + clientRect.left_;			if ( (x >= clientRect.getWidth()) || ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {				line = P;				//scootch back				if ( (*P != ' ') && (*P != '\n') && (*P != '\r') ){					const VCFChar* tmp = P;					while ( (*P != ' ') && (*P != '\n') && (*P != '\r') && (P > start) ) {						P--;					}					lineOfText.erase( lineOfText.size()-(tmp-P), tmp-P );					line ++;				}				gc->textAt( clientRect.left_, y, lineOfText );				y += gc->getTextHeight( lineOfText );				x = clientRect.left_;				if ( ((*P == '\n') || ((*P == '\r') && (*(P+1) == '\n'))) ) {					if ( (*P == '\r') && (*(P+1) == '\n') ) {						P++;						line++;					}					line++;				}				lineOfText = "";			}			P++;		}		if ( (line < P) && ((P-line) < size) && (y < clientRect.getHeight()) ) {			lineOfText = "";			lineOfText.append( line, P-line );			gc->textAt( 0, y, lineOfText );		}		if ( NULL != caret ) {			Rect r( caret->x_, caret->y_, caret->x_ + 2, caret->y_ + gc->getTextHeight( "EM" ) );			gc->rectangle( &r );			gc->setColor( Color::getColor("blue") );			gc->fillPath();		}	}	updateRects_.clear();}void X11SimpleTextControl::onTextModelTextChanged( TextEvent* event ){	if ( NULL != event ){		String text = event->getChangeText();		if ( true == enabledSetTextOnControl_ ){			setText( text );		}	}}/***CVS Log info*$Log$*Revision 1.3  2005/07/09 23:14:59  ddiego*merging in changes from devmain-0-6-7 branch.**Revision 1.2.4.2  2005/04/30 11:52:36  marcelloptr*added a comment for the enabledSetTextOnControl_ member variable**Revision 1.2.4.1  2005/04/09 17:20:36  marcelloptr*bugfix [ 1179853 ] memory fixes around memset. Documentation. DocumentManager::saveAs and DocumentManager::reload**Revision 1.2  2004/08/07 02:49:12  ddiego*merged in the devmain-0-6-5 branch to stable**Revision 1.1.2.2  2004/04/29 03:43:16  marcelloptr*reformatting of source files: macros and csvlog and copyright sections**Revision 1.1.2.1  2004/04/28 00:28:21  ddiego*migration towards new directory structure**Revision 1.3  2003/05/17 20:37:40  ddiego*this is the checkin for the 0.6.1 release - represents the merge over from*the devmain-0-6-0 branch plus a few minor bug fixes**Revision 1.2.2.2  2003/03/23 03:23:58  marcelloptr*3 empty lines at the end of the files**Revision 1.2.2.1  2003/03/12 03:12:45  ddiego*switched all member variable that used the "m_"<name> prefix to* <name>"_" suffix nameing standard.*Also changed all vcf builder files to accomadate this.*Changes were made to the Stream classes to NOT multiple inheritance and to*be a little more correct. Changes include breaking the FileStream into two*distinct classes, one for input and one for output.**Revision 1.2  2003/02/26 04:30:52  ddiego*merge of code in the devmain-0-5-9 branch into the current tree.*most additions are in the area of the current linux port, but the major*addition to this release is the addition of a Condition class (currently*still under development) and the change over to using the Delegate class*exclusively from the older event handler macros.**Revision 1.1.2.1  2003/02/09 05:38:54  ddiego*added a VERY simple editable text control. It is dog slow though, but*better than nothing.*Auto generated C++ implementation for class X11SimpleTextControl*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?