Skip to content

Commit c82f9e8

Browse files
authored
Add BackendFlag guards and backend redraw cleanup
1 parent 12a6396 commit c82f9e8

3 files changed

Lines changed: 122 additions & 1 deletion

File tree

include/Widget.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ extern Widget* mouseOwningFlag;
1818
extern Widget* focusingWidget;
1919
extern std::vector<Widget*> widgetOrder;
2020
extern bool PanelScaleChanged;
21+
extern bool BackendFlag;
22+
extern std::vector<Widget*> widgetBackendRedraw;
23+
void markWidgetBackendRedraw(Widget* widget);
2124

2225
/**
2326
* @brief 所有可绘制控件的基类
@@ -94,10 +97,16 @@ class Widget {
9497
*/
9598
int getDrawingState() const;
9699

100+
/**
101+
* @brief 检查控件是否仍需要后台更新
102+
* @return true表示仍处于dirty状态
103+
*/
104+
virtual bool isBackendDirty() const;
105+
97106
virtual void reset();
98107

99108
// 仅作用于部分控件
100-
void setNeedRedraw(bool b) { needRedraw = b; };
109+
void setNeedRedraw(bool b);
101110

102111
protected:
103112
double cx = 0, cy = 0; ///< 中心坐标
@@ -231,6 +240,8 @@ class Panel : public Widget {
231240

232241
int getAlwaysDirtyState();
233242

243+
bool isBackendDirty() const override;
244+
234245
/**
235246
* @brief 启用或禁用滚动条
236247
* @param enable 是否启用
@@ -484,6 +495,8 @@ class Button : public Widget {
484495
virtual void catchMouseOwningFlag(const mouse_msg& msg) override;
485496

486497
void reset() override;
498+
499+
bool isBackendDirty() const override;
487500
};
488501

489502
/**
@@ -667,6 +680,8 @@ class InputBox : public Widget {
667680
void updateIMEPosition();
668681

669682
void reset() override;
683+
684+
bool isBackendDirty() const override;
670685
};
671686

672687

@@ -833,6 +848,8 @@ class Slider : public Widget {
833848
* @brief 修正进度值到最近的步进点
834849
*/
835850
double fixProgress();
851+
852+
bool isBackendDirty() const override;
836853
};
837854

838855

@@ -944,6 +961,8 @@ class ProgressBar : public Widget {
944961
bool handleEvent(const mouse_msg& msg) override;
945962
void setPosition(double x, double y) override;
946963
void setScale(double s) override;
964+
965+
bool isBackendDirty() const override;
947966
};
948967

949968

@@ -985,6 +1004,8 @@ class Dropdown : public Widget {
9851004
bool handleEvent(const mouse_msg& msg) override;
9861005
bool isInside(double x, double y) const;
9871006

1007+
bool isBackendDirty() const override;
1008+
9881009

9891010
protected:
9901011
Button* mainButton;
@@ -1052,6 +1073,8 @@ class Radio : public Widget {
10521073
void draw() override;
10531074
bool handleEvent(const mouse_msg& msg) override;
10541075

1076+
bool isBackendDirty() const override;
1077+
10551078
protected:
10561079
double cx, cy;
10571080
double radius, scale = 1.0;
@@ -1170,6 +1193,8 @@ class Toggle : public Widget {
11701193
virtual void releaseMouseOwningFlag(const mouse_msg& msg) override;
11711194
virtual void catchMouseOwningFlag(const mouse_msg& msg) override;
11721195

1196+
bool isBackendDirty() const override;
1197+
11731198
protected:
11741199
double cx, cy;
11751200
double width, height, scale = 1.0;
@@ -1388,6 +1413,8 @@ class Knob : public Widget {
13881413
virtual void releaseMouseOwningFlag(const mouse_msg& msg) override;
13891414
virtual void catchMouseOwningFlag(const mouse_msg& msg) override;
13901415

1416+
bool isBackendDirty() const override;
1417+
13911418
protected:
13921419
double cx, cy; ///< 中心坐标
13931420
double radius; ///< 半径

src/Element.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,22 @@ void reflush() {
14301430
if(!is_run()) return;
14311431
w->draw();
14321432
}
1433+
1434+
BackendFlag = true;
1435+
for (auto it = widgetBackendRedraw.begin(); it != widgetBackendRedraw.end(); ) {
1436+
Widget* w = *it;
1437+
if (!w) {
1438+
it = widgetBackendRedraw.erase(it);
1439+
continue;
1440+
}
1441+
w->draw();
1442+
if (!w->isBackendDirty()) {
1443+
it = widgetBackendRedraw.erase(it);
1444+
} else {
1445+
++it;
1446+
}
1447+
}
1448+
BackendFlag = false;
14331449

14341450
POINT pt;
14351451
::GetCursorPos(&pt); // 获取当前鼠标位置

src/Widget.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ Widget* focusingWidget = nullptr;
88
vector<Widget*> widgets;
99
double absolutPosDeltaX = 0,absolutPosDeltaY = 0;
1010
bool PanelScaleChanged = false;
11+
bool BackendFlag = false;
12+
std::vector<Widget*> widgetBackendRedraw;
13+
14+
void markWidgetBackendRedraw(Widget* widget) {
15+
if (!widget) return;
16+
auto it = std::find(widgetBackendRedraw.begin(), widgetBackendRedraw.end(), widget);
17+
if (it == widgetBackendRedraw.end()) {
18+
widgetBackendRedraw.push_back(widget);
19+
}
20+
}
1121

1222
// 当前可绘制区域(全局坐标系),Panel绘制时逐层收窄
1323
static constexpr double DRAWING_BOUND_MIN = -1e9;
@@ -55,6 +65,17 @@ int Widget::getDrawingState() const {
5565
return this->m_drawing;
5666
}
5767

68+
bool Widget::isBackendDirty() const {
69+
return needRedraw || m_drawing > 0;
70+
}
71+
72+
void Widget::setNeedRedraw(bool b) {
73+
needRedraw = b;
74+
if (b) {
75+
markWidgetBackendRedraw(this);
76+
}
77+
}
78+
5879
void Widget::reset() {
5980

6081
}
@@ -105,6 +126,7 @@ void Panel::draw() {
105126
}
106127

107128
void Panel::draw(PIMAGE dst, double x, double y) {
129+
if (BackendFlag) return;
108130
double left = x - width / 2 - 4;
109131
double top = y - height / 2 - 4;
110132
double layerWidth = this->width + 8;
@@ -236,6 +258,9 @@ Panel::~Panel(){
236258

237259
void Panel::setAlwaysDirty(bool d) {
238260
this->needRedrawAlways += ((int)d + d - 1);
261+
if (d) {
262+
markWidgetBackendRedraw(this);
263+
}
239264
if(this->parent != nullptr){
240265
if (Panel* p = dynamic_cast<Panel*>(this->parent)) {
241266
p->setAlwaysDirty(d);
@@ -245,6 +270,7 @@ void Panel::setAlwaysDirty(bool d) {
245270

246271
void Panel::setDirty() {
247272
this->needRedraw = true;
273+
markWidgetBackendRedraw(this);
248274
if(this->parent != nullptr){
249275
if (Panel* p = dynamic_cast<Panel*>(this->parent)) {
250276
p->setDirty();
@@ -256,6 +282,10 @@ int Panel::getAlwaysDirtyState() {
256282
return this->needRedrawAlways;
257283
}
258284

285+
bool Panel::isBackendDirty() const {
286+
return needRedraw || needRedrawAlways > 0 || scaleChanged;
287+
}
288+
259289
void Panel::setPosition(double x,double y){
260290
cx = x;
261291
cy = y;
@@ -650,6 +680,7 @@ void Ripple::update() {
650680
}
651681

652682
void Ripple::draw(PIMAGE dst) const {
683+
if (BackendFlag) return;
653684
double progress = (double)age / life;
654685
double r = maxRadius * progress;
655686
int alpha = static_cast<int>(120 * std::cos(progress * PI / 2));
@@ -658,6 +689,7 @@ void Ripple::draw(PIMAGE dst) const {
658689
}
659690

660691
void Ripple::draw_aa(PIMAGE dst) const {
692+
if (BackendFlag) return;
661693
double progress = (double)age / life;
662694
double r = maxRadius * progress;
663695
int alpha = static_cast<int>(120 * std::cos(progress * PI / 2));
@@ -686,6 +718,7 @@ Button::~Button() {
686718
}
687719

688720
void Button::draw(PIMAGE dst,double x,double y){
721+
if (BackendFlag) return;
689722
double left = x - width / 2 - 4;
690723
double top = y - height / 2 - 4;
691724
double width = this->width + 8;
@@ -752,6 +785,10 @@ void Button::draw(){
752785
draw(nullptr,cx,cy);
753786
}
754787

788+
bool Button::isBackendDirty() const {
789+
return needRedraw || !ripples.empty();
790+
}
791+
755792
void Button::releaseMouseOwningFlag(const mouse_msg& msg){
756793
if(!msg.is_left() || !msg.is_up() || !m_clicking) return;
757794
bool inside = isInside(msg.x, msg.y);
@@ -1039,6 +1076,7 @@ double InputBoxSinDoubleForCursor(double time) {
10391076
}
10401077

10411078
void InputBox::draw(PIMAGE dst, double x, double y) {
1079+
if (BackendFlag) return;
10421080
double left = x - width / 2 - 4;
10431081
double top = y - height / 2 - 4;
10441082
double width = this->width + 8;
@@ -1213,6 +1251,10 @@ void InputBox::draw(){
12131251
draw(nullptr,cx,cy);
12141252
}
12151253

1254+
bool InputBox::isBackendDirty() const {
1255+
return needRedraw || on_focus || !ripples.empty() || scaleChanged || PanelScaleChanged;
1256+
}
1257+
12161258
void InputBox::deleteFocus(const mouse_msg& msg){
12171259
on_focus = false;
12181260
dragging = false;
@@ -1798,6 +1840,7 @@ void Slider::create(double x, double y, double w, double h) {
17981840
}
17991841

18001842
void Slider::draw(PIMAGE dst,double x,double y){
1843+
if (BackendFlag) return;
18011844
double left = x - width / 2;
18021845
double top = y - height / 2;
18031846
// 动态更新缩放比例
@@ -1885,6 +1928,12 @@ void Slider::draw(){
18851928
draw(nullptr,cx,cy);
18861929
}
18871930

1931+
bool Slider::isBackendDirty() const {
1932+
bool scaleAnimating = std::fabs(m_scale - (m_pressed ? 0.8f : 1.0f)) > 0.01;
1933+
bool progressAnimating = std::fabs(m_progress - m_finalprogress) > 0.005;
1934+
return m_dragging || m_pressed || m_hover || scaleAnimating || progressAnimating;
1935+
}
1936+
18881937
bool Slider::isInside(double x, double y){
18891938
double knobX, knobY;
18901939
if (m_orientation == Orientation::Column) {
@@ -2199,6 +2248,7 @@ void ProgressBar::setBackground(color_t bg) {
21992248
}
22002249

22012250
void ProgressBar::draw(PIMAGE dst, double x, double y) {
2251+
if (BackendFlag) return;
22022252
double left = x - width / 2;
22032253
double top = y - height / 2;
22042254

@@ -2231,6 +2281,10 @@ void ProgressBar::draw() {
22312281
draw(nullptr, cx, cy);
22322282
}
22332283

2284+
bool ProgressBar::isBackendDirty() const {
2285+
return needRedraw || std::fabs(currentProgress - targetProgress) > 1e-4;
2286+
}
2287+
22342288
bool ProgressBar::handleEvent(const mouse_msg& msg){
22352289
return false;
22362290
}
@@ -2360,6 +2414,7 @@ void Dropdown::updateDropdownLayout() {
23602414
}
23612415

23622416
void Dropdown::draw(PIMAGE dst, double x, double y) {
2417+
if (BackendFlag) return;
23632418
// 主按钮正常绘制
23642419
mainButton->draw(dst, x, y);
23652420

@@ -2395,6 +2450,13 @@ void Dropdown::draw() {
23952450
draw(nullptr, cx, cy);
23962451
}
23972452

2453+
bool Dropdown::isBackendDirty() const {
2454+
bool fading = fadingIn || fadingOut || fadeAlpha > 0.08;
2455+
bool mainDirty = mainButton && mainButton->isBackendDirty();
2456+
bool panelDirty = dropdownPanel && dropdownPanel->isBackendDirty();
2457+
return expanded || fading || mainDirty || panelDirty;
2458+
}
2459+
23982460
bool Dropdown::handleEvent(const mouse_msg& msg) {
23992461
if (expanded) {
24002462
dropdownPanel->handleEvent(msg);
@@ -2549,6 +2611,7 @@ bool Radio::isChecked() const {
25492611
}
25502612

25512613
void Radio::draw(PIMAGE dst, double x, double y) {
2614+
if (BackendFlag) return;
25522615
bool nowChecked = isChecked();
25532616
bool showDot = isChecked() || (animOut && animProgress < 1.0);
25542617
if (!nowChecked && wasChecked && !animOut) {
@@ -2626,6 +2689,10 @@ void Radio::draw() {
26262689
draw(nullptr, cx, cy);
26272690
}
26282691

2692+
bool Radio::isBackendDirty() const {
2693+
return hovered || animIn || animOut;
2694+
}
2695+
26292696
bool Radio::handleEvent(const mouse_msg& msg) {
26302697
int dx = msg.x - cx;
26312698
int dy = msg.y - cy;
@@ -2873,6 +2940,7 @@ color_t mixColor(color_t c1, color_t c2, double ratio) {
28732940
}
28742941

28752942
void Toggle::draw(PIMAGE dst, double x, double y) {
2943+
if (BackendFlag) return;
28762944
// === 动画推进 ===
28772945
if (std::abs(knobOffset - knobTarget) > 1e-3)
28782946
knobOffset += (knobTarget - knobOffset) * animationSpeed;
@@ -2933,6 +3001,10 @@ void Toggle::draw() {
29333001
draw(nullptr, cx, cy);
29343002
}
29353003

3004+
bool Toggle::isBackendDirty() const {
3005+
return hovered || pressedIn || std::fabs(knobOffset - knobTarget) > 1e-3;
3006+
}
3007+
29363008
ToggleBuilder& ToggleBuilder::setCenter(double x, double y) {
29373009
cx = x; cy = y;
29383010
return *this;
@@ -3089,6 +3161,7 @@ void Text::draw() {
30893161
}
30903162

30913163
void Text::draw(PIMAGE dst, double x, double y) {
3164+
if (BackendFlag) return;
30923165
ege_setfont(fontSize * scale, fontName.c_str(), dst);
30933166
settextcolor(color, dst);
30943167

@@ -3352,6 +3425,7 @@ bool Knob::isInside(double x, double y) const {
33523425
}
33533426

33543427
void Knob::draw(PIMAGE dst, double x, double y) {
3428+
if (BackendFlag) return;
33553429
ege_enable_aa(true,dst);
33563430
double r = radius;
33573431

@@ -3455,6 +3529,10 @@ void Knob::draw() {
34553529
draw(nullptr, cx, cy);
34563530
}
34573531

3532+
bool Knob::isBackendDirty() const {
3533+
return dragging || hovered || std::fabs(displayValue - value) >= 0.01;
3534+
}
3535+
34583536
void Knob::releaseMouseOwningFlag(const mouse_msg& msg){
34593537
dragging = false;
34603538
mouseOwningFlag = nullptr;

0 commit comments

Comments
 (0)