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()
|
||||
{
|
||||
delete menu;
|
||||
|
@ -207,5 +207,8 @@ namespace ui
|
||||
|
||||
virtual void OnTextInput(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);
|
||||
}
|
||||
|
||||
void Textbox::OnDefocus()
|
||||
{
|
||||
if (defocusCallback.callback)
|
||||
defocusCallback.callback();
|
||||
}
|
||||
|
||||
void Textbox::Draw(const Point& screenPos)
|
||||
{
|
||||
Label::Draw(screenPos);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user