YSTest: ShlExplorer.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

ShlExplorer.cpp
浏览该文件的文档.
1 /*
2 © 2010-2019 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "ShlExplorer.h" // for ystdex::polymorphic_cast, ystdex::tolower,
29 // to_string, make_string_view;
30 #include "ShlReader.h"
31 #include YFM_YSLib_UI_ExStyle
32 #include <ystdex/functional.hpp> // for ystdex::bind1;
33
34 namespace YReader
35 {
36
37 namespace
38 {
39
41
42 using namespace IO;
43
44 enum class FileCategory
45 {
46 Empty = yimpl(int)(NodeCategory::Empty),
47 Unknown = yimpl(int)(NodeCategory::Regular),
48 Binary,
49 Text
50 };
51
52 YB_ATTR_nodiscard bool
53 CheckTextFileExtensions(string ext)
54 {
55 for(auto& c : ext)
56 c = ystdex::tolower(c);
57 try
58 {
59 const auto& m(FetchMIMEBiMapping().GetExtensionMap());
60 const auto i(m.find(ext));
61
62 // TODO: Compare for multiple values.
63 if(i != m.end())
64 {
65 const auto& pth(i->second);
66
67 return !pth.empty() && (pth.front() == "text"
68 || ystdex::ends_with(pth.back(), "xml"));
69 }
70 }
71 CatchIgnore(std::out_of_range&)
72 return {};
73 }
74
75 YB_ATTR_nodiscard FileCategory
76 ClassifyFile(const Path& pth)
77 {
78 switch(ClassifyNode(pth))
79 {
80 case NodeCategory::Regular:
81 return CheckTextFileExtensions(GetExtensionOf(pth).GetMBCS())
82 ? FileCategory::Text : FileCategory::Binary;
83 case NodeCategory::Unknown:
84 break;
85 default:
86 return FileCategory::Empty;
87 }
88 // TODO: Verifying.
89 // TODO: Implementation for other categories.
90 return FileCategory::Unknown;
91 }
93
95 YB_ATTR_nodiscard bool
96 CheckReaderEnability(FileBox& fb, RadioBox& hex)
97 {
98 if(fb.IsSelected())
99 {
100 switch(ClassifyFile(fb.GetPath()))
101 {
102 case FileCategory::Text:
103 return true;
104 case FileCategory::Binary:
105 return hex.GetState().get() == &hex;
106 default:
107 ;
108 }
109 }
110 return {};
111 }
112
113
115 inline bool
116 CheckMenuKey(const KeyInput& k)
117 {
118 #if YCL_Win32
119 auto ke(k);
120
121 ystdex::unseq_apply([&](int vk) ynothrow{
122 ke.set(size_t(vk), {});
123 }, VK_CONTROL, VK_LCONTROL, VK_RCONTROL);
124 return ke.none() && k[VK_CONTROL];
125 #else
126 return k.count() == 1 && k[YCL_KEY_Start];
127 #endif
128 }
129
130
132
133 yconstexpr const auto PI = 3.141592F;
134 yconstexpr const auto PI_2 = PI * 2;
135
137 void
138 DrawStar(Graphics& g, const Rect& bounds, Color c, const Point& pt, SDst r,
139 float a, size_t n = 5)
140 {
141 static yconstexpr const auto PI_4 = PI * 4;
142 vector<Point> pts(n);
143
144 for(size_t i = 0; i < n; ++i)
145 pts[i] = {int(-std::cos(PI_4 / n * i + a) * r + pt.X),
146 int(std::sin(PI_4 / n * i + a) * r + pt.Y)};
147 DrawPolygon(g, bounds, pts.cbegin(), pts.cend(), c);
148 }
150
152 const char TU_Explorer_Main[]{R"NPL(root
153 ($type "Panel")($bounds "0 0 256 192")
154 (lblTitle
155 ($type "Label")($bounds "16 20 220 22"))
156 (lblPath
157 ($type "Label")($bounds "8 48 240 48"))
158 (lblInfo
159 ($type "Label")($bounds "8 100 240 64"))
160 )NPL"};
162 const char TU_Explorer_Sub[]{R"NPL(root
163 ($type "Panel")($bounds "0 0 256 192")
164 (fbMain
165 ($type "FileBox")($bounds "0 0 256 170"))
166 (btnOK
167 ($type "Button")($bounds "170 170 64 22"))
168 (btnMenu
169 ($type "Button")($bounds "0 170 72 22"))
170 (pnlSetting
171 ($type "Panel")($bounds "10 40 224 100")($z 128)
172 (ddlStyle
173 ($type "DropDownList")($bounds "10 24 80 22"))
174 (rbTxt
175 ($type "RadioButton")($bounds "120 18 100 18"))
176 (rbHex
177 ($type "RadioButton")($bounds "120 36 100 18"))
178 (cbFPS
179 ($type "CheckButton")($bounds "10 60 72 18"))
180 (btnPrevBackground
181 ($type "Button")($bounds "120 60 30 22"))
182 (btnNextBackground
183 ($type "Button")($bounds "164 60 30 22"))
184 )
185 (pnlTest1
186 ($type "Panel")($bounds "10 20 224 144")($z 128)
187 (tcTest1
188 ($type "TabControl")
189 ($bounds "3 3 218 138")
190 (pnlPage1
191 ($type "Panel")
192 (btnEnterTest
193 ($type "Button")($bounds "8 32 104 22"))
194 (lblDragTest
195 ($type "Label")($bounds "4 4 104 22"))
196 )
197 (pnlPage2
198 ($type "Panel")
199 (btnTestAni
200 ($type "Button")($bounds "8 32 104 22"))
201 )
202 (pnlPage3
203 ($type "Panel")
204 (tbTest
205 ($type "TextBox")($bounds "8 4 104 22"))
206 (btnTestEx
207 ($type "Button")($bounds "8 32 104 22"))
208 (cbDisableSetting
209 ($type "CheckButton")($bounds "8 64 104 22"))
210 (cbShowTextBoxContent
211 ($type "CheckButton")($bounds "8 88 104 22"))
212 )
213 )
214 )
215 )NPL"};
216
217 } // unnamed namespace;
218
219
220 IO::Path
221 FetchDefaultShellDirectory()
222 {
223 #if YCL_Android
224 return
225 Path(AccessChild<string>(FetchRoot()["YFramework"], "DataDirectory"));
226 #else
227 return Path(FetchCurrentWorkingDirectory<char16_t>(IO::MaxPathLength));
228 #endif
229 }
230
231 SwitchScreensButton::SwitchScreensButton(ShlDS& shl, const Point& pt)
232 : Button({pt, {22, 22}}, 60),
233 shell(shl)
234 {
235 yunseq(
236 Text = u"％",
237 FetchEvent<Click>(*this) += [this]{
238 shell.get().SwapScreens();
239 }
240 );
241 }
242 ImplDeDtor(SwitchScreensButton)
243
244
245 ShlExplorer::ShlExplorer(const IO::Path& pth,
246 const shared_ptr<Desktop>& h_dsk_up, const shared_ptr<Desktop>& h_dsk_dn)
247 : ShlDS(h_dsk_up, h_dsk_dn),
248 dynWgts_Main(FetchWidgetLoader(), TU_Explorer_Main),
249 dynWgts_Sub(FetchWidgetLoader(), TU_Explorer_Sub),
250 fpsCounter(std::chrono::milliseconds(500)),
251 btnSwitchMain(*this, {234, 170}), btnSwitchSub(*this, {234, 170})
252 {
253 using namespace std::placeholders;
254 using ystdex::bind1;
255 static const struct Init
256 {
257 Init()
258 {
259 YTraceDe(Debug, "First time to load extra styles.");
260 Styles::InitExStyles();
261 }
262 } init;
263 static int up_i(1);
264 auto& dsk_m(GetMainDesktop());
265 auto& dsk_s(GetSubDesktop());
266 auto& node(dynWgts_Main.WidgetNode);
267 DeclDynWidget(Panel, root, node)
268 DeclDynWidgetNode(Label, lblTitle)
269 DeclDynWidgetNode(Label, lblPath)
270 DeclDynWidgetNode(Label, lblInfo)
271 auto& node_sub(dynWgts_Sub.WidgetNode);
272 DeclDynWidget(Panel, root_sub, node_sub)
273 DeclDynWidgetN(FileBox, fbMain, node_sub)
274 DeclDynWidgetN(Button, btnOK, node_sub)
275 DeclDynWidgetN(Button, btnMenu, node_sub)
276 auto& node_pnlSetting(AccessWidgetNode(node_sub, "pnlSetting"));
277 DeclDynWidget(Panel, pnlSetting, node_pnlSetting)
278 DeclDynWidgetN(DropDownList, ddlStyle, node_pnlSetting)
279 DeclDynWidgetN(RadioButton, rbTxt, node_pnlSetting)
280 DeclDynWidgetN(RadioButton, rbHex, node_pnlSetting)
281 DeclDynWidgetN(CheckButton, cbFPS, node_pnlSetting)
282 DeclDynWidgetN(Button, btnPrevBackground, node_pnlSetting)
283 DeclDynWidgetN(Button, btnNextBackground, node_pnlSetting)
284 auto& node_pnlTest1(AccessWidgetNode(node_sub, "pnlTest1"));
285 auto& node_tcTest1(AccessWidgetNode(node_pnlTest1, "tcTest1"));
286 DeclDynWidget(Panel, pnlTest1, node_pnlTest1)
287 DeclDynWidgetN(TabControl, tcTest1, node_pnlTest1)
288 auto& node_pnlPage1(AccessWidgetNode(node_tcTest1, "pnlPage1"));
289 auto& node_pnlPage2(AccessWidgetNode(node_tcTest1, "pnlPage2"));
290 auto& node_pnlPage3(AccessWidgetNode(node_tcTest1, "pnlPage3"));
291 DeclDynWidget(Panel, pnlPage2, node_pnlPage2)
292 DeclDynWidgetN(Label, lblDragTest, node_pnlPage1)
293 DeclDynWidgetN(Button, btnEnterTest, node_pnlPage1)
294 DeclDynWidgetN(Button, btnTestAni, node_pnlPage2)
295 DeclDynWidgetN(TextBox, tbTest, node_pnlPage3)
296 DeclDynWidgetN(Button, btnTestEx, node_pnlPage3)
297 DeclDynWidgetN(CheckButton, cbDisableSetting, node_pnlPage3)
298 DeclDynWidgetN(CheckButton, cbShowTextBoxContent, node_pnlPage3)
299 const auto f_refresh_current([&]{
300 lblPath.Text = fbMain.GetPath().Verify(),
301 Invalidate(lblPath),
302 Enable(btnOK, CheckReaderEnability(fbMain, rbHex));
303 });
304
305 YTraceDe(Debug, "Initialization of ShlExplorer began.");
306 AddButtonToTabBar(tcTest1, node_pnlTest1, "btnTab1", u"基本测试");
307 AddButtonToTabBar(tcTest1, node_pnlTest1, "btnTab2", u"动画测试");
308 AddButtonToTabBar(tcTest1, node_pnlTest1, "btnTab3", u"附加测试");
309 tcTest1.UpdateTabPages();
310 p_border.reset(new BorderResizer(pnlTest1, 4)),
311 p_ChkFPS = &cbFPS,
312 tpDefault.Text = u"请输入文本",
313 tpDefault.BindByFocus(tbTest, &TextPlaceholder::SwapTextBox<TextBox>),
314 tpDefault.Font.SetStyle(FontStyle::Italic),
315 pnlAbout.OnCommand += [this]{
316 YTraceDe(Informative, "System information panel request received.");
317 pnlSysInfo.UpdateContents();
318 Show(pnlSysInfo);
319 };
320 dsk_m += root,
321 dsk_m.Add(btnSwitchMain, 96),
322 dsk_s += root_sub,
323 // XXX: NPL script should be used to describe Z-order variable.
324 dsk_s.Add(btnSwitchSub, 96),
325 AddWidgetsZ(root_sub, DefaultWindowZOrder, pnlAbout, pnlSysInfo);
326 fbMain.SetRenderer(make_unique<BufferedRenderer>(true)),
327 pnlSetting.SetRenderer(make_unique<BufferedRenderer>()),
328 pnlTest1.SetRenderer(make_unique<BufferedRenderer>()),
329 ystdex::unseq_apply(bind1(SetVisibleOf, false), pnlSetting, pnlTest1,
330 pnlAbout, pnlSysInfo),
331 ystdex::unseq_apply(bind(&ShlDS::WrapForSwapScreens, this, _1,
332 ref(SwapMask)), dsk_m, dsk_s),
333 ani.Reset(make_observer(&pnlTest1)),
334 ddlStyle.SetList(FetchVisualStyleNames()),
335 rbTxt.ShareTo(rbHex),
336 rbTxt.Select(),
337 ystdex::unseq_apply(bind1(Enable, false), btnOK, btnPrevBackground),
338 yunseq(
339 dsk_m.Background = ImageBrush(FetchImage(0)),
340 dsk_s.Background
341 = SolidBrush(FetchGUIConfiguration().Colors[Styles::Panel]),
342 root.Background = nullptr,
343 root_sub.Background = nullptr,
344 lblTitle.Text = G_APP_NAME,
345 lblPath.AutoWrapLine = true, lblPath.Text = pth.Verify(),
346 lblInfo.AutoWrapLine = true, lblInfo.Text = u"文件列表：请选择一个文件。",
347 // TODO: Show current working directory properly.
348 btnOK.Text = u"确定(A)",
349 #if YCL_Win32
350 btnMenu.Text = u"菜单(Ctrl)",
351 #else
352 btnMenu.Text = u"菜单(Start)",
353 #endif
354 tbTest.Text = u"测试文本框输入字符串",
355 tbTest.MaskChar = u'●',
356 tbTest.MaxLength = 8,
357 ddlStyle.Text = [](const TextList::ListType& lst){
358 const auto& name(FetchGUIConfiguration().Styles.GetCurrent()->first);
359
360 YAssert(!lst.empty(), "Invalid list found.");
361 return name.empty() ? lst[0] : String(name);
362 }(ddlStyle.GetList()),
363 rbTxt.Text = u"文本阅读",
364 rbHex.Text = u"十六进制浏览",
365 cbFPS.Text = u"显示 FPS",
366 pnlSetting.Background = SolidBrush({160, 252, 160}),
367 pnlTest1.Background = SolidBrush({248, 248, 120}),
368 lblDragTest.HorizontalAlignment = TextAlignment::Left,
369 // btnTestEx.Enabled = {},
370 btnTestEx.Font.SetStyle(FontStyle::Bold | FontStyle::Italic),
371 btnTestEx.Text = u"附加测试",
372 btnTestEx.HorizontalAlignment = TextAlignment::Left,
373 btnTestEx.VerticalAlignment = TextAlignment::Down,
374 btnTestAni.Text = u"开始动画",
375 cbDisableSetting.Text = u"禁用设置选择框",
376 cbShowTextBoxContent.Text = u"显示文本框内容",
377 lblDragTest.Text = u"移动设置面板位置",
378 btnEnterTest.Font.SetStyle(FontStyle::Italic),
379 btnEnterTest.Text = u"边界测试",
380 btnEnterTest.HorizontalAlignment = TextAlignment::Right,
381 btnEnterTest.VerticalAlignment = TextAlignment::Up,
382 btnPrevBackground.Font.SetStyle(FontStyle::Bold),
383 btnPrevBackground.Text = u"<<",
384 btnNextBackground.Font.SetStyle(FontStyle::Bold),
385 btnNextBackground.Text = u">>",
386 fbMain.SetPath(pth),
387 dsk_s.BoundControlPtr = [&](const KeyInput& k) -> observer_ptr<IWidget>{
388 if(k.count() == 1)
389 {
390 if(k[YCL_KEY(A)])
391 return make_observer(&btnOK);
392 }
393 else if(CheckMenuKey(k))
394 return make_observer(&btnMenu);
395 return {};
396 },
397 FetchEvent<KeyUp>(dsk_s) += OnKey_Bound_TouchUp,
398 FetchEvent<KeyDown>(dsk_s) += OnKey_Bound_TouchDown,
399 FetchEvent<KeyDown>(dsk_s) += [&](KeyEventArgs&& e){
400 if(e.Strategy != RoutedEventArgs::Bubble && e.GetKeys()[YCL_KEY(X)])
401 {
402 SwitchVisibleToFront(pnlSetting);
403 RequestFocusCascade(pnlSetting);
404 }
405 },
406 // TODO: Improve UI action when %ViewChanged being called?
407 fbMain.GetSelected() += f_refresh_current,
408 fbMain.GetViewChanged() += f_refresh_current,
409 FetchEvent<Click>(btnOK) += [&]{
410 if(fbMain.IsSelected())
411 {
412 const auto& fb_path(fbMain.GetPath());
413 // const string s(fb_path);
414 const auto category(ClassifyFile(fb_path));
415
416 if(category == FileCategory::Text
417 || category == FileCategory::Binary)
418 {
419 const auto h_up(GetMainDesktopHandle());
420 const auto h_dn(GetSubDesktopHandle());
421 const bool b(category == FileCategory::Text
422 && rbTxt.IsSelected());
423
424 PostTask([=]{
425 ResetDSDesktops(*h_up, *h_dn);
426 NowShellTo(b ? shared_ptr<Shell>(make_shared<ShlTextReader>(
427 fb_path, h_up, h_dn)) : shared_ptr<Shell>(
428 make_shared<ShlHexBrowser>(fb_path, h_up, h_dn)));
429 }, 0xF8);
430 }
431 }
432 },
433 FetchEvent<Click>(cbFPS) += [this]{
434 SetInvalidationOf(GetSubDesktop());
435 },
436 FetchEvent<Click>(rbHex) += [&]{
437 Enable(btnOK, CheckReaderEnability(fbMain, rbHex));
438 SetInvalidationOf(GetSubDesktop());
439 },
440 FetchEvent<Move>(pnlSetting) += [&]{
441 lblDragTest.Text = String(
442 make_string_view(to_string(GetLocationOf(pnlSetting)) + ';'));
443 Invalidate(lblDragTest);
444 },
445 FetchEvent<TouchHeld>(pnlSetting) += OnTouchHeld_Dragging,
446 #if YCL_DS
447 FetchEvent<TouchDown>(pnlSetting) += [&]{
448 struct ::mallinfo t(::mallinfo());
449
450 lblInfo.Text = sfmt("%d,%d,%d,%d,%d;", t.arena, t.ordblks, t.uordblks,
451 t.fordblks, t.keepcost);
452 Invalidate(lblInfo);
453 },
454 #endif
455 FetchEvent<Click>(pnlSetting) += [&]{
456 yunseq(
457 lblDragTest.ForeColor = GenerateRandomColor(),
458 lblTitle.ForeColor = GenerateRandomColor()
459 );
460 Invalidate(pnlSetting);
461 },
462 FetchEvent<TouchHeld>(pnlTest1) += OnTouchHeld_Dragging,
463 FetchEvent<Paint>(pnlPage2) += [&, this](PaintEventArgs&& e){
464 auto& g(e.Target);
465 const auto& pt(GetLocationOf(pnlTest1));
466 auto& bounds(e.ClipArea);
467
468 DrawStar(g, bounds, ColorSpace::Red, pt + Point{96, 96}, 48, rad);
469 DrawStar(g, bounds, ColorSpace::Green, pt + Point{96, 96}, 48,
470 rad + PI);
471 if(ani.GetConnectionRef().Ready)
472 {
473 rad += 0.02F;
474 if(rad > PI_2)
475 rad -= PI_2;
476 }
477 UpdateClipArea(e, {{}, GetSizeOf(e.GetSender())});
478 },
479 FetchEvent<Click>(btnTestEx) += [&](CursorEventArgs&& e){
480 const auto& k(e.GetKeys());
481 auto& btn(ystdex::polymorphic_downcast<Button&>(e.GetSender()));
482
483 if(lblTitle.Background)
484 lblTitle.Background = nullptr;
485 else
486 lblTitle.Background = SolidBrush(GenerateRandomColor());
487 lblInfo.Text = btn.Text + u", "
488 + String(to_string(FetchImageLoadTime())) + u";\n"
489 + String(make_string_view(k.to_string()));
490 InvalidateWidgets(lblTitle, lblInfo);
491 },
492 FetchEvent<Click>(btnTestAni) += [&]{
493 auto& conn(ani.GetConnectionRef());
494
495 if(conn.Ready)
496 yunseq(btnTestAni.Text = u"开始动画", conn.Ready = {});
497 else
498 {
499 yunseq(btnTestAni.Text = u"停止动画", conn.Ready = true),
500 ani.Start();
501 }
502 Invalidate(btnTestAni);
503 },
504 FetchEvent<Enter>(btnEnterTest) += [](CursorEventArgs&& e){
505 auto& btn(ystdex::polymorphic_downcast<Button&>(e.GetSender()));
506
507 btn.Text = u"Enter: " + String(make_string_view(to_string(e.Position)));
508 Invalidate(btn);
509 },
510 FetchEvent<Leave>(btnEnterTest) += [&](CursorEventArgs&& e){
511 btnEnterTest.Text = u"Leave: "
512 + String(make_string_view(to_string(e.Position)));
513 Invalidate(btnEnterTest);
514 },
515 FetchEvent<Click>(btnMenu) += [this]{
516 auto& mnu(*p_m0);
517
518 if(mhMain.IsShowing(mnu))
519 {
520 mhMain.HideAll();
521 mnu.ClearSelected();
522 }
523 else
524 mhMain.Show(mnu);
525 Invalidate(mnu);
526 },
527 FetchEvent<Click>(btnPrevBackground) += [&]{
528 if(up_i > 0)
529 {
530 --up_i;
531 Enable(btnNextBackground);
532 }
533 if(up_i == 0)
534 Enable(btnPrevBackground, false);
535 GetMainDesktop().Background = ImageBrush(FetchImage(size_t(up_i)));
536 ystdex::unseq_apply(SetInvalidationOf, GetMainDesktop(),
537 GetSubDesktop());
538 },
539 FetchEvent<Click>(btnNextBackground) += [&]{
540 if(size_t(up_i + 1) < Image_N)
541 {
542 ++up_i;
543 Enable(btnPrevBackground);
544 }
545 if(size_t(up_i + 1) == Image_N)
546 Enable(btnNextBackground, false);
547 GetMainDesktop().Background = ImageBrush(FetchImage(size_t(up_i)));
548 SetInvalidationOf(GetMainDesktop()),
549 SetInvalidationOf(GetSubDesktop());
550 },
551 cbDisableSetting.Ticked += [&](CheckBox::TickedArgs&& e){
552 ystdex::unseq_apply(bind1(SetEnabledOf, !e), cbFPS, rbTxt, rbHex);
553 InvalidateWidgets(cbFPS, rbTxt, rbHex);
554 },
555 cbShowTextBoxContent.Ticked += [&](CheckBox::TickedArgs&& e){
556 (tpDefault.GetCapturedPtr().get() == &tbTest ? tpDefault.MaskChar
557 : tbTest.MaskChar) = e ? char32_t() : u'●';
558 Invalidate(tbTest);
559 },
560 ddlStyle.GetConfirmed() += [&]{
561 FetchGUIConfiguration().Styles.Switch(ddlStyle.Text.GetMBCS());
562 InvalidateWidgets(dsk_m, dsk_s);
563 }
564 );
565 RequestFocusCascade(fbMain),
566 ystdex::unseq_apply(SetInvalidationOf, dsk_m, dsk_s);
567
568 {
569 p_m0.reset(new Menu({}, make_shared<Menu::ListType, String>(
570 {u"测试", u"关于", u"设置(X)", u"退出"})));
571 p_m1.reset(new Menu({},
572 make_shared<Menu::ListType, String>({u"项目1", u"项目2"})));
573 auto& m0(*p_m0);
574 auto& m1(*p_m1);
575
576 m0.Confirmed += [&](IndexEventArgs&& e){
577 switch(e.Value)
578 {
579 case 1U:
580 Show(pnlAbout);
581 break;
582 case 2U:
583 SwitchVisibleToFront(pnlSetting);
584 break;
585 case 3U:
586 YSLib::PostQuitMessage(0);
587 }
588 },
589 m1.Confirmed += [&](IndexEventArgs&& e){
590 #if YCL_Win32
591 Windows::TestFramework(e.Value);
592 #endif
593 if(e.Value == 0)
594 SwitchVisibleToFront(pnlTest1);
595 },
596 AddWidgetsZ(GetSubDesktop(), DefaultMenuZOrder, m0, m1),
597 mhMain += m0, mhMain += m1,
598 m0 += {0u, make_observer(&m1)};
599 mhMain.Roots[btnMenu] = make_observer(&m0);
600 ystdex::unseq_apply(ResizeForContent, m0, m1),
601 // XXX: Conversion to 'SPos' might be implementation-defined.
602 SetLocationOf(m0,
603 Point(btnMenu.GetX(), btnMenu.GetY() - SPos(m0.GetHeight())));
604 //m0.SetWidth(btnMenu.GetWidth() + 20);
605 }
606 YTraceDe(Debug, "Initialization of ShlExplorer ended.");
607 }
608
609 void
610 ShlExplorer::OnPaint()
611 {
612 // NOTE: Hack for performance.
613 // DeclDynWidgetN(CheckButton, cbFPS, dynWgts_Sub.WidgetNode, "pnlSetting")
614 auto& cbFPS(*p_ChkFPS);
615
616 // NOTE: Overriding member function %OnInput using %SM_TASK is also valid
617 // because the %SM_Input message is sent continuously, but less efficient.
618 if(cbFPS.IsTicked())
619 {
620 using namespace ColorSpace;
621 const auto t(fpsCounter.Refresh());
622
623 if(t != 0)
624 {
625 const auto g(ystdex::polymorphic_downcast<BufferedRenderer&>(
626 GetMainDesktop().GetRenderer()).GetContext());
627 static yconstexpr const Rect r(176, 0, 80, 20);
628 char strt[20];
629
630 std::sprintf(strt, "FPS: %u.%03u", unsigned(t / 1000),
631 unsigned(t % 1000));
632 FillRect(g, r, Blue);
633 DrawText(g, r, strt, DefaultMargin, White, false);
634 bUpdateUp = true;
635 }
636 }
637 }
638
639 } // namespace YReader;
640
YSLib::IO::Path
路径。
Definition: YSLib/Service/FileSystem.h:217
YSLib::UI::SetLocationOf
YF_API void SetLocationOf(IWidget &, const Point &)
设置部件左上角所在位置（相对容器的偏移坐标）。
Definition: YWidget.cpp:76
YReader::SwitchScreensButton::SwitchScreensButton
SwitchScreensButton(ShlDS &, const Point &)
Definition: ShlExplorer.cpp:231
YSLib::FetchMIMEBiMapping
YF_API MIMEBiMapping & FetchMIMEBiMapping()
取 MIME 类型名和文件扩展名双向映射对象。
Definition: Initialization.cpp:836
YB_ATTR_nodiscard
#define YB_ATTR_nodiscard
标记返回值不被忽略的属性。
Definition: ydef.h:715
YSLib::UI::Enable
bool Enable(IWidget &wgt, bool b)
Definition: YControl.cpp:91
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:112
Path
IO::Path Path
Definition: Initialization.cpp:116
platform::KeyCodes::DS::Down
@ Down
Definition: Keys.h:224
YReader::FetchDefaultShellDirectory
IO::Path FetchDefaultShellDirectory()
取默认 Shell 起始路径。
Definition: ShlExplorer.cpp:221
ShlExplorer.h
文件浏览器。
YSLib::IO::GetExtensionOf
_tString GetExtensionOf(const _tString &fname)
取扩展名。
Definition: YSLib/Service/FileSystem.h:476
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
YSLib::Drawing::FillRect
c YF_API void FillRect(const Graphics &g, const Rect &r, Color c)
填充标准矩形。
Definition: YDraw.cpp:150
CHRLib::c
c
Definition: CharacterProcessing.h:84
YSLib::UI::OnKey_Bound_TouchUp
YF_API void OnKey_Bound_TouchUp(KeyEventArgs &&)
处理按键事件：按键-指针设备接触结束。
Definition: YControl.cpp:160
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:1072
ystdex::bind1
auto bind1(_func &&f, _tParams &&... args) -> decltype(std::bind(std::forward< decltype(f)>(f), std::placeholders::_1, std::forward< decltype(args)>(args)...))
复合调用 std::bind 和 std::placeholders::_1 。
Definition: functional.hpp:53
YSLib::PostQuitMessage
YF_API void PostQuitMessage(int=0, Messaging::Priority p=DefaultQuitPriority)
以指定错误码和优先级发起 Shell 终止请求。
Definition: YApplication.cpp:87
YSLib::Drawing::Graphics
GGraphics< BitmapPtr > Graphics
Definition: YGraphics.h:163
YReader::ShlExplorer::ShlExplorer
ShlExplorer(const IO::Path &=FetchDefaultShellDirectory(), const shared_ptr< Desktop > &={}, const shared_ptr< Desktop > &={})
构造：使用指定路径和上下桌面。
YSLib::UI::FetchVisualStyleNames
YF_API shared_ptr< TextList::ListType > FetchVisualStyleNames(String=u"<Default>")
取视觉样式名称。
Definition: ShellHelper.cpp:161
YSLib::shared_ptr< Shell >
shared_ptr< Shell >
Definition: GUIApplication.h:308
YReader
Definition: About.h:34
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
YSLib::Drawing::ImageTag::to_string
YB_ATTR_nodiscard YF_API YB_PURE string to_string(const ImageTag &, ImageMetadataModel)
取按指定图像元数据模型解释的标签值字符串表示。
Definition: Image.cpp:707
ystdex::unseq_apply
void unseq_apply(_func &&f, _tParams &&... args)
无序调用。
Definition: function.hpp:314
YSLib::Consoles::White
@ White
Definition: YConsole.h:68
YSLib::UI::Button
按钮。
Definition: Button.h:127
YReader::ImplDeDtor
ImplDeDtor(AboutPanel) SystemInformationPanel
Definition: About.cpp:103
YReader::FetchImageLoadTime
YB_ATTR_nodiscard YB_PURE double FetchImageLoadTime()
Definition: Shells.cpp:118
G_APP_NAME
#define G_APP_NAME
Definition: Shells.h:56
YSLib::IO::int
YF_API int
Definition: File.h:51
YSLib::Consoles::Blue
@ Blue
Definition: YConsole.h:62
YSLib::UI::InvalidateWidgets
void InvalidateWidgets(_tWidgets &... wgts)
向无效化部件。
Definition: YWidget.h:534
YSLib::UI::GetSizeOf
YB_ATTR_nodiscard YB_PURE pt pt Y YB_ATTR_nodiscard YB_PURE const IWidget &wgt const IWidget &wgt GetSizeOf
无效化：使相对部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.h:165
YReader::SwitchScreensButton
Definition: ShlExplorer.h:46
ShlReader.h
Shell 阅读器框架。
YSLib::UI::DefaultWindowZOrder
const ZOrder DefaultWindowZOrder(128)
默认窗口 Z 顺序值。
YSLib::Consoles::Red
@ Red
Definition: YConsole.h:65
YCL_KEY
#define YCL_KEY(X)
Definition: Input.h:45
DeclDynWidgetN
#define DeclDynWidgetN(_t, _n,...)
声明指定节点下的按相同名称访问的动态部件。
Definition: Loader.h:309
platform::KeyCategory::Menu
@ Menu
表示菜单键（如 Menu 和 Win ）。
Definition: Keys.h:131
YSLib::Drawing::g
The boundary is out of the const Graphics & g
Definition: YDraw.h:161
YReader::FetchWidgetLoader
YB_ATTR_nodiscard YB_PURE WidgetLoader & FetchWidgetLoader()
Definition: Shells.cpp:125
YSLib::UI::Invalidate
YF_API void Invalidate(IWidget &, const Rect &)
无效化：使相对部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.cpp:108
YSLib::UI::Show
YF_API void Show(IWidget &)
显示部件。
Definition: YWidget.cpp:202
YSLib::UI::Styles::Panel
@ Panel
面板背景。
Definition: YStyle.h:312
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:405
YSLib::Drawing::Point
GBinaryGroup< SPos > Point
屏幕二维点（直角坐标表示）。
Definition: YGDIBase.h:520
YSLib::UI::IndexEventArgs
GValueEventArgs< size_t > IndexEventArgs
索引事件。
Definition: ListControl.h:47
platform::Descriptions::Informative
@ Informative
Definition: YCommon.h:185
std
Definition: optional.h:982
ystdex::sfmt
_tString sfmt(const typename string_traits< _tString >::value_type *fmt,...)
以 C 标准输出格式的输出 basic_string 实例的对象。
Definition: string.hpp:2028
YSLib::UI::FetchGUIConfiguration
GUIConfiguration & FetchGUIConfiguration()
Definition: YGUI.cpp:517
functional.hpp
函数和可调用对象。
platform::KeyCodes::DS::X
@ X
Definition: Keys.h:229
YSLib::i
return i
Definition: YCoreUtilities.h:177
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1535
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:407
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:44
YSLib::FetchRoot
YF_API ValueNode & FetchRoot() ynothrow
取值类型根节点。
Definition: Initialization.cpp:816
YReader::FetchImage
YB_ATTR_nodiscard shared_ptr< Image > & FetchImage(size_t)
Definition: Shells.cpp:87
YCL_KEY_Start
#define YCL_KEY_Start
Definition: Input.h:46
platform::KeyCodes::DS::Up
@ Up
Definition: Keys.h:223
YSLib::Drawing::Rect
屏幕标准矩形：表示屏幕矩形区域。
Definition: YGDIBase.h:788
platform::KeyInput
std::bitset< KeyBitsetWidth > KeyInput
按键并行位宽。
Definition: Keys.h:67
YSLib::UI::Styles::InitExStyles
YF_API void InitExStyles()
初始化扩展样式。
Definition: ExStyle.cpp:236
YSLib::UI::SwitchVisibleToFront
YF_API void SwitchVisibleToFront(IWidget &)
切换部件显示状态并请求提升至前端。
Definition: ShellHelper.cpp:153
Color
Pixel Color
Definition: CharRenderer.cpp:59
ystdex::tolower
char tolower(char c)
转换大小写字符。
Definition: cctype.h:153
ystdex::lref::get
_type & get() const
Definition: ref.hpp:96
YSLib::Drawing::bounds
The boundary is out of the const Rect & bounds
Definition: YDraw.h:127
YSLib::Drawing::DrawText
YF_API void DrawText(const Graphics &g, TextState &ts, const String &str, bool line_wrap)
绘制文本。
Definition: TextRenderer.cpp:246
YSLib::UI::DefaultMenuZOrder
yconstexpr const ZOrder DefaultMenuZOrder(224)
默认菜单 Z 顺序值。
NPL::SXML::ParseOption::String
@ String
YReader::SwitchScreensButton::shell
lref< ShlDS > shell
Definition: ShlExplorer.h:49
YSLib::Drawing::DrawPolygon
void DrawPolygon(Graphics &g, const Rect &bounds, _tIn first, _tIn last, Color c)
描画多边形。
Definition: YDraw.h:214
platform::KeyCodes::Win32::Empty
@ Empty
Definition: Keys.h:282
YSLib::UI::SetEnabledOf
SetEnabledOf
Definition: YControl.h:113
YReader::Image_N
yconstexpr const size_t Image_N(3)
YReader::AddButtonToTabBar
void AddButtonToTabBar(TabControl &, ValueNode &, const string &, const String &, SDst=64)
向标签栏和节点添加按钮。
Definition: Shells.cpp:154
YSLib::UI::MLabel::Text
String Text
标签文本。
Definition: Label.h:94
DeclDynWidgetNode
#define DeclDynWidgetNode(_t, _n)
声明名称为 node 的节点下的按相同名称访问的动态部件。
Definition: Loader.h:315
DeclDynWidget
#define DeclDynWidget(_t, _n,...)
声明动态部件。
Definition: Loader.h:302
YSLib::UI::TextList::ResizeForContent
YF_API void ResizeForContent(TextList &)
根据文本内容调整文本列表大小。
Definition: ListControl.cpp:414
YSLib::PostTask
void PostTask(_fCallable &&f, Messaging::Priority prior=Messaging::NormalPriority)
通过消息队列部署后任务。
Definition: Task.h:43
ystdex::ends_with
bool ends_with(const _tRange1 &input, const _tRange2 &test, _fPred comp)
判断第一参数指定的串是否以第二参数结束。
Definition: string.hpp:1195
YSLib::UI::AddWidgetsZ
void AddWidgetsZ(_tCon &con, ZOrder z, _tWidgets &... wgts)
向部件容器添加指定 Z 顺序的子部件。
Definition: YUIContainer.h:460
YSLib::UI::SetInvalidationOf
void SetInvalidationOf(IWidget &wgt)
Definition: YWidget.cpp:63
YSLib::Drawing::DefaultMargin
yconstexpr const Padding DefaultMargin(2, 2, 2, 2)
默认边距。
platform::KeyCodes::DS::Left
@ Left
Definition: Keys.h:222
YSLib::UI::RequestFocusCascade
YF_API void RequestFocusCascade(IWidget &)
级联请求部件及上层容器焦点。
Definition: YFocus.cpp:137
YSLib::IO::MaxPathLength
yconstexpr const size_t MaxPathLength(yimpl(1<< 10))
默认目录路径长度。
YSLib::UI::GetLocationOf
YB_ATTR_nodiscard YB_PURE pt pt Y YB_ATTR_nodiscard YB_PURE const IWidget &wgt GetLocationOf
Definition: YWidget.h:157
YSLib::Consoles::Green
@ Green
Definition: YConsole.h:63
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:413
platform::SPos
std::int16_t SPos
屏幕坐标度量。
Definition: Video.h:43
ystdex::make_string_view
basic_string_view< typename string_traits< _tString >::value_type, typename string_traits< _tString >::traits_type > make_string_view(const _tString &str)
从字符串创建 basic_string_view 对象。
Definition: string.hpp:814
ystdex::path_category::node
@ node
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:1199
YSLib::Drawing::char32_t
YB_ATTR_nodiscard YB_PURE tr TextRegion &tr char32_t
Definition: TextLayout.h:93
YSLib::UI::OnKey_Bound_TouchDown
YF_API void OnKey_Bound_TouchDown(KeyEventArgs &&)
处理按键事件：按键-指针设备接触开始。
Definition: YControl.cpp:166
platform::KeyCodes::DS::Right
@ Right
Definition: Keys.h:221
ystdex::ref
void ref(const _type &&)=delete
YSLib::IO::ClassifyNode
const Path &pth const string &pth vector< String > &YF_API NodeCategory ClassifyNode(const Path &)
按文件系统节点类别对路径分类。
Definition: YSLib/Service/FileSystem.cpp:225
YSLib::a
YB_PURE const _type * a
Definition: YCoreUtilities.h:168
YSLib::DS::ResetDSDesktops
YF_API void ResetDSDesktops(Desktop &, Desktop &)
以默认屏幕复位两个桌面。
Definition: Shell_DS.cpp:52
platform::Descriptions::Debug
@ Debug
Definition: YCommon.h:186
YSLib::UI::OnTouchHeld_Dragging
YF_API void OnTouchHeld_Dragging(CursorEventArgs &&)
处理屏幕接触移动事件：拖放按下部件。
Definition: YControl.cpp:145