fluxbox/src/TextDialog.cc
nacitar sevaht 822c02e96a TextDialog now handles parentrelative labels
Prior to this patch, TextDialog did not handle parentrelative labels;
borrowing code from OSDWindow, now TextDialog properly handles this.

Eventually, I plan to combine the good parts of TextDialog and OSDWindow
into OSDWindow, and then let TextDialog derive from OSDWindow... but for
now, here's the band-aid fix for the issue without the refactorization.
2011-05-16 22:09:57 +02:00

204 lines
6.6 KiB
C++

// TextDialog.cc
// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org)
//
// 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.
#include "TextDialog.hh"
#include "Screen.hh"
#include "FbWinFrameTheme.hh"
#include "fluxbox.hh"
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/KeyUtil.hh"
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <memory>
using std::string;
/**
* This is an abstract class providing a text box dialog
*/
TextDialog::TextDialog(BScreen &screen,
const string &title) :
FbTk::FbWindow(screen.rootWindow().screenNumber(), 0, 0, 200, 1, ExposureMask),
m_textbox(*this, screen.focusedWinFrameTheme()->font(), ""),
m_label(*this, screen.focusedWinFrameTheme()->iconbarTheme().text().font(), title),
m_gc(m_textbox),
m_screen(screen),
m_move_x(0),
m_move_y(0),
m_pixmap(0){
init();
}
TextDialog::~TextDialog() {
FbTk::EventManager::instance()->remove(*this);
hide();
if (m_pixmap != 0)
m_screen.imageControl().removeImage(m_pixmap);
}
void TextDialog::setText(const FbTk::BiDiString& text) {
m_textbox.setText(text);
}
void TextDialog::show() {
FbTk::FbWindow::show();
m_textbox.setInputFocus();
m_label.clear();
Fluxbox::instance()->setShowingDialog(true);
// resize to correct width, which should be the width of label text
// no need to truncate label text in this dialog
// but if label text size < 200 we set 200
if (m_label.textWidth() < 200)
return;
else {
resize(m_label.textWidth(), height());
updateSizes();
render();
}
}
void TextDialog::hide() {
FbTk::FbWindow::hide();
Fluxbox::instance()->setShowingDialog(false);
}
void TextDialog::exposeEvent(XExposeEvent &event) {
if (event.window == window())
clearArea(event.x, event.y, event.width, event.height);
}
void TextDialog::buttonPressEvent(XButtonEvent &event) {
m_textbox.setInputFocus();
m_move_x = event.x_root - x();
m_move_y = event.y_root - y();
}
void TextDialog::handleEvent(XEvent &event) {
if (event.type == ConfigureNotify && event.xconfigure.window != window()) {
moveResize(event.xconfigure.x, event.xconfigure.y,
event.xconfigure.width, event.xconfigure.height);
} else if (event.type == DestroyNotify)
delete this;
}
void TextDialog::motionNotifyEvent(XMotionEvent &event) {
int new_x = event.x_root - m_move_x;
int new_y = event.y_root - m_move_y;
move(new_x, new_y);
}
void TextDialog::keyPressEvent(XKeyEvent &event) {
unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(event.state);
if (state)
return;
KeySym ks;
char keychar;
XLookupString(&event, &keychar, 1, &ks, 0);
if (ks == XK_Return) {
exec(m_textbox.text());
delete this;
} else if (ks == XK_Escape)
delete this; // end this
else if (ks == XK_Tab) {
// try to expand a command
tabComplete();
}
}
void TextDialog::render() {
if (m_screen.focusedWinFrameTheme()->iconbarTheme().texture().type() &
FbTk::Texture::PARENTRELATIVE) {
if (!m_screen.focusedWinFrameTheme()->titleTexture().usePixmap()) {
m_pixmap = None;
m_label.setBackgroundColor(m_screen.focusedWinFrameTheme()->titleTexture().color());
} else {
m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
m_screen.focusedWinFrameTheme()->titleTexture());
m_label.setBackgroundPixmap(m_pixmap);
}
} else {
if (!m_screen.focusedWinFrameTheme()->iconbarTheme().texture().usePixmap()) {
m_pixmap = None;
m_label.setBackgroundColor(m_screen.focusedWinFrameTheme()->iconbarTheme().texture().color());
} else {
m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
m_screen.focusedWinFrameTheme()->iconbarTheme().texture());
m_label.setBackgroundPixmap(m_pixmap);
}
}
if (m_pixmap)
m_screen.imageControl().removeImage(m_pixmap);
}
void TextDialog::init() {
// setup label
// we listen to motion notify too
m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
m_label.setGC(m_screen.focusedWinFrameTheme()->iconbarTheme().text().textGC());
m_label.setJustify(m_screen.focusedWinFrameTheme()->iconbarTheme().text().justify());
m_label.show();
// setup text box
FbTk::Color white("white", m_textbox.screenNumber());
m_textbox.setBackgroundColor(white);
FbTk::Color black("black", m_textbox.screenNumber());
m_gc.setForeground(black);
m_textbox.setGC(m_gc.gc());
m_textbox.show();
// setup this window
setBorderWidth(m_screen.focusedWinFrameTheme()->border().width());
setBorderColor(m_screen.focusedWinFrameTheme()->border().color());
// move to center of the current head
unsigned int head = m_screen.getCurrHead();
move(m_screen.getHeadX(head) + (m_screen.getHeadWidth(head) - width()) / 2,
m_screen.getHeadY(head) + (m_screen.getHeadHeight(head) - height()) / 2);
updateSizes();
resize(width(), m_textbox.height() + m_label.height());
render();
// we need ConfigureNotify from children
FbTk::EventManager::instance()->addParent(*this, *this);
}
void TextDialog::updateSizes() {
m_label.moveResize(0, 0,
width(), m_textbox.font().height() + 2);
m_textbox.moveResize(0, m_label.height(),
width(), m_textbox.font().height() + 2);
}