00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "CommandDialog.hh"
00026
00027 #include "Screen.hh"
00028 #include "FbWinFrameTheme.hh"
00029 #include "WinClient.hh"
00030 #include "CommandParser.hh"
00031 #include "fluxbox.hh"
00032
00033 #include "FbTk/ImageControl.hh"
00034 #include "FbTk/EventManager.hh"
00035 #include "FbTk/StringUtil.hh"
00036 #include "FbTk/App.hh"
00037
00038 #include <X11/keysym.h>
00039 #include <X11/Xutil.h>
00040
00041 #include <iostream>
00042 #include <memory>
00043 #include <stdexcept>
00044 using namespace std;
00045
00046 CommandDialog::CommandDialog(BScreen &screen, const std::string &title):
00047 FbWindow(screen.rootWindow().screenNumber(),
00048 0, 0, 200, 1, ExposureMask),
00049 m_font("fixed"),
00050 m_textbox(*this, m_font, ""),
00051 m_label(*this, screen.winFrameTheme().font(), title),
00052 m_gc(m_textbox),
00053 m_screen(screen),
00054 m_move_x(0),
00055 m_move_y(0),
00056 m_pixmap(0) {
00057 init();
00058
00059 }
00060
00061 CommandDialog::CommandDialog(BScreen &screen, const std::string &title, const std::string &precommand):
00062 FbWindow(screen.rootWindow().screenNumber(),
00063 0, 0, 200, 1, ExposureMask),
00064 m_font("fixed"),
00065 m_textbox(*this, m_font, ""),
00066 m_label(*this, screen.winFrameTheme().font(), title),
00067 m_gc(m_textbox),
00068 m_screen(screen),
00069 m_move_x(0),
00070 m_move_y(0),
00071 m_pixmap(0),
00072 m_precommand(precommand) {
00073 init();
00074
00075 }
00076
00077 CommandDialog::~CommandDialog() {
00078 FbTk::EventManager::instance()->remove(*this);
00079 hide();
00080 if (m_pixmap != 0)
00081 m_screen.imageControl().removeImage(m_pixmap);
00082 }
00083
00084 void CommandDialog::setText(const std::string &text) {
00085 m_textbox.setText(text);
00086 }
00087
00088 void CommandDialog::show() {
00089 FbTk::FbWindow::show();
00090 m_textbox.setInputFocus();
00091 m_label.clear();
00092
00093
00094
00095 if (m_label.textWidth() < 200)
00096 return;
00097 else {
00098 resize(m_label.textWidth(), height());
00099 updateSizes();
00100 render();
00101 }
00102 }
00103
00104 void CommandDialog::hide() {
00105 FbTk::FbWindow::hide();
00106
00107
00108 if (Fluxbox::instance()->getFocusedWindow() &&
00109 Fluxbox::instance()->getFocusedWindow()->fbwindow())
00110 Fluxbox::instance()->getFocusedWindow()->fbwindow()->setInputFocus();
00111
00112 }
00113
00114 void CommandDialog::exposeEvent(XExposeEvent &event) {
00115 if (event.window == window())
00116 clearArea(event.x, event.y, event.width, event.height);
00117 }
00118
00119 void CommandDialog::buttonPressEvent(XButtonEvent &event) {
00120 m_textbox.setInputFocus();
00121 m_move_x = event.x_root - x();
00122 m_move_y = event.y_root - y();
00123 }
00124
00125 void CommandDialog::handleEvent(XEvent &event) {
00126 if (event.type == ConfigureNotify && event.xconfigure.window != window()) {
00127 moveResize(event.xconfigure.x, event.xconfigure.y,
00128 event.xconfigure.width, event.xconfigure.height);
00129 } else if (event.type == DestroyNotify)
00130 delete this;
00131 }
00132
00133 void CommandDialog::motionNotifyEvent(XMotionEvent &event) {
00134 int new_x = event.x_root - m_move_x;
00135 int new_y = event.y_root - m_move_y;
00136 move(new_x, new_y);
00137 }
00138
00139 void CommandDialog::keyPressEvent(XKeyEvent &event) {
00140 if (event.state)
00141 return;
00142
00143 KeySym ks;
00144 char keychar[1];
00145 XLookupString(&event, keychar, 1, &ks, 0);
00146
00147 if (ks == XK_Return) {
00148 hide();
00149
00150 std::auto_ptr<FbTk::Command> cmd(CommandParser::instance().
00151 parseLine(m_precommand + m_textbox.text()));
00152 if (cmd.get())
00153 cmd->execute();
00154
00155 if (*m_postcommand != 0)
00156 m_postcommand->execute();
00157
00158 delete this;
00159 } else if (ks == XK_Escape)
00160 delete this;
00161 else if (ks == XK_Tab) {
00162
00163 tabComplete();
00164 }
00165 }
00166
00167 void CommandDialog::tabComplete() {
00168 try {
00169 string::size_type first = m_textbox.text().find_last_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00170 "abcdefghijklmnopqrstuvwxyz"
00171 "0123456789",
00172 m_textbox.cursorPosition());
00173 if (first == string::npos)
00174 first = 0;
00175 string prefix = FbTk::StringUtil::toLower(m_textbox.text().substr(first, m_textbox.cursorPosition()));
00176 if (prefix.size() == 0) {
00177 XBell(FbTk::App::instance()->display(), 0);
00178 return;
00179 }
00180
00181 CommandParser::CommandFactoryMap::const_iterator it = CommandParser::instance().factorys().begin();
00182 const CommandParser::CommandFactoryMap::const_iterator it_end = CommandParser::instance().factorys().end();
00183 std::vector<std::string> matches;
00184 for (; it != it_end; ++it) {
00185 if ((*it).first.find(prefix) == 0) {
00186 matches.push_back((*it).first);
00187 }
00188 }
00189
00190 if (!matches.empty()) {
00191
00192 std::sort(matches.begin(), matches.end(), less<string>());
00193 m_textbox.setText(m_textbox.text() + matches[0].substr(prefix.size()));
00194 } else
00195 XBell(FbTk::App::instance()->display(), 0);
00196
00197 } catch (std::out_of_range &oor) {
00198 XBell(FbTk::App::instance()->display(), 0);
00199 }
00200 }
00201
00202 void CommandDialog::render() {
00203 Pixmap tmp = m_pixmap;
00204 if (!m_screen.winFrameTheme().labelFocusTexture().usePixmap()) {
00205 m_label.setBackgroundColor(m_screen.winFrameTheme().labelFocusTexture().color());
00206 m_pixmap = 0;
00207 } else {
00208 m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
00209 m_screen.winFrameTheme().labelFocusTexture());
00210 m_label.setBackgroundPixmap(m_pixmap);
00211 }
00212
00213 if (tmp)
00214 m_screen.imageControl().removeImage(tmp);
00215
00216 }
00217
00218 void CommandDialog::init() {
00219
00220
00221
00222
00223 m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
00224 m_label.setGC(m_screen.winFrameTheme().labelTextFocusGC());
00225 m_label.show();
00226
00227
00228 FbTk::Color white("white", m_textbox.screenNumber());
00229 m_textbox.setBackgroundColor(white);
00230 FbTk::Color black("black", m_textbox.screenNumber());
00231 m_gc.setForeground(black);
00232 m_textbox.setGC(m_gc.gc());
00233 m_textbox.show();
00234
00235
00236 setBorderWidth(1);
00237 setBackgroundColor(white);
00238
00239 move((m_screen.width() - width())/2, (m_screen.height() - height())/2);
00240
00241 updateSizes();
00242 resize(width(), m_textbox.height() + m_label.height());
00243
00244 render();
00245
00246
00247 FbTk::EventManager::instance()->addParent(*this, *this);
00248 }
00249
00250 void CommandDialog::updateSizes() {
00251 m_label.moveResize(0, 0,
00252 width(), m_font.height() + 2);
00253
00254 m_textbox.moveResize(2, m_label.height(),
00255 width() - 4, m_font.height() + 2);
00256 }