]> O.S.I.I.S - jp/crow.git/commitdiff
new ColorPicker, 2 levels DataSource bindings with struct and property handling,...
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 10 Oct 2019 05:24:38 +0000 (07:24 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 10 Oct 2019 05:24:38 +0000 (07:24 +0200)
24 files changed:
Crow/Crow.csproj
Crow/Default.style
Crow/Templates/ColorPicker.template
Crow/Templates/ColorPicker2.template [new file with mode: 0755]
Crow/Templates/EnumSelector.template [new file with mode: 0755]
Crow/Templates/GroupBox.template
Crow/Templates/Spinner.template
Crow/src/CompilerServices/CompilerServices.cs
Crow/src/Instantiator.cs
Crow/src/Interface.cs
Crow/src/Widgets/CheckBox.cs
Crow/src/Widgets/ColorPicker.cs
Crow/src/Widgets/ColorPicker2.cs [new file with mode: 0644]
Crow/src/Widgets/EnumSelector.cs
Crow/src/Widgets/GenericStack.cs
Crow/src/Widgets/Group.cs
Crow/src/Widgets/Label.cs
Crow/src/Widgets/PrivateContainer.cs
Crow/src/Widgets/TemplatedGroup.cs
Crow/src/Widgets/Widget.cs
Samples/ShowCase/ShowCase.csproj
Samples/ShowCase/main.cs
Samples/common/ui/Interfaces/Divers/0.crow
Samples/common/ui/Interfaces/basicTests/7.crow [deleted file]

index 8e8934e9b2fe62ed44f948648b7fc16ab2218526..3519cc7fc5504381d841442bcf0920a12266b553 100644 (file)
@@ -5,7 +5,7 @@
                <AssemblyName>Crow</AssemblyName>
                <Copyright>
                </Copyright>
-               <AssemblyVersion>0.8.4.1</AssemblyVersion>
+               <AssemblyVersion>0.8.6</AssemblyVersion>
                <Description>C.R.O.W. is a widget toolkit and rendering engine entirely developed in C# with templates, styles, compositing, and bindings.</Description>
                <EnableDefaultItems>false</EnableDefaultItems>
                <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
                <PackageLicense>https://opensource.org/licenses/MIT</PackageLicense>
                <PackageIconUrl>https://jpbruyere.github.io/Crow/images/crow.png</PackageIconUrl>
                <PackageCopyright>Copyright 2013-2019</PackageCopyright>
-               <PackageReleaseNotes>xcb backend</PackageReleaseNotes>
-               <DefineConstants>DESIGN_MODE</DefineConstants>
+               <PackageReleaseNotes></PackageReleaseNotes>
+               <DefineConstants>DESIGN_MODE</DefineConstants>          
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
                <DebugType>full</DebugType>
-               <DefineConstants>_DEBUG_DISPOSE;TRACE;_DEBUG_BINDING;DESIGN_MODE;_DEBUG_CLIP_RECTANGLE;_DEBUG_FOCUS;_DEBUG_DRAGNDROP;NET471;NETFRAMEWORK;NET461;DEBUG;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
+               <DefineConstants>_DEBUG_DISPOSE;TRACE;_DEBUG_BINDING;DESIGN_MODE;_DEBUG_CLIP_RECTANGLE;DEBUG_FOCUS;_DEBUG_DRAGNDROP;NET471;NET461;NETFRAMEWORK;NET472;DEBUG;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
                <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
        </PropertyGroup>
-       <!--  <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
-    <Reference Include="System" />
-    <Reference Include="mscorlib" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-    <Reference Include="Microsoft.CSharp" />        
-  </ItemGroup> -->
        <ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
                <PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.6.0" />
                <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.6.0" />
index 4108a1fb9c85f80a128fb19507bbec1d2789b38f..8865efc0bd6f893c6f68d19e5330ebac613682d4 100644 (file)
@@ -226,4 +226,21 @@ EnumSelector {
     Orientation = "Vertical";
     Height = "Fit";
     Spacing = "0";
+}
+labColor {
+       Margin="2";     
+       Width="Fit";
+}
+labColorV {
+       Margin="1";             
+       Width="Fit";
+}
+ColorSlider {
+       Focusable="true";
+       Height="12";
+       Margin="0";
+}
+ColorPicker {
+       Height="Fit";
+       MinimumSize="200,100";  
 }
\ No newline at end of file
index b43555177cbda2e63cc7fa0b6b1e50c4c7be8135..10976523a3ac18bfc31c2a12eee276cfe9c4780a 100755 (executable)
@@ -1,44 +1,42 @@
 <?xml version="1.0"?>
-<Border Background="{./Background}"    Foreground="{./Foreground}"
-               CornerRadius="{./CornerRadius}" BorderWidth="1">
-               <HorizontalStack Spacing="0">
-                       <VerticalStack Margin="5">
-                               <SaturationValueSelector S="{²./S}" V="{²./V}" Focusable="true" Name="colorSelector" Margin="0"
-                                       Foreground="{../hueSelector.HueColor}"
-                                       Width="128" Height="128"/>
-                               <HueSelector Hue="{²./H}" Focusable="true" Name="hueSelector" Margin="0" Width="128" Height="20"/>
-                       </VerticalStack>
-                       <VerticalStack Margin="5" Spacing="1">
-                               <Widget Width="34" Height="21" Background="{./SelectedColor}"/>
-                               <Label Focusable="true" Selectable="true" Text="{./SelectedColor}" />                           
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="R" Width="Fit"/>
-                                       <Spinner Style="ColorSpinner" Value="{²./R}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="G" Width="Fit"/>
-                                       <Spinner Style="ColorSpinner" Value="{²./G}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="B" Width="Fit"/>
-                                       <Spinner Style="ColorSpinner" Value="{²./B}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="A" Width="Fit"/>
-                                       <Spinner Style="ColorSpinner" Value="{²./A}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="H" Width="Fit"/>
-                                       <Spinner Style="HSVSpinner" Value="{²./H}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="S" Width="Fit"/>
-                                       <Spinner Style="HSVSpinner" Value="{²./S}" Width="46"  />
-                               </HorizontalStack>
-                               <HorizontalStack Height="Fit">
-                                       <Label Text="V" Width="Fit"/>
-                                       <Spinner Style="HSVSpinner" Value="{²./V}" Width="46"  />
-                               </HorizontalStack>
-                       </VerticalStack>
+<Border Background="{./Background}"    Foreground="{./Foreground}" Width="Stretched"
+               CornerRadius="{./CornerRadius}" BorderWidth="1">                
+       <VerticalStack Margin="2">
+               <Widget Width="30" Height="16" Background="{./CurrentColor}"/>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="R:"/>
+                       <ColorSlider Name="cs" Component="Red" CurrentColor="{²./CurrentColor}"/>                      
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
                </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="G:"/>
+                       <ColorSlider Name="cs" Component="Green" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="B:"/>
+                       <ColorSlider Name="cs" Component="Blue" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="A:"/>
+                       <ColorSlider Name="cs" Component="Alpha" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="H:"/>
+                       <ColorSlider Name="cs" Component="Hue" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="S:"/>
+                       <ColorSlider Name="cs" Component="Saturation" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>                      
+               <HorizontalStack Height="Fit">
+                       <Label Style="labColor" Text="V:"/>
+                       <ColorSlider Name="cs" Component="Value" CurrentColor="{²./CurrentColor}"/>
+                       <Label Style="labColorV" Text="{../cs.CurrentValue}" />
+               </HorizontalStack>
+       </VerticalStack>                        
 </Border>
diff --git a/Crow/Templates/ColorPicker2.template b/Crow/Templates/ColorPicker2.template
new file mode 100755 (executable)
index 0000000..b435551
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<Border Background="{./Background}"    Foreground="{./Foreground}"
+               CornerRadius="{./CornerRadius}" BorderWidth="1">
+               <HorizontalStack Spacing="0">
+                       <VerticalStack Margin="5">
+                               <SaturationValueSelector S="{²./S}" V="{²./V}" Focusable="true" Name="colorSelector" Margin="0"
+                                       Foreground="{../hueSelector.HueColor}"
+                                       Width="128" Height="128"/>
+                               <HueSelector Hue="{²./H}" Focusable="true" Name="hueSelector" Margin="0" Width="128" Height="20"/>
+                       </VerticalStack>
+                       <VerticalStack Margin="5" Spacing="1">
+                               <Widget Width="34" Height="21" Background="{./SelectedColor}"/>
+                               <Label Focusable="true" Selectable="true" Text="{./SelectedColor}" />                           
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="R" Width="Fit"/>
+                                       <Spinner Style="ColorSpinner" Value="{²./R}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="G" Width="Fit"/>
+                                       <Spinner Style="ColorSpinner" Value="{²./G}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="B" Width="Fit"/>
+                                       <Spinner Style="ColorSpinner" Value="{²./B}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="A" Width="Fit"/>
+                                       <Spinner Style="ColorSpinner" Value="{²./A}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="H" Width="Fit"/>
+                                       <Spinner Style="HSVSpinner" Value="{²./H}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="S" Width="Fit"/>
+                                       <Spinner Style="HSVSpinner" Value="{²./S}" Width="46"  />
+                               </HorizontalStack>
+                               <HorizontalStack Height="Fit">
+                                       <Label Text="V" Width="Fit"/>
+                                       <Spinner Style="HSVSpinner" Value="{²./V}" Width="46"  />
+                               </HorizontalStack>
+                       </VerticalStack>
+               </HorizontalStack>
+</Border>
diff --git a/Crow/Templates/EnumSelector.template b/Crow/Templates/EnumSelector.template
new file mode 100755 (executable)
index 0000000..cc4e239
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<GroupBox Caption="{./Caption}" CornerRadius="{./CornerRadius}" Foreground="{./Foreground}" Background="{./Background}">
+       <HorizontalStack Name="Content"/>
+</GroupBox>
+
index 0540b55257b96cc2e126ec7ef3ef9a41ea315013..f10b1c4cb5d088d9afc2b9a0f9f72e3cb048382d 100755 (executable)
@@ -3,7 +3,7 @@
        <Group>
                <VerticalStack Spacing="0">
                        <Widget Height="6"/>
-                       <Border  CornerRadius="5" BorderWidth="1" Margin="10" Foreground="{./Foreground}">
+                       <Border  CornerRadius="{./CornerRadius}" BorderWidth="1" Margin="10" Foreground="{./Foreground}">
                                <Container Name="Content" Margin="0" MinimumSize="70,10"/>
                        </Border>
                </VerticalStack>
index 613b622969be83262c9d532c6f7905ecb17d5d89..1bac0d1dc4ab7f007d41db60b96af051fb5a6054 100755 (executable)
@@ -5,7 +5,7 @@
                <TextBox Foreground="{./Foreground}" Font="{./Font}" Width="Stretched"
                        Text="{²./Value}" TextAlignment="Right" Margin="0"/>
        </Border>
-       <VerticalStack MinimumSize="13,13" Width="25%" Height="Stretched" Spacing="1" Margin="1">
+       <VerticalStack MinimumSize="13,13" Width="16" Height="Stretched" Spacing="1" Margin="1">
                <Shape Style="ArrowBut" Height="50%" MouseDown="./onUp" Size="10,10" Path="M 4.5,0.5 L 9.5,9.5 L 0.5,9.5 Z"/>                   
                <Shape Style="ArrowBut" Height="50%" MouseDown="./onDown" Size="10,10" Path="M 0.5,0.5 L 9.5,0.5 L 4.5,9.5 Z"/>
        </VerticalStack>
index d1751920c2c919a0dcea1e38a2fcdb56ddd174b4..8849895172dd0b09ac264750724abda1251e94cf 100644 (file)
@@ -322,10 +322,7 @@ namespace Crow.IML
                                return;
                        }
 
-                       if (miDest.MemberType == MemberTypes.Property)
-                               destType =(miDest as PropertyInfo).PropertyType;
-                       else if (miDest.MemberType == MemberTypes.Field)
-                               destType =(miDest as FieldInfo).FieldType;
+                       destType = CompilerServices.GetMemberInfoType (miDest);
 
                        try {
                                if (value != null) {
@@ -1050,6 +1047,12 @@ namespace Crow.IML
 
                        il.Emit (OpCodes.Ldfld, fi);
                }
+
+               //helper to get member info underlying type.
+               internal static Type GetMemberInfoType (MemberInfo mi) =>
+                               mi.MemberType == MemberTypes.Field ? (mi as FieldInfo).FieldType :
+                               mi.MemberType == MemberTypes.Property ? (mi as PropertyInfo).PropertyType :
+                               mi.MemberType == MemberTypes.Method ? (mi as MethodInfo).ReturnType : null;
        }
 }
 
index 3268d2e67448473b9cdbe6658545eacad08c1ba5..1dcb989a9f0f53a54d334a9383f77ba7464bce43 100644 (file)
@@ -1160,7 +1160,7 @@ namespace Crow.IML {
                                        typeof (void),
                                        CompilerServices.argsBoundValueChange, true);
 
-                               il = dm.GetILGenerator (32);
+                               il = dm.GetILGenerator (64);
 
                                System.Reflection.Emit.Label endMethod = il.DefineLabel ();
 
@@ -1173,7 +1173,7 @@ namespace Crow.IML {
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
 
                                //test if it's the expected one
-                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);
+                               il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ? $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);
                                il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
                                il.Emit (OpCodes.Call, CompilerServices.stringEquals);
                                il.Emit (OpCodes.Brfalse, endMethod);
@@ -1218,6 +1218,7 @@ namespace Crow.IML {
                        il.DeclareLocal (typeof(object));//used for checking propery less bindings
                        il.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
                        il.DeclareLocal (typeof (object));//new datasource store, save one field access
+                       il.DeclareLocal (typeof (MemberInfo));//used for binding with datasource.object.member (2 levels)
                        System.Reflection.Emit.Label cancel = il.DefineLabel ();
                        System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
                        System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
@@ -1238,9 +1239,19 @@ namespace Crow.IML {
                                il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
                        }
 
-#region fetch initial Value
+                       #region fetch initial Value
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               il.Emit (OpCodes.Ldloc_2); 
+                               il.Emit (OpCodes.Ldloc_2);
+                               if (bindingDef.HasUnresolvedTargetName) {
+                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetName);//load parent object
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
+                                       il.Emit (OpCodes.Stloc_3);
+                                       il.Emit (OpCodes.Ldloc_3);
+                                       il.Emit (OpCodes.Brfalse, cancelInit);//may be propertyLessBinding
+                                       il.Emit (OpCodes.Ldloc_2);//load datasource
+                                       il.Emit (OpCodes.Ldloc_3);//load first memberInfo
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
+                               } 
                                il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name
                                il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
                                il.Emit (OpCodes.Stloc_1);//save memberInfo
@@ -1251,12 +1262,16 @@ namespace Crow.IML {
                        il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
                        il.Emit (OpCodes.Ldloc_2);//load new datasource
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
+                               if (bindingDef.HasUnresolvedTargetName) {
+                                       il.Emit (OpCodes.Ldloc_3);
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);//get first member level
+                               }
                                il.Emit (OpCodes.Ldloc_1);//push mi for value fetching
                                il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
                        }
                        CompilerServices.emitConvert (il, piSource.PropertyType);
                        il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-#endregion
+                       #endregion
 
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
                                il.MarkLabel(cancelInit);
@@ -1268,7 +1283,7 @@ namespace Crow.IML {
                                il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
                                il.Emit (OpCodes.Ldarg_1);//load datasource change source
                                il.Emit (OpCodes.Ldloc_2);//load new datasource
-                               il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynmathod
+                               il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynMethod
                                il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
 
                                il.MarkLabel (cancel);
@@ -1277,7 +1292,8 @@ namespace Crow.IML {
                                        il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
                                        il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
                                        il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
-                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member
+                                       il.Emit (OpCodes.Ldstr, bindingDef.HasUnresolvedTargetName ?
+                                               $"{bindingDef.TargetName}.{bindingDef.TargetMember}" : bindingDef.TargetMember);//arg4: dest member
                                        il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
                                }
 
@@ -1297,6 +1313,16 @@ namespace Crow.IML {
                        Debug.WriteLine("\tDataSource Changed: " + dm.Name);
 #endif
                }
+
+               static void emitSetValue (ILGenerator il, MemberInfo mi)
+               {
+                       if (mi.MemberType == MemberTypes.Field)
+                               il.Emit (OpCodes.Stfld, mi as FieldInfo);
+                       else if (mi.MemberType == MemberTypes.Property)
+                               il.Emit (OpCodes.Callvirt, (mi as PropertyInfo).GetSetMethod ());
+                       else
+                               throw new NotImplementedException ();
+               }
                /// <summary>
                /// Two way binding for datasource, graphicObj=>dataSource link, datasource value has priority
                /// and will be set as init for source property (in emitDataSourceBindings func)
@@ -1309,12 +1335,18 @@ namespace Crow.IML {
                        Type tOrig = orig.GetType ();
                        Type tDest = dest.GetType ();
                        PropertyInfo piOrig = tOrig.GetProperty (origMember);
-                       PropertyInfo piDest = tDest.GetProperty (destMember);
-
-                       if (piDest == null) {
-                               Debug.WriteLine ("Member '{0}' not found in new DataSource '{1}' of '{2}'", destMember, dest, orig);
-                               return;
+                       List<MemberInfo> miDests = new List<MemberInfo> ();
+                       Type curType = tDest;
+                       foreach (string m in destMember.Split('.')) {
+                               MemberInfo miDest = curType.GetMember (m).FirstOrDefault ();
+                               if (miDest == null) {
+                                       Debug.WriteLine ($"Member '{destMember}' not found in new DataSource '{dest}' of '{orig}'");
+                                       return;
+                               }
+                               miDests.Add (miDest);
+                               curType = CompilerServices.GetMemberInfoType (miDest);
                        }
+
 #if DEBUG_BINDING
                        Debug.WriteLine ("DS Reverse binding: Member '{0}' found in new DS '{1}' of '{2}'", destMember, dest, orig);
 #endif
@@ -1322,7 +1354,7 @@ namespace Crow.IML {
 #region ValueChanged emit
                        DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId,
                                typeof (void), CompilerServices.argsBoundValueChange, true);
-                       ILGenerator il = dm.GetILGenerator (256);
+                       ILGenerator il = dm.GetILGenerator (64);
 
                        System.Reflection.Emit.Label endMethod = il.DefineLabel ();
 
@@ -1340,20 +1372,44 @@ namespace Crow.IML {
                        //set destination member with valueChanged new value
                        //load destination ref
                        il.Emit (OpCodes.Ldarg_0);
+                       for (int i = 0; i < miDests.Count - 1; i++) {
+                               if (miDests [i].MemberType == MemberTypes.Field)
+                                       il.Emit (OpCodes.Ldflda, miDests [i] as FieldInfo);
+                               else if (miDests [i].MemberType == MemberTypes.Property) {
+                                       PropertyInfo pi = miDests [i] as PropertyInfo;
+                                       if (pi.PropertyType.IsValueType) {
+                                               il.Emit (OpCodes.Dup);//dup parent for calling property set afterward
+                                               il.Emit (OpCodes.Callvirt, pi.GetGetMethod ());
+                                               il.Emit (OpCodes.Box, pi.PropertyType);
+                                               il.Emit (OpCodes.Dup);//dup boxed valueType, should unbox before setting parent
+                                       } else
+                                               il.Emit (OpCodes.Callvirt, pi.GetGetMethod ());
+                               } else
+                                       throw new NotImplementedException ();
+                       }
+
                        //load new value onto the stack
                        il.Emit (OpCodes.Ldarg_2);
                        il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
 
-                       //if (piOrig.PropertyType != piDest.PropertyType)
-                               CompilerServices.emitConvert (il, piOrig.PropertyType, piDest.PropertyType);
+                       CompilerServices.emitConvert (il, piOrig.PropertyType, curType);
 
-                       il.Emit (OpCodes.Callvirt, piDest.GetSetMethod ());
+                       emitSetValue (il, miDests.Last ());
 
+                       for (int i = miDests.Count -2; i >= 0; i--) {
+                               if (miDests [i].MemberType != MemberTypes.Property)
+                                       continue;
+                               PropertyInfo pi = miDests [i] as PropertyInfo;
+                               if (!pi.PropertyType.IsValueType)
+                                       continue;
+                               il.Emit (OpCodes.Ldobj, pi.PropertyType);
+                               il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());//updating parent
+                       }
                        il.MarkLabel (endMethod);
                        il.Emit (OpCodes.Ret);
-#endregion
-
-                       orig.ValueChanged += (EventHandler<ValueChangeEventArgs>)dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>), dest);
+                       #endregion
+                       EventHandler<ValueChangeEventArgs> tmp = (EventHandler<ValueChangeEventArgs>)dm.CreateDelegate (typeof (EventHandler<ValueChangeEventArgs>), dest);
+                       orig.ValueChanged += tmp;
                }
 #endregion
 
index 2ef26fced6fc1c31c66ac29c04ab08ace3850eda..cb836a9f6c09c3b569b3b4b731f20c857babe164 100644 (file)
@@ -977,7 +977,7 @@ namespace Crow
                MouseCursor cursor = MouseCursor.Arrow;
 
                public MouseState Mouse;
-               Stopwatch lastMouseDown = new Stopwatch (), mouseRepeatTimer = new Stopwatch ();
+               Stopwatch lastMouseDown = Stopwatch.StartNew (), mouseRepeatTimer = new Stopwatch ();
                bool doubleClickTriggered;      //next mouse up will trigger a double click
                //int mouseRepeatCount;
                MouseButtonEventArgs lastMouseDownEvent;
index 7dc2b073a8fd1cc4162aebf413ddf98426f76f7a..7a6e5d45d67487594eab9d70606f396f10efd795 100644 (file)
@@ -1,28 +1,6 @@
-//
-// CheckBox.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.ComponentModel;
index 928377177055f9fdd9085f51bf7a1d234640cae2..72f77deae24077928387da58d09d7f1bba933930 100644 (file)
@@ -1,28 +1,6 @@
-//
-// ColorPicker.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Xml.Serialization;
@@ -40,189 +18,18 @@ namespace Crow
                public ColorPicker (Interface iface) : base(iface){}
                #endregion
 
-               const double div = 255.0;
-               const double colDiv = 1.0 / div;
+               Color currentColor;
 
-               Color curColor;
-               double h,s,v;
-
-               
-               public virtual double R {
-                       get { return Math.Round(curColor.R * div); }
-                       set {
-                               if (R == value)
-                                       return;
-                               curColor.R = value * colDiv;
-                               NotifyValueChanged ("R", R);
-                               hsvFromRGB ();
-                               notifyCurColorHasChanged ();
-                       }
-               }
-               
-               public virtual double G {
-                       get { return Math.Round(curColor.G * div); }
-                       set {
-                               if (G == value)
-                                       return;
-                               curColor.G = value * colDiv;
-                               NotifyValueChanged ("G", G);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double B {
-                       get { return Math.Round(curColor.B * div); }
-                       set {
-                               if (B == value)
-                                       return;
-                               curColor.B = value * colDiv;
-                               NotifyValueChanged ("B", B);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double A {
-                       get { return Math.Round(curColor.A * div); }
-                       set {
-                               if (A == value)
-                                       return;
-                               curColor.A = value * colDiv;
-                               NotifyValueChanged ("A", A);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double H {
-                       get { return Math.Round (h, 3); }
-                       set {
-                               if (H == value)
-                                       return;
-                               h = value;
-                               NotifyValueChanged ("H", H);
-                               rgbFromHSV ();
-                       }
-               }
-               
-               public virtual double S {
-                       get { return Math.Round (s, 2); }
+               [DefaultValue("Black")]
+               public virtual Color CurrentColor {
+                       get => currentColor;
                        set {
-                               if (s == value)
+                               if (currentColor == value)
                                        return;
-                               s = value;
-                               NotifyValueChanged ("S", S);
-                               rgbFromHSV ();
+                               currentColor = value;
+                               NotifyValueChanged ("CurrentColor", currentColor);
                        }
                }
-               
-               public virtual double V {
-                       get { return Math.Round (v, 2); }
-                       set {
-                               if (v == value)
-                                       return;
-                               v = value;
-                               NotifyValueChanged ("V", V);
-                               rgbFromHSV ();
-                       }
-               }
-
-               
-               public virtual Fill SelectedColor {
-                       get { return new SolidColor(curColor); }
-                       set {
-                               if (value == null)
-                                       curColor = Color.White;
-                               else if (value is SolidColor) {
-                                       Color c = (value as SolidColor).color;
-                                       if (curColor == c)
-                                               return;
-                                       curColor = c;
-                               }
-                               notifyCurColorHasChanged ();
-                               notifyRGBAHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual Color SelectedRawColor {
-                       get { return curColor; }
-                       set {
-                               if (curColor == value)
-                                       return;
-                               curColor = value;
-                               notifyCurColorHasChanged ();
-                               notifyRGBAHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               void notifyCurColorHasChanged(){
-                       NotifyValueChanged ("SelectedColor", SelectedColor);
-                       NotifyValueChanged ("SelectedRawColor", curColor);
-                       string n = curColor.ToString ();
-                       if (char.IsLetter(n[0]))
-                               NotifyValueChanged ("SelectedColorName", n);
-                       else
-                               NotifyValueChanged ("SelectedColorName", "-");
-                       string tmp = ((int)Math.Round (R)).ToString ("X2") +
-                                    ((int)Math.Round (G)).ToString ("X2") +
-                                    ((int)Math.Round (B)).ToString ("X2");
-                       if (curColor.A < 1.0)
-                               tmp += ((int)Math.Round (A)).ToString ("X2");
-                       NotifyValueChanged ("HexColor", tmp);
-               }
-               void notifyRGBAHasChanged(){
-                       NotifyValueChanged ("R", R);
-                       NotifyValueChanged ("G", G);
-                       NotifyValueChanged ("B", B);
-                       NotifyValueChanged ("A", A);
-               }
-               void notifyHSVHasChanged(){
-                       NotifyValueChanged ("H", H);
-                       NotifyValueChanged ("S", S);
-                       NotifyValueChanged ("V", V);
-               }
-               void hsvFromRGB(){
-                       Color c = curColor;
-                       c.ResetName ();
-                       double min = Math.Min (c.R, Math.Min (c.G, c.B));       //Min. value of RGB
-                       double max = Math.Max (c.R, Math.Max (c.G, c.B));       //Max. value of RGB
-                       double diff = max - min;                                                        //Delta RGB value
-
-                       v = max;
-
-                       if ( diff == 0 )//This is a gray, no chroma...
-                       {
-                               h = 0;
-                               s = 0;
-                       }else{//Chromatic data...
-                               s = diff / max;
-
-                               double diffR = (((max - c.R) / 6.0) + (diff / 2.0)) / diff;
-                               double diffG = (((max - c.G) / 6.0) + (diff / 2.0)) / diff;
-                               double diffB = (((max - c.B) / 6.0) + (diff / 2.0)) / diff;
-
-                               if (c.R == max)
-                                       h = diffB - diffG;
-                               else if (c.G == max)
-                                       h = (1.0 / 3.0) + diffR - diffB;
-                               else if (c.B == max)
-                                       h = (2.0 / 3.0) + diffG - diffR;
-
-                               if (h < 0)
-                                       h += 1;
-                               if (h > 1)
-                                       h -= 1;
-
-                       }
-                       notifyHSVHasChanged ();
-               }
-               void rgbFromHSV(){
-                       curColor = Color.FromHSV (h, v, s, curColor.A);
-                       notifyCurColorHasChanged ();
-                       notifyRGBAHasChanged ();
-               }
        }
 }
 
diff --git a/Crow/src/Widgets/ColorPicker2.cs b/Crow/src/Widgets/ColorPicker2.cs
new file mode 100644 (file)
index 0000000..f5b457c
--- /dev/null
@@ -0,0 +1,206 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated color selector control
+       /// </summary>
+       public class ColorPicker2 : TemplatedControl
+       {
+               #region CTOR
+               protected ColorPicker2() : base(){}
+               public ColorPicker2 (Interface iface) : base(iface){}
+               #endregion
+
+               const double div = 255.0;
+               const double colDiv = 1.0 / div;
+
+               Color curColor;
+               double h,s,v;
+
+               
+               public virtual double R {
+                       get { return Math.Round(curColor.R * div); }
+                       set {
+                               if (R == value)
+                                       return;
+                               curColor.R = value * colDiv;
+                               NotifyValueChanged ("R", R);
+                               hsvFromRGB ();
+                               notifyCurColorHasChanged ();
+                       }
+               }
+               
+               public virtual double G {
+                       get { return Math.Round(curColor.G * div); }
+                       set {
+                               if (G == value)
+                                       return;
+                               curColor.G = value * colDiv;
+                               NotifyValueChanged ("G", G);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double B {
+                       get { return Math.Round(curColor.B * div); }
+                       set {
+                               if (B == value)
+                                       return;
+                               curColor.B = value * colDiv;
+                               NotifyValueChanged ("B", B);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double A {
+                       get { return Math.Round(curColor.A * div); }
+                       set {
+                               if (A == value)
+                                       return;
+                               curColor.A = value * colDiv;
+                               NotifyValueChanged ("A", A);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double H {
+                       get { return Math.Round (h, 3); }
+                       set {
+                               if (H == value)
+                                       return;
+                               h = value;
+                               NotifyValueChanged ("H", H);
+                               rgbFromHSV ();
+                       }
+               }
+               
+               public virtual double S {
+                       get { return Math.Round (s, 2); }
+                       set {
+                               if (s == value)
+                                       return;
+                               s = value;
+                               NotifyValueChanged ("S", S);
+                               rgbFromHSV ();
+                       }
+               }
+               
+               public virtual double V {
+                       get { return Math.Round (v, 2); }
+                       set {
+                               if (v == value)
+                                       return;
+                               v = value;
+                               NotifyValueChanged ("V", V);
+                               rgbFromHSV ();
+                       }
+               }
+
+               
+               public virtual Fill SelectedColor {
+                       get { return new SolidColor(curColor); }
+                       set {
+                               if (value == null)
+                                       curColor = Color.White;
+                               else if (value is SolidColor) {
+                                       Color c = (value as SolidColor).color;
+                                       if (curColor == c)
+                                               return;
+                                       curColor = c;
+                               }
+                               notifyCurColorHasChanged ();
+                               notifyRGBAHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual Color SelectedRawColor {
+                       get { return curColor; }
+                       set {
+                               if (curColor == value)
+                                       return;
+                               curColor = value;
+                               notifyCurColorHasChanged ();
+                               notifyRGBAHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               void notifyCurColorHasChanged(){
+                       NotifyValueChanged ("SelectedColor", SelectedColor);
+                       NotifyValueChanged ("SelectedRawColor", curColor);
+                       string n = curColor.ToString ();
+                       if (char.IsLetter(n[0]))
+                               NotifyValueChanged ("SelectedColorName", n);
+                       else
+                               NotifyValueChanged ("SelectedColorName", "-");
+                       string tmp = ((int)Math.Round (R)).ToString ("X2") +
+                                    ((int)Math.Round (G)).ToString ("X2") +
+                                    ((int)Math.Round (B)).ToString ("X2");
+                       if (curColor.A < 1.0)
+                               tmp += ((int)Math.Round (A)).ToString ("X2");
+                       NotifyValueChanged ("HexColor", tmp);
+               }
+               void notifyRGBAHasChanged(){
+                       NotifyValueChanged ("R", R);
+                       NotifyValueChanged ("G", G);
+                       NotifyValueChanged ("B", B);
+                       NotifyValueChanged ("A", A);
+               }
+               void notifyHSVHasChanged(){
+                       NotifyValueChanged ("H", H);
+                       NotifyValueChanged ("S", S);
+                       NotifyValueChanged ("V", V);
+               }
+               void hsvFromRGB(){
+                       Color c = curColor;
+                       c.ResetName ();
+                       double min = Math.Min (c.R, Math.Min (c.G, c.B));       //Min. value of RGB
+                       double max = Math.Max (c.R, Math.Max (c.G, c.B));       //Max. value of RGB
+                       double diff = max - min;                                                        //Delta RGB value
+
+                       v = max;
+
+                       if ( diff == 0 )//This is a gray, no chroma...
+                       {
+                               h = 0;
+                               s = 0;
+                       }else{//Chromatic data...
+                               s = diff / max;
+
+                               double diffR = (((max - c.R) / 6.0) + (diff / 2.0)) / diff;
+                               double diffG = (((max - c.G) / 6.0) + (diff / 2.0)) / diff;
+                               double diffB = (((max - c.B) / 6.0) + (diff / 2.0)) / diff;
+
+                               if (c.R == max)
+                                       h = diffB - diffG;
+                               else if (c.G == max)
+                                       h = (1.0 / 3.0) + diffR - diffB;
+                               else if (c.B == max)
+                                       h = (2.0 / 3.0) + diffG - diffR;
+
+                               if (h < 0)
+                                       h += 1;
+                               if (h > 1)
+                                       h -= 1;
+
+                       }
+                       notifyHSVHasChanged ();
+               }
+               void rgbFromHSV(){
+                       curColor = Color.FromHSV (h, v, s, curColor.A);
+                       notifyCurColorHasChanged ();
+                       notifyRGBAHasChanged ();
+               }
+       }
+}
+
index 932e90e2986c9d9139ecd5fa191e82ced2379ccd..576eb95381459b8556c01fda86f35490e085d154 100644 (file)
@@ -8,15 +8,26 @@ using System.ComponentModel;
 namespace Crow
 {
        /// <summary>
-       /// Convenient widget for selecting value from enum
+       /// Convenient widget for selecting value among enum values. This is a templated control
+       /// expecting a 'Group' widget named 'Content' inside the template to handle the enum values display.
        /// </summary>
-       public class EnumSelector : GenericStack
+       public class EnumSelector : TemplatedControl
        {
                #region CTOR
                protected EnumSelector () : base(){}
                public EnumSelector (Interface iface) : base(iface){}
                #endregion
 
+               Group enumValueContainer;
+
+               protected override void loadTemplate (Widget template = null)
+               {
+                       base.loadTemplate (template);
+                       enumValueContainer = this.child.FindByName ("Content") as Group;
+                       if (enumValueContainer == null)
+                               throw new Exception("EnumSelector template MUST contain a 'Group' named 'Content'");
+               }
+
                #region private fields
                Enum enumValue;
                Type enumType;
@@ -37,20 +48,22 @@ namespace Crow
 
                                if (enumValue != null) {
                                        if (enumType != enumValue.GetType ()) {
-                                               ClearChildren ();
+                                               enumValueContainer.ClearChildren ();
                                                enumType = enumValue.GetType ();
                                                foreach (string en in enumType.GetEnumNames ()) {
                                                        RadioButton rb = new RadioButton (IFace);
                                                        rb.Caption = en;
-                                                       if (enumValue.ToString() == en)
+                                                       rb.Fit = true;
+                                                       rb.LogicalParent = this;
+                                                       if (enumValue.ToString () == en)
                                                                rb.IsChecked = true;
-                                                       rb.Checked += (sender, e) => (((RadioButton)sender).Parent as EnumSelector).EnumValue = (Enum)Enum.Parse (enumType, (sender as RadioButton).Caption);
-                                                       AddChild (rb);
-                                                       RegisterForLayouting (LayoutingType.All);
+                                                       rb.Checked += (sender, e) => (((RadioButton)sender).LogicalParent as EnumSelector).EnumValue = (Enum)Enum.Parse (enumType, (sender as RadioButton).Caption);
+                                                       enumValueContainer.AddChild (rb);
                                                }
+                                       
                                        }
-                               } else 
-                                       ClearChildren ();
+                               } else
+                                       enumValueContainer.ClearChildren ();
 
                                NotifyValueChanged ("EnumValue", enumValue);
                                RegisterForRedraw ();
index 5189748759d7da2d081697eb7b372af64d537ede..7d1facf04f09fcc018c4893846fae55903996dd9 100644 (file)
@@ -1,28 +1,6 @@
-//
-// GenericStack.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System.ComponentModel;
 using System.Diagnostics;
index a0ae35b24c7785e76c7724c1e98ea04f87a9f3c8..a992e5af6ab63dd4073bbb568651fba58f5e07de 100644 (file)
@@ -91,6 +91,13 @@ namespace Crow
             set { _multiSelect = value; }
         }
                public virtual void AddChild(Widget g){
+#if DEBUG
+                       if (disposed) {
+                               Console.WriteLine ($"AddChild ({g}) in disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
+#endif
+
                        childrenRWLock.EnterWriteLock();
 
                        g.Parent = this;
@@ -132,6 +139,12 @@ namespace Crow
                        child.Dispose ();
         }
                public virtual void InsertChild (int idx, Widget g) {
+#if DEBUG
+                       if (disposed) {
+                               Console.WriteLine ($"InsertChild ({idx},{g}) in disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
+#endif
                        childrenRWLock.EnterWriteLock ();
                                
                        g.Parent = this;
@@ -164,7 +177,7 @@ namespace Crow
 
                        resetChildrenMaxSize ();
 
-                       this.RegisterForLayouting (LayoutingType.Sizing);
+                       RegisterForLayouting (LayoutingType.Sizing);
                        ChildrenCleared.Raise (this, new EventArgs ());
                }
                public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
@@ -463,8 +476,10 @@ namespace Crow
                protected override void Dispose (bool disposing)
                {
                        if (disposing) {
+                               childrenRWLock.EnterReadLock ();
                                foreach (Widget c in children)
                                        c.Dispose ();
+                               childrenRWLock.ExitReadLock ();
                        }
                        base.Dispose (disposing);
                }
index f597f5d7afe0a13c9a05a1249e0a4b11d441e9f3..a03a0bdc053b07cd047390214e13fddd71c7e720 100644 (file)
@@ -1,41 +1,16 @@
-//
-// Label.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Diagnostics;
 using Crow.Cairo;
 using System.Text.RegularExpressions;
-using System.Xml.Serialization;
 using System.ComponentModel;
 
-namespace Crow
-{
-    public class Label : Widget
+namespace Crow {
+       public class Label : Widget
     {
                #region CTOR
                protected Label () : base(){}
index 7909a6d9d1fae4c9cf194b6d242e76ca74dc09dc..9f2dbdc5b654459a2b85e5eecc043fc37bda08a0 100644 (file)
@@ -1,28 +1,6 @@
-//
-// PrivateContainer.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Xml.Serialization;
index da87b91e578bf3eb05b1e072dd7d03a24e4e1aea..42e4dc06660c277dd96978d312e572688b2e746e 100644 (file)
@@ -1,28 +1,6 @@
-//
-// TemplatedGroup.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Collections;
index d6c3a9685bd508ee527a74843d249ad192951375..7fdec5a1bda6d9342f0ff671904b8fa605045ba6 100644 (file)
@@ -1,28 +1,6 @@
-//
-// GraphicObject.cs
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
 //
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using System.Collections.Generic;
@@ -163,13 +141,13 @@ namespace Crow
                        GC.SuppressFinalize(this);  
                }  
                ~Widget(){
-                       Console.WriteLine(this.ToString() + " not disposed by user");
+                       Debug.WriteLine(this.ToString() + " not disposed by user");
                        Dispose(false);
                }
                protected virtual void Dispose(bool disposing){
                        if (disposed){
                                #if DEBUG_DISPOSE
-                               Console.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
+                               Debug.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
                                #endif
                                return;
                        }
@@ -1408,6 +1386,10 @@ namespace Crow
                /// </summary>
                /// <param name="clip">Clip rectangle</param>
                public virtual void RegisterClip(Rectangle clip){
+                       if (disposed) {
+                               Debug.WriteLine ($"Trying to register clip for disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
                        #if DEBUG_LOG
                        DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORegisterClip, this);
                        #endif
@@ -1417,6 +1399,10 @@ namespace Crow
                                r.Width -= r.Right - cb.Right;
                        if (r.Bottom > cb.Bottom)
                                r.Height -= r.Bottom - cb.Bottom;
+                       if (r.Width < 0 || r.Height < 0) {
+                               Debug.WriteLine ($"Invalid clip: {clip}:{r} hnd:{this}");//\n{Environment.StackTrace}");
+                               return;
+                       }
                        if (cacheEnabled && !IsDirty)
                                Clipping.UnionRectangle (r);
                        if (Parent == null)
@@ -1433,6 +1419,12 @@ namespace Crow
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                public void RegisterForGraphicUpdate ()
                {
+#if DEBUG
+                       if (disposed) {
+                               Console.WriteLine ($"RegisterForGraphicUpdate for disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
+#endif
                        IsDirty = true;
                        if (Width.IsFit || Height.IsFit)
                                RegisterForLayouting (LayoutingType.Sizing);
@@ -1443,6 +1435,13 @@ namespace Crow
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                public void RegisterForRedraw ()
                {
+#if DEBUG
+                       if (disposed) {
+                               Console.WriteLine ($"RegisterForRedraw for disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
+#endif
+
                        IsDirty = true;
                        if (RegisteredLayoutings == LayoutingType.None)
                                IFace.EnqueueForRepaint (this);
@@ -1461,6 +1460,12 @@ namespace Crow
                }
                public virtual bool ArrangeChildren { get { return false; } }
                public virtual void RegisterForLayouting(LayoutingType layoutType){
+#if DEBUG
+                       if (disposed) {
+                               Console.WriteLine ($"RegisterForLayouting({layoutType}) for disposed Widget: {this}\n{System.Environment.StackTrace}");
+                               return;
+                       }
+#endif
                        if (Parent == null)
                                return;
                        lock (IFace.LayoutMutex) {
@@ -1744,12 +1749,29 @@ namespace Crow
                /// of the widget </summary>
                public virtual void Paint (ref Context ctx)
                {
-                       #if DEBUG_LOG
+#if DEBUG_LOG
                        DebugLog.AddEvent(DbgEvtType.GOPaint, this);
-                       #endif
+#endif
                        //TODO:this test should not be necessary
-                       if (Slot.Height < 0 || Slot.Width < 0 || parent == null)
-                               return;
+
+                       if (disposed || Slot.Height < 0 || Slot.Width < 0 || parent == null){
+#if DEBUG
+                               Console.ForegroundColor = ConsoleColor.Red;
+                               if (disposed)
+                                       Console.WriteLine ($"Paint disposed widget: {this}");
+                               Console.ForegroundColor = ConsoleColor.DarkRed;
+                               if (Slot.Height < 0 || Slot.Width < 0)
+                                       Console.WriteLine ($"Paint slot invalid ({Slot}): {this}");
+                               Console.ForegroundColor = ConsoleColor.DarkMagenta;
+                               if (parent == null)
+                                       Console.WriteLine ($"Paint with parent == null: {this}");
+                               Console.ForegroundColor = ConsoleColor.Magenta;
+                               if (!isVisible)
+                                       Console.WriteLine ($"Paint invisible widget: {this}");
+                               Console.ForegroundColor = ConsoleColor.Gray;
+#endif
+                               return; 
+                       }
                        lock (this) {
                                if (cacheEnabled) {
                                        if (Slot.Width > Interface.MaxCacheSize || Slot.Height > Interface.MaxCacheSize)
index 97dd96901b55c53ec42ab83468784a5644fdce4d..60dbd9ec665d6c6e2fde9416a92c4c4870de0d49 100644 (file)
@@ -3,6 +3,7 @@
     <TargetFrameworks>net471</TargetFrameworks>
     <OutputType>Exe</OutputType>        
     <EnableDefaultNoneItems>false</EnableDefaultNoneItems>    
+    <ReleaseVersion>0.8.0</ReleaseVersion>
   </PropertyGroup>
             
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -27,4 +28,7 @@
       <Link>Interfaces\%(RecursiveDir)%(Filename)%(Extension)</Link>
     </None>
   </ItemGroup>     
+  <ItemGroup>
+    <None Remove="..\common\ui\Interfaces\basicTests\7.crow" />
+  </ItemGroup>
 </Project>
index a2b263fe25f7beaf247b530858ff0a2004793c52..09f86f76e22ede2317554944b037ac18c306a27e 100644 (file)
@@ -1,28 +1,6 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
 //
-// UIEditor.cs
-//
-// Author:
-//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
 using System;
 using Crow;
@@ -193,7 +171,7 @@ namespace tests
                        }
                        get { return List2; }
                }
-               IList<Color> testList = Color.ColorDic.Values.ToList ();
+               IList<Color> testList = Color.ColorDic.Values.OrderBy(c=>c.Hue).ThenBy(c=>c.Value).ToList ();
                public IList<Color> TestList {
                        set {
                                testList = value;
index e7cf3e2f3620e9641243f425d148d3e534a1e0c5..d083946c10b4fad49fc9ede1fc179eba32921d7d 100755 (executable)
                                </TabItem>
                        </TabView>-->
                        <MessageBox Movable="false"/>
-                       <ColorPicker SelectedColor="{²../go.Background}" Name="colorPicker" Margin="5" Fit="True" />
+                       <ColorPicker CurrentColor="{²../go.Background}" Name="colorPicker" Margin="5" />
                        <Widget Name="go" Width="100" Height="60" Background="{../../colorList.SelectedItem}"/>
-                       <Label Text="{../colorPicker.SelectedColor}"/>
+                       <Label Text="{../colorPicker.CurrentColor}"/>
                </VerticalStack>
                <Splitter/>
                <VerticalStack Width="30%" Margin="5">
diff --git a/Samples/common/ui/Interfaces/basicTests/7.crow b/Samples/common/ui/Interfaces/basicTests/7.crow
deleted file mode 100755 (executable)
index 21f75fe..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0"?>
-<Window Title="Showcase" Height="90%" Width="90%">
-       <HorizontalStack >
-               <VerticalStack Width="33%" Margin="5">
-                       <GroupBox Caption="Performance" Height="Fit">
-                               <VerticalStack Width="90%" Height="Fit" Spacing="2" >
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Fps:" Style="FpsLabel"/>
-                                               <Label Text="{fps}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Min:" Style="FpsLabel"/>
-                                               <Label Text="{fpsMin}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Max:" Style="FpsLabel"/>
-                                               <Label Text="{fpsMax}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Update:" Style="FpsLabel"/>
-                                               <Label Text="{update}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Layouting:" Style="FpsLabel"/>
-                                               <Label Text="{layouting}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Clipping:" Style="FpsLabel"/>
-                                               <Label Text="{clipping}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                                       <HorizontalStack Height="Fit">
-                                               <Label Text="Drawing:" Style="FpsLabel"/>
-                                               <Label Text="{drawing}" Style="FpsDisp"/>
-                                       </HorizontalStack>
-                               </VerticalStack>
-                       </GroupBox>
-                       <Label Width="Stretched" Margin="3" Background="Onyx"/>
-                       <TextBox Text="TextBox" Multiline="true" Margin="3"/>
-                       <HorizontalStack Height="Fit" Margin="5" Background="Onyx" CornerRadius="10">
-                               <VerticalStack Spacing="5" Width="50%">
-                                       <CheckBox Fit="true"/>
-                                       <CheckBox Fit="true"/>
-                                       <CheckBox Fit="true"/>
-                                       <CheckBox Fit="true"/>
-                               </VerticalStack>
-                               <VerticalStack Spacing="5" Width="50%">
-                                       <RadioButton Fit="true"/>
-                                       <RadioButton Fit="true"/>
-                                       <RadioButton Fit="true"/>
-                                       <RadioButton Fit="true"/>
-                               </VerticalStack>
-                       </HorizontalStack>
-                       <HorizontalStack Height="Fit" Margin="5">
-                               <Label Text="MouseEvents" Width="50%" Margin="3"
-                                       Background="Onyx"
-                                       Foreground="DimGrey"
-                                       TextAlignment="Center"
-                                       MouseEnter="{Foreground=White}"
-                                       MouseLeave="{Foreground=DimGrey}"
-                                       MouseDown="{Background=DarkRed}"
-                                       MouseUp="{Background=Onyx}"/>
-                               <Label Text="MouseEvents" Width="50%" Margin="3"
-                                       Background="Onyx"
-                                       Foreground="DimGrey"
-                                       TextAlignment="Center"
-                                       MouseEnter="{Foreground=White}"
-                                       MouseLeave="{Foreground=DimGrey}"
-                                       MouseDown="{Background=Mantis}"
-                                       MouseUp="{Background=Onyx}"/>
-                       </HorizontalStack>
-                       <GroupBox Caption="Templated controls" Height="Fit" Margin="5">
-                               <HorizontalStack Height="Fit">
-                                       <VerticalStack Width="50%">
-                                               <CheckBox Template="#Tests.Interfaces.CheckBox2.imlt" Style="CheckBox2"/>
-                                               <CheckBox  Template="#Tests.Interfaces.CheckBox2.imlt" Style="CheckBox2"/>
-                                               <CheckBox  Template="#Tests.Interfaces.CheckBox2.imlt" Style="CheckBox2"/>
-                                               <CheckBox  Template="#Tests.Interfaces.CheckBox2.imlt" Style="CheckBox2"/>
-                                       </VerticalStack>
-                                       <Splitter/>
-                                       <VerticalStack Width="50%">
-                                               <RadioButton  Template="#Tests.Interfaces.CheckBox2.imlt" Style="RadioButton2"/>
-                                               <RadioButton  Template="#Tests.Interfaces.CheckBox2.imlt" Style="RadioButton2"/>
-                                               <RadioButton  Template="#Tests.Interfaces.CheckBox2.imlt" Style="RadioButton2"/>
-                                               <RadioButton  Template="#Tests.Interfaces.CheckBox2.imlt" Style="RadioButton2"/>
-                                       </VerticalStack>
-                               </HorizontalStack>
-                       </GroupBox>
-                       <Spinner Fit="true"/>
-               </VerticalStack>
-               <VerticalStack Width="33%" Margin="5" Spacing="5">
-                       <Expandable Background="DimGrey">
-                               <Image Path="#Crow.Icons.crow.svg"/>
-                       </Expandable>
-                       <Popper Background="DimGrey" PopDirection="Bottom">
-                               <Border Fit="True" Background="DimGrey" CornerRadius="0" BorderWidth="1">
-                                       <Image Path="#Crow.Icons.crow.svg" Width="100" Height="100" Margin="10"
-                                               MouseEnter="{Background=LightGrey}"
-                                               MouseLeave="{Background=Transparent}"/>
-                               </Border>
-                       </Popper>
-                       <Slider Height="10" Width="90%"/>
-                       <Container Height="Fit" Background="Onyx" Margin="2" CornerRadius="5">
-                               <ProgressBar Background="DimGrey" Height="10" Value="50"/>
-                       </Container>
-                       <Image Path="#Crow.Icons.crow.svg" Width="60" Height="60" Background="LightGrey" />
-                       <TabView Name="tabview1"
-                               Height="120" Orientation="Horizontal" Spacing="15">
-                               <TabItem Name="TabItem1" Caption="Tab 1" Margin="0">
-                                       <VerticalStack Fit="true">
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                               <CheckBox/>
-                                       </VerticalStack>
-                               </TabItem>
-                               <TabItem Name="TabItem2" Caption="Tab 2" Background="Grey">
-                                       <VerticalStack Fit="true">
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                               <RadioButton/>
-                                       </VerticalStack>
-                               </TabItem>
-                               <TabItem Name="TabItem2" Caption="Tab 3" Background="Grey">
-                                       <Container Margin="5" CornerRadius="2">
-                                               <TextBox Height="Stretched" Margin="5" Multiline="true" TextAlignment="TopLeft"/>
-                                       </Container>
-                               </TabItem>
-                       </TabView>
-                       <MessageBox Movable="false"/>
-               </VerticalStack>
-               <VerticalStack Width="33%" Margin="5">
-                       <Border Margin="5" Background="Onyx" Height="Fit">
-                               <Label Width="Stretched" Margin="1" Text="{../../dv.SelectedItem}"/>
-                       </Border>
-                       <Border Margin="5" Background="Onyx" Height="50%">
-                               <DirectoryView Name="dv" Root="./" Margin="1"/>
-                       </Border>
-                       <ListBox Data="{TestList}" Background="Onyx" Margin="5"
-                                        ItemTemplate="#Tests.Interfaces.colorItem.crow"
-                                        Template="#Crow.Templates.ScrollingListBox.goml"/>
-               </VerticalStack>
-       </HorizontalStack>
-</Window>
\ No newline at end of file