diff --git a/samples/ControlCatalog/Icons.cs b/samples/ControlCatalog/Icons.cs index 58d0e0b7d4..5f99bdc877 100644 --- a/samples/ControlCatalog/Icons.cs +++ b/samples/ControlCatalog/Icons.cs @@ -190,5 +190,8 @@ namespace ControlCatalog // Slider tune/adjust public const string Tune = "M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z"; + + // Home + public const string Home = "M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z"; } } diff --git a/samples/ControlCatalog/Pages/HomePage.xaml b/samples/ControlCatalog/Pages/HomePage.xaml new file mode 100644 index 0000000000..bd0d6432fa --- /dev/null +++ b/samples/ControlCatalog/Pages/HomePage.xaml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/ControlCatalog/Pages/HomePage.xaml.cs b/samples/ControlCatalog/Pages/HomePage.xaml.cs new file mode 100644 index 0000000000..95fa183745 --- /dev/null +++ b/samples/ControlCatalog/Pages/HomePage.xaml.cs @@ -0,0 +1,78 @@ +using System; +using Avalonia; +using Avalonia.Animation; +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.Styling; +using Avalonia.VisualTree; +using ControlCatalog.ViewModels; + +namespace ControlCatalog.Pages +{ + public partial class HomePage : ContentPage + { + public HomePage() + { + InitializeComponent(); + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + + // Pages hosted in a NavigationPage inherit the navigator as DataContext; + // the card grid binds to MainWindowViewModel, so resolve it from MainView. + if (DataContext is not MainWindowViewModel) + DataContext = this.FindAncestorOfType()?.DataContext; + + StartFloatingAnimation(FloatIcon1, 12, 8, TimeSpan.FromSeconds(12)); + StartFloatingAnimation(FloatIcon2, -14, 8, TimeSpan.FromSeconds(10)); + StartFloatingAnimation(FloatIcon3, -12, -12, TimeSpan.FromSeconds(14)); + StartFloatingAnimation(FloatIcon4, 12, -8, TimeSpan.FromSeconds(11)); + } + + private static void StartFloatingAnimation(Control target, double dx, double dy, TimeSpan duration) + { + var transform = new TranslateTransform(); + target.RenderTransform = transform; + + var animation = new Animation + { + Duration = duration, + IterationCount = IterationCount.Infinite, + Children = + { + new KeyFrame + { + Cue = new Cue(0d), + Setters = + { + new Setter(TranslateTransform.XProperty, 0d), + new Setter(TranslateTransform.YProperty, 0d), + } + }, + new KeyFrame + { + Cue = new Cue(0.5d), + Setters = + { + new Setter(TranslateTransform.XProperty, dx), + new Setter(TranslateTransform.YProperty, dy), + } + }, + new KeyFrame + { + Cue = new Cue(1d), + Setters = + { + new Setter(TranslateTransform.XProperty, 0d), + new Setter(TranslateTransform.YProperty, 0d), + } + }, + } + }; + + _ = animation.RunAsync(target); + } + } +} diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs index 0d877b253f..7b9bbac603 100644 --- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs +++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs @@ -37,6 +37,7 @@ namespace ControlCatalog.ViewModels { (App.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown(); }); + NavigateToPageCommand = MiniCommand.Create(NavigateToPage); WindowState = WindowState.Normal; @@ -127,6 +128,8 @@ namespace ControlCatalog.ViewModels public MiniCommand ExitCommand { get; } + public MiniCommand NavigateToPageCommand { get; } + private DateTime? _validatedDateExample; /// diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs index 03047bedae..8142004af8 100644 --- a/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs +++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs @@ -26,78 +26,114 @@ namespace ControlCatalog.ViewModels private List _items = new() { - new PageItem("Composition", () => new CompositionPage(), Icons.Layers), - new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard), - new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur), - new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle), - new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput), - new PageItem("Border",() => new BorderPage(), Icons.Border), - new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning), - new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick), - new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner), - new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar), - new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas), - new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal), - new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides), - new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides), - new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox), - new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard), - new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette), - new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown), - new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container), - new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document), - new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu), - new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu), - new PageItem("Cursor",() => new CursorPage(), Icons.Cursor), - new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush), - new PageItem("DataGrid",() => new DataGridPage(), Icons.Grid), - new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield), - new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock), - new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar), - new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog), - new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop), - new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer), - new PageItem("Expander",() => new ExpanderPage(), Icons.Expand), - new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout), - new PageItem("Focus",() => new FocusPage(), Icons.Target), - new PageItem("Gestures",() => new GesturePage(), Icons.Gesture), - new PageItem("Image",() => new ImagePage(), Icons.Image), - new PageItem("Label",() => new LabelsPage(), Icons.Tag), - new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform), - new PageItem("ListBox",() => new ListBoxPage(), Icons.List), - new PageItem("Menu",() => new MenuPage(), Icons.Menu), - new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation), - new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell), - new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number), - new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D), - new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D), - new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots), - new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info), - new PageItem("Pointers",() => new PointersPage(), Icons.Cursor), - new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress), - new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio), - new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh), - new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout), - new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll), - new PageItem("Slider",() => new SliderPage(), Icons.Tune), - new PageItem("SplitView",() => new SplitViewPage(), Icons.Split), - new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab), - new PageItem("TabControl",() => new TabControlPage(), Icons.Tab), - new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab), - new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput), - new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput), - new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme), - new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle), - new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip), - new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition), - new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree), - new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox), - new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle), - new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window), - new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header), - new PageItem("Screens",() => new ScreenPage(), Icons.Monitor), + new PageItem("Home", () => new HomePage(), Icons.Home, "Overview of everything in the catalog"), + new PageItem("Composition", () => new CompositionPage(), Icons.Layers, "Composition-layer animations and effects", "Media & Graphics"), + new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard, "Keyboard shortcuts that invoke commands", "Interaction"), + new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur, "Translucent acrylic window materials", "Media & Graphics"), + new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle, "Overlay visuals on top of other controls", "Status & Feedback"), + new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput, "Text input with completion suggestions", "Text"), + new PageItem("Border",() => new BorderPage(), Icons.Border, "Decorate elements with borders and corner radii", "Layout"), + new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning, "Cache visuals as bitmaps for performance", "Media & Graphics"), + new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick, "Button, RepeatButton, ToggleButton and friends", "Basic Input"), + new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner, "Content with increment and decrement buttons", "Basic Input"), + new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar, "A month calendar for selecting dates", "Date & Time"), + new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas, "Position children at explicit coordinates", "Layout"), + new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal, "A toolbar of commands with an overflow menu", "Menus & Flyouts"), + new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides, "Cycle through a collection of items", "Collections & Data"), + new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides, "Swipeable page-based navigation", "Navigation & Pages"), + new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox, "Two- and three-state check boxes", "Basic Input"), + new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard, "Read from and write to the system clipboard", "Interaction"), + new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette, "Pick colors from spectrum and palette views", "Basic Input"), + new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown, "A drop-down list of selectable items", "Basic Input"), + new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container, "Styles that respond to container size", "Layout"), + new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document, "A page that hosts a single content view", "Navigation & Pages"), + new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu, "Attach flyouts shown on right-click", "Menus & Flyouts"), + new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu, "Traditional right-click context menus", "Menus & Flyouts"), + new PageItem("Cursor",() => new CursorPage(), Icons.Cursor, "Change the pointer cursor over elements", "Interaction"), + new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush, "Render custom geometry in code", "Media & Graphics"), + new PageItem("DataGrid",() => new DataGridPage(), Icons.Grid, "Tabular data with sorting and editing", "Collections & Data"), + new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield, "Display validation errors from bindings", "Status & Feedback"), + new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock, "Spinner-style date and time pickers", "Date & Time"), + new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar, "A date picker with a drop-down calendar", "Date & Time"), + new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog, "File pickers and modal dialog windows", "Status & Feedback"), + new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop, "Drag data within and between applications", "Interaction"), + new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer, "A page with a sliding navigation drawer", "Navigation & Pages"), + new PageItem("Expander",() => new ExpanderPage(), Icons.Expand, "A header that expands to reveal content", "Layout"), + new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout, "Lightweight popups anchored to controls", "Menus & Flyouts"), + new PageItem("Focus",() => new FocusPage(), Icons.Target, "Track and control keyboard focus", "Interaction"), + new PageItem("Gestures",() => new GesturePage(), Icons.Gesture, "Tap, scroll and pinch gesture recognition", "Interaction"), + new PageItem("Image",() => new ImagePage(), Icons.Image, "Display bitmaps with different stretch modes", "Media & Graphics"), + new PageItem("Label",() => new LabelsPage(), Icons.Tag, "Captions with access keys for other controls", "Text"), + new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform, "Apply transforms that affect layout", "Layout"), + new PageItem("ListBox",() => new ListBoxPage(), Icons.List, "A selectable, virtualized list of items", "Collections & Data"), + new PageItem("Menu",() => new MenuPage(), Icons.Menu, "Menu bars with nested menu items", "Menus & Flyouts"), + new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation, "Stack-based page navigation", "Navigation & Pages"), + new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell, "Toast-style in-app notifications", "Status & Feedback"), + new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number, "Numeric input with spinner buttons", "Basic Input"), + new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D, "Embed custom OpenGL rendering", "Media & Graphics"), + new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D, "Low-level access to the OpenGL context", "Media & Graphics"), + new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots, "Dot-style pager for paginated content", "Collections & Data"), + new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info, "Runtime platform and capability info", "Window & Platform"), + new PageItem("Pointers",() => new PointersPage(), Icons.Cursor, "Raw pointer input and capture", "Interaction"), + new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress, "Determinate and indeterminate progress", "Status & Feedback"), + new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio, "Mutually exclusive option groups", "Basic Input"), + new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh, "Pull-to-refresh for scrollable content", "Collections & Data"), + new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout, "Arrange children relative to each other", "Layout"), + new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll, "Scrollable viewport over large content", "Layout"), + new PageItem("Slider",() => new SliderPage(), Icons.Tune, "Select a value from a continuous range", "Basic Input"), + new PageItem("SplitView",() => new SplitViewPage(), Icons.Split, "A collapsible pane beside content", "Navigation & Pages"), + new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab, "Tab-based page navigation", "Navigation & Pages"), + new PageItem("TabControl",() => new TabControlPage(), Icons.Tab, "Switch between tabbed content views", "Navigation & Pages"), + new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab, "A standalone strip of selectable tabs", "Navigation & Pages"), + new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput, "Single- and multi-line text editing", "Text"), + new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput, "Styled read-only text display", "Text"), + new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme, "Switch between light and dark variants", "Window & Platform"), + new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle, "An on/off switch with a sliding knob", "Basic Input"), + new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip, "Hover hints for any control", "Status & Feedback"), + new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition, "Animate between content changes", "Media & Graphics"), + new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree, "Hierarchical data with expandable nodes", "Collections & Data"), + new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox, "Scale content to fit available space", "Layout"), + new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle, "Host native platform controls", "Window & Platform"), + new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window, "Custom chrome, decorations and sizing", "Window & Platform"), + new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header, "Content paired with a header", "Layout"), + new PageItem("Screens",() => new ScreenPage(), Icons.Monitor, "Enumerate displays and their bounds", "Window & Platform"), }; + /// Section order for the home page card grid. + private static readonly string[] s_categoryOrder = + { + "Basic Input", + "Text", + "Collections & Data", + "Date & Time", + "Menus & Flyouts", + "Navigation & Pages", + "Layout", + "Media & Graphics", + "Status & Feedback", + "Interaction", + "Window & Platform", + }; + + private IReadOnlyList? _homeSections; + + public IReadOnlyList HomeSections => _homeSections ??= + s_categoryOrder + .Select(category => new HomeSection(category, _items.Where(i => i.Category == category).ToArray())) + .Where(section => section.Items.Count > 0) + .ToArray(); + + public void NavigateToPage(PageItem item) + { + // Clear any active search so the target is present in the filtered list. + if (!string.IsNullOrEmpty(Query)) + Query = ""; + + var index = Pages.IndexOf(item); + if (index >= 0) + SelectedPageIndex = index; + } + public AvaloniaList Pages { get; } = new AvaloniaList(); public void Filter(string? query = "") @@ -206,11 +242,19 @@ namespace ControlCatalog.ViewModels } } - class PageItem(string header, Func factory, string? iconData = null) + class HomeSection(string title, IReadOnlyList items) + { + public string Title { get; } = title; + public IReadOnlyList Items { get; } = items; + } + + class PageItem(string header, Func factory, string? iconData = null, string? description = null, string? category = null) { public string Header { get; } = header; public Func Factory { get; } = factory; public string? IconData { get; } = iconData; + public string? Description { get; } = description; + public string? Category { get; } = category; private string SearchKey { get; } = CreateSearchKey(header); public bool IsVisible { get; set; } = true;