From 7473c2e0b0ac6d74773bebc247364be5a85792c0 Mon Sep 17 00:00:00 2001 From: fluxgen Date: Tue, 26 Aug 2003 23:24:48 +0000 Subject: text box for input --- src/FbTk/TextBox.cc | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/FbTk/TextBox.hh | 84 +++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 src/FbTk/TextBox.cc create mode 100644 src/FbTk/TextBox.hh diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc new file mode 100644 index 0000000..817c4f6 --- /dev/null +++ b/src/FbTk/TextBox.cc @@ -0,0 +1,287 @@ +// TextBox.cc for FbTk - fluxbox toolkit +// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id: TextBox.cc,v 1.1 2003/08/26 23:24:48 fluxgen Exp $ + +#include "TextBox.hh" +#include "Font.hh" +#include "EventManager.hh" +#include "App.hh" + +#include +#include +#include + +namespace FbTk { + +TextBox::TextBox(int screen_num, + const Font &font, const std::string &text): + FbWindow(screen_num, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask), + m_font(&font), + m_text(text), + m_gc(0), + m_cursor_pos(0), + m_start_pos(0), + m_end_pos(0) { + + FbTk::EventManager::instance()->add(*this, *this); +} + +TextBox::TextBox(const FbWindow &parent, + const Font &font, const std::string &text): + FbWindow(parent, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask), + m_font(&font), + m_text(text), + m_gc(0), + m_cursor_pos(0), + m_start_pos(0), + m_end_pos(0) { + + FbTk::EventManager::instance()->add(*this, *this); +} + +TextBox::~TextBox() { + +} + +void TextBox::setText(const std::string &text) { + m_text = text; + cursorEnd(); + adjustStartPos(); +} + +void TextBox::setFont(const Font &font) { + m_font = &font; +} + +void TextBox::setGC(GC gc) { + m_gc = gc; +} + +void TextBox::setInputFocus() { + XSetInputFocus(FbTk::App::instance()->display(), + window(), + RevertToParent, + CurrentTime); +} + +void TextBox::cursorHome() { + m_start_pos = m_cursor_pos = 0; +} + +void TextBox::cursorEnd() { + m_cursor_pos = m_end_pos = text().size(); +} + +void TextBox::cursorForward() { + if (m_start_pos + cursorPosition() < m_end_pos) + m_cursor_pos++; + else if (m_end_pos < text().size()) { + m_cursor_pos++; + m_end_pos++; + adjustStartPos(); + } +} + +void TextBox::cursorBackward() { + if (cursorPosition()) + m_cursor_pos--; + else if (m_start_pos) { + m_start_pos--; + adjustEndPos(); + } +} + +void TextBox::backspace() { + if (m_start_pos || cursorPosition()) { + m_text.erase(m_start_pos + cursorPosition() - 1, 1); + if (cursorPosition()) + setCursorPosition(cursorPosition() - 1); + else + m_start_pos--; + adjustEndPos(); + } +} + +void TextBox::deleteForward() { + if (m_start_pos + m_cursor_pos < m_end_pos) { + m_text.erase(m_start_pos + m_cursor_pos, 1); + adjustEndPos(); + } +} + +void TextBox::insertText(const std::string &val) { + m_text.insert(m_start_pos + cursorPosition(), val); + m_cursor_pos += val.size(); + m_end_pos += val.size(); + if (m_start_pos + cursorPosition() < m_end_pos) + adjustEndPos(); + else + adjustStartPos(); +} + +void TextBox::killToEnd() { + if (cursorPosition() < text().size()) { + m_text.erase(cursorPosition()); + setText(m_text); + } +} + +void TextBox::clear() { + FbWindow::clear(); + // center text by default + int center_pos = (height() + font().ascent())/2; + if (gc() == 0) + setGC(DefaultGC(FbTk::App::instance()->display(), screenNumber())); + + font().drawText(window(), screenNumber(), + gc(), + text().c_str() + m_start_pos, + m_end_pos - m_start_pos, + 0, center_pos); // pos + + // draw cursor position + int cursor_pos = font().textWidth(text().c_str() + m_start_pos, m_cursor_pos) + 1; + drawLine(gc(), cursor_pos, 0, cursor_pos, font().height()); +} + +void TextBox::moveResize(int x, int y, + unsigned int width, unsigned int height) { + FbWindow::moveResize(x, y, width, height); + clear(); +} + +void TextBox::resize(unsigned int width, unsigned int height) { + FbWindow::resize(width, height); + clear(); +} + +void TextBox::exposeEvent(XExposeEvent &event) { + clear(); +} + +void TextBox::buttonPressEvent(XButtonEvent &event) { + setInputFocus(); +} + +void TextBox::keyPressEvent(XKeyEvent &event) { + KeySym ks; + char keychar[1]; + XLookupString(&event, keychar, 1, &ks, 0); + // a modifier key by itself doesn't do anything + if (IsModifierKey(ks)) return; + + if (event.state) { // handle keybindings without state + if (event.state == ControlMask) { + + switch (ks) { + case XK_b: + cursorBackward(); + break; + case XK_f: + cursorForward(); + break; + case XK_a: + cursorHome(); + break; + case XK_e: + cursorEnd(); + break; + case XK_d: + deleteForward(); + break; + case XK_k: + killToEnd(); + break; + } + } else if (event.state == ShiftMask) { + if (isprint(keychar[0])) { + std::string val; + val += keychar[0]; + insertText(val); + } + } + + } else { // no state + + switch (ks) { + case XK_BackSpace: + backspace(); + break; + case XK_Home: + cursorHome(); + break; + case XK_End: + cursorEnd(); + break; + case XK_Left: + cursorBackward(); + break; + case XK_Right: + cursorForward(); + break; + default: + if (isprint(keychar[0])) { + std::string val; + val += keychar[0]; + insertText(val); + } + } + } + clear(); +} + +void TextBox::setCursorPosition(int pos) { + m_cursor_pos = pos; + if (m_cursor_pos > text().size()) + cursorEnd(); + else if (m_cursor_pos < 0) + cursorHome(); +} + +void TextBox::adjustEndPos() { + m_end_pos = text().size(); + int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos); + while (text_width > width()) { + m_end_pos--; + text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos); + } +} + +void TextBox::adjustStartPos() { + int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos); + if (text_width < width()) + return; + + int start_pos = 0; + text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos); + while (text_width > width()) { + start_pos++; + text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos); + } + // adjust cursorPosition() according relative to change to m_start_pos + m_cursor_pos -= start_pos - m_start_pos; + m_start_pos = start_pos; +} + + + +}; // end namespace FbTk diff --git a/src/FbTk/TextBox.hh b/src/FbTk/TextBox.hh new file mode 100644 index 0000000..10e7f66 --- /dev/null +++ b/src/FbTk/TextBox.hh @@ -0,0 +1,84 @@ +// TextBox.hh for FbTk - fluxbox toolkit +// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id: TextBox.hh,v 1.1 2003/08/26 23:24:48 fluxgen Exp $ + +#ifndef FBTK_TEXTBOX_HH +#define FBTK_TEXTBOX_HH + +#include "FbWindow.hh" +#include "Color.hh" +#include "Text.hh" +#include "EventHandler.hh" + +#include + +namespace FbTk { + +class Font; + +class TextBox:public FbWindow, public EventHandler { +public: + TextBox(int screen_num, const Font &font, const std::string &text); + TextBox(const FbWindow &parent, const Font &font, const std::string &text); + virtual ~TextBox(); + + void setText(const std::string &text); + void setFont(const Font &font); + void setGC(GC gc); + void setCursorPosition(int cursor); + void setInputFocus(); + void cursorEnd(); + void cursorHome(); + void cursorForward(); + void cursorBackward(); + void deleteForward(); + void insertText(const std::string &val); + void backspace(); + void killToEnd(); + + void moveResize(int x, int y, + unsigned int width, unsigned int height); + void resize(unsigned int width, unsigned int height); + void clear(); + + void exposeEvent(XExposeEvent &event); + void buttonPressEvent(XButtonEvent &event); + void keyPressEvent(XKeyEvent &event); + + const std::string &text() const { return m_text; } + const Font &font() const { return *m_font; } + GC gc() const { return m_gc; } + int cursorPosition() const { return m_cursor_pos; } + +private: + void adjustEndPos(); + void adjustStartPos(); + + const FbTk::Font *m_font; + std::string m_text; + GC m_gc; + std::string::size_type m_cursor_pos, m_start_pos, m_end_pos; +}; + +} // end namespace FbTk + +#endif // FBTK_TEXTBOX_HH -- cgit v0.11.2