When air temp textbox is defocused, correct out of range temperatures

This commit is contained in:
jacob1 2021-06-18 23:07:17 -04:00
parent b0e29c8c23
commit 3c9882598c
No known key found for this signature in database
GPG Key ID: 4E58A32D510E1995
7 changed files with 102 additions and 50 deletions

View File

@ -252,6 +252,16 @@ void Component::OnMouseWheelInside(int localx, int localy, int d)
{
}
void Component::OnFocus()
{
}
void Component::OnDefocus()
{
}
Component::~Component()
{
delete menu;

View File

@ -207,5 +207,8 @@ namespace ui
virtual void OnTextInput(String text);
virtual void OnTextEditing(String text);
virtual void OnFocus();
virtual void OnDefocus();
};
}

View File

@ -604,6 +604,12 @@ void Textbox::OnMouseMoved(int localx, int localy, int dx, int dy)
Label::OnMouseMoved(localx, localy, dx, dy);
}
void Textbox::OnDefocus()
{
if (defocusCallback.callback)
defocusCallback.callback();
}
void Textbox::Draw(const Point& screenPos)
{
Label::Draw(screenPos);

View File

@ -12,6 +12,11 @@ struct TextboxAction
std::function<void ()> change;
};
struct TextboxDefocusAction
{
std::function<void ()> callback;
};
class Textbox : public Label
{
void AfterTextChange(bool changed);
@ -34,6 +39,7 @@ public:
void SetHidden(bool hidden);
bool GetHidden() { return masked; }
void SetActionCallback(TextboxAction action) { actionCallback = action; }
void SetDefocusCallback(TextboxDefocusAction action) { defocusCallback = action; }
void SetLimit(size_t limit);
size_t GetLimit();
@ -57,6 +63,7 @@ public:
void OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override;
void OnTextInput(String text) override;
void OnTextEditing(String text) override;
void OnDefocus() override;
void Draw(const Point& screenPos) override;
protected:
@ -69,6 +76,7 @@ protected:
bool masked, border;
int cursor, cursorPositionX, cursorPositionY;
TextboxAction actionCallback;
TextboxDefocusAction defocusCallback;
String backingText;
String placeHolder;

View File

@ -119,7 +119,14 @@ bool Window::IsFocused(const Component* c) const
void Window::FocusComponent(Component* c)
{
this->focusedComponent_ = c;
if (focusedComponent_ != c)
{
if (focusedComponent_)
focusedComponent_->OnDefocus();
this->focusedComponent_ = c;
if (c)
c->OnFocus();
}
}
void Window::MakeActiveWindow()

View File

@ -26,8 +26,7 @@
#include "graphics/Graphics.h"
OptionsView::OptionsView():
ui::Window(ui::Point(-1, -1), ui::Point(320, 340)),
ambientAirTempPreviewValid(false)
ui::Window(ui::Point(-1, -1), ui::Point(320, 340))
{
auto autowidth = [this](ui::Component *c) {
@ -126,28 +125,11 @@ OptionsView::OptionsView():
currentY+=20;
ambientAirTemp = new ui::Textbox(ui::Point(Size.X-95, currentY), ui::Point(60, 16));
ambientAirTemp->SetActionCallback({ [this] {
float temp;
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();
UpdateAirTemp(ambientAirTemp->GetText(), false);
} });
ambientAirTemp->SetDefocusCallback({ [this] {
UpdateAirTemp(ambientAirTemp->GetText(), true);
}});
scrollPanel->AddChild(ambientAirTemp);
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);
}
void OptionsView::UpdateAmbientAirTempPreview()
void OptionsView::UpdateAmbientAirTempPreview(float airTemp, bool isValid)
{
if (ambientAirTempPreviewValid)
if (isValid)
{
int HeatToColour(float temp);
int c = HeatToColour(ambientAirTempPreviewValue);
int c = HeatToColour(airTemp);
ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c));
ambientAirTempPreview->SetText("");
}
@ -386,6 +368,55 @@ void OptionsView::UpdateAmbientAirTempPreview()
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)
{
heatSimulation->SetChecked(sender->GetHeatSimulation());
@ -393,28 +424,14 @@ void OptionsView::NotifySettingsChanged(OptionsModel * sender)
newtonianGravity->SetChecked(sender->GetNewtonianGravity());
waterEqualisation->SetChecked(sender->GetWaterEqualisation());
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
// NotifySettingsChanged is first called when the view is registered as an
// observer, this block executes. Once this happens, NotifySettingsChanged is
// 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();
initializedAirTempPreview = true;
float airTemp = sender->GetAmbientAirTemperature();
UpdateAmbientAirTempPreview(airTemp, true);
StringBuilder sb;
sb << Format::Precision(2) << ambientAirTempPreviewValue;
sb << Format::Precision(2) << airTemp;
ambientAirTemp->SetText(sb.Build());
}
gravityMode->SetOption(sender->GetGravityMode());

View File

@ -1,6 +1,7 @@
#ifndef OPTIONSVIEW_H_
#define OPTIONSVIEW_H_
#include "common/String.h"
#include "gui/interface/Window.h"
#include "gui/interface/ScrollPanel.h"
@ -39,9 +40,9 @@ class OptionsView: public ui::Window
ui::Checkbox * includePressure;
ui::Checkbox * perfectCirclePressure;
ui::ScrollPanel * scrollPanel;
bool ambientAirTempPreviewValid;
float ambientAirTempPreviewValue;
void UpdateAmbientAirTempPreview();
bool initializedAirTempPreview = false;
void UpdateAmbientAirTempPreview(float airTemp, bool isValid);
void UpdateAirTemp(String temp, bool isDefocus);
public:
OptionsView();
void NotifySettingsChanged(OptionsModel * sender);