<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" />
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
<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0"?>
+<GroupBox Caption="{./Caption}" CornerRadius="{./CornerRadius}" Foreground="{./Foreground}" Background="{./Background}">
+ <HorizontalStack Name="Content"/>
+</GroupBox>
+
<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>
<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>
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) {
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;
}
}
typeof (void),
CompilerServices.argsBoundValueChange, true);
- il = dm.GetILGenerator (32);
+ il = dm.GetILGenerator (64);
System.Reflection.Emit.Label endMethod = il.DefineLabel ();
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);
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 ();
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
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);
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);
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);
}
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)
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
#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 ();
//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
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;
-//
-// 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;
-//
-// 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;
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 ();
- }
}
}
--- /dev/null
+// 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 ();
+ }
+ }
+}
+
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;
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 ();
-//
-// 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;
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;
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;
resetChildrenMaxSize ();
- this.RegisterForLayouting (LayoutingType.Sizing);
+ RegisterForLayouting (LayoutingType.Sizing);
ChildrenCleared.Raise (this, new EventArgs ());
}
public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
protected override void Dispose (bool disposing)
{
if (disposing) {
+ childrenRWLock.EnterReadLock ();
foreach (Widget c in children)
c.Dispose ();
+ childrenRWLock.ExitReadLock ();
}
base.Dispose (disposing);
}
-//
-// 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(){}
-//
-// 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;
-//
-// 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;
-//
-// 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;
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;
}
/// </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
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)
[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);
[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);
}
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) {
/// 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)
<TargetFrameworks>net471</TargetFrameworks>
<OutputType>Exe</OutputType>
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
+ <ReleaseVersion>0.8.0</ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<Link>Interfaces\%(RecursiveDir)%(Filename)%(Extension)</Link>
</None>
</ItemGroup>
+ <ItemGroup>
+ <None Remove="..\common\ui\Interfaces\basicTests\7.crow" />
+ </ItemGroup>
</Project>
+// 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;
}
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;
</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">
+++ /dev/null
-<?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