Skip to content

Commit

Permalink
Add double precision widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
darbyjohnston committed May 18, 2023
1 parent ce9fa77 commit b2a2015
Show file tree
Hide file tree
Showing 14 changed files with 633 additions and 20 deletions.
22 changes: 11 additions & 11 deletions examples/play-glfw/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

#include <tlUI/ButtonGroup.h>
#include <tlUI/ComboBox.h>
#include <tlUI/DoubleEdit.h>
#include <tlUI/DoubleModel.h>
#include <tlUI/IncButtons.h>
#include <tlUI/FloatEdit.h>
#include <tlUI/FloatModel.h>
#include <tlUI/RowLayout.h>
#include <tlUI/Splitter.h>
#include <tlUI/TimeEdit.h>
Expand All @@ -31,23 +31,23 @@ namespace tl
struct MainWindow::Private
{
std::shared_ptr<timeline::TimeUnitsModel> timeUnitsModel;
std::shared_ptr<ui::FloatModel> speedModel;
std::shared_ptr<ui::DoubleModel> speedModel;
timelineui::ItemOptions itemOptions;

std::shared_ptr<timelineui::TimelineViewport> timelineViewport;
std::shared_ptr<timelineui::TimelineWidget> timelineWidget;
std::shared_ptr<ui::ButtonGroup> playbackButtonGroup;
std::shared_ptr<ui::ButtonGroup> frameButtonGroup;
std::shared_ptr<ui::TimeEdit> currentTimeEdit;
std::shared_ptr<ui::FloatEdit> speedEdit;
std::shared_ptr<ui::DoubleEdit> speedEdit;
std::shared_ptr<ui::TimeLabel> durationLabel;
std::shared_ptr<ui::ComboBox> timeUnitsComboBox;
std::shared_ptr<ui::Splitter> splitter;
std::shared_ptr<ui::RowLayout> layout;

std::shared_ptr<observer::ValueObserver<timeline::TimeUnits> > timeUnitsObserver;
std::shared_ptr<observer::ValueObserver<double> > speedObserver;
std::shared_ptr<observer::ValueObserver<float> > speedObserver2;
std::shared_ptr<observer::ValueObserver<double> > speedObserver2;
std::shared_ptr<observer::ValueObserver<timeline::Playback> > playbackObserver;
std::shared_ptr<observer::ValueObserver<otime::RationalTime> > currentTimeObserver;
};
Expand All @@ -62,8 +62,8 @@ namespace tl
setBackgroundRole(ui::ColorRole::Window);

p.timeUnitsModel = timeline::TimeUnitsModel::create(context);
p.speedModel = ui::FloatModel::create(context);
p.speedModel->setRange(math::FloatRange(0.F, 1000.F));
p.speedModel = ui::DoubleModel::create(context);
p.speedModel->setRange(math::DoubleRange(0.0, 1000.0));
p.speedModel->setStep(1.F);
p.speedModel->setLargeStep(10.F);

Expand Down Expand Up @@ -103,8 +103,8 @@ namespace tl
p.currentTimeEdit = ui::TimeEdit::create(p.timeUnitsModel, context);
auto currentTimeIncButtons = ui::IncButtons::create(context);

p.speedEdit = ui::FloatEdit::create(p.speedModel, context);
auto speedIncButtons = ui::FloatIncButtons::create(p.speedModel, context);
p.speedEdit = ui::DoubleEdit::create(p.speedModel, context);
auto speedIncButtons = ui::DoubleIncButtons::create(p.speedModel, context);

p.durationLabel = ui::TimeLabel::create(p.timeUnitsModel, context);
p.durationLabel->setValue(player->getTimeRange().duration());
Expand Down Expand Up @@ -181,9 +181,9 @@ namespace tl
{
_p->speedModel->setValue(value);
});
p.speedObserver2 = observer::ValueObserver<float>::create(
p.speedObserver2 = observer::ValueObserver<double>::create(
p.speedModel->observeValue(),
[player](float value)
[player](double value)
{
player->setSpeed(value);
});
Expand Down
43 changes: 43 additions & 0 deletions lib/tlCore/Range.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ namespace tl
json = { value.getMin(), value.getMax() };
}

void to_json(nlohmann::json& json, const DoubleRange& value)
{
json = { value.getMin(), value.getMax() };
}

void from_json(const nlohmann::json& json, IntRange& value)
{
int min = 0;
Expand Down Expand Up @@ -55,6 +60,15 @@ namespace tl
value = FloatRange(min, max);
}

void from_json(const nlohmann::json& json, DoubleRange& value)
{
double min = 0.0;
double max = 0.0;
json.at(0).get_to(min);
json.at(1).get_to(max);
value = DoubleRange(min, max);
}

std::ostream& operator << (std::ostream& os, const IntRange& value)
{
os << value.getMin() << "-" << value.getMax();
Expand All @@ -73,6 +87,12 @@ namespace tl
return os;
}

std::ostream& operator << (std::ostream& os, const DoubleRange& value)
{
os << value.getMin() << "-" << value.getMax();
return os;
}

std::istream& operator >> (std::istream& is, IntRange& value)
{
std::string s;
Expand Down Expand Up @@ -141,5 +161,28 @@ namespace tl
value = FloatRange(min, max);
return is;
}

std::istream& operator >> (std::istream& is, DoubleRange& value)
{
std::string s;
is >> s;
auto split = string::split(s, '-');
if (split.size() != 2)
{
throw error::ParseError();
}
double min = 0.0;
double max = 0.0;
{
std::stringstream ss(split[0]);
ss >> min;
}
{
std::stringstream ss(split[1]);
ss >> max;
}
value = DoubleRange(min, max);
return is;
}
}
}
7 changes: 7 additions & 0 deletions lib/tlCore/Range.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,28 @@ namespace tl
//! This typedef provides a floating point range.
typedef Range<float> FloatRange;

//! This typedef provides a double precision floating point range.
typedef Range<double> DoubleRange;

void to_json(nlohmann::json&, const IntRange&);
void to_json(nlohmann::json&, const SizeTRange&);
void to_json(nlohmann::json&, const FloatRange&);
void to_json(nlohmann::json&, const DoubleRange&);

void from_json(const nlohmann::json&, IntRange&);
void from_json(const nlohmann::json&, SizeTRange&);
void from_json(const nlohmann::json&, FloatRange&);
void from_json(const nlohmann::json&, DoubleRange&);

std::ostream& operator << (std::ostream&, const IntRange&);
std::ostream& operator << (std::ostream&, const SizeTRange&);
std::ostream& operator << (std::ostream&, const FloatRange&);
std::ostream& operator << (std::ostream&, const DoubleRange&);

std::istream& operator >> (std::istream&, IntRange&);
std::istream& operator >> (std::istream&, SizeTRange&);
std::istream& operator >> (std::istream&, FloatRange&);
std::istream& operator >> (std::istream&, DoubleRange&);
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/tlUI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
set(HEADERS
ButtonGroup.h
ComboBox.h
DoubleEdit.h
DoubleModel.h
DrawUtil.h
Event.h
EventLoop.h
Expand Down Expand Up @@ -43,6 +45,8 @@ set(HEADERS_PRIVATE)
set(SOURCE
ButtonGroup.cpp
ComboBox.cpp
DoubleEdit.cpp
DoubleModel.cpp
DrawUtil.cpp
Event.cpp
EventLoop.cpp
Expand Down
186 changes: 186 additions & 0 deletions lib/tlUI/DoubleEdit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2021-2023 Darby Johnston
// All rights reserved.

#include <tlUI/DoubleEdit.h>

#include <tlUI/DoubleModel.h>
#include <tlUI/LayoutUtil.h>
#include <tlUI/LineEdit.h>

#include <tlCore/StringFormat.h>

namespace tl
{
namespace ui
{
struct DoubleEdit::Private
{
std::shared_ptr<DoubleModel> model;
std::shared_ptr<LineEdit> lineEdit;
int digits = 3;
int precision = 2;

struct SizeData
{
int margin = 0;
};
SizeData size;

std::shared_ptr<observer::ValueObserver<double> > valueObserver;
std::shared_ptr<observer::ValueObserver<math::DoubleRange> > rangeObserver;
};

void DoubleEdit::_init(
const std::shared_ptr<DoubleModel>& model,
const std::shared_ptr<system::Context>& context,
const std::shared_ptr<IWidget>& parent)
{
IWidget::_init("tl::ui::DoubleEdit", context, parent);
TLRENDER_P();

p.lineEdit = LineEdit::create(context, shared_from_this());
p.lineEdit->setFontRole(FontRole::Mono);

p.model = model;
if (!p.model)
{
p.model = DoubleModel::create(context);
}

p.lineEdit->setTextCallback(
[this](const std::string& value)
{
_p->model->setValue(std::atof(value.c_str()));
_textUpdate();
});
p.lineEdit->setFocusCallback(
[this](bool value)
{
if (!value)
{
_textUpdate();
}
});

p.valueObserver = observer::ValueObserver<double>::create(
p.model->observeValue(),
[this](double)
{
_textUpdate();
});

p.rangeObserver = observer::ValueObserver<math::DoubleRange>::create(
p.model->observeRange(),
[this](const math::DoubleRange&)
{
_textUpdate();
});

_textUpdate();
}

DoubleEdit::DoubleEdit() :
_p(new Private)
{}

DoubleEdit::~DoubleEdit()
{}

std::shared_ptr<DoubleEdit> DoubleEdit::create(
const std::shared_ptr<DoubleModel>& model,
const std::shared_ptr<system::Context>& context,
const std::shared_ptr<IWidget>& parent)
{
auto out = std::shared_ptr<DoubleEdit>(new DoubleEdit);
out->_init(model, context, parent);
return out;
}

const std::shared_ptr<DoubleModel>& DoubleEdit::getModel() const
{
return _p->model;
}

void DoubleEdit::setDigits(int value)
{
TLRENDER_P();
if (value == p.digits)
return;
p.digits = value;
_textUpdate();
}

void DoubleEdit::setPrecision(int value)
{
TLRENDER_P();
if (value == p.precision)
return;
p.precision = value;
_textUpdate();
}

void DoubleEdit::setFontRole(FontRole value)
{
_p->lineEdit->setFontRole(value);
}

void DoubleEdit::setGeometry(const math::BBox2i& value)
{
IWidget::setGeometry(value);
_p->lineEdit->setGeometry(value);
}

void DoubleEdit::sizeHintEvent(const SizeHintEvent& event)
{
IWidget::sizeHintEvent(event);
_sizeHint = _p->lineEdit->getSizeHint();
}

void DoubleEdit::keyPressEvent(KeyEvent& event)
{
TLRENDER_P();
if (isEnabled() && p.model)
{
switch (event.key)
{
case Key::Down:
event.accept = true;
p.model->decrementStep();
break;
case Key::Up:
event.accept = true;
p.model->incrementStep();
break;
case Key::PageUp:
event.accept = true;
p.model->incrementLargeStep();
break;
case Key::PageDown:
event.accept = true;
p.model->decrementLargeStep();
break;
}
}
}

void DoubleEdit::keyReleaseEvent(KeyEvent& event)
{
event.accept = true;
}

void DoubleEdit::_textUpdate()
{
TLRENDER_P();
std::string text;
std::string format;
if (p.model)
{
text = string::Format("{0}").arg(p.model->getValue(), p.precision);
format = string::Format("{0}").arg(0, p.digits + 1 + p.precision);
}
p.lineEdit->setText(text);
p.lineEdit->setFormat(format);
}
}
}
Loading

0 comments on commit b2a2015

Please sign in to comment.