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 
31 
32 using namespace Drawing;
33 using namespace Text;
34 
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
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.
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
163 {
164  vsbVertical.SetValue(0);
165  datCurrent.clear();
166  UpdateItemNum(GetHeight());
167  UpdateView();
168 }
169 
170 void
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 
206 
207 YSL_END
208