30 #include YFM_NPL_Lexical
46 enum MNU_READER : Menu::IndexType
64 btnMenu({4, 12, 16, 16}), btnSetting({24, 12, 16, 16}),
65 btnInfo({44, 12, 16, 16}), btnBookmark({64, 12, 16, 16}),
66 btnReturn({84, 12, 16, 16}),
67 btnPrev({104, 12, 16, 16}), btnNext({124, 12, 16, 16}),
68 pbReader({4, 0, 248, 8}), lblProgress({216, 12, 40, 16})
71 SetRenderer(make_unique<BufferedRenderer>()),
72 unseq_apply(ContainerSetter(*
this), btnMenu, btnSetting, btnInfo,
73 btnBookmark, btnReturn, btnPrev, btnNext, pbReader, lblProgress);
81 pbReader.ForeColor =
Color(192, 192, 64),
82 lblProgress.SetRenderer(make_unique<BufferedRenderer>()),
83 lblProgress.Background =
nullptr,
84 lblProgress.Font.SetSize(12),
89 ReaderBox::InitializeProgress()
99 const auto ts(reader.GetTextSize());
103 const auto tp(reader.GetTopPosition());
106 std::sprintf(str,
"%2u%%", tp * 100 / ts);
114 InitializeProgress();
117 InitializeProgress();
124 lblEncoding({4, 20, 192, 18}),
125 lblSize({4, 40, 192, 18}),
126 lblTop({4, 60, 192, 18}),
127 lblBottom({4, 80, 192, 18})
129 unseq_apply(ContainerSetter(*
this), lblEncoding, lblSize);
156 :
Panel(
Size(MainScreenWidth, MainScreenHeight)),
157 lblPath({8, 20, 240, 16}),
158 lblSize({8, 40, 240, 16}),
159 lblAccessTime({8, 60, 240, 16}),
160 lblModifiedTime({8, 80, 240, 16}),
161 lblOperations({8, 120, 240, 16})
163 Background = SolidBrush(ColorSpace::Silver);
165 lblOperations.Text =
"<↑↓> 滚动一行 <LR> 滚动一屏 <B>退出";
167 lblOperations.Text =
"<↑↓> 滚动一行 <LR> 滚动一屏 <Esc>退出";
169 AddWidgets(*
this, lblPath, lblSize, lblAccessTime, lblModifiedTime,
175 const shared_ptr<Desktop>& h_dsk_up,
const shared_ptr<Desktop>& h_dsk_dn)
176 : ShlDS(h_dsk_up, h_dsk_dn),
177 CurrentPath(pth), fBackgroundTask(), bExit()
189 const auto h_up(GetMainDesktopHandle());
190 const auto h_dn(GetSubDesktopHandle());
209 int)
>(std::isspace), [&](string::iterator b, string::iterator e){
214 catch(std::invalid_argument&)
216 catch(std::out_of_range&)
220 catch(std::exception& e)
231 .at(
"ReaderSetting").GetContainer());
233 catch(std::exception& e)
241 PostMessage<SM_Paint>(0xE0, {});
255 for(
const auto& pos : bookmarks)
263 catch(std::exception& e)
277 catch(std::exception& e)
284 reader_box_shown(
IsVisible(shl.boxReader))
292 auto& shl(GetShell());
294 shl.reader.SetVisible(
true),
295 shl.boxReader.UpdateData(shl.reader),
296 shl.boxTextInfo.UpdateData(shl.reader);
305 auto& dsk_m(shl.GetMainDesktop());
306 auto& dsk_s(shl.GetSubDesktop());
311 shl.
reader.SetVisible(
false),
329 "pnlPage2",
"ddlEncoding").Text =
Encodings[i].second);
335 auto& shl(GetShell());
338 shl.pnlSetting.lblAreaUp, shl.pnlSetting.lblAreaDown);
351 const shared_ptr<Desktop>& h_dsk_up,
const shared_ptr<Desktop>& h_dsk_dn)
357 pnlSetting(), pTextFile(), mhMain(GetSubDesktop()),
358 pnlBookmark(LoadBookmarks(pth), *
this), session_ptr()
361 using namespace placeholders;
364 const auto exit_session([
this]{
368 unseq_apply(bind(SetVisibleOf, _1,
false), boxReader, boxTextInfo,
369 pnlSetting, pnlBookmark);
371 reader.ViewChanged = [
this]{
372 if(IsVisible(boxReader))
373 boxReader.UpdateData(reader);
374 if(IsVisible(boxTextInfo))
375 boxTextInfo.UpdateData(reader);
377 mhMain.Roots[&boxReader.btnMenu] = 1U,
378 FetchEvent<Click>(boxReader.btnMenu) += [
this]{
379 if(mhMain.IsShowing(1U))
383 const auto& pt(LocateForWidget(GetSubDesktop(),
386 ShowMenu(1U, Point(pt.X, pt.Y - mhMain[1U].GetHeight()));
389 FetchEvent<Click>(boxReader.btnSetting) += [
this]{
392 FetchEvent<Click>(boxReader.btnInfo) += [
this]{
395 FetchEvent<Click>(boxReader.btnBookmark) += [
this]{
398 FetchEvent<Click>(boxReader.btnReturn) += [
this]{
401 FetchEvent<Click>(boxReader.btnPrev) += [
this]{
402 UpdateReadingList(
true);
404 FetchEvent<Click>(boxReader.btnNext) += [
this]{
405 UpdateReadingList(
false);
407 FetchEvent<TouchDown>(boxReader.pbReader) += [
this](CursorEventArgs&& e){
408 const auto s(reader.GetTextSize());
411 Locate(e.Position.X *
s / boxReader.pbReader.GetWidth());
413 FetchEvent<Paint>(boxReader.pbReader) += [
this](PaintEventArgs&& e){
414 auto& pb(boxReader.pbReader);
415 const auto mval(pb.GetMaxValue());
416 const auto w(pb.GetWidth() - 2);
417 auto& pt(e.Location);
419 FillRect(e.Target, e.ClipArea, Rect(pt.X + 1 + round(pb.GetValue()
420 * w / mval), pt.Y + 1, round((reader.GetBottomPosition()
421 - GetReaderPosition()) * w / mval), pb.GetHeight() - 2),
424 FetchEvent<Click>(pnlSetting.btnClose) += exit_session,
425 FetchEvent<Click>(pnlSetting.btnOK) += [&,
this]{
426 pnlSetting >> CurrentSetting;
427 tmrScroll.Interval = CurrentSetting.GetTimerSetting();
428 Switch(pnlSetting.current_encoding),
429 reader.SetColor(CurrentSetting.FontColor),
430 reader.SetFont(CurrentSetting.Font);
432 yunseq(GetMainDesktop().Background = pnlSetting.lblAreaUp.Background,
433 GetSubDesktop().Background = pnlSetting.lblAreaDown.Background
436 for(
auto pr(boxReader.GetChildren()); pr.first != pr.second;
438 if(dynamic_cast<BufferedRenderer*>(&pr.first->GetRenderer()))
441 FetchEvent<Click>(pnlSetting.btnOK) += exit_session,
442 FetchEvent<Click>(pnlBookmark.btnClose) += exit_session,
443 FetchEvent<Click>(pnlBookmark.btnOK) += [
this]{
444 if(pnlBookmark.lbPosition.IsSelected() && Locate(
445 pnlBookmark.bookmarks[pnlBookmark.lbPosition.GetSelectedIndex()]))
446 boxReader.UpdateData(reader);
448 FetchEvent<Click>(pnlBookmark.btnOK) += exit_session
451 Menu& mnu(*(
ynew Menu({}, shared_ptr<Menu::ListType>(
new
452 Menu::ListType{
"返回",
"设置...",
"文件信息...",
"书签...",
453 "向上一行",
"向下一行",
"向上一屏",
"向下一屏"}), 1u)));
462 auto& dsk_m(GetMainDesktop());
463 auto& dsk_s(GetSubDesktop());
465 reader.SetColor(CurrentSetting.FontColor),
466 reader.SetFont(CurrentSetting.Font),
468 dsk_m.Background = SolidBrush(CurrentSetting.UpColor),
469 dsk_s.Background = SolidBrush(CurrentSetting.DownColor),
472 FetchEvent<KeyHeld>(dsk_s) += OnEvent_Call<KeyDown>
474 reader.Attach(dsk_m, dsk_s),
475 AddWidgets(dsk_s, boxReader, boxTextInfo, pnlSetting, pnlBookmark);
477 LastRead.DropSubsequent();
481 OnClick(CursorEventArgs(dsk_s, 0));
517 reader.Execute(DualScreenReader::LineUpScroll);
520 reader.Execute(DualScreenReader::LineDownScroll);
523 reader.Execute(DualScreenReader::ScreenUpScroll);
526 reader.Execute(DualScreenReader::ScreenDownScroll);
539 const auto text_size(
reader.GetTextSize());
542 return pos >= text_size;
549 const auto s(
reader.GetTextSize());
553 const auto old_pos(GetReaderPosition());
556 if(
YB_LIKELY(old_pos != GetReaderPosition()))
573 if(CurrentSetting.SmoothScroll)
576 reader.Execute(DualScreenReader::LineDownScroll);
591 mnu.SetItemEnabled(MR_LineUp, !
reader.IsTextTop());
592 mnu.SetItemEnabled(MR_LineDown, !
reader.IsTextBottom());
593 mnu.SetItemEnabled(MR_ScreenUp, !
reader.IsTextTop());
594 mnu.SetItemEnabled(MR_ScreenDown, !
reader.IsTextBottom());
612 reader.AdjustScrollOffset(),
633 const auto& bm(
LastRead.Switch(is_prev));
637 if(
reader.IsBufferReady())
638 reader.Locate(bm.Position);
653 if(e.Keys[VK_RBUTTON])
688 using namespace Timers;
689 using namespace KeyCodes;
695 const auto ntick(HighResolutionClock::now());
704 const auto& k(e.GetKeys());
713 if(k[KeyCodes::Enter])
718 reader.Execute(DualScreenReader::LineUpScroll);
720 reader.Execute(DualScreenReader::LineDownScroll);
723 auto size(
reader.GetFont().GetSize());
752 reader.Execute(DualScreenReader::ScreenUpScroll);
755 reader.Execute(DualScreenReader::ScreenDownScroll);
758 tmrInput.Delay(HighResolutionClock::now() - ntick);
765 const shared_ptr<Desktop>& h_dsk_up,
const shared_ptr<Desktop>& h_dsk_dn)
767 HexArea(
Rect({}, MainScreenWidth, MainScreenHeight)), pnlFileInfo()
769 HexArea.SetRenderer(make_unique<BufferedRenderer>(
true));
771 FetchEvent<KeyDown>(HexArea) += [
this](
KeyEventArgs&& e){
774 if(keys.count() == 1 && keys[KeyCodes::Esc])
778 pnlFileInfo.lblSize.Text = u
"当前位置: "
779 + String(
to_string(HexArea.GetModel().GetPosition())
780 +
" / " +
to_string(HexArea.GetModel().GetSize()));
785 auto& dsk_m(GetMainDesktop());
786 auto& dsk_s(GetSubDesktop());
787 const string& path_str(pth);
789 pnlFileInfo.lblPath.Text = u
"文件路径:" + String(pth);
791 struct ::stat file_stat;
794 ::stat(path_str.c_str(), &file_stat);
796 pnlFileInfo.lblAccessTime.Text = u
"访问时间:"
798 pnlFileInfo.lblModifiedTime.Text = u
"修改时间:"
801 dsk_m += pnlFileInfo;
802 HexArea.Load(path_str.c_str());
803 HexArea.UpdateData(0);
ReadingList & LastRead
近期浏览记录。
YF_API string MakeEscape(const string &)
转义字符串:替换指定字符串中的可转义字符。
set< ValueNode > Container
bool Locate(Bookmark::PositionType)
定位到文本中的指定位置:更新阅读器状态、阅读列表和按钮状态。
pt pt Y const IWidget &wgt const IWidget &wgt GetSizeOf
无效化:使相对于部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
GValueEventArgs< MTextList::IndexType > IndexEventArgs
索引事件。
const ValueNode & at(const string &) const
YF_API void SetLocationOf(IWidget &, const Point &)
设置部件左上角所在位置(相对于容器的偏移坐标)。
yconstexpr EncodingInfoItem Encodings[]
编码信息。
virtual void Refresh(PaintEventArgs &&)
刷新:按指定参数绘制界面并更新状态。
YF_API GUIState & FetchGUIState()
取默认图形用户界面公共状态。
static yconstexpr FontSize MinimalSize
#define yunused(...)
标记未使用的表达式。
bool tmrScrollActive
滚屏计时器激活状态。
YF_API ValueNode & FetchRoot()
取值类型根节点。
size_t arrlen(_type(&)[_vN])
计算指定数组类型对象的长度。
YF_API void FillRect(const Graphics &g, const Rect &, Color c)
填充标准矩形。
YF_API void Invalidate(IWidget &, const Rect &)
无效化:使相对于部件的指定区域在直接和间接的窗口缓冲区中无效。
Timers::Timer tmrScroll
滚屏计时器。
Label lblAreaUp
标签:文本区域示例。
std::function< void()> fBackgroundTask
背景任务:用于滚屏。
void Exit()
退出阅读器:停止后台任务并发送消息准备切换至 ShlExplorer 。
YF_API const char * TranslateTime(const std::tm &, const char *=DefaultTimeFormat)
格式化时间字符串。
void Switch(Text::Encoding)
切换编码。
BookmarkSession(ShlTextReader &)
void UpdateButtons()
更新按钮状态。
YF_API bool Enable(IWidget &, bool=true)
设置部件可用性,且当可用性改变时无效化部件区域。
size_t PositionType
文件位置类型。
YF_API void OnTouchHeld_Dragging(CursorEventArgs &&)
处理屏幕接触移动事件:拖放按下部件。
YF_API void Hide(IWidget &)
隐藏部件。
void split(_tIn b, _tIn e, _fPred is_delim, _fInsert insert)
以指定字符分割字符序列。
void unseq_apply(_fCallable &&f, _tParams &&...args)
无序调用。
void StopAutoScroll()
停止自动滚屏。
~ShlTextReader() override
析构:释放资源。
YF_API void Show(IWidget &)
显示部件。
void RemoveWidgets(_tCon &con, _tWidgets &...wgts)
从部件容器移除子部件。
void AddWidgets(_tCon &con, _tWidgets &...wgts)
向部件容器添加子部件。
BaseSession(ShlTextReader &)
YF_API void SaveConfiguration(const ValueNode &)
保存默认配置。
YF_API void Execute(GUIApplication &, shared_ptr< Shell >=make_shared< Shells::GUIShell >())
执行程序主消息循环。
#define YB_UNLIKELY(expr)
分支预测提示。
SettingSession(ShlTextReader &)
unique_ptr< TextFile > pTextFile
BookmarkPanel pnlBookmark
书签管理面板。
GBinaryGroup< SPos > Point
屏幕二维点(直角坐标表示)。
#define yunseq
无序列依赖表达式组求值。
void UpdateData(DualScreenReader &)
更新进度数据。
IO::Path CurrentPath
当前路径。
YF_API ValueNode LoadConfiguration(bool={})
载入默认配置。
static void SaveGlobalConfiguration(const ReaderSetting &)
保存阅读器配置。
void OnClick(CursorEventArgs &&)
static BookmarkList LoadBookmarks(const string &)
bool Activate(const shared_ptr< Shell > &hShl)
激活 Shell 对象:控制权转移给此对象以维持单线程运行。
void Show(Menu::ID, ZOrderType=DefaultMenuZOrder)
按指定 Z 顺序显示菜单组中菜单标识指定的菜单。
size_t RefreshClick(size_t, const Duration &=Timers::TimeSpan(400))
重复检测连续点击状态。
ShlHexBrowser(const IO::Path &, const shared_ptr< Desktop > &={}, const shared_ptr< Desktop > &={})
构造:使用指定路径和上下屏幕。
GSStringTemplate< char >::basic_string string
void ShowMenu(Menu::ID, const Point &)
void Scroll()
当自动滚屏有效状态为 true 时超时自动滚屏。
YF_API void RequestFocusCascade(IWidget &)
级联请求部件及上层容器焦点。
vector< Bookmark::PositionType > BookmarkList
书签列表类型。
void Execute(IndexEventArgs::ValueType)
执行阅读器命令。
errno_t NowShellTo(const shared_ptr< Shell > &hShl)
向句柄指定的 Shell 对象转移线程控制权。
void LoadFile(const IO::Path &)
读取文件。
_tString && ltrim(_tString &&str, typename string_traits< _tString >::const_pointer t=&to_array< typename string_traits< _tString >::value_type >("\n\r\t\v ")[0])
删除字符串中指定的连续前缀字符。
void Insert(const IO::Path &, size_t)
插入阅读记录。
SettingPanel pnlSetting
设置面板。
_type & parameterize_static_object()
类型参数化静态对象。
std::string to_string(unsigned char val)
转换为字符串。
String FetchEncodingString(MTextList::IndexType)
取编码字符串。
ShlReader(const IO::Path &, const shared_ptr< Desktop > &={}, const shared_ptr< Desktop > &={})
构造:使用指定路径和上下桌面。
YF_API void ResetDSDesktops(Desktop &, Desktop &)
以默认屏幕复位两个桌面。
static yconstexpr FontSize MaximalSize
unique_ptr< BaseSession > session_ptr
void OnKeyDown(KeyEventArgs &&)
void erase_all_if(_tRange &c, _fPred pred)
删除指定序列范围中满足条件的元素。
void UpdateReadingList(bool)
更新近期浏览记录并更新按钮状态。
ReaderSetting CurrentSetting
当前阅读器设置。
void UpdateData(DualScreenReader &)
void SetBufferRendererAndText(_tWidget &wgt, const String &s)
设置部件渲染器为 BufferedRenderer 及部件的 Text 成员。
ShlTextReader(const IO::Path &, const shared_ptr< Desktop > &={}, const shared_ptr< Desktop > &={})
构造:使用指定路径和上下桌面。
virtual void Refresh(PaintEventArgs &&)
刷新:按指定参数绘制界面并更新状态。
std::chrono::milliseconds TimeSpan
低精度时间间隔。
void StartAutoScroll()
开始自动滚屏。
void ResizeForContent(TextList &tl)
InputTimer tmrInput
按键计时器。
static ReaderSetting LoadGlobalConfiguration()
载入阅读器配置。
string CopySliceFrom(TextFileBuffer &buf, size_t pos, size_t len) ythrow(std
~SettingSession() override
void OnInput() override
处理输入消息:发送绘制消息,当处于滚屏状态时自动执行滚屏。
void PostTask(_fCallable &&f, Messaging::Priority prior=Messaging::NormalPriority)
通过消息队列部署后任务。
BookmarkList bookmarks
当前打开文件的书签列表。
GValueEventArgs< bool > ViewArgs
视图参数类型。
YF_API bool RepeatHeld(InputTimer &, InputTimer::HeldStateType &, const Timers::Duration &, const Timers::Duration &)
向指定计时器传递参数,根据状态重复按键。
static void SaveBookmarks(const string &, const BookmarkList &)