Browse Source

Merge branch 'master' into add-itemscontrol-istextsearchenabled

pull/6210/head
Max Katz 5 years ago
committed by GitHub
parent
commit
7b5b848d3a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .gitignore
  2. 196
      native/Avalonia.Native/inc/comimpl.h
  3. 32
      native/Avalonia.Native/src/OSX/AvnString.mm
  4. 4
      native/Avalonia.Native/src/OSX/Screens.mm
  5. 8
      native/Avalonia.Native/src/OSX/cgl.mm
  6. 82
      native/Avalonia.Native/src/OSX/clipboard.mm
  7. 63
      native/Avalonia.Native/src/OSX/controlhost.mm
  8. 52
      native/Avalonia.Native/src/OSX/cursor.mm
  9. 174
      native/Avalonia.Native/src/OSX/main.mm
  10. 22
      native/Avalonia.Native/src/OSX/menu.mm
  11. 2
      native/Avalonia.Native/src/OSX/platformthreading.mm
  12. 6
      native/Avalonia.Native/src/OSX/rendertarget.mm
  13. 220
      native/Avalonia.Native/src/OSX/window.mm
  14. 10
      samples/Sandbox/Program.cs
  15. 103
      src/Avalonia.Controls/Shapes/Arc.cs
  16. 2
      src/Avalonia.Controls/TextBox.cs
  17. 39
      src/Avalonia.Controls/Window.cs
  18. 3
      src/Avalonia.Visuals/ApiCompatBaseline.txt
  19. 3
      src/Avalonia.Visuals/Media/Brush.cs
  20. 11
      src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs
  21. 14
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
  22. 9
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  23. 136
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  24. 20
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
  25. 2
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs
  26. 20
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
  27. 2
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
  28. 2
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs

3
.gitignore

@ -106,6 +106,9 @@ _NCrunch_*/
*.ncrunchsolution.user
nCrunchTemp_*
# CodeRush
.cr/
# Others
sql/
*.Cache

196
native/Avalonia.Native/inc/comimpl.h

@ -8,8 +8,109 @@
#include <cstring>
/**
START_COM_CALL causes AddRef to be called at the beggining of a function.
When a function is exited, it causes ReleaseRef to be called.
This ensures that the object cannot be destroyed whilst the function is running.
For example: Window Show is called, which triggers an event, and user calls Close inside the event
causing the refcount to reach 0, and the object to be destroyed. Function then continues and this pointer
will now be invalid.
START_COM_CALL protects against this scenario.
*/
#define START_COM_CALL auto r = this->UnknownSelf()
__IID_DEF(IUnknown, 0, 0, 0, C0, 00, 00, 00, 00, 00, 00, 46);
template<class TInterface>
class ComPtr
{
private:
TInterface* _obj;
public:
ComPtr()
{
_obj = 0;
}
ComPtr(TInterface* pObj)
{
_obj = 0;
if (pObj)
{
_obj = pObj;
_obj->AddRef();
}
}
ComPtr(const ComPtr& ptr)
{
_obj = 0;
if (ptr._obj)
{
_obj = ptr._obj;
_obj->AddRef();
}
}
ComPtr& operator=(ComPtr other)
{
if(_obj != NULL)
_obj->Release();
_obj = other._obj;
if(_obj != NULL)
_obj->AddRef();
return *this;
}
~ComPtr()
{
if (_obj)
{
_obj->Release();
_obj = 0;
}
}
TInterface* getRaw()
{
return _obj;
}
TInterface* getRetainedReference()
{
if(_obj == NULL)
return NULL;
_obj->AddRef();
return _obj;
}
TInterface** getPPV()
{
return &_obj;
}
operator TInterface*() const
{
return _obj;
}
TInterface& operator*() const
{
return *_obj;
}
TInterface** operator&()
{
return &_obj;
}
TInterface* operator->() const
{
return _obj;
}
};
class ComObject : public virtual IUnknown
{
private:
@ -58,6 +159,12 @@ public:
_refCount++;
return S_OK;
}
protected:
ComPtr<IUnknown> UnknownSelf()
{
return this;
}
};
@ -104,94 +211,5 @@ public:
virtual ~ComSingleObject(){}
};
template<class TInterface>
class ComPtr
{
private:
TInterface* _obj;
public:
ComPtr()
{
_obj = 0;
}
ComPtr(TInterface* pObj)
{
_obj = 0;
if (pObj)
{
_obj = pObj;
_obj->AddRef();
}
}
ComPtr(const ComPtr& ptr)
{
_obj = 0;
if (ptr._obj)
{
_obj = ptr._obj;
_obj->AddRef();
}
}
ComPtr& operator=(ComPtr other)
{
if(_obj != NULL)
_obj->Release();
_obj = other._obj;
if(_obj != NULL)
_obj->AddRef();
return *this;
}
~ComPtr()
{
if (_obj)
{
_obj->Release();
_obj = 0;
}
}
TInterface* getRaw()
{
return _obj;
}
TInterface* getRetainedReference()
{
if(_obj == NULL)
return NULL;
_obj->AddRef();
return _obj;
}
TInterface** getPPV()
{
return &_obj;
}
operator TInterface*() const
{
return _obj;
}
TInterface& operator*() const
{
return *_obj;
}
TInterface** operator&()
{
return &_obj;
}
TInterface* operator->() const
{
return _obj;
}
};
#endif // COMIMPL_H_INCLUDED
#pragma clang diagnostic pop

32
native/Avalonia.Native/src/OSX/AvnString.mm

@ -43,6 +43,8 @@ public:
virtual HRESULT Pointer(void**retOut) override
{
START_COM_CALL;
@autoreleasepool
{
if(retOut == nullptr)
@ -58,14 +60,19 @@ public:
virtual HRESULT Length(int*retOut) override
{
if(retOut == nullptr)
START_COM_CALL;
@autoreleasepool
{
return E_POINTER;
if(retOut == nullptr)
{
return E_POINTER;
}
*retOut = _length;
return S_OK;
}
*retOut = _length;
return S_OK;
}
};
@ -109,10 +116,15 @@ public:
virtual HRESULT Get(unsigned int index, IAvnString**ppv) override
{
if(_list.size() <= index)
return E_INVALIDARG;
*ppv = _list[index].getRetainedReference();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
if(_list.size() <= index)
return E_INVALIDARG;
*ppv = _list[index].getRetainedReference();
return S_OK;
}
}
};

4
native/Avalonia.Native/src/OSX/Screens.mm

@ -8,6 +8,8 @@ class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens>
public:
virtual HRESULT GetScreenCount (int* ret) override
{
START_COM_CALL;
@autoreleasepool
{
*ret = (int)[NSScreen screens].count;
@ -18,6 +20,8 @@ public:
virtual HRESULT GetScreen (int index, AvnScreen* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(index < 0 || index >= [NSScreen screens].count)

8
native/Avalonia.Native/src/OSX/cgl.mm

@ -69,6 +69,8 @@ public:
virtual HRESULT LegacyMakeCurrent() override
{
START_COM_CALL;
if(CGLSetCurrentContext(Context) != 0)
return E_FAIL;
return S_OK;
@ -76,6 +78,8 @@ public:
virtual HRESULT MakeCurrent(IUnknown** ppv) override
{
START_COM_CALL;
CGLContextObj saved = CGLGetCurrentContext();
CGLLockContext(Context);
if(CGLSetCurrentContext(Context) != 0)
@ -128,6 +132,8 @@ public:
virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) override
{
START_COM_CALL;
CGLContextObj shareContext = nil;
if(share != nil)
{
@ -144,6 +150,8 @@ public:
virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) override
{
START_COM_CALL;
if(native == nil)
return E_INVALIDARG;
*ppv = new AvnGlContext((CGLContextObj) native);

82
native/Avalonia.Native/src/OSX/clipboard.mm

@ -25,6 +25,8 @@ public:
virtual HRESULT GetText (char* type, IAvnString**ppv) override
{
START_COM_CALL;
@autoreleasepool
{
if(ppv == nullptr)
@ -42,6 +44,8 @@ public:
virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv= nil;
@ -69,56 +73,71 @@ public:
virtual HRESULT SetText (char* type, char* utf8String) override
{
Clear();
START_COM_CALL;
@autoreleasepool
{
Clear();
auto string = [NSString stringWithUTF8String:(const char*)utf8String];
auto typeString = [NSString stringWithUTF8String:(const char*)type];
if(_item == nil)
[_pb setString: string forType: typeString];
else
[_item setString: string forType:typeString];
}
return S_OK;
return S_OK;
}
}
virtual HRESULT SetBytes(char* type, void* bytes, int len) override
{
auto typeString = [NSString stringWithUTF8String:(const char*)type];
auto data = [NSData dataWithBytes:bytes length:len];
if(_item == nil)
[_pb setData:data forType:typeString];
else
[_item setData:data forType:typeString];
return S_OK;
START_COM_CALL;
@autoreleasepool
{
auto typeString = [NSString stringWithUTF8String:(const char*)type];
auto data = [NSData dataWithBytes:bytes length:len];
if(_item == nil)
[_pb setData:data forType:typeString];
else
[_item setData:data forType:typeString];
return S_OK;
}
}
virtual HRESULT GetBytes(char* type, IAvnString**ppv) override
{
*ppv = nil;
auto typeString = [NSString stringWithUTF8String:(const char*)type];
NSData*data;
@try
START_COM_CALL;
@autoreleasepool
{
if(_item)
data = [_item dataForType:typeString];
else
data = [_pb dataForType:typeString];
if(data == nil)
*ppv = nil;
auto typeString = [NSString stringWithUTF8String:(const char*)type];
NSData*data;
@try
{
if(_item)
data = [_item dataForType:typeString];
else
data = [_pb dataForType:typeString];
if(data == nil)
return E_FAIL;
}
@catch(NSException* e)
{
return E_FAIL;
}
*ppv = CreateByteArray((void*)data.bytes, (int)data.length);
return S_OK;
}
@catch(NSException* e)
{
return E_FAIL;
}
*ppv = CreateByteArray((void*)data.bytes, (int)data.length);
return S_OK;
}
virtual HRESULT Clear() override
{
START_COM_CALL;
@autoreleasepool
{
if(_item != nil)
@ -128,15 +147,20 @@ public:
[_pb clearContents];
[_pb setString:@"" forType:NSPasteboardTypeString];
}
}
return S_OK;
return S_OK;
}
}
virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
{
*ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
return S_OK;
}
}
};

63
native/Avalonia.Native/src/OSX/controlhost.mm

@ -16,11 +16,16 @@ public:
virtual HRESULT CreateDefaultChild(void* parent, void** retOut) override
{
NSView* view = [NSView new];
[view setWantsLayer: true];
START_COM_CALL;
*retOut = (__bridge_retained void*)view;
return S_OK;
@autoreleasepool
{
NSView* view = [NSView new];
[view setWantsLayer: true];
*retOut = (__bridge_retained void*)view;
return S_OK;
}
};
virtual IAvnNativeControlHostTopLevelAttachment* CreateAttachment() override
@ -69,32 +74,42 @@ public:
virtual HRESULT InitializeWithChildHandle(void* child) override
{
if(_child != nil)
return E_FAIL;
_child = (__bridge NSView*)child;
if(_child == nil)
return E_FAIL;
[_holder addSubview:_child];
[_child setHidden: false];
return S_OK;
START_COM_CALL;
@autoreleasepool
{
if(_child != nil)
return E_FAIL;
_child = (__bridge NSView*)child;
if(_child == nil)
return E_FAIL;
[_holder addSubview:_child];
[_child setHidden: false];
return S_OK;
}
};
virtual HRESULT AttachTo(IAvnNativeControlHost* host) override
{
if(host == nil)
{
[_holder removeFromSuperview];
[_holder setHidden: true];
}
else
START_COM_CALL;
@autoreleasepool
{
AvnNativeControlHost* chost = dynamic_cast<AvnNativeControlHost*>(host);
if(chost == nil || chost->View == nil)
return E_FAIL;
[_holder setHidden:true];
[chost->View addSubview:_holder];
if(host == nil)
{
[_holder removeFromSuperview];
[_holder setHidden: true];
}
else
{
AvnNativeControlHost* chost = dynamic_cast<AvnNativeControlHost*>(host);
if(chost == nil || chost->View == nil)
return E_FAIL;
[_holder setHidden:true];
[chost->View addSubview:_holder];
}
return S_OK;
}
return S_OK;
};
virtual void ShowInBounds(float x, float y, float width, float height) override

52
native/Avalonia.Native/src/OSX/cursor.mm

@ -53,36 +53,46 @@ public:
virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) override
{
*retOut = s_cursorMap[cursorType];
START_COM_CALL;
if(*retOut != nullptr)
@autoreleasepool
{
(*retOut)->AddRef();
}
*retOut = s_cursorMap[cursorType];
return S_OK;
if(*retOut != nullptr)
{
(*retOut)->AddRef();
}
return S_OK;
}
}
virtual HRESULT CreateCustomCursor (void* bitmapData, size_t length, AvnPixelSize hotPixel, IAvnCursor** retOut) override
{
if(bitmapData == nullptr || retOut == nullptr)
START_COM_CALL;
@autoreleasepool
{
return E_POINTER;
if(bitmapData == nullptr || retOut == nullptr)
{
return E_POINTER;
}
NSData *imageData = [NSData dataWithBytes:bitmapData length:length];
NSImage *image = [[NSImage alloc] initWithData:imageData];
NSPoint hotSpot;
hotSpot.x = hotPixel.Width;
hotSpot.y = hotPixel.Height;
*retOut = new Cursor([[NSCursor new] initWithImage: image hotSpot: hotSpot]);
(*retOut)->AddRef();
return S_OK;
}
NSData *imageData = [NSData dataWithBytes:bitmapData length:length];
NSImage *image = [[NSImage alloc] initWithData:imageData];
NSPoint hotSpot;
hotSpot.x = hotPixel.Width;
hotSpot.y = hotPixel.Height;
*retOut = new Cursor([[NSCursor new] initWithImage: image hotSpot: hotSpot]);
(*retOut)->AddRef();
return S_OK;
}
};

174
native/Avalonia.Native/src/OSX/main.mm

@ -107,27 +107,42 @@ public:
virtual HRESULT SetApplicationTitle(char* utf8String) override
{
auto appTitle = [NSString stringWithUTF8String: utf8String];
START_COM_CALL;
[[NSProcessInfo processInfo] setProcessName:appTitle];
SetProcessName(appTitle);
return S_OK;
@autoreleasepool
{
auto appTitle = [NSString stringWithUTF8String: utf8String];
[[NSProcessInfo processInfo] setProcessName:appTitle];
SetProcessName(appTitle);
return S_OK;
}
}
virtual HRESULT SetShowInDock(int show) override
{
AvnDesiredActivationPolicy = show
? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
return S_OK;
START_COM_CALL;
@autoreleasepool
{
AvnDesiredActivationPolicy = show
? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
return S_OK;
}
}
virtual HRESULT SetDisableDefaultApplicationMenuItems (bool enabled) override
{
SetAutoGenerateDefaultAppMenuItems(!enabled);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
SetAutoGenerateDefaultAppMenuItems(!enabled);
return S_OK;
}
}
};
@ -165,6 +180,8 @@ public:
FORWARD_IUNKNOWN()
virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator, IAvnApplicationEvents* events) override
{
START_COM_CALL;
_deallocator = deallocator;
@autoreleasepool{
[[ThreadingInitializer new] do];
@ -180,89 +197,154 @@ public:
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) override
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;
*ppv = CreateAvnWindow(cb, gl);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;
*ppv = CreateAvnWindow(cb, gl);
return S_OK;
}
};
virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) override
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;
START_COM_CALL;
*ppv = CreateAvnPopup(cb, gl);
return S_OK;
@autoreleasepool
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;
*ppv = CreateAvnPopup(cb, gl);
return S_OK;
}
}
virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) override
{
*ppv = CreatePlatformThreading();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = CreatePlatformThreading();
return S_OK;
}
}
virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) override
{
*ppv = ::CreateSystemDialogs();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateSystemDialogs();
return S_OK;
}
}
virtual HRESULT CreateScreens (IAvnScreens** ppv) override
{
*ppv = ::CreateScreens ();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateScreens ();
return S_OK;
}
}
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
{
*ppv = ::CreateClipboard (nil, nil);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateClipboard (nil, nil);
return S_OK;
}
}
virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
{
*ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
return S_OK;
}
}
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) override
{
*ppv = ::CreateCursorFactory();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateCursorFactory();
return S_OK;
}
}
virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) override
{
auto rv = ::GetGlDisplay();
if(rv == NULL)
return E_FAIL;
rv->AddRef();
*ppv = rv;
return S_OK;
START_COM_CALL;
@autoreleasepool
{
auto rv = ::GetGlDisplay();
if(rv == NULL)
return E_FAIL;
rv->AddRef();
*ppv = rv;
return S_OK;
}
}
virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) override
{
*ppv = ::CreateAppMenu(cb);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateAppMenu(cb);
return S_OK;
}
}
virtual HRESULT CreateMenuItem (IAvnMenuItem** ppv) override
{
*ppv = ::CreateAppMenuItem();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateAppMenuItem();
return S_OK;
}
}
virtual HRESULT CreateMenuItemSeparator (IAvnMenuItem** ppv) override
{
*ppv = ::CreateAppMenuItemSeparator();
return S_OK;
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateAppMenuItemSeparator();
return S_OK;
}
}
virtual HRESULT SetAppMenu (IAvnMenu* appMenu) override
{
::SetAppMenu(s_appTitle, appMenu);
return S_OK;
START_COM_CALL;
@autoreleasepool
{
::SetAppMenu(s_appTitle, appMenu);
return S_OK;
}
}
};

22
native/Avalonia.Native/src/OSX/menu.mm

@ -95,6 +95,8 @@ NSMenuItem* AvnAppMenuItem::GetNative()
HRESULT AvnAppMenuItem::SetSubMenu (IAvnMenu* menu)
{
START_COM_CALL;
@autoreleasepool
{
if(menu != nullptr)
@ -114,6 +116,8 @@ HRESULT AvnAppMenuItem::SetSubMenu (IAvnMenu* menu)
HRESULT AvnAppMenuItem::SetTitle (char* utf8String)
{
START_COM_CALL;
@autoreleasepool
{
if (utf8String != nullptr)
@ -128,6 +132,8 @@ HRESULT AvnAppMenuItem::SetTitle (char* utf8String)
HRESULT AvnAppMenuItem::SetGesture (AvnKey key, AvnInputModifiers modifiers)
{
START_COM_CALL;
@autoreleasepool
{
if(key != AvnKeyNone)
@ -183,6 +189,8 @@ HRESULT AvnAppMenuItem::SetGesture (AvnKey key, AvnInputModifiers modifiers)
HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback)
{
START_COM_CALL;
@autoreleasepool
{
_predicate = predicate;
@ -193,6 +201,8 @@ HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionC
HRESULT AvnAppMenuItem::SetIsChecked (bool isChecked)
{
START_COM_CALL;
@autoreleasepool
{
[_native setState:(isChecked && _isCheckable ? NSOnState : NSOffState)];
@ -202,6 +212,8 @@ HRESULT AvnAppMenuItem::SetIsChecked (bool isChecked)
HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType)
{
START_COM_CALL;
@autoreleasepool
{
switch(toggleType)
@ -231,6 +243,8 @@ HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType)
HRESULT AvnAppMenuItem::SetIcon(void *data, size_t length)
{
START_COM_CALL;
@autoreleasepool
{
if(data != nullptr)
@ -317,6 +331,8 @@ void AvnAppMenu::RaiseClosed()
HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
{
START_COM_CALL;
@autoreleasepool
{
if([_native hasGlobalMenuItem])
@ -337,6 +353,8 @@ HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
HRESULT AvnAppMenu::RemoveItem (IAvnMenuItem* item)
{
START_COM_CALL;
@autoreleasepool
{
auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item);
@ -352,6 +370,8 @@ HRESULT AvnAppMenu::RemoveItem (IAvnMenuItem* item)
HRESULT AvnAppMenu::SetTitle (char* utf8String)
{
START_COM_CALL;
@autoreleasepool
{
if (utf8String != nullptr)
@ -365,6 +385,8 @@ HRESULT AvnAppMenu::SetTitle (char* utf8String)
HRESULT AvnAppMenu::Clear()
{
START_COM_CALL;
@autoreleasepool
{
[_native removeAllItems];

2
native/Avalonia.Native/src/OSX/platformthreading.mm

@ -114,6 +114,8 @@ public:
virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) override
{
START_COM_CALL;
auto can = dynamic_cast<LoopCancellation*>(cancel);
if(can->Cancelled)
return S_OK;

6
native/Avalonia.Native/src/OSX/rendertarget.mm

@ -247,6 +247,8 @@ public:
virtual HRESULT GetPixelSize(AvnPixelSize* ret) override
{
START_COM_CALL;
if(!_surface)
return E_FAIL;
*ret = _surface->size;
@ -255,6 +257,8 @@ public:
virtual HRESULT GetScaling(double* ret) override
{
START_COM_CALL;
if(!_surface)
return E_FAIL;
*ret = _surface->scale;
@ -281,6 +285,8 @@ public:
virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) override
{
START_COM_CALL;
ComPtr<IUnknown> releaseContext;
@synchronized (_target->lock) {
if(_target->surface == nil)

220
native/Avalonia.Native/src/OSX/window.mm

@ -54,6 +54,8 @@ public:
virtual HRESULT ObtainNSWindowHandle(void** ret) override
{
START_COM_CALL;
if (ret == nullptr)
{
return E_POINTER;
@ -66,6 +68,8 @@ public:
virtual HRESULT ObtainNSWindowHandleRetained(void** ret) override
{
START_COM_CALL;
if (ret == nullptr)
{
return E_POINTER;
@ -78,6 +82,8 @@ public:
virtual HRESULT ObtainNSViewHandle(void** ret) override
{
START_COM_CALL;
if (ret == nullptr)
{
return E_POINTER;
@ -90,6 +96,8 @@ public:
virtual HRESULT ObtainNSViewHandleRetained(void** ret) override
{
START_COM_CALL;
if (ret == nullptr)
{
return E_POINTER;
@ -107,23 +115,27 @@ public:
virtual HRESULT Show(bool activate) override
{
START_COM_CALL;
@autoreleasepool
{
SetPosition(lastPositionSet);
UpdateStyle();
[Window setContentView: StandardContainer];
[Window setTitle:_lastTitle];
if(ShouldTakeFocusOnShow() && activate)
{
[Window orderFront: Window];
[Window makeKeyAndOrderFront:Window];
[Window makeFirstResponder:View];
[NSApp activateIgnoringOtherApps:YES];
}
else
{
[Window orderFront: Window];
}
[Window setTitle:_lastTitle];
_shown = true;
@ -138,6 +150,8 @@ public:
virtual HRESULT Hide () override
{
START_COM_CALL;
@autoreleasepool
{
if(Window != nullptr)
@ -152,6 +166,8 @@ public:
virtual HRESULT Activate () override
{
START_COM_CALL;
@autoreleasepool
{
if(Window != nullptr)
@ -166,6 +182,8 @@ public:
virtual HRESULT SetTopMost (bool value) override
{
START_COM_CALL;
@autoreleasepool
{
[Window setLevel: value ? NSFloatingWindowLevel : NSNormalWindowLevel];
@ -176,11 +194,16 @@ public:
virtual HRESULT Close() override
{
START_COM_CALL;
@autoreleasepool
{
if (Window != nullptr)
{
[Window close];
auto window = Window;
Window = nullptr;
[window close];
}
return S_OK;
@ -189,6 +212,8 @@ public:
virtual HRESULT GetClientSize(AvnSize* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -219,6 +244,8 @@ public:
virtual HRESULT GetScaling (double* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -237,6 +264,8 @@ public:
virtual HRESULT SetMinMaxSize (AvnSize minSize, AvnSize maxSize) override
{
START_COM_CALL;
@autoreleasepool
{
[Window setMinSize: ToNSSize(minSize)];
@ -248,6 +277,8 @@ public:
virtual HRESULT Resize(double x, double y) override
{
START_COM_CALL;
@autoreleasepool
{
auto maxSize = [Window maxSize];
@ -287,6 +318,8 @@ public:
virtual HRESULT Invalidate (AvnRect rect) override
{
START_COM_CALL;
@autoreleasepool
{
[View setNeedsDisplayInRect:[View frame]];
@ -297,6 +330,8 @@ public:
virtual HRESULT SetMainMenu(IAvnMenu* menu) override
{
START_COM_CALL;
_mainMenu = menu;
auto nativeMenu = dynamic_cast<AvnAppMenu*>(menu);
@ -315,6 +350,8 @@ public:
virtual HRESULT BeginMoveDrag () override
{
START_COM_CALL;
@autoreleasepool
{
auto lastEvent = [View lastMouseDownEvent];
@ -332,11 +369,15 @@ public:
virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) override
{
START_COM_CALL;
return S_OK;
}
virtual HRESULT GetPosition (AvnPoint* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -357,6 +398,8 @@ public:
virtual HRESULT SetPosition (AvnPoint point) override
{
START_COM_CALL;
@autoreleasepool
{
lastPositionSet = point;
@ -368,6 +411,8 @@ public:
virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -386,6 +431,8 @@ public:
virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -403,12 +450,16 @@ public:
virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) override
{
START_COM_CALL;
[View setSwRenderedFrame: fb dispose: dispose];
return S_OK;
}
virtual HRESULT SetCursor(IAvnCursor* cursor) override
{
START_COM_CALL;
@autoreleasepool
{
Cursor* avnCursor = dynamic_cast<Cursor*>(cursor);
@ -438,6 +489,8 @@ public:
virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ppv) override
{
START_COM_CALL;
if(View == NULL)
return E_FAIL;
*ppv = [renderTarget createSurfaceRenderTarget];
@ -446,6 +499,8 @@ public:
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost** retOut) override
{
START_COM_CALL;
if(View == NULL)
return E_FAIL;
*retOut = ::CreateNativeControlHost(View);
@ -454,6 +509,8 @@ public:
virtual HRESULT SetBlurEnabled (bool enable) override
{
START_COM_CALL;
[StandardContainer ShowBlur:enable];
return S_OK;
@ -463,6 +520,8 @@ public:
IAvnClipboard* clipboard, IAvnDndResultCallback* cb,
void* sourceHandle) override
{
START_COM_CALL;
auto item = TryGetPasteboardItem(clipboard);
[item setString:@"" forType:GetAvnCustomDataType()];
if(item == nil)
@ -564,6 +623,11 @@ private:
void HideOrShowTrafficLights ()
{
if (Window == nil)
{
return;
}
for (id subview in Window.contentView.superview.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"NSTitlebarContainerView")]) {
NSView *titlebarView = [subview subviews][0];
@ -590,8 +654,10 @@ private:
virtual HRESULT Show (bool activate) override
{
START_COM_CALL;
@autoreleasepool
{
{
WindowBaseImpl::Show(activate);
HideOrShowTrafficLights();
@ -602,6 +668,8 @@ private:
virtual HRESULT SetEnabled (bool enable) override
{
START_COM_CALL;
@autoreleasepool
{
[Window setEnabled:enable];
@ -611,6 +679,8 @@ private:
virtual HRESULT SetParent (IAvnWindow* parent) override
{
START_COM_CALL;
@autoreleasepool
{
if(parent == nullptr)
@ -722,6 +792,8 @@ private:
virtual HRESULT SetCanResize(bool value) override
{
START_COM_CALL;
@autoreleasepool
{
_canResize = value;
@ -732,6 +804,8 @@ private:
virtual HRESULT SetDecorations(SystemDecorations value) override
{
START_COM_CALL;
@autoreleasepool
{
auto currentWindowState = _lastWindowState;
@ -797,6 +871,8 @@ private:
virtual HRESULT SetTitle (char* utf8title) override
{
START_COM_CALL;
@autoreleasepool
{
_lastTitle = [NSString stringWithUTF8String:(const char*)utf8title];
@ -808,6 +884,8 @@ private:
virtual HRESULT SetTitleBarColor(AvnColor color) override
{
START_COM_CALL;
@autoreleasepool
{
float a = (float)color.Alpha / 255.0f;
@ -837,6 +915,8 @@ private:
virtual HRESULT GetWindowState (AvnWindowState*ret) override
{
START_COM_CALL;
@autoreleasepool
{
if(ret == nullptr)
@ -870,86 +950,111 @@ private:
virtual HRESULT TakeFocusFromChildren () override
{
if(Window == nil)
return S_OK;
if([Window isKeyWindow])
[Window makeFirstResponder: View];
START_COM_CALL;
return S_OK;
@autoreleasepool
{
if(Window == nil)
return S_OK;
if([Window isKeyWindow])
[Window makeFirstResponder: View];
return S_OK;
}
}
virtual HRESULT SetExtendClientArea (bool enable) override
{
_isClientAreaExtended = enable;
START_COM_CALL;
if(enable)
@autoreleasepool
{
Window.titleVisibility = NSWindowTitleHidden;
[Window setTitlebarAppearsTransparent:true];
auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
if (wantsTitleBar)
{
[StandardContainer ShowTitleBar:true];
}
else
{
[StandardContainer ShowTitleBar:false];
}
_isClientAreaExtended = enable;
if(_extendClientHints & AvnOSXThickTitleBar)
if(enable)
{
Window.toolbar = [NSToolbar new];
Window.toolbar.showsBaselineSeparator = false;
Window.titleVisibility = NSWindowTitleHidden;
[Window setTitlebarAppearsTransparent:true];
auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
if (wantsTitleBar)
{
[StandardContainer ShowTitleBar:true];
}
else
{
[StandardContainer ShowTitleBar:false];
}
if(_extendClientHints & AvnOSXThickTitleBar)
{
Window.toolbar = [NSToolbar new];
Window.toolbar.showsBaselineSeparator = false;
}
else
{
Window.toolbar = nullptr;
}
}
else
{
Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr;
[Window setTitlebarAppearsTransparent:false];
View.layer.zPosition = 0;
}
[Window setIsExtended:enable];
HideOrShowTrafficLights();
UpdateStyle();
return S_OK;
}
else
{
Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr;
[Window setTitlebarAppearsTransparent:false];
View.layer.zPosition = 0;
}
[Window setIsExtended:enable];
HideOrShowTrafficLights();
UpdateStyle();
return S_OK;
}
virtual HRESULT SetExtendClientAreaHints (AvnExtendClientAreaChromeHints hints) override
{
_extendClientHints = hints;
START_COM_CALL;
SetExtendClientArea(_isClientAreaExtended);
return S_OK;
@autoreleasepool
{
_extendClientHints = hints;
SetExtendClientArea(_isClientAreaExtended);
return S_OK;
}
}
virtual HRESULT GetExtendTitleBarHeight (double*ret) override
{
if(ret == nullptr)
START_COM_CALL;
@autoreleasepool
{
return E_POINTER;
if(ret == nullptr)
{
return E_POINTER;
}
*ret = [Window getExtendedTitleBarHeight];
return S_OK;
}
*ret = [Window getExtendedTitleBarHeight];
return S_OK;
}
virtual HRESULT SetExtendTitleBarHeight (double value) override
{
[StandardContainer SetTitleBarHeightHint:value];
return S_OK;
START_COM_CALL;
@autoreleasepool
{
[StandardContainer SetTitleBarHeightHint:value];
return S_OK;
}
}
void EnterFullScreenMode ()
@ -978,8 +1083,15 @@ private:
virtual HRESULT SetWindowState (AvnWindowState state) override
{
START_COM_CALL;
@autoreleasepool
{
if(Window == nullptr)
{
return S_OK;
}
if(_actualWindowState == state)
{
return S_OK;
@ -1926,7 +2038,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
if(![self windowShouldClose:self]) return;
}
[self close];
}

10
samples/Sandbox/Program.cs

@ -4,12 +4,12 @@ namespace Sandbox
{
public class Program
{
static void Main(string[] args)
{
static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace()
.StartWithClassicDesktopLifetime(args);
}
.LogToTrace();
}
}

103
src/Avalonia.Controls/Shapes/Arc.cs

@ -0,0 +1,103 @@
using System;
using Avalonia.Media;
namespace Avalonia.Controls.Shapes
{
public class Arc : Shape
{
/// <summary>
/// Defines the <see cref="StartAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> StartAngleProperty =
AvaloniaProperty.Register<Arc, double>(nameof(StartAngle), 0.0);
/// <summary>
/// Defines the <see cref="SweepAngle"/> property.
/// </summary>
public static readonly StyledProperty<double> SweepAngleProperty =
AvaloniaProperty.Register<Arc, double>(nameof(SweepAngle), 0.0);
static Arc()
{
StrokeThicknessProperty.OverrideDefaultValue<Arc>(1);
AffectsGeometry<Arc>(BoundsProperty, StrokeThicknessProperty, StartAngleProperty, SweepAngleProperty);
}
/// <summary>
/// Gets or sets the angle at which the arc starts, in degrees.
/// </summary>
public double StartAngle
{
get => GetValue(StartAngleProperty);
set => SetValue(StartAngleProperty, value);
}
/// <summary>
/// Gets or sets the angle, in degrees, added to the <see cref="StartAngle"/> defining where the arc ends.
/// A positive value is clockwise, negative is counter-clockwise.
/// </summary>
public double SweepAngle
{
get => GetValue(SweepAngleProperty);
set => SetValue(SweepAngleProperty, value);
}
protected override Geometry CreateDefiningGeometry()
{
var angle1 = DegreesToRad(StartAngle);
var angle2 = angle1 + DegreesToRad(SweepAngle);
var startAngle = Math.Min(angle1, angle2);
var sweepAngle = Math.Max(angle1, angle2);
var normStart = RadToNormRad(startAngle);
var normEnd = RadToNormRad(sweepAngle);
var rect = new Rect(Bounds.Size);
if ((normStart == normEnd) && (startAngle != sweepAngle)) // Complete ring.
{
return new EllipseGeometry(rect.Deflate(StrokeThickness / 2));
}
else if (SweepAngle == 0)
{
return new StreamGeometry();
}
else // Partial arc.
{
var deflatedRect = rect.Deflate(StrokeThickness / 2);
var centerX = rect.Center.X;
var centerY = rect.Center.Y;
var radiusX = deflatedRect.Width / 2;
var radiusY = deflatedRect.Height / 2;
var angleGap = RadToNormRad(sweepAngle - startAngle);
var startPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, startAngle);
var endPoint = GetRingPoint(radiusX, radiusY, centerX, centerY, sweepAngle);
var arcGeometry = new StreamGeometry();
using (var ctx = arcGeometry.Open())
{
ctx.BeginFigure(startPoint, false);
ctx.ArcTo(endPoint, new Size(radiusX, radiusY), angleGap, angleGap >= Math.PI,
SweepDirection.Clockwise);
ctx.EndFigure(false);
}
return arcGeometry;
}
}
static double DegreesToRad(double inAngle) =>
inAngle * Math.PI / 180;
static double RadToNormRad(double inAngle) => ((inAngle % (Math.PI * 2)) + (Math.PI * 2)) % (Math.PI * 2);
static Point GetRingPoint(double radiusX, double radiusY, double centerX, double centerY, double angle) =>
new Point((radiusX * Math.Cos(angle)) + centerX, (radiusY * Math.Sin(angle)) + centerY);
}
}

2
src/Avalonia.Controls/TextBox.cs

@ -145,7 +145,7 @@ namespace Avalonia.Controls
(o, v) => o.UndoLimit = v,
unsetValue: -1);
struct UndoRedoState : IEquatable<UndoRedoState>
readonly struct UndoRedoState : IEquatable<UndoRedoState>
{
public string Text { get; }
public int CaretPosition { get; }

39
src/Avalonia.Controls/Window.cs

@ -592,6 +592,14 @@ namespace Avalonia.Controls
owner.RemoveChild(this);
}
if (_children.Count > 0)
{
foreach (var child in _children.ToArray())
{
child.child.Hide();
}
}
Owner = null;
PlatformImpl?.Hide();
@ -635,6 +643,22 @@ namespace Avalonia.Controls
throw new InvalidOperationException("Cannot re-show a closed window.");
}
if (parent != null)
{
if (parent.PlatformImpl == null)
{
throw new InvalidOperationException("Cannot show a window with a closed parent.");
}
else if (parent == this)
{
throw new InvalidOperationException("A Window cannot be its own parent.");
}
else if (!parent.IsVisible)
{
throw new InvalidOperationException("Cannot show window with non-visible parent.");
}
}
if (IsVisible)
{
return;
@ -708,11 +732,22 @@ namespace Avalonia.Controls
{
throw new ArgumentNullException(nameof(owner));
}
if (IsVisible)
else if (owner.PlatformImpl == null)
{
throw new InvalidOperationException("Cannot show a window with a closed owner.");
}
else if (owner == this)
{
throw new InvalidOperationException("A Window cannot be its own owner.");
}
else if (IsVisible)
{
throw new InvalidOperationException("The window is already being shown.");
}
else if (!owner.IsVisible)
{
throw new InvalidOperationException("Cannot show window with non-visible parent.");
}
RaiseEvent(new RoutedEventArgs(WindowOpenedEvent));

3
src/Avalonia.Visuals/ApiCompatBaseline.txt

@ -5,6 +5,7 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Threading.Task
MembersMustExist : Member 'public System.Threading.Tasks.Task Avalonia.Animation.IPageTransition.Start(Avalonia.Visual, Avalonia.Visual, System.Boolean)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Threading.Tasks.Task Avalonia.Animation.IPageTransition.Start(Avalonia.Visual, Avalonia.Visual, System.Boolean, System.Threading.CancellationToken)' is present in the implementation but not in the contract.
MembersMustExist : Member 'public System.Threading.Tasks.Task Avalonia.Animation.PageSlide.Start(Avalonia.Visual, Avalonia.Visual, System.Boolean)' does not exist in the implementation but it does exist in the contract.
TypeCannotChangeClassification : Type 'Avalonia.Media.Immutable.ImmutableSolidColorBrush' is a 'class' in the implementation but is a 'struct' in the contract.
MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext)' does not exist in the implementation but it does exist in the contract.
CannotAddAbstractMembers : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' is abstract in the implementation but is missing in the contract.
CannotSealType : Type 'Avalonia.Media.TextFormatting.GenericTextParagraphProperties' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
@ -73,4 +74,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWr
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmap(System.String)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmapToHeight(System.IO.Stream, System.Int32, Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmapToWidth(System.IO.Stream, System.Int32, Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode)' is present in the implementation but not in the contract.
Total Issues: 74
Total Issues: 75

3
src/Avalonia.Visuals/Media/Brush.cs

@ -2,6 +2,7 @@ using System;
using System.ComponentModel;
using Avalonia.Animation;
using Avalonia.Animation.Animators;
using Avalonia.Media.Immutable;
namespace Avalonia.Media
{
@ -47,7 +48,7 @@ namespace Avalonia.Media
if (s[0] == '#')
{
return new SolidColorBrush(Color.Parse(s));
return new ImmutableSolidColorBrush(Color.Parse(s));
}
var brush = KnownColors.GetKnownBrush(s);

11
src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.Immutable
/// <summary>
/// Fills an area with a solid color.
/// </summary>
public readonly struct ImmutableSolidColorBrush : ISolidColorBrush, IEquatable<ImmutableSolidColorBrush>
public class ImmutableSolidColorBrush : ISolidColorBrush, IEquatable<ImmutableSolidColorBrush>
{
/// <summary>
/// Initializes a new instance of the <see cref="ImmutableSolidColorBrush"/> class.
@ -48,8 +48,9 @@ namespace Avalonia.Media.Immutable
public bool Equals(ImmutableSolidColorBrush other)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return Color == other.Color && Opacity == other.Opacity;
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Color.Equals(other.Color) && Opacity.Equals(other.Opacity);
}
public override bool Equals(object obj)
@ -67,12 +68,12 @@ namespace Avalonia.Media.Immutable
public static bool operator ==(ImmutableSolidColorBrush left, ImmutableSolidColorBrush right)
{
return left.Equals(right);
return Equals(left, right);
}
public static bool operator !=(ImmutableSolidColorBrush left, ImmutableSolidColorBrush right)
{
return !left.Equals(right);
return !Equals(left, right);
}
/// <summary>

14
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs

@ -207,6 +207,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return true;
}
if (types.IBrush.IsAssignableFrom(type))
{
if (Color.TryParse(text, out Color color))
{
var brushTypeRef = new XamlAstClrTypeReference(node, types.ImmutableSolidColorBrush, false);
result = new XamlAstNewClrObjectNode(node, brushTypeRef,
types.ImmutableSolidColorBrushConstructorColor,
new List<IXamlAstValueNode> { new XamlConstantNode(node, types.UInt, color.ToUint32()) });
return true;
}
}
result = null;
return false;
}

9
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -80,7 +80,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType ColumnDefinitions { get; }
public IXamlType Classes { get; }
public IXamlMethod ClassesBindMethod { get; }
public IXamlProperty StyledElementClassesProperty { get; set; }
public IXamlProperty StyledElementClassesProperty { get; }
public IXamlType IBrush { get; }
public IXamlType ImmutableSolidColorBrush { get; }
public IXamlConstructor ImmutableSolidColorBrushConstructorColor { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{
@ -178,6 +181,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.FindMethod( "BindClass", IDisposable, false, IStyledElement,
cfg.WellKnownTypes.String,
IBinding, cfg.WellKnownTypes.Object);
IBrush = cfg.TypeSystem.GetType("Avalonia.Media.IBrush");
ImmutableSolidColorBrush = cfg.TypeSystem.GetType("Avalonia.Media.Immutable.ImmutableSolidColorBrush");
ImmutableSolidColorBrushConstructorColor = ImmutableSolidColorBrush.GetConstructor(new List<IXamlType> { UInt });
}
}

136
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -279,10 +279,11 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = Mock.Of<Window>();
var parent = new Window();
var renderer = new Mock<IRenderer>();
var target = new Window(CreateImpl(renderer));
parent.Show();
target.ShowDialog<object>(parent);
renderer.Verify(x => x.Start(), Times.Once);
@ -294,10 +295,11 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = Mock.Of<Window>();
var parent = new Window();
var target = new Window();
var raised = false;
parent.Show();
target.Opened += (s, e) => raised = true;
target.ShowDialog<object>(parent);
@ -326,14 +328,15 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Mock<Window>();
var parent = new Window();
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.DesktopScaling).Returns(1);
windowImpl.Setup(x => x.RenderScaling).Returns(1);
parent.Show();
var target = new Window(windowImpl.Object);
var task = target.ShowDialog<bool>(parent.Object);
var task = target.ShowDialog<bool>(parent);
windowImpl.Object.Closed();
@ -366,14 +369,16 @@ namespace Avalonia.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Mock<Window>();
var parent = new Window();
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.DesktopScaling).Returns(1);
windowImpl.Setup(x => x.RenderScaling).Returns(1);
parent.Show();
var target = new Window(windowImpl.Object);
var task = target.ShowDialog<bool>(parent.Object);
var task = target.ShowDialog<bool>(parent);
windowImpl.Object.Closed();
await task;
@ -381,12 +386,128 @@ namespace Avalonia.Controls.UnitTests
var openedRaised = false;
target.Opened += (s, e) => openedRaised = true;
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent.Object));
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent));
Assert.Equal("Cannot re-show a closed window.", ex.Message);
Assert.False(openedRaised);
}
}
[Fact]
public void Calling_Show_With_Closed_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
parent.Close();
var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
Assert.Equal("Cannot show a window with a closed parent.", ex.Message);
}
}
[Fact]
public async Task Calling_ShowDialog_With_Closed_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
parent.Close();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
Assert.Equal("Cannot show a window with a closed owner.", ex.Message);
}
}
[Fact]
public void Calling_Show_With_Invisible_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
Assert.Equal("Cannot show window with non-visible parent.", ex.Message);
}
}
[Fact]
public async Task Calling_ShowDialog_With_Invisible_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var parent = new Window();
var target = new Window();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
Assert.Equal("Cannot show window with non-visible parent.", ex.Message);
}
}
[Fact]
public void Calling_Show_With_Self_As_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new Window();
var ex = Assert.Throws<InvalidOperationException>(() => target.Show(target));
Assert.Equal("A Window cannot be its own parent.", ex.Message);
}
}
[Fact]
public async Task Calling_ShowDialog_With_Self_As_Parent_Window_Should_Throw()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new Window();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(target));
Assert.Equal("A Window cannot be its own owner.", ex.Message);
}
}
[Fact]
public void Hiding_Parent_Window_Should_Close_Children()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var parent = new Window();
var child = new Window();
parent.Show();
child.Show(parent);
parent.Hide();
Assert.False(parent.IsVisible);
Assert.False(child.IsVisible);
}
}
[Fact]
public void Hiding_Parent_Window_Should_Close_Dialog_Children()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var parent = new Window();
var child = new Window();
parent.Show();
child.ShowDialog(parent);
parent.Hide();
Assert.False(parent.IsVisible);
Assert.False(child.IsVisible);
}
}
[Fact]
public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
{
@ -686,6 +807,7 @@ namespace Avalonia.Controls.UnitTests
protected override void Show(Window window)
{
var owner = new Window();
owner.Show();
window.ShowDialog(owner);
}
}

20
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

@ -33,7 +33,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
DelayedBinding.ApplyBindings(border);
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -80,7 +80,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
DelayedBinding.ApplyBindings(border);
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -108,7 +108,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
DelayedBinding.ApplyBindings(border);
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -140,7 +140,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
DelayedBinding.ApplyBindings(border);
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -212,7 +212,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = window.FindControl<Button>("button");
var brush = (SolidColorBrush)button.Background;
var brush = (ISolidColorBrush)button.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -241,7 +241,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = window.FindControl<Button>("button");
var brush = (SolidColorBrush)button.Background;
var brush = (ISolidColorBrush)button.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -275,7 +275,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = window.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -317,7 +317,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
window.Show();
var border = (Border)button.GetVisualChildren().Single();
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -648,7 +648,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
DelayedBinding.ApplyBindings(border);
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
window.Content = null;
@ -657,7 +657,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
window.Content = border;
brush = (SolidColorBrush)border.Background;
brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
}

2
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs

@ -39,7 +39,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
}

20
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs

@ -29,7 +29,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -72,7 +72,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -119,7 +119,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -149,7 +149,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -200,7 +200,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = window.FindControl<Button>("button");
var brush = (SolidColorBrush)button.Background;
var brush = (ISolidColorBrush)button.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -229,7 +229,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = window.FindControl<Button>("button");
var brush = (SolidColorBrush)button.Background;
var brush = (ISolidColorBrush)button.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -263,7 +263,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = window.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -344,7 +344,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
window.Show();
var border = (Border)button.GetVisualChildren().Single();
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
@ -484,12 +484,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = userControl.FindControl<Border>("border");
var brush = (SolidColorBrush)border.Background;
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
userControl.Content = null;
brush = (SolidColorBrush)border.Background;
brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}

2
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -512,7 +512,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
style.TryGetResource("Brush", out var brush);
Assert.NotNull(brush);
Assert.IsType<SolidColorBrush>(brush);
Assert.IsAssignableFrom<ISolidColorBrush>(brush);
Assert.Equal(Colors.White, ((ISolidColorBrush)brush).Color);
style.TryGetResource("Double", out var d);

2
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs

@ -101,7 +101,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
</UserControl.Styles>
</UserControl>";
var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var brush = (SolidColorBrush)((Style)userControl.Styles[0]).Resources["brush"];
var brush = (ISolidColorBrush)((Style)userControl.Styles[0]).Resources["brush"];
Assert.Equal(0xff506070, brush.Color.ToUint32());
}

Loading…
Cancel
Save