// This file is part of VSTGUI. It is subject to the license terms // in the LICENSE file found in the top-level directory of this // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE #include "../../lib/cframe.h" #include "../../lib/controls/cbuttons.h" #include "../../lib/controls/ctextlabel.h" #include "../../lib/iviewlistener.h" #include "../../uidescription/delegationcontroller.h" #include "../../uidescription/iuidescription.h" #include "../include/helpers/uidesc/customization.h" #include "../include/helpers/value.h" #include "../include/helpers/valuelistener.h" #include "../include/helpers/windowcontroller.h" #include "genericalertbox.h" #include //------------------------------------------------------------------------ namespace VSTGUI { namespace Standalone { namespace Detail { namespace { //------------------------------------------------------------------------ const auto xmlText = R"( )"; //------------------------------------------------------------------------ } //------------------------------------------------------------------------ class AlertBoxController : public UIDesc::IModelBinding, public UIDesc::CustomizationAdapter, public ValueListenerAdapter, public WindowControllerAdapter, public ViewListenerAdapter, public std::enable_shared_from_this { public: static constexpr auto Button1TagName = "AlertBox.firstButton"; static constexpr auto Button2TagName = "AlertBox.secondButton"; static constexpr auto Button3TagName = "AlertBox.thirdButton"; AlertBoxController (const AlertBoxConfig& config, const AlertBoxCallback& callback) : callback (callback) , firstButtonTitle (config.defaultButton) , secondButtonTitle (config.secondButton) , thirdButtonTitle (config.thirdButton) { addValue (Value::make (Button1TagName)); addValue (Value::make (Button2TagName)); addValue (Value::make (Button3TagName)); addValue (Value::makeStringListValue ("AlertBox.headline", {config.headline})) ->setActive (false); addValue (Value::makeStringListValue ("AlertBox.description", {config.description})) ->setActive (false); if (!firstButtonTitle.empty ()) ++usedButtons; if (!secondButtonTitle.empty ()) ++usedButtons; if (!thirdButtonTitle.empty ()) ++usedButtons; } void setWindow (const WindowPtr& w) { window = w; window->registerWindowListener (this); CTextButton* focusButton = nullptr; switch (usedButtons) { case 1: focusButton = buttons[0]; break; case 2: case 3: focusButton = buttons[1]; break; } if (focusButton) focusButton->getFrame ()->setFocusView (focusButton); } const ValueList& getValues () const override { return values; } IController* createController (const UTF8StringView& name, IController* parent, const IUIDescription* uiDesc) override { if (name == "ButtonController") { return new ButtonController (*this, parent); } return nullptr; } void onEndEdit (IValue& value) override { if (value.getValue () < 0.5) return; auto self = shared_from_this (); if (value.getID () == Button1TagName) { if (usedButtons == 1) alertResult = AlertResult::DefaultButton; else alertResult = AlertResult::SecondButton; } else if (value.getID () == Button2TagName) { alertResult = AlertResult::DefaultButton; } else if (value.getID () == Button3TagName) { alertResult = AlertResult::ThirdButton; } window->close (); } void onClosed (const IWindow&) override { for (auto button : buttons) { if (button) button->unregisterViewListener (this); } if (callback) { callback (alertResult); callback = nullptr; } } void onSetContentView (IWindow& inWindow, const SharedPointer& contentView) override { std::vector views; if (contentView->getChildViewsOfType (views, true) == 0) return; CCoord diffY = 0.; CCoord lastViewBottom = 0.; for (auto label : views) { auto prevSize = label->getViewSize (); label->setAutoHeight (true); auto newSize = label->getViewSize (); diffY += newSize.getHeight () - prevSize.getHeight (); if (lastViewBottom == 0) { lastViewBottom = newSize.bottom; } else { newSize.offset (0, lastViewBottom - newSize.top); label->setViewSize (newSize); } } if (diffY == 0.) return; auto windowSize = inWindow.getSize (); windowSize.y += diffY; inWindow.setSize (windowSize); contentView->setSize (windowSize.x, windowSize.y); } void viewLostFocus (CView* view) override { if (auto button = dynamic_cast (view)) button->setGradient (normalButtonGradient); } void viewTookFocus (CView* view) override { if (auto button = dynamic_cast (view)) button->setGradient (focusedButtonGradient); } void onUIDescriptionParsed (const IUIDescription* uiDesc) override { focusedButtonGradient = uiDesc->getGradient ("Focused TextButton Gradient"); normalButtonGradient = uiDesc->getGradient ("Default TextButton Gradient"); } private: struct ButtonController : DelegationController { ButtonController (AlertBoxController& alertBoxController, IController* parent) : DelegationController (parent), alertBoxController (alertBoxController) { } CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override { if (auto button = dynamic_cast (view)) { UTF8StringView tagName = description->lookupControlTagName (button->getTag ()); if (!setupButton (button, tagName)) { view->forget (); return nullptr; } button->registerViewListener (&alertBoxController); } return controller->verifyView (view, attributes, description); } bool setupButton (CTextButton* button, UTF8StringView name) { if (name == Button3TagName) { if (alertBoxController.usedButtons < 3) return false; button->setTitle (alertBoxController.thirdButtonTitle); alertBoxController.buttons[2] = button; return true; } if (name == Button2TagName) { if (alertBoxController.usedButtons < 2) return false; button->setTitle (alertBoxController.firstButtonTitle); alertBoxController.buttons[1] = button; return true; } if (name == Button1TagName) { if (alertBoxController.usedButtons == 1) button->setTitle (alertBoxController.firstButtonTitle); else button->setTitle (alertBoxController.secondButtonTitle); alertBoxController.buttons[0] = button; return true; } return false; } AlertBoxController& alertBoxController; }; ValuePtr addValue (ValuePtr&& value) { value->registerListener (this); values.emplace_back (std::move (value)); return values.back (); } WindowPtr window; AlertBoxCallback callback; ValueList values; UTF8String firstButtonTitle; UTF8String secondButtonTitle; UTF8String thirdButtonTitle; AlertResult alertResult {AlertResult::Error}; uint32_t usedButtons {0}; std::array buttons {{nullptr}}; SharedPointer focusedButtonGradient; SharedPointer normalButtonGradient; }; //------------------------------------------------------------------------ WindowPtr createAlertBox (const AlertBoxConfig& alertBoxConfig, const AlertBoxCallback& callback) { vstgui_assert (callback); auto controller = std::make_shared (alertBoxConfig, callback); UIDesc::Config config; config.windowConfig.type = WindowType::Document; config.windowConfig.style.transparent ().movableByWindowBackground (); config.viewName = "AlertBox"; config.uiDescFileName = xmlText; config.modelBinding = staticPtrCast (controller); config.customization = staticPtrCast (controller); auto window = UIDesc::makeWindow (config); controller->setWindow (window); return window; } //------------------------------------------------------------------------ } // Detail } // Standalone } // VSTGUI