5 #include <wx/graphics.h>
10 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(800, 600)) {
11 this->Connect(wxEVT_PAINT, wxPaintEventHandler(CurvePanel::onPaint));
12 this->Connect(wxEVT_MOTION, wxMouseEventHandler(CurvePanel::onMouseMotion));
13 this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CurvePanel::onLeftDown));
14 this->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(CurvePanel::onLeftUp));
15 this->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(CurvePanel::onRightUp));
20 void CurvePanel::onPaint(wxPaintEvent&
UNUSED(evt)) {
23 dc.SetPen(*wxWHITE_PEN);
25 wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
26 wxPen pen = *wxWHITE_PEN;
29 wxBrush brush = *wxWHITE_BRUSH;
30 brush.SetColour(wxColour(100, 100, 100));
35 wxGraphicsPath path = gc->CreatePath();
36 const int x1 = curveToWindow<wxPoint>(curve.
getPoint(i)).x;
37 const int x2 = curveToWindow<wxPoint>(curve.
getPoint(i + 1)).x;
39 if (i == highlightSegment) {
40 pen.SetColour(wxColour(255, 100, 50));
42 pen.SetColour(wxColour(180, 180, 180));
46 for (
int x = x1; x <= x2; ++x) {
47 const float f = float(curve(windowToCurve(wxPoint(x, 0)).x));
48 const float y = float(curveToWindow<wxPoint2DDouble, double>(
CurvePoint{ 0.f, f }).m_y);
49 const wxPoint2DDouble p(x, y);
51 path.AddLineToPoint(p);
60 pen.SetColour(wxColour(180, 180, 180));
63 const wxPoint p = curveToWindow<wxPoint>(curve.
getPoint(i));
64 if (highlightIdx == i) {
65 brush.SetColour(wxColour(255, 100, 50));
67 brush.SetColour(wxColour(100, 100, 100));
74 wxSize size = this->GetSize() - wxSize(2 * padding, 2 * padding);
75 dc.DrawLine(wxPoint(padding, padding + size.y), wxPoint(padding + size.x, padding + size.y));
76 dc.DrawLine(wxPoint(padding, padding), wxPoint(padding, padding + size.y));
81 for (
Size i = 0; i < ticsX.
size(); ++i) {
83 const int x = padding + i * size.x / (ticsX.
size() - 1);
85 dc.DrawLine(wxPoint(x, size.y + padding - 2), wxPoint(x, size.y + padding + 2));
89 for (
Size i = 0; i < ticsY.
size(); ++i) {
91 const int y = padding + size.y - i * size.y / (ticsY.
size() - 1);
93 dc.DrawLine(wxPoint(padding - 2, y), wxPoint(padding + 2, y));
97 if (mousePosition != wxDefaultPosition) {
98 dc.SetPen(*wxGREY_PEN);
100 CurvePoint curvePos = windowToCurve(mousePosition);
101 curvePos.
y = curve(curvePos.
x);
102 const wxPoint center = curveToWindow<wxPoint>(curvePos);
103 dc.DrawLine(wxPoint(padding, center.y), wxPoint(padding + size.x, center.y));
104 dc.DrawLine(wxPoint(center.x, padding), wxPoint(center.x, padding + size.y));
105 dc.SetTextForeground(wxColour(128, 128, 128));
106 wxFont font = dc.GetFont().Smaller();
117 void CurvePanel::onMouseMotion(wxMouseEvent& evt) {
118 mousePosition = evt.GetPosition();
119 highlightIdx = this->getIdx(mousePosition);
120 highlightSegment = this->getSegment(mousePosition);
121 if (evt.Dragging() && lockedIdx) {
122 CurvePoint newPos = windowToCurve(evt.GetPosition());
128 void CurvePanel::onLeftDown(wxMouseEvent& evt) {
129 mousePosition = evt.GetPosition();
134 const CurvePoint newPos = windowToCurve(mousePosition);
136 lockedIdx = this->getIdx(mousePosition);
141 void CurvePanel::onLeftUp(wxMouseEvent&
UNUSED(evt)) {
145 void CurvePanel::onRightUp(wxMouseEvent& evt) {
146 mousePosition = evt.GetPosition();
149 }
else if (
Optional<Size> segmentIdx = this->getSegment(mousePosition)) {
155 template <
typename TPo
int,
typename T>
156 TPoint CurvePanel::curveToWindow(
const CurvePoint& p)
const {
157 wxSize size = this->GetSize() - wxSize(2 * padding, 2 * padding);
161 return TPoint(T(padding + (p.
x - rangeX.
lower()) / rangeX.
size() * size.x),
162 T(padding + size.y - (p.
y - rangeY.
lower()) / rangeY.
size() * size.y));
165 CurvePoint CurvePanel::windowToCurve(
const wxPoint2DDouble p)
const {
166 wxSize size = this->GetSize() - wxSize(2 * padding, 2 * padding);
170 float(rangeY.
size() - (p.m_y - padding) * rangeY.
size() / size.y + rangeY.
lower()) };
175 wxPoint dist = curveToWindow<wxPoint>(curve.
getPoint(i)) - mousePos;
183 Optional<Size> CurvePanel::getSegment(
const wxPoint mousePos)
const {
185 const wxPoint p1 = curveToWindow<wxPoint>(curve.
getPoint(i));
186 const wxPoint p2 = curveToWindow<wxPoint>(curve.
getPoint(i + 1));
187 if (mousePos.x > p1.x && mousePos.x < p2.x) {
190 const wxPoint projPos = curveToWindow<wxPoint>(m);
191 if (
abs(mousePos.y - projPos.y) <
radius) {
200 wxPGProperty* property,
202 const wxSize& size)
const {
210 wxPropertyGridEvent* changeEvent = new wxPropertyGridEvent(wxEVT_PG_CHANGED);
211 changeEvent->SetProperty(property);
212 CurveProperty* curveProp = dynamic_cast<CurveProperty*>(property);
213 SPH_ASSERT(curveProp);
214 curveProp->setCurve(curve);
215 propgrid->GetEventHandler()->ProcessEvent(*changeEvent);
218 return wxPGWindowList(
nullptr);
228 wxPGProperty* property,
229 const wxString& text)
const {
230 dc.SetBrush(*wxBLACK_BRUSH);
231 dc.DrawRectangle({ 0, 0 }, { 200, 100 });
238 wxPGProperty* property,
239 wxWindow* wnd_primary,
240 wxEvent& event)
const {
249 : wxFrame(parent, wxID_ANY,
"Curve", wxDefaultPosition, wxSize(600, 450))
250 , curveChanged(curveChanged) {
251 wxBoxSizer* sizer =
new wxBoxSizer(wxVERTICAL);
254 sizer->Add(panel, 1, wxEXPAND | wxALL);
256 wxBoxSizer* buttonSizer =
new wxBoxSizer(wxHORIZONTAL);
257 wxButton* okButton =
new wxButton(
this, wxID_ANY,
"OK");
258 okButton->Bind(wxEVT_BUTTON, [
this, panel](wxCommandEvent&
UNUSED(evt)) {
259 this->curveChanged(panel->
getCurve());
262 buttonSizer->Add(okButton, 0);
264 wxButton* cancelButton =
new wxButton(
this, wxID_ANY,
"Cancel");
265 cancelButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->Close(); });
266 buttonSizer->Add(cancelButton, 0);
268 sizer->Add(buttonSizer);
270 this->SetSizer(sizer);
uint32_t Size
Integral type used to index arrays (by default).
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
INLINE auto abs(const T &f)
#define NAMESPACE_SPH_END
const NothingType NOTHING
Array< Float > getLinearTics(const Interval &interval, const Size minCount)
Returns the tics to be drawn on a linear axis of a plot.
Drawing quantity values as functions of time or spatial coordinates.
void drawTextWithSubscripts(wxDC &dc, const std::wstring &text, const wxPoint point)
std::wstring toPrintableString(const Float value, const Size precision, const Float decimalThreshold)
Converts the value to a printable string.
Random utility functions for drawing stuff to DC.
INLINE TCounter size() const noexcept
CurveDialog(wxWindow *parent, const Curve &curve, Function< void(const Curve &)> curveChanged)
virtual wxPGWindowList CreateControls(wxPropertyGrid *propgrid, wxPGProperty *property, const wxPoint &pos, const wxSize &size) const override
virtual void DrawValue(wxDC &dc, const wxRect &rect, wxPGProperty *property, const wxString &text) const override
virtual void UpdateControl(wxPGProperty *property, wxWindow *ctrl) const override
virtual bool OnEvent(wxPropertyGrid *propgrid, wxPGProperty *property, wxWindow *wnd_primary, wxEvent &event) const override
void setCurve(const Curve &newCurve)
CurvePanel(wxWindow *parent)
const Curve & getCurve() const
Represents a user-defined function, defined by a set of points interpolated by either piecewise linea...
const CurvePoint & getPoint(const Size idx) const
Returns the position of idx-th point.
Interval rangeY() const
Returns the extent of the curve in y-direction.
void setPoint(const Size idx, const CurvePoint &newPoint)
Modifies the position of idx-th points.
Size getPointCnt() const
Returns the number of points defining the curve.
void addPoint(const CurvePoint &newPoint)
Adds a new point to the curve.
void setSegment(const Size idx, const bool cubic)
Modifies the interpolation type of idx-th segment.
Interval rangeX() const
Returns the extent of the curve in x-direction.
bool getSegment(const Size idx) const
Returns the interpolation type of idx-th segment.
void deletePoint(const Size idx)
Removes idx-th point from curve.
Object representing a 1D interval of real numbers.
INLINE Float lower() const
Returns lower bound of the interval.
INLINE Float size() const
Returns the size of the interval.
INLINE Type & value()
Returns the reference to the stored value.
2D point and other primitives for 2D geometry