When air temp textbox is defocused, correct out of range temperatures
This commit is contained in:
parent
b0e29c8c23
commit
3c9882598c
@ -252,6 +252,16 @@ void Component::OnMouseWheelInside(int localx, int localy, int d)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Component::OnFocus()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Component::OnDefocus()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Component::~Component()
|
Component::~Component()
|
||||||
{
|
{
|
||||||
delete menu;
|
delete menu;
|
||||||
|
@ -207,5 +207,8 @@ namespace ui
|
|||||||
|
|
||||||
virtual void OnTextInput(String text);
|
virtual void OnTextInput(String text);
|
||||||
virtual void OnTextEditing(String text);
|
virtual void OnTextEditing(String text);
|
||||||
|
|
||||||
|
virtual void OnFocus();
|
||||||
|
virtual void OnDefocus();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -604,6 +604,12 @@ void Textbox::OnMouseMoved(int localx, int localy, int dx, int dy)
|
|||||||
Label::OnMouseMoved(localx, localy, dx, dy);
|
Label::OnMouseMoved(localx, localy, dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Textbox::OnDefocus()
|
||||||
|
{
|
||||||
|
if (defocusCallback.callback)
|
||||||
|
defocusCallback.callback();
|
||||||
|
}
|
||||||
|
|
||||||
void Textbox::Draw(const Point& screenPos)
|
void Textbox::Draw(const Point& screenPos)
|
||||||
{
|
{
|
||||||
Label::Draw(screenPos);
|
Label::Draw(screenPos);
|
||||||
|
@ -12,6 +12,11 @@ struct TextboxAction
|
|||||||
std::function<void ()> change;
|
std::function<void ()> change;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextboxDefocusAction
|
||||||
|
{
|
||||||
|
std::function<void ()> callback;
|
||||||
|
};
|
||||||
|
|
||||||
class Textbox : public Label
|
class Textbox : public Label
|
||||||
{
|
{
|
||||||
void AfterTextChange(bool changed);
|
void AfterTextChange(bool changed);
|
||||||
@ -34,6 +39,7 @@ public:
|
|||||||
void SetHidden(bool hidden);
|
void SetHidden(bool hidden);
|
||||||
bool GetHidden() { return masked; }
|
bool GetHidden() { return masked; }
|
||||||
void SetActionCallback(TextboxAction action) { actionCallback = action; }
|
void SetActionCallback(TextboxAction action) { actionCallback = action; }
|
||||||
|
void SetDefocusCallback(TextboxDefocusAction action) { defocusCallback = action; }
|
||||||
|
|
||||||
void SetLimit(size_t limit);
|
void SetLimit(size_t limit);
|
||||||
size_t GetLimit();
|
size_t GetLimit();
|
||||||
@ -57,6 +63,7 @@ public:
|
|||||||
void OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override;
|
void OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override;
|
||||||
void OnTextInput(String text) override;
|
void OnTextInput(String text) override;
|
||||||
void OnTextEditing(String text) override;
|
void OnTextEditing(String text) override;
|
||||||
|
void OnDefocus() override;
|
||||||
void Draw(const Point& screenPos) override;
|
void Draw(const Point& screenPos) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -69,6 +76,7 @@ protected:
|
|||||||
bool masked, border;
|
bool masked, border;
|
||||||
int cursor, cursorPositionX, cursorPositionY;
|
int cursor, cursorPositionX, cursorPositionY;
|
||||||
TextboxAction actionCallback;
|
TextboxAction actionCallback;
|
||||||
|
TextboxDefocusAction defocusCallback;
|
||||||
String backingText;
|
String backingText;
|
||||||
String placeHolder;
|
String placeHolder;
|
||||||
|
|
||||||
|
@ -119,7 +119,14 @@ bool Window::IsFocused(const Component* c) const
|
|||||||
|
|
||||||
void Window::FocusComponent(Component* c)
|
void Window::FocusComponent(Component* c)
|
||||||
{
|
{
|
||||||
|
if (focusedComponent_ != c)
|
||||||
|
{
|
||||||
|
if (focusedComponent_)
|
||||||
|
focusedComponent_->OnDefocus();
|
||||||
this->focusedComponent_ = c;
|
this->focusedComponent_ = c;
|
||||||
|
if (c)
|
||||||
|
c->OnFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::MakeActiveWindow()
|
void Window::MakeActiveWindow()
|
||||||
|
@ -26,8 +26,7 @@
|
|||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
|
|
||||||
OptionsView::OptionsView():
|
OptionsView::OptionsView():
|
||||||
ui::Window(ui::Point(-1, -1), ui::Point(320, 340)),
|
ui::Window(ui::Point(-1, -1), ui::Point(320, 340))
|
||||||
ambientAirTempPreviewValid(false)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
auto autowidth = [this](ui::Component *c) {
|
auto autowidth = [this](ui::Component *c) {
|
||||||
@ -126,28 +125,11 @@ OptionsView::OptionsView():
|
|||||||
currentY+=20;
|
currentY+=20;
|
||||||
ambientAirTemp = new ui::Textbox(ui::Point(Size.X-95, currentY), ui::Point(60, 16));
|
ambientAirTemp = new ui::Textbox(ui::Point(Size.X-95, currentY), ui::Point(60, 16));
|
||||||
ambientAirTemp->SetActionCallback({ [this] {
|
ambientAirTemp->SetActionCallback({ [this] {
|
||||||
float temp;
|
UpdateAirTemp(ambientAirTemp->GetText(), false);
|
||||||
try
|
|
||||||
{
|
|
||||||
void ParseFloatProperty(String value, float &out);
|
|
||||||
ParseFloatProperty(ambientAirTemp->GetText(), temp);
|
|
||||||
ambientAirTempPreviewValid = true;
|
|
||||||
}
|
|
||||||
catch (const std::exception &ex)
|
|
||||||
{
|
|
||||||
ambientAirTempPreviewValid = false;
|
|
||||||
}
|
|
||||||
if (!(MIN_TEMP <= temp && MAX_TEMP >= temp))
|
|
||||||
{
|
|
||||||
ambientAirTempPreviewValid = false;
|
|
||||||
}
|
|
||||||
if (ambientAirTempPreviewValid)
|
|
||||||
{
|
|
||||||
ambientAirTempPreviewValue = temp;
|
|
||||||
c->SetAmbientAirTemperature(ambientAirTempPreviewValue);
|
|
||||||
}
|
|
||||||
UpdateAmbientAirTempPreview();
|
|
||||||
} });
|
} });
|
||||||
|
ambientAirTemp->SetDefocusCallback({ [this] {
|
||||||
|
UpdateAirTemp(ambientAirTemp->GetText(), true);
|
||||||
|
}});
|
||||||
scrollPanel->AddChild(ambientAirTemp);
|
scrollPanel->AddChild(ambientAirTemp);
|
||||||
|
|
||||||
ambientAirTempPreview = new ui::Button(ui::Point(Size.X-31, currentY), ui::Point(16, 16), "", "Preview");
|
ambientAirTempPreview = new ui::Button(ui::Point(Size.X-31, currentY), ui::Point(16, 16), "", "Preview");
|
||||||
@ -369,12 +351,12 @@ OptionsView::OptionsView():
|
|||||||
scrollPanel->InnerSize = ui::Point(Size.X, currentY);
|
scrollPanel->InnerSize = ui::Point(Size.X, currentY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsView::UpdateAmbientAirTempPreview()
|
void OptionsView::UpdateAmbientAirTempPreview(float airTemp, bool isValid)
|
||||||
{
|
{
|
||||||
if (ambientAirTempPreviewValid)
|
if (isValid)
|
||||||
{
|
{
|
||||||
int HeatToColour(float temp);
|
int HeatToColour(float temp);
|
||||||
int c = HeatToColour(ambientAirTempPreviewValue);
|
int c = HeatToColour(airTemp);
|
||||||
ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c));
|
ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c));
|
||||||
ambientAirTempPreview->SetText("");
|
ambientAirTempPreview->SetText("");
|
||||||
}
|
}
|
||||||
@ -386,6 +368,55 @@ void OptionsView::UpdateAmbientAirTempPreview()
|
|||||||
ambientAirTempPreview->Appearance.BackgroundHover = ambientAirTempPreview->Appearance.BackgroundInactive;
|
ambientAirTempPreview->Appearance.BackgroundHover = ambientAirTempPreview->Appearance.BackgroundInactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptionsView::UpdateAirTemp(String temp, bool isDefocus)
|
||||||
|
{
|
||||||
|
// Parse air temp and determine validity
|
||||||
|
float airTemp;
|
||||||
|
bool isValid;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void ParseFloatProperty(String value, float &out);
|
||||||
|
ParseFloatProperty(temp, airTemp);
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// While defocusing, correct out of range temperatures and empty textboxes
|
||||||
|
if (isDefocus)
|
||||||
|
{
|
||||||
|
if (temp.empty())
|
||||||
|
{
|
||||||
|
isValid = true;
|
||||||
|
airTemp = R_TEMP + 273.15;
|
||||||
|
}
|
||||||
|
else if (!isValid)
|
||||||
|
return;
|
||||||
|
else if (airTemp < MIN_TEMP)
|
||||||
|
airTemp = MIN_TEMP;
|
||||||
|
else if (airTemp > MAX_TEMP)
|
||||||
|
airTemp = MAX_TEMP;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Update textbox with the new value
|
||||||
|
StringBuilder sb;
|
||||||
|
sb << Format::Precision(2) << airTemp;
|
||||||
|
ambientAirTemp->SetText(sb.Build());
|
||||||
|
}
|
||||||
|
// Out of range temperatures are invalid, preview should go away
|
||||||
|
else if (airTemp < MIN_TEMP || airTemp > MAX_TEMP)
|
||||||
|
isValid = false;
|
||||||
|
|
||||||
|
// If valid, set temp
|
||||||
|
if (isValid)
|
||||||
|
c->SetAmbientAirTemperature(airTemp);
|
||||||
|
|
||||||
|
UpdateAmbientAirTempPreview(airTemp, isValid);
|
||||||
|
}
|
||||||
|
|
||||||
void OptionsView::NotifySettingsChanged(OptionsModel * sender)
|
void OptionsView::NotifySettingsChanged(OptionsModel * sender)
|
||||||
{
|
{
|
||||||
heatSimulation->SetChecked(sender->GetHeatSimulation());
|
heatSimulation->SetChecked(sender->GetHeatSimulation());
|
||||||
@ -393,28 +424,14 @@ void OptionsView::NotifySettingsChanged(OptionsModel * sender)
|
|||||||
newtonianGravity->SetChecked(sender->GetNewtonianGravity());
|
newtonianGravity->SetChecked(sender->GetNewtonianGravity());
|
||||||
waterEqualisation->SetChecked(sender->GetWaterEqualisation());
|
waterEqualisation->SetChecked(sender->GetWaterEqualisation());
|
||||||
airMode->SetOption(sender->GetAirMode());
|
airMode->SetOption(sender->GetAirMode());
|
||||||
if (!ambientAirTempPreviewValid)
|
// Initialize air temp and preview only when the options menu is opened, and not when user is actively editing the textbox
|
||||||
|
if (!initializedAirTempPreview)
|
||||||
{
|
{
|
||||||
// * ambientAirTempPreviewValid is initially false (see constructor). Thus, when
|
initializedAirTempPreview = true;
|
||||||
// NotifySettingsChanged is first called when the view is registered as an
|
float airTemp = sender->GetAmbientAirTemperature();
|
||||||
// observer, this block executes. Once this happens, NotifySettingsChanged is
|
UpdateAmbientAirTempPreview(airTemp, true);
|
||||||
// only ever called when some setting is changed by the user in OptionsView.
|
|
||||||
// This means either a change that doesn't involve the ambientAirTemp Textbox,
|
|
||||||
// or one that does involve it. The latter case can only happen if the action
|
|
||||||
// callback of the Textbox called OptionsController::SetAmbientAirTemperature,
|
|
||||||
// which in turn implies that ambientAirTempPreviewValid is already true.
|
|
||||||
// * What this all boils down to is that this block is only ever run on two
|
|
||||||
// occasions: when OptionsView is initialized and when the user decides to
|
|
||||||
// cancel changing the ambient temperature via the ambientAirTemp Textbox,
|
|
||||||
// and hasn't yet succeeded. What we want to avoid is SetText being called
|
|
||||||
// on the Textbox while the user is actively editing its contents, so this
|
|
||||||
// works out perfectly.
|
|
||||||
// * Rather twisted. I blame the MVC pattern TPT uses. -- LBPHacker
|
|
||||||
ambientAirTempPreviewValid = true;
|
|
||||||
ambientAirTempPreviewValue = sender->GetAmbientAirTemperature();
|
|
||||||
UpdateAmbientAirTempPreview();
|
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb << Format::Precision(2) << ambientAirTempPreviewValue;
|
sb << Format::Precision(2) << airTemp;
|
||||||
ambientAirTemp->SetText(sb.Build());
|
ambientAirTemp->SetText(sb.Build());
|
||||||
}
|
}
|
||||||
gravityMode->SetOption(sender->GetGravityMode());
|
gravityMode->SetOption(sender->GetGravityMode());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef OPTIONSVIEW_H_
|
#ifndef OPTIONSVIEW_H_
|
||||||
#define OPTIONSVIEW_H_
|
#define OPTIONSVIEW_H_
|
||||||
|
|
||||||
|
#include "common/String.h"
|
||||||
#include "gui/interface/Window.h"
|
#include "gui/interface/Window.h"
|
||||||
#include "gui/interface/ScrollPanel.h"
|
#include "gui/interface/ScrollPanel.h"
|
||||||
|
|
||||||
@ -39,9 +40,9 @@ class OptionsView: public ui::Window
|
|||||||
ui::Checkbox * includePressure;
|
ui::Checkbox * includePressure;
|
||||||
ui::Checkbox * perfectCirclePressure;
|
ui::Checkbox * perfectCirclePressure;
|
||||||
ui::ScrollPanel * scrollPanel;
|
ui::ScrollPanel * scrollPanel;
|
||||||
bool ambientAirTempPreviewValid;
|
bool initializedAirTempPreview = false;
|
||||||
float ambientAirTempPreviewValue;
|
void UpdateAmbientAirTempPreview(float airTemp, bool isValid);
|
||||||
void UpdateAmbientAirTempPreview();
|
void UpdateAirTemp(String temp, bool isDefocus);
|
||||||
public:
|
public:
|
||||||
OptionsView();
|
OptionsView();
|
||||||
void NotifySettingsChanged(OptionsModel * sender);
|
void NotifySettingsChanged(OptionsModel * sender);
|
||||||
|
Loading…
Reference in New Issue
Block a user