These are chat archives for AvaloniaUI/Avalonia

11th
Apr 2018
Florian
@boombuler
Apr 11 2018 06:38
@grokys if drag and drop still not works for you please send me a PM so we can debug the problem and find the reason for this.
Achal Shah
@achal7
Apr 11 2018 09:04
Guys.. i am trying to create Map control in Avalonia using GMap
the problem is i want to translate the GMap image stream in to ImageSource, and then later on want to to transmit on the canvas
Achal Shah
@achal7
Apr 11 2018 09:11
code snippet looks like this:
public SharpDX.Direct2D1.ImageSource FromStream(System.IO.Stream stream)
{
var imagingFactory = new wic.ImagingFactory2();
var type = stream.ReadByte();
stream.Position = 0;
wic.BitmapDecoder bitmapDecoder = new wic.PngBitmapDecoder(imagingFactory);
var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA;
var inputStream = new wic.WICStream(imagingFactory, stream);
bitmapDecoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad);
var formatConverter = new wic.FormatConverter(imagingFactory);
formatConverter.Initialize(bitmapDecoder.GetFrame(0), wicPixelFormat);
                //translage it to image source
               ImageSource src = null;
           return src;
    }
so basically this function converts Stream of GMap in to the ImageSource and then target it to on the rendering surface. Does anyone have idea how can i move ahead? Any hint/direction to look forward?
danwalmsley
@danwalmsley
Apr 11 2018 10:38
@grokys you around, I think we are forgetting to invalidate layout / measure when styles change / get applied
its basically #1436
I'm submitting a simple repro now
im hoping I might be able to fix it myself
here is the repro branch
AvaloniaUI/Avalonia@a58a171
i'll post a gif to show you what happens:
style-layout-bug.gif
if you can see the borders are not recalculated.. my style looks like this
<Style Selector="TabStripItem:selected">
                    <Setter Property="Background" Value="#AA0000" />
                    <Setter Property="Foreground" Value="{DynamicResource ApplicationAccentBrushLight}" />
                    <Setter Property="BorderThickness" Value="1 0 1 1" />
                    <Setter Property="Margin" Value="0 -1 0 0" />
                </Style>
so style here affects measure / layout
Steven Kirk
@grokys
Apr 11 2018 10:43
ok
danwalmsley
@danwalmsley
Apr 11 2018 10:43
If I resize window to trigger layout pass it fixes it
where in code should I look to trigger InvalidateLayout / measure?
danwalmsley
@danwalmsley
Apr 11 2018 10:45
ok I will try fixing it thanks :)
danwalmsley
@danwalmsley
Apr 11 2018 10:55
@grokys changed to
static Border()
        {
            AffectsRender(BackgroundProperty, BorderBrushProperty);
            AffectsMeasure(BorderThicknessProperty);
        }
and now I have this...
style-layout-bug1.gif
Steven Kirk
@grokys
Apr 11 2018 11:04
isn't that the same? can't quite tell
danwalmsley
@danwalmsley
Apr 11 2018 11:04
no, before the unselected tab kept its borders
now they correctly dissapear
the only thing remaining is that the margin of the selected tabstripitem gets set to -1 on the top and border thickness 0 on the top
so that it looks like the main red area and the button are one
so its a partial improvement
Steven Kirk
@grokys
Apr 11 2018 11:06
what if you add border thickness to AffectsRender too? i don't think that will change anything, but worth a try
danwalmsley
@danwalmsley
Apr 11 2018 11:07
no doesn't do anything
danwalmsley
@danwalmsley
Apr 11 2018 11:15
how would you debug the render pass to check if its redrawing controls in the wrong z-order?
Steven Kirk
@grokys
Apr 11 2018 11:17
this line should order controls according to z-order
danwalmsley
@danwalmsley
Apr 11 2018 11:19
cheers
there should definitely be tests to check the z-order
danwalmsley
@danwalmsley
Apr 11 2018 11:20
ok so its not likely that then?
Steven Kirk
@grokys
Apr 11 2018 11:21
no, i mean there are no tests for that currently, we should definitely add some
danwalmsley
@danwalmsley
Apr 11 2018 11:21
oh ok
Steven Kirk
@grokys
Apr 11 2018 11:21
not sure how i missed that
danwalmsley
@danwalmsley
Apr 11 2018 11:23
ok so I have a little more info
this is the layout of the window
 <DockPanel Margin="10">
        <TabStrip Name="toolStrip" DockPanel.Dock="Bottom" ClipToBounds="False" Focusable="false" ZIndex="1">


            <TabStrip.Items>
                <TabStripItem>
                    <TextBlock Text="Item1" />
                </TabStripItem>
                <TabStripItem>
                    <TextBlock Text="Item2" />
                </TabStripItem>
            </TabStrip.Items>
        </TabStrip>

        <Border  BorderThickness="1" BorderBrush="Black">
            <Grid Background="#AA0000" />
        </Border>
    </DockPanel>
when set a conditional bp on the lin you suggested to check that the visual == DockPanel
and I click the tab,
the bp doesn't get hit
however when I resize the page it does
how do I make it use direct renderer instead?
found that
danwalmsley
@danwalmsley
Apr 11 2018 11:28
@grokys If I switch off DefferedRendering it works
possibly the dirty rects don't take into account a margin of -1?
Steven Kirk
@grokys
Apr 11 2018 11:30
ahhh yeh that might be it?
danwalmsley
@danwalmsley
Apr 11 2018 11:31
where should I look for that?
maybe make a copy of that and check for negative margins?
danwalmsley
@danwalmsley
Apr 11 2018 11:34
ok
Steven Kirk
@grokys
Apr 11 2018 11:35
dirty rects are in global coordinates
danwalmsley
@danwalmsley
Apr 11 2018 11:35
ok so in DIPs but X,Y position is from TopLeft of the main window / toplevel?
Steven Kirk
@grokys
Apr 11 2018 11:35
yeah
danwalmsley
@danwalmsley
Apr 11 2018 11:42
this was my test seems to pass
using (TestApplication())
            {
                Decorator decorator;
                Border border;
                Canvas canvas;
                var tree = new TestRoot
                {
                    Width = 100,
                    Height = 100,
                    Child = decorator = new Decorator
                    {
                        Margin = new Thickness(0, 10, 0, 0),
                        Child = border = new Border
                        {
                            Background = Brushes.Red,
                            Child = canvas = new Canvas(),
                        }
                    }
                };

                var layout = AvaloniaLocator.Current.GetService<ILayoutManager>();
                layout.ExecuteInitialLayoutPass(tree);

                var scene = new Scene(tree);
                var sceneBuilder = new SceneBuilder();
                sceneBuilder.UpdateAll(scene);

                var borderNode = scene.FindNode(border);
                var canvasNode = scene.FindNode(canvas);
                Assert.Equal(Matrix.CreateTranslation(0, 10), borderNode.Transform);
                Assert.Equal(Matrix.CreateTranslation(0, 10), canvasNode.Transform);

                border.Margin = new Thickness(0, -1, 0, 0);
                border.BorderThickness = new Thickness(1, 0, 1, 1);
                layout.ExecuteLayoutPass();

                scene = scene.CloneScene();

                sceneBuilder.Update(scene, border);

                var rects = scene.Layers.Single().Dirty.ToArray();
                Assert.Equal(new[] { new Rect(0, 9, 100, 91) }, rects);
            }
if you agree the numbers look correct?
main change was this..
border.Margin = new Thickness(0, -1, 0, 0);
                border.BorderThickness = new Thickness(1, 0, 1, 1);
style-layout-bug2.gif
danwalmsley
@danwalmsley
Apr 11 2018 11:47
if you look closely on that the dirty rect does seem to cover the top border
so must not be dirty rects
Steven Kirk
@grokys
Apr 11 2018 11:48
damn
danwalmsley
@danwalmsley
Apr 11 2018 11:48
do you think my conclusion that its the deffered renderer is right, or is it just that direct renderer triggers a layout / measure pass each time?
Steven Kirk
@grokys
Apr 11 2018 11:49
honestly i'm not sure
the direct renderer doesn't trigger a layout each time
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:49
any way to pass a full pass from border?
just to check
danwalmsley
@danwalmsley
Apr 11 2018 11:51
the black part of the border that remains is not from the border of the tab item
image.png
I changed the tabitems border to blue
so I guess that pointing to a zorder issue?
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:52
of your snippet, why is the tab cntrol zindex 1?
i mean, in the test, is it necessary?
danwalmsley
@danwalmsley
Apr 11 2018 11:53
which line are you referring to?
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:53
<TabStrip Name="toolStrip" DockPanel.Dock="Bottom" ClipToBounds="False" Focusable="false" ZIndex="1">
danwalmsley
@danwalmsley
Apr 11 2018 11:53
oh
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:54
for the repro, is that zindex necessary?
danwalmsley
@danwalmsley
Apr 11 2018 11:54
that's what makes the tabstrip (the tab buttons) get rendered over the control area at the top
its necessary
if I take that out then it always looks like the last screenshot I posted
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:54
controls at top? you mean the fps display?
danwalmsley
@danwalmsley
Apr 11 2018 11:54
no
the main red area
that's what the z-order does
needs to be draw behind the tab buttons at the bottom to make the effect work
tabstrip doesn't contain the content area
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:55
ahh, the red is from the border
okay, didn't get that part :)
will shut up now :)
danwalmsley
@danwalmsley
Apr 11 2018 11:56
:)
its ok
Matthijs ter Woord
@mterwoord
Apr 11 2018 11:56
cna't resist: if you remove the border, and the zindex, does it work ok then?
danwalmsley
@danwalmsley
Apr 11 2018 11:56
no
it renders correctly when it does a full layout pass
just not when tab changes at runtime
@grokys does deffered renderer have to take into account z-order to recompose the final bitmap? like maybe this is a layers issue? How can order that the bitmaps are composited in deffered renderer?
Steven Kirk
@grokys
Apr 11 2018 11:59
layers should only be created with animated opacity so they shouldn't come into it
and outputting the result of node.Visual.GetType().Name or something
that way you can see what order stuff is being drawn in?
danwalmsley
@danwalmsley
Apr 11 2018 12:05
first pass:
MainWindow
Border
AdornerDecorator
ContentPresenter
DockPanel
Border
Grid
TabStrip
ItemsPresenter
WrapPanel
TabStripItem
ContentPresenter
TextBlock
TabStripItem
AdornerLayer
changing selected tab
MainWindow
Border
AdornerDecorator
ContentPresenter
DockPanel
Border
Grid
TabStrip
ItemsPresenter
WrapPanel
TabStripItem
ContentPresenter
TextBlock
TabStripItem
ContentPresenter
TextBlock
AdornerLayer
looks ok
Steven Kirk
@grokys
Apr 11 2018 12:07
damn...
sorry, got to go right now, will be back in a bit
good luck! :D
Steven Kirk
@grokys
Apr 11 2018 13:42
@danwalmsley any luck?
danwalmsley
@danwalmsley
Apr 11 2018 13:46
Unfortunately no
I'm out of ideas now
Steven Kirk
@grokys
Apr 11 2018 13:50
i might be able to look at it later, not sure. i think what i'd start off doing is logging the actual drawing calls
danwalmsley
@danwalmsley
Apr 11 2018 14:09
@grokys ok well if you do get a chance there is a repro branch here, https://github.com/AvaloniaUI/Avalonia/compare/repro/1436-layout-not-done-after-style-applied
danwalmsley
@danwalmsley
Apr 11 2018 14:24
@wieslawsoltes do you by anychance have a behaviour so you can say open a Window and Close it via databinding from a viewmodel?
Wiesław Šoltés
@wieslawsoltes
Apr 11 2018 14:25
No
But should not be that hard to make
and hook to event
danwalmsley
@danwalmsley
Apr 11 2018 14:26
ok will try it
danwalmsley
@danwalmsley
Apr 11 2018 15:05
@grokys / @wieslawsoltes if I have a property like this:
public static readonly AvaloniaProperty<Type> WindowTypeProperty =
            AvaloniaProperty.Register<OpenCloseWindowBehavior, Type>(nameof(WindowType), defaultBindingMode: BindingMode.TwoWay);

        public Type WindowType
        {
            get => GetValue(WindowTypeProperty);
            set => SetValue(WindowTypeProperty, value);
        }
  <i:Interaction.Behaviors>
    <beh:OpenCloseWindowBehavior DataContext="ModalDialog" IsOpen="{Binding IsVisible}" WindowType="cont:ModalDialog" />
  </i:Interaction.Behaviors>
WindowType="cont:ModalDialog"
isn't accepted by XAML parser
what would the syntax be to pass a type here?
Wiesław Šoltés
@wieslawsoltes
Apr 11 2018 15:12
{x:Type cont:ModalDialog} ?
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
danwalmsley
@danwalmsley
Apr 11 2018 15:16
thanks works perfectly
:)
Wiesław Šoltés
@wieslawsoltes
Apr 11 2018 15:16
:smile:
James Burnside
@JCBurnside
Apr 11 2018 15:17
does AvaloniaObject.SetAndRaise(...) return true if it changed or what is the condition?
danwalmsley
@danwalmsley
Apr 11 2018 15:21
@JCBurnside what are you trying to do?
it returns true if the value was changed
James Burnside
@JCBurnside
Apr 11 2018 15:21
I was making a UserControl (a pretty simple one) and noticed that it had it.
I just wanted to make sure it did what I thought it did.
danwalmsley
@danwalmsley
Apr 11 2018 15:22
its a bit unusual to use AvaloniaObject directly though
James Burnside
@JCBurnside
Apr 11 2018 15:22
well I didn't look if anything along the inheritance tree overwrote it before it got to UserControl
so technically I am using UserControl.SetAndRaise
danwalmsley
@danwalmsley
Apr 11 2018 15:24
normally for stuff on usercontrol you would have DataContext set to a class that inherits something like ReactiveObject, and then call this.SetAndRaise()
unless your doing something unusual that might require code behind
?
James Burnside
@JCBurnside
Apr 11 2018 15:26
ah I see your using the control itself as datacontext
James Burnside
@JCBurnside
Apr 11 2018 15:29
yeap.
danwalmsley
@danwalmsley
Apr 11 2018 15:29
would you be happy for me to suggest an improvement, to help you code that in the way avalonia is designed to work?
James Burnside
@JCBurnside
Apr 11 2018 15:30
go right ahead
danwalmsley
@danwalmsley
Apr 11 2018 15:30
2 secs while I type this in ;)
danwalmsley
@danwalmsley
Apr 11 2018 15:38
ok
I pushed a small refactor
if you take a look, in user controls you shouldn't use AvaloniaProperty
its kind of overkill
so what iv done is created a ScrollingTextViewModel class which contains your properties
James Burnside
@JCBurnside
Apr 11 2018 15:39
I see. that is much cleaner.
danwalmsley
@danwalmsley
Apr 11 2018 15:39
it inherits ReactiveObject which implement INPC for you :)
its not far off what you had
but that's more they way avalonia is designed to work
:)
James Burnside
@JCBurnside
Apr 11 2018 15:40
normally for my VM's I implement INPC myself (because that is what I am used to doing)
danwalmsley
@danwalmsley
Apr 11 2018 15:40
let me know if you run into any trouble or have any questions, I hope it makes things easier for you
you can do that
if you want
avalonia wont care how its implemented :)
James Burnside
@JCBurnside
Apr 11 2018 15:40
do you mind if I just pull that in?
danwalmsley
@danwalmsley
Apr 11 2018 15:41
of course not
iv not tested it
but go for it
id imaging you can make the same change for your main window
too
James Burnside
@JCBurnside
Apr 11 2018 15:41
yes I probably will at some point
Steven Kirk
@grokys
Apr 11 2018 15:59
yeah the question of adding properties to a control vs using a view model is a bit of a tricky one
it's kind of like you need to categorize stuff into "controls" and "views"
but the boundary isn't always clear
ahopper
@ahopper
Apr 11 2018 16:06
I'm trying to fix AvaloniaUI/Avalonia#1484 and am failing
I can't find a way to discover the parent of a popup
yowl
@yowl
Apr 11 2018 16:08
butting in, but if you are authoring a control you wouldn't normally create a vm would you? Is AvaloniaProperty not inspired by DependencyProperty (btw http://avaloniaui.net/guides/quickstart is returning 404)
ahopper
@ahopper
Apr 11 2018 16:14
@yowl it is not unusual to have internal vms inside a user control in wpf
yowl
@yowl
Apr 11 2018 16:15
ok, thinking about it, the more complicated the control I suppose that makes sense.
Steven Kirk
@grokys
Apr 11 2018 16:16
yeah, as i say @yowl it's kinda unclear, i tend to go on a control-by-control basis
and then change my mind
@ahopper popup.Parent?
i assume you've seen that and it's not what you want though ;)
ahopper
@ahopper
Apr 11 2018 16:17
ahh, I'll try that then :)
ahopper
@ahopper
Apr 11 2018 16:32
so do both the logical and visual tree stop at each popup as you walk up the tree?
I have a fairly clean fix for just one level of popup inside a popup but I guess there could be many levels
Steven Kirk
@grokys
Apr 11 2018 16:40
yeah... kinda. the logical and visual tree stops at PopupRoot but the PopupRoot still inherits styles and property values
by overriding
(if i'm remembering correctly - it's been a while)
ahopper
@ahopper
Apr 11 2018 16:43
so to find if a popuproot is a distant child of another popuproot will probably be more than one line of code?
Steven Kirk
@grokys
Apr 11 2018 16:56
yeah but it should still be pretty simple. you should just be able to go up the IStyleHost.StylingParent chain
ahopper
@ahopper
Apr 11 2018 16:57
ok cheers, just making sure I wasn't missing something simple
Achal Shah
@achal7
Apr 11 2018 16:59
dear avalonia Gurus, one question regarding view model
public class ClientsDetailViewModel : ViewModelBase
{
public IBitmap ImgSource { get; set; }
public ClientsDetailViewModel()
{
Task.Run(async () =>
{
ImgSource = new Bitmap("Before.jpg"); // This displayes image in Image control
await Task.Delay(5000);
ImgSource = new Bitmap("After.png"); //Nothing happens, Image control still displays Before.jpg
});
}
Why Image control only gets updated once when i use Tasks
this is problem of all other controls, label, list etc. same behaviour
Jeremy Koritzinsky
@jkoritzinsky
Apr 11 2018 17:04
The ImgSource property isn't raising the PropertyChanged event so Avalonia doesn't know that the value has changed and that it needs to update.
danwalmsley
@danwalmsley
Apr 11 2018 17:05
@achal7
private IBitmap _imgSource;
public IBitmap ImgSource
{
    set => this.RaiseAndSetIfChanged(ref _imgSource, value);
    get => _imgSource;
}
should fix your issue
Achal Shah
@achal7
Apr 11 2018 17:08
Yes, just tried and indeed problem is fixed.
but still, why do we need to write this boilerplate code.
IBitmap ImgSource { get; set; } already updates the control, then why it doesnt work 2nd time?
i know about standard WPF and property changed, notification thingi
but thats the whole point, if get;set works 1st time without above polution then why not 2nd time
danwalmsley
@danwalmsley
Apr 11 2018 17:15
its because the UI the View (XAML) when it loads
it calls the getter to read the value
so it gets it the first time
but after that at runtime, the view wont read the getter unless it has an event to tell it that property has changed
Achal Shah
@achal7
Apr 11 2018 17:19
thanks for the explanation, its once time service, after that self service :)
danwalmsley
@danwalmsley
Apr 11 2018 17:20
no problem :)
@grokys @kekekeks if I wanted to use Window as a Modal Dialog
danwalmsley
@danwalmsley
Apr 11 2018 17:25
how can I assign my main window as its parent
so that if I click that it puts my dialog window in front?
Steven Kirk
@grokys
Apr 11 2018 18:28
@danwalmsley really not sure, my win32 foo kinda sucks :(
@ahopper maybe we should be making PopupRoot a logical child of Popup, i've wondered this many times
not done it mainly because WPF doesn't do it
Stano Turza
@Sorien
Apr 11 2018 18:37
In winapi modals are created by calling https://msdn.microsoft.com/en-us/library/windows/desktop/ms646291(v=vs.85).aspx on parent windows and opening child window
ahopper
@ahopper
Apr 11 2018 18:38
can any top level window type other than popup be a child of popup?
Steven Kirk
@grokys
Apr 11 2018 18:54
oh i remember why PopupRoot isn't the logical child of Popup
because if you have say:
<Popup>
  <Button>Hello</Button>
</Popup>
then the Button is the logical child of the popup
@ahopper did you mean "can any top level window type other than popup root be a child of popup"?
ahopper
@ahopper
Apr 11 2018 18:59
I really was thinking out loud and wondering if the same problem with nested popups can happen with anything else nested in a popup that puts a break in the visual tree
Steven Kirk
@grokys
Apr 11 2018 20:01
i don't think we have anything else currently