nux-1.14.0
EditTextBox.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 
00025 #include "EditTextBox.h"
00026 #include "Layout.h"
00027 #include "HLayout.h"
00028 #include "VLayout.h"
00029 #include "Validator.h"
00030 
00031 namespace nux
00032 {
00033   EditTextBox::EditTextBox (const TCHAR *Caption, NUX_FILE_LINE_DECL)
00034     :   View (NUX_FILE_LINE_PARAM)
00035   {
00036     m_Validator             = NULL;
00037     BlinkCursor             = false;
00038     m_ScrollTimerHandler    = 0;
00039     m_BlinkTimerFunctor     = 0;
00040     m_WriteAlpha            = true;
00041     m_Prefix                = TEXT("");
00042     m_Suffix                = TEXT("");
00043 
00044     key_nav_mode_           = false;
00045     text_input_mode_        = false;
00046 
00047     SetGeometry (Geometry (0, 0, 3 * DEFAULT_WIDGET_WIDTH, DEFAULT_WIDGET_HEIGHT) );
00048     SetMinimumSize (DEFAULT_WIDGET_WIDTH, PRACTICAL_WIDGET_HEIGHT);
00049     SetGeometry (Geometry (0, 0, 3 * DEFAULT_WIDGET_WIDTH, DEFAULT_WIDGET_HEIGHT) );
00050     mouse_down.connect (sigc::mem_fun (this, &EditTextBox::RecvMouseDown) );
00051     mouse_drag.connect (sigc::mem_fun (this, &EditTextBox::RecvMouseDrag) );
00052     mouse_up.connect (sigc::mem_fun (this, &EditTextBox::RecvMouseUp) );
00053     mouse_double_click.connect (sigc::mem_fun (this, &EditTextBox::RecvMouseDoubleClick) );
00054 
00055     key_down.connect (sigc::mem_fun (this, &EditTextBox::RecvKeyEvent) );
00056 
00057     begin_key_focus.connect (sigc::mem_fun (this, &EditTextBox::RecvStartKeyFocus) );
00058     end_key_focus.connect (sigc::mem_fun (this, &EditTextBox::RecvEndKeyFocus) );
00059 
00060     SetText (Caption);
00061     SetTextColor (color::White);
00062     m_BackgroundColor = Color (0xFF343434); //COLOR_TEXTEDIT_BACKGROUNG;
00063     m_SelectedTextColor = Color (0xFFFAFAFA);
00064     m_SelectedTextBackgroundColor = Color (0xFF777777);
00065     m_TextBlinkColor = Color (0xFF003D0A);
00066     m_CursorColor = Color (0xFFDDDDDD);
00067 
00068 
00069     hlayout = new HLayout (NUX_TRACKER_LOCATION);
00070     SetLayout(hlayout);
00071 
00072     m_BlinkTimerFunctor = new TimerFunctor();
00073     m_BlinkTimerFunctor->OnTimerExpired.connect (sigc::mem_fun (this, &EditTextBox::BlinkCursorTimerInterrupt) );
00074 
00075     m_ScrollTimerFunctor = new TimerFunctor();
00076     m_ScrollTimerFunctor->OnTimerExpired.connect (sigc::mem_fun (this, &EditTextBox::ScrollTimerInterrupt) );
00077 
00078     SetAcceptKeyboardEvent(true);
00079     EnableDoubleClick(true);
00080   }
00081 
00082   EditTextBox::~EditTextBox()
00083   {
00084     delete m_BlinkTimerFunctor;
00085     delete m_ScrollTimerFunctor;
00086     delete m_Validator;
00087 
00088     if (m_BlinkTimerHandler.IsValid() )
00089       GetTimer().RemoveTimerHandler (m_BlinkTimerHandler);
00090 
00091     m_BlinkTimerHandler = 0;
00092   }
00093 
00094   void EditTextBox::ScrollTimerInterrupt (void *v)
00095   {
00096     Geometry base = GetGeometry();
00097     IEvent &ievent = GetGraphicsDisplay()->GetCurrentEvent();
00098 
00099     int X = ievent.e_x;
00100     m_KeyboardHandler.CaretAutoScroll (ievent.e_x, ievent.e_y, base);
00101 
00102     if ( ( (X < base.x) && (m_KeyboardHandler.GetCursorPosition() > 0) ) ||
00103          ( (X > base.x + base.GetWidth() ) && (m_KeyboardHandler.GetCursorPosition() < m_KeyboardHandler.GetLength() ) ) )
00104     {
00105       m_ScrollTimerHandler = GetTimer().AddTimerHandler (50, m_ScrollTimerFunctor, this);
00106     }
00107     else
00108     {
00109       GetTimer().RemoveTimerHandler (m_BlinkTimerHandler);
00110       m_ScrollTimerHandler = 0;
00111     }
00112 
00113     // While the mouse is selecting the text, no blinking of cursor
00114     StopBlinkCursor (false);
00115     StartBlinkCursor (false);
00116 
00117     QueueDraw();
00118   }
00119 
00120   void EditTextBox::BlinkCursorTimerInterrupt (void *v)
00121   {
00122     GetTimer().RemoveTimerHandler (m_BlinkTimerHandler);
00123     m_BlinkTimerHandler = GetTimer().AddTimerHandler (500, m_BlinkTimerFunctor, this);
00124     BlinkCursor = !BlinkCursor;
00125     QueueDraw();
00126   }
00127 
00128   void EditTextBox::StopBlinkCursor (bool BlinkState)
00129   {
00130     GetTimer().RemoveTimerHandler (m_BlinkTimerHandler);
00131     m_BlinkTimerHandler = 0;
00132     BlinkCursor = BlinkState;
00133     QueueDraw();
00134   }
00135 
00136   void EditTextBox::StartBlinkCursor (bool BlinkState)
00137   {
00138     m_BlinkTimerHandler = GetTimer().AddTimerHandler (500, m_BlinkTimerFunctor, this);
00139     BlinkCursor = BlinkState;
00140     QueueDraw();
00141   }
00142 
00143   void EditTextBox::SetValidator (const Validator *validator)
00144   {
00145     nuxAssert (validator != 0);
00146     delete m_Validator;
00147     m_Validator = validator->Clone();
00148   }
00149 
00150   long EditTextBox::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00151   {
00152     long ret = TraverseInfo;
00153     ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
00154     return ret;
00155   }
00156 
00157   void EditTextBox::Draw (GraphicsEngine &GfxContext, bool force_draw)
00158   {
00159     Geometry base = GetGeometry();
00160 
00161     {
00162       GfxContext.PushClippingRectangle (base);
00163 
00164       GetPainter().Paint2DQuadColor (GfxContext, base, Color (m_BackgroundColor) );
00165 
00166       if (HasKeyboardFocus() )
00167       {
00168 
00169         GetPainter().PaintColorTextLineEdit (GfxContext, GetGeometry(),
00170                                          m_KeyboardHandler.GetTextLine(),
00171                                          GetTextColor(),
00172                                          m_WriteAlpha,
00173                                          m_SelectedTextColor,
00174                                          m_SelectedTextBackgroundColor,
00175                                          m_TextBlinkColor,
00176                                          m_CursorColor,
00177                                          !BlinkCursor,
00178                                          m_KeyboardHandler.GetCursorPosition(),
00179                                          m_KeyboardHandler.GetPositionX(),
00180                                          m_KeyboardHandler.GetTextSelectionStart(),
00181                                          m_KeyboardHandler.GetTextSelectionEnd()
00182                                         );
00183       }
00184       else
00185       {
00186         GetPainter().PaintTextLineStatic (GfxContext, GetFont (), GetGeometry(),
00187                                       m_KeyboardHandler.GetTextLine(),
00188                                       GetTextColor() );
00189       }
00190     }
00191     GfxContext.PopClippingRectangle();
00192   }
00193 
00194   void EditTextBox::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00195   {
00196 
00197   }
00198 
00199   void EditTextBox::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00200   {
00201 
00202   }
00203 
00204   void EditTextBox::SetText (const TCHAR &Caption)
00205   {
00206     NString s (Caption);
00207     SetText (s);
00208   }
00209 
00210   void EditTextBox::SetText (const TCHAR *Caption)
00211   {
00212     NString s (Caption);
00213     SetText (s);
00214   }
00215 
00216   void EditTextBox::SetText (const tstring &Caption)
00217   {
00218     NString s (Caption);
00219     SetText (s);
00220   }
00221 
00222   void EditTextBox::SetText (const NString &Caption)
00223   {
00224     NString s (Caption);
00225     s.RemovePrefix (m_Prefix);
00226     s.RemoveSuffix (m_Suffix);
00227 
00228     if (ValidateKeyboardEntry (s.GetTCharPtr ()))
00229     {
00230       m_Text = (m_Prefix + s) + m_Suffix;
00231       m_KeyboardHandler.SetText (m_Text.GetTStringRef ());
00232       m_temporary_caption = m_Text;
00233       sigSetText.emit (this);
00234     }
00235 
00236     QueueDraw();
00237   }
00238 
00239 
00240   const TCHAR *EditTextBox::GetText() const
00241   {
00242     return m_Text.GetTCharPtr();
00243   }
00244 
00246   NString EditTextBox::GetCleanText() const
00247   {
00248     NString CleanText (m_Text);
00249     CleanText.RemovePrefix (m_Prefix);
00250     CleanText.RemoveSuffix (m_Suffix);
00251     return CleanText.m_string;
00252   }
00253 
00254   void EditTextBox::RecvMouseDoubleClick (int x, int y, unsigned long button_flags, unsigned long key_flags)
00255   {
00256     m_KeyboardHandler.SelectAllText();
00257     QueueDraw();
00258   }
00259 
00260   void EditTextBox::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
00261   {
00262     m_KeyboardHandler.MouseUp (x, y);
00263 
00264     if (m_ScrollTimerHandler.IsValid() )
00265     {
00266       GetTimer().RemoveTimerHandler (m_ScrollTimerHandler);
00267       m_ScrollTimerHandler = 0;
00268     }
00269 
00270     QueueDraw();
00271   }
00272 
00273   void EditTextBox::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
00274   {
00275     if (HasKeyboardFocus() == false)
00276     {
00277       // First mouse down
00278       m_KeyboardHandler.EnterFocus();
00279     }
00280     else
00281     {
00282       // Second mouse down and more
00283       m_KeyboardHandler.UnselectAllText();
00284       m_KeyboardHandler.MouseDown (x, y);
00285 
00286       // Always make the cursor visible when a mouse down happens.
00287       StopBlinkCursor (false);
00288       StartBlinkCursor (false);
00289     }
00290 
00291     QueueDraw();
00292   }
00293 
00294   void EditTextBox::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00295   {
00296     Geometry base = GetGeometry();
00297 
00298     int X = x + base.x;
00299 
00300     if ( (!m_ScrollTimerHandler.IsValid() ) && ( (X < base.x) || (X > base.x + base.GetWidth() ) ) )
00301     {
00302       m_ScrollTimerHandler = GetTimer().AddTimerHandler (25, m_ScrollTimerFunctor, this);
00303     }
00304     else if ( (X >= base.x) && (X < base.x + base.GetWidth() ) )
00305     {
00306       m_KeyboardHandler.MouseDrag (x, y);
00307 
00308       // While the mouse is selecting the text, no blinking of cursor
00309       StopBlinkCursor (false);
00310       StartBlinkCursor (false);
00311     }
00312 
00313     QueueDraw();
00314   }
00315 
00316   long EditTextBox::PostLayoutManagement (long LayoutResult)
00317   {
00318     long ret = View::PostLayoutManagement (LayoutResult);
00319 
00320     m_KeyboardHandler.SetClipRegion (GetGeometry() );
00321     return ret;
00322   }
00323 
00324 
00325   void EditTextBox::RecvKeyEvent (
00326     unsigned long   eventType  , /*event type*/
00327     unsigned long   keysym     , /*event keysym*/
00328     unsigned long   state      , /*event state*/
00329     const TCHAR*    character  , /*character*/
00330     unsigned short  keyCount     /*key repeat count*/)
00331   {
00332     
00333     if (eventType == NUX_KEYDOWN)
00334       text_input_mode_ = true;
00335 
00336     m_KeyboardHandler.ProcessKey (eventType, keysym, state, character[0], GetGeometry() );
00337 
00338 
00339     // When a key event happens, show the cursor.
00340     StopBlinkCursor (false);
00341     // Start a new blink cycle with the cursor originally visible.
00342     StartBlinkCursor (false);
00343 
00344     if (character)
00345     {
00346       sigCharacter.emit (this, character[0]);
00347       sigEditChange.emit (this);
00348     }
00349 
00350     if (keysym == NUX_VK_ENTER || keysym == NUX_KP_ENTER)
00351     {
00352       NString str (m_KeyboardHandler.GetTextLine() );
00353       str.RemoveSuffix (m_Suffix);
00354 
00355       if (ValidateKeyboardEntry (str.m_string.c_str() ) )
00356       {
00357         m_Text = m_KeyboardHandler.GetTextLine();
00358         m_temporary_caption = m_Text;
00359         sigValidateKeyboardEntry.emit (this, m_Text);
00360         sigValidateEntry.emit (this);
00361         m_KeyboardHandler.SelectAllText();
00362       }
00363       else
00364       {
00365         m_Text = m_temporary_caption;
00366         m_KeyboardHandler.SetText (m_Text);
00367         m_KeyboardHandler.SelectAllText();
00368       }
00369     }
00370 
00371     if (keysym == NUX_VK_ESCAPE)
00372     {
00373       text_input_mode_ = false;
00374     }
00375 
00376     QueueDraw();
00377   }
00378 
00379   bool EditTextBox::ValidateKeyboardEntry (const TCHAR *text) const
00380   {
00381     if (m_Validator)
00382     {
00383       if (m_Validator->Validate (text) == Validator::Acceptable)
00384       {
00385         return true;
00386       }
00387       else
00388       {
00389         return false;
00390       }
00391     }
00392 
00393     return true;
00394   }
00395 
00396   void EditTextBox::EscapeKeyboardFocus()
00397   {
00398     SetKeyboardFocus (false);
00399     // Revert back the caption text
00400     m_Text = m_temporary_caption;
00401     sigEscapeKeyboardFocus.emit (this);
00402     QueueDraw();
00403   }
00404 
00405   void EditTextBox::EnteringKeyboardFocus()
00406   {
00407     m_KeyboardHandler.SetText (m_Text.GetTStringRef() );
00408     m_KeyboardHandler.SelectAllText();
00409     // Preserve the current caption text. If ESC is pressed while we have keyboard focus then
00410     // the previous caption text is restored
00411     m_temporary_caption = m_Text;
00412     sigStartKeyboardFocus.emit (this);
00413     QueueDraw();
00414   }
00415 
00416   void EditTextBox::QuitingKeyboardFocus()
00417   {
00418     NString CleanText (m_KeyboardHandler.GetTextLine() );
00419     CleanText.RemovePrefix (m_Prefix);
00420     CleanText.RemoveSuffix (m_Suffix);
00421 
00422     if (ValidateKeyboardEntry (CleanText.GetTCharPtr() ) )
00423     {
00424       CleanText = m_Prefix + CleanText;
00425       CleanText = CleanText + m_Suffix;
00426 
00427       m_Text = CleanText.m_string; //m_KeyboardHandler.GetTextLine();
00428       m_KeyboardHandler.SetText (CleanText.m_string);
00429       m_temporary_caption = m_Text;
00430       sigValidateKeyboardEntry.emit (this, m_Text.GetTStringRef() );
00431       sigValidateEntry.emit (this);
00432     }
00433     else
00434     {
00435       m_Text = m_temporary_caption;
00436       m_KeyboardHandler.SetText (m_Text.GetTStringRef() );
00437       m_KeyboardHandler.SelectAllText();
00438     }
00439 
00440     QueueDraw();
00441   }
00442 
00443   void EditTextBox::RecvStartKeyFocus()
00444   {
00445     key_nav_mode_     = true;
00446     text_input_mode_  = false;
00447     
00448     EnteringKeyboardFocus();
00449     m_BlinkTimerHandler = GetTimer().AddTimerHandler (500, m_BlinkTimerFunctor, this);
00450   }
00451 
00452   void EditTextBox::RecvEndKeyFocus()
00453   {
00454     key_nav_mode_     = false;
00455     text_input_mode_  = false;
00456 
00457     QuitingKeyboardFocus();
00458     GetTimer().RemoveTimerHandler (m_BlinkTimerHandler);
00459     m_BlinkTimerHandler = 0;
00460     BlinkCursor = false;
00461   }
00462 
00463   void EditTextBox::SetDoubleValue (double d)
00464   {
00465     SetText (NString::Printf ("%f", d) );
00466   }
00467 
00468   void EditTextBox::SetIntegerValue (int i)
00469   {
00470     SetText (NString::Printf ("%d", i) );
00471   }
00472 
00473   void EditTextBox::SetTextBackgroundColor (const Color &color)
00474   {
00475     m_BackgroundColor = color;
00476     QueueDraw();
00477   }
00478 
00479   Color EditTextBox::GetTextBackgroundColor() const
00480   {
00481     return m_BackgroundColor;
00482   }
00483 
00484   bool EditTextBox::IsEmpty()
00485   {
00486     if (m_Text == TEXT ("") )
00487     {
00488       return true;
00489     }
00490 
00491     return false;
00492   }
00493 
00494   bool EditTextBox::InspectKeyEvent(unsigned int eventType,
00495     unsigned int keysym,
00496     const char* character)
00497   {
00498     if ((eventType == NUX_KEYDOWN) && (key_nav_mode_ == true) && (text_input_mode_ == false))
00499     {
00500       if (keysym == NUX_VK_ENTER ||
00501         keysym == NUX_KP_ENTER ||
00502         keysym == NUX_VK_UP ||
00503         keysym == NUX_VK_DOWN ||
00504         keysym == NUX_VK_LEFT ||
00505         keysym == NUX_VK_RIGHT ||
00506         keysym == NUX_VK_LEFT_TAB ||
00507         keysym == NUX_VK_TAB)
00508       {
00509         return false;
00510       }
00511     }
00512 
00513     if ((eventType == NUX_KEYDOWN) && (key_nav_mode_ == false) && (text_input_mode_ == false))
00514     {
00515       return false;
00516     }
00517 
00518     return true;
00519   }
00520 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends