Skip to content

Commit 77cad54

Browse files
authored
Merge pull request #1473 from unoplatform/dev/xygu/20251003/zcc-v2
refactor: ZoomContentControl
2 parents e22d0b1 + 6773b84 commit 77cad54

File tree

8 files changed

+1044
-447
lines changed

8 files changed

+1044
-447
lines changed

doc/controls/ZoomContentControl.md

Lines changed: 29 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ uid: Toolkit.Controls.ZoomContentControl
1111

1212
`ZoomContentControl` allows you to display content that can be zoomed in and out, as well as panned. It is especially useful for scenarios such as viewing large images, maps, or documents where users need control over zoom levels and panning.
1313

14-
### C\#
15-
16-
```csharp
17-
public partial class ZoomContentControl : Control
18-
```
19-
2014
### XAML
2115

2216
```xml
@@ -29,43 +23,39 @@ xmlns:utu="using:Uno.Toolkit.UI"
2923
IsZoomAllowed="True"
3024
IsPanAllowed="True">
3125
<utu:ZoomContentControl.Content>
32-
<Image Source="ms-appx:///Assets/Media/LargeMedia.svg"
33-
Stretch="Uniform" />
26+
<Image Source="ms-appx:///Assets/Media/LargeMedia.svg" Stretch="Uniform" />
3427
</utu:ZoomContentControl.Content>
3528
</utu:ZoomContentControl>
3629
```
3730

38-
### Inheritance
39-
40-
`Object` &#8594; `DependencyObject` &#8594; `UIElement` &#8594; `FrameworkElement` &#8594; `Control` &#8594; `ContentControl` &#8594; `ZoomContentControl`
41-
42-
### Constructors
43-
44-
| Constructor | Description |
45-
| ---------------------- | ------------------------------------------------------------- |
46-
| `ZoomContentControl()` | Initializes a new instance of the `ZoomContentControl` class. |
47-
4831
### Properties
4932

50-
| Property | Type | Description |
51-
| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------ |
52-
| `ZoomLevel` | `double` | Gets or sets the current zoom level for the content. |
53-
| `MinZoomLevel` | `double` | Gets or sets the minimum zoom level allowed for the content. |
54-
| `MaxZoomLevel` | `double` | Gets or sets the maximum zoom level allowed for the content. |
55-
| `IsZoomAllowed` | `bool` | Gets or sets a value indicating whether zooming is allowed. |
56-
| `ScaleWheelRatio` | `double` | Gets or sets the ratio for scaling zoom level when using a mouse wheel. |
57-
| `PanWheelRatio` | `double` | Gets or sets the ratio for panning when using a mouse wheel. |
58-
| `IsPanAllowed` | `bool` | Gets or sets a value indicating whether panning is allowed. |
59-
| `IsActive` | `bool` | Gets or sets a value indicating whether the control is active. |
60-
| `AutoFitToCanvas` | `bool` | Determines if the content should automatically fit into the available canvas when the control resizes. |
61-
| `AdditionalMargin` | `Thickness` | Gets or sets additional margins around the content. |
33+
| Property | Type | Description |
34+
| ------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------- |
35+
| `ZoomLevel` | `double` | Gets or sets the current zoom level for the content. |
36+
| `MinZoomLevel` | `double` | Gets or sets the minimum zoom level allowed for the content. |
37+
| `MaxZoomLevel` | `double` | Gets or sets the maximum zoom level allowed for the content. |
38+
| `IsZoomAllowed` | `bool` | Gets or sets a value indicating whether zooming is allowed. |
39+
| `ScaleWheelRatio` | `double` | Gets or sets the ratio for scaling zoom level when using a mouse wheel. |
40+
| `PanWheelRatio` | `double` | Gets or sets the ratio for panning when using a mouse wheel. |
41+
| `IsPanAllowed` | `bool` | Gets or sets a value indicating whether panning is allowed. |
42+
| `IsActive` | `bool` | Gets or sets a value indicating whether the control is active. |
43+
| `AutoFitToCanvas` | `bool` | Gets or sets a value indicating whether the content should be automatically scaled to fit within the viewport. |
44+
| `AutoCenterContent` | `bool` | Gets or sets a value indicating whether the content should be automatically centered within the viewport. |
45+
| `AllowFreePanning` | `bool` | Gets or sets a value indicating whether content can be panned outside of the viewport. |
46+
| `AdditionalMargin` | `Thickness` | Gets or sets additional margins around the content. |
47+
| `ScrollBarLayout` | `ZoomContentControlScrollBarLayout` | Gets or sets the layout style of the scroll bars. |
48+
| `ElementOnFocus` | `FrameworkElement` | Gets or sets the focused element which auto-zoom and auto-fit will be centered around. |
6249

6350
### Methods
6451

65-
| Method | Return Type | Description |
66-
| ----------------- | ----------- | ----------------------------------------------------------------------------------------- |
67-
| `FitToCanvas()` | `void` | Adjust the zoom level so that the content fits within the available space. |
68-
| `ResetViewport()` | `void` | Resets the zoom level and panning offset to their default values and centers the content. |
52+
| Method | Return Type | Description |
53+
| ----------------- | ----------- | ------------------------------------------------------------------- |
54+
| `CenterContent()` | `void` | Centers the content within the viewport. |
55+
| `FitToCanvas()` | `void` | Adjusts the ZoomLevel so that the content fits within the viewport. |
56+
| `ResetViewport()` | `void` | Resets the ZoomLevel to 1, and center the content. |
57+
| `ResetZoom()` | `void` | Resets the ZoomLevel to 1. |
58+
| `ResetScroll()` | `void` | Resets the scroll position to (0,0). |
6959

7060
### Usage
7161

@@ -77,43 +67,17 @@ Below are the built-in interactions for ZoomContentControl usage. For these inte
7767

7868
#### Zooming (Ctrl + Mouse Wheel)
7969

80-
Ctrl + Mouse Wheel: Zoom in/out around the current cursor position.
70+
Ctrl + Mouse Wheel: Zoom in/out around the current cursor position.
8171
The `ScaleWheelRatio` property controls how quickly the zoom factor changes per mouse wheel tick.
8272

8373
#### Scrolling (Mouse Wheel)
8474

85-
Mouse Wheel by itself scrolls vertically.
86-
Shift + Mouse Wheel scrolls horizontally.
75+
Mouse Wheel by itself scrolls vertically.
76+
Shift + Mouse Wheel scrolls horizontally.
8777
The `PanWheelRatio` property determines how many pixels to move per mouse wheel tick.
8878

8979
#### Panning (Middle-Click + Drag)
9080

91-
Press and hold the middle button.
92-
Drag to move the content.
81+
Press and hold the middle button.
82+
Drag to move the content.
9383
Release the mouse button to stop panning.
94-
95-
#### Programmatic Control
96-
97-
Beyond user interactions, you can control zoom and pan directly:
98-
99-
`FitToCanvas()`: Automatically sizes the content so it fits the entire available space.
100-
`ResetViewport()`: Resets both zoom level and offset to their defaults (zoom = 1, scroll offsets = 0).
101-
102-
### Advanced Usage: Overriding Pointer Methods
103-
104-
ZoomContentControl does not subscribe to pointer events directly. Instead, it overrides the base OnPointer methods. This lets you derive from ZoomContentControl and fully customize pointer handling in your subclass. For example:
105-
106-
```csharp
107-
public class MyCustomZoomControl : ZoomContentControl
108-
{
109-
protected override void OnPointerPressed(PointerRoutedEventArgs e)
110-
{
111-
// Skip or extend default behavior:
112-
// base.OnPointerPressed(e);
113-
114-
// Implement your own pointer logic here...
115-
}
116-
}
117-
```
118-
119-
If you do not call `base.OnPointerPressed(e)`, you bypass the built-in pan/zoom logic entirely. This approach lets you disable or alter parts of the default pointer behavior without modifying the original code.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Linq;
2+
using Windows.Foundation;
3+
4+
#if IS_WINUI
5+
using Microsoft.UI.Xaml.Controls;
6+
#else
7+
using Windows.UI.Xaml.Controls;
8+
#endif
9+
10+
namespace Uno.Toolkit.UI;
11+
12+
/// <summary>
13+
/// A container that allows its children to overflow its bounds.
14+
/// </summary>
15+
/// <remarks>This control allows <see cref="ZoomContentControl"/> content to not limited by its viewport.</remarks>
16+
public partial class OverflowContainer : Grid
17+
{
18+
protected override Size MeasureOverride(Size availableSize)
19+
{
20+
if (Children.FirstOrDefault() is { } child)
21+
{
22+
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
23+
return child.DesiredSize;
24+
}
25+
26+
return default;
27+
}
28+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Diagnostics.CodeAnalysis;
4+
5+
namespace Uno.Toolkit.UI;
6+
7+
partial class ZoomContentControl // events
8+
{
9+
#if DEBUG
10+
public event EventHandler? StateChanged;
11+
#endif
12+
13+
public event EventHandler? RenderedContentUpdated;
14+
public event ZoomLevelChangedEventHandler? ZoomLevelChanged;
15+
public event EventHandler? IsActiveChanged;
16+
public event EventHandler? ContentSizeChanged;
17+
public event EventHandler? ViewportSizeChanged;
18+
19+
[Conditional("DEBUG")]
20+
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "It does access instance members, conditionally.")]
21+
private void NotifyStateChanged()
22+
{
23+
#if DEBUG
24+
StateChanged?.Invoke(this, EventArgs.Empty);
25+
#endif
26+
}
27+
28+
public delegate void ZoomLevelChangedEventHandler(object sender, ZoomLevelChangedEventArgs e);
29+
30+
public class ZoomLevelChangedEventArgs : EventArgs
31+
{
32+
public double OldZoomLevel { get; }
33+
public double NewZoomLevel { get; }
34+
public bool FromMouseWheelPanning { get; }
35+
36+
public ZoomLevelChangedEventArgs(double oldZoomLevel, double newZoomLevel, bool fromMouseWheelPanning)
37+
{
38+
OldZoomLevel = oldZoomLevel;
39+
NewZoomLevel = newZoomLevel;
40+
FromMouseWheelPanning = fromMouseWheelPanning;
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)