#include "CurveEdit.h" #include "../../SDK/PlatformIndependent/Core/Timer.h" #include #include #include using namespace Wt; using namespace Wt::Chart; using namespace TVNG; //------------------------------------------------------------------------- CurveEdit::CurveEdit(const std::string& label) : WCartesianChart(), label_(label), selectedRowIndex_(-1), lastEmitTime_(0) { model_ = new WStandardItemModel(0, 3); labelFont_.setFamily(WFont::SansSerif); labelFont_.setSize(WFont::FixedSize, WLength(7, WLength::Point)); // needed to capture key events (HTML5) setAttributeValue("tabindex", "0"); setModel(model_); setXSeriesColumn(0); setLegendEnabled(false); setType(ScatterPlot); WPen pen; pen.setColor(WColor(0, 0, 0, 100)); pen.setWidth(1); WAxis& xAxis = axis(XAxis); WAxis& yAxis = axis(YAxis); xAxis.setLocation(ZeroValue); yAxis.setLocation(ZeroValue); WFont labelFont; labelFont.setFamily(WFont::SansSerif); labelFont.setSize(WFont::FixedSize, WLength(0, WLength::Point)); xAxis.setLabelFont(labelFont); yAxis.setLabelFont(labelFont); xAxis.setLabelFormat("%.2f"); yAxis.setLabelFormat("%.2f"); xAxis.setLabelInterval(0.05); yAxis.setLabelInterval(0.05); xAxis.setRange(-0.1, 1.1); yAxis.setRange(-0.1, 1.1); xAxis.setGridLinesEnabled(true); yAxis.setGridLinesEnabled(true); xAxis.setGridLinesPen(pen); yAxis.setGridLinesPen(pen); setPlotAreaPadding(0, Left); setPlotAreaPadding(0, Right); setPlotAreaPadding(0, Bottom); setPlotAreaPadding(0, Top); setMargin(5, Top | Bottom); setMargin(WLength::Auto, Left | Right); setBackground(WBrush(WColor(150, 150, 150))); // Add the curves WDataSeries s(1, LineSeries); s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 2)); s.setMarker(Chart::SquareMarker); s.setMarkerSize(5); s.setMarkerPen(WPen(WColor(0, 0, 0))); s.setMarkerBrush(WBrush(WColor(255, 255, 0))); s.setPen(WPen(WColor(0, 255, 0, 255))); s.setLabelsEnabled(XAxis); s.setLabelsEnabled(YAxis); addSeries(s); WDataSeries selection(2, PointSeries); selection.setMarker(Chart::SquareMarker); selection.setMarkerPen(WPen(WColor(0, 0, 0))); selection.setMarkerBrush(WBrush(WColor(255, 0, 0))); selection.setMarkerSize(5); addSeries(selection); mouseWentDown().connect(this, &CurveEdit::MouseWentDown); doubleClicked().connect(this, &CurveEdit::DoubleClicked); mouseDragged().connect(this, &CurveEdit::MouseDragged); keyWentUp().connect(this, &CurveEdit::KeyWentUp); resize(300, 135); } //------------------------------------------------------------------------- CurveEdit::~CurveEdit() { delete model_; } //------------------------------------------------------------------------- void CurveEdit::DoubleClicked(const WMouseEvent& e) { if (e.button() != WMouseEvent::LeftButton) return; WPointF pointF = mapFromDevice(WPointF(e.widget().x, e.widget().y)); Vector2f p( static_cast(pointF.x()), static_cast(pointF.y()) ); if (p.X() < 0.) p.SetX(0.); if (p.X() > 1.) p.SetX(1.); if (p.Y() < 0.) p.SetY(0.); if (p.Y() > 1.) p.SetY(1.); for (int i(0); irowCount(); i++) { Vector2f elem( boost::any_cast(model_->data(i, 0)), boost::any_cast(model_->data(i, 1)) ); if (SamePoints(p, elem)) return; if (p.X() == elem.X()) return; } int row = model_->rowCount(); model_->insertRow(row); model_->setData(row, 0, boost::any(p.X())); model_->setData(row, 1, boost::any(p.Y())); model_->setData(row, 2, boost::any(p.Y())); if (selectedRowIndex_ != -1) model_->setData(selectedRowIndex_, 2, boost::any()); model_->sort(0); for (int i(0); irowCount(); i++) { float x( boost::any_cast(model_->data(i, 0)) ); if (x == p.X()) { selectedRowIndex_ = i; break; } } UpdateCurve(); changed_.emit(); } //------------------------------------------------------------------------- void CurveEdit::MouseWentDown(const WMouseEvent& e) { if (e.button() != WMouseEvent::LeftButton) return; WPointF pointF = mapFromDevice(WPointF(e.widget().x, e.widget().y)); Vector2f p( static_cast(pointF.x()), static_cast(pointF.y()) ); if (p.X() < 0.) p.SetX(0.); if (p.X() > 1.) p.SetX(1.); if (p.Y() < 0.) p.SetY(0.); if (p.Y() > 1.) p.SetY(1.); int row(-1); for (int i(0); irowCount(); i++) { Vector2f elem( boost::any_cast(model_->data(i, 0)), boost::any_cast(model_->data(i, 1)) ); if (SamePoints(elem, p)) { row = i; p = elem; break; } } if (selectedRowIndex_ != -1 && row != selectedRowIndex_) model_->setData(selectedRowIndex_, 2, boost::any()); if (row != -1 && selectedRowIndex_ != row) model_->setData(row, 2, boost::any(p.Y())); selectedRowIndex_ = row; } //------------------------------------------------------------------------- void CurveEdit::MouseDragged(const WMouseEvent& e) { if (e.button() != WMouseEvent::LeftButton) return; if (selectedRowIndex_ == -1) return; WPointF pointF = mapFromDevice(WPointF(e.widget().x, e.widget().y)); Vector2f p( static_cast(pointF.x()), static_cast(pointF.y()) ); if (p.X() < 0.) p.SetX(0.); if (p.X() > 1.) p.SetX(1.); if (p.Y() < 0.) p.SetY(0.); if (p.Y() > 1.) p.SetY(1.); for (int i(0); irowCount(); i++) { if (i == selectedRowIndex_) continue; float x = boost::any_cast(model_->data(i, 0)); if (x == p.X()) return; } model_->setData(selectedRowIndex_, 0, boost::any(p.X())); model_->setData(selectedRowIndex_, 1, boost::any(p.Y())); model_->setData(selectedRowIndex_, 2, boost::any(p.Y())); model_->sort(0); for (int i(0); irowCount(); i++) { float x( boost::any_cast(model_->data(i, 0)) ); if (x == p.X()) { selectedRowIndex_ = i; break; } } UpdateCurve(); double emitTime( Timer::DGetTime() ); if (emitTime - lastEmitTime_ > 0.04) { lastEmitTime_ = emitTime; changed_.emit(); } } //------------------------------------------------------------------------- void CurveEdit::KeyWentUp(const WKeyEvent& e) { if (selectedRowIndex_ == -1) return; if (e.key() == Wt::Key_Delete) { model_->removeRow(selectedRowIndex_); selectedRowIndex_ = -1; UpdateCurve(); changed_.emit(); } } //------------------------------------------------------------------------- void CurveEdit::SetCurve( const FloatAnimationCurvePtr& curve ) { model_->removeRows(0, model_->rowCount()); if (curve != NULL) { for (unsigned int i(0); iGetNumKeyFrames(); i++) { int row = model_->rowCount(); model_->insertRow(row); const std::pair< float, float >& keyframe = curve->GetKeyFrame(i); model_->setData(row, 0, boost::any(keyframe.first)); model_->setData(row, 1, boost::any(keyframe.second)); model_->setData(row, 2, boost::any()); } } UpdateCurve(); selectedRowIndex_ = -1; } //------------------------------------------------------------------------- void CurveEdit::UpdateCurve() { curve_.RemoveAllKeyFrames(); for (int i(0); irowCount(); i++) { Vector2f elem( boost::any_cast(model_->data(i, 0)), boost::any_cast(model_->data(i, 1)) ); curve_.AddKeyFrame(elem.X(), elem.Y()); } } //------------------------------------------------------------------------- bool CurveEdit::SamePoints(const Vector2f& p1, const Vector2f& p2) { float d = sqrt((p1.X() - p2.X()) * (p1.X() - p2.X()) + (p1.Y() - p2.Y()) * (p1.Y() - p2.Y())); if (d < 0.05) return true; return false; } //------------------------------------------------------------------------- void CurveEdit::paint(Wt::WPainter& painter, const Wt::WRectF& rectangle) const { painter.setFont(labelFont_); WCartesianChart::paint(painter, rectangle); }