Rect BufferedRenderer::Validate(IWidget& wgt, IWidget& sender, const PaintContext& pc) { if(RequiresRefresh()) { const auto& l(GetLocationOf(sender)); if(!IgnoreBackground && FetchContainerPtr(sender)) Invalidate(sender); const Rect& clip(pc.ClipArea & (rInvalidated + l)); if(!IgnoreBackground && FetchContainerPtr(sender)) { const auto& g(GetContext()); CopyTo(g.GetBufferPtr(), pc.Target, g.GetSize(), clip.GetPoint() - pc.Location, clip.GetPoint(), clip.GetSize()); } PaintEventArgs e(sender, {GetContext(), Point(), clip - l}); CallEvent<UI::Paint>(wgt, e); //清除无效区域:只设置一个分量为零可能会使 CommitInvalidation 结果错误。 rInvalidated.GetSizeRef() = {}; return e.ClipArea; } return {}; }
void InvalidateVisibleParent(IWidget& wgt) { if(IsVisible(wgt)) if(const auto p_con = FetchContainerPtr(wgt)) InvalidateVisible(*p_con, GetBoundsOf(wgt)); }
void Close(IWidget& wgt) { Hide(wgt); if(const auto pCon = FetchContainerPtr(wgt)) ClearFocusingOf(*pCon); }
void Invalidate(IWidget& wgt, const Rect& bounds) { Rect r(bounds); for(auto p_wgt(&wgt); p_wgt; p_wgt = FetchContainerPtr(*p_wgt)) { r = p_wgt->GetRenderer().CommitInvalidation(r); r.GetPointRef() += GetLocationOf(*p_wgt); } }
bool Window::operator-=(Window& wnd) { if(FetchContainerPtr(wnd) == this) { SetContainerPtrOf(wnd); if(FetchFocusingPtr(*this) == &wnd) GetView().FocusingPtr = {}; return MUIContainer::operator-=(wnd); } return {}; }
bool Window::operator-=(IWidget& wgt) { if(FetchContainerPtr(wgt) == this) { SetContainerPtrOf(wgt); if(FetchFocusingPtr(*this) == &wgt) GetView().FocusingPtr = {}; return MUIContainer::operator-=(wgt); } return {}; }
void DropDownList::Refresh(PaintEventArgs&& e) { const auto cs(GetCursorState()); if(FetchContainerPtr(lbContent)) csCurrent = CursorState::Pressed; Button::Refresh(std::move(e)); csCurrent = cs; // XXX: Conversion to 'SPos' might be implementation-defined. DrawArrow(e.Target, e.ClipArea, Rect(e.Location.X + SPos(GetWidth()) - 16, e.Location.Y, Size(16, GetHeight())), 4, RDeg270, ForeColor); }
void InvalidateVisible(IWidget& wgt, const Rect& bounds) { auto p_wgt(&wgt); Rect r(bounds); while(IsVisible(*p_wgt)) { r = p_wgt->GetRenderer().CommitInvalidation(r); r.GetPointRef() += GetLocationOf(*p_wgt); if(!(p_wgt = FetchContainerPtr(*p_wgt))) break; } }
void SetInvalidationToParent(IWidget& wgt) { if(const auto p_con = FetchContainerPtr(wgt)) p_con->GetRenderer().CommitInvalidation(GetBoundsOf(wgt)); }
void RequestToFront(IWidget& wgt) { if(const auto p_pnl = dynamic_cast<Panel*>(FetchContainerPtr(wgt))) p_pnl->MoveToFront(wgt); }
void DropDownList::DetachTopWidget() { Detach(FetchContainerPtr(lbContent), lbContent); }
DropDownList::DropDownList(const Rect& r, const shared_ptr<ListType>& h) : Button(r), lbContent( {}, h) { const auto detacher([this](UIEventArgs&& e) { if(!dynamic_cast<RoutedEventArgs*>(&e)) DetachTopWidget(); }); yunseq( Margin.Left = 4, Margin.Right = 18, HorizontalAlignment = TextAlignment::Left, lbContent.GetView().DependencyPtr = this, FetchEvent<TouchDown>(*this) += [this](CursorEventArgs&& e) { if(!FetchContainerPtr(lbContent)) { Point pt; if(const auto p = dynamic_cast<Panel*>(&FetchTopLevel(e.GetSender(), pt))) { // NOTE: Get height of top widget, top and bottom spaces. const SDst h0(GetSizeOf(*p).Height); // XXX: Conversion to 'SPos' might be implementation-defined. const SDst h1(SDst(max<SPos>(0, pt.Y))), h2(SDst(max<SPos>(0, SPos(h0) - pt.Y - SPos(GetHeight())))); if(IsInOpenInterval(h1, h0) || IsInOpenInterval(h2, h0)) { lbContent.ResizeForPreferred(Size(0, max(h1, h2)), Size(GetWidth(), 0)); const SDst h3(lbContent.GetHeight()); // NOTE: Bottom space is preferred. // XXX: Conversion to 'SPos' might be // implementation-defined. pt.Y += SPos(h2 < h3 ? -h3 : GetHeight()); SetLocationOf(lbContent, pt); lbContent.AdjustViewLength(); { const auto& lst(lbContent.GetList()); const auto i(std::find(lst.cbegin(), lst.cend(), Text)); if(i != lst.cend()) lbContent.SetSelected(size_t(i - lst.cbegin())); else lbContent.ClearSelected(); } p->Add(lbContent, 224U); // TODO: Use non-magic number. RequestFocusCascade(lbContent); e.Handled = true; } } } }, FetchEvent<LostFocus>(*this) += detacher, FetchEvent<LostFocus>(lbContent) += detacher, lbContent.GetConfirmed() += [this](IndexEventArgs&& e) { YAssert(e.Value < lbContent.GetList().size(), "Invalid index found."); Text = lbContent.GetList()[e.Value]; // XXX: This seems to be redundant if the detached top widget would be // always invalidated, however there is no such guarantee. Invalidate(e.GetSender()), Invalidate(*this); DetachTopWidget(); } ); }