]> Dogcows Code - chaz/openbox/blob - otk/messagedialog.cc
only hide the dialog if a default button exists when enter is hit
[chaz/openbox] / otk / messagedialog.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 #include "messagedialog.hh"
6 #include "assassin.hh"
7 #include "button.hh"
8 #include "label.hh"
9 #include "display.hh"
10 #include "property.hh"
11 #include "eventdispatcher.hh"
12 #include "timer.hh"
13
14 #include <algorithm>
15
16 namespace otk {
17
18 DialogButton MessageDialog::_default_result("", false);
19
20 class DialogButtonWidget : public Button {
21 MessageDialog *_dia;
22 const DialogButton &_res;
23 public:
24 DialogButtonWidget(Widget *parent, MessageDialog *dia,
25 const DialogButton &b)
26 : Button(parent),
27 _dia(dia),
28 _res(b)
29 {
30 assert(dia);
31 setBevel(1);
32 setMaxSize(Size(0,0));
33 setText(b.label());
34 setHighlighted(b.isDefault());
35 show();
36 }
37
38 virtual void buttonPressHandler(const XButtonEvent &e) {
39 // limit to the left button
40 if (e.button == Button1)
41 Button::buttonPressHandler(e);
42 }
43 virtual void clickHandler(unsigned int) {
44 _dia->setResult(_res);
45 _dia->hide();
46 }
47 };
48
49 MessageDialog::MessageDialog(int screen, EventDispatcher *ed, ustring title,
50 ustring caption)
51 : Widget(screen, ed, Widget::Vertical)
52 {
53 init(title, caption);
54 }
55
56 MessageDialog::MessageDialog(EventDispatcher *ed, ustring title,
57 ustring caption)
58 : Widget(DefaultScreen(**display), ed, Widget::Vertical)
59 {
60 init(title, caption);
61 }
62
63 MessageDialog::MessageDialog(Widget *parent, ustring title, ustring caption)
64 : Widget(parent, Widget::Vertical)
65 {
66 init(title, caption);
67 }
68
69 void MessageDialog::init(const ustring &title, const ustring &caption)
70 {
71 _label = new Label(this);
72 _label->show();
73 _label->setHighlighted(true);
74 _button_holder = new Widget(this, Widget::Horizontal);
75 _button_holder->show();
76 _return = XKeysymToKeycode(**display, XStringToKeysym("Return"));
77 _escape = XKeysymToKeycode(**display, XStringToKeysym("Escape"));
78 _result = &_default_result;
79
80 setEventMask(eventMask() | KeyPressMask);
81 _label->setText(caption);
82 if (title.utf8())
83 otk::Property::set(window(), otk::Property::atoms.net_wm_name,
84 otk::Property::utf8, title);
85 otk::Property::set(window(), otk::Property::atoms.wm_name,
86 otk::Property::ascii, otk::ustring(title.c_str(), false));
87
88 // set WM Protocols on the window
89 Atom protocols[2];
90 protocols[0] = Property::atoms.wm_protocols;
91 protocols[1] = Property::atoms.wm_delete_window;
92 XSetWMProtocols(**display, window(), protocols, 2);
93 }
94
95 MessageDialog::~MessageDialog()
96 {
97 if (visible()) hide();
98 delete _button_holder;
99 delete _label;
100 }
101
102 const DialogButton& MessageDialog::run()
103 {
104 if (!visible())
105 show();
106
107 while (visible()) {
108 dispatcher()->dispatchEvents();
109 if (visible())
110 Timer::dispatchTimers(); // fire pending events
111 }
112 return *_result;
113 }
114
115 void MessageDialog::focus()
116 {
117 if (visible())
118 XSetInputFocus(**display, window(), None, CurrentTime);
119 }
120
121 void MessageDialog::show()
122 {
123 std::vector<DialogButton>::const_iterator it, end = _buttons.end();
124 for (it = _buttons.begin(); it != end; ++it)
125 _button_widgets.push_back(new DialogButtonWidget(_button_holder,
126 this, *it));
127
128 Rect r;
129
130 if (parent())
131 r = parent()->area();
132 else
133 r = Rect(Point(0, 0), display->screenInfo(screen())->size());
134
135 XSizeHints size;
136 size.flags = PMinSize | PPosition;
137 size.min_width = minSize().width();
138 size.min_height = minSize().height();
139
140 Size dest = area().size();
141 if (dest.width() < 200 || dest.height() < 100) {
142 if (dest.width() < 200 && dest.height() < 100) dest = Size(200, 100);
143 else if (dest.width() < 200) dest = Size(200, dest.height());
144 else dest = Size(dest.width(), 100);
145 resize(dest);
146 }
147
148 // center it above its parent
149 move(Point(r.x() + (r.width() - dest.width()) / 2,
150 r.y() + (r.height() - dest.height()) / 2));
151
152 XSetWMNormalHints(**display, window(), &size);
153
154 Widget::show();
155 }
156
157 void MessageDialog::hide()
158 {
159 Widget::hide();
160 std::for_each(_button_widgets.begin(), _button_widgets.end(),
161 PointerAssassin());
162 }
163
164 void MessageDialog::keyPressHandler(const XKeyEvent &e)
165 {
166 if (e.keycode == _return) {
167 std::vector<DialogButton>::const_iterator it, end = _buttons.end();
168 for (it = _buttons.begin(); it != end; ++it)
169 if (it->isDefault()) {
170 _result = &(*it);
171 hide();
172 break;
173 }
174 } else if (e.keycode == _escape) {
175 hide();
176 }
177 }
178
179 void MessageDialog::clientMessageHandler(const XClientMessageEvent &e)
180 {
181 EventHandler::clientMessageHandler(e);
182 if (e.message_type == Property::atoms.wm_protocols &&
183 static_cast<Atom>(e.data.l[0]) == Property::atoms.wm_delete_window)
184 hide();
185 }
186
187 }
This page took 0.041065 seconds and 5 git commands to generate.