YSTest: HexBrowser.cpp 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
HexBrowser.cpp
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2011 - 2013.
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 "HexBrowser.h"
29
30 YSL_BEGIN
31
32 using namespace Drawing;
33 using namespace Text;
34
35 YSL_BEGIN_NAMESPACE(UI)
36
37 HexView::HexView(FontCache& fc)
38 : TextState(fc), item_num(0), datCurrent()
39 {
40 TextState.Color = ColorSpace::Black;
41 }
42
43
44 HexViewArea::HexViewArea(const Rect& r, FontCache& fc)
45 : ScrollableContainer(r), HexView(fc),
46 model()
47 {
48 SetVisibleOf(hsbHorizontal, false);
49 SetVisibleOf(vsbVertical, true);
50 vsbVertical.SetSmallDelta(1);
51 yunseq(
52 vsbVertical.GetTrack().GetScroll() += [this](ScrollEventArgs&& e){
53 LocateViewPosition(round(e.GetValue()));
54 },
55 FetchEvent<KeyDown>(*this) += [this](KeyEventArgs&& e){
56 using namespace KeyCodes;
57
58 const auto& k(e.GetKeys());
59
60 if(k.count() != 1)
61 return;
62
63 ScrollCategory t(ScrollCategory::SmallDecrement);
64
65 if(k[Down])
66 t = ScrollCategory::SmallIncrement;
67 else if(k[PgUp])
68 t = ScrollCategory::LargeDecrement;
69 else if(k[PgDn])
70 t = ScrollCategory::LargeIncrement;
71 else if(!k[Up])
72 return;
73 vsbVertical.LocateThumb(k[Up] || k[Down]
74 ? vsbVertical.GetSmallDelta() : vsbVertical.GetLargeDelta(), t);
75 RequestFocus(*this);
76 e.Handled = true;
77 },
78 FetchEvent<KeyHeld>(*this) += OnKeyHeld
79 );
80 Reset();
81 }
82
83 void
84 HexViewArea::Load(const_path_t path)
85 {
86 Reset();
87 model = make_unique<File>(path);
88
89 const IndexType n_total_ln((model.GetSize() + ItemPerLine - 1)
90 / ItemPerLine);
91
92 if(n_total_ln > GetItemNum())
93 {
94 vsbVertical.SetMaxValue(n_total_ln - GetItemNum());
95 vsbVertical.SetLargeDelta(GetItemNum());
96 }
97 else
98 SetVisibleOf(vsbVertical, false);
99 }
100
101 void
102 HexViewArea::LocateViewPosition(u32 line)
103 {
104 UpdateData(ItemPerLine * line);
105 UpdateView(true);
106 }
107
108 void
109 HexViewArea::Refresh(PaintEventArgs&& e)
110 {
111 using namespace Text;
112
113 // TODO: Refresh for 'rect' properly.
114 // Background(PaintEventArgs(*this, e.Target, e.Location, Rect(e.Location,
115 // GetWidth(), GetHeight())));
116 // Background(PaintEventArgs(*this, e));
117 ScrollableContainer::Refresh(std::move(e));
118 TextState.ResetPen();
119
120 // NOTE: It seems there is a bug in linker for checking odr-using.
121 yconstexpr auto ItemPerLine(HexViewArea::ItemPerLine);
122 auto& y(TextState.Pen.Y);
123 const SDst lh(GetItemHeight()), h(GetHeight()),
124 w_all(GetWidth() - vsbVertical.GetWidth()
125 - GetHorizontalOf(TextState.Margin)),
126 w_blank(w_all / (10 + ItemPerLine * 3)),
127 w_ch((w_all - w_blank * (1 + ItemPerLine)) / (8 + ItemPerLine * 2)),
128 w_addr(w_ch * 8 + w_blank),
129 w_item(w_ch * 2 + w_blank);
130 const int fsize(model.GetSize());
131 auto& pen_x(TextState.Pen.X);
132 TextRenderer tr(TextState, e.Target);
133 auto pos(model.GetPosition());
134 auto i_data(datCurrent.begin());
135
136 while(y < h && pos < fsize && i_data < datCurrent.end())
137 {
138 pen_x = TextState.Margin.Left;
139
140 auto x(pen_x);
141
142 {
143 char straddr[(32 >> 2) + 1];
144
145 std::sprintf(straddr, "%08X", pos);
146 PutLine(tr, straddr);
147 }
148 x += w_addr;
149
150 const auto n(min<IndexType>(fsize - pos, ItemPerLine));
151
152 for(IndexType j(0); j < n; yunseq(++j, i_data += 2, x += w_item))
153 {
154 pen_x = x;
155 PutLine(tr, &*i_data, &*i_data + 2);
156 }
157 yunseq(y += lh + TextState.LineGap, pos += ItemPerLine);
158 }
159 }
160
161 void
162 HexViewArea::Reset()
163 {
164 vsbVertical.SetValue(0);
165 datCurrent.clear();
166 UpdateItemNum(GetHeight());
167 UpdateView();
168 }
169
170 void
171 HexViewArea::UpdateData(u32 pos)
172 {
173 if(model.IsValid() && pos < model.GetSize())
174 {
175 const DataType::size_type n(ItemPerLine * GetItemNum() * 2);
176
177 model.SetPosition(pos, SEEK_SET);
178 datCurrent.resize(n);
179
180 auto b(datCurrent.begin());
181 const auto e(datCurrent.end());
182
183 while(!model.CheckEOF() && b != e)
184 {
185 byte c(std::fgetc(model.GetPtr()));
186 char h, l;
187
188 yunseq(h = (c >> 4 & 0x0F) + '0', l = (c & 0x0F) + '0');
189 *b++ = h > '9' ? h + 'A' - '9' - 1 : h;
190 *b++ = l > '9' ? l + 'A' - '9' - 1 : l;
191 }
192 // vsbVertical.SetValue(pos / ItemPerLine);
193 datCurrent.resize(b - datCurrent.begin());
194 model.SetPosition(pos, SEEK_SET); // Refresh 需要据此判断接近文件结尾。
195 }
196 }
197
198 void
199 HexViewArea::UpdateView(bool is_active)
200 {
201 ViewChanged(ViewArgs(*this, is_active));
202 Invalidate(*this);
203 }
204
205 YSL_END_NAMESPACE(UI)
206
207 YSL_END
208