mirror of https://github.com/AxioDL/metaforce.git
Add MessageWindow class
This commit is contained in:
parent
26dffbd99e
commit
8dfafc81c2
|
@ -37,6 +37,7 @@ list(APPEND SPECTER_HEADERS
|
|||
include/Specter/View.hpp
|
||||
include/Specter/RootView.hpp
|
||||
include/Specter/ModalWindow.hpp
|
||||
include/Specter/MessageWindow.hpp
|
||||
include/Specter/Tooltip.hpp
|
||||
include/Specter/SplitView.hpp
|
||||
include/Specter/ScrollView.hpp
|
||||
|
@ -66,6 +67,7 @@ list(APPEND SPECTER_SOURCES
|
|||
lib/View.cpp
|
||||
lib/RootView.cpp
|
||||
lib/ModalWindow.cpp
|
||||
lib/MessageWindow.cpp
|
||||
lib/Tooltip.cpp
|
||||
lib/SplitView.cpp
|
||||
lib/ScrollView.cpp
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Table.hpp"
|
||||
#include "ViewResources.hpp"
|
||||
#include "IViewManager.hpp"
|
||||
#include "MessageWindow.hpp"
|
||||
#include <HECL/HECL.hpp>
|
||||
|
||||
namespace Specter
|
||||
|
@ -20,6 +21,7 @@ public:
|
|||
enum class Type
|
||||
{
|
||||
SaveFile,
|
||||
SaveDirectory,
|
||||
OpenFile,
|
||||
OpenDirectory,
|
||||
OpenHECLProject
|
||||
|
@ -114,6 +116,8 @@ private:
|
|||
}
|
||||
} m_fileFieldBind;
|
||||
|
||||
std::unique_ptr<MessageWindow> m_confirmWindow;
|
||||
|
||||
struct FileListingDataBind : ITableDataBinding, ITableStateBinding
|
||||
{
|
||||
FileBrowser& m_fb;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef SPECTER_MESSAGEWINDOW_HPP
|
||||
#define SPECTER_MESSAGEWINDOW_HPP
|
||||
|
||||
#include "ModalWindow.hpp"
|
||||
#include "MultiLineTextView.hpp"
|
||||
#include "Button.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
class MessageWindow : public ModalWindow
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
InfoOk,
|
||||
ErrorOk,
|
||||
ConfirmOkCancel
|
||||
};
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
std::function<void(bool ok)> m_func;
|
||||
|
||||
std::unique_ptr<MultiLineTextView> m_text;
|
||||
|
||||
struct OKBinding : IButtonBinding
|
||||
{
|
||||
MessageWindow& m_mw;
|
||||
std::string m_name;
|
||||
OKBinding(MessageWindow& mw, std::string&& name) : m_mw(mw), m_name(std::move(name)) {}
|
||||
const char* name() const {return m_name.c_str();}
|
||||
void activated(const boo::SWindowCoord& coord)
|
||||
{
|
||||
m_mw.m_func(true);
|
||||
}
|
||||
} m_okBind;
|
||||
ViewChild<std::unique_ptr<Button>> m_ok;
|
||||
|
||||
struct CancelBinding : IButtonBinding
|
||||
{
|
||||
MessageWindow& m_mw;
|
||||
std::string m_name;
|
||||
CancelBinding(MessageWindow& mw, std::string&& name) : m_mw(mw), m_name(std::move(name)) {}
|
||||
const char* name() const {return m_name.c_str();}
|
||||
void activated(const boo::SWindowCoord& coord)
|
||||
{
|
||||
m_mw.m_func(false);
|
||||
}
|
||||
} m_cancelBind;
|
||||
ViewChild<std::unique_ptr<Button>> m_cancel;
|
||||
|
||||
public:
|
||||
MessageWindow(ViewResources& res, View& parentView,
|
||||
Type type, const std::string& message, std::function<void(bool ok)> func);
|
||||
|
||||
void updateContentOpacity(float opacity)
|
||||
{
|
||||
Zeus::CColor color = Zeus::CColor::lerp({1,1,1,0}, {1,1,1,1}, opacity);
|
||||
ModalWindow::setMultiplyColor(color);
|
||||
m_text->setMultiplyColor(color);
|
||||
m_ok.m_view->setMultiplyColor(color);
|
||||
m_cancel.m_view->setMultiplyColor(color);
|
||||
}
|
||||
|
||||
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
|
||||
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
|
||||
void mouseMove(const boo::SWindowCoord&);
|
||||
void mouseEnter(const boo::SWindowCoord&);
|
||||
void mouseLeave(const boo::SWindowCoord&);
|
||||
|
||||
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SPECTER_MESSAGEWINDOW_HPP
|
|
@ -59,6 +59,7 @@ protected:
|
|||
virtual void updateContentOpacity(float opacity) {}
|
||||
|
||||
public:
|
||||
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint, const Zeus::CColor& bgColor);
|
||||
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint);
|
||||
void think();
|
||||
bool skipBuildInAnimation();
|
||||
|
|
|
@ -37,6 +37,12 @@ public:
|
|||
|
||||
void colorGlyphs(const Zeus::CColor& newColor);
|
||||
|
||||
void setMultiplyColor(const Zeus::CColor& color)
|
||||
{
|
||||
for (std::unique_ptr<TextView>& l : m_lines)
|
||||
l->setMultiplyColor(color);
|
||||
}
|
||||
|
||||
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ class ThemeData
|
|||
Zeus::CColor m_tbBg = {0.4, 0.4, 0.4, 1.0};
|
||||
Zeus::CColor m_tooltipBg = {0.1, 0.1, 0.1, 0.85};
|
||||
Zeus::CColor m_splashBg = {0.075, 0.075, 0.075, 0.85};
|
||||
Zeus::CColor m_splashErrorBg = {0.1, 0.01, 0.01, 0.85};
|
||||
|
||||
Zeus::CColor m_splash1 = {1.0, 1.0, 1.0, 1.0};
|
||||
Zeus::CColor m_splash2 = {0.3, 0.3, 0.3, 1.0};
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
virtual const Zeus::CColor& toolbarBackground() const {return m_tbBg;}
|
||||
virtual const Zeus::CColor& tooltipBackground() const {return m_tooltipBg;}
|
||||
virtual const Zeus::CColor& splashBackground() const {return m_splashBg;}
|
||||
virtual const Zeus::CColor& splashErrorBackground() const {return m_splashErrorBg;}
|
||||
|
||||
virtual const Zeus::CColor& splash1() const {return m_splash1;}
|
||||
virtual const Zeus::CColor& splash2() const {return m_splash2;}
|
||||
|
|
|
@ -275,7 +275,7 @@ void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
|||
float pf = rootView().viewRes().pixelFactor();
|
||||
if (m_style == Style::Block)
|
||||
textRect.location[1] += 7 * pf;
|
||||
textRect.location[0] += sub.size[0] / 2;
|
||||
textRect.location[0] += m_nomWidth / 2;
|
||||
textRect.size[0] = m_nomWidth;
|
||||
textRect.size[1] = m_nomHeight;
|
||||
m_text->resized(root, textRect);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "Specter/FileBrowser.hpp"
|
||||
#include "Specter/RootView.hpp"
|
||||
#include "Specter/MessageWindow.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
@ -207,6 +208,54 @@ void FileBrowser::okActivated(bool viaButton)
|
|||
int err = HECL::Stat(path.c_str(), &theStat);
|
||||
if (m_type == Type::SaveFile)
|
||||
{
|
||||
if (m_fileField.m_view->getText().empty())
|
||||
{
|
||||
m_fileField.m_view->setErrorState(
|
||||
vm.translateOr("file_field_empty", "Unable to save empty file").c_str());
|
||||
return;
|
||||
}
|
||||
if (!err && !S_ISDIR(theStat.st_mode))
|
||||
{
|
||||
m_confirmWindow.reset(new MessageWindow(rootView().viewRes(), *this,
|
||||
MessageWindow::Type::ConfirmOkCancel,
|
||||
HECL::Format(vm.translateOr("overwrite_confirm", "Overwrite '%s'?").c_str(), path.c_str()),
|
||||
[&,path](bool ok)
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
m_returnFunc(true, path);
|
||||
m_confirmWindow->close();
|
||||
close();
|
||||
}
|
||||
else
|
||||
m_confirmWindow->close();
|
||||
}));
|
||||
updateSize();
|
||||
return;
|
||||
}
|
||||
if (!err && S_ISDIR(theStat.st_mode))
|
||||
{
|
||||
navigateToPath(path);
|
||||
return;
|
||||
}
|
||||
m_returnFunc(true, path);
|
||||
close();
|
||||
return;
|
||||
}
|
||||
else if (m_type == Type::SaveDirectory)
|
||||
{
|
||||
if (m_fileField.m_view->getText().empty())
|
||||
{
|
||||
m_fileField.m_view->setErrorState(
|
||||
vm.translateOr("directory_field_empty", "Unable to make empty-named directory").c_str());
|
||||
return;
|
||||
}
|
||||
if (!err && !S_ISDIR(theStat.st_mode))
|
||||
{
|
||||
m_fileField.m_view->setErrorState(
|
||||
vm.translateOr("no_overwrite_file", "Unable to make directory over file").c_str());
|
||||
return;
|
||||
}
|
||||
if (!err && S_ISDIR(theStat.st_mode))
|
||||
{
|
||||
navigateToPath(path);
|
||||
|
@ -302,6 +351,10 @@ void FileBrowser::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton bu
|
|||
{
|
||||
if (skipBuildInAnimation() || closed())
|
||||
return;
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->mouseDown(coord, button, mod);
|
||||
|
||||
m_split.mouseDown(coord, button, mod);
|
||||
for (PathButton& b : m_pathButtons)
|
||||
b.m_button.mouseDown(coord, button, mod);
|
||||
|
@ -336,6 +389,9 @@ void FileBrowser::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton butt
|
|||
m_recentBookmarks.m_view->mouseUp(coord, button, mod);
|
||||
m_ok.m_button.mouseUp(coord, button, mod);
|
||||
m_cancel.m_button.mouseUp(coord, button, mod);
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->mouseUp(coord, button, mod);
|
||||
}
|
||||
|
||||
void FileBrowser::mouseMove(const boo::SWindowCoord& coord)
|
||||
|
@ -352,6 +408,9 @@ void FileBrowser::mouseMove(const boo::SWindowCoord& coord)
|
|||
m_recentBookmarks.m_view->mouseMove(coord);
|
||||
m_ok.m_button.mouseMove(coord);
|
||||
m_cancel.m_button.mouseMove(coord);
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->mouseMove(coord);
|
||||
}
|
||||
|
||||
void FileBrowser::mouseEnter(const boo::SWindowCoord& coord)
|
||||
|
@ -369,6 +428,9 @@ void FileBrowser::mouseLeave(const boo::SWindowCoord& coord)
|
|||
m_fileListing.mouseLeave(coord);
|
||||
m_ok.m_button.mouseLeave(coord);
|
||||
m_cancel.m_button.mouseLeave(coord);
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->mouseLeave(coord);
|
||||
}
|
||||
|
||||
void FileBrowser::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
|
||||
|
@ -422,6 +484,9 @@ void FileBrowser::resized(const boo::SWindowRect& root, const boo::SWindowRect&
|
|||
|
||||
if (m_split.m_view)
|
||||
m_split.m_view->resized(root, centerRect);
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->resized(root, sub);
|
||||
}
|
||||
|
||||
void FileBrowser::LeftSide::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
||||
|
@ -500,12 +565,18 @@ void FileBrowser::think()
|
|||
m_systemBookmarks.m_view->think();
|
||||
m_projectBookmarks.m_view->think();
|
||||
m_recentBookmarks.m_view->think();
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->think();
|
||||
}
|
||||
|
||||
void FileBrowser::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
ModalWindow::draw(gfxQ);
|
||||
m_split.m_view->draw(gfxQ);
|
||||
|
||||
if (m_confirmWindow)
|
||||
m_confirmWindow->draw(gfxQ);
|
||||
}
|
||||
|
||||
void FileBrowser::LeftSide::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
#include "Specter/MessageWindow.hpp"
|
||||
#include "Specter/ViewResources.hpp"
|
||||
#include "Specter/RootView.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
MessageWindow::MessageWindow(ViewResources& res, View& parentView,
|
||||
Type type, const std::string& message,
|
||||
std::function<void (bool)> func)
|
||||
: ModalWindow(res, parentView, RectangleConstraint(400 * res.pixelFactor(), 150 * res.pixelFactor()),
|
||||
type==Type::ErrorOk ? res.themeData().splashErrorBackground() : res.themeData().splashBackground()),
|
||||
m_type(type), m_func(func),
|
||||
m_okBind(*this, rootView().viewManager().translateOr("ok", "OK")),
|
||||
m_cancelBind(*this, rootView().viewManager().translateOr("cancel", "Cancel"))
|
||||
{
|
||||
commitResources(res);
|
||||
|
||||
m_text.reset(new MultiLineTextView(res, *this, res.m_mainFont, TextView::Alignment::Center));
|
||||
m_text->typesetGlyphs(message, res.themeData().uiText(), 380 * res.pixelFactor());
|
||||
|
||||
m_ok.m_view.reset(new Button(res, *this, &m_okBind, m_okBind.m_name,
|
||||
Button::Style::Block, RectangleConstraint(150 * res.pixelFactor())));
|
||||
if (type == Type::ConfirmOkCancel)
|
||||
m_cancel.m_view.reset(new Button(res, *this, &m_cancelBind, m_cancelBind.m_name,
|
||||
Button::Style::Block, RectangleConstraint(150 * res.pixelFactor())));
|
||||
|
||||
updateContentOpacity(0.0);
|
||||
}
|
||||
|
||||
void MessageWindow::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
|
||||
{
|
||||
if (closed() || skipBuildInAnimation())
|
||||
return;
|
||||
m_ok.mouseDown(coord, button, mods);
|
||||
m_cancel.mouseDown(coord, button, mods);
|
||||
}
|
||||
|
||||
void MessageWindow::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
|
||||
{
|
||||
if (closed())
|
||||
return;
|
||||
m_ok.mouseUp(coord, button, mods);
|
||||
m_cancel.mouseUp(coord, button, mods);
|
||||
}
|
||||
|
||||
void MessageWindow::mouseMove(const boo::SWindowCoord& coord)
|
||||
{
|
||||
if (closed())
|
||||
return;
|
||||
m_ok.mouseMove(coord);
|
||||
m_cancel.mouseMove(coord);
|
||||
}
|
||||
|
||||
void MessageWindow::mouseEnter(const boo::SWindowCoord& coord)
|
||||
{
|
||||
if (closed())
|
||||
return;
|
||||
m_ok.mouseEnter(coord);
|
||||
m_cancel.mouseEnter(coord);
|
||||
}
|
||||
|
||||
void MessageWindow::mouseLeave(const boo::SWindowCoord& coord)
|
||||
{
|
||||
if (closed())
|
||||
return;
|
||||
m_ok.mouseLeave(coord);
|
||||
m_cancel.mouseLeave(coord);
|
||||
}
|
||||
|
||||
void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
||||
{
|
||||
ModalWindow::resized(root, sub);
|
||||
boo::SWindowRect buttonRect = subRect();
|
||||
float pf = rootView().viewRes().pixelFactor();
|
||||
buttonRect.location[1] += 25 * pf;
|
||||
buttonRect.size[0] = m_ok.m_view->nominalWidth();
|
||||
buttonRect.size[1] = m_ok.m_view->nominalHeight();
|
||||
if (m_type == Type::ConfirmOkCancel)
|
||||
{
|
||||
buttonRect.location[0] += 45 * pf;
|
||||
m_ok.m_view->resized(root, buttonRect);
|
||||
buttonRect.location[0] += 160 * pf;
|
||||
m_cancel.m_view->resized(root, buttonRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonRect.location[0] += 125 * pf;
|
||||
m_ok.m_view->resized(root, buttonRect);
|
||||
}
|
||||
|
||||
boo::SWindowRect textRect = subRect();
|
||||
textRect.location[0] += 200 * pf;
|
||||
textRect.location[1] += 120 * pf;
|
||||
m_text->resized(root, textRect);
|
||||
}
|
||||
|
||||
void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
ModalWindow::draw(gfxQ);
|
||||
m_text->draw(gfxQ);
|
||||
m_ok.m_view->draw(gfxQ);
|
||||
if (m_type == Type::ConfirmOkCancel)
|
||||
m_cancel.m_view->draw(gfxQ);
|
||||
}
|
||||
|
||||
}
|
|
@ -276,9 +276,12 @@ void ModalWindow::setFillColors(float t)
|
|||
}
|
||||
|
||||
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint)
|
||||
: ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {}
|
||||
|
||||
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint, const Zeus::CColor& bgColor)
|
||||
: View(res, parentView),
|
||||
m_constraint(constraint),
|
||||
m_windowBg(res.themeData().splashBackground()),
|
||||
m_windowBg(bgColor),
|
||||
m_windowBgClear(m_windowBg),
|
||||
m_line1(res.themeData().splash1()),
|
||||
m_line2(res.themeData().splash2()),
|
||||
|
|
|
@ -58,7 +58,7 @@ std::string MultiLineTextView::LineWrap(const std::string& str, int wrap)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (sz == 1 && (it[0] == ' ' || it[0] == '-'))
|
||||
if (sz == 1 && (it[0] == ' ' || it[0] == '-' || it[0] == '/' || it[0] == '\\'))
|
||||
{
|
||||
lastSpaceIt = it + 1;
|
||||
lastSpaceRem = rem - 1;
|
||||
|
|
Loading…
Reference in New Issue