70 return static_cast<decoration>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
75 return static_cast<decoration>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
80 return aLhs =
static_cast<decoration>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
85 return aLhs =
static_cast<decoration>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
95 return static_cast<decoration_style>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
100 return static_cast<decoration_style>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
105 return aLhs =
static_cast<decoration_style>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
110 return aLhs =
static_cast<decoration_style>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
113 template <
typename WidgetType,
typename... OtherBases>
117 typedef decorated<WidgetType, OtherBases...> self_type;
129 template <
typename... Args>
132 iInitialized{ false },
134 iDecoration{ default_decoration(aStyle) }
151 auto& self = widget_type::as_widget();
153 if (iStyle != aStyle)
157 self.update_layout();
167 return iClient !=
nullptr;
193 iClientLayout = make_ref<vertical_layout>();
201 iClientLayout->remove_all();
203 if (iClient !=
nullptr)
205 iClientLayout->add(iClient);
206 iClient->set_parent(iClientLayout->parent_widget());
217 return const_cast<i_title_bar&
>(to_const(*this).title_bar());
225 iTitleBar = aTitleBar;
226 if (iTitleBarLayout->find(iTitleBar->as_widget()) == std::nullopt)
227 iTitleBarLayout->add(iTitleBar->as_widget());
237 return const_cast<i_status_bar&
>(to_const(*this).status_bar());
245 iStatusBar = aStatusBar;
246 if (iStatusBarLayout->find(iStatusBar->as_widget()) == std::nullopt)
247 iStatusBarLayout->add(iStatusBar->as_widget());
249 template <
typename... Args>
253 return create_title_bar<normal_title_bar>(std::forward<Args>(aArgs)...);
255 return create_title_bar<tool_title_bar>(std::forward<Args>(aArgs)...);
257 template <
typename TitleBar,
typename... Args>
260 set_title_bar(to_abstract(make_ref<TitleBar>(*
this, std::forward<Args>(aArgs)...)));
263 template <
typename StatusBar,
typename... Args>
266 set_status_bar(to_abstract(make_ref<StatusBar>(*
this, std::forward<Args>(aArgs)...)));
308 auto& self = widget_type::as_widget();
311 if (debug::layoutItem ==
this)
314 auto result = widget_type::part(aPosition);
317 if (iTitleBar !=
nullptr && self.to_client_coordinates(iTitleBar->to_window_coordinates(iTitleBar->client_rect())).contains(aPosition))
319 else if (iMenuLayout &&
rect{ iMenuLayout->origin(), iMenuLayout->extents() }.contains(aPosition))
321 else if (iToolbarLayout &&
rect{ iToolbarLayout->origin(), iToolbarLayout->extents() }.contains(aPosition))
325 enum { left = 1, top = 2, right = 4, bottom = 8 };
327 auto const nonClientRect = self.to_client_coordinates(self.non_client_rect());
328 auto const nonClientBorder = self.is_root() ? self.root().window_border() : self.internal_spacing();
329 if (aPosition.
x < nonClientRect.left() + nonClientBorder.left)
331 if (aPosition.
x > nonClientRect.right() - nonClientBorder.right)
333 if (aPosition.
y < nonClientRect.top() + nonClientBorder.top)
335 if (aPosition.
y > nonClientRect.bottom() - nonClientBorder.bottom)
337 if (iStatusBar !=
nullptr)
339 point const sizeGripPos = self.to_client_coordinates(iStatusBar->size_grip().non_client_rect().position());
340 rect const sizeGripRect = { sizeGripPos,
size{ nonClientRect.bottom_right() - sizeGripPos } };
341 if (sizeGripRect.
contains(aPosition))
342 hit |= (right | bottom);
344 if (hit & top && hit & left)
346 else if (hit & top && hit & right)
348 else if (hit & bottom && hit & left)
350 else if (hit & bottom && hit & right)
356 else if (hit & right)
358 else if (hit & bottom)
363 if (debug::layoutItem ==
this)
369 using widget_type::has_layout;
370 using widget_type::layout;
373 auto& self = widget_type::as_widget();
375 switch (aStandardLayout)
378 return self.has_layout();
380 return !!iClientLayout;
382 return !!iNonClientLayout;
384 return !!iTitleBarLayout;
386 return !!iMenuLayout;
388 return !!iToolbarLayout;
390 return !!iDockLayout;
392 return !!iStatusBarLayout;
399 auto& self = widget_type::as_widget();
404 switch (aStandardLayout)
407 return self.layout();
411 return *iNonClientLayout;
413 return *iTitleBarLayout;
418 return *iToolbarLayout;
420 return iToolbarLayout->part(aPosition);
425 return iDockLayout->part(aPosition);
427 return *iStatusBarLayout;
434 return const_cast<i_layout&
>(to_const(*this).layout(aStandardLayout, aPosition));
439 widget_type::fix_weightings(aRecalculate);
449 auto& self = widget_type::as_widget();
451 if (self.has_size_policy() || self.is_root())
452 return widget_type::size_policy();
457 auto& self = widget_type::as_widget();
459 if (self.has_weight() || self.is_root())
460 return widget_type::weight();
466 widget_type::capture_released();
467 iTracking = std::nullopt;
472 auto& self = widget_type::as_widget();
474 widget_type::mouse_button_pressed(aButton, aPosition, aKeyModifiers);
476 (!self.is_root() || self.root().is_nested()))
478 auto const clickedPart =
part(aPosition);
483 self.root().window_manager().update_mouse_cursor(self.root());
489 widget_type::mouse_moved(aPosition, aKeyModifiers);
495 auto clipRect = widget_type::default_clip_rect(aIncludeNonClient);
504 auto& self = widget_type::as_widget();
514 iNonClientLayout.emplace(*
this);
536 if (!iDockLayoutContainer)
543 service<i_skin_manager>().active_skin().draw_separators(aGc, *iDockLayoutContainer,
dock_layout(
dock_area::East).parent_layout());
544 service<i_skin_manager>().active_skin().draw_separators(aGc, *iDockLayoutContainer,
dock_layout(
dock_area::North).parent_layout());
547 iDockLayout.emplace(*iDockLayoutContainer);
549 iDockLayout->center().set_padding(service<i_app>().current_style().padding(
padding_role::Dock));
561 auto& self = widget_type::as_widget();
568 return const_cast<i_layout_item&
>(to_const(*this).resizing_context());
572 auto& self = widget_type::as_widget();
577 auto const delta = widget_type::to_window_coordinates(aPosition) - iTracking->trackFrom;
578 auto const currentPosition = resizingContext.position();
579 auto const currentSize = resizingContext.extents();
582 switch (iTracking->part)
585 newPosition = iTracking->startPosition +
delta;
588 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx -
delta.x, iTracking->startSize.cy });
589 if (newSize != currentSize)
590 newPosition = iTracking->startPosition - (*newSize - iTracking->startSize).with_cy(0.0);
593 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx -
delta.x, iTracking->startSize.cy -
delta.y });
594 if (newSize != currentSize)
595 newPosition = iTracking->startPosition - (*newSize - iTracking->startSize);
598 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx, iTracking->startSize.cy -
delta.y });
599 if (newSize != currentSize)
600 newPosition = iTracking->startPosition - (*newSize - iTracking->startSize).with_cx(0.0);
603 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx +
delta.x, iTracking->startSize.cy -
delta.y });
604 if (newSize != currentSize)
605 newPosition = iTracking->startPosition - (*newSize - iTracking->startSize).with_cx(0.0);
608 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx +
delta.x, iTracking->startSize.cy });
611 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx +
delta.x, iTracking->startSize.cy +
delta.y });
614 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx, iTracking->startSize.cy +
delta.y });
617 newSize = resizingContext.minimum_size().max(
size{ iTracking->startSize.cx -
delta.x, iTracking->startSize.cy +
delta.y });
618 if (newSize != currentSize)
619 newPosition = iTracking->startPosition - (*newSize - iTracking->startSize).with_cy(0.0);
622 if (newPosition && newPosition != currentPosition)
625 if (debug::layoutItem ==
this)
626 service<debug::logger>() <<
neolib::logger::severity::Debug <<
"update_tracking(" << aPosition <<
"): " << currentPosition <<
" -> " << newPosition << endl;
633 self.move(newPosition.
value());
635 if (newSize && newSize != currentSize)
638 if (debug::layoutItem ==
this)
643 resizingContext.set_fixed_size(newSize,
false);
647 self.resize(newSize.
value());
673 std::optional<vertical_layout> iNonClientLayout;
674 std::optional<vertical_layout> iTitleBarLayout;
675 std::optional<vertical_layout> iMenuLayout;
676 std::optional<border_layout> iToolbarLayout;
677 std::optional<layout_manager<scrollable_widget<>>> iDockLayoutContainer;
678 std::optional<border_layout> iDockLayout;
679 std::optional<vertical_layout> iStatusBarLayout;
680 ref_ptr<i_title_bar> iTitleBar;
681 ref_ptr<i_status_bar> iStatusBar;
682 ref_ptr<i_layout> iClientLayout;
683 ref_ptr<i_widget> iClient;
684 std::optional<tracking> iTracking;
bool contains(const point_type &point) const
void set_client(i_widget &aClient) override
neogfx::decoration decoration() const
bool has_layout(standard_layout aStandardLayout) const override
neogfx::decoration_style decoration_style() const
rect default_clip_rect(bool aIncludeNonClient=false) const override
bool part_active(widget_part aPart) const override
size weight() const override
void set_client(i_ref_ptr< i_widget > const &aClient) override
void mouse_moved(const point &aPosition, key_modifiers_e aKeyModifiers) override
i_layout & layout(standard_layout aStandardLayout, layout_position aPosition=layout_position::None) override
const i_widget & client_widget() const override
void update_tracking(const point &aPosition)
const i_layout & layout(standard_layout aStandardLayout, layout_position aPosition=layout_position::None) const override
widget_part part(const point &aPosition) const override
const i_title_bar & title_bar() const override
void set_status_bar(i_status_bar &aStatusBar) override
neogfx::autoscale autoscale() const
i_widget & client_widget() override
void set_title_bar(i_ref_ptr< i_title_bar > const &aTitleBar)
void set_decoration_style(neogfx::decoration_style aStyle)
i_status_bar & status_bar() override
void set_status_bar(i_ref_ptr< i_status_bar > const &aStatusBar)
ref_ptr< i_title_bar > create_title_bar(Args &&... aArgs)
ref_ptr< i_status_bar > create_status_bar(Args &&... aArgs)
i_widget & as_widget() override
i_layout_item const & resizing_context() const
decorated(neogfx::decoration_style aStyle, Args &&... aArgs)
ref_ptr< i_title_bar > create_title_bar(Args &&... aArgs)
i_title_bar & title_bar() override
i_layout_item & resizing_context()
const i_status_bar & status_bar() const override
void mouse_button_pressed(mouse_button aButton, const point &aPosition, key_modifiers_e aKeyModifiers) override
neogfx::size_policy size_policy() const override
void capture_released() override
const i_widget & as_widget() const override
void set_title_bar(i_title_bar &aTitleBar) override
bool is_widget() const override
void fix_weightings(bool aRecalculate=true) override
bool has_client_widget() const override
virtual const i_layout & parent_layout() const =0
virtual void fix_weightings(bool aRecalculate=true)=0
virtual void update_layout(bool aDeferLayout=true, bool aAncestors=false)=0
virtual neogfx::autoscale autoscale() const =0
virtual void set_spacing(optional_size const &sSpacing, bool aUpdateLayout=true)=0
virtual layout_item_index count() const =0
virtual layout_item_index index_of(const i_layout_item &aItem) const =0
virtual i_layout_item & add_at(layout_item_index aPosition, i_layout_item &aItem)=0
const i_layout & non_client_layout() const
const i_layout & status_bar_layout() const
const i_layout & dock_layout(layout_position aPosition=layout_position::Left) const
const i_layout & toolbar_layout(layout_position aPosition=layout_position::Top) const
size extents() const final
constexpr font_style & operator&=(font_style &aLhs, font_style aRhs)
constexpr style_aspect operator&(style_aspect aLhs, style_aspect aRhs)
audio_channel operator~(audio_channel lhs)
basic_delta< coordinate > delta
uint32_t layout_item_index
constexpr font_style & operator|=(font_style &aLhs, font_style aRhs)
constexpr style_aspect operator|(style_aspect aLhs, style_aspect aRhs)