Back to index

nux  3.0.0
EditTextBox.cpp
Go to the documentation of this file.
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 char *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                = "";
00042     m_Suffix                = "";
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->time_expires.connect(sigc::mem_fun(this, &EditTextBox::BlinkCursorTimerInterrupt));
00074 
00075     m_ScrollTimerFunctor = new TimerFunctor();
00076     m_ScrollTimerFunctor->time_expires.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     Event &event = GetGraphicsDisplay()->GetCurrentEvent();
00098 
00099     int X = event.x;
00100     m_KeyboardHandler.CaretAutoScroll(event.x, event.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   void EditTextBox::Draw(GraphicsEngine &graphics_engine, bool force_draw)
00151   {
00152     Geometry base = GetGeometry();
00153 
00154     {
00155       graphics_engine.PushClippingRectangle(base);
00156 
00157       GetPainter().Paint2DQuadColor(graphics_engine, base, Color(m_BackgroundColor));
00158 
00159       if (HasKeyboardFocus())
00160       {
00161 
00162         GetPainter().PaintColorTextLineEdit(graphics_engine, GetGeometry(),
00163                                          m_KeyboardHandler.GetTextLine(),
00164                                          GetTextColor(),
00165                                          m_WriteAlpha,
00166                                          m_SelectedTextColor,
00167                                          m_SelectedTextBackgroundColor,
00168                                          m_TextBlinkColor,
00169                                          m_CursorColor,
00170                                          !BlinkCursor,
00171                                          m_KeyboardHandler.GetCursorPosition(),
00172                                          m_KeyboardHandler.GetPositionX(),
00173                                          m_KeyboardHandler.GetTextSelectionStart(),
00174                                          m_KeyboardHandler.GetTextSelectionEnd()
00175                                         );
00176       }
00177       else
00178       {
00179         GetPainter().PaintTextLineStatic(graphics_engine, GetFont(), GetGeometry(),
00180                                       m_KeyboardHandler.GetTextLine(),
00181                                       GetTextColor());
00182       }
00183     }
00184     graphics_engine.PopClippingRectangle();
00185   }
00186 
00187   void EditTextBox::DrawContent(GraphicsEngine &graphics_engine, bool force_draw)
00188   {
00189 
00190   }
00191 
00192   void EditTextBox::PostDraw(GraphicsEngine &graphics_engine, bool force_draw)
00193   {
00194 
00195   }
00196 
00197   void EditTextBox::SetText(const char &Caption)
00198   {
00199     NString s(Caption);
00200     SetText(s);
00201   }
00202 
00203   void EditTextBox::SetText(const char *Caption)
00204   {
00205     NString s(Caption);
00206     SetText(s);
00207   }
00208 
00209   void EditTextBox::SetText(const tstring &Caption)
00210   {
00211     NString s(Caption);
00212     SetText(s);
00213   }
00214 
00215   void EditTextBox::SetText(const NString &Caption)
00216   {
00217     NString s(Caption);
00218     s.RemovePrefix(m_Prefix);
00219     s.RemoveSuffix(m_Suffix);
00220 
00221     if (ValidateKeyboardEntry(s.GetTCharPtr()))
00222     {
00223       m_Text = (m_Prefix + s) + m_Suffix;
00224       m_KeyboardHandler.SetText(m_Text.GetTStringRef());
00225       m_temporary_caption = m_Text;
00226       sigSetText.emit(this);
00227     }
00228 
00229     QueueDraw();
00230   }
00231 
00232 
00233   const char *EditTextBox::GetText() const
00234   {
00235     return m_Text.GetTCharPtr();
00236   }
00237 
00239   NString EditTextBox::GetCleanText() const
00240   {
00241     NString CleanText(m_Text);
00242     CleanText.RemovePrefix(m_Prefix);
00243     CleanText.RemoveSuffix(m_Suffix);
00244     return CleanText.m_string;
00245   }
00246 
00247   void EditTextBox::RecvMouseDoubleClick(int x, int y, unsigned long button_flags, unsigned long key_flags)
00248   {
00249     m_KeyboardHandler.SelectAllText();
00250     QueueDraw();
00251   }
00252 
00253   void EditTextBox::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
00254   {
00255     m_KeyboardHandler.MouseUp(x, y);
00256 
00257     if (m_ScrollTimerHandler.IsValid())
00258     {
00259       GetTimer().RemoveTimerHandler(m_ScrollTimerHandler);
00260       m_ScrollTimerHandler = 0;
00261     }
00262 
00263     QueueDraw();
00264   }
00265 
00266   void EditTextBox::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
00267   {
00268     if (HasKeyboardFocus() == false)
00269     {
00270       // First mouse down
00271       m_KeyboardHandler.EnterFocus();
00272     }
00273     else
00274     {
00275       // Second mouse down and more
00276       m_KeyboardHandler.UnselectAllText();
00277       m_KeyboardHandler.MouseDown(x, y);
00278 
00279       // Always make the cursor visible when a mouse down happens.
00280       StopBlinkCursor(false);
00281       StartBlinkCursor(false);
00282     }
00283 
00284     QueueDraw();
00285   }
00286 
00287   void EditTextBox::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00288   {
00289     Geometry base = GetGeometry();
00290 
00291     int X = x + base.x;
00292 
00293     if ((!m_ScrollTimerHandler.IsValid()) && ((X < base.x) || (X > base.x + base.GetWidth())))
00294     {
00295       m_ScrollTimerHandler = GetTimer().AddTimerHandler(25, m_ScrollTimerFunctor, this);
00296     }
00297     else if ((X >= base.x) && (X < base.x + base.GetWidth()))
00298     {
00299       m_KeyboardHandler.MouseDrag(x, y);
00300 
00301       // While the mouse is selecting the text, no blinking of cursor
00302       StopBlinkCursor(false);
00303       StartBlinkCursor(false);
00304     }
00305 
00306     QueueDraw();
00307   }
00308 
00309   long EditTextBox::PostLayoutManagement(long LayoutResult)
00310   {
00311     long ret = View::PostLayoutManagement(LayoutResult);
00312 
00313     m_KeyboardHandler.SetClipRegion(GetGeometry());
00314     return ret;
00315   }
00316 
00317 
00318   void EditTextBox::RecvKeyEvent(
00319     unsigned long   eventType  , /*event type*/
00320     unsigned long   keysym     , /*event keysym*/
00321     unsigned long   state      , /*event state*/
00322     const char*     character  , /*character*/
00323     unsigned short  keyCount     /*key repeat count*/)
00324   {
00325     
00326     if (eventType == NUX_KEYDOWN)
00327       text_input_mode_ = true;
00328 
00329     m_KeyboardHandler.ProcessKey(eventType, keysym, state, character[0], GetGeometry());
00330 
00331 
00332     // When a key event happens, show the cursor.
00333     StopBlinkCursor(false);
00334     // Start a new blink cycle with the cursor originally visible.
00335     StartBlinkCursor(false);
00336 
00337     if (character)
00338     {
00339       sigCharacter.emit(this, character[0]);
00340       sigEditChange.emit(this);
00341     }
00342 
00343     if (keysym == NUX_VK_ENTER || keysym == NUX_KP_ENTER)
00344     {
00345       NString str(m_KeyboardHandler.GetTextLine());
00346       str.RemoveSuffix(m_Suffix);
00347 
00348       if (ValidateKeyboardEntry(str.m_string.c_str()))
00349       {
00350         m_Text = m_KeyboardHandler.GetTextLine();
00351         m_temporary_caption = m_Text;
00352         sigValidateKeyboardEntry.emit(this, m_Text);
00353         sigValidateEntry.emit(this);
00354         m_KeyboardHandler.SelectAllText();
00355       }
00356       else
00357       {
00358         m_Text = m_temporary_caption;
00359         m_KeyboardHandler.SetText(m_Text);
00360         m_KeyboardHandler.SelectAllText();
00361       }
00362     }
00363 
00364     if (keysym == NUX_VK_ESCAPE)
00365     {
00366       text_input_mode_ = false;
00367     }
00368 
00369     QueueDraw();
00370   }
00371 
00372   bool EditTextBox::ValidateKeyboardEntry(const char *text) const
00373   {
00374     if (m_Validator)
00375     {
00376       if (m_Validator->Validate(text) == Validator::Acceptable)
00377       {
00378         return true;
00379       }
00380       else
00381       {
00382         return false;
00383       }
00384     }
00385 
00386     return true;
00387   }
00388 
00389   void EditTextBox::EscapeKeyboardFocus()
00390   {
00391     // todo(jaytaoko): SetKeyboardFocus(false);
00392     // Revert back the caption text
00393     m_Text = m_temporary_caption;
00394     sigEscapeKeyboardFocus.emit(this);
00395     QueueDraw();
00396   }
00397 
00398   void EditTextBox::EnteringKeyboardFocus()
00399   {
00400     m_KeyboardHandler.SetText(m_Text.GetTStringRef());
00401     m_KeyboardHandler.SelectAllText();
00402     // Preserve the current caption text. If ESC is pressed while we have keyboard focus then
00403     // the previous caption text is restored
00404     m_temporary_caption = m_Text;
00405     sigStartKeyboardFocus.emit(this);
00406     QueueDraw();
00407   }
00408 
00409   void EditTextBox::QuitingKeyboardFocus()
00410   {
00411     NString CleanText(m_KeyboardHandler.GetTextLine());
00412     CleanText.RemovePrefix(m_Prefix);
00413     CleanText.RemoveSuffix(m_Suffix);
00414 
00415     if (ValidateKeyboardEntry(CleanText.GetTCharPtr()))
00416     {
00417       CleanText = m_Prefix + CleanText;
00418       CleanText = CleanText + m_Suffix;
00419 
00420       m_Text = CleanText.m_string; //m_KeyboardHandler.GetTextLine();
00421       m_KeyboardHandler.SetText(CleanText.m_string);
00422       m_temporary_caption = m_Text;
00423       sigValidateKeyboardEntry.emit(this, m_Text.GetTStringRef());
00424       sigValidateEntry.emit(this);
00425     }
00426     else
00427     {
00428       m_Text = m_temporary_caption;
00429       m_KeyboardHandler.SetText(m_Text.GetTStringRef());
00430       m_KeyboardHandler.SelectAllText();
00431     }
00432 
00433     QueueDraw();
00434   }
00435 
00436   void EditTextBox::RecvStartKeyFocus()
00437   {
00438     key_nav_mode_     = true;
00439     text_input_mode_  = false;
00440     
00441     EnteringKeyboardFocus();
00442     m_BlinkTimerHandler = GetTimer().AddTimerHandler(500, m_BlinkTimerFunctor, this);
00443   }
00444 
00445   void EditTextBox::RecvEndKeyFocus()
00446   {
00447     key_nav_mode_     = false;
00448     text_input_mode_  = false;
00449 
00450     QuitingKeyboardFocus();
00451     GetTimer().RemoveTimerHandler(m_BlinkTimerHandler);
00452     m_BlinkTimerHandler = 0;
00453     BlinkCursor = false;
00454   }
00455 
00456   void EditTextBox::SetDoubleValue(double d)
00457   {
00458     SetText(NString::Printf("%f", d));
00459   }
00460 
00461   void EditTextBox::SetIntegerValue(int i)
00462   {
00463     SetText(NString::Printf("%d", i));
00464   }
00465 
00466   void EditTextBox::SetTextBackgroundColor(const Color &color)
00467   {
00468     m_BackgroundColor = color;
00469     QueueDraw();
00470   }
00471 
00472   Color EditTextBox::GetTextBackgroundColor() const
00473   {
00474     return m_BackgroundColor;
00475   }
00476 
00477   bool EditTextBox::IsEmpty()
00478   {
00479     if (m_Text == "")
00480     {
00481       return true;
00482     }
00483 
00484     return false;
00485   }
00486 
00487   bool EditTextBox::InspectKeyEvent(unsigned int eventType,
00488     unsigned int keysym,
00489     const char* character)
00490   {
00491     if ((eventType == NUX_KEYDOWN) && (key_nav_mode_ == true) && (text_input_mode_ == false))
00492     {
00493       if (keysym == NUX_VK_ENTER ||
00494         keysym == NUX_KP_ENTER ||
00495         keysym == NUX_VK_UP ||
00496         keysym == NUX_VK_DOWN ||
00497         keysym == NUX_VK_LEFT ||
00498         keysym == NUX_VK_RIGHT ||
00499         keysym == NUX_VK_LEFT_TAB ||
00500         keysym == NUX_VK_TAB)
00501       {
00502         return false;
00503       }
00504     }
00505 
00506     if ((eventType == NUX_KEYDOWN) && (key_nav_mode_ == false) && (text_input_mode_ == false))
00507     {
00508       return false;
00509     }
00510 
00511     return true;
00512   }
00513 }