29 #include YFM_YSLib_UI_Scroll
30 #include YFM_YSLib_UI_YGUI
31 #include YFM_YSLib_Core_YStorage
34 using namespace ystdex;
46 FixScrollBarLayout(Size& d,
const Size&
s,
SDst min_width,
SDst min_height)
48 bool need_h(d.Width < s.Width), need_v(d.Height < s.Height);
52 if(d.Height < min_height)
54 d.Height -= min_height;
58 if(d.Width < min_width)
64 if(!need_h && d.Width < s.Width)
67 if(d.Height < min_height)
69 d.Height -= min_height;
71 if(!need_v && d.Height < s.Height)
74 if(d.Width < min_width)
79 return pair<bool, bool>(need_h, need_v);
82 const SDst defMinScrollBarWidth(16);
83 const SDst defMinScrollBarHeight(16);
88 ATrack::ATrack(
const Rect&
r,
SDst uMinThumbLength)
89 : Control({r.GetPoint(), max<SDst>(defMinScrollBarWidth, r.Width),
90 max<SDst>(defMinScrollBarHeight, r.Height)}),
91 GMRange<ValueType>(0xFF, 0),
92 tmbScroll(Size(defMinScrollBarWidth, defMinScrollBarHeight)),
93 min_thumb_length(uMinThumbLength), large_delta(min_thumb_length)
95 SetContainerPtrOf(tmbScroll,
this);
99 GetThumbDrag() += [
this]{
100 LocateThumb(0, ScrollCategory::ThumbTrack);
103 FetchEvent<TouchDown>(*this) += [
this](CursorEventArgs&& e){
104 if(e.Strategy == RoutedEventArgs::Direct && &e.GetSender() ==
this
109 switch(CheckArea(e.Position.GetRef(IsHorizontal())))
112 t = ScrollCategory::LargeDecrement;
115 t = ScrollCategory::LargeIncrement;
120 t = ScrollCategory::EndScroll;
129 ATrack::SetThumbLength(
SDst l)
134 const bool is_h(IsHorizontal());
136 if(l != s.GetRef(is_h))
144 ATrack::SetThumbPosition(
SPos pos)
146 RestrictInClosedInterval<SPos>(pos, 0, GetScrollableLength());
149 const bool is_h(IsHorizontal());
151 if(pos != pt.GetRef(is_h))
154 pt.GetRef(is_h) = pos;
159 ATrack::SetMaxValue(ValueType m)
169 ATrack::SetValue(ValueType val)
172 SetThumbPosition(
SPos(round(val * GetScrollableLength() / max_value)));
175 ATrack::SetLargeDelta(ValueType val)
178 SetThumbLength(
SDst(round(val * GetTrackLength() / (val + max_value))));
182 ATrack::CheckArea(
SPos q)
const
188 SPos(GetThumbPosition() + GetThumbLength())};
200 ValueType old_value(value);
202 if(t == ScrollCategory::ThumbTrack)
203 value = GetThumbPosition() == GetScrollableLength() ? max_value
204 : max_value * GetThumbPosition()
205 / (GetTrackLength() - GetThumbLength());
208 if(t == ScrollCategory::LargeDecrement
209 || t == ScrollCategory::LargeIncrement)
210 val = GetLargeDelta();
213 case ScrollCategory::SmallDecrement:
214 case ScrollCategory::LargeDecrement:
217 SetValue(value - val);
220 case ScrollCategory::First:
224 case ScrollCategory::SmallIncrement:
225 case ScrollCategory::LargeIncrement:
226 if(value + val < max_value)
228 SetValue(value + val);
231 case ScrollCategory::Last:
233 SetThumbPosition(GetScrollableLength());
238 GetScroll()(ScrollEventArgs(*
this, t, value, old_value));
245 const auto&
g(e.Target);
246 const auto& pt(e.Location);
252 #define YSL_UI_ATRACK_PARTIAL_INVALIDATION
255 #ifdef YSL_UI_ATRACK_PARTIAL_INVALIDATION
258 SPos xr(x + trk.GetWidth());
259 SPos yr(y + trk.GetHeight());
261 const SPos xr(pt.X + trk.GetWidth());
262 const SPos yr(pt.Y + trk.GetHeight());
265 if(trk.IsHorizontal())
267 #ifdef YSL_UI_ATRACK_PARTIAL_INVALIDATION
276 #ifdef YSL_UI_ATRACK_PARTIAL_INVALIDATION
286 HorizontalTrack::HorizontalTrack(
const Rect& r,
SDst uMinThumbLength)
287 : ATrack(r, uMinThumbLength)
289 YAssert(GetWidth() > GetHeight(),
"Width is not greater than height.");
295 if(st.CheckDraggingOffset())
297 SPos x(st.CursorLocation.X + st.DraggingOffset.X);
299 RestrictInClosedInterval<SPos>(x, 0,
300 GetWidth() - tmbScroll.GetWidth());
311 : ATrack(r, uMinThumbLength)
313 YAssert(GetHeight() > GetWidth(),
"height is not greater than width.");
319 if(st.CheckDraggingOffset())
321 SPos y(st.CursorLocation.Y + st.DraggingOffset.Y);
323 RestrictInClosedInterval<SPos>(y, 0,
324 GetHeight() - tmbScroll.GetHeight());
338 Rect(r.Height, 0, r.
Width - r.Height * 2, r.Height), uMinThumbSize))
341 btnPrev(
Rect()), btnNext(
Rect()), small_delta(2)
343 SetContainerPtrOf(*
pTrack,
this),
344 SetContainerPtrOf(
btnPrev,
this);
345 SetContainerPtrOf(
btnNext,
this);
347 FetchEvent<Resize>(*
this) += [
this](
UIEventArgs&& e){
349 const bool is_h(track.IsHorizontal());
354 "No enough space for track.");
358 yunseq(track.GetView().GetSizeRef().GetRef(is_h) = tl,
359 btnNext.
GetView().GetLocationRef().GetRef(is_h) = tl + prev_metric);
368 else if(e.GetDelta() < 0)
372 FetchEvent<TouchDown>(
btnPrev) += [
this]{
376 FetchEvent<TouchDown>(
btnNext) += [
this]{
383 const SDst l(s.GetRef(!bHorizontal));
385 s.GetRef(bHorizontal) =
l;
397 using namespace placeholders;
451 :
Control(r, MakeBlankBrush()),
452 hsbHorizontal(
Size(r.
Width, defMinScrollBarHeight)),
453 vsbVertical(
Size(defMinScrollBarWidth, r.Height))
473 const pair<bool, bool> p(FixScrollBarLayout(arena, s,
474 defMinScrollBarWidth, defMinScrollBarHeight));
476 if(p.first && p.second && GetWidth() > defMinScrollBarWidth
477 && GetHeight() > defMinScrollBarHeight)
480 vsbVertical.SetHeight(GetHeight() - defMinScrollBarHeight);
VerticalTrack(const Rect &={}, SDst=8)
构造:使用指定边界和最小滑块长。
void DrawVLineSeg(const Graphics &g, const Rect &bounds, SPos x, SPos y1, SPos y2, Color c)
描画竖直线段。
pt pt Y const IWidget &wgt const IWidget &wgt GetSizeOf
无效化:使相对于部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
pt pt Y const IWidget &wgt GetLocationOf
YF_API void OnKeyHeld(KeyEventArgs &&)
处理键接触保持事件。
YF_API void OnKey_Bound_TouchDown(KeyEventArgs &&)
处理按键事件:按键-指针设备接触开始。
YF_API void SetLocationOf(IWidget &, const Point &)
设置部件左上角所在位置(相对于容器的偏移坐标)。
YF_API GUIState & FetchGUIState()
取默认图形用户界面公共状态。
YF_API void FillRect(const Graphics &g, const Rect &, Color c)
填充标准矩形。
YF_API void Invalidate(IWidget &, const Rect &)
无效化:使相对于部件的指定区域在直接和间接的窗口缓冲区中无效。
VerticalScrollBar(const Rect &={}, SDst=8)
ScrollableContainer(const Rect &={})
YF_API void SetSizeOf(IWidget &, const Size &)
设置部件大小。
Size FixLayout(const Size &)
固定布局。
std::uint16_t SDst
屏幕坐标距离。
YF_API void MoveToBottom(IWidget &wgt)
移动部件 wgt 至容器下端。
YF_API void MoveToRight(IWidget &wgt)
移动部件 wgt 至容器右端。
YF_API void DrawTrackBackground(PaintEventArgs &&e, ATrack &)
绘制指定色调的基本按钮背景。
YF_API void OnTouchHeld(CursorEventArgs &&)
处理屏幕接触保持事件。
std::runtime_error GeneralEvent
一般运行时异常事件类。
ValueType small_delta
小距离滚动偏移量:滚动事件关联的滑块位置变化绝对值。
VerticalScrollBar vsbVertical
控制竖直可视区域的竖直滚动条。
unique_ptr< ATrack > pTrack
GBinaryGroup< SPos > Point
屏幕二维点(直角坐标表示)。
#define yunseq
无序列依赖表达式组求值。
void DrawHLineSeg(const Graphics &g, const Rect &bounds, SPos y, SPos x1, SPos x2, Color c)
描画水平线段。
ATrack *pTrack GetTrackRef()) DefGetterMem(const ynothrow
HorizontalScrollBar hsbHorizontal
控制水平可视区域的水平滚动条。
HorizontalScrollBar(const Rect &={}, SDst=8)
#define yconstexpr
指定编译时常量表达式。
YF_API void DrawArrow(const Graphics &, const Rect &, SDst=4, Rotation=RDeg0, Color=ColorSpace::Black)
在指定图形接口上下文上描画箭头。
YF_API void OnKey_Bound_TouchUp(KeyEventArgs &&)
处理按键事件:按键-指针设备接触结束。
void RestrictInInterval(_type &i, int a, int b) ynothrow
约束整数 i 在左闭右开区间 [a, b) 中。
if(YB_UNLIKELY(r >=sGraphics.Height)) throw std return pBuffer r *sGraphics Width
AScrollBar(const Rect &={}, SDst=8, Orientation=Horizontal)
构造:使用指定边界、大小和方向。
AController *controller_ptr Renderer *renderer_ptr View *view_ptr GetView()) DefGetterMem(const ynothrow
size_t SwitchInterval(_type v, const _type *a, size_t n) ynothrow
计算满足指定的值 v 在区间 [a[i], a[i + 1]) 内最小的 i 。
std::bitset< KeyBitsetWidth > KeyInput
按键并行位宽。
#define YAssert(_expr, _msg)