From 7a41f7730dfa7e5733720f98f89c5a5906f1e786 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 16 Feb 2003 11:59:12 +0000 Subject: [PATCH] add otk::MessageDialog --- otk/.cvsignore | 1 + otk/Makefile.am | 4 +- otk/button.cc | 2 + otk/button.hh | 2 + otk/messagedialog.cc | 168 +++++++++++++++++++++++++++++++++++++++++++ otk/messagedialog.hh | 66 +++++++++++++++++ otk/otk.hh | 1 + otk/widget.hh | 2 + 8 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 otk/messagedialog.cc create mode 100644 otk/messagedialog.hh diff --git a/otk/.cvsignore b/otk/.cvsignore index 7dab6bb6..a563c2af 100644 --- a/otk/.cvsignore +++ b/otk/.cvsignore @@ -37,6 +37,7 @@ surface.lo rendertexture.lo rendertest renderstyle.lo +messagedialog.lo rendercontrol.lo rendercolor.lo otk.py diff --git a/otk/Makefile.am b/otk/Makefile.am index dc53291f..566fafcf 100644 --- a/otk/Makefile.am +++ b/otk/Makefile.am @@ -11,7 +11,7 @@ libotk_la_SOURCES=rendercontrol.cc truerendercontrol.cc surface.cc util.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 @@ includeotk_HEADERS=application.hh appwidget.hh assassin.hh button.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 diff --git a/otk/button.cc b/otk/button.cc index 774aa11b..f068d5a5 100644 --- a/otk/button.cc +++ b/otk/button.cc @@ -38,6 +38,8 @@ void Button::release(unsigned int mouse_button) styleChanged(*RenderStyle::style(screen())); refresh(); + + clickHandler(_mouse_button); } void Button::buttonPressHandler(const XButtonEvent &e) diff --git a/otk/button.hh b/otk/button.hh index 09fc0d6b..a3805aa0 100644 --- a/otk/button.hh +++ b/otk/button.hh @@ -20,6 +20,8 @@ public: 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: diff --git a/otk/messagedialog.cc b/otk/messagedialog.cc new file mode 100644 index 00000000..df004347 --- /dev/null +++ b/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 + +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::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::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(e.data.l[0]) == Property::atoms.wm_delete_window) + hide(); +} + +} diff --git a/otk/messagedialog.hh b/otk/messagedialog.hh new file mode 100644 index 00000000..d68c1726 --- /dev/null +++ b/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 + +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 _buttons; + std::vector