text box for input

This commit is contained in:
fluxgen 2003-08-26 23:24:48 +00:00
parent 462286b46c
commit 7473c2e0b0
2 changed files with 371 additions and 0 deletions

287
src/FbTk/TextBox.cc Normal file
View file

@ -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 <cctype>
#include <X11/keysym.h>
#include <X11/Xutil.h>
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

84
src/FbTk/TextBox.hh Normal file
View file

@ -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 <string>
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