Browse Source

Merge branch 'master' into UseDynamicResource

pull/1168/head
Steven Kirk 9 years ago
committed by GitHub
parent
commit
8b0b0c1266
  1. 4
      readme.md
  2. BIN
      samples/ControlCatalog/Assets/test_icon.ico
  3. 6
      samples/ControlCatalog/ControlCatalog.csproj
  4. 1
      samples/ControlCatalog/MainView.xaml
  5. 24
      samples/ControlCatalog/Pages/ProgressBarPage.xaml
  6. 18
      samples/ControlCatalog/Pages/ProgressBarPage.xaml.cs
  7. 21
      src/Avalonia.Controls/Orientation.cs
  8. 2
      src/Avalonia.Controls/Primitives/ScrollBar.cs
  9. 139
      src/Avalonia.Controls/ProgressBar.cs
  10. 18
      src/Avalonia.Controls/StackPanel.cs
  11. 5
      src/Avalonia.Themes.Default/ProgressBar.xaml
  12. 22
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  13. 2
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs

4
readme.md

@ -7,7 +7,7 @@
A multi-platform .NET UI framework. It can run on Windows, Linux, Mac OS X, iOS and Android.
![](docs/images/screen.png)
[![](docs/images/screen.png)](https://youtu.be/wHcB3sGLVYg)
Desktop platforms:
@ -36,7 +36,7 @@ Try out the ControlCatalog to give it a quick demo.
Avalonia is a multi-platform windowing toolkit - somewhat like WPF - that is intended to be multi-
platform. It supports XAML, lookless controls and a flexible styling system, and runs on Windows
using Direct2D and other operating systems using Gtk & Cairo.
using Direct2D and other operating systems using Skia and OS-specific windowing backend (GTK, Cocoa, etc).
## Current Status

BIN
samples/ControlCatalog/Assets/test_icon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 172 KiB

6
samples/ControlCatalog/ControlCatalog.csproj

@ -69,6 +69,9 @@
<EmbeddedResource Include="Pages\MenuPage.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Pages\ProgressBarPage.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Pages\RadioButtonPage.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
@ -131,6 +134,9 @@
<Compile Include="Pages\MenuPage.xaml.cs">
<DependentUpon>MenuPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\ProgressBarPage.xaml.cs">
<DependentUpon>ProgressBarPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\RadioButtonPage.xaml.cs">
<DependentUpon>RadioButtonPage.xaml</DependentUpon>
</Compile>

1
samples/ControlCatalog/MainView.xaml

@ -16,6 +16,7 @@
<TabItem Header="Image"><pages:ImagePage/></TabItem>
<TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
<TabItem Header="Menu"><pages:MenuPage/></TabItem>
<TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
<TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
<TabItem Header="Slider"><pages:SliderPage/></TabItem>
<TabItem Header="TextBox"><pages:TextBoxPage/></TabItem>

24
samples/ControlCatalog/Pages/ProgressBarPage.xaml

@ -0,0 +1,24 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<TextBlock Classes="h1">ProgressBar</TextBlock>
<TextBlock Classes="h2">A progress bar control</TextBlock>
<StackPanel>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
<StackPanel Gap="16">
<ProgressBar Value="{Binding #hprogress.Value}" />
<ProgressBar IsIndeterminate="True"/>
</StackPanel>
<ProgressBar Value="{Binding #vprogress.Value}" Orientation="Vertical" />
<ProgressBar Orientation="Vertical" IsIndeterminate="True" />
</StackPanel>
<StackPanel Margin="16">
<Slider Name="hprogress" Maximum="100" Value="40"/>
<Slider Name="vprogress" Maximum="100" Value="60"/>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

18
samples/ControlCatalog/Pages/ProgressBarPage.xaml.cs

@ -0,0 +1,18 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace ControlCatalog.Pages
{
public class ProgressBarPage : UserControl
{
public ProgressBarPage()
{
this.InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}

21
src/Avalonia.Controls/Orientation.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Controls
{
/// <summary>
/// Defines vertical or horizontal orientation.
/// </summary>
public enum Orientation
{
/// <summary>
/// Horizontal orientation.
/// </summary>
Horizontal,
/// <summary>
/// Vertical orientation.
/// </summary>
Vertical,
}
}

2
src/Avalonia.Controls/Primitives/ScrollBar.cs

@ -30,7 +30,7 @@ namespace Avalonia.Controls.Primitives
/// Defines the <see cref="Orientation"/> property.
/// </summary>
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<ScrollBar, Orientation>(nameof(Orientation));
AvaloniaProperty.Register<ScrollBar, Orientation>(nameof(Orientation), Orientation.Vertical);
private Button _lineUpButton;
private Button _lineDownButton;

139
src/Avalonia.Controls/ProgressBar.cs

@ -1,8 +1,12 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive.Linq;
using Avalonia.Animation;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
namespace Avalonia.Controls
{
@ -11,11 +15,38 @@ namespace Avalonia.Controls
/// </summary>
public class ProgressBar : RangeBase
{
public static readonly StyledProperty<bool> IsIndeterminateProperty =
AvaloniaProperty.Register<ProgressBar, bool>(nameof(IsIndeterminate));
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<ProgressBar, Orientation>(nameof(Orientation), Orientation.Horizontal);
private Border _indicator;
private IndeterminateAnimation _indeterminateAnimation;
static ProgressBar()
{
ValueProperty.Changed.AddClassHandler<ProgressBar>(x => x.ValueChanged);
HorizontalAlignmentProperty.OverrideDefaultValue<ProgressBar>(HorizontalAlignment.Left);
VerticalAlignmentProperty.OverrideDefaultValue<ProgressBar>(VerticalAlignment.Top);
IsIndeterminateProperty.Changed.AddClassHandler<ProgressBar>(
(p, e) => { if (p._indicator != null) p.UpdateIsIndeterminate((bool)e.NewValue); });
OrientationProperty.Changed.AddClassHandler<ProgressBar>(
(p, e) => { if (p._indicator != null) p.UpdateOrientation((Orientation)e.NewValue); });
}
public bool IsIndeterminate
{
get => GetValue(IsIndeterminateProperty);
set => SetValue(IsIndeterminateProperty, value);
}
public Orientation Orientation
{
get => GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
/// <inheritdoc/>
@ -29,21 +60,123 @@ namespace Avalonia.Controls
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
{
_indicator = e.NameScope.Get<Border>("PART_Indicator");
UpdateIndicator(Bounds.Size);
UpdateOrientation(Orientation);
UpdateIsIndeterminate(IsIndeterminate);
}
private void UpdateIndicator(Size bounds)
{
if (_indicator != null)
{
double percent = Maximum == Minimum ? 1.0 : (Value - Minimum) / (Maximum - Minimum);
_indicator.Width = bounds.Width * percent;
if (IsIndeterminate)
{
if (Orientation == Orientation.Horizontal)
_indicator.Width = bounds.Width / 5.0;
else
_indicator.Height = bounds.Height / 5.0;
}
else
{
double percent = Maximum == Minimum ? 1.0 : (Value - Minimum) / (Maximum - Minimum);
if (Orientation == Orientation.Horizontal)
_indicator.Width = bounds.Width * percent;
else
_indicator.Height = bounds.Height * percent;
}
}
}
private void UpdateOrientation(Orientation orientation)
{
if (orientation == Orientation.Horizontal)
{
MinHeight = 14;
MinWidth = 200;
_indicator.HorizontalAlignment = HorizontalAlignment.Left;
_indicator.VerticalAlignment = VerticalAlignment.Stretch;
}
else
{
MinHeight = 200;
MinWidth = 14;
_indicator.HorizontalAlignment = HorizontalAlignment.Stretch;
_indicator.VerticalAlignment = VerticalAlignment.Bottom;
}
}
private void UpdateIsIndeterminate(bool isIndeterminate)
{
if (isIndeterminate)
if (_indeterminateAnimation == null || _indeterminateAnimation.Disposed)
_indeterminateAnimation = IndeterminateAnimation.StartAnimation(this);
else
_indeterminateAnimation?.Dispose();
}
private void ValueChanged(AvaloniaPropertyChangedEventArgs e)
{
UpdateIndicator(Bounds.Size);
}
private class IndeterminateAnimation : IDisposable
{
private WeakReference<ProgressBar> _progressBar;
private IDisposable _indeterminateBindSubscription;
private TimeSpan _startTime;
private bool _disposed;
public bool Disposed => _disposed;
private IndeterminateAnimation(ProgressBar progressBar)
{
_progressBar = new WeakReference<ProgressBar>(progressBar);
_startTime = Animate.Stopwatch.Elapsed;
_indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - _startTime).TotalSeconds <= 4.0)
.Select(GetAnimationRect)
.Finally(() => _startTime = Animate.Stopwatch.Elapsed)
.Repeat()
.Subscribe(AnimationTick);
}
public static IndeterminateAnimation StartAnimation(ProgressBar progressBar)
{
return new IndeterminateAnimation(progressBar);
}
private Rect GetAnimationRect(TimeSpan time)
{
if (_progressBar.TryGetTarget(out var progressBar))
{
if (progressBar.Orientation == Orientation.Horizontal)
return new Rect(-progressBar._indicator.Width - 5 + (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Width + progressBar._indicator.Width + 10), 0, progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height);
else
return new Rect(0, progressBar.Bounds.Height + 5 - (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Height + progressBar._indicator.Height + 10), progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height);
}
else
{
_indeterminateBindSubscription.Dispose();
return Rect.Empty;
}
}
private void AnimationTick(Rect rect)
{
if (_progressBar.TryGetTarget(out var progressBar))
progressBar._indicator.Arrange(rect);
else
_indeterminateBindSubscription.Dispose();
}
public void Dispose()
{
_indeterminateBindSubscription?.Dispose();
_disposed = true;
}
}
}
}

18
src/Avalonia.Controls/StackPanel.cs

@ -6,22 +6,6 @@ using Avalonia.Input;
namespace Avalonia.Controls
{
/// <summary>
/// Defines vertical or horizontal orientation.
/// </summary>
public enum Orientation
{
/// <summary>
/// Vertical orientation.
/// </summary>
Vertical,
/// <summary>
/// Horizontal orientation.
/// </summary>
Horizontal,
}
/// <summary>
/// A panel which lays out its children horizontally or vertically.
/// </summary>
@ -37,7 +21,7 @@ namespace Avalonia.Controls
/// Defines the <see cref="Orientation"/> property.
/// </summary>
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<StackPanel, Orientation>(nameof(Orientation));
AvaloniaProperty.Register<StackPanel, Orientation>(nameof(Orientation), Orientation.Vertical);
/// <summary>
/// Initializes static members of the <see cref="StackPanel"/> class.

5
src/Avalonia.Themes.Default/ProgressBar.xaml

@ -1,8 +1,6 @@
<Style xmlns="https://github.com/avaloniaui" Selector="ProgressBar">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}"/>
<Setter Property="Foreground" Value="{DynamicResource ThemeAccentBrush}"/>
<Setter Property="MinHeight" Value="14"/>
<Setter Property="MinWidth" Value="200"/>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
@ -14,8 +12,7 @@
BorderBrush="{TemplateBinding Background}"/>
<Border Name="PART_Indicator"
BorderThickness="1"
Background="{TemplateBinding Foreground}"
HorizontalAlignment="Left"/>
Background="{TemplateBinding Foreground}"/>
</Grid>
</Border>
</ControlTemplate>

22
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -54,11 +54,6 @@ namespace Avalonia.Gtk3
Connect<Native.D.signal_generic>("destroy", OnDestroy);
Native.GtkWidgetRealize(gtkWidget);
_lastSize = ClientSize;
GlibTimeout.Add(0, 16, () =>
{
Invalidate(default(Rect));
return true;
});
if (Gtk3Platform.UseDeferredRendering)
{
Native.GtkWidgetSetDoubleBuffered(gtkWidget, false);
@ -138,7 +133,7 @@ namespace Avalonia.Gtk3
? RawMouseEventType.LeftButtonDown
: evnt->button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown,
new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state));
Input?.Invoke(e);
OnInput(e);
return true;
}
@ -166,7 +161,7 @@ namespace Avalonia.Gtk3
_inputRoot,
RawMouseEventType.Move,
position, GetModifierKeys(evnt->state));
Input(e);
OnInput(e);
return true;
}
@ -195,7 +190,7 @@ namespace Avalonia.Gtk3
}
var e = new RawMouseWheelEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot,
new Point(evnt->x, evnt->y), delta, GetModifierKeys(evnt->state));
Input(e);
OnInput(e);
return true;
}
@ -210,7 +205,7 @@ namespace Avalonia.Gtk3
evnt->time,
evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state));
Input(e);
OnInput(e);
return true;
}
@ -218,7 +213,7 @@ namespace Avalonia.Gtk3
{
var evnt = (GdkEventCrossing*) pev;
var position = new Point(evnt->x, evnt->y);
Input(new RawMouseEventArgs(Gtk3Platform.Mouse,
OnInput(new RawMouseEventArgs(Gtk3Platform.Mouse,
evnt->time,
_inputRoot,
RawMouseEventType.Move,
@ -228,7 +223,7 @@ namespace Avalonia.Gtk3
private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
{
Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
OnInput(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
return true;
}
@ -338,6 +333,11 @@ namespace Avalonia.Gtk3
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
void OnInput(RawInputEventArgs args)
{
Dispatcher.UIThread.InvokeAsync(() => Input?.Invoke(args), DispatcherPriority.Input);
}
public Point PointToClient(Point point)
{
int x, y;

2
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -45,7 +45,7 @@ namespace Avalonia.Skia
var s = sourceRect.ToSKRect();
var d = destRect.ToSKRect();
using (var paint = new SKPaint()
{ Color = new SKColor(255, 255, 255, (byte)(255 * opacity)) })
{ Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity)) })
{
Canvas.DrawBitmap(impl.Bitmap, s, d, paint);
}

Loading…
Cancel
Save