Update text rendering.
This commit is contained in:
parent
8536908eab
commit
8130308f7f
27 changed files with 503 additions and 77 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
struct Bounds
|
||||
{
|
||||
Bounds(double minX, double maxX, double minY, double maxY, double minZ = 0.0, double maxZ = 0.0)
|
||||
Bounds(double minX = 0.0, double maxX = 0.0, double minY = 0.0, double maxY = 0.0, double minZ = 0.0, double maxZ = 0.0)
|
||||
: mMinX(minX),
|
||||
mMaxX(maxX),
|
||||
mMinY(minY),
|
||||
|
@ -60,4 +60,21 @@ struct Bounds
|
|||
mMaxZ = z;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Bounds& rhs) const
|
||||
{
|
||||
return (mMinX == rhs.mMinX)
|
||||
&& (mMaxX == rhs.mMaxX)
|
||||
|
||||
&& (mMinY == rhs.mMinY)
|
||||
&& (mMaxY == rhs.mMaxY)
|
||||
|
||||
&& (mMinZ == rhs.mMinZ)
|
||||
&& (mMaxZ == rhs.mMaxZ);
|
||||
}
|
||||
|
||||
bool operator!=(const Bounds& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
|
@ -31,6 +31,21 @@ public:
|
|||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
bool hasDefaultLocation() const
|
||||
{
|
||||
return mLocation.getX() == 0.0 && mLocation.getY() == 0.0 && mLocation.getZ() == 0.0;
|
||||
}
|
||||
|
||||
bool hasDefaultScale() const
|
||||
{
|
||||
return mScaleX == 1.0 && mScaleY == 1.0 && mScaleZ == 1.0;
|
||||
}
|
||||
|
||||
bool isDefaultTransform() const
|
||||
{
|
||||
return hasDefaultLocation() && hasDefaultScale();
|
||||
}
|
||||
|
||||
private:
|
||||
Point mLocation;
|
||||
double mScaleX{1};
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
#include "AbstractFace.h"
|
||||
|
||||
#include "Circle.h"
|
||||
#include "Rectangle.h"
|
||||
|
||||
#include "SvgShapeElements.h"
|
||||
#include "SvgTextElement.h"
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
std::unique_ptr<SvgDocument> SvgPainter::paint(Scene* scene, double width, double height) const
|
||||
|
@ -102,22 +104,33 @@ void SvgPainter::setStyle(SceneModel* model, SvgShapeElement* element) const
|
|||
if (model->hasOutlineColor())
|
||||
{
|
||||
element->setStrokeColor(model->getOutlineColor());
|
||||
element->setStrokeWidth(model->getOutlineThickness() / transform.getScaleX());
|
||||
element->setStrokeWidth(model->getOutlineThickness());
|
||||
}
|
||||
else
|
||||
{
|
||||
element->setNoStroke();
|
||||
}
|
||||
element->addAttribute(std::move(toTransform(transform)));
|
||||
|
||||
if (!transform.isDefaultTransform())
|
||||
{
|
||||
element->addAttribute(std::move(toTransform(transform)));
|
||||
}
|
||||
}
|
||||
|
||||
void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
|
||||
{
|
||||
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
|
||||
{
|
||||
auto model_rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry());
|
||||
|
||||
auto rect = std::make_unique<SvgRectangle>();
|
||||
rect->setWidth(1.0);
|
||||
rect->setHeight(1.0);
|
||||
rect->setWidth(model_rect->getWidth());
|
||||
rect->setHeight(model_rect->getHeight());
|
||||
|
||||
if (model_rect->getRadius() > 0.0)
|
||||
{
|
||||
rect->setRadius(model_rect->getRadius());
|
||||
}
|
||||
|
||||
setStyle(model, rect.get());
|
||||
document->getRoot()->addChild(std::move(rect));
|
||||
|
@ -139,9 +152,17 @@ void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
|
|||
}
|
||||
}
|
||||
|
||||
void SvgPainter::paintText(SvgDocument* document, SceneText* model) const
|
||||
void SvgPainter::paintText(SvgDocument* document, SceneText* text) const
|
||||
{
|
||||
auto svg_text = std::make_unique<SvgTextElement>();
|
||||
svg_text->setContent(text->getTextData().mContent);
|
||||
svg_text->setLocation(text->getTransform().getLocation());
|
||||
|
||||
svg_text->setFontFamily(text->getTextData().mFont.getFaceName());
|
||||
svg_text->setFill(text->getFillColor());
|
||||
svg_text->setFontSize(text->getTextData().mFont.getSize());
|
||||
|
||||
document->getRoot()->addChild(std::move(svg_text));
|
||||
}
|
||||
|
||||
std::unique_ptr<XmlAttribute> SvgPainter::toTransform(const Transform& transform) const
|
||||
|
@ -149,8 +170,14 @@ std::unique_ptr<XmlAttribute> SvgPainter::toTransform(const Transform& transform
|
|||
auto svg_transform = std::make_unique<XmlAttribute>("transform");
|
||||
|
||||
std::string ops;
|
||||
ops += "translate(" + std::to_string(transform.getLocation().getX()) + " " + std::to_string(transform.getLocation().getY()) + ") ";
|
||||
ops += "scale(" + std::to_string(transform.getScaleX()) + " " + std::to_string(transform.getScaleY()) + ") ";
|
||||
if (!transform.hasDefaultLocation())
|
||||
{
|
||||
ops += "translate(" + std::to_string(transform.getLocation().getX()) + " " + std::to_string(transform.getLocation().getY()) + ") ";
|
||||
}
|
||||
if (!transform.hasDefaultScale())
|
||||
{
|
||||
ops += "scale(" + std::to_string(transform.getScaleX()) + " " + std::to_string(transform.getScaleY()) + ") ";
|
||||
}
|
||||
svg_transform->setValue(ops);
|
||||
|
||||
return std::move(svg_transform);
|
||||
|
|
|
@ -34,22 +34,46 @@ void DirectX2dPainter::paint(SceneModel* model)
|
|||
|
||||
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
|
||||
{
|
||||
auto rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry());
|
||||
|
||||
const auto loc = model->getTransform().getLocation();
|
||||
const auto scale_x = model->getTransform().getScaleX();
|
||||
const auto scale_y = model->getTransform().getScaleY();
|
||||
D2D1_RECT_F d2d_rect{ static_cast<float>(loc.getX()), static_cast<float>(loc.getY() + scale_y), static_cast<float>(loc.getX() + scale_x), static_cast<float>(loc.getY()) };
|
||||
|
||||
if (model->hasFillColor())
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
|
||||
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
|
||||
const auto min_x = static_cast<float>(loc.getX());
|
||||
const auto max_x = static_cast<float>(loc.getX() + rect->getWidth()* scale_x);
|
||||
|
||||
const auto min_y = static_cast<float>(loc.getY());
|
||||
const auto max_y = static_cast<float>(loc.getY() + rect->getHeight() * scale_y);
|
||||
|
||||
D2D1_RECT_F d2d_rect{ min_x, max_y, max_x, min_y };
|
||||
if (rect->getRadius() == 0.0)
|
||||
{
|
||||
if (model->hasFillColor())
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
|
||||
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
|
||||
}
|
||||
if (model->hasOutlineColor())
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
|
||||
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (model->hasOutlineColor())
|
||||
else
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
|
||||
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
|
||||
}
|
||||
D2D1_ROUNDED_RECT rounded_rect{ d2d_rect , static_cast<float>(rect->getRadius()), static_cast<float>(rect->getRadius()) };
|
||||
if (model->hasFillColor())
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
|
||||
rt->FillRoundedRectangle(rounded_rect, mSolidBrush.Get());
|
||||
}
|
||||
if (model->hasOutlineColor())
|
||||
{
|
||||
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
|
||||
rt->DrawRoundedRectangle(rounded_rect, mSolidBrush.Get(), 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::CIRCLE)
|
||||
{
|
||||
|
|
|
@ -30,28 +30,40 @@ void DirectXTextPainter::setD2dInterface(DirectX2dInterface* d2dIterface)
|
|||
mD2dInterface->getRenderTarget()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mTextBrush);
|
||||
}
|
||||
|
||||
void DirectXTextPainter::updateTextFormat(const FontItem& font)
|
||||
void DirectXTextPainter::updateTextFormat(SceneText* text)
|
||||
{
|
||||
mD2dInterface->getDirectWriteFactory()->CreateTextFormat(
|
||||
UnicodeUtils::utf8ToUtf16WString(font.getFaceName()).c_str(),
|
||||
UnicodeUtils::utf8ToUtf16WString(text->getTextData().mFont.getFaceName()).c_str(),
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT_NORMAL,
|
||||
DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
static_cast<float>(font.getSize()),
|
||||
static_cast<float>(text->getTextData().mFont.getSize()),
|
||||
L"en-us",
|
||||
&mTextFormat
|
||||
);
|
||||
//mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
|
||||
//mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
|
||||
mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
|
||||
mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
|
||||
|
||||
mTextBrush->SetColor(toD2dColor(text->getFillColor()));
|
||||
}
|
||||
|
||||
D2D1::ColorF DirectXTextPainter::toD2dColor(const Color& color)
|
||||
{
|
||||
return D2D1::ColorF(static_cast<float>(color.getR() / 255.0), static_cast<float>(color.getG() / 255.0),
|
||||
static_cast<float>(color.getB() / 255.0), static_cast<float>(color.getAlpha()));
|
||||
}
|
||||
|
||||
void DirectXTextPainter::paint(SceneText* text, DrawingContext* context)
|
||||
{
|
||||
const auto location = text->getTransform().getLocation();
|
||||
D2D1_RECT_F textRect = D2D1::RectF(static_cast<float>(location.getX()), static_cast<float>(location.getY()), static_cast<float>(location.getX() + 200), static_cast<float>(location.getY() + 100));
|
||||
|
||||
updateTextFormat(text->getTextData().mFont);
|
||||
const auto width = static_cast<float>(text->getTextWidth());
|
||||
const auto height = static_cast<float>(text->getTextHeight());
|
||||
|
||||
D2D1_RECT_F textRect = D2D1::RectF(static_cast<float>(location.getX()), static_cast<float>(location.getY()), static_cast<float>(location.getX() + width), static_cast<float>(location.getY() + height));
|
||||
|
||||
updateTextFormat(text);
|
||||
|
||||
auto content = UnicodeUtils::utf8ToUtf16WString(text->getTextData().mContent);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "FontItem.h"
|
||||
#include "Color.h"
|
||||
|
||||
#include <wrl.h>
|
||||
#include <dwrite.h>
|
||||
|
@ -32,7 +33,9 @@ public:
|
|||
void setD2dInterface(DirectX2dInterface* d2dIterface);
|
||||
|
||||
private:
|
||||
void updateTextFormat(const FontItem& font);
|
||||
void updateTextFormat(SceneText* text);
|
||||
|
||||
D2D1::ColorF toD2dColor(const Color& color);
|
||||
|
||||
DirectX2dInterface* mD2dInterface{ nullptr };
|
||||
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mTextBrush;
|
||||
|
|
|
@ -23,6 +23,8 @@ list(APPEND visual_elements_LIB_INCLUDES
|
|||
svg/SvgReader.h
|
||||
svg/SvgShapeElement.h
|
||||
svg/SvgElement.h
|
||||
svg/SvgTextElement.h
|
||||
svg/SvgTextElement.cpp
|
||||
svg/elements/SvgShapeElements.h
|
||||
svg/SvgDocument.cpp
|
||||
svg/SvgReader.cpp
|
||||
|
|
|
@ -42,7 +42,7 @@ void RectangleNode::setWidth(double width)
|
|||
{
|
||||
if (mWidth != width)
|
||||
{
|
||||
mTransformIsDirty = true;
|
||||
mGeometryIsDirty = true;
|
||||
mWidth = width;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ void RectangleNode::setHeight(double height)
|
|||
{
|
||||
if (mHeight != height)
|
||||
{
|
||||
mTransformIsDirty = true;
|
||||
mGeometryIsDirty = true;
|
||||
mHeight = height;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
|||
{
|
||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||
{
|
||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
|
||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
|
||||
rect->setRadius(mRadius);
|
||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
|||
{
|
||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||
{
|
||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
|
||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
|
||||
rect->setRadius(mRadius);
|
||||
mBackgroundItem->updateGeometry(std::move(rect));
|
||||
}
|
||||
|
@ -96,5 +96,5 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
|||
|
||||
void RectangleNode::updateTransform()
|
||||
{
|
||||
mBackgroundItem->updateTransform({ mLocation, mWidth, mHeight });
|
||||
mBackgroundItem->updateTransform({ mLocation });
|
||||
}
|
|
@ -161,7 +161,7 @@ void TextNode::update(SceneInfo* sceneInfo)
|
|||
|
||||
if (mContentIsDirty || mLinesAreDirty)
|
||||
{
|
||||
dynamic_cast<SceneText*>(mTextItem.get())->setTextData(mTextData);
|
||||
mTextItem->setTextData(mTextData);
|
||||
mContentIsDirty = false;
|
||||
mLinesAreDirty = false;
|
||||
}
|
||||
|
@ -169,6 +169,8 @@ void TextNode::update(SceneInfo* sceneInfo)
|
|||
if (mTransformIsDirty)
|
||||
{
|
||||
mTextItem->updateTransform({mLocation});
|
||||
mTextItem->setTextWidth(mWidth);
|
||||
mTextItem->setTextHeight(mHeight);
|
||||
mTransformIsDirty = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "FontItem.h"
|
||||
#include "TextData.h"
|
||||
#include "Bounds.h"
|
||||
#include "SceneText.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -47,7 +49,7 @@ private:
|
|||
double mWidth{1};
|
||||
double mHeight{1};
|
||||
|
||||
std::unique_ptr<SceneItem> mTextItem;
|
||||
std::unique_ptr<SceneText> mTextItem;
|
||||
};
|
||||
|
||||
using TextNodetr = std::unique_ptr<TextNode>;
|
||||
|
|
|
@ -23,3 +23,31 @@ void SceneText::setTextData(const TextData& data)
|
|||
mTextData = data;
|
||||
}
|
||||
}
|
||||
|
||||
double SceneText::getTextWidth() const
|
||||
{
|
||||
return mTextWidth;
|
||||
}
|
||||
|
||||
double SceneText::getTextHeight() const
|
||||
{
|
||||
return mTextHeight;
|
||||
}
|
||||
|
||||
void SceneText::setTextWidth(double width)
|
||||
{
|
||||
if (mTextWidth != width)
|
||||
{
|
||||
mTextWidth = width;
|
||||
mTextGeometryIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneText::setTextHeight(double height)
|
||||
{
|
||||
if (mTextHeight != height)
|
||||
{
|
||||
mTextHeight = height;
|
||||
mTextGeometryIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,21 @@ public:
|
|||
|
||||
Type getType() const override;
|
||||
|
||||
double getTextWidth() const;
|
||||
|
||||
double getTextHeight() const;
|
||||
|
||||
const TextData& getTextData() const;
|
||||
|
||||
void setTextWidth(double width);
|
||||
|
||||
void setTextHeight(double height);
|
||||
|
||||
void setTextData(const TextData& content);
|
||||
|
||||
private:
|
||||
bool mTextGeometryIsDirty{true};
|
||||
TextData mTextData;
|
||||
double mTextWidth{ 0.0 };
|
||||
double mTextHeight{ 0.0 };
|
||||
};
|
||||
|
|
53
src/rendering/visual_elements/svg/SvgTextElement.cpp
Normal file
53
src/rendering/visual_elements/svg/SvgTextElement.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "SvgTextElement.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgTextElement::SvgTextElement()
|
||||
:SvgElement("text")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgTextElement::setLocation(const Point& loc)
|
||||
{
|
||||
auto x = std::make_unique<XmlAttribute>("x");
|
||||
auto y = std::make_unique<XmlAttribute>("y");
|
||||
|
||||
x->setValue(std::to_string(loc.getX()));
|
||||
y->setValue(std::to_string(loc.getY()));
|
||||
|
||||
addAttribute(std::move(x));
|
||||
addAttribute(std::move(y));
|
||||
}
|
||||
|
||||
void SvgTextElement::setContent(const std::string& content)
|
||||
{
|
||||
setText(content);
|
||||
}
|
||||
|
||||
void SvgTextElement::setFill(const Color& fill)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("fill");
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "rgb(" << fill.toString() << ")";
|
||||
attr->setValue(sstr.str());
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgTextElement::setFontFamily(const std::string& family)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("font-family");
|
||||
attr->setValue(family);
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgTextElement::setFontSize(float size)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("font-size");
|
||||
attr->setValue(std::to_string(size));
|
||||
addAttribute(std::move(attr));
|
||||
}
|
21
src/rendering/visual_elements/svg/SvgTextElement.h
Normal file
21
src/rendering/visual_elements/svg/SvgTextElement.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgElement.h"
|
||||
#include "Point.h"
|
||||
#include "Color.h"
|
||||
|
||||
class SvgTextElement : public SvgElement
|
||||
{
|
||||
public:
|
||||
SvgTextElement();
|
||||
|
||||
void setLocation(const Point& loc);
|
||||
|
||||
void setContent(const std::string& content);
|
||||
|
||||
void setFill(const Color& fill);
|
||||
|
||||
void setFontFamily(const std::string& family);
|
||||
|
||||
void setFontSize(float size);
|
||||
};
|
|
@ -124,6 +124,15 @@ void SvgRectangle::setHeight(double h)
|
|||
addAttribute(std::move(height));
|
||||
}
|
||||
|
||||
void SvgRectangle::setRadius(double radius)
|
||||
{
|
||||
auto rx = std::make_unique<XmlAttribute>("rx");
|
||||
|
||||
rx->setValue(std::to_string(radius));
|
||||
|
||||
addAttribute(std::move(rx));
|
||||
}
|
||||
|
||||
|
||||
SvgPolygon::SvgPolygon()
|
||||
: SvgShapeElement("polygon")
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
void setWidth(double width);
|
||||
|
||||
void setHeight(double height);
|
||||
|
||||
void setRadius(double radius);
|
||||
};
|
||||
|
||||
class SvgPolygon : public SvgShapeElement
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "ThemeManager.h"
|
||||
#include "PaintEvent.h"
|
||||
|
||||
#include "FontTokens.h"
|
||||
|
||||
#include "MouseEvent.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
|
@ -16,6 +18,10 @@ Button::Button(ButtonData::Component component)
|
|||
{
|
||||
mStyle.mComponent = component;
|
||||
mName = "Button";
|
||||
|
||||
setHeight(mStyle.getContainerHeight());
|
||||
setMaxHeight(mStyle.getContainerHeight());
|
||||
setRadius(mStyle.getContainerCornerRadius());
|
||||
}
|
||||
|
||||
Button::~Button()
|
||||
|
@ -66,7 +72,39 @@ void Button::setEnabled(bool isEnabled)
|
|||
void Button::updateState()
|
||||
{
|
||||
setBackground(mStyle.getContainerColor());
|
||||
setBackgroundTone(mStyle.getContainerSurfaceTintColor());
|
||||
setElevation(mStyle.getContainerElevation());
|
||||
|
||||
setLabelTextColor(mStyle.getLabelTextColor());
|
||||
setLabelTextOpacity(mStyle.getLabelOpacity());
|
||||
setLabelTextTypescale(mStyle.getLabelTypescale());
|
||||
}
|
||||
|
||||
void Button::setLabelTextColor(Theme::Sys::Color color)
|
||||
{
|
||||
if (mLabelTextColor != color)
|
||||
{
|
||||
mLabelTextColor = color;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setLabelTextOpacity(float opacity)
|
||||
{
|
||||
if (mLabelOpacity != opacity)
|
||||
{
|
||||
mLabelOpacity = opacity;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setLabelTextTypescale(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
if (mLabelTextTypescale != typescale)
|
||||
{
|
||||
mLabelTextTypescale = typescale;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::onMyMouseEvent(const MouseEvent* event)
|
||||
|
@ -131,29 +169,31 @@ void Button::doPaint(const PaintEvent* event)
|
|||
|
||||
void Button::updateLabel(const PaintEvent* event)
|
||||
{
|
||||
unsigned fontOffset = unsigned(mLabel.size()) * 4;
|
||||
auto middle = DiscretePoint(mLocation.getX() + mSize.mWidth/2 - fontOffset, mLocation.getY() + mSize.mHeight/2 + 4);
|
||||
|
||||
if (!mTextNode)
|
||||
{
|
||||
mTextNode = TextNode::Create(mLabel, middle);
|
||||
mTextNode = TextNode::Create(mLabel, mLocation);
|
||||
mTextNode->setName(mName + "_TextNode");
|
||||
mTextNode->setContent(mLabel);
|
||||
mTextNode->setWidth(mSize.mWidth);
|
||||
mTextNode->setHeight(mSize.mHeight);
|
||||
mRootNode->addChild(mTextNode.get());
|
||||
}
|
||||
|
||||
if (mTransformDirty)
|
||||
{
|
||||
mTextNode->setLocation(middle);
|
||||
mTextNode->setLocation(mLocation);
|
||||
mTextNode->setWidth(mSize.mWidth);
|
||||
mTextNode->setHeight(mSize.mHeight);
|
||||
}
|
||||
|
||||
if (mMaterialDirty)
|
||||
{
|
||||
mTextNode->setFillColor(event->getThemesManager()->getColor(mBackground));
|
||||
auto fill_color = event->getThemesManager()->getColor(mLabelTextColor);
|
||||
fill_color.setAlpha(mLabelOpacity);
|
||||
mTextNode->setFillColor(fill_color);
|
||||
|
||||
auto size = FontTokens::getSize(mLabelTextTypescale);
|
||||
auto family = FontTokens::getFont(FontTokens::getFont(mLabelTextTypescale));
|
||||
auto font_data = FontItem(family, static_cast<float>(size));
|
||||
mTextNode->setFont(font_data);
|
||||
}
|
||||
|
||||
if (mContentDirty)
|
||||
|
|
|
@ -34,6 +34,10 @@ protected:
|
|||
bool isDirty() const override;
|
||||
void doPaint(const PaintEvent* event) override;
|
||||
|
||||
void setLabelTextColor(Theme::Sys::Color color);
|
||||
void setLabelTextOpacity(float opacity);
|
||||
void setLabelTextTypescale(Theme::Sys::Typescale typescale);
|
||||
|
||||
void updateLabel(const PaintEvent* event);
|
||||
|
||||
void setState(ButtonData::State state);
|
||||
|
@ -44,6 +48,10 @@ private:
|
|||
ButtonData mStyle;
|
||||
|
||||
std::string mLabel;
|
||||
Theme::Sys::Color mLabelTextColor;
|
||||
Theme::Sys::Typescale mLabelTextTypescale;
|
||||
float mLabelOpacity{ 1.0 };
|
||||
|
||||
clickFunc mClickFunc;
|
||||
|
||||
std::unique_ptr<TextNode> mTextNode;
|
||||
|
|
|
@ -218,6 +218,29 @@ float ButtonData::getStateLayerOverlayOpacity() const
|
|||
}
|
||||
}
|
||||
|
||||
float ButtonData::getLabelOpacity() const
|
||||
{
|
||||
if (auto iter = mLabelTextOpacity.find(std::make_pair(mComponent, mState)); iter != mLabelTextOpacity.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mState == State::Enabled)
|
||||
{
|
||||
return DEFAULT_CONTAINER_OPACITY;
|
||||
}
|
||||
else if (auto iter = mLabelTextOpacity.find(std::make_pair(mComponent, State::Enabled)); iter != mLabelTextOpacity.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEFAULT_CONTAINER_OPACITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Theme::Sys::Typescale ButtonData::getLabelTypescale() const
|
||||
{
|
||||
switch (mComponent)
|
||||
|
|
|
@ -40,20 +40,21 @@ public:
|
|||
Theme::Sys::Color getContainerShadowColor() const;
|
||||
Theme::Sys::Color getContainerSurfaceTintColor() const;
|
||||
Theme::Sys::Elevation getContainerElevation() const;
|
||||
float getStateLayerOverlayOpacity() const;
|
||||
|
||||
Theme::Sys::Color getLabelTextColor() const;
|
||||
Theme::Sys::Typescale getLabelTypescale() const;
|
||||
float getLabelOpacity() const;
|
||||
|
||||
bool canHaveIcon() const;
|
||||
Theme::Sys::Color getIconColor() const;
|
||||
|
||||
float getStateLayerOverlayOpacity() const;
|
||||
unsigned getContainerHeight() const;
|
||||
unsigned getContainerCornerRadius() const;
|
||||
|
||||
unsigned getIconSize() const;
|
||||
unsigned getLeftRightPadding() const;
|
||||
|
||||
unsigned getLeftRightPadding() const;
|
||||
unsigned getLeftPaddingWithIcon() const;
|
||||
unsigned getRightPaddingWithIcon() const;
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
#include "FontTokens.h"
|
||||
|
||||
|
||||
|
||||
std::string FontTokens::getFont(Theme::Ref::Typeface::Font font)
|
||||
{
|
||||
switch (font)
|
||||
{
|
||||
case Theme::Ref::Typeface::Font::Brand:
|
||||
return "Segoe UI";
|
||||
case Theme::Ref::Typeface::Font::Plain:
|
||||
return "Segoe UI";
|
||||
default:
|
||||
return "Segoe UI";
|
||||
}
|
||||
}
|
||||
|
||||
Theme::Ref::Typeface::Font FontTokens::getFont(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
switch (typescale)
|
||||
{
|
||||
case Theme::Sys::Typescale::Label_Large:
|
||||
return Theme::Ref::Typeface::Font::Brand;
|
||||
default:
|
||||
return Theme::Ref::Typeface::Font::Brand;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FontTokens::getLineHeight(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
switch (typescale)
|
||||
{
|
||||
case Theme::Sys::Typescale::Label_Large:
|
||||
return 67;
|
||||
default:
|
||||
return 67;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FontTokens::getSize(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
switch (typescale)
|
||||
{
|
||||
case Theme::Sys::Typescale::Label_Large:
|
||||
return static_cast<unsigned>(57/3);
|
||||
default:
|
||||
return 57;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FontTokens::getTracking(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned FontTokens::getWeight(Theme::Ref::Typeface::Font font)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Theme::Ref::Typeface::Font FontTokens::getWeight(Theme::Sys::Typescale typescale)
|
||||
{
|
||||
return Theme::Ref::Typeface::Font::Brand;
|
||||
}
|
|
@ -51,6 +51,7 @@ namespace Theme
|
|||
|
||||
class FontTokens
|
||||
{
|
||||
public:
|
||||
static std::string getFont(Theme::Ref::Typeface::Font font);
|
||||
|
||||
static Theme::Ref::Typeface::Font getFont(Theme::Sys::Typescale typescale);
|
||||
|
|
|
@ -77,6 +77,25 @@ void BoxGeometry::setBounds(unsigned width, unsigned height)
|
|||
}
|
||||
}
|
||||
|
||||
void BoxGeometry::setWidth(unsigned width)
|
||||
{
|
||||
setBounds(width, mSize.mHeight);
|
||||
}
|
||||
|
||||
void BoxGeometry::setHeight(unsigned height)
|
||||
{
|
||||
setBounds(mSize.mWidth, height);
|
||||
}
|
||||
|
||||
void BoxGeometry::setMaxHeight(unsigned maxHieght)
|
||||
{
|
||||
if (mSize.mMaxHeight != maxHieght)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mSize.mMaxHeight = maxHieght;
|
||||
}
|
||||
}
|
||||
|
||||
void BoxGeometry::setLocation(const DiscretePoint& loc)
|
||||
{
|
||||
if (mLocation != loc)
|
||||
|
|
|
@ -59,6 +59,12 @@ public:
|
|||
|
||||
const DiscretePoint& getLocation() const;
|
||||
|
||||
void setWidth(unsigned width);
|
||||
|
||||
void setHeight(unsigned height);
|
||||
|
||||
void setMaxHeight(unsigned maxHieght);
|
||||
|
||||
void setBounds(unsigned width, unsigned height);
|
||||
|
||||
void setSize(const BoundedSize& size);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
|
||||
Widget::Widget()
|
||||
: BoxGeometry(),
|
||||
|
@ -73,6 +72,24 @@ void Widget::setBackground(Theme::Sys::Color token)
|
|||
}
|
||||
}
|
||||
|
||||
void Widget::setBackgroundTone(Theme::Sys::Color token)
|
||||
{
|
||||
if (mBackgroundTone != token)
|
||||
{
|
||||
mBackgroundTone = token;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setElevation(Theme::Sys::Elevation elevation)
|
||||
{
|
||||
if (mElevation != elevation)
|
||||
{
|
||||
mElevation = elevation;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setBackgroundOpacity(float opacity)
|
||||
{
|
||||
if (mBackgroundOpacity != opacity)
|
||||
|
@ -173,6 +190,9 @@ void Widget::onPaintEvent(const PaintEvent* event)
|
|||
}
|
||||
|
||||
doPaint(event);
|
||||
mGeometryDirty = false;
|
||||
mMaterialDirty = false;
|
||||
mTransformDirty = false;
|
||||
|
||||
if (mVisibilityDirty)
|
||||
{
|
||||
|
@ -293,32 +313,30 @@ void Widget::onMyMouseEvent(const MouseEvent* event)
|
|||
|
||||
void Widget::createOrUpdateGeometry()
|
||||
{
|
||||
const auto deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
|
||||
const auto deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
|
||||
if (!mBackgroundNode)
|
||||
{
|
||||
unsigned locX = mLocation.getX() + mMargin.mLeft;
|
||||
unsigned locY = mLocation.getY() + mMargin.mTop;
|
||||
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
|
||||
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
|
||||
|
||||
const auto locX = mLocation.getX() + mMargin.mLeft;
|
||||
const auto locY = mLocation.getY() + mMargin.mTop;
|
||||
mBackgroundNode = std::make_unique<RectangleNode>(DiscretePoint(locX, locY), deltaX, deltaY);
|
||||
mBackgroundNode->setRadius(mRadius);
|
||||
|
||||
mBackgroundNode->setName(mName + "_BackgroundNode");
|
||||
mRootNode->addChild(mBackgroundNode.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
mBackgroundNode->setWidth(deltaX);
|
||||
mBackgroundNode->setHeight(deltaY);
|
||||
mBackgroundNode->setRadius(mRadius);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::updateTransform()
|
||||
{
|
||||
unsigned locX = mLocation.getX() + mMargin.mLeft;
|
||||
unsigned locY = mLocation.getY() + mMargin.mTop;
|
||||
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
|
||||
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
|
||||
|
||||
mBackgroundNode->setWidth(deltaX);
|
||||
mBackgroundNode->setHeight(deltaY);
|
||||
const auto locX = mLocation.getX() + mMargin.mLeft;
|
||||
const auto locY = mLocation.getY() + mMargin.mTop;
|
||||
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
|
||||
}
|
||||
|
||||
|
@ -326,9 +344,16 @@ void Widget::updateMaterial(const PaintEvent* event)
|
|||
{
|
||||
if (mBackground != Theme::Sys::Color::None)
|
||||
{
|
||||
auto background_color = event->getThemesManager()->getColor(mBackground);
|
||||
background_color.setAlpha(mBackgroundOpacity);
|
||||
mBackgroundNode->setFillColor(background_color);
|
||||
//if (mBackgroundTone == Theme::Sys::Color::None || mElevation == Theme::Sys::Elevation::Level_0)
|
||||
//{
|
||||
auto background_color = event->getThemesManager()->getColor(mBackground);
|
||||
background_color.setAlpha(mBackgroundOpacity);
|
||||
mBackgroundNode->setFillColor(background_color);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
//event->getThemesManager()->getColor(mBackground);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -348,22 +373,14 @@ void Widget::updateMaterial(const PaintEvent* event)
|
|||
|
||||
void Widget::updateBackground(const PaintEvent* event)
|
||||
{
|
||||
unsigned locX = mLocation.getX() + mMargin.mLeft;
|
||||
unsigned locY = mLocation.getY() + mMargin.mTop;
|
||||
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
|
||||
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
|
||||
|
||||
if (!mBackgroundNode)
|
||||
if (mGeometryDirty)
|
||||
{
|
||||
mBackgroundNode = std::make_unique<RectangleNode>(DiscretePoint(locX, locY), deltaX, deltaY);
|
||||
mBackgroundNode->setName(mName + "_BackgroundNode");
|
||||
mRootNode->addChild(mBackgroundNode.get());
|
||||
createOrUpdateGeometry();
|
||||
}
|
||||
|
||||
if (mTransformDirty)
|
||||
{
|
||||
updateTransform();
|
||||
mTransformDirty = false;
|
||||
}
|
||||
|
||||
if (mMaterialDirty)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "FontItem.h"
|
||||
#include "ITheme.h"
|
||||
#include "WidgetState.h"
|
||||
#include "BoxGeometry.h"
|
||||
#include "TransformNode.h"
|
||||
|
||||
#include "ITheme.h"
|
||||
#include "ElevationTokens.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -55,6 +57,10 @@ public:
|
|||
|
||||
void setBackground(Theme::Sys::Color token);
|
||||
|
||||
void setBackgroundTone(Theme::Sys::Color token);
|
||||
|
||||
void setElevation(Theme::Sys::Elevation elevation);
|
||||
|
||||
void setOutlineThickness(double thickness);
|
||||
|
||||
void setOutline(Theme::Sys::Color token);
|
||||
|
@ -102,7 +108,9 @@ protected:
|
|||
Theme::Sys::Color mBorder;
|
||||
double mBorderThickness{0};
|
||||
|
||||
Theme::Sys::Color mBackgroundTone;
|
||||
Theme::Sys::Color mBackground;
|
||||
Theme::Sys::Elevation mElevation{ Theme::Sys::Elevation::Level_0 };
|
||||
float mBackgroundOpacity{ 1.0 };
|
||||
|
||||
bool mVisible{true};
|
||||
|
|
|
@ -5,25 +5,37 @@
|
|||
#include "ThemeManager.h"
|
||||
#include "PaintEvent.h"
|
||||
|
||||
#include "VerticalSpacer.h"
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
TEST_CASE(TestButton_Elevated, "ui_controls")
|
||||
{
|
||||
auto theme_manager = std::make_unique<ThemeManager>();
|
||||
|
||||
auto paint_event = PaintEvent::Create(theme_manager.get(), nullptr);
|
||||
VerticalSpacer spacer;
|
||||
spacer.setWidth(300);
|
||||
spacer.setHeight(200);
|
||||
|
||||
Button button(ButtonData::Component::Elevated);
|
||||
button.setLabel("Enabled");
|
||||
auto enabled_button = Button::Create(ButtonData::Component::Elevated);
|
||||
enabled_button->setLabel("Enabled");
|
||||
|
||||
button.onPaintEvent(paint_event.get());
|
||||
auto disabled_button = Button::Create(ButtonData::Component::Elevated);
|
||||
disabled_button->setEnabled(false);
|
||||
disabled_button->setLabel("Disabled");
|
||||
|
||||
auto node = button.getRootNode();
|
||||
spacer.addWidget(std::move(enabled_button));
|
||||
spacer.addWidget(std::move(disabled_button));
|
||||
|
||||
auto node = spacer.getRootNode();
|
||||
|
||||
TestRenderer renderer;
|
||||
renderer.getScene()->addNode(node);
|
||||
|
||||
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "Elevated_Enabled.svg");
|
||||
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "Elevated_Enabled.png");
|
||||
auto paint_event = PaintEvent::Create(theme_manager.get(), nullptr);
|
||||
spacer.onPaintEvent(paint_event.get());
|
||||
|
||||
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "Elevated.svg");
|
||||
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "Elevated.png");
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue