diff --git a/libelemental.vcxproj b/libelemental.vcxproj
index 5a57a3a..a36155b 100644
--- a/libelemental.vcxproj
+++ b/libelemental.vcxproj
@@ -42,6 +42,7 @@
+
@@ -143,6 +144,7 @@
+
@@ -391,4 +393,4 @@
-
\ No newline at end of file
+
diff --git a/libelemental.vcxproj.filters b/libelemental.vcxproj.filters
index ded84b8..e8bca73 100644
--- a/libelemental.vcxproj.filters
+++ b/libelemental.vcxproj.filters
@@ -229,6 +229,9 @@
src\el\elements
+
+ src\el\elements
+
src\el\elements
@@ -560,6 +563,9 @@
src\el\elements
+
+ src\el\elements
+
src\el\elements
@@ -702,4 +708,4 @@
-
\ No newline at end of file
+
diff --git a/src/el/elements.h b/src/el/elements.h
index 1be3b5c..9533fc8 100644
--- a/src/el/elements.h
+++ b/src/el/elements.h
@@ -26,6 +26,7 @@
#include "el/elements/list_box.h"
#include "el/elements/menu_window.h"
#include "el/elements/message_window.h"
+#include "el/elements/modal_window.h"
#include "el/elements/mover.h"
#include "el/elements/popup_window.h"
#include "el/elements/progress_spinner.h"
diff --git a/src/el/elements/modal_window.cc b/src/el/elements/modal_window.cc
new file mode 100644
index 0000000..4f4f3bf
--- /dev/null
+++ b/src/el/elements/modal_window.cc
@@ -0,0 +1,95 @@
+/**
+ ******************************************************************************
+ * Elemental Forms : a lightweight user interface framework *
+ ******************************************************************************
+ * ©2015 Ben Vanik. All rights reserved. Released under the BSD license. *
+ * Portions ©2011-2015 Emil Segerås: https://github.com/fruxo/turbobadger *
+ ******************************************************************************
+ */
+
+#include
+
+#include "el/animation_manager.h"
+#include "el/element_animation.h"
+#include "el/elements/dimmer.h"
+#include "el/elements/modal_window.h"
+
+namespace el {
+namespace elements {
+
+int ModalWindow::visible_count_ = 0;
+
+ModalWindow::ModalWindow(std::function on_close_callback)
+ : on_close_callback_(on_close_callback) {
+ ++visible_count_;
+ set_settings(el::WindowSettings::kTitleBar |
+ el::WindowSettings::kCloseButton |
+ el::WindowSettings::kCanActivate);
+ el::ElementListener::AddGlobalListener(this);
+}
+
+ModalWindow::~ModalWindow() {
+ --visible_count_;
+ el::ElementListener::RemoveGlobalListener(this);
+ if (auto dimmer = dimmer_.get()) {
+ dimmer->RemoveFromParent();
+ delete dimmer;
+ }
+}
+
+void ModalWindow::Show(el::Element* root_element) {
+ auto dimmer = new Dimmer();
+ root_element->AddChild(dimmer);
+ dimmer_.reset(dimmer);
+
+ BuildUI();
+
+ root_element->AddChild(this);
+ ResizeToFitContent();
+ CenterInParent();
+}
+
+bool ModalWindow::OnEvent(const el::Event& ev) {
+ if (ev.target->id() == TBIDC("exit_button") &&
+ ev.type == el::EventType::kClick) {
+ Die();
+ return true;
+ } else if (ev.type == el::EventType::kKeyDown &&
+ ev.special_key == el::SpecialKey::kEsc) {
+ Die();
+ return true;
+ }
+ return el::Window::OnEvent(ev);
+}
+
+void ModalWindow::OnDie() {
+ if (auto dimmer = dimmer_.get()) {
+ dimmer->Die();
+ }
+ Window::OnDie();
+}
+
+void ModalWindow::OnRemove() { on_close_callback_(); }
+
+void ModalWindow::OnElementAdded(Element* parent, Element* element) {
+ if (element == this) {
+ // Move in.
+ auto anim = new RectElementAnimation(this, Rect(0, -50, 0, 0),
+ RectElementAnimation::Mode::kDeltaOut);
+ AnimationManager::StartAnimation(anim);
+ }
+}
+
+bool ModalWindow::OnElementDying(Element* element) {
+ if (element == this) {
+ // Move out.
+ auto anim = new RectElementAnimation(this, Rect(0, 50, 0, 0),
+ RectElementAnimation::Mode::kDeltaIn);
+ AnimationManager::StartAnimation(anim, AnimationCurve::kSpeedUp);
+ return true;
+ }
+ return false;
+}
+
+} // namespace elements
+} // namespace el
diff --git a/src/el/elements/modal_window.h b/src/el/elements/modal_window.h
new file mode 100644
index 0000000..75aef1c
--- /dev/null
+++ b/src/el/elements/modal_window.h
@@ -0,0 +1,57 @@
+/**
+ ******************************************************************************
+ * Elemental Forms : a lightweight user interface framework *
+ ******************************************************************************
+ * ©2015 Ben Vanik. All rights reserved. Released under the BSD license. *
+ * Portions ©2011-2015 Emil Segerås: https://github.com/fruxo/turbobadger *
+ ******************************************************************************
+ */
+
+#ifndef EL_ELEMENTS_MODAL_WINDOW_H_
+#define EL_ELEMENTS_MODAL_WINDOW_H_
+
+#include
+
+#include "el/element_listener.h"
+#include "el/window.h"
+
+namespace el {
+namespace elements {
+
+// A window for showing modal messages.
+// Events invoked in this window will travel up through the target element.
+// When the user click any of its buttons, it will invoke a click event
+// (with the window ID), with the clicked buttons id as ref_id.
+// Then it will delete itself.
+// If the target element is deleted while this window is alive, the window will
+// delete itself.
+class ModalWindow : public Window, private ElementListener {
+ public:
+ TBOBJECT_SUBCLASS(ModalWindow, Window);
+
+ ModalWindow(std::function on_close_callback);
+ ~ModalWindow() override;
+
+ void Show(el::Element* root_element);
+
+ static bool is_any_visible() { return visible_count_ > 0; }
+
+ protected:
+ static int visible_count_;
+
+ virtual void BuildUI() = 0;
+
+ bool OnEvent(const el::Event& ev) override;
+ void OnDie() override;
+ void OnRemove() override;
+ void OnElementAdded(Element* parent, Element* element);
+ bool OnElementDying(Element* element) override;
+
+ std::function on_close_callback_;
+ WeakElementPointer dimmer_;
+};
+
+} // namespace elements
+} // namespace el
+
+#endif // EL_ELEMENTS_MODAL_WINDOW_H_