]> O.S.I.I.S - jp/crow.git/commitdiff
CrowIDE, ObservableList, include Crow.Coding
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 13 Feb 2018 05:53:18 +0000 (06:53 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 13 Feb 2018 05:53:18 +0000 (06:53 +0100)
24 files changed:
Crow.csproj
Crow.sln
Default.style
Templates/ColorPicker.template
Templates/Spinner.template
Tests/BasicTests.cs
Tests/CrowWindow.cs
Tests/Interfaces/TabItem.template [new file with mode: 0644]
Tests/Interfaces/TemplatedContainer/testTabView.crow
Tests/Interfaces/TemplatedControl/testSpinner.crow
Tests/Tests.csproj
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/Group.cs
src/GraphicObjects/IMLContainer.cs [new file with mode: 0644]
src/GraphicObjects/MDIContainer.cs [new file with mode: 0644]
src/GraphicObjects/MessageBox.cs
src/GraphicObjects/PrivateContainer.cs
src/GraphicObjects/TabItem.cs
src/GraphicObjects/TabView.cs
src/GraphicObjects/TemplatedGroup.cs
src/IListChanged.cs [new file with mode: 0644]
src/Instantiator.cs
src/Interface.cs
src/ObservableList.cs [new file with mode: 0644]

index a8b47dc80ba1a5e51c1809ee44f397a5e96f21e7..4de640dd190ca5d47864cfd94220c9c7b6fcc72b 100644 (file)
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
-    <DefineConstants>DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_LAYOUTING0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD0;DEBUG_BINDING0;DEBUG_CLIP_RECTANGLE0</DefineConstants>
+    <DefineConstants>DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_LAYOUTING0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD0;DEBUG_BINDING;DEBUG_CLIP_RECTANGLE0</DefineConstants>
     <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)build\Debug</OutputPath>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <Optimize>true</Optimize>
     <DefineConstants>__linux__</DefineConstants>
+    <OutputPath>$(SolutionDir)build\Release</OutputPath>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="src\Colors.cs" />
     <Compile Include="src\IML\IMLContext.cs" />
     <Compile Include="src\Mono.Cairo\MeshPattern.cs" />
     <Compile Include="src\GraphicObjects\Shape.cs" />
+    <Compile Include="src\GraphicObjects\MDIContainer.cs" />
+    <Compile Include="src\IListChanged.cs" />
+    <Compile Include="src\ObservableList.cs" />
+    <Compile Include="src\GraphicObjects\IMLContainer.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
index 5fc9079fa00801de87694084d1ff5da14ab6d424..61aaa3af8775aeb9a09a749f64f9daf9dd49ede9 100644 (file)
--- a/Crow.sln
+++ b/Crow.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow.Test", "Crow.Test\Crow
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrowIDE", "CrowIDE\CrowIDE.csproj", "{B6D911CD-1D09-42FC-B300-9187190F2AE1}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow.Coding", "..\gts\CrowEdit\Crow.Coding\Crow.Coding.csproj", "{78842EE4-8A2F-4C75-AEC6-C95F15AD3994}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -22,32 +24,46 @@ Global
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.Build.0 = Release|Any CPU
                {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.Build.0 = Release|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Any CPU.Build.0 = Release|Any CPU
+               {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(MonoDevelopProperties) = preSolution
                Policies = $0
                $0.StandardHeader = $1
                $1.Text = @\n${FileName}\n \nAuthor:\n      ${AuthorName} <${AuthorEmail}>\n\nCopyright (c) 2013-2017 Jean-Philippe Bruyère\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.
-               $1.IncludeInNewFiles = True
                $0.DotNetNamingPolicy = $2
-               $2.DirectoryNamespaceAssociation = None
-               $2.ResourceNamePolicy = FileFormatDefault
                $0.TextStylePolicy = $3
-               $3.FileWidth = 120
-               $3.TabsToSpaces = False
                $3.EolMarker = Unix
-               $3.inheritsSet = VisualStudio
-               $3.inheritsScope = text/plain
                $3.scope = text/x-csharp
                $0.CSharpFormattingPolicy = $4
                $4.AfterDelegateDeclarationParameterComma = True
-               $4.inheritsSet = Mono
-               $4.inheritsScope = text/x-csharp
                $4.scope = text/x-csharp
+               $4.IndentSwitchSection = False
+               $4.NewLinesForBracesInProperties = False
+               $4.NewLinesForBracesInAccessors = False
+               $4.NewLinesForBracesInAnonymousMethods = False
+               $4.NewLinesForBracesInControlBlocks = False
+               $4.NewLinesForBracesInAnonymousTypes = False
+               $4.NewLinesForBracesInObjectCollectionArrayInitializers = False
+               $4.NewLinesForBracesInLambdaExpressionBody = False
+               $4.NewLineForElse = False
+               $4.NewLineForCatch = False
+               $4.NewLineForFinally = False
+               $4.NewLineForMembersInObjectInit = False
+               $4.NewLineForMembersInAnonymousTypes = False
+               $4.NewLineForClausesInQuery = False
+               $4.SpacingAfterMethodDeclarationName = True
+               $4.SpaceAfterMethodCallName = True
+               $4.SpaceBeforeOpenSquareBracket = True
                $0.VersionControlPolicy = $5
                $5.CommitMessageStyle = $6
                $6.Indent = @\t
@@ -55,7 +71,6 @@ Global
                $6.LastFilePostfix = "@:\n  "
                $6.LineAlign = 0
                $6.Wrap = False
-               $5.inheritsSet = Mono
                description = @C.R.O.W. c# Rapid Open Widgets\n\nCrow is a pure c# widget toolkit with XML definition of interface, bindings, styling...\n
                version = 0.5
        EndGlobalSection
index c5c04ea74e6eabebd30f23c92b8b28a4bf09af12..9a0f3f54fbae8cb6e5b90e68c458a0f01062eaaa 100644 (file)
@@ -157,7 +157,7 @@ ArrowBut {
        Focusable=true;
        Foreground=Jet;
        Background=hgradient|0:Gray|1:Jet;
-       MouseDown={Background=hgradient|0:White|0.2:BlueCrayola|1:Jet};
+       MouseDown={Background=hgradient|0:White|0.4:BlueCrayola|1:Jet};
        MouseUp={Background=hgradient|0:Gray|1:Jet};
        MouseEnter={Foreground=Black};
        MouseLeave={Foreground=Jet};
index d6bda34644262b225228ed85e9c44e7c97df2416..f626bfea0fe174ec0192d3d725592baa87dfd809 100755 (executable)
@@ -8,7 +8,7 @@
                                        Width="128" Height="128"/>
                                <HueSelector Hue="{²./H}" Focusable="true" Name="hueSelector" Margin="0" Width="128" Height="20"/>
                        </VerticalStack>
-                       <VerticalStack Margin="5" Spacing="0">
+                       <VerticalStack Margin="5" Spacing="1">
                                <GraphicObject Width="34" Height="21" Background="{./SelectedColor}"/>
                                <Label Focusable="true" Selectable="true" Width="Stretched" Text="{./HexColor}" />                              
                                <HorizontalStack Height="Fit">
index de1a4d824f6689657b211be92bf11ff9f1fa1c48..dd957d2532e45acf90857d023c11fd2b9d2b47b5 100755 (executable)
@@ -1,18 +1,12 @@
 <?xml version="1.0"?>
-<HorizontalStack MinimumSize="40,10" Name="hstack" Margin="0" Spacing="0">
-       <Border BorderWidth="1" Width="80%"  Background="White" 
+<HorizontalStack MinimumSize="40,13" Name="hstack" Margin="0" Spacing="0">
+       <Border BorderWidth="1" Width="75%"  Background="White" 
                Foreground="{./Foreground}" Margin="0">
                <TextBox Foreground="{./Foreground}" Font="{./Font}" Width="Stretched"
                        Text="{²./Value}" TextAlignment="Right" Margin="0"/>
        </Border>
-       <VerticalStack MinimumSize="8,10" Width="20%" Height="Stretched" Spacing="0" Margin="0" Background="Red">
-               <Button MouseRepeat="true" Width="Stretched" Height="50%" Margin="0" MouseClick="./onUp"
-                       Template="#Crow.Templates.ArrowBut.template">
-                       <Image Path="#Crow.Images.Icons.updown.svg" SvgSub="up" Margin="0"/>
-               </Button>                               
-               <Button MouseRepeat="true" Width="Stretched" Height="50%" Margin="0" MouseClick="./onDown" 
-                       Template="#Crow.Templates.ArrowBut.template">
-                       <Image Path="#Crow.Images.Icons.updown.svg" SvgSub="down" Margin="0"/>
-               </Button>
+       <VerticalStack MinimumSize="13,13" Width="25%" Height="Stretched" Spacing="0" Margin="0">
+               <Shape Style="ArrowBut" Height="50%" MouseClick="./onUp" Path="M 5.5,0.5 L 10.5,6.5 L 0.5,6.5 Z"/>                      
+               <Shape Style="ArrowBut" Height="50%" MouseClick="./onDown" Path="M 0.5,0.5 L 10.5,0.5 L 5.5,6.5 Z"/>                    
        </VerticalStack>
 </HorizontalStack>
index e04f160e552f4150ce61f779c19f8a2ba9dd657a..a33470b00ac849e349eaad31cc07dce43c239aa3 100644 (file)
@@ -143,7 +143,9 @@ namespace Tests
 
                        //testFiles = new string [] { @"Interfaces/Unsorted/testFileDialog.crow" };
                        //testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" };
-                       testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
+                       //testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
+                       //testFiles = new string [] { @"Interfaces/TemplatedContainer/testTabView.crow" };
+                       testFiles = new string [] { @"Interfaces/TemplatedControl/testSpinner.crow" };
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray ();
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Container", "*.crow")).ToArray ();
                        testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Group", "*.crow")).ToArray ();
@@ -203,7 +205,7 @@ namespace Tests
                                GraphicObject obj = Load (testFiles[idx]);
                                obj.DataSource = this;
                        } catch (Exception ex) {                                
-                               MessageBox.Show (MessageBox.Type.Error, ex.Message + "\n" + ex.InnerException);
+                               MessageBox.Show (CurrentInterface, MessageBox.Type.Error, ex.Message + "\n" + ex.InnerException);
                        }
                }
 //             void Tv_SelectedItemChanged (object sender, SelectionChangeEventArgs e)
index 9a0c4df0479eaf2525ba74c8a228f29fe50e824a..8ce0abb375afd90806a921ba1ad95a9dc3e8b8b4 100644 (file)
@@ -200,10 +200,13 @@ namespace Crow
                        addInterfaceControler (tmp);
                        return tmp;
                }
+               public GraphicObject AddWidget (string path)
+               {                       
+                       GraphicObject tmp = Load (path);
+                       return tmp;
+               }
                public GraphicObject AddWidget (GraphicObject g, int interfaceIdx = 0){
-                       if (ifaceControl.Count == 0)//create default orthogonal interface
-                               addInterfaceControler (new InterfaceControler (
-                                       new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height)));
+                       checkDefaultIFace ();
                        ifaceControl [interfaceIdx].CrowInterface.AddWidget (g);
                        return g;
                }
diff --git a/Tests/Interfaces/TabItem.template b/Tests/Interfaces/TabItem.template
new file mode 100644 (file)
index 0000000..3691a2d
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<GenericStack Orientation="Vertical" Spacing="0"
+               Background="Onyx"
+               MouseEnter="{caption.Foreground=White}"
+               MouseLeave="{caption.Foreground=Gray}">
+       <HorizontalStack Margin="2" Left="{./TabOffset}"
+               Name="TabTitle"
+               HorizontalAlignment="Left"
+               Height="{./TabThickness}"
+               Width="Fit">
+               <Label Name="caption" Text="{./Caption}" Foreground="Gray"/>
+               <Label Text="{./ViewIndex}" Foreground="Green"/>
+               <Label Text="{./TabOffset}" Foreground="Red"/>
+               <Border CornerRadius="5" BorderWidth="1" Foreground="Transparent"  Height="12" Width="12"
+                                       MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
+                       <Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Images.Icons.exit2.svg"
+                                MouseClick="./butCloseTabClick"/>
+               </Border>
+       </HorizontalStack>
+       <Container Name="Content"/>
+</GenericStack>
+
index fa33318b11408093c33dbe74c18504cd397a1444..63c898d9e3f07d094d51baf3e89beaf614ee8d56 100644 (file)
@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <VerticalStack Height="50%" Width="80%">
+       <HorizontalStack Height="Fit">
+               <Label Text="Selected Tab:"/>
+               <Label Text="{../../tabview1.SelectedTab}"/>
+       </HorizontalStack>
        <TabView Name="tabview1" Orientation="Horizontal" Spacing="24">
                <TabItem Name="TabItem1" Caption="tab item 1">
                        <VerticalStack Margin="20">
                                <RadioButton/>
                        </VerticalStack>
                </TabItem>
-               <TabItem Name="TabItem2" Caption="tab item 3" Background="Gray">
+               <TabItem Name="TabItem3" Caption="tab item 3" Background="Gray">
                        <Container Margin="5" CornerRadius="2" >
                                <TextBox Margin="5" Multiline="true" TextAlignment="TopLeft"/>
                        </Container>
                </TabItem>
-               <TabItem Name="TabItem2" Caption="tab item 4" Margin="0" Background="Gray">
+               <TabItem Name="TabItem4" Caption="tab item 4" Margin="0" Background="Gray">
                        <TextBox/>
                </TabItem>
        </TabView>
index 4efd587af5986289f19277ef6290d2f73e2f8de6..09f618be181beada32b110059922b21b1fe549d6 100755 (executable)
@@ -8,4 +8,5 @@
                <Spinner Value="5"/>
                <Button/>
        </HorizontalStack>
+       <IMLContainer Path="Interfaces/Divers/colorPicker.crow"/>
 </VerticalStack>
\ No newline at end of file
index 7fd3f6ed004a7861bb71c90501fdc793197c109c..5016b0ee01c276ec109afc1b34f7b0ab42fa375e 100644 (file)
@@ -8,7 +8,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>Tests</RootNamespace>
     <AssemblyName>Tests</AssemblyName>
-    <StartupObject>Tests.Showcase</StartupObject>
+    <StartupObject>Tests.BasicTests</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ReleaseVersion>0.5</ReleaseVersion>
     <StartWorkingDirectory>%24{SolutionDir}\build\%24{ProjectConfigName}</StartWorkingDirectory>
     <ConsolePause>false</ConsolePause>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(RunConfiguration)' == 'Custom Command' ">
+    <StartAction>Program</StartAction>
+    <StartProgram>%24{TargetName}</StartProgram>
+    <StartWorkingDirectory>%24{SolutionDir}\build\%24{ProjectConfigName}</StartWorkingDirectory>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(RunConfiguration)' == 'Custom Command' ">
+    <StartAction>Program</StartAction>
+    <StartProgram>%24{TargetName}</StartProgram>
+    <StartWorkingDirectory>%24{SolutionDir}\build\%24{ProjectConfigName}</StartWorkingDirectory>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Data" />
     <EmbeddedResource Include="Tutorials\test.crow">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </EmbeddedResource>
+    <EmbeddedResource Include="Interfaces\TabItem.template">
+      <LogicalName>Crow.TabItem.template</LogicalName>
+    </EmbeddedResource>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Crow.csproj">
index e24e9b284ff307b822f1d5bb08abe1c3031fbea5..6ec60cf3e75e6969293342e81c13e4d8fc7120ab 100644 (file)
@@ -363,6 +363,11 @@ namespace Crow
                                this.RegisterForRedraw ();
                        }
                }
+               #if DEBUG
+               [XmlIgnore]public string TreePath {
+                       get { return this.GetType().Name + uid.ToString ();     }
+               }
+               #endif
                /// <summary>
                /// Name is used in binding to reference other GraphicObjects inside the graphic tree
                /// and by template controls to find special element in their template implementation such
@@ -785,7 +790,7 @@ namespace Crow
                                OnDataSourceChanged (this, e);
                }
                internal bool localDataSourceIsNull { get { return dataSource == null; } }
-               internal bool localLogicalParentIsNull { get { return logicalParent == null; } }
+               public bool localLogicalParentIsNull { get { return logicalParent == null; } }
 
                public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){
                        DataSourceChanged.Raise (this, e);
index a940ee7e7cd034d4ceb1c82e278e6cc22b1752bf..c944eba256dc78d6897cda59d71ae22c6e030a05 100644 (file)
@@ -38,7 +38,7 @@ namespace Crow
        public class Group : GraphicObject
     {
                #region CTOR
-               protected Group () : base(){}
+               public Group () : base() {}
                public Group(Interface iface) : base(iface){}
                #endregion
 
@@ -90,6 +90,18 @@ namespace Crow
 
                        this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
         }
+               public virtual void InsertChild (int idx, GraphicObject g) {
+                       lock (children) {
+                               g.Parent = this;
+                               Children.Insert (idx, g);
+                       }
+                       g.RegisteredLayoutings = LayoutingType.None;
+                       g.LayoutChanged += OnChildLayoutChanges;
+                       g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
+               }
+               public virtual void RemoveChild (int idx) {
+                       RemoveChild (children[idx]);
+               }
                public virtual void ClearChildren()
                {
                        lock (children) {
diff --git a/src/GraphicObjects/IMLContainer.cs b/src/GraphicObjects/IMLContainer.cs
new file mode 100644 (file)
index 0000000..a221a78
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// IMLContainer.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.
+using System;
+
+namespace Crow
+{
+       public class IMLContainer : PrivateContainer
+       {
+               public IMLContainer () : base()
+               {
+               }
+
+               string path;
+
+               public string Path {
+                       get { return path; }
+                       set {
+                               if (path == value)
+                                       return;
+                               path = value;
+                               this.SetChild (CurrentInterface.Load (path));
+                               NotifyValueChanged ("Path", path);
+                       }
+               }
+       }
+}
+
diff --git a/src/GraphicObjects/MDIContainer.cs b/src/GraphicObjects/MDIContainer.cs
new file mode 100644 (file)
index 0000000..d8ce464
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// MDIContainer.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.
+using System;
+
+namespace Crow
+{
+       public class MDIContainer : Group
+       {
+               #region CTOR
+               public MDIContainer () : base()
+               {
+               }
+               #endregion
+
+       }
+}
+
index 7f945810095a69917b99fc26175ee583ccc7dd7b..e1c8cc876d31d6f26d7ab861181fe0988bb6f843 100644 (file)
@@ -134,9 +134,9 @@ namespace Crow
                        Cancel.Raise (this, null);
                        close ();
                }
-               public static MessageBox Show (Type msgBoxType, string message, string okMsg = "", string cancelMsg = ""){
+               public static MessageBox Show (Interface iface, Type msgBoxType, string message, string okMsg = "", string cancelMsg = ""){
                        //lock (Interface.CurrentInterface.UpdateMutex) {
-                               MessageBox mb = new MessageBox (Interface.CurrentInterface);
+                               MessageBox mb = new MessageBox (iface);
                                mb.CurrentInterface.AddWidget (mb);
                                mb.MsgType = msgBoxType;
                                mb.Message = message;
index 5ee29e9498c3be9b0c1eafd3ab2273e2503e5411..e76b57a828debf8e2a52ec3b7cede086a873d009 100644 (file)
@@ -47,7 +47,7 @@ namespace Crow
 
                protected GraphicObject child;
 
-               internal virtual void SetChild(GraphicObject _child)
+               protected virtual void SetChild(GraphicObject _child)
                {
 
                        if (child != null) {
@@ -204,6 +204,7 @@ namespace Crow
                public override void checkHoverWidget (MouseMoveEventArgs e)
                {
                        base.checkHoverWidget (e);
+
                        if (child != null) 
                                if (child.MouseIsIn (e.Position)) 
                                        child.checkHoverWidget (e);
index b35c544c101dafb2a5381287e88235d72aad7985..d811ea5453eb57221151f789150db1e8278fd93c 100644 (file)
@@ -29,6 +29,7 @@ using System.Xml.Serialization;
 using System.ComponentModel;
 using System.Diagnostics;
 using Cairo;
+using System.Linq;
 
 namespace Crow
 {
@@ -39,6 +40,8 @@ namespace Crow
                public TabItem (Interface iface) : base(iface){}
                #endregion
 
+               public event EventHandler QueryClose;
+
                #region Private fields
                GraphicObject titleWidget;
                int tabOffset;
@@ -70,6 +73,21 @@ namespace Crow
                internal GraphicObject TabTitle { get { return titleWidget; }}
                #endregion
 
+               /// <summary>
+               /// order of redrawing, items can't be reordered in TemplatedGroup due to data linked, so we need another index
+               /// instead of children list order
+               /// </summary>
+               public int viewIndex = 0;
+               public virtual int ViewIndex {
+                       get { return viewIndex; }
+                       set {
+                               if (viewIndex == value)
+                                       return;
+                               viewIndex = value;
+                               NotifyValueChanged ("ViewIndex", viewIndex);
+                       }
+               }
+
                [XmlAttributeAttribute][DefaultValue("18")]
                public virtual Measure TabThickness {
                        get { return tabThickness; }
@@ -128,7 +146,7 @@ namespace Crow
                        gr.LineTo (Slot.Width-0.5, Slot.Height-0.5);
                        gr.LineTo (0.5, Slot.Height-0.5);
                        gr.ClosePath ();
-                       gr.LineWidth = 2;
+                       gr.LineWidth = 1;
                        Foreground.SetAsSource (gr);
                        gr.StrokePreserve ();
 
@@ -138,6 +156,8 @@ namespace Crow
                }
 
                #region Mouse Handling
+               public bool HoldCursor = false;
+
                public override bool MouseIsIn (Point m)
                {
                        if (!(Visible & IsEnabled) || IsDragged)
@@ -150,23 +170,22 @@ namespace Crow
                        return _contentContainer.ScreenCoordinates (_contentContainer.Slot).ContainsOrIsEqual (m)
                                || mouseIsInTitle;
                }
-               bool holdCursor = false;
                public override void onMouseDown (object sender, MouseButtonEventArgs e)
                {
                        base.onMouseDown (sender, e);
-                       holdCursor = true;
+                       HoldCursor = true;
                }
                public override void onMouseUp (object sender, MouseButtonEventArgs e)
                {
                        base.onMouseUp (sender, e);
-                       holdCursor = false;
+                       HoldCursor = false;
                        (Parent as TabView).UpdateLayout (LayoutingType.ArrangeChildren);
                }
                public override void onMouseMove (object sender, MouseMoveEventArgs e)
                {
                        base.onMouseMove (sender, e);
 
-                       if (!(HasFocus&&holdCursor))
+                       if (!(HasFocus && HoldCursor))
                                return;
                        TabView tv = Parent as TabView;
                        TabItem previous = null, next = null;
@@ -176,31 +195,28 @@ namespace Crow
                        else if (tmp > Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing)
                                TabOffset = Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing;
                        else{
-                               int idx = tv.Children.IndexOf (this);
-                               if (idx > 0 && e.XDelta < 0) {
-                                       previous = tv.Children [idx - 1] as TabItem;
-
+                               TabItem[] tabItms = tv.Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                               if (ViewIndex > 0 && e.XDelta < 0) {
+                                       previous = tabItms [ViewIndex - 1];
                                        if (tmp < previous.TabOffset + previous.TabTitle.Slot.Width / 2) {
-                                               tv.Children.RemoveAt (idx);
-                                               tv.Children.Insert (idx - 1, this);
-                                               tv.SelectedTab = idx - 1;
+                                               previous.ViewIndex = ViewIndex;
+                                               ViewIndex--;
                                                tv.UpdateLayout (LayoutingType.ArrangeChildren);
                                        }
 
-                               }else if (idx < tv.Children.Count - 1 && e.XDelta > 0) {
-                                       next = tv.Children [idx + 1] as TabItem;
+                               }else if (ViewIndex < tabItms.Length - 1 && e.XDelta > 0) {
+                                       next = tabItms [ViewIndex + 1];
                                        if (tmp > next.TabOffset - next.TabTitle.Slot.Width / 2){
-                                               tv.Children.RemoveAt (idx);
-                                               tv.Children.Insert (idx + 1, this);
-                                               tv.SelectedTab = idx + 1;
+                                               next.ViewIndex = ViewIndex;
+                                               ViewIndex++;
                                                tv.UpdateLayout (LayoutingType.ArrangeChildren);
                                        }
                                }
                                TabOffset = tmp;
                        }
                }
-               public void butCloseTabClick (object sender, MouseButtonEventArgs e){
-                       (Parent as TabView).RemoveChild(this);
+               public void butCloseTabClick (object sender, MouseButtonEventArgs e){                   
+                       QueryClose.Raise (this, null);
                }
                #endregion
 
index 7bf93abdb1e0a376b962f3b95b334d5ad94d56c0..3e776d3a46a5ded56e718ba3afaabd427666a4bf 100644 (file)
@@ -29,13 +29,14 @@ using System.Xml.Serialization;
 using System.ComponentModel;
 using Cairo;
 using System.Diagnostics;
+using System.Linq;
 
 namespace Crow
 {      
        public class TabView : Group
        {
                #region CTOR
-               protected TabView() : base(){}
+               public TabView() : base(){}
                public TabView (Interface iface) : base(iface){}
                #endregion
 
@@ -46,7 +47,6 @@ namespace Crow
                int selectedTab = 0;
                #endregion
 
-
                #region public properties
                [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)]
                public virtual Orientation Orientation
@@ -92,6 +92,12 @@ namespace Crow
                }
                #endregion
 
+               void Ti_TabTitle_LayoutChanged (object sender, LayoutingEventArgs e)
+               {
+                       if (e.LayoutType == LayoutingType.Width)
+                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+               }
+
                public override void AddChild (GraphicObject child)
                {
                        TabItem ti = child as TabItem;
@@ -99,22 +105,28 @@ namespace Crow
                                throw new Exception ("TabView control accept only TabItem as child.");
 
                        ti.MouseDown += Ti_MouseDown;
-
-                       if (Children.Count == 0) {
-                               ti.IsSelected = true;
-                               SelectedTab = 0;
-                       }
+                       ti.TabTitle.LayoutChanged += Ti_TabTitle_LayoutChanged;
 
                        base.AddChild (child);
+
+                       SelectedTab = ti.ViewIndex = Children.Count - 1;
                }
+
                public override void RemoveChild (GraphicObject child)
                {
-                       base.RemoveChild (child);
-                       if (selectedTab > Children.Count - 1)
+                       TabItem ti = child as TabItem;
+                       if (ti == null)
+                               throw new Exception ("TabView control accept only TabItem as child.");
+
+                       ti.MouseDown -= Ti_MouseDown;
+                       ti.TabTitle.LayoutChanged -= Ti_TabTitle_LayoutChanged;
+
+                       if (selectedTab > Children.Count - 2)
                                SelectedTab--;
-                       else
-                               SelectedTab = selectedTab;
+                       
+                       base.RemoveChild (child);
                }
+
                public override bool ArrangeChildren { get { return true; } }
                public override bool UpdateLayout (LayoutingType layoutType)
                {
@@ -122,19 +134,20 @@ namespace Crow
 
                        if (layoutType == LayoutingType.ArrangeChildren) {
                                int curOffset = Spacing;
-                               for (int i = 0; i < Children.Count; i++) {
-                                       if (!Children [i].Visible)
+                               TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                               for (int i = 0; i < tabItms.Length; i++) {
+                                       if (!tabItms [i].Visible)
                                                continue;
-                                       TabItem ti = Children [i] as TabItem;
-                                       ti.TabOffset = curOffset;
+                                       if (!tabItms [i].HoldCursor)
+                                               tabItms [i].TabOffset = curOffset;
                                        if (Orientation == Orientation.Horizontal) {
-                                               if (ti.TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Width))
+                                               if (tabItms [i].TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Width))
                                                        return false;
-                                               curOffset += ti.TabTitle.Slot.Width + Spacing;
+                                               curOffset += tabItms [i].TabTitle.Slot.Width + Spacing;
                                        } else {
-                                               if (ti.TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Height))
+                                               if (tabItms [i].TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Height))
                                                        return false;
-                                               curOffset += ti.TabTitle.Slot.Height + Spacing;
+                                               curOffset += tabItms [i].TabTitle.Slot.Height + Spacing;
                                        }
                                }
 
@@ -163,15 +176,17 @@ namespace Crow
                                gr.Clip ();
                        }
 
-                       for (int i = 0; i < Children.Count; i++) {
-                               if (i == SelectedTab)
-                                       continue;
-                               Children [i].Paint (ref gr);
-                       }
-
-                       if (SelectedTab < Children.Count && SelectedTab >= 0)
-                               Children [SelectedTab].Paint (ref gr);
+                       lock (Children) {
+                               TabItem[] tabItms = Children.Cast<TabItem> ().OrderBy (t => t.ViewIndex).ToArray ();
+                               for (int i = 0; i < tabItms.Length; i++) {
+                                       if (tabItms [i] == Children [SelectedTab])
+                                               continue;
+                                       tabItms [i].Paint (ref gr);
+                               }
 
+                               if (SelectedTab < tabItms.Length && SelectedTab >= 0)
+                                       Children [SelectedTab].Paint (ref gr);
+                       }
                        gr.Restore ();
                }
 
@@ -191,11 +206,11 @@ namespace Crow
                                Children[SelectedTab].checkHoverWidget (e);
                                return;
                        }
-                       for (int i = Children.Count - 1; i >= 0; i--) {
-                               TabItem ti = Children [i] as TabItem;
-                               if (ti.TabTitle.MouseIsIn(e.Position))
+                       TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                       for (int i = tabItms.Length - 1; i >= 0; i--) {                         
+                               if (tabItms [i].TabTitle.MouseIsIn(e.Position))
                                {
-                                       Children[i].checkHoverWidget (e);
+                                       tabItms [i].checkHoverWidget (e);
                                        return;
                                }
                        }
index 34d5772700a81bf28226c31ba7a1aadb7760a6cd..069303dd0114f2097eda4956fdcbd0833a93472d 100644 (file)
@@ -172,8 +172,20 @@ namespace Crow
 
                                cancelLoadingThread ();
 
+                               if (data is IObservableList) {
+                                       IObservableList ol = data as IObservableList;
+                                       ol.ListAdd -= Ol_ListAdd;
+                                       ol.ListRemove -= Ol_ListRemove;
+                               }
+
                                data = value;
 
+                               if (data is IObservableList) {
+                                       IObservableList ol = data as IObservableList;
+                                       ol.ListAdd += Ol_ListAdd;
+                                       ol.ListRemove += Ol_ListRemove;
+                               }
+
                                NotifyValueChanged ("Data", data);
 
                                lock (CurrentInterface.LayoutMutex)
@@ -193,6 +205,27 @@ namespace Crow
                        }
                }
 
+               void Ol_ListRemove (object sender, ListChangedEventArg e)
+               {
+                       if (this.isPaged) {
+                               int p = e.Index / itemPerPage;
+                               int i = e.Index % itemPerPage;
+                               (items.Children [p] as Group).RemoveChild (i);
+                       } else
+                               items.RemoveChild (e.Index);
+               }
+
+               void Ol_ListAdd (object sender, ListChangedEventArg e)
+               {
+                       if (this.isPaged) {
+                               throw new NotImplementedException();
+//                             int p = e.Index / itemPerPage;
+//                             int i = e.Index % itemPerPage;
+//                             (items.Children [p] as Group).InsertChild (i, e.Element);
+                       } else
+                               loadItem (e.Index, items);
+               }
+
                [XmlAttributeAttribute][DefaultValue("SteelBlue")]
                public virtual Color SelectionBackground {
                        get { return selBackground; }
@@ -311,7 +344,7 @@ namespace Crow
                        #endif
 
                        Group page;
-                       if (typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
+                       if (typeof(TabView).IsAssignableFrom (items.GetType ())||typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
                                page = items;
                                itemPerPage = int.MaxValue;
                        } else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) {
@@ -326,6 +359,8 @@ namespace Crow
                                isPaged = true;
                        } else {
                                page = Activator.CreateInstance (items.GetType ()) as Group;
+                               page.CurrentInterface = items.CurrentInterface;
+                               page.Initialize ();
                                page.Name = "page" + pageNum;
                                isPaged = true;
                        }
diff --git a/src/IListChanged.cs b/src/IListChanged.cs
new file mode 100644 (file)
index 0000000..b2b2337
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// IListChanged.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.
+using System;
+
+namespace Crow
+{
+       public class ListChangedEventArg : EventArgs {
+               public int Index;
+               public object Element;
+               public ListChangedEventArg (int index, object element) {
+                       Index = index;
+                       Element = element;
+               }
+       }
+       public interface IObservableList {
+               event EventHandler<ListChangedEventArg> ListAdd;
+               event EventHandler<ListChangedEventArg> ListRemove;             
+       }
+}
+
index b3f070e7d609d1ba7231e36c296cb49caf900c59..f5355c177755376a3e5af940a807db626e85e7ad 100644 (file)
@@ -560,8 +560,13 @@ namespace Crow.IML
                                System.Reflection.Emit.Label finish = il.DefineLabel ();
                                il.Emit (OpCodes.Br, finish);
                                il.MarkLabel (cancel);
-                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' not found in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
+                               #if DEBUG_BINDING
+                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' NOT FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
+                               #endif
                                il.MarkLabel (finish);
+                               #if DEBUG_BINDING
+                               il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name));
+                               #endif
                                il.Emit (OpCodes.Ret);
 
                                //store dschange delegate in instatiator instance for access while instancing graphic object
@@ -1075,18 +1080,23 @@ namespace Crow.IML
 
                /// <summary>
                /// search for graphic object type in crow assembly, if not found,
-               /// search for type independently of namespace in entry assembly
+               /// search for type independently of namespace in all the loaded assemblies
                /// </summary>
+               /// <remarks>
+               /// </remarks>
                /// <returns>the corresponding type object</returns>
                /// <param name="typeName">graphic object type name without its namespace</param>
                Type tryGetGOType (string typeName){
                        Type t = Type.GetType ("Crow." + typeName);
                        if (t != null)
-                               return t;
-                       Assembly a = Assembly.GetEntryAssembly ();
-                       foreach (Type expT in a.GetExportedTypes ()) {
-                               if (expT.Name == typeName)
-                                       return expT;
+                               return t;                       
+                       foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
+                               if (a.IsDynamic)
+                                       continue;
+                               foreach (Type expT in a.GetExportedTypes ()) {
+                                       if (expT.Name == typeName)
+                                               return expT;
+                               }
                        }
                        return null;
                }
index 992ff6f69950f4bbcbfc1c7c3832aaf560eb5aa9..d4cc63c40b3d3efcc2520b3fbb63bf7afb6d304b 100644 (file)
@@ -132,7 +132,7 @@ namespace Crow
                /// Each control need a ref to the root interface containing it, if not set in GraphicObject.currentInterface,
                /// the ref of this one will be stored in GraphicObject.currentInterface
                /// </summary>
-               internal static Interface CurrentInterface;
+               protected static Interface CurrentInterface;
                internal Stopwatch clickTimer = new Stopwatch();
                internal GraphicObject eligibleForDoubleClick = null;
                #endregion
@@ -337,11 +337,11 @@ namespace Crow
                /// <param name="path">path of the iml file to load</param>
                public GraphicObject Load (string path)
                {
-                       try {
+                       //try {
                                return GetInstantiator (path).CreateInstance (this);
-                       } catch (Exception ex) {
-                               throw new Exception ("Error loading <" + path + ">:", ex);
-                       }
+                       //} catch (Exception ex) {
+                       //      throw new Exception ("Error loading <" + path + ">:", ex);
+                       //}
                }
                /// <summary>
                /// Fetch instantiator from cache or create it.
@@ -409,7 +409,7 @@ namespace Crow
                        }
                }
                /// <summary>Pointer is over the widget</summary>
-               public GraphicObject HoverWidget
+               public virtual GraphicObject HoverWidget
                {
                        get { return _hoverWidget; }
                        set {
@@ -775,7 +775,7 @@ namespace Crow
                /// <summary>Processes mouse move events from the root container, this function
                /// should be called by the host on mouse move event to forward events to crow interfaces</summary>
                /// <returns>true if mouse is in the interface</returns>
-               public bool ProcessMouseMove(int x, int y)
+               public virtual bool ProcessMouseMove(int x, int y)
                {
                        int deltaX = x - Mouse.X;
                        int deltaY = y - Mouse.Y;
diff --git a/src/ObservableList.cs b/src/ObservableList.cs
new file mode 100644 (file)
index 0000000..c3d49e2
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// IListChanged.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.
+using System;
+using System.Collections.Generic;
+
+namespace Crow
+{      
+       public class ObservableList<T> : List<T> , IObservableList {
+               public event EventHandler<ListChangedEventArg> ListAdd;
+               public event EventHandler<ListChangedEventArg> ListRemove;              
+
+               public void AddElement (T elem) {
+                       this.Add(elem);
+                       ListAdd.Raise (this, new ListChangedEventArg (this.Count - 1, elem));
+               }
+               public void RemoveElement (T elem) {
+                       int idx = this.IndexOf (elem);
+                       this.RemoveAt (idx);
+                       ListRemove.Raise (this, new ListChangedEventArg (idx, elem));
+               }
+       }
+}
+