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

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 ulong     Editbox::DefaultNormalTextColour                        = 0x00FFFFFF;
00089 const ulong     Editbox::DefaultSelectedTextColour                      = 0x00000000;
00090 const ulong     Editbox::DefaultNormalSelectionColour           = 0x006060FF;
00091 const ulong     Editbox::DefaultInactiveSelectionColour         = 0x00808080;
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 ulong 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 ulong 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 ulong 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(ulong 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(ulong start_pos, ulong 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                 ulong 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(ulong 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 = 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 
00694                 e.handled = true;
00695         }
00696 
00697 }
00698 
00699 
00700 /*************************************************************************
00701         Processing for backspace key    
00702 *************************************************************************/
00703 void Editbox::handleBackspace(void)
00704 {
00705         if (!isReadOnly())
00706         {
00707                 String tmp(d_text);
00708 
00709                 if (getSelectionLength() != 0)
00710                 {
00711                         tmp.erase(getSelectionStartIndex(), getSelectionLength());
00712 
00713                         if (isStringValid(tmp))
00714                         {
00715                                 // erase selection using mode that does not modify d_text (we just want to update state)
00716                                 eraseSelectedText(false);
00717 
00718                                 // set text to the newly modified string
00719                                 setText(tmp);
00720                         }
00721                         else
00722                         {
00723                                 // Trigger invalid modification attempted event.
00724                                 WindowEventArgs args(this);
00725                                 onInvalidEntryAttempted(args);
00726                         }
00727 
00728                 }
00729                 else if (getCaratIndex() > 0)
00730                 {
00731                         tmp.erase(d_caratPos - 1, 1);
00732 
00733                         if (isStringValid(tmp))
00734                         {
00735                                 setCaratIndex(d_caratPos - 1);
00736 
00737                                 // set text to the newly modified string
00738                                 setText(tmp);
00739                         }
00740                         else
00741                         {
00742                                 // Trigger invalid modification attempted event.
00743                                 WindowEventArgs args(this);
00744                                 onInvalidEntryAttempted(args);
00745                         }
00746 
00747                 }
00748 
00749         }
00750 
00751 }
00752 
00753 
00754 /*************************************************************************
00755         Processing for Delete key       
00756 *************************************************************************/
00757 void Editbox::handleDelete(void)
00758 {
00759         if (!isReadOnly())
00760         {
00761                 String tmp(d_text);
00762 
00763                 if (getSelectionLength() != 0)
00764                 {
00765                         tmp.erase(getSelectionStartIndex(), getSelectionLength());
00766 
00767                         if (isStringValid(tmp))
00768                         {
00769                                 // erase selection using mode that does not modify d_text (we just want to update state)
00770                                 eraseSelectedText(false);
00771 
00772                                 // set text to the newly modified string
00773                                 setText(tmp);
00774                         }
00775                         else
00776                         {
00777                                 // Trigger invalid modification attempted event.
00778                                 WindowEventArgs args(this);
00779                                 onInvalidEntryAttempted(args);
00780                         }
00781 
00782                 }
00783                 else if (getCaratIndex() < tmp.length())
00784                 {
00785                         tmp.erase(d_caratPos, 1);
00786 
00787                         if (isStringValid(tmp))
00788                         {
00789                                 // set text to the newly modified string
00790                                 setText(tmp);
00791                         }
00792                         else
00793                         {
00794                                 // Trigger invalid modification attempted event.
00795                                 WindowEventArgs args(this);
00796                                 onInvalidEntryAttempted(args);
00797                         }
00798 
00799                 }
00800 
00801         }
00802 
00803 }
00804 
00805 
00806 /*************************************************************************
00807         Move the carat one character to the left.
00808 *************************************************************************/
00809 void Editbox::handleCharLeft(uint sysKeys)
00810 {
00811         if (d_caratPos > 0)
00812         {
00813                 setCaratIndex(d_caratPos - 1);
00814         }
00815 
00816         if (sysKeys & Shift)
00817         {
00818                 setSelection(d_caratPos, d_dragAnchorIdx);      
00819         }
00820         else
00821         {
00822                 clearSelection();
00823         }
00824 
00825 }
00826 
00827 
00828 /*************************************************************************
00829         Move the carat one word to the left
00830 *************************************************************************/
00831 void Editbox::handleWordLeft(uint sysKeys)
00832 {
00833         if (d_caratPos > 0)
00834         {
00835                 setCaratIndex(TextUtils::getWordStartIdx(d_text, getCaratIndex()));
00836         }
00837 
00838         if (sysKeys & Shift)
00839         {
00840                 setSelection(d_caratPos, d_dragAnchorIdx);      
00841         }
00842         else
00843         {
00844                 clearSelection();
00845         }
00846 
00847 }
00848 
00849 
00850 /*************************************************************************
00851         Move the carat one character to the right.
00852 *************************************************************************/
00853 void Editbox::handleCharRight(uint sysKeys)
00854 {
00855         if (d_caratPos < d_text.length())
00856         {
00857                 setCaratIndex(d_caratPos + 1);
00858         }
00859 
00860         if (sysKeys & Shift)
00861         {
00862                 setSelection(d_caratPos, d_dragAnchorIdx);      
00863         }
00864         else
00865         {
00866                 clearSelection();
00867         }
00868 
00869 }
00870 
00871 
00872 /*************************************************************************
00873         Move the carat one word to the right
00874 *************************************************************************/
00875 void Editbox::handleWordRight(uint sysKeys)
00876 {
00877         if (d_caratPos < d_text.length())
00878         {
00879                 setCaratIndex(TextUtils::getNextWordStartIdx(d_text, getCaratIndex()));
00880         }
00881 
00882         if (sysKeys & Shift)
00883         {
00884                 setSelection(d_caratPos, d_dragAnchorIdx);      
00885         }
00886         else
00887         {
00888                 clearSelection();
00889         }
00890 
00891 }
00892 
00893 
00894 /*************************************************************************
00895         Move the carat to the start of the text
00896 *************************************************************************/
00897 void Editbox::handleHome(uint sysKeys)
00898 {
00899         if (d_caratPos > 0)
00900         {
00901                 setCaratIndex(0);
00902         }
00903 
00904         if (sysKeys & Shift)
00905         {
00906                 setSelection(d_caratPos, d_dragAnchorIdx);      
00907         }
00908         else
00909         {
00910                 clearSelection();
00911         }
00912 
00913 }
00914 
00915 
00916 /*************************************************************************
00917         Move the carat to the end of the text.  
00918 *************************************************************************/
00919 void Editbox::handleEnd(uint sysKeys)
00920 {
00921         if (d_caratPos < d_text.length())
00922         {
00923                 setCaratIndex(d_text.length());
00924         }
00925 
00926         if (sysKeys & Shift)
00927         {
00928                 setSelection(d_caratPos, d_dragAnchorIdx);      
00929         }
00930         else
00931         {
00932                 clearSelection();
00933         }
00934 
00935 }
00936 
00937 
00938 /*************************************************************************
00939         Add edit box specific events
00940 *************************************************************************/
00941 void Editbox::addEditboxEvents(void)
00942 {
00943         addEvent(EventReadOnlyModeChanged);                             addEvent(EventMaskedRenderingModeChanged);
00944         addEvent(EventMaskCodePointChanged);                    addEvent(EventValidationStringChanged);
00945         addEvent(EventMaximumTextLengthChanged);                addEvent(EventTextInvalidated);
00946         addEvent(EventInvalidEntryAttempted);                   addEvent(EventCaratMoved);
00947         addEvent(EventTextSelectionChanged);                    addEvent(EventEditboxFull);
00948         addEvent(EventTextAccepted);
00949 }
00950 
00951 
00952 /*************************************************************************
00953         Event fired internally when the read only state of the Editbox has
00954         been changed
00955 *************************************************************************/
00956 void Editbox::onReadOnlyChanged(WindowEventArgs& e)
00957 {
00958         requestRedraw();
00959         fireEvent(EventReadOnlyModeChanged, e, EventNamespace);
00960 }
00961 
00962 
00963 /*************************************************************************
00964         Event fired internally when the masked rendering mode (password mode)
00965         has been changed
00966 *************************************************************************/
00967 void Editbox::onMaskedRenderingModeChanged(WindowEventArgs& e)
00968 {
00969         requestRedraw();
00970         fireEvent(EventMaskedRenderingModeChanged , e, EventNamespace);
00971 }
00972 
00973 
00974 /*************************************************************************
00975         Event fired internally when the code point to use for masked
00976         rendering has been changed.
00977 *************************************************************************/
00978 void Editbox::onMaskCodePointChanged(WindowEventArgs& e)
00979 {
00980         // if we are in masked mode, trigger a GUI redraw.
00981         if (isTextMasked())
00982         {
00983                 requestRedraw();
00984         }
00985 
00986         fireEvent(EventMaskCodePointChanged , e, EventNamespace);
00987 }
00988 
00989 
00990 /*************************************************************************
00991         Event fired internally when the validation string is changed.   
00992 *************************************************************************/
00993 void Editbox::onValidationStringChanged(WindowEventArgs& e)
00994 {
00995         fireEvent(EventValidationStringChanged , e, EventNamespace);
00996 }
00997 
00998 
00999 /*************************************************************************
01000         Event fired internally when the maximum text length for the edit box
01001         is changed.     
01002 *************************************************************************/
01003 void Editbox::onMaximumTextLengthChanged(WindowEventArgs& e)
01004 {
01005         fireEvent(EventMaximumTextLengthChanged , e, EventNamespace);
01006 }
01007 
01008 
01009 /*************************************************************************
01010         Event fired internally when something has caused the current text to
01011         now fail validation     
01012 *************************************************************************/
01013 void Editbox::onTextInvalidatedEvent(WindowEventArgs& e)
01014 {
01015         fireEvent(EventTextInvalidated, e, EventNamespace);
01016 }
01017 
01018 
01019 /*************************************************************************
01020         Event fired internally when the user attempted to make a change to
01021         the edit box that would have caused it to fail validation.
01022 *************************************************************************/
01023 void Editbox::onInvalidEntryAttempted(WindowEventArgs& e)
01024 {
01025         fireEvent(EventInvalidEntryAttempted , e, EventNamespace);
01026 }
01027 
01028 
01029 /*************************************************************************
01030         Event fired internally when the carat (insert point) position changes.  
01031 *************************************************************************/
01032 void Editbox::onCaratMoved(WindowEventArgs& e)
01033 {
01034         requestRedraw();
01035         fireEvent(EventCaratMoved , e, EventNamespace);
01036 }
01037 
01038 
01039 /*************************************************************************
01040         Event fired internally when the current text selection changes. 
01041 *************************************************************************/
01042 void Editbox::onTextSelectionChanged(WindowEventArgs& e)
01043 {
01044         requestRedraw();
01045         fireEvent(EventTextSelectionChanged , e, EventNamespace);
01046 }
01047 
01048 
01049 /*************************************************************************
01050         Event fired internally when the edit box text has reached the set
01051         maximum length. 
01052 *************************************************************************/
01053 void Editbox::onEditboxFullEvent(WindowEventArgs& e)
01054 {
01055         fireEvent(EventEditboxFull, e, EventNamespace);
01056 }
01057 
01058 
01059 /*************************************************************************
01060         Event fired internally when the user accepts the edit box text by
01061         pressing Return, Enter, or Tab. 
01062 *************************************************************************/
01063 void Editbox::onTextAcceptedEvent(WindowEventArgs& e)
01064 {
01065         fireEvent(EventTextAccepted, e, EventNamespace);
01066 }
01067 
01068 
01069 /*************************************************************************
01070         Set the colour to be used for rendering Editbox text in the normal,
01071         unselected state.       
01072 *************************************************************************/
01073 void Editbox::setNormalTextColour(const colour& col)
01074 {
01075         d_normalTextColour = col;
01076         requestRedraw();
01077 }
01078 
01079 
01080 /*************************************************************************
01081         Set the colour to be used for rendering the Editbox text when within
01082         the selected region.
01083 *************************************************************************/
01084 void Editbox::setSelectedTextColour(const colour& col)
01085 {
01086         d_selectTextColour = col;
01087         requestRedraw();
01088 }
01089 
01090 
01091 /*************************************************************************
01092         Set the colour to be used for rendering the Editbox selection highlight
01093         when the Editbox is active.
01094 *************************************************************************/
01095 void Editbox::setNormalSelectBrushColour(const colour& col)
01096 {
01097         d_selectBrushColour = col;
01098         requestRedraw();
01099 }
01100 
01101 
01102 /*************************************************************************
01103         Set the colour to be used for rendering the Editbox selection highlight
01104         when the Editbox is inactive.
01105 *************************************************************************/
01106 void Editbox::setInactiveSelectBrushColour(const colour& col)
01107 {
01108         d_inactiveSelectBrushColour = col;
01109         requestRedraw();
01110 }
01111 
01112 
01113 /*************************************************************************
01114         Handler for when text is changed programmatically
01115 *************************************************************************/
01116 void Editbox::onTextChanged(WindowEventArgs& e)
01117 {
01118         // base class processing
01119         Window::onTextChanged(e);
01120 
01121         // clear selection
01122         clearSelection();
01123 
01124         // make sure carat is within the text
01125         if (getCaratIndex() > d_text.length())
01126         {
01127                 setCaratIndex(d_text.length());
01128         }
01129 
01130         e.handled = true;
01131 }
01132 
01133 /*************************************************************************
01134         Add properties
01135 *************************************************************************/
01136 void Editbox::addEditboxProperties(void)
01137 {
01138         addProperty(&d_readOnlyProperty);
01139         addProperty(&d_maskTextProperty);
01140         addProperty(&d_maskCodepointProperty);
01141         addProperty(&d_validationStringProperty);
01142         addProperty(&d_caratIndexProperty);
01143         addProperty(&d_selectionStartProperty);
01144         addProperty(&d_selectionLengthProperty);
01145         addProperty(&d_maxTextLengthProperty);
01146         addProperty(&d_normalTextColourProperty);
01147         addProperty(&d_selectedTextColourProperty);
01148         addProperty(&d_activeSelectionColourProperty);
01149         addProperty(&d_inactiveSelectionColourProperty);
01150 }
01151 
01152 
01153 } // End of  CEGUI namespace section

Generated on Wed Feb 16 12:41:05 2005 for Crazy Eddies GUI System by  doxygen 1.3.9.1