add otk::MessageDialog
authorDana Jansens <danakj@orodu.net>
Sun, 16 Feb 2003 11:59:12 +0000 (11:59 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Feb 2003 11:59:12 +0000 (11:59 +0000)
otk/.cvsignore
otk/Makefile.am
otk/button.cc
otk/button.hh
otk/messagedialog.cc [new file with mode: 0644]
otk/messagedialog.hh [new file with mode: 0644]
otk/otk.hh
otk/widget.hh

index 7dab6bb..a563c2a 100644 (file)
@@ -37,6 +37,7 @@ surface.lo
 rendertexture.lo
 rendertest
 renderstyle.lo
+messagedialog.lo
 rendercontrol.lo
 rendercolor.lo
 otk.py
index dc53291..566fafc 100644 (file)
@@ -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
 
index 774aa11..f068d5a 100644 (file)
@@ -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)
index 09fc0d6..a3805aa 100644 (file)
@@ -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 (file)
index 0000000..df00434
--- /dev/null
@@ -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 (file)
index 0000000..d68c172
--- /dev/null
@@ -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
index 74187f0..9ddf34e 100644 (file)
@@ -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"
index c56b4a5..93121c8 100644 (file)
@@ -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);