all repos — openbox @ 7a41f7730dfa7e5733720f98f89c5a5906f1e786

openbox fork - make it a bit more like ryudo

add otk::MessageDialog
Dana Jansens danakj@orodu.net
commit

7a41f7730dfa7e5733720f98f89c5a5906f1e786

parent

f325abe4e454f3c413ad91e6145b8a8c458c8758

M otk/.cvsignoreotk/.cvsignore

@@ -37,6 +37,7 @@ surface.lo

rendertexture.lo rendertest renderstyle.lo +messagedialog.lo rendercontrol.lo rendercolor.lo otk.py
M otk/Makefile.amotk/Makefile.am

@@ -11,7 +11,7 @@ renderstyle.cc rendercolor.cc pseudorendercontrol.cc \

display.cc font.cc screeninfo.cc property.cc timer.cc \ eventdispatcher.cc eventhandler.cc ustring.cc \ widget.cc application.cc label.cc appwidget.cc button.cc \ - otk.cc + otk.cc messagedialog.cc #focuswidget.cc focuslabel.cc

@@ -21,7 +21,7 @@ label.hh otk.hh point.hh property.hh pseudorendercontrol.hh\

rect.hh rendercolor.hh rendercontrol.hh renderstyle.hh \ rendertexture.hh screeninfo.hh size.hh strut.hh surface.hh \ timer.hh truerendercontrol.hh ustring.hh util.hh widget.hh \ - ../config.h + messagedialog.hh ../config.h EXTRA_DIST = otk.pc.in
M otk/button.ccotk/button.cc

@@ -38,6 +38,8 @@ _pressed = false;

styleChanged(*RenderStyle::style(screen())); refresh(); + + clickHandler(_mouse_button); } void Button::buttonPressHandler(const XButtonEvent &e)
M otk/button.hhotk/button.hh

@@ -20,6 +20,8 @@

virtual void buttonPressHandler(const XButtonEvent &e); virtual void buttonReleaseHandler(const XButtonEvent &e); + virtual void clickHandler(unsigned int button) {(void)button;} + virtual void styleChanged(const RenderStyle &style); private:
A otk/messagedialog.cc

@@ -0,0 +1,168 @@

+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- + +#include "config.h" + +#include "messagedialog.hh" +#include "assassin.hh" +#include "button.hh" +#include "label.hh" +#include "display.hh" +#include "property.hh" +#include "eventdispatcher.hh" +#include "timer.hh" + +#include <algorithm> + +namespace otk { + +DialogButton MessageDialog::_default_result("", false); + +class DialogButtonWidget : public Button { + MessageDialog *_dia; + const DialogButton &_res; +public: + DialogButtonWidget(Widget *parent, MessageDialog *dia, + const DialogButton &b) + : Button(parent), + _dia(dia), + _res(b) + { + assert(dia); + setBevel(1); + setMaxSize(Size(0,0)); + setText(b.label()); + setHighlighted(b.isDefault()); + show(); + } + + virtual void buttonPressHandler(const XButtonEvent &e) { + // limit to the left button + if (e.button == Button1) + Button::buttonPressHandler(e); + } + virtual void clickHandler(unsigned int) { + _dia->setResult(_res); + _dia->hide(); + } +}; + +MessageDialog::MessageDialog(int screen, EventDispatcher *ed, ustring title, + ustring caption) + : Widget(screen, ed, Widget::Vertical) +{ + init(title, caption); +} + +MessageDialog::MessageDialog(EventDispatcher *ed, ustring title, + ustring caption) + : Widget(DefaultScreen(**display), ed, Widget::Vertical) +{ + init(title, caption); +} + +MessageDialog::MessageDialog(Widget *parent, ustring title, ustring caption) + : Widget(parent, Widget::Vertical) +{ + init(title, caption); +} + +void MessageDialog::init(const ustring &title, const ustring &caption) +{ + _label = new Label(this); + _label->show(); + _label->setHighlighted(true); + _button_holder = new Widget(this, Widget::Horizontal); + _button_holder->show(); + _return = XKeysymToKeycode(**display, XStringToKeysym("Return")); + _escape = XKeysymToKeycode(**display, XStringToKeysym("Escape")); + _result = &_default_result; + + setEventMask(eventMask() | KeyPressMask); + _label->setText(caption); + if (title.utf8()) + otk::Property::set(window(), otk::Property::atoms.net_wm_name, + otk::Property::utf8, title); + otk::Property::set(window(), otk::Property::atoms.wm_name, + otk::Property::ascii, otk::ustring(title.c_str(), false)); + + // set WM Protocols on the window + Atom protocols[2]; + protocols[0] = Property::atoms.wm_protocols; + protocols[1] = Property::atoms.wm_delete_window; + XSetWMProtocols(**display, window(), protocols, 2); +} + +MessageDialog::~MessageDialog() +{ + if (visible()) hide(); + delete _button_holder; + delete _label; +} + +const DialogButton& MessageDialog::run() +{ + show(); + + while (visible()) { + dispatcher()->dispatchEvents(); + if (visible()) + Timer::dispatchTimers(); // fire pending events + } + return *_result; +} + +void MessageDialog::show() +{ + std::vector<DialogButton>::const_iterator it, end = _buttons.end(); + for (it = _buttons.begin(); it != end; ++it) + _button_widgets.push_back(new DialogButtonWidget(_button_holder, + this, *it)); + + XSizeHints size; + size.flags = PMinSize; + size.min_width = minSize().width(); + size.min_height = minSize().height(); + XSetWMNormalHints(**display, window(), &size); + + Size dest = area().size(); + if (dest.width() < 200 || dest.height() < 100) { + if (dest.width() < 200 && dest.height() < 100) dest = Size(200, 100); + else if (dest.width() < 200) dest = Size(200, dest.height()); + else dest = Size(dest.width(), 100); + resize(dest); + } + + Widget::show(); +} + +void MessageDialog::hide() +{ + Widget::hide(); + std::for_each(_button_widgets.begin(), _button_widgets.end(), + PointerAssassin()); +} + +void MessageDialog::keyPressHandler(const XKeyEvent &e) +{ + if (e.keycode == _return) { + std::vector<DialogButton>::const_iterator it, end = _buttons.end(); + for (it = _buttons.begin(); it != end; ++it) + if (it->isDefault()) { + _result = &(*it); + break; + } + hide(); + } else if (e.keycode == _escape) { + hide(); + } +} + +void MessageDialog::clientMessageHandler(const XClientMessageEvent &e) +{ + EventHandler::clientMessageHandler(e); + if (e.message_type == Property::atoms.wm_protocols && + static_cast<Atom>(e.data.l[0]) == Property::atoms.wm_delete_window) + hide(); +} + +}
A otk/messagedialog.hh

@@ -0,0 +1,66 @@

+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +#ifndef __messagedialog_hh +#define __messagedialog_hh + +#include "widget.hh" +#include "ustring.hh" + +#include <vector> + +namespace otk { + +class Button; +class Label; + +class DialogButton { + ustring _label; + bool _default; +public: + DialogButton(char *label) : _label(label), _default(false) + {} + DialogButton(ustring label) : _label(label), _default(false) + {} + DialogButton(ustring label, bool def) : _label(label), _default(def) + {} + inline const ustring& label() const { return _label; } + inline const bool& isDefault() const { return _default; } +}; + +class MessageDialog : public Widget { +public: + MessageDialog(int screen, EventDispatcher *ed, ustring title, + ustring caption); + MessageDialog(EventDispatcher *ed, ustring title, ustring caption); + MessageDialog(Widget *parent, ustring title, ustring caption); + virtual ~MessageDialog(); + + virtual void addButton(const DialogButton &b) { _buttons.push_back(b); } + + virtual const DialogButton& run(); + + virtual void show(); + virtual void hide(); + + virtual const DialogButton& result() const { return *_result; } + virtual void setResult(const DialogButton &result) { _result = &result; } + + virtual void keyPressHandler(const XKeyEvent &e); + virtual void clientMessageHandler(const XClientMessageEvent &e); + +private: + static DialogButton _default_result; + + void init(const ustring &title, const ustring &caption); + + std::vector<DialogButton> _buttons; + std::vector<Button *> _button_widgets; + Label *_label; + Widget *_button_holder; + KeyCode _return; + KeyCode _escape; + const DialogButton *_result; +}; + +} + +#endif // __messagedialog_hh
M otk/otk.hhotk/otk.hh

@@ -15,6 +15,7 @@ #include "button.hh"

#include "rendercolor.hh" #include "display.hh" #include "font.hh" +#include "messagedialog.hh" #include "rendercontrol.hh" #include "size.hh" #include "point.hh"
M otk/widget.hhotk/widget.hh

@@ -100,6 +100,8 @@

void createWindow(bool overrideredir); RenderTexture *_texture; + + EventDispatcher *dispatcher() const { return _dispatcher; } private: void internal_moveresize(int x, int y, int w, int h);