diff options
Diffstat (limited to 'dggui/lineedit.cc')
-rw-r--r-- | dggui/lineedit.cc | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/dggui/lineedit.cc b/dggui/lineedit.cc new file mode 100644 index 0000000..14cc234 --- /dev/null +++ b/dggui/lineedit.cc @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * lineedit.cc + * + * Sun Oct 9 13:01:52 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "lineedit.h" + +#include <stdio.h> +#include <hugin.hpp> + +#define BORDER 10 + +namespace GUI { + +LineEdit::LineEdit(Widget *parent) + : Widget(parent) +{ + setReadOnly(false); +} + +LineEdit::~LineEdit() +{ +} + +void LineEdit::setReadOnly(bool ro) +{ + readonly = ro; +} + +bool LineEdit::readOnly() +{ + return readonly; +} + +void LineEdit::setText(const std::string& text) +{ + _text = text; + pos = text.size(); + + visibleText = _text; + offsetPos = 0; + + redraw(); + textChanged(); +} + +std::string LineEdit::getText() +{ + return _text; +} + +void LineEdit::buttonEvent(ButtonEvent *buttonEvent) +{ + if(readOnly()) + { + return; + } + + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->direction == Direction::down) + { + for(int i = 0; i < (int)visibleText.length(); ++i) + { + int textWidth = font.textWidth(visibleText.substr(0, i)); + if(buttonEvent->x < (textWidth + BORDER)) + { + pos = i + offsetPos; + break; + } + } + redraw(); + } +} + +void LineEdit::keyEvent(KeyEvent *keyEvent) +{ + if(readOnly()) + { + return; + } + + bool change = false; + + if(keyEvent->direction == Direction::down) + { + switch(keyEvent->keycode) { + case Key::left: + if(pos == 0) + { + return; + } + + pos--; + + if(offsetPos >= pos) + { + walkstate = WalkLeft; + } + break; + + case Key::right: + if(pos == _text.length()) + { + return; + } + + pos++; + + if((pos < _text.length()) && ((offsetPos + visibleText.length()) <= pos)) + { + walkstate = WalkRight; + } + break; + + case Key::home: + pos = 0; + visibleText = _text; + offsetPos = 0; + break; + + case Key::end: + pos = _text.length(); + visibleText = _text; + offsetPos = 0; + break; + + case Key::deleteKey: + if(pos < _text.length()) + { + std::string t = _text.substr(0, pos); + t += _text.substr(pos + 1, std::string::npos); + _text = t; + change = true; + } + break; + + case Key::backspace: + if(pos > 0) + { + std::string t = _text.substr(0, pos - 1); + t += _text.substr(pos, std::string::npos); + _text = t; + pos--; + change = true; + } + break; + + case Key::character: + { + std::string pre = _text.substr(0, pos); + std::string post = _text.substr(pos, std::string::npos); + _text = pre + keyEvent->text + post; + change = true; + pos++; + } + break; + + case Key::enter: + enterPressedNotifier(); + break; + + default: + break; + } + + redraw(); + } + + if(change) + { + textChanged(); + } +} + +void LineEdit::repaintEvent(RepaintEvent *repaintEvent) +{ + Painter p(*this); + + int w = width(); + int h = height(); + if((w == 0) || (h == 0)) + { + return; + } + + box.setSize(w, h); + p.drawImage(0, 0, box); + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + switch(walkstate) { + case WalkLeft: + visibleText = _text.substr(pos, std::string::npos); + offsetPos = pos; + break; + + case WalkRight: + { + int delta = (offsetPos < _text.length()) ? 1 : 0; + visibleText = _text.substr(offsetPos + delta); + offsetPos = offsetPos + delta; + } + break; + + case Noop: + visibleText = _text; + offsetPos = 0; + break; + } + + while(true) + { + int textWidth = font.textWidth(visibleText); + if(textWidth <= std::max(w - BORDER - 4 + 3, 0)) + { + break; + } + + switch(walkstate) { + case WalkLeft: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case WalkRight: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case Noop: + if(offsetPos < pos) + { + visibleText = visibleText.substr(1); + offsetPos++; + } + else + { + visibleText = visibleText.substr(0, visibleText.length() - 1); + } + break; + } + } + + walkstate = Noop; + + p.drawText(BORDER - 4 + 3, height() / 2 + 5 + 1 + 1 + 1, font, visibleText); + + if(readOnly()) + { + return; + } + + if(hasKeyboardFocus()) + { + size_t px = font.textWidth(visibleText.substr(0, pos - offsetPos)); + p.drawLine(px + BORDER - 1 - 4 + 3, 6, + px + BORDER - 1 - 4 + 3, height() - 7); + } +} + +} // GUI:: |