mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/shared] Add toggle buttons in Graph view
Change-Id: I7548d11fb114b2605ce34d3bda0776277b79ff9d
This commit is contained in:
committed by
Émilie Feral
parent
a76e54642c
commit
2f97dab6d1
@@ -34,7 +34,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
|||||||
for (int index = 0; index < m_store->numberOfPairsOfSeries(series); index++) {
|
for (int index = 0; index < m_store->numberOfPairsOfSeries(series); index++) {
|
||||||
drawDot(ctx, rect, m_store->get(series, 0, index), m_store->get(series, 1, index), color);
|
drawDot(ctx, rect, m_store->get(series, 0, index), m_store->get(series, 1, index), color);
|
||||||
}
|
}
|
||||||
drawDot(ctx, rect, m_store->meanOfColumn(series, 0), m_store->meanOfColumn(series, 1), color, Size::Medium);
|
drawDot(ctx, rect, m_store->meanOfColumn(series, 0), m_store->meanOfColumn(series, 1), color, Size::Small);
|
||||||
drawDot(ctx, rect, m_store->meanOfColumn(series, 0), m_store->meanOfColumn(series, 1), KDColorWhite);
|
drawDot(ctx, rect, m_store->meanOfColumn(series, 0), m_store->meanOfColumn(series, 1), KDColorWhite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -458,14 +458,14 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor
|
|||||||
KDCoordinate diameter = 0;
|
KDCoordinate diameter = 0;
|
||||||
const uint8_t * mask = nullptr;
|
const uint8_t * mask = nullptr;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case Size::Tiny:
|
||||||
|
diameter = Dots::TinyDotDiameter;
|
||||||
|
mask = (const uint8_t *)Dots::TinyDotMask;
|
||||||
|
break;
|
||||||
case Size::Small:
|
case Size::Small:
|
||||||
diameter = Dots::SmallDotDiameter;
|
diameter = Dots::SmallDotDiameter;
|
||||||
mask = (const uint8_t *)Dots::SmallDotMask;
|
mask = (const uint8_t *)Dots::SmallDotMask;
|
||||||
break;
|
break;
|
||||||
case Size::Medium:
|
|
||||||
diameter = Dots::MediumDotDiameter;
|
|
||||||
mask = (const uint8_t *)Dots::MediumDotMask;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
assert(size == Size::Large);
|
assert(size == Size::Large);
|
||||||
diameter = Dots::LargeDotDiameter;
|
diameter = Dots::LargeDotDiameter;
|
||||||
|
|||||||
@@ -75,11 +75,11 @@ protected:
|
|||||||
KDColor color, bool thick = true
|
KDColor color, bool thick = true
|
||||||
) const;
|
) const;
|
||||||
enum class Size : uint8_t {
|
enum class Size : uint8_t {
|
||||||
|
Tiny,
|
||||||
Small,
|
Small,
|
||||||
Medium,
|
|
||||||
Large
|
Large
|
||||||
};
|
};
|
||||||
void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, Size size = Size::Small) const;
|
void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, Size size = Size::Tiny) const;
|
||||||
/* 'drawArrow' draws the edge of an arrow pointing to (x,y) with the
|
/* 'drawArrow' draws the edge of an arrow pointing to (x,y) with the
|
||||||
* orientation (dx,dy).
|
* orientation (dx,dy).
|
||||||
* The parameters defining the shape of the arrow are the length of
|
* The parameters defining the shape of the arrow are the length of
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
const uint8_t Dots::SmallDotMask[Dots::SmallDotDiameter][Dots::SmallDotDiameter] = {
|
const uint8_t Dots::TinyDotMask[Dots::TinyDotDiameter][Dots::TinyDotDiameter] = {
|
||||||
{0xE1, 0x45, 0x0C, 0x45, 0xE1},
|
{0xE1, 0x45, 0x0C, 0x45, 0xE1},
|
||||||
{0x45, 0x00, 0x00, 0x00, 0x45},
|
{0x45, 0x00, 0x00, 0x00, 0x45},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
@@ -10,7 +10,7 @@ const uint8_t Dots::SmallDotMask[Dots::SmallDotDiameter][Dots::SmallDotDiameter]
|
|||||||
{0xE1, 0x45, 0x0C, 0x45, 0xE1},
|
{0xE1, 0x45, 0x0C, 0x45, 0xE1},
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t Dots::MediumDotMask[Dots::MediumDotDiameter][Dots::MediumDotDiameter] = {
|
const uint8_t Dots::SmallDotMask[Dots::SmallDotDiameter][Dots::SmallDotDiameter] = {
|
||||||
{0xE1, 0x45, 0x0C, 0x00, 0x0C, 0x45, 0xE1},
|
{0xE1, 0x45, 0x0C, 0x00, 0x0C, 0x45, 0xE1},
|
||||||
{0x45, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x45},
|
{0x45, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x45},
|
||||||
{0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C},
|
{0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C},
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ namespace Shared {
|
|||||||
|
|
||||||
class Dots {
|
class Dots {
|
||||||
public:
|
public:
|
||||||
static constexpr KDCoordinate SmallDotDiameter = 5;
|
static constexpr KDCoordinate TinyDotDiameter = 5;
|
||||||
|
static const uint8_t TinyDotMask[TinyDotDiameter][TinyDotDiameter];
|
||||||
|
static constexpr KDCoordinate SmallDotDiameter = 7;
|
||||||
static const uint8_t SmallDotMask[SmallDotDiameter][SmallDotDiameter];
|
static const uint8_t SmallDotMask[SmallDotDiameter][SmallDotDiameter];
|
||||||
static constexpr KDCoordinate MediumDotDiameter = 7;
|
|
||||||
static const uint8_t MediumDotMask[MediumDotDiameter][MediumDotDiameter];
|
|
||||||
static constexpr KDCoordinate LargeDotDiameter = 10;
|
static constexpr KDCoordinate LargeDotDiameter = 10;
|
||||||
static const uint8_t LargeDotMask[LargeDotDiameter][LargeDotDiameter];
|
static const uint8_t LargeDotMask[LargeDotDiameter][LargeDotDiameter];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ float InteractiveCurveViewController::addMargin(float y, float range, bool isVer
|
|||||||
return y + ratio * range;
|
return y + ratio * range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InteractiveCurveViewController::updateZoomButtons() {
|
||||||
|
m_autoButton.setState(m_interactiveRange->zoomAuto());
|
||||||
|
m_normalizeButton.setState(m_interactiveRange->zoomNormalize());
|
||||||
|
}
|
||||||
|
|
||||||
const char * InteractiveCurveViewController::title() {
|
const char * InteractiveCurveViewController::title() {
|
||||||
return I18n::translate(I18n::Message::GraphTab);
|
return I18n::translate(I18n::Message::GraphTab);
|
||||||
}
|
}
|
||||||
@@ -304,9 +309,7 @@ bool InteractiveCurveViewController::autoButtonAction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InteractiveCurveViewController::normalizeButtonAction() {
|
bool InteractiveCurveViewController::normalizeButtonAction() {
|
||||||
if (m_interactiveRange->zoomNormalize()) {
|
if (!m_interactiveRange->zoomNormalize()) {
|
||||||
m_interactiveRange->setZoomNormalize(false);
|
|
||||||
} else {
|
|
||||||
m_interactiveRange->setZoomAuto(false);
|
m_interactiveRange->setZoomAuto(false);
|
||||||
m_interactiveRange->normalize();
|
m_interactiveRange->normalize();
|
||||||
setCurveViewAsMainView();
|
setCurveViewAsMainView();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "range_parameter_controller.h"
|
#include "range_parameter_controller.h"
|
||||||
#include "function_zoom_and_pan_curve_view_controller.h"
|
#include "function_zoom_and_pan_curve_view_controller.h"
|
||||||
#include <poincare/coordinate_2D.h>
|
#include <poincare/coordinate_2D.h>
|
||||||
|
#include <escher/button_state.h>
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ private:
|
|||||||
|
|
||||||
// InteractiveCurveViewRangeDelegate
|
// InteractiveCurveViewRangeDelegate
|
||||||
float addMargin(float x, float range, bool isVertical, bool isMin) override;
|
float addMargin(float x, float range, bool isVertical, bool isMin) override;
|
||||||
|
void updateZoomButtons() override;
|
||||||
|
|
||||||
void setCurveViewAsMainView();
|
void setCurveViewAsMainView();
|
||||||
|
|
||||||
@@ -79,8 +81,8 @@ private:
|
|||||||
RangeParameterController m_rangeParameterController;
|
RangeParameterController m_rangeParameterController;
|
||||||
FunctionZoomAndPanCurveViewController m_zoomParameterController;
|
FunctionZoomAndPanCurveViewController m_zoomParameterController;
|
||||||
InteractiveCurveViewRange * m_interactiveRange;
|
InteractiveCurveViewRange * m_interactiveRange;
|
||||||
Button m_autoButton;
|
ButtonState m_autoButton;
|
||||||
Button m_normalizeButton;
|
ButtonState m_normalizeButton;
|
||||||
Button m_navigationButton;
|
Button m_navigationButton;
|
||||||
Button m_rangeButton;
|
Button m_rangeButton;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ using namespace Poincare;
|
|||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
|
void InteractiveCurveViewRange::setDelegate(InteractiveCurveViewRangeDelegate * delegate) {
|
||||||
|
m_delegate = delegate;
|
||||||
|
if (delegate) {
|
||||||
|
m_delegate->updateZoomButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t InteractiveCurveViewRange::rangeChecksum() {
|
uint32_t InteractiveCurveViewRange::rangeChecksum() {
|
||||||
float data[] = {xMin(), xMax(), yMin(), yMax()};
|
float data[] = {xMin(), xMax(), yMin(), yMax()};
|
||||||
size_t dataLengthInBytes = sizeof(data);
|
size_t dataLengthInBytes = sizeof(data);
|
||||||
@@ -18,6 +25,20 @@ uint32_t InteractiveCurveViewRange::rangeChecksum() {
|
|||||||
return Ion::crc32Word((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
|
return Ion::crc32Word((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InteractiveCurveViewRange::setZoomAuto(bool v) {
|
||||||
|
m_zoomAuto = v;
|
||||||
|
if (m_delegate) {
|
||||||
|
m_delegate->updateZoomButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractiveCurveViewRange::setZoomNormalize(bool v) {
|
||||||
|
m_zoomNormalize = v;
|
||||||
|
if (m_delegate) {
|
||||||
|
m_delegate->updateZoomButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InteractiveCurveViewRange::setXMin(float xMin) {
|
void InteractiveCurveViewRange::setXMin(float xMin) {
|
||||||
MemoizedCurveViewRange::protectedSetXMin(xMin, k_lowerMaxFloat, k_upperMaxFloat);
|
MemoizedCurveViewRange::protectedSetXMin(xMin, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
}
|
}
|
||||||
@@ -55,7 +76,7 @@ void InteractiveCurveViewRange::zoom(float ratio, float x, float y) {
|
|||||||
float xMa = xMax();
|
float xMa = xMax();
|
||||||
float yMi = yMin();
|
float yMi = yMin();
|
||||||
float yMa = yMax();
|
float yMa = yMax();
|
||||||
m_zoomAuto = false;
|
setZoomAuto(false);
|
||||||
if (ratio*std::fabs(xMa-xMi) < Range1D::k_minFloat || ratio*std::fabs(yMa-yMi) < Range1D::k_minFloat) {
|
if (ratio*std::fabs(xMa-xMi) < Range1D::k_minFloat || ratio*std::fabs(yMa-yMi) < Range1D::k_minFloat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -163,7 +184,7 @@ void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float to
|
|||||||
const float xRange = xMax() - xMin();
|
const float xRange = xMax() - xMin();
|
||||||
const float leftMargin = leftMarginRatio * xRange;
|
const float leftMargin = leftMarginRatio * xRange;
|
||||||
if (x < xMin() + leftMargin) {
|
if (x < xMin() + leftMargin) {
|
||||||
m_zoomAuto = false;
|
setZoomAuto(false);
|
||||||
/* The panning increment is a whole number of pixels so that the caching
|
/* The panning increment is a whole number of pixels so that the caching
|
||||||
* for cartesian functions is not invalidated. */
|
* for cartesian functions is not invalidated. */
|
||||||
const float newXMin = std::floor((x - leftMargin - xMin()) / pixelWidth) * pixelWidth + xMin();
|
const float newXMin = std::floor((x - leftMargin - xMin()) / pixelWidth) * pixelWidth + xMin();
|
||||||
@@ -172,7 +193,7 @@ void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float to
|
|||||||
}
|
}
|
||||||
const float rightMargin = rightMarginRatio * xRange;
|
const float rightMargin = rightMarginRatio * xRange;
|
||||||
if (x > xMax() - rightMargin) {
|
if (x > xMax() - rightMargin) {
|
||||||
m_zoomAuto = false;
|
setZoomAuto(false);
|
||||||
const float newXMax = std::ceil((x + rightMargin - xMax()) / pixelWidth) * pixelWidth + xMax();
|
const float newXMax = std::ceil((x + rightMargin - xMax()) / pixelWidth) * pixelWidth + xMax();
|
||||||
m_xRange.setMax(newXMax, k_lowerMaxFloat, k_upperMaxFloat);
|
m_xRange.setMax(newXMax, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
MemoizedCurveViewRange::protectedSetXMin(xMax() - xRange, k_lowerMaxFloat, k_upperMaxFloat);
|
MemoizedCurveViewRange::protectedSetXMin(xMax() - xRange, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
@@ -182,14 +203,14 @@ void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float to
|
|||||||
const float yRange = yMax() - yMin();
|
const float yRange = yMax() - yMin();
|
||||||
const float bottomMargin = bottomMarginRatio * yRange;
|
const float bottomMargin = bottomMarginRatio * yRange;
|
||||||
if (y < yMin() + bottomMargin) {
|
if (y < yMin() + bottomMargin) {
|
||||||
m_zoomAuto = false;
|
setZoomAuto(false);
|
||||||
const float newYMin = y - bottomMargin;
|
const float newYMin = y - bottomMargin;
|
||||||
m_yRange.setMax(newYMin + yRange, k_lowerMaxFloat, k_upperMaxFloat);
|
m_yRange.setMax(newYMin + yRange, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
MemoizedCurveViewRange::protectedSetYMin(newYMin, k_lowerMaxFloat, k_upperMaxFloat);
|
MemoizedCurveViewRange::protectedSetYMin(newYMin, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
}
|
}
|
||||||
const float topMargin = topMarginRatio * yRange;
|
const float topMargin = topMarginRatio * yRange;
|
||||||
if (y > yMax() - topMargin) {
|
if (y > yMax() - topMargin) {
|
||||||
m_zoomAuto = false;
|
setZoomAuto(false);
|
||||||
m_yRange.setMax(y + topMargin, k_lowerMaxFloat, k_upperMaxFloat);
|
m_yRange.setMax(y + topMargin, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
MemoizedCurveViewRange::protectedSetYMin(yMax() - yRange, k_lowerMaxFloat, k_upperMaxFloat);
|
MemoizedCurveViewRange::protectedSetYMin(yMax() - yRange, k_lowerMaxFloat, k_upperMaxFloat);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,25 @@ class InteractiveCurveViewRange : public MemoizedCurveViewRange {
|
|||||||
public:
|
public:
|
||||||
InteractiveCurveViewRange(InteractiveCurveViewRangeDelegate * delegate = nullptr) :
|
InteractiveCurveViewRange(InteractiveCurveViewRangeDelegate * delegate = nullptr) :
|
||||||
MemoizedCurveViewRange(),
|
MemoizedCurveViewRange(),
|
||||||
m_delegate(delegate),
|
m_delegate(nullptr),
|
||||||
m_zoomAuto(true),
|
m_zoomAuto(true),
|
||||||
m_zoomNormalize(false)
|
m_zoomNormalize(false)
|
||||||
{}
|
{
|
||||||
|
if (delegate) {
|
||||||
|
setDelegate(delegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr float NormalYXRatio() { return NormalizedYHalfRange(1.f) / NormalizedXHalfRange(1.f); }
|
static constexpr float NormalYXRatio() { return NormalizedYHalfRange(1.f) / NormalizedXHalfRange(1.f); }
|
||||||
bool isOrthonormal(float tolerance = 2 * FLT_EPSILON) const;
|
bool isOrthonormal(float tolerance = 2 * FLT_EPSILON) const;
|
||||||
|
|
||||||
void setDelegate(InteractiveCurveViewRangeDelegate * delegate) { m_delegate = delegate; }
|
void setDelegate(InteractiveCurveViewRangeDelegate * delegate);
|
||||||
uint32_t rangeChecksum() override;
|
uint32_t rangeChecksum() override;
|
||||||
|
|
||||||
bool zoomAuto() const { return m_zoomAuto; }
|
bool zoomAuto() const { return m_zoomAuto; }
|
||||||
void setZoomAuto(bool v) { m_zoomAuto = v; }
|
void setZoomAuto(bool v);
|
||||||
bool zoomNormalize() const { return m_zoomNormalize; }
|
bool zoomNormalize() const { return m_zoomNormalize; }
|
||||||
void setZoomNormalize(bool v) { m_zoomNormalize = v; }
|
void setZoomNormalize(bool v);
|
||||||
|
|
||||||
// MemoizedCurveViewRange
|
// MemoizedCurveViewRange
|
||||||
float xGridUnit() const override { return m_zoomNormalize ? yGridUnit() : MemoizedCurveViewRange::xGridUnit(); }
|
float xGridUnit() const override { return m_zoomNormalize ? yGridUnit() : MemoizedCurveViewRange::xGridUnit(); }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public:
|
|||||||
virtual bool defaultRangeIsNormalized() const { return false; }
|
virtual bool defaultRangeIsNormalized() const { return false; }
|
||||||
virtual void interestingRanges(InteractiveCurveViewRange * range) const { assert(false); }
|
virtual void interestingRanges(InteractiveCurveViewRange * range) const { assert(false); }
|
||||||
virtual float addMargin(float x, float range, bool isVertical, bool isMin) = 0;
|
virtual float addMargin(float x, float range, bool isVertical, bool isMin) = 0;
|
||||||
|
virtual void updateZoomButtons() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ escher_src += $(addprefix escher/src/,\
|
|||||||
bordered.cpp \
|
bordered.cpp \
|
||||||
buffer_text_view.cpp \
|
buffer_text_view.cpp \
|
||||||
button.cpp \
|
button.cpp \
|
||||||
|
button_state.cpp \
|
||||||
button_row_controller.cpp \
|
button_row_controller.cpp \
|
||||||
chevron_view.cpp \
|
chevron_view.cpp \
|
||||||
clipboard.cpp \
|
clipboard.cpp \
|
||||||
@@ -81,6 +82,8 @@ escher_src += $(addprefix escher/src/,\
|
|||||||
text_view.cpp \
|
text_view.cpp \
|
||||||
tiled_view.cpp \
|
tiled_view.cpp \
|
||||||
timer.cpp \
|
timer.cpp \
|
||||||
|
toggleable_dot_view.cpp \
|
||||||
|
toggleable_view.cpp \
|
||||||
toolbox.cpp \
|
toolbox.cpp \
|
||||||
transparent_view.cpp \
|
transparent_view.cpp \
|
||||||
view.cpp \
|
view.cpp \
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ public:
|
|||||||
KDSize minimalSizeForOptimalDisplay() const override;
|
KDSize minimalSizeForOptimalDisplay() const override;
|
||||||
protected:
|
protected:
|
||||||
MessageTextView m_messageTextView;
|
MessageTextView m_messageTextView;
|
||||||
|
void layoutSubviews(bool force = false) override;
|
||||||
private:
|
private:
|
||||||
constexpr static KDCoordinate k_verticalMargin = 5;
|
constexpr static KDCoordinate k_verticalMargin = 5;
|
||||||
constexpr static KDCoordinate k_horizontalMarginSmall = 10;
|
constexpr static KDCoordinate k_horizontalMarginSmall = 10;
|
||||||
constexpr static KDCoordinate k_horizontalMarginLarge = 20;
|
constexpr static KDCoordinate k_horizontalMarginLarge = 20;
|
||||||
int numberOfSubviews() const override;
|
int numberOfSubviews() const override;
|
||||||
View * subviewAtIndex(int index) override;
|
View * subviewAtIndex(int index) override;
|
||||||
void layoutSubviews(bool force = false) override;
|
|
||||||
Invocation m_invocation;
|
Invocation m_invocation;
|
||||||
const KDFont * m_font;
|
const KDFont * m_font;
|
||||||
};
|
};
|
||||||
|
|||||||
24
escher/include/escher/button_state.h
Normal file
24
escher/include/escher/button_state.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef ESCHER_BUTTON_STATE_H
|
||||||
|
#define ESCHER_BUTTON_STATE_H
|
||||||
|
|
||||||
|
#include <escher/button.h>
|
||||||
|
#include <escher/toggleable_dot_view.h>
|
||||||
|
|
||||||
|
class ButtonState : public Button {
|
||||||
|
public:
|
||||||
|
using Button::Button;
|
||||||
|
void setState(bool state) { m_stateView.setState(state); }
|
||||||
|
KDSize minimalSizeForOptimalDisplay() const override;
|
||||||
|
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||||
|
private:
|
||||||
|
// Dot right margin.
|
||||||
|
constexpr static KDCoordinate k_stateMargin = 9;
|
||||||
|
// Dot vertical position offset.
|
||||||
|
constexpr static KDCoordinate k_verticalOffset = 5;
|
||||||
|
int numberOfSubviews() const override { return 2; }
|
||||||
|
View * subviewAtIndex(int index) override;
|
||||||
|
void layoutSubviews(bool force = false) override;
|
||||||
|
ToggleableDotView m_stateView;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
#ifndef ESCHER_SWITCH_VIEW_H
|
#ifndef ESCHER_SWITCH_VIEW_H
|
||||||
#define ESCHER_SWITCH_VIEW_H
|
#define ESCHER_SWITCH_VIEW_H
|
||||||
|
|
||||||
#include <escher/transparent_view.h>
|
#include <escher/toggleable_view.h>
|
||||||
|
#include <escher/palette.h>
|
||||||
|
|
||||||
class SwitchView : public TransparentView {
|
|
||||||
|
class SwitchView final : public ToggleableView {
|
||||||
public:
|
public:
|
||||||
SwitchView();
|
using ToggleableView::ToggleableView;
|
||||||
bool state();
|
|
||||||
void setState(bool state);
|
|
||||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
|
||||||
KDSize minimalSizeForOptimalDisplay() const override;
|
|
||||||
/* k_switchHeight and k_switchWidth are the dimensions of the switch
|
/* k_switchHeight and k_switchWidth are the dimensions of the switch
|
||||||
* (including the outline of the switch). */
|
* (including the outline of the switch). */
|
||||||
constexpr static KDCoordinate k_onOffSize = 12;
|
constexpr static KDCoordinate k_onOffSize = 12;
|
||||||
constexpr static KDCoordinate k_switchHeight = 12;
|
constexpr static KDCoordinate k_switchHeight = 12;
|
||||||
constexpr static KDCoordinate k_switchWidth = 22;
|
constexpr static KDCoordinate k_switchWidth = 22;
|
||||||
|
KDSize minimalSizeForOptimalDisplay() const override { return KDSize(k_switchWidth, k_switchHeight); }
|
||||||
private:
|
private:
|
||||||
bool m_state;
|
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
16
escher/include/escher/toggleable_dot_view.h
Normal file
16
escher/include/escher/toggleable_dot_view.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ESCHER_TOGGLEABLE_DOT_VIEW_H
|
||||||
|
#define ESCHER_TOGGLEABLE_DOT_VIEW_H
|
||||||
|
|
||||||
|
#include <escher/toggleable_view.h>
|
||||||
|
|
||||||
|
class ToggleableDotView final : public ToggleableView {
|
||||||
|
public:
|
||||||
|
using ToggleableView::ToggleableView;
|
||||||
|
/* k_dotSize is the dimensions of the toggle dot */
|
||||||
|
constexpr static KDCoordinate k_dotSize = 8;
|
||||||
|
KDSize minimalSizeForOptimalDisplay() const override { return KDSize(k_dotSize, k_dotSize); }
|
||||||
|
private:
|
||||||
|
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
15
escher/include/escher/toggleable_view.h
Normal file
15
escher/include/escher/toggleable_view.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef ESCHER_TOGGLEABLE_VIEW_H
|
||||||
|
#define ESCHER_TOGGLEABLE_VIEW_H
|
||||||
|
|
||||||
|
#include <escher/transparent_view.h>
|
||||||
|
|
||||||
|
class ToggleableView : public TransparentView {
|
||||||
|
public:
|
||||||
|
ToggleableView() : m_state(true) {}
|
||||||
|
bool state() { return m_state; }
|
||||||
|
void setState(bool state);
|
||||||
|
protected:
|
||||||
|
bool m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
35
escher/src/button_state.cpp
Normal file
35
escher/src/button_state.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include <escher/button_state.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
View * ButtonState::subviewAtIndex(int index) {
|
||||||
|
assert(index >= 0 && index < 2);
|
||||||
|
if (index == 0) {
|
||||||
|
return &m_messageTextView;
|
||||||
|
}
|
||||||
|
return &m_stateView;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonState::layoutSubviews(bool force) {
|
||||||
|
KDSize textSize = Button::minimalSizeForOptimalDisplay();
|
||||||
|
KDRect textRect = KDRect(0, 0, textSize.width(), bounds().height());
|
||||||
|
// State view will be vertically centered and aligned on the left
|
||||||
|
KDSize stateSize = m_stateView.minimalSizeForOptimalDisplay();
|
||||||
|
KDRect stateRect = KDRect(textSize.width(), k_verticalOffset, stateSize.width(), stateSize.height());
|
||||||
|
|
||||||
|
m_messageTextView.setFrame(textRect, force);
|
||||||
|
m_stateView.setFrame(stateRect, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonState::drawRect(KDContext * ctx, KDRect rect) const {
|
||||||
|
KDColor backColor = isHighlighted() ? highlightedBackgroundColor() : KDColorWhite;
|
||||||
|
ctx->fillRect(bounds(), backColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
KDSize ButtonState::minimalSizeForOptimalDisplay() const {
|
||||||
|
KDSize textSize = Button::minimalSizeForOptimalDisplay();
|
||||||
|
KDSize stateSize = m_stateView.minimalSizeForOptimalDisplay();
|
||||||
|
return KDSize(
|
||||||
|
textSize.width() + stateSize.width() + k_stateMargin,
|
||||||
|
std::max(textSize.height(), stateSize.height()));
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <escher/switch_view.h>
|
#include <escher/switch_view.h>
|
||||||
#include <escher/palette.h>
|
|
||||||
|
|
||||||
const uint8_t switchMask[SwitchView::k_switchHeight][SwitchView::k_switchWidth] = {
|
const uint8_t switchMask[SwitchView::k_switchHeight][SwitchView::k_switchWidth] = {
|
||||||
{0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF},
|
{0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF},
|
||||||
@@ -32,37 +31,28 @@ const uint8_t onOffMask[SwitchView::k_onOffSize][SwitchView::k_onOffSize] = {
|
|||||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||||
};
|
};
|
||||||
|
|
||||||
SwitchView::SwitchView() :
|
|
||||||
m_state(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SwitchView::state() {
|
|
||||||
return m_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchView::setState(bool state) {
|
|
||||||
m_state = state;
|
|
||||||
markRectAsDirty(bounds());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchView::drawRect(KDContext * ctx, KDRect rect) const {
|
void SwitchView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||||
/* Draw the switch aligned on the right of the view and vertically centered.
|
/* Draw the view aligned on the right of the view and vertically centered
|
||||||
* The heightCenter is the coordinate of the vertical middle of the view. That
|
* The heightCenter is the coordinate of the vertical middle of the view. That
|
||||||
* way, (heightCenter-switchHalfHeight) indicates the top the switch. */
|
* way, (heightCenter-halfHeight) indicates the top of the StateView. */
|
||||||
KDCoordinate width = bounds().width();
|
KDCoordinate width = bounds().width();
|
||||||
KDCoordinate heightCenter = bounds().height()/2;
|
KDCoordinate heightCenter = bounds().height() / 2;
|
||||||
KDCoordinate switchHalfHeight = k_switchHeight/2;
|
KDCoordinate halfHeight = k_switchHeight / 2;
|
||||||
KDColor switchWorkingBuffer[SwitchView::k_switchWidth*SwitchView::k_switchHeight];
|
KDColor workingBuffer[k_switchWidth * k_switchHeight];
|
||||||
|
|
||||||
|
KDRect frame(width - k_switchWidth, heightCenter - halfHeight, k_switchWidth, k_switchHeight);
|
||||||
|
ctx->blendRectWithMask(
|
||||||
|
frame,
|
||||||
|
m_state ? Palette::YellowDark : Palette::GrayDark,
|
||||||
|
reinterpret_cast<const uint8_t *>(switchMask),
|
||||||
|
workingBuffer);
|
||||||
|
|
||||||
|
|
||||||
KDColor mainColor = m_state ? Palette::YellowDark : Palette::GrayDark;
|
|
||||||
KDRect frame(width - k_switchWidth, heightCenter -switchHalfHeight, k_switchWidth, k_switchHeight);
|
|
||||||
ctx->blendRectWithMask(frame, mainColor, (const uint8_t *)switchMask, switchWorkingBuffer);
|
|
||||||
KDCoordinate onOffX = width - (m_state ? k_onOffSize : k_switchWidth);
|
KDCoordinate onOffX = width - (m_state ? k_onOffSize : k_switchWidth);
|
||||||
KDRect onOffFrame(onOffX, heightCenter -switchHalfHeight, k_onOffSize, k_onOffSize);
|
KDRect onOffFrame(onOffX, heightCenter - halfHeight, k_onOffSize, k_onOffSize);
|
||||||
ctx->blendRectWithMask(onOffFrame, KDColorWhite, (const uint8_t *)onOffMask, switchWorkingBuffer);
|
ctx->blendRectWithMask(
|
||||||
}
|
onOffFrame,
|
||||||
|
KDColorWhite,
|
||||||
KDSize SwitchView::minimalSizeForOptimalDisplay() const {
|
reinterpret_cast<const uint8_t *>(onOffMask),
|
||||||
return KDSize(k_switchWidth, k_switchHeight);
|
workingBuffer);
|
||||||
}
|
}
|
||||||
41
escher/src/toggleable_dot_view.cpp
Normal file
41
escher/src/toggleable_dot_view.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <escher/toggleable_dot_view.h>
|
||||||
|
#include <escher/palette.h>
|
||||||
|
|
||||||
|
const uint8_t MediumDotMask[ToggleableDotView::k_dotSize][ToggleableDotView::k_dotSize] = {
|
||||||
|
{0xFF, 0xDB, 0x53, 0x0F, 0x0F, 0x53, 0xDB, 0xFF},
|
||||||
|
{0xD8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD8},
|
||||||
|
{0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53},
|
||||||
|
{0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C},
|
||||||
|
{0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C},
|
||||||
|
{0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53},
|
||||||
|
{0xD7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD7},
|
||||||
|
{0xFF, 0xD8, 0x53, 0x0C, 0x0C, 0x53, 0xD8, 0xFF},
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t MediumShallowDotMask[ToggleableDotView::k_dotSize][ToggleableDotView::k_dotSize] = {
|
||||||
|
{0xFF, 0xDB, 0x53, 0x0F, 0x0F, 0x53, 0xDB, 0xFF},
|
||||||
|
{0xD8, 0x17, 0x90, 0xEC, 0xEC, 0x90, 0x17, 0xD8},
|
||||||
|
{0x53, 0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x53},
|
||||||
|
{0x0F, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0x0C},
|
||||||
|
{0x0F, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0x0C},
|
||||||
|
{0x53, 0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x53},
|
||||||
|
{0xD7, 0x17, 0x90, 0xEF, 0xEF, 0x90, 0x17, 0xD7},
|
||||||
|
{0xFF, 0xD8, 0x53, 0x0C, 0x0C, 0x53, 0xD8, 0xFF},
|
||||||
|
};
|
||||||
|
|
||||||
|
void ToggleableDotView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||||
|
/* Draw the view aligned on the right of the view and vertically centered
|
||||||
|
* The heightCenter is the coordinate of the vertical middle of the view. That
|
||||||
|
* way, (heightCenter-halfHeight) indicates the top of the StateView. */
|
||||||
|
KDCoordinate width = bounds().width();
|
||||||
|
KDCoordinate heightCenter = bounds().height() / 2;
|
||||||
|
KDCoordinate halfHeight = k_dotSize / 2;
|
||||||
|
KDColor workingBuffer[k_dotSize * k_dotSize];
|
||||||
|
|
||||||
|
KDRect frame(width - k_dotSize, heightCenter - halfHeight, k_dotSize, k_dotSize);
|
||||||
|
ctx->blendRectWithMask(
|
||||||
|
frame,
|
||||||
|
m_state ? Palette::YellowDark : Palette::GrayDark,
|
||||||
|
m_state ? reinterpret_cast<const uint8_t *>(MediumDotMask) : reinterpret_cast<const uint8_t *>(MediumShallowDotMask),
|
||||||
|
workingBuffer);
|
||||||
|
}
|
||||||
6
escher/src/toggleable_view.cpp
Normal file
6
escher/src/toggleable_view.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <escher/toggleable_view.h>
|
||||||
|
|
||||||
|
void ToggleableView::setState(bool state) {
|
||||||
|
m_state = state;
|
||||||
|
markRectAsDirty(bounds());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user