Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

CEGUIEditbox.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUIEditbox.cpp
00003         created:        13/4/2004
00004         author:         Paul D Turner
00005         
00006         purpose:        Implementation of Editbox base class widget
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 #include "elements/CEGUIEditbox.h"
00027 #include "CEGUITextUtils.h"
00028 #include "CEGUIExceptions.h"
00029 #include "CEGUIFont.h"
00030 #include "../pcre/pcre.h"
00031 #include <string.h>
00032 
00033 
00034 // Start of CEGUI namespace section
00035 namespace CEGUI
00036 {
00037 const String Editbox::EventNamespace("Editbox");
00038 
00043 struct RegexValidator
00044 {
00045         RegexValidator(void) : d_regex(0) {}
00046         ~RegexValidator(void) { release(); }
00047 
00048         void release()
00049         {
00050                 if (d_regex != 0)
00051                 {
00052                         pcre_free(d_regex);
00053                         d_regex = 0;
00054                 }
00055 
00056         }
00057 
00058         pcre* d_regex;
00059 };
00060 
00061 /*************************************************************************
00062         TODO:
00063 
00064         Clipboard support
00065         Undo support
00066 *************************************************************************/
00067 /*************************************************************************
00068         Definition of Properties
00069 *************************************************************************/
00070 EditboxProperties::ReadOnly                                     Editbox::d_readOnlyProperty;
00071 EditboxProperties::MaskText                                     Editbox::d_maskTextProperty;
00072 EditboxProperties::MaskCodepoint                        Editbox::d_maskCodepointProperty;
00073 EditboxProperties::ValidationString                     Editbox::d_validationStringProperty;
00074 EditboxProperties::CaratIndex                           Editbox::d_caratIndexProperty;
00075 EditboxProperties::SelectionStart                       Editbox::d_selectionStartProperty;
00076 EditboxProperties::SelectionLength                      Editbox::d_selectionLengthProperty;
00077 EditboxProperties::MaxTextLength                        Editbox::d_maxTextLengthProperty;
00078 EditboxProperties::NormalTextColour                     Editbox::d_normalTextColourProperty;
00079 EditboxProperties::SelectedTextColour           Editbox::d_selectedTextColourProperty;
00080 EditboxProperties::ActiveSelectionColour        Editbox::d_activeSelectionColourProperty;
00081 EditboxProperties::InactiveSelectionColour      Editbox::d_inactiveSelectionColourProperty;
00082 
00083 
00084 /*************************************************************************
00085         Constants
00086 *************************************************************************/
00087 // default colours
00088 const argb_t Editbox::DefaultNormalTextColour                   = 0xFFFFFFFF;
00089 const argb_t Editbox::DefaultSelectedTextColour                 = 0xFF000000;
00090 const argb_t Editbox::DefaultNormalSelectionColour              = 0xFF6060FF;
00091 const argb_t Editbox::DefaultInactiveSelectionColour    = 0xFF808080;
00092 
00093 
00094 /*************************************************************************
00095         Event name constants
00096 *************************************************************************/
00097 const String Editbox::EventReadOnlyModeChanged( (utf8*)"ReadOnlyChanged" );
00098 const String Editbox::EventMaskedRenderingModeChanged( (utf8*)"MaskRenderChanged" );
00099 const String Editbox::EventMaskCodePointChanged( (utf8*)"MaskCPChanged" );
00100 const String Editbox::EventValidationStringChanged( (utf8*)"ValidatorChanged" );
00101 const String Editbox::EventMaximumTextLengthChanged( (utf8*)"MaxTextLenChanged" );
00102 const String Editbox::EventTextInvalidated( (utf8*)"TextInvalidated" );
00103 const String Editbox::EventInvalidEntryAttempted( (utf8*)"InvalidInputAttempt" );
00104 const String Editbox::EventCaratMoved( (utf8*)"TextCaratMoved" );
00105 const String Editbox::EventTextSelectionChanged( (utf8*)"TextSelectChanged" );
00106 const String Editbox::EventEditboxFull( (utf8*)"EditboxFull" );
00107 const String Editbox::EventTextAccepted( (utf8*)"TextAccepted" );
00108 
00109 
00110 /*************************************************************************
00111         Constructor for Editbox class.
00112 *************************************************************************/
00113 Editbox::Editbox(const String& type, const String& name) :
00114         Window(type, name),
00115         d_readOnly(false),
00116         d_maskText(false),
00117         d_maskCodePoint('*'),
00118         d_maxTextLen(String::max_size()),
00119         d_caratPos(0),
00120         d_selectionStart(0),
00121         d_selectionEnd(0),
00122         d_dragging(false),
00123         d_normalTextColour(DefaultNormalTextColour),
00124         d_selectTextColour(DefaultSelectedTextColour),
00125         d_selectBrushColour(DefaultNormalSelectionColour),
00126         d_inactiveSelectBrushColour(DefaultInactiveSelectionColour)
00127 {
00128         d_validator = new RegexValidator;
00129 
00130         addEditboxEvents();
00131         addEditboxProperties();
00132 
00133         // default to accepting all characters
00134         setValidationString((utf8*)".*");
00135 }
00136 
00137 
00138 /*************************************************************************
00139         Destructor for Editbox class.
00140 *************************************************************************/
00141 Editbox::~Editbox(void)
00142 {
00143         delete d_validator;
00144 }
00145 
00146 
00147 /*************************************************************************
00148         return true if the Editbox has input focus.
00149 *************************************************************************/
00150 bool Editbox::hasInputFocus(void) const
00151 {
00152         return isActive();
00153 }
00154 
00155 
00156 /*************************************************************************
00157         return true if the Editbox text is valid given the currently set
00158         validation string.
00159 *************************************************************************/
00160 bool Editbox::isTextValid(void) const
00161 {
00162         return isStringValid(d_text);
00163 }
00164 
00165 
00166 /*************************************************************************
00167         return the current selection start point.
00168 *************************************************************************/
00169 size_t Editbox::getSelectionStartIndex(void) const
00170 {
00171         return (d_selectionStart != d_selectionEnd) ? d_selectionStart : d_caratPos;
00172 }
00173 
00174 
00175 /*************************************************************************
00176         return the current selection end point.
00177 *************************************************************************/
00178 size_t Editbox::getSelectionEndIndex(void) const
00179 {
00180         return (d_selectionStart != d_selectionEnd) ? d_selectionEnd : d_caratPos;
00181 }
00182 
00183 
00184 /*************************************************************************
00185         return the length of the current selection
00186         (in code points / characters).
00187 *************************************************************************/
00188 size_t Editbox::getSelectionLength(void) const
00189 {
00190         return d_selectionEnd - d_selectionStart;
00191 }
00192 
00193 
00194 /*************************************************************************
00195         Specify whether the Editbox is read-only.
00196 *************************************************************************/
00197 void Editbox::setReadOnly(bool setting)
00198 {
00199         // if setting is changed
00200         if (d_readOnly != setting)
00201         {
00202                 d_readOnly = setting;
00203                 WindowEventArgs args(this);
00204                 onReadOnlyChanged(args);
00205         }
00206 
00207 }
00208 
00209 
00210 /*************************************************************************
00211         Specify whether the text for the Editbox will be rendered masked.
00212 *************************************************************************/
00213 void Editbox::setTextMasked(bool setting)
00214 {
00215         // if setting is changed
00216         if (d_maskText != setting)
00217         {
00218                 d_maskText = setting;
00219                 WindowEventArgs args(this);
00220                 onMaskedRenderingModeChanged(args);
00221         }
00222 
00223 }
00224 
00225 
00226 /*************************************************************************
00227         Set the text validation string.
00228 *************************************************************************/
00229 void Editbox::setValidationString(const String& validation_string)
00230 {
00231         if (d_validationString != validation_string)
00232         {
00233                 d_validationString = validation_string;
00234                 d_validator->release();
00235 
00236                 // try to compile this new regex string
00237                 const char* prce_error;
00238                 int pcre_erroff;
00239                 d_validator->d_regex = pcre_compile(d_validationString.c_str(), PCRE_UTF8, &prce_error, &pcre_erroff, 0);
00240 
00241                 // handle failure
00242                 if (d_validator->d_regex == 0)
00243                 {
00244                         throw InvalidRequestException("The Editbox named '" + getName() + "' had the following bad validation expression set: '" + validation_string + "'.  Additional Information: " + prce_error);                    
00245                 }
00246 
00247                 // notification
00248                 WindowEventArgs args(this);
00249                 onValidationStringChanged(args);
00250 
00251                 if (!isTextValid())
00252                 {
00253                         // also notify if text is now invalid.
00254                         onTextInvalidatedEvent(args);
00255                 }
00256 
00257         }
00258 
00259 }
00260 
00261 
00262 /*************************************************************************
00263         Set the current position of the carat.
00264 *************************************************************************/
00265 void Editbox::setCaratIndex(size_t carat_pos)
00266 {
00267         // make sure new position is valid
00268         if (carat_pos > d_text.length())
00269         {
00270                 carat_pos = d_text.length();
00271         }
00272 
00273         // if new position is different
00274         if (d_caratPos != carat_pos)
00275         {
00276                 d_caratPos = carat_pos;
00277 
00278                 // Trigger "carat moved" event
00279                 WindowEventArgs args(this);
00280                 onCaratMoved(args);
00281         }
00282 
00283 }
00284 
00285 
00286 /*************************************************************************
00287         Define the current selection for the Editbox
00288 *************************************************************************/
00289 void Editbox::setSelection(size_t start_pos, size_t end_pos)
00290 {
00291         // ensure selection start point is within the valid range
00292         if (start_pos > d_text.length())
00293         {
00294                 start_pos = d_text.length();
00295         }
00296 
00297         // ensure selection end point is within the valid range
00298         if (end_pos > d_text.length())
00299         {
00300                 end_pos = d_text.length();
00301         }
00302 
00303         // ensure start is before end
00304         if (start_pos > end_pos)
00305         {
00306                 size_t tmp = end_pos;
00307                 end_pos = start_pos;
00308                 start_pos = tmp;
00309         }
00310 
00311         // only change state if values are different.
00312         if ((start_pos != d_selectionStart) || (end_pos != d_selectionEnd))
00313         {
00314                 // setup selection
00315                 d_selectionStart = start_pos;
00316                 d_selectionEnd   = end_pos;
00317 
00318                 // Trigger "selection changed" event
00319                 WindowEventArgs args(this);
00320                 onTextSelectionChanged(args);
00321         }
00322 
00323 }
00324 
00325 
00326 /*************************************************************************
00327         set the utf32 code point used when rendering masked text.
00328 *************************************************************************/
00329 void Editbox::setMaskCodePoint(utf32 code_point)
00330 {
00331         if (code_point != d_maskCodePoint)
00332         {
00333                 d_maskCodePoint = code_point;
00334 
00335                 // Trigger "mask code point changed" event
00336                 WindowEventArgs args(this);
00337                 onMaskCodePointChanged(args);
00338         }
00339 
00340 }
00341 
00342 
00343 /*************************************************************************
00344         set the maximum text length for this Editbox.
00345 *************************************************************************/
00346 void Editbox::setMaxTextLength(size_t max_len)
00347 {
00348         if (d_maxTextLen != max_len)
00349         {
00350                 d_maxTextLen = max_len;
00351                 
00352                 // Trigger max length changed event
00353                 WindowEventArgs args(this);
00354                 onMaximumTextLengthChanged(args);
00355 
00356                 // trim string
00357                 if (d_text.length() > d_maxTextLen)
00358                 {
00359                         d_text.resize(d_maxTextLen);
00360                         onTextChanged(args);
00361 
00362                         // see if new text is valid
00363                         if (!isTextValid())
00364                         {
00365                                 // Trigger Text is invalid event.
00366                                 onTextInvalidatedEvent(args);
00367                         }
00368 
00369                 }
00370 
00371         }
00372 
00373 }
00374 
00375 
00376 /*************************************************************************
00377         Clear the current selection setting     
00378 *************************************************************************/
00379 void Editbox::clearSelection(void)
00380 {
00381         // perform action only if required.
00382         if (getSelectionLength() != 0)
00383         {
00384                 setSelection(0, 0);
00385         }
00386 
00387 }
00388 
00389 
00390 /*************************************************************************
00391         Erase the currently selected text.
00392 *************************************************************************/
00393 void Editbox::eraseSelectedText(bool modify_text)
00394 {
00395         if (getSelectionLength() != 0)
00396         {
00397                 // setup new carat position and remove selection highlight.
00398                 setCaratIndex(getSelectionStartIndex());
00399                 clearSelection();
00400 
00401                 // erase the selected characters (if required)
00402                 if (modify_text)
00403                 {
00404                         d_text.erase(getSelectionStartIndex(), getSelectionLength());
00405 
00406                         // trigger notification that text has changed.
00407                         WindowEventArgs args(this);
00408                         onTextChanged(args);
00409                 }
00410 
00411         }
00412 
00413 }
00414 
00415 
00416 /*************************************************************************
00417         return true if the given string matches the validation regular
00418         expression.     
00419 *************************************************************************/
00420 bool Editbox::isStringValid(const String& str) const
00421 {
00422         // if the regex is not valid, then an exception is thrown
00423         if (d_validator->d_regex == 0)
00424         {
00425                 throw InvalidRequestException("Editbox::isStringValid - An attempt was made to use the invalid RegEx '" + d_validationString + "'.");
00426         }
00427 
00428         const char* utf8str = str.c_str();
00429         int     match[3];
00430         int len = static_cast<int>(strlen(utf8str));
00431         int result = pcre_exec(d_validator->d_regex, NULL, utf8str, len, 0, 0, match, 3);
00432 
00433         if (result >= 0)
00434         {
00435                 // this ensures that any regex match is for the entire string
00436                 return (match[1] - match[0] == len);
00437         }
00438         // invalid string if there's no match or if string or regex is NULL.
00439         else if ((result == PCRE_ERROR_NOMATCH) || (result == PCRE_ERROR_NULL))
00440         {
00441                 return false;
00442         }
00443         // anything else is an error.
00444         else
00445         {
00446                 throw InvalidRequestException("Editbox::isStringValid - An internal error occurred while attempting to match the invalid RegEx '" + d_validationString + "'.");
00447         }
00448 
00449 }
00450 
00451 
00452 /*************************************************************************
00453         Handler for mouse button pushed events
00454 *************************************************************************/
00455 void Editbox::onMouseButtonDown(MouseEventArgs& e)
00456 {
00457         // base class handling
00458         Window::onMouseButtonDown(e);
00459 
00460         if (e.button == LeftButton)
00461         {
00462                 // grab inputs
00463                 if (captureInput())
00464                 {
00465                         // handle mouse down
00466                         clearSelection();
00467                         d_dragging = true;
00468                         d_dragAnchorIdx = getTextIndexFromPosition(e.position);
00469                         setCaratIndex(d_dragAnchorIdx);
00470                 }
00471 
00472                 e.handled = true;
00473         }
00474 
00475 }
00476 
00477 /*************************************************************************
00478         Handler for mouse button release events
00479 *************************************************************************/
00480 void Editbox::onMouseButtonUp(MouseEventArgs& e)
00481 {
00482         // base class processing
00483         Window::onMouseButtonUp(e);
00484 
00485         if (e.button == LeftButton)
00486         {
00487                 releaseInput();
00488                 e.handled = true;
00489         }
00490 
00491 }
00492 
00493 
00494 /*************************************************************************
00495         Handler for mouse double-clicks
00496 *************************************************************************/
00497 void Editbox::onMouseDoubleClicked(MouseEventArgs& e)
00498 {
00499         // base class processing
00500         Window::onMouseDoubleClicked(e);
00501 
00502         if (e.button == LeftButton)
00503         {
00504                 // if masked, set up to select all
00505                 if (isTextMasked())
00506                 {
00507                         d_dragAnchorIdx = 0;
00508                         setCaratIndex(d_text.length());
00509                 }
00510                 // not masked, so select the word that was double-clicked.
00511                 else
00512                 {
00513                         d_dragAnchorIdx = TextUtils::getWordStartIdx(d_text, (d_caratPos == d_text.length()) ? d_caratPos : d_caratPos + 1);
00514                         d_caratPos              = TextUtils::getNextWordStartIdx(d_text, d_caratPos);
00515                 }
00516 
00517                 // perform actual selection operation.
00518                 setSelection(d_dragAnchorIdx, d_caratPos);
00519 
00520                 e.handled = true;
00521         }
00522 
00523 }
00524 
00525 
00526 /*************************************************************************
00527         Handler for mouse triple-clicks
00528 *************************************************************************/
00529 void Editbox::onMouseTripleClicked(MouseEventArgs& e)
00530 {
00531         // base class processing
00532         Window::onMouseTripleClicked(e);
00533 
00534         if (e.button == LeftButton)
00535         {
00536                 d_dragAnchorIdx = 0;
00537                 setCaratIndex(d_text.length());
00538                 setSelection(d_dragAnchorIdx, d_caratPos);
00539                 e.handled = true;
00540         }
00541 
00542 }
00543 
00544 
00545 /*************************************************************************
00546         Handler for mouse movements
00547 *************************************************************************/
00548 void Editbox::onMouseMove(MouseEventArgs& e)
00549 {
00550         // base class processing
00551         Window::onMouseMove(e);
00552 
00553         if (d_dragging)
00554         {
00555                 setCaratIndex(getTextIndexFromPosition(e.position));
00556                 setSelection(d_caratPos, d_dragAnchorIdx);
00557         }
00558 
00559         e.handled = true;
00560 }
00561 
00562 /*************************************************************************
00563         Handler for when input capture is lost
00564 *************************************************************************/
00565 void Editbox::onCaptureLost(WindowEventArgs& e)
00566 {
00567         d_dragging = false;
00568 
00569         // base class processing
00570         Window::onCaptureLost(e);
00571 
00572         e.handled = true;
00573 }
00574 
00575 /*************************************************************************
00576         Handler for type characters
00577 *************************************************************************/
00578 void Editbox::onCharacter(KeyEventArgs& e)
00579 {
00580         // base class processing
00581         Window::onCharacter(e);
00582 
00583         // only need to take notice if we have focus
00584         if (hasInputFocus() && getFont()->isCodepointAvailable(e.codepoint) && !isReadOnly())
00585         {
00586                 // backup current text
00587                 String tmp(d_text);
00588                 tmp.erase(getSelectionStartIndex(), getSelectionLength());
00589 
00590                 // if there is room
00591                 if (tmp.length() < d_maxTextLen)
00592                 {
00593                         tmp.insert(getSelectionStartIndex(), 1, e.codepoint);
00594 
00595                         if (isStringValid(tmp))
00596                         {
00597                                 // erase selection using mode that does not modify d_text (we just want to update state)
00598                                 eraseSelectedText(false);
00599 
00600                 // advance carat (done first so we can "do stuff" in event handlers!)
00601                 d_caratPos++;
00602 
00603                 // set text to the newly modified string
00604                                 setText(tmp);
00605                         }
00606                         else
00607                         {
00608                                 // Trigger invalid modification attempted event.
00609                                 WindowEventArgs args(this);
00610                                 onInvalidEntryAttempted(args);
00611                         }
00612 
00613                 }
00614                 else
00615                 {
00616                         // Trigger text box full event
00617                         WindowEventArgs args(this);
00618                         onEditboxFullEvent(args);
00619                 }
00620 
00621         }
00622 
00623         e.handled = true;
00624 }
00625 
00626 
00627 /*************************************************************************
00628         Handler for key-down events
00629 *************************************************************************/
00630 void Editbox::onKeyDown(KeyEventArgs& e)
00631 {
00632         // base class processing
00633         Window::onKeyDown(e);
00634 
00635         if (hasInputFocus() && !isReadOnly())
00636         {
00637                 WindowEventArgs args(this);
00638                 switch (e.scancode)
00639                 {
00640                 case Key::LeftShift:
00641                 case Key::RightShift:
00642                         if (getSelectionLength() == 0)
00643                         {
00644                                 d_dragAnchorIdx = getCaratIndex();
00645                         }
00646                         break;
00647 
00648                 case Key::Backspace:
00649                         handleBackspace();
00650                         break;
00651 
00652                 case Key::Delete:
00653                         handleDelete();
00654                         break;
00655 
00656                 case Key::Tab:
00657                 case Key::Return:
00658                 case Key::NumpadEnter:
00659                         // Fire 'input accepted' event
00660                         onTextAcceptedEvent(args);
00661                         break;
00662 
00663                 case Key::ArrowLeft:
00664                         if (e.sysKeys & Control)
00665                         {
00666                                 handleWordLeft(e.sysKeys);
00667                         }
00668                         else
00669                         {
00670                                 handleCharLeft(e.sysKeys);
00671                         }
00672                         break;
00673 
00674                 case Key::ArrowRight:
00675                         if (e.sysKeys & Control)
00676                         {
00677                                 handleWordRight(e.sysKeys);
00678                         }
00679                         else
00680                         {
00681                                 handleCharRight(e.sysKeys);
00682                         }
00683                         break;
00684 
00685                 case Key::Home:
00686                         handleHome(e.sysKeys);
00687                         break;
00688 
00689                 case Key::End:
00690                         handleEnd(e.sysKeys);
00691                         break;
00692 
00693         // default case is now to leave event as (possibly) unhandled.
00694         default:
00695             return;
00696                 }
00697 
00698                 e.handled = true;
00699         }
00700 
00701 }
00702 
00703 
00704 /*************************************************************************
00705         Processing for backspace key    
00706 *************************************************************************/
00707 void Editbox::handleBackspace(void)
00708 {
00709         if (!isReadOnly())
00710         {
00711                 String tmp(d_text);
00712 
00713                 if (getSelectionLength() != 0)
00714                 {
00715                         tmp.erase(getSelectionStartIndex(), getSelectionLength());
00716 
00717                         if (isStringValid(tmp))
00718                         {
00719                                 // erase selection using mode that does not modify d_text (we just want to update state)
00720                                 eraseSelectedText(false);
00721 
00722                                 // set text to the newly modified string
00723                                 setText(tmp);
00724                         }
00725                         else
00726                         {
00727                                 // Trigger invalid modification attempted event.
00728                                 WindowEventArgs args(this);
00729                                 onInvalidEntryAttempted(args);
00730                         }
00731 
00732                 }
00733                 else if (getCaratIndex() > 0)
00734                 {
00735                         tmp.erase(d_caratPos - 1, 1);
00736 
00737                         if (isStringValid(tmp))
00738                         {
00739                                 setCaratIndex(d_caratPos - 1);
00740 
00741                                 // set text to the newly modified string
00742                                 setText(tmp);
00743                         }
00744                         else
00745                         {
00746                                 // Trigger invalid modification attempted event.
00747                                 WindowEventArgs args(this);
00748                                 onInvalidEntryAttempted(args);
00749                         }
00750 
00751                 }
00752 
00753         }
00754 
00755 }
00756 
00757 
00758 /*************************************************************************
00759         Processing for Delete key       
00760 *************************************************************************/
00761 void Editbox::handleDelete(void)
00762 {
00763         if (!isReadOnly())
00764         {
00765                 String tmp(d_text);
00766 
00767                 if (getSelectionLength() != 0)
00768                 {
00769                         tmp.erase(getSelectionStartIndex(), getSelectionLength());
00770 
00771                         if (isStringValid(tmp))
00772                         {
00773                                 // erase selection using mode that does not modify d_text (we just want to update state)
00774                                 eraseSelectedText(false);
00775 
00776                                 // set text to the newly modified string
00777                                 setText(tmp);
00778                         }
00779                         else
00780                         {
00781                                 // Trigger invalid modification attempted event.
00782                                 WindowEventArgs args(this);
00783                                 onInvalidEntryAttempted(args);
00784                         }
00785 
00786                 }
00787                 else if (getCaratIndex() < tmp.length())
00788                 {
00789                         tmp.erase(d_caratPos, 1);
00790 
00791                         if (isStringValid(tmp))
00792                         {
00793                                 // set text to the newly modified string
00794                                 setText(tmp);
00795                         }
00796                         else
00797                         {
00798                                 // Trigger invalid modification attempted event.
00799                                 WindowEventArgs args(this);
00800                                 onInvalidEntryAttempted(args);
00801                         }
00802 
00803                 }
00804 
00805         }
00806 
00807 }
00808 
00809 
00810 /*************************************************************************
00811         Move the carat one character to the left.
00812 *************************************************************************/
00813 void Editbox::handleCharLeft(uint sysKeys)
00814 {
00815         if (d_caratPos > 0)
00816         {
00817                 setCaratIndex(d_caratPos - 1);
00818         }
00819 
00820         if (sysKeys & Shift)
00821         {
00822                 setSelection(d_caratPos, d_dragAnchorIdx);      
00823         }
00824         else
00825         {
00826                 clearSelection();
00827         }
00828 
00829 }
00830 
00831 
00832 /*************************************************************************
00833         Move the carat one word to the left
00834 *************************************************************************/
00835 void Editbox::handleWordLeft(uint sysKeys)
00836 {
00837         if (d_caratPos > 0)
00838         {
00839                 setCaratIndex(TextUtils::getWordStartIdx(d_text, getCaratIndex()));
00840         }
00841 
00842         if (sysKeys & Shift)
00843         {
00844                 setSelection(d_caratPos, d_dragAnchorIdx);      
00845         }
00846         else
00847         {
00848                 clearSelection();
00849         }
00850 
00851 }
00852 
00853 
00854 /*************************************************************************
00855         Move the carat one character to the right.
00856 *************************************************************************/
00857 void Editbox::handleCharRight(uint sysKeys)
00858 {
00859         if (d_caratPos < d_text.length())
00860         {
00861                 setCaratIndex(d_caratPos + 1);
00862         }
00863 
00864         if (sysKeys & Shift)
00865         {
00866                 setSelection(d_caratPos, d_dragAnchorIdx);      
00867         }
00868         else
00869         {
00870                 clearSelection();
00871         }
00872 
00873 }
00874 
00875 
00876 /*************************************************************************
00877         Move the carat one word to the right
00878 *************************************************************************/
00879 void Editbox::handleWordRight(uint sysKeys)
00880 {
00881         if (d_caratPos < d_text.length())
00882         {
00883                 setCaratIndex(TextUtils::getNextWordStartIdx(d_text, getCaratIndex()));
00884         }
00885 
00886         if (sysKeys & Shift)
00887         {
00888                 setSelection(d_caratPos, d_dragAnchorIdx);      
00889         }
00890         else
00891         {
00892                 clearSelection();
00893         }
00894 
00895 }
00896 
00897 
00898 /*************************************************************************
00899         Move the carat to the start of the text
00900 *************************************************************************/
00901 void Editbox::handleHome(uint sysKeys)
00902 {
00903         if (d_caratPos > 0)
00904         {
00905                 setCaratIndex(0);
00906         }
00907 
00908         if (sysKeys & Shift)
00909         {
00910                 setSelection(d_caratPos, d_dragAnchorIdx);      
00911         }
00912         else
00913         {
00914                 clearSelection();
00915         }
00916 
00917 }
00918 
00919 
00920 /*************************************************************************
00921         Move the carat to the end of the text.  
00922 *************************************************************************/
00923 void Editbox::handleEnd(uint sysKeys)
00924 {
00925         if (d_caratPos < d_text.length())
00926         {
00927                 setCaratIndex(d_text.length());
00928         }
00929 
00930         if (sysKeys & Shift)
00931         {
00932                 setSelection(d_caratPos, d_dragAnchorIdx);      
00933         }
00934         else
00935         {
00936                 clearSelection();
00937         }
00938 
00939 }
00940 
00941 
00942 /*************************************************************************
00943         Add edit box specific events
00944 *************************************************************************/
00945 void Editbox::addEditboxEvents(void)
00946 {
00947         addEvent(EventReadOnlyModeChanged);                             addEvent(EventMaskedRenderingModeChanged);
00948         addEvent(EventMaskCodePointChanged);                    addEvent(EventValidationStringChanged);
00949         addEvent(EventMaximumTextLengthChanged);                addEvent(EventTextInvalidated);
00950         addEvent(EventInvalidEntryAttempted);                   addEvent(EventCaratMoved);
00951         addEvent(EventTextSelectionChanged);                    addEvent(EventEditboxFull);
00952         addEvent(EventTextAccepted);
00953 }
00954 
00955 
00956 /*************************************************************************
00957         Event fired internally when the read only state of the Editbox has
00958         been changed
00959 *************************************************************************/
00960 void Editbox::onReadOnlyChanged(WindowEventArgs& e)
00961 {
00962         requestRedraw();
00963         fireEvent(EventReadOnlyModeChanged, e, EventNamespace);
00964 }
00965 
00966 
00967 /*************************************************************************
00968         Event fired internally when the masked rendering mode (password mode)
00969         has been changed
00970 *************************************************************************/
00971 void Editbox::onMaskedRenderingModeChanged(WindowEventArgs& e)
00972 {
00973         requestRedraw();
00974         fireEvent(EventMaskedRenderingModeChanged , e, EventNamespace);
00975 }
00976 
00977 
00978 /*************************************************************************
00979         Event fired internally when the code point to use for masked
00980         rendering has been changed.
00981 *************************************************************************/
00982 void Editbox::onMaskCodePointChanged(WindowEventArgs& e)
00983 {
00984         // if we are in masked mode, trigger a GUI redraw.
00985         if (isTextMasked())
00986         {
00987                 requestRedraw();
00988         }
00989 
00990         fireEvent(EventMaskCodePointChanged , e, EventNamespace);
00991 }
00992 
00993 
00994 /*************************************************************************
00995         Event fired internally when the validation string is changed.   
00996 *************************************************************************/
00997 void Editbox::onValidationStringChanged(WindowEventArgs& e)
00998 {
00999         fireEvent(EventValidationStringChanged , e, EventNamespace);
01000 }
01001 
01002 
01003 /*************************************************************************
01004         Event fired internally when the maximum text length for the edit box
01005         is changed.     
01006 *************************************************************************/
01007 void Editbox::onMaximumTextLengthChanged(WindowEventArgs& e)
01008 {
01009         fireEvent(EventMaximumTextLengthChanged , e, EventNamespace);
01010 }
01011 
01012 
01013 /*************************************************************************
01014         Event fired internally when something has caused the current text to
01015         now fail validation     
01016 *************************************************************************/
01017 void Editbox::onTextInvalidatedEvent(WindowEventArgs& e)
01018 {
01019         fireEvent(EventTextInvalidated, e, EventNamespace);
01020 }
01021 
01022 
01023 /*************************************************************************
01024         Event fired internally when the user attempted to make a change to
01025         the edit box that would have caused it to fail validation.
01026 *************************************************************************/
01027 void Editbox::onInvalidEntryAttempted(WindowEventArgs& e)
01028 {
01029         fireEvent(EventInvalidEntryAttempted , e, EventNamespace);
01030 }
01031 
01032 
01033 /*************************************************************************
01034         Event fired internally when the carat (insert point) position changes.  
01035 *************************************************************************/
01036 void Editbox::onCaratMoved(WindowEventArgs& e)
01037 {
01038         requestRedraw();
01039         fireEvent(EventCaratMoved , e, EventNamespace);
01040 }
01041 
01042 
01043 /*************************************************************************
01044         Event fired internally when the current text selection changes. 
01045 *************************************************************************/
01046 void Editbox::onTextSelectionChanged(WindowEventArgs& e)
01047 {
01048         requestRedraw();
01049         fireEvent(EventTextSelectionChanged , e, EventNamespace);
01050 }
01051 
01052 
01053 /*************************************************************************
01054         Event fired internally when the edit box text has reached the set
01055         maximum length. 
01056 *************************************************************************/
01057 void Editbox::onEditboxFullEvent(WindowEventArgs& e)
01058 {
01059         fireEvent(EventEditboxFull, e, EventNamespace);
01060 }
01061 
01062 
01063 /*************************************************************************
01064         Event fired internally when the user accepts the edit box text by
01065         pressing Return, Enter, or Tab. 
01066 *************************************************************************/
01067 void Editbox::onTextAcceptedEvent(WindowEventArgs& e)
01068 {
01069         fireEvent(EventTextAccepted, e, EventNamespace);
01070 }
01071 
01072 
01073 /*************************************************************************
01074         Set the colour to be used for rendering Editbox text in the normal,
01075         unselected state.       
01076 *************************************************************************/
01077 void Editbox::setNormalTextColour(const colour& col)
01078 {
01079         d_normalTextColour = col;
01080         requestRedraw();
01081 }
01082 
01083 
01084 /*************************************************************************
01085         Set the colour to be used for rendering the Editbox text when within
01086         the selected region.
01087 *************************************************************************/
01088 void Editbox::setSelectedTextColour(const colour& col)
01089 {
01090         d_selectTextColour = col;
01091         requestRedraw();
01092 }
01093 
01094 
01095 /*************************************************************************
01096         Set the colour to be used for rendering the Editbox selection highlight
01097         when the Editbox is active.
01098 *************************************************************************/
01099 void Editbox::setNormalSelectBrushColour(const colour& col)
01100 {
01101         d_selectBrushColour = col;
01102         requestRedraw();
01103 }
01104 
01105 
01106 /*************************************************************************
01107         Set the colour to be used for rendering the Editbox selection highlight
01108         when the Editbox is inactive.
01109 *************************************************************************/
01110 void Editbox::setInactiveSelectBrushColour(const colour& col)
01111 {
01112         d_inactiveSelectBrushColour = col;
01113         requestRedraw();
01114 }
01115 
01116 
01117 /*************************************************************************
01118         Handler for when text is changed programmatically
01119 *************************************************************************/
01120 void Editbox::onTextChanged(WindowEventArgs& e)
01121 {
01122         // base class processing
01123         Window::onTextChanged(e);
01124 
01125         // clear selection
01126         clearSelection();
01127 
01128         // make sure carat is within the text
01129         if (getCaratIndex() > d_text.length())
01130         {
01131                 setCaratIndex(d_text.length());
01132         }
01133 
01134         e.handled = true;
01135 }
01136 
01137 /*************************************************************************
01138         Add properties
01139 *************************************************************************/
01140 void Editbox::addEditboxProperties(void)
01141 {
01142         addProperty(&d_readOnlyProperty);
01143         addProperty(&d_maskTextProperty);
01144         addProperty(&d_maskCodepointProperty);
01145         addProperty(&d_validationStringProperty);
01146         addProperty(&d_caratIndexProperty);
01147         addProperty(&d_selectionStartProperty);
01148         addProperty(&d_selectionLengthProperty);
01149         addProperty(&d_maxTextLengthProperty);
01150         addProperty(&d_normalTextColourProperty);
01151         addProperty(&d_selectedTextColourProperty);
01152         addProperty(&d_activeSelectionColourProperty);
01153         addProperty(&d_inactiveSelectionColourProperty);
01154 }
01155 
01156 
01157 } // End of  CEGUI namespace section

Generated on Wed Sep 7 09:56:31 2005 for Crazy Eddies GUI System by  doxygen 1.4.3