Skip to content

Commit

Permalink
feat: 添加 SimpleStackPanel
Browse files Browse the repository at this point in the history
  • Loading branch information
Blinue committed Dec 13, 2023
1 parent 5481981 commit d414e8e
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/Magpie.App/App.idl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Magpie.App {
#include "IsNullStateTrigger.idl"
#include "LoggerHelper.idl"
#include "TextBlockHelper.idl"
#include "SimpleStackPanel.idl"
#include "WrapPanel.idl"
#include "PageFrame.idl"
#include "SettingsCard.idl"
Expand Down
12 changes: 6 additions & 6 deletions src/Magpie.App/KeyVisualState.idl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
namespace Magpie.App {
runtimeclass KeyVisualState {
KeyVisualState(Int32 key, Boolean isError);
Int32 Key { get; };
Boolean IsError { get; };
}
runtimeclass KeyVisualState {
KeyVisualState(Int32 key, Boolean isError);
Int32 Key { get; };
Boolean IsError { get; };
}
}
11 changes: 11 additions & 0 deletions src/Magpie.App/Magpie.App.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@
<DependentUpon>ShortcutDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="SimpleStackPanel.h">
<DependentUpon>SimpleStackPanel.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="TextBlockHelper.h">
<DependentUpon>TextBlockHelper.idl</DependentUpon>
<SubType>Code</SubType>
Expand Down Expand Up @@ -381,6 +385,10 @@
<DependentUpon>ShortcutDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="SimpleStackPanel.cpp">
<DependentUpon>SimpleStackPanel.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="TextBlockHelper.cpp">
<DependentUpon>TextBlockHelper.idl</DependentUpon>
<SubType>Code</SubType>
Expand All @@ -396,6 +404,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="SimpleStackPanel.idl">
<SubType>Designer</SubType>
</None>
<None Include="SettingsExpander.idl">
<SubType>Designer</SubType>
</None>
Expand Down
3 changes: 3 additions & 0 deletions src/Magpie.App/Magpie.App.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@
<None Include="SettingsExpander.idl">
<Filter>Controls</Filter>
</None>
<None Include="SimpleStackPanel.idl">
<Filter>Controls</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Page Include="RootPage.xaml" />
Expand Down
16 changes: 8 additions & 8 deletions src/Magpie.App/PageFrame.idl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Magpie.App {
[Windows.UI.Xaml.Markup.ContentProperty("MainContent")]
runtimeclass PageFrame : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged {
PageFrame();
[Windows.UI.Xaml.Markup.ContentProperty("MainContent")]
runtimeclass PageFrame : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged {
PageFrame();

String Title;
Windows.UI.Xaml.Controls.IconElement Icon;
Windows.UI.Xaml.FrameworkElement HeaderAction;
Object MainContent;
}
String Title;
Windows.UI.Xaml.Controls.IconElement Icon;
Windows.UI.Xaml.FrameworkElement HeaderAction;
Object MainContent;
}
}
128 changes: 128 additions & 0 deletions src/Magpie.App/SimpleStackPanel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "pch.h"
#include "SimpleStackPanel.h"
#if __has_include("SimpleStackPanel.g.cpp")
#include "SimpleStackPanel.g.cpp"
#endif

using namespace winrt;
using namespace Windows::UI::Xaml::Controls;

namespace winrt::Magpie::App::implementation {

const DependencyProperty SimpleStackPanel::_orientationProperty = DependencyProperty::Register(
L"Orientation",
xaml_typename<Controls::Orientation>(),
xaml_typename<class_type>(),
PropertyMetadata(box_value(Orientation::Horizontal), &SimpleStackPanel::_OnLayoutPropertyChanged)
);

const DependencyProperty SimpleStackPanel::_paddingProperty = DependencyProperty::Register(
L"Padding",
xaml_typename<Thickness>(),
xaml_typename<class_type>(),
PropertyMetadata(box_value(Thickness{}), &SimpleStackPanel::_OnLayoutPropertyChanged)
);

const DependencyProperty SimpleStackPanel::_spacingProperty = DependencyProperty::Register(
L"Spacing",
xaml_typename<double>(),
xaml_typename<class_type>(),
PropertyMetadata(box_value(0.0), &SimpleStackPanel::_OnLayoutPropertyChanged)
);

Size SimpleStackPanel::MeasureOverride(const Size& availableSize) {
const float spacing = (float)Spacing();
const Thickness padding = Padding();
const Size paddings{ (float)padding.Left + (float)padding.Right,(float)padding.Top + (float)padding.Bottom };

const Size childAvailableSize{
availableSize.Width - paddings.Width,
availableSize.Height - paddings.Height
};

bool firstItem = true;
bool anyStretch = false;
Size finalSize{ paddings.Width, paddings.Height };

for (UIElement const& item : Children()) {
if (item.Visibility() == Visibility::Collapsed) {
// 不可见的子项不添加间距
continue;
}

item.Measure(childAvailableSize);
const Size itemSize = item.DesiredSize();

if (firstItem) {
finalSize.Height += itemSize.Height;
firstItem = false;
} else {
finalSize.Height += spacing + itemSize.Height;
}

if (anyStretch) {
continue;
}

if (!std::isinf(availableSize.Width)) {
FrameworkElement elem = item.try_as<FrameworkElement>();
if (elem && elem.HorizontalAlignment() == HorizontalAlignment::Stretch) {
anyStretch = true;
finalSize.Width = availableSize.Width;
continue;
}
}

finalSize.Width = std::max(finalSize.Width, itemSize.Width + paddings.Width);
}

return finalSize;
}

Size SimpleStackPanel::ArrangeOverride(Size finalSize) const {
const Controls::Orientation orientation = Orientation();
const Thickness padding = Padding();
const float spacing = (float)Spacing();

Point position{ (float)padding.Left, (float)padding.Top };

for (UIElement const& item : Children()) {
if (item.Visibility() == Visibility::Collapsed) {
// 不可见的子项不添加间距
continue;
}

auto alignment = HorizontalAlignment::Left;
if (FrameworkElement elem = item.try_as<FrameworkElement>()) {
alignment = elem.HorizontalAlignment();
}

const Size itemSize = item.DesiredSize();
Rect itemRect{ position.X, position.Y, itemSize.Width, itemSize.Height };

switch (alignment) {
case HorizontalAlignment::Center:
itemRect.X = position.X + (finalSize.Width - position.X - (float)padding.Right - itemRect.Width) / 2;
break;
case HorizontalAlignment::Right:
itemRect.X = finalSize.Width - (float)padding.Right - itemRect.Width;
break;
case HorizontalAlignment::Stretch:
itemRect.Width = finalSize.Width - position.X - (float)padding.Right;
break;
}
item.Arrange(itemRect);

position.Y += itemSize.Height + spacing;
}

return finalSize;
}

void SimpleStackPanel::_OnLayoutPropertyChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const&) {
SimpleStackPanel* that = get_self<SimpleStackPanel>(sender.as<class_type>());
that->InvalidateMeasure();
that->InvalidateArrange();
}

}
39 changes: 39 additions & 0 deletions src/Magpie.App/SimpleStackPanel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once
#include "SimpleStackPanel.g.h"

namespace winrt::Magpie::App::implementation {

struct SimpleStackPanel : SimpleStackPanelT<SimpleStackPanel> {
static DependencyProperty OrientationProperty() { return _orientationProperty; }
static DependencyProperty PaddingProperty() { return _paddingProperty; }
static DependencyProperty SpacingProperty() { return _spacingProperty; }

Controls::Orientation Orientation() const { return GetValue(_orientationProperty).as<Controls::Orientation>(); }
void Orientation(Controls::Orientation value) const { SetValue(_orientationProperty, box_value(value)); }

Thickness Padding() const { return GetValue(_paddingProperty).as<Thickness>(); }
void Padding(const Thickness& value) const { SetValue(_paddingProperty, box_value(value)); }

double Spacing() const { return GetValue(_spacingProperty).as<double>(); }
void Spacing(double value) const { SetValue(_spacingProperty, box_value(value)); }

Size MeasureOverride(const Size& availableSize);

Size ArrangeOverride(Size finalSize) const;

private:
static const DependencyProperty _orientationProperty;
static const DependencyProperty _paddingProperty;
static const DependencyProperty _spacingProperty;

static void _OnLayoutPropertyChanged(DependencyObject const& sender, DependencyPropertyChangedEventArgs const&);
};

}

namespace winrt::Magpie::App::factory_implementation {

struct SimpleStackPanel : SimpleStackPanelT<SimpleStackPanel, implementation::SimpleStackPanel> {
};

}
13 changes: 13 additions & 0 deletions src/Magpie.App/SimpleStackPanel.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Magpie.App {
runtimeclass SimpleStackPanel : Windows.UI.Xaml.Controls.Panel {
SimpleStackPanel();

static Windows.UI.Xaml.DependencyProperty OrientationProperty { get; };
static Windows.UI.Xaml.DependencyProperty PaddingProperty { get; };
static Windows.UI.Xaml.DependencyProperty SpacingProperty { get; };

Windows.UI.Xaml.Controls.Orientation Orientation;
Windows.UI.Xaml.Thickness Padding;
Double Spacing;
}
}

0 comments on commit d414e8e

Please sign in to comment.