193 lines
6.1 KiB
C++
193 lines
6.1 KiB
C++
#pragma once
|
|
|
|
#include "AbsAxis_p.h"
|
|
#include "Core/Base/RingBuffer.hpp"
|
|
#include "TimeAxis.h"
|
|
|
|
|
|
#include <QTime>
|
|
|
|
#include "YSGraphic_Core/base/RingBuffer.hpp"
|
|
|
|
|
|
namespace YSG {
|
|
|
|
struct TimeTicker {
|
|
bool mStartCoordToEndCoord = true;
|
|
// 最小值的范围 lower在这里面循环变化
|
|
int mLower = 0, mTimePointSize{};
|
|
int mLowerMin{}, mLowerMax{}; //闭区间
|
|
int mTickStart = 0, mTickSpace = 4;
|
|
[[nodiscard]] int upper() const {
|
|
return mLower - 1 + mTimePointSize;
|
|
}
|
|
|
|
void setTickSpace(int tickSpace) {
|
|
if(mTickSpace == tickSpace) return;
|
|
mTickSpace = tickSpace;
|
|
mTickStart = 0;
|
|
}
|
|
|
|
void setTimePointSize(int timePointSize) {
|
|
if(mTimePointSize == timePointSize) return;
|
|
mTimePointSize = timePointSize;
|
|
// 除2怕溢出
|
|
mLowerMin = std::numeric_limits<int>::min()/2;
|
|
mLowerMax = std::numeric_limits<int>::max()/2 - timePointSize + 1;
|
|
mTickStart = 0;
|
|
}
|
|
|
|
std::pair<int, bool> getNewDataTickInfo() {
|
|
{ // 获取 坐标轴的起点
|
|
if(mStartCoordToEndCoord) {
|
|
if(mLower != mLowerMin) mLower--;
|
|
else {
|
|
mLower = mLowerMax;
|
|
}
|
|
} else {
|
|
if(mLower != mLowerMax) mLower++;
|
|
else {
|
|
mLower = mLowerMin;
|
|
}
|
|
}
|
|
}
|
|
mTickStart = ++mTickStart % mTickSpace;
|
|
int endIndex = mLower + mTimePointSize - 1;
|
|
auto startIndex = mLower;
|
|
if(mTickStart == 1) {
|
|
return {mStartCoordToEndCoord ? startIndex : endIndex, true};
|
|
}
|
|
return {mStartCoordToEndCoord ? startIndex : endIndex, false};
|
|
}
|
|
};
|
|
struct TimeTick {
|
|
QTime mTime;
|
|
int mTick{};
|
|
};
|
|
|
|
struct TimeAxisTempData : AbsAxisTempData {
|
|
std::list<TimeTick> mData;
|
|
std::list<QTime> mAllTime;
|
|
};
|
|
|
|
|
|
struct TimeAxisRenderState : AbsAxisRenderState, TimeAxis_Prop {
|
|
int tickSpace = 4;
|
|
int getTickSpaceHint(SRC src = SRC::Cache) {
|
|
QFontMetrics fm(font);
|
|
double rate = (double)timePointSize/(double)pixelSize;
|
|
double ret = rate * (tickPixelSpace + (orientation == Qt::Horizontal ? fm.horizontalAdvance(timeFormat) : fm.height()));
|
|
|
|
return std::max(1, (int)ret);
|
|
}
|
|
};
|
|
|
|
struct TimeAxisPrivate : AbsAxisPrivate {
|
|
D_Ptr(TimeAxis)
|
|
TimeTicker mTimeTicker{};
|
|
int mTickPixelSpace;
|
|
QFont mFont;
|
|
QString mTimeFormat;
|
|
YSG::RingBuffer mRingBuffer;
|
|
std::list<TimeTick> mData;
|
|
void prepareData() override {
|
|
SpinLockGuard guard(&mBufferLock);
|
|
loadCache();
|
|
auto d = tempData();
|
|
auto s = renderState();
|
|
auto sc = renderStateCache();
|
|
bool refreshSpace = false;
|
|
if(mTimeTicker.mTimePointSize != s->timePointSize) {
|
|
mTimeTicker.setTimePointSize(s->timePointSize);
|
|
mRingBuffer.resize(sizeof(QTime), s->timePointSize, 10 * s->timePointSize);
|
|
mData.clear();
|
|
refreshSpace = true;
|
|
}
|
|
if(mTickPixelSpace != s->tickPixelSpace) {
|
|
mTickPixelSpace = s->tickPixelSpace;
|
|
refreshSpace = true;
|
|
}
|
|
if(mFont != s->font) {
|
|
mFont = s->font;
|
|
refreshSpace = true;
|
|
}
|
|
if(mTimeFormat != s->timeFormat) {
|
|
mTimeFormat = s->timeFormat;
|
|
if(s->orientation == Qt::Horizontal) {
|
|
refreshSpace = true;
|
|
}
|
|
}
|
|
if(refreshSpace) {
|
|
s->tickSpace = s->getTickSpaceHint();
|
|
sc->tickSpace = s->tickSpace;
|
|
if(mTimeTicker.mTickSpace != s->tickSpace) {
|
|
mTimeTicker.setTickSpace(s->tickSpace);
|
|
mData.resize(0);
|
|
}
|
|
}
|
|
s->coordStart = mTimeTicker.mLower;
|
|
s->coordLength = mTimeTicker.mTimePointSize;
|
|
sc->coordStart = mTimeTicker.mLower;
|
|
sc->coordLength = mTimeTicker.mTimePointSize;
|
|
|
|
int lowwer = mTimeTicker.mLower;
|
|
int upper = mTimeTicker.upper();
|
|
if(lowwer > upper) std::swap(lowwer, upper);
|
|
|
|
|
|
for(QTime& time : d->mAllTime) {
|
|
mRingBuffer.pushData(&time);
|
|
}
|
|
d->mAllTime.clear();
|
|
|
|
mData.splice(mData.begin(), d->mData);
|
|
|
|
while (!mData.empty()) {
|
|
int tick = mData.back().mTick;
|
|
if(tick < lowwer || tick > upper) {
|
|
mData.pop_back();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
int i = 0;
|
|
ticks.clear();
|
|
labels.clear();
|
|
for(TimeTick& t : mData) {
|
|
ticks.append(t.mTick);
|
|
labels.append(t.mTime.toString(s->timeFormat));
|
|
++i;
|
|
}
|
|
}
|
|
|
|
|
|
QVector<QString> createLabelVector(const QVector<double>& ticks, SRC src) override {
|
|
return labels;
|
|
}
|
|
|
|
QVector<double> createTickVector(double tickStep, const Range& range) override {
|
|
return ticks;
|
|
}
|
|
|
|
QVector<double> createSubTickVector(int subTickCount, const QVector<double>& ticks, const Range& range) override{return {};}
|
|
|
|
// 最小值的范围 lower在这里面循环变化
|
|
int mLower = 0, mLowerMin = 0, mLowerMax{}; //闭区间
|
|
int mTickStart = 0;
|
|
|
|
QVector<QString> labels;
|
|
QVector<double> ticks;
|
|
|
|
void draw(QPainter* painter) override {
|
|
AbsAxisPrivate::draw(painter);
|
|
}
|
|
|
|
QString getTickLabel(double tick, SRC src) override {
|
|
auto renderState = reinterpret_cast<TimeAxisRenderState*>(getState(src));
|
|
return q()->tickToTime((int)tick, src).toString(renderState->timeFormat);
|
|
}
|
|
};
|
|
}
|
|
|