summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-02-16 11:59:12 +0000
committerDana Jansens <danakj@orodu.net>2003-02-16 11:59:12 +0000
commit7a41f7730dfa7e5733720f98f89c5a5906f1e786 (patch)
tree17c99ac6c1d5cc88109d1013fc638303a3f5450c
parentf325abe4e454f3c413ad91e6145b8a8c458c8758 (diff)
add otk::MessageDialog
-rw-r--r--otk/.cvsignore1
-rw-r--r--otk/Makefile.am4
-rw-r--r--otk/button.cc2
-rw-r--r--otk/button.hh2
-rw-r--r--otk/messagedialog.cc168
-rw-r--r--otk/messagedialog.hh66
-rw-r--r--otk/otk.hh1
-rw-r--r--otk/widget.hh2
8 files changed, 244 insertions, 2 deletions
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 <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();
+}
+
+}
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 <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
diff --git a/otk/otk.hh b/otk/otk.hh
index 74187f05..9ddf34e9 100644
--- a/otk/otk.hh
+++ b/otk/otk.hh
@@ -15,6 +15,7 @@
#include "rendercolor.hh"
#include "display.hh"
#include "font.hh"
+#include "messagedialog.hh"
#include "rendercontrol.hh"
#include "size.hh"
#include "point.hh"
diff --git a/otk/widget.hh b/otk/widget.hh
index c56b4a56..93121c85 100644
--- a/otk/widget.hh
+++ b/otk/widget.hh
@@ -100,6 +100,8 @@ protected:
void createWindow(bool overrideredir);
RenderTexture *_texture;
+
+ EventDispatcher *dispatcher() const { return _dispatcher; }
private:
void internal_moveresize(int x, int y, int w, int h);