textfield.cpp

00001 /*      _______   __   __   __   ______   __   __   _______   __   __
00002  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
00003  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
00004  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
00005  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
00006  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
00007  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
00008  *
00009  * Copyright (c) 2004, 2005, 2006 Olof Naessén and Per Larsson
00010  *
00011  *                                                         Js_./
00012  * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
00013  * Olof Naessén a.k.a jansem/yakslem                _asww7!uY`>  )\a//
00014  *                                                 _Qhm`] _f "'c  1!5m
00015  * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
00016  *                                               .)j(] .d_/ '-(  P .   S
00017  * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
00018  * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
00019  * binary forms, with or without                 )4d[#7r, .   '     )d`)[
00020  * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
00021  * that the following conditions are met:       j<<WP+k/);.        _W=j f
00022  * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
00023  *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
00024  *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
00025  *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
00026  * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
00027  *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
00028  *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
00029  *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
00030  *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
00031  *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
00032  * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
00033  *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
00034  *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
00035  *    from this software without specific        (js, \[QQW$QWW#?!V"".
00036  *    prior written permission.                    ]y:.<\..          .
00037  *                                                 -]n w/ '         [.
00038  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
00039  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
00040  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
00041  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
00042  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
00043  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
00044  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
00045  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
00046  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
00047  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
00048  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
00049  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
00050  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00052  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00053  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00054  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00055  */
00056 
00057 /*
00058  * For comments regarding functions please see the header file.
00059  */
00060 
00061 #include "guichan/widgets/textfield.hpp"
00062 
00063 #include "guichan/font.hpp"
00064 #include "guichan/graphics.hpp"
00065 #include "guichan/key.hpp"
00066 #include "guichan/mouseinput.hpp"
00067 
00068 namespace gcn
00069 {
00070     TextField::TextField()
00071     {
00072         mCaretPosition = 0;
00073         mXScroll = 0;
00074 
00075         setFocusable(true);
00076 
00077         addMouseListener(this);
00078         addKeyListener(this);
00079         adjustHeight();
00080         setBorderSize(1);
00081     }
00082 
00083     TextField::TextField(const std::string& text)
00084     {
00085         mCaretPosition = 0;
00086         mXScroll = 0;
00087 
00088         mText = text;
00089         adjustSize();
00090         setBorderSize(1);
00091 
00092         setFocusable(true);
00093 
00094         addMouseListener(this);
00095         addKeyListener(this);
00096     }
00097 
00098     void TextField::setText(const std::string& text)
00099     {
00100         if(text.size() < mCaretPosition )
00101         {
00102             mCaretPosition = text.size();
00103         }
00104 
00105         mText = text;
00106     }
00107 
00108     void TextField::draw(Graphics* graphics)
00109     {
00110         Color faceColor = getBackgroundColor();
00111         graphics->setColor(faceColor);
00112         graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
00113 
00114         if (isFocused())
00115         {
00116             drawCaret(graphics, getFont()->getWidth(mText.substr(0, mCaretPosition)) - mXScroll);
00117         }
00118 
00119         graphics->setColor(getForegroundColor());
00120         graphics->setFont(getFont());
00121         graphics->drawText(mText, 1 - mXScroll, 1);
00122     }
00123 
00124     void TextField::drawBorder(Graphics* graphics)
00125     {
00126         Color faceColor = getBaseColor();
00127         Color highlightColor, shadowColor;
00128         int alpha = getBaseColor().a;
00129         int width = getWidth() + getBorderSize() * 2 - 1;
00130         int height = getHeight() + getBorderSize() * 2 - 1;
00131         highlightColor = faceColor + 0x303030;
00132         highlightColor.a = alpha;
00133         shadowColor = faceColor - 0x303030;
00134         shadowColor.a = alpha;
00135 
00136         unsigned int i;
00137         for (i = 0; i < getBorderSize(); ++i)
00138         {
00139             graphics->setColor(shadowColor);
00140             graphics->drawLine(i,i, width - i, i);
00141             graphics->drawLine(i,i + 1, i, height - i - 1);
00142             graphics->setColor(highlightColor);
00143             graphics->drawLine(width - i,i + 1, width - i, height - i);
00144             graphics->drawLine(i,height - i, width - i - 1, height - i);
00145         }
00146     }
00147 
00148     void TextField::drawCaret(Graphics* graphics, int x)
00149     {
00150         graphics->setColor(getForegroundColor());
00151         graphics->drawLine(x, getHeight() - 2, x, 1);
00152     }
00153 
00154     void TextField::mousePress(int x, int y, int button)
00155     {
00156         if (hasMouse() && button == MouseInput::LEFT)
00157         {
00158             mCaretPosition = getFont()->getStringIndexAt(mText, x + mXScroll);
00159             fixScroll();
00160         }
00161     }
00162 
00163     void TextField::keyPress(const Key& key)
00164     {
00165         if (key.getValue() == Key::LEFT && mCaretPosition > 0)
00166         {
00167             --mCaretPosition;
00168         }
00169 
00170         else if (key.getValue() == Key::RIGHT && mCaretPosition < mText.size())
00171         {
00172             ++mCaretPosition;
00173         }
00174 
00175         else if (key.getValue() == Key::DELETE && mCaretPosition < mText.size())
00176         {
00177             mText.erase(mCaretPosition, 1);
00178         }
00179 
00180         else if (key.getValue() == Key::BACKSPACE && mCaretPosition > 0)
00181         {
00182             mText.erase(mCaretPosition - 1, 1);
00183             --mCaretPosition;
00184         }
00185 
00186         else if (key.getValue() == Key::ENTER)
00187         {
00188             generateAction();
00189         }
00190 
00191         else if (key.getValue() == Key::HOME)
00192         {
00193             mCaretPosition = 0;
00194         }
00195 
00196         else if (key.getValue() == Key::END)
00197         {
00198             mCaretPosition = mText.size();
00199         }
00200 
00201         else if (key.isCharacter())
00202         {
00203             mText.insert(mCaretPosition, std::string(1,(char)key.getValue()));
00204             ++mCaretPosition;
00205         }
00206 
00207         fixScroll();
00208     }
00209 
00210     void TextField::adjustSize()
00211     {
00212         setWidth(getFont()->getWidth(mText) + 4);
00213         adjustHeight();
00214 
00215         fixScroll();
00216     }
00217 
00218     void TextField::adjustHeight()
00219     {
00220         setHeight(getFont()->getHeight() + 2);
00221     }
00222 
00223     void TextField::fixScroll()
00224     {
00225         if (isFocused())
00226         {
00227             int caretX = getFont()->getWidth(mText.substr(0, mCaretPosition));
00228 
00229             if (caretX - mXScroll > getWidth() - 4)
00230             {
00231                 mXScroll = caretX - getWidth() + 4;
00232             }
00233             else if (caretX - mXScroll < getFont()->getWidth(" "))
00234             {
00235                 mXScroll = caretX - getFont()->getWidth(" ");
00236 
00237                 if (mXScroll < 0)
00238                 {
00239                     mXScroll = 0;
00240                 }
00241             }
00242         }
00243     }
00244 
00245     void TextField::setCaretPosition(unsigned int position)
00246     {
00247         if (position > mText.size())
00248         {
00249             mCaretPosition = mText.size();
00250         }
00251         else
00252         {
00253             mCaretPosition = position;
00254         }
00255 
00256         fixScroll();
00257     }
00258 
00259     unsigned int TextField::getCaretPosition() const
00260     {
00261         return mCaretPosition;
00262     }
00263 
00264     const std::string& TextField::getText() const
00265     {
00266         return mText;
00267     }
00268 
00269     void TextField::fontChanged()
00270     {
00271         fixScroll();
00272     }
00273 }

Generated on Sat Jul 29 19:38:48 2006 for Guichan by  doxygen 1.4.7