diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2017-01-01 18:30:51 +0100 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2017-01-01 18:30:51 +0100 |
| commit | 0f1346e33b59f7693f4ff40b5524c93d2629c5ce (patch) | |
| tree | 7f531b6bf6fe3f37da101a12a9b2529403e4c53c /src/GraphicObjects | |
| parent | 7c00385bda3a9a913050480fada2efab8d6d3090 (diff) | |
| parent | 7fa6c6ca89e7a3aeadd815867de8a2a3b955134a (diff) | |
New binding system and new inherited measures
Diffstat (limited to 'src/GraphicObjects')
21 files changed, 962 insertions, 432 deletions
diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs index 59762182..1cfbe85c 100644 --- a/src/GraphicObjects/Button.cs +++ b/src/GraphicObjects/Button.cs @@ -47,12 +47,6 @@ namespace Crow #endregion #region GraphicObject Overrides - public override void ResolveBindings () - { - base.ResolveBindings (); - if (Content != null) - Content.ResolveBindings (); - } public override void onMouseDown (object sender, MouseButtonEventArgs e) { IsPressed = true; diff --git a/src/GraphicObjects/ColorPicker.cs b/src/GraphicObjects/ColorPicker.cs new file mode 100644 index 00000000..cc8dfac3 --- /dev/null +++ b/src/GraphicObjects/ColorPicker.cs @@ -0,0 +1,223 @@ +// +// ColorPicker.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + public class ColorPicker : TemplatedControl + { + public ColorPicker () : base () + { + } + + const double div = 255.0; + const double colDiv = 1.0 / div; + + Color curColor; + double h,s,v; + + [XmlAttributeAttribute()] + 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 (); + } + } + [XmlAttributeAttribute()] + 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 (); + } + } + [XmlAttributeAttribute()] + 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 (); + } + } + [XmlAttributeAttribute()] + 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 (); + } + } + [XmlAttributeAttribute()] + public virtual double H { + get { return Math.Round (h, 3); } + set { + if (H == value) + return; + h = value; + NotifyValueChanged ("H", H); + rgbFromHSV (); + } + } + [XmlAttributeAttribute()] + public virtual double S { + get { return Math.Round (s, 2); } + set { + if (s == value) + return; + s = value; + NotifyValueChanged ("S", S); + rgbFromHSV (); + } + } + [XmlAttributeAttribute()] + public virtual double V { + get { return Math.Round (v, 2); } + set { + if (v == value) + return; + v = value; + NotifyValueChanged ("V", V); + rgbFromHSV (); + } + } + + [XmlAttributeAttribute] + public virtual Fill SelectedColor { + get { return new SolidColor(curColor); } + set { + Color c = (value as SolidColor).color; + if (curColor == c) + return; + curColor = c; + notifyCurColorHasChanged (); + notifyRGBAHasChanged (); + hsvFromRGB (); + } + } + + void notifyCurColorHasChanged(){ + NotifyValueChanged ("SelectedColor", SelectedColor); + string n = curColor.ToString (); + if (char.IsLetter(n[0])) + NotifyValueChanged ("SelectedColorName", n); + else + NotifyValueChanged ("SelectedColorName", "-"); + NotifyValueChanged ("HexColor", ((int)R).ToString ("X2") + ((int)G).ToString ("X2") + ((int)B).ToString ("X2") + ((int)A).ToString ("X2")); + } + 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; + 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(){ + Color c = Color.Black; + + if (s == 0) {//HSV from 0 to 1 + c.R = v; + c.G = v; + c.B = v; + }else{ + double var_h = h * 6.0; + + if (var_h == 6.0) + var_h = 0; //H must be < 1 + double var_i = Math.Floor( var_h ); //Or ... var_i = floor( var_h ) + double var_1 = v * ( 1.0 - s ); + double var_2 = v * (1.0 - s * (var_h - var_i)); + double var_3 = v * (1.0 - s * (1.0 - (var_h - var_i))); + + if (var_i == 0.0) { + c.R = v; + c.G = var_3; + c.B = var_1; + }else if ( var_i == 1.0 ) { c.R = var_2 ; c.G = v ; c.B = var_1; } + else if ( var_i == 2 ) { c.R = var_1 ; c.G = v ; c.B = var_3; } + else if ( var_i == 3 ) { c.R = var_1 ; c.G = var_2 ; c.B = v; } + else if ( var_i == 4 ) { c.R = var_3 ; c.G = var_1 ; c.B = v; } + else { c.R = v ; c.G = var_1 ; c.B = var_2; } + } + + curColor = c; + notifyCurColorHasChanged (); + notifyRGBAHasChanged (); + } + } +} + diff --git a/src/GraphicObjects/ColorSelector.cs b/src/GraphicObjects/ColorSelector.cs new file mode 100644 index 00000000..13a588ce --- /dev/null +++ b/src/GraphicObjects/ColorSelector.cs @@ -0,0 +1,89 @@ +// +// ColorPicker.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + public class ColorSelector : GraphicObject + { + public ColorSelector (): base() + { + } + + const double div = 255.0; + const double colDiv = 1.0 / div; + protected Point mousePos; + + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + if (CurrentInterface.Mouse.LeftButton == ButtonState.Released) + return; + updateMouseLocalPos (e.Position); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); + if (e.Button == MouseButton.Left) + updateMouseLocalPos (e.Position); + } + + protected virtual void updateMouseLocalPos(Point mPos){ + Rectangle r = ScreenCoordinates (Slot); + Rectangle cb = ClientRectangle; + mousePos = mPos - r.Position; + + mousePos.X = Math.Max(cb.X, mousePos.X); + mousePos.X = Math.Min(cb.Right-1, mousePos.X); + mousePos.Y = Math.Max(cb.Y, mousePos.Y); + mousePos.Y = Math.Min(cb.Bottom-1, mousePos.Y); + } +// virtual protected void updateColorFromPicking(bool redraw = true){ +// SelectedColor = new SolidColor(getPixelAt(mousePos.X, mousePos.Y)); +// +// updateHSV (); +// +// NotifyValueChanged ("R", R); +// NotifyValueChanged ("G", G); +// NotifyValueChanged ("B", B); +// NotifyValueChanged ("A", A); +// +// if (redraw) +// RegisterForRedraw (); +// } +// +// protected Color getPixelAt(int x, int y){ +// if (bmp == null) +// return Color.Transparent; +// +// int ptr = y * Slot.Width * 4 + x * 4; +// +// return new Color( +// (double)bmp[ptr + 2] * colDiv, +// (double)bmp[ptr + 1] * colDiv, +// (double)bmp[ptr] * colDiv, +// (double)bmp[ptr + 3] * colDiv); +// } + } +} + diff --git a/src/GraphicObjects/IBindable.cs b/src/GraphicObjects/DataSourceChangeEventArgs.cs index 45ff5864..56d44428 100644 --- a/src/GraphicObjects/IBindable.cs +++ b/src/GraphicObjects/DataSourceChangeEventArgs.cs @@ -1,10 +1,10 @@ // -// IValueChange.cs +// DataSourceChangeEventArg.cs // // Author: // Jean-Philippe Bruyère <jp.bruyere@hotmail.com> // -// Copyright (c) 2015 jp +// Copyright (c) 2016 jp // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -19,14 +19,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. using System; -using System.Collections.Generic; namespace Crow { - public interface IBindable + public class DataSourceChangeEventArgs : EventArgs { - List<Binding> Bindings { get; } - object DataSource { get; set; } + public object OldDataSource; + public object NewDataSource; + + public DataSourceChangeEventArgs (object oldDataSource, object newDataSource) : base() + { + OldDataSource = oldDataSource; + NewDataSource = newDataSource; + } + public override string ToString () + { + return string.Format ("DSChangeEA: {0} => {1}", OldDataSource, NewDataSource); + } } } diff --git a/src/GraphicObjects/DirectoryView.cs b/src/GraphicObjects/DirectoryView.cs index 4e29621e..5ed46f3e 100644 --- a/src/GraphicObjects/DirectoryView.cs +++ b/src/GraphicObjects/DirectoryView.cs @@ -52,7 +52,7 @@ namespace Crow NotifyValueChanged ("SelectedItem", _selectedItem); } } - [XmlAttributeAttribute()][DefaultValue(false)] + [XmlAttributeAttribute()][DefaultValue(true)] public virtual bool ShowFiles { get { return showFiles; } set { @@ -76,8 +76,10 @@ namespace Crow } [XmlIgnore]public FileSystemInfo[] FileSystemEntries { get { - return showFiles ? new DirectoryInfo (CurrentDirectory).GetFileSystemInfos (): - new DirectoryInfo(currentDirectory).GetDirectories(); + return string.IsNullOrEmpty(CurrentDirectory) ? null : + showFiles ? + new DirectoryInfo (CurrentDirectory).GetFileSystemInfos () : + new DirectoryInfo(CurrentDirectory).GetDirectories(); } } public void onSelectedItemChanged (object sender, SelectionChangeEventArgs e){ diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs index 70451f41..38506de8 100644 --- a/src/GraphicObjects/Expandable.cs +++ b/src/GraphicObjects/Expandable.cs @@ -45,14 +45,12 @@ namespace Crow public event EventHandler Collapse; #endregion - #region GraphicObject overrides - public override void onMouseClick (object sender, MouseButtonEventArgs e) + public BooleanTestOnInstance GetIsExpandable; + + public void onClickForExpand (object sender, MouseButtonEventArgs e) { - if (this.HasFocus) - IsExpanded = !IsExpanded; - base.onMouseClick (sender, e); + IsExpanded = !IsExpanded; } - #endregion public override GraphicObject Content { get { @@ -70,15 +68,9 @@ namespace Crow _contentContainer = this.child.FindByName ("Content") as Container; } - public override void ResolveBindings () - { - base.ResolveBindings (); - if (Content != null) - Content.ResolveBindings (); - } #region Public properties - [XmlAttributeAttribute()][DefaultValue("Expandable")] + [XmlAttributeAttribute][DefaultValue("Expandable")] public string Caption { get { return caption; } set { @@ -88,7 +80,7 @@ namespace Crow NotifyValueChanged ("Caption", caption); } } - [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.expandable.svg")] + [XmlAttributeAttribute][DefaultValue("#Crow.Images.Icons.expandable.svg")] public string Image { get { return image; } set { @@ -98,7 +90,7 @@ namespace Crow NotifyValueChanged ("Image", image); } } - [XmlAttributeAttribute()][DefaultValue(false)] + [XmlAttributeAttribute][DefaultValue(false)] public bool IsExpanded { get { return _isExpanded; } @@ -109,7 +101,9 @@ namespace Crow _isExpanded = value; - if (!HasContent) + bool isExp = IsExpandable; + NotifyValueChanged ("IsExpandable", isExp); + if (!(HasContent & isExp)) _isExpanded = false; NotifyValueChanged ("IsExpanded", _isExpanded); @@ -123,7 +117,16 @@ namespace Crow [XmlIgnore]public bool HasContent { get { return _contentContainer == null ? false : _contentContainer.Child != null; } } - + [XmlIgnore]public bool IsExpandable { + get { + try { + return GetIsExpandable == null ? true : GetIsExpandable (this); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine ("Not Expandable error: " + ex.ToString ()); + return false; + } + } + } #endregion public virtual void onExpand(object sender, EventArgs e) diff --git a/src/GraphicObjects/FileDialog.cs b/src/GraphicObjects/FileDialog.cs index 16a60a4f..543b27cc 100644 --- a/src/GraphicObjects/FileDialog.cs +++ b/src/GraphicObjects/FileDialog.cs @@ -29,112 +29,103 @@ using System.Text.RegularExpressions; namespace Crow { - public class FileDialog: IValueChange + public class FileDialog: Window { - #region IValueChange implementation - public event EventHandler<ValueChangeEventArgs> ValueChanged; - public virtual void NotifyValueChanged(string MemberName, object _value) - { - ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); - } - #endregion - - Window window; - DirectoryInfo currentDir; - FileInfo selectedFile; - string searchPattern = "*"; + string searchPattern, curDirectory; #region CTOR - public FileDialog () + public FileDialog () : base() { - currentDir = new DirectoryInfo (Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); - //window = Interface..Load("#Crow.Templates.FileDialog.goml") as Window; - window.DataSource = this; } #endregion - - public string CurrentPath { - get { return currentDir.FullName; } + //[DefaultValue(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))] + [XmlAttributeAttribute][DefaultValue("/home")] + public virtual string CurrentDirectory { + get { return curDirectory; } set { - currentDir = new DirectoryInfo (value); - NotifyValueChanged ("CurrentPath", CurrentPath); + if (curDirectory == value) + return; + curDirectory = value; + NotifyValueChanged ("CurrentDirectory", curDirectory); + } - } - public string SearchPattern { + } + + [XmlAttributeAttribute()][DefaultValue("*")] + public virtual string SearchPattern { get { return searchPattern; } set { - searchPattern = value; - NotifyValueChanged ("Files", Files); - } - } + if (searchPattern == value) + return; + searchPattern = value; + NotifyValueChanged ("SearchPattern", searchPattern); - public DirectoryInfo[] Directories - { - get { - //currentDir.GetDirectories - List<DirectoryInfo> tmp = currentDir.GetDirectories ().Where(fi => !fi.Attributes.HasFlag(FileAttributes.Hidden)).ToList(); - if (currentDir.Parent != null) - tmp.Insert (0, currentDir.Parent); - return tmp.ToArray (); } - } - public FileInfo[] Files - { - get { - string[] exts = searchPattern.Replace("*","").Split ('|'); - //return currentDir.GetFiles (searchPattern).Where(fi => !fi.Attributes.HasFlag(FileAttributes.Hidden)).ToArray(); - return currentDir.GetFiles().Where(f => exts.Any - (x => f.Name.EndsWith (x, StringComparison.InvariantCultureIgnoreCase))).ToArray(); - } - } - - public void Show(){ - //.AddWidget(window); - } - - void OnSelectedItemChanged (object sender, SelectionChangeEventArgs e) - { - currentDir = e.NewValue as DirectoryInfo; - NotifyValueChanged ("CurrentPath", CurrentPath); - NotifyValueChanged ("Directories", Directories); - NotifyValueChanged ("Files", Files); - - } - void onFileListItemChanged (object sender, SelectionChangeEventArgs e) - { - selectedFile = e.NewValue as FileInfo; - } - void onFileSelect(object sender, MouseButtonEventArgs e){ - //OpenTKGameWindow.currentWindow.DeleteWidget(window); - } - } - public class DirContainer: IValueChange - { - #region IValueChange implementation - public event EventHandler<ValueChangeEventArgs> ValueChanged; - public void NotifyValueChanged(string name, object value) - { - ValueChanged.Raise (this, new ValueChangeEventArgs (name, value)); - } - #endregion + } - public DirectoryInfo CurDir; - public DirContainer(DirectoryInfo _dir){ - CurDir = _dir; - } - public string Name { - get { return CurDir.Name; } - } - - void onDirUp(object sender, MouseButtonEventArgs e) - { - - } - public void onMouseDown(object sender, MouseButtonEventArgs e) - { - Debug.WriteLine (sender.ToString ()); - } +// public DirectoryInfo[] Directories +// { +// get { +// //currentDir.GetDirectories +// List<DirectoryInfo> tmp = currentDir.GetDirectories ().Where(fi => !fi.Attributes.HasFlag(FileAttributes.Hidden)).ToList(); +// if (currentDir.Parent != null) +// tmp.Insert (0, currentDir.Parent); +// return tmp.ToArray (); +// } +// } +// public FileInfo[] Files +// { +// get { +// string[] exts = searchPattern.Replace("*","").Split ('|'); +// //return currentDir.GetFiles (searchPattern).Where(fi => !fi.Attributes.HasFlag(FileAttributes.Hidden)).ToArray(); +// return currentDir.GetFiles().Where(f => exts.Any +// (x => f.Name.EndsWith (x, StringComparison.InvariantCultureIgnoreCase))).ToArray(); +// } +// } +// void OnSelectedItemChanged (object sender, SelectionChangeEventArgs e) +// { +// currentDir = e.NewValue as DirectoryInfo; +// NotifyValueChanged ("CurrentPath", CurrentPath); +// NotifyValueChanged ("Directories", Directories); +// NotifyValueChanged ("Files", Files); +// +// } +// void onFileListItemChanged (object sender, SelectionChangeEventArgs e) +// { +// selectedFile = e.NewValue as FileInfo; +// } +// void onFileSelect(object sender, MouseButtonEventArgs e){ +// //OpenTKGameWindow.currentWindow.DeleteWidget(window); +// } } +// public class DirContainer: IValueChange +// { +// #region IValueChange implementation +// public event EventHandler<ValueChangeEventArgs> ValueChanged; +// public void NotifyValueChanged(string name, object value) +// { +// ValueChanged.Raise (this, new ValueChangeEventArgs (name, value)); +// } +// #endregion +// +// public DirectoryInfo CurDir; +// public DirContainer(DirectoryInfo _dir){ +// CurDir = _dir; +// } +// public string Name { +// get { return CurDir.Name; } +// } +// +// void onDirUp(object sender, MouseButtonEventArgs e) +// { +// +// } +// public void onMouseDown(object sender, MouseButtonEventArgs e) +// { +// Debug.WriteLine (sender.ToString ()); +// } +// +// } } diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index e69aaaca..e5313ea2 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -12,22 +12,14 @@ using System.IO; namespace Crow { - public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable, IBindable + public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable { - #region IBindable implementation - List<Binding> bindings = new List<Binding> (); - public List<Binding> Bindings { - get { return bindings; } - } - - #endregion - internal static ulong currentUid = 0; internal ulong uid = 0; Interface currentInterface = null; - public Interface CurrentInterface { + [XmlIgnore]public Interface CurrentInterface { get { if (currentInterface == null) { currentInterface = Interface.CurrentInterface; @@ -47,6 +39,7 @@ namespace Crow public event EventHandler<ValueChangeEventArgs> ValueChanged; public virtual void NotifyValueChanged(string MemberName, object _value) { + //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value); ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); } #endregion @@ -87,7 +80,7 @@ namespace Crow Size minimumSize = "0,0"; bool cacheEnabled = false; bool clipToClientRect = true; - object dataSource; + protected object dataSource; string style; #endregion @@ -132,11 +125,29 @@ namespace Crow /// </summary> [XmlIgnore]public virtual ILayoutable Parent { get { return parent; } - set { parent = value; } + set { + if (parent == value) + return; + DataSourceChangeEventArgs e = new DataSourceChangeEventArgs (parent, value); + parent = value; + + onParentChanged (this, e); + } } [XmlIgnore]public ILayoutable LogicalParent { get { return logicalParent == null ? Parent : logicalParent; } - set { logicalParent = value; } + set { + if (logicalParent == value) + return; + if (logicalParent != null) + (logicalParent as GraphicObject).DataSourceChanged -= onLogicalParentDataSourceChanged; + DataSourceChangeEventArgs dsce = new DataSourceChangeEventArgs (LogicalParent, null); + logicalParent = value; + dsce.NewDataSource = LogicalParent; + if (logicalParent != null) + (logicalParent as GraphicObject).DataSourceChanged += onLogicalParentDataSourceChanged; + onLogicalParentChanged (this, dsce); + } } [XmlIgnore]public virtual Rectangle ClientRectangle { get { @@ -177,6 +188,9 @@ namespace Crow public event EventHandler Enabled; public event EventHandler Disabled; public event EventHandler<LayoutingEventArgs> LayoutChanged; + public event EventHandler<DataSourceChangeEventArgs> DataSourceChanged; + public event EventHandler<DataSourceChangeEventArgs> ParentChanged; + public event EventHandler<DataSourceChangeEventArgs> LogicalParentChanged; #endregion #region public properties @@ -226,6 +240,7 @@ namespace Crow verticalAlignment = value; NotifyValueChanged("VerticalAlignment", verticalAlignment); + RegisterForLayouting (LayoutingType.Y); } } [XmlAttributeAttribute()][DefaultValue(HorizontalAlignment.Center)] @@ -237,6 +252,7 @@ namespace Crow horizontalAlignment = value; NotifyValueChanged("HorizontalAlignment", horizontalAlignment); + RegisterForLayouting (LayoutingType.X); } } [XmlAttributeAttribute()][DefaultValue(0)] @@ -373,6 +389,10 @@ namespace Crow return; hasFocus = value; + if (hasFocus) + onFocused (this, null); + else + onUnfocused (this, null); NotifyValueChanged ("HasFocus", hasFocus); } } @@ -402,6 +422,8 @@ namespace Crow set { if (background == value) return; + if (value == null) + return; background = value; NotifyValueChanged ("Background", background); RegisterForRedraw (); @@ -523,32 +545,45 @@ namespace Crow RegisterForLayouting (LayoutingType.Sizing); } } + /// <summary> + /// Seek first logical tree upward if logicalParent is set, or seek graphic tree for + /// a not null dataSource that will be active for all descendants having dataSource=null + /// </summary> [XmlAttributeAttribute][DefaultValue(null)] public virtual object DataSource { set { - if (dataSource == value) + if (DataSource == value) return; - #if DEBUG_BINDING - Debug.WriteLine("******************************"); - Debug.WriteLine("New DataSource for => " + this.ToString()); - Debug.WriteLine("\t- " + DataSource); - Debug.WriteLine("\t+ " + value); - #endif - - this.ClearBinding (); + DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (DataSource, null); dataSource = value; + dse.NewDataSource = DataSource; - this.ResolveBindings(); + OnDataSourceChanged (this, dse); - NotifyValueChanged ("DataSource", dataSource); + NotifyValueChanged ("DataSource", DataSource); } get { - return dataSource == null ? LogicalParent == null ? null : - LogicalParent is GraphicObject ? - (LogicalParent as GraphicObject).DataSource : null : dataSource; + return dataSource == null ? + LogicalParent == null ? null : + LogicalParent is GraphicObject ? (LogicalParent as GraphicObject).DataSource : null : + dataSource; } } + protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){ + if (localDataSourceIsNull) + OnDataSourceChanged (this, e); + } + internal bool localDataSourceIsNull { get { return dataSource == null; } } + internal bool localLogicalParentIsNull { get { return logicalParent == null; } } + + public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){ + DataSourceChanged.Raise (this, e); + #if DEBUG_BINDING + Debug.WriteLine("New DataSource for => {0} \n\t{1}=>{2}", this.ToString(),e.OldDataSource,e.NewDataSource); + #endif + } + [XmlAttributeAttribute] public virtual string Style { get { return style; } @@ -630,10 +665,10 @@ namespace Crow dm = new DynamicMethod("dyn_loadDefValues", MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot, CallingConventions.Standard, - typeof(void),new Type[] {typeof(object)},thisType,true); + typeof(void),new Type[] {CompilerServices.TObject},thisType,true); il = dm.GetILGenerator(256); - il.DeclareLocal(typeof(GraphicObject)); + il.DeclareLocal(CompilerServices.TObject); il.Emit(OpCodes.Nop); //set local GraphicObject to root object passed as 1st argument il.Emit (OpCodes.Ldarg_0); @@ -643,7 +678,26 @@ namespace Crow string expression; if (!getDefaultEvent(ei, styling, out expression)) continue; - CompilerServices.emitBindingCreation (il, ei.Name, expression); + //TODO:dynEventHandler could be cached somewhere, maybe a style instanciato class holding the styling delegate and bound to it. + foreach (string exp in CompilerServices.splitOnSemiColumnOutsideAccolades(expression)) { + string trimed = exp.Trim(); + if (trimed.StartsWith ("{", StringComparison.OrdinalIgnoreCase)){ + il.Emit (OpCodes.Ldloc_0);//load this as 1st arg of event Add + + //push eventInfo as 1st arg of compile + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Call, CompilerServices.miGetType); + il.Emit (OpCodes.Ldstr, ei.Name);//push event name + il.Emit (OpCodes.Call, CompilerServices.miGetEvent); + //push expression as 2nd arg of compile + il.Emit (OpCodes.Ldstr, trimed.Substring (1, trimed.Length - 2)); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Callvirt, CompilerServices.miCompileDynEventHandler); + il.Emit (OpCodes.Castclass, ei.EventHandlerType); + il.Emit (OpCodes.Callvirt, ei.AddMethod); + }else + Debug.WriteLine("error in styling, event not handled : " + trimed); + } } foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { @@ -1030,9 +1084,6 @@ namespace Crow /// of the widget </summary> public virtual void Paint (ref Context ctx) { - if (!Visible) - return; - //TODO:this test should not be necessary if (Slot.Height < 0 || Slot.Width < 0) return; @@ -1120,6 +1171,12 @@ namespace Crow MouseMove.Raise (sender, e); } public virtual void onMouseDown(object sender, MouseButtonEventArgs e){ + if (CurrentInterface.eligibleForDoubleClick == this && CurrentInterface.clickTimer.ElapsedMilliseconds < Interface.DoubleClick) + onMouseDoubleClick (this, e); + else + currentInterface.clickTimer.Restart(); + CurrentInterface.eligibleForDoubleClick = null; + if (CurrentInterface.activeWidget == null) CurrentInterface.activeWidget = this; if (this.Focusable && !Interface.FocusOnHover) { @@ -1144,19 +1201,13 @@ namespace Crow MouseUp.Raise (this, e); - if (MouseIsIn (e.Position) && IsActive) + if (MouseIsIn (e.Position) && IsActive) { + if (CurrentInterface.clickTimer.ElapsedMilliseconds < Interface.DoubleClick) + CurrentInterface.eligibleForDoubleClick = this; onMouseClick (this, e); + } } public virtual void onMouseClick(object sender, MouseButtonEventArgs e){ - - if (Interface.clickTimer.ElapsedMilliseconds > 0 && - Interface.clickTimer.ElapsedMilliseconds < Interface.DoubleClick) { - Interface.clickTimer.Reset (); - onMouseDoubleClick (this, e); - return; - } else - Interface.clickTimer.Restart (); - GraphicObject p = Parent as GraphicObject; if (p != null) p.onMouseClick(sender,e); @@ -1191,20 +1242,17 @@ namespace Crow } #endregion - public virtual void onFocused(object sender, EventArgs e){ + protected virtual void onFocused(object sender, EventArgs e){ #if DEBUG_FOCUS Debug.WriteLine("Focused => " + this.ToString()); #endif Focused.Raise (this, e); - this.HasFocus = true; } - public virtual void onUnfocused(object sender, EventArgs e){ + protected virtual void onUnfocused(object sender, EventArgs e){ #if DEBUG_FOCUS Debug.WriteLine("UnFocused => " + this.ToString()); #endif - Unfocused.Raise (this, e); - this.HasFocus = false; } public virtual void onEnable(object sender, EventArgs e){ Enabled.Raise (this, e); @@ -1212,147 +1260,73 @@ namespace Crow public virtual void onDisable(object sender, EventArgs e){ Disabled.Raise (this, e); } - - #region Binding - public void BindMember(string _member, string _expression){ - Bindings.Add(new Binding (this, _member, _expression)); + protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) { + ParentChanged.Raise (this, e); + if (logicalParent == null) + LogicalParentChanged.Raise (this, e); } - public virtual void ResolveBindings() - { - if (Bindings.Count == 0) - return; - #if DEBUG_BINDING - Debug.WriteLine ("Resolve Bindings => " + this.ToString ()); - #endif - - CompilerServices.ResolveBindings (Bindings); + protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) { + LogicalParentChanged.Raise (this, e); } - - /// <summary> - /// Remove dynamic delegates by ids from dataSource - /// and delete ref of this in Shared interface refs - /// </summary> - public virtual void ClearBinding(){ - //dont clear binding if dataSource is not null, - foreach (Binding b in Bindings) { - try { - if (!b.Resolved) - continue; - //cancel compiled events - if (b.Target == null){ - continue; - #if DEBUG_BINDING - Debug.WriteLine("Clear binding canceled for => " + b.ToString()); - #endif - } - if (b.Target.Instance != DataSource){ - #if DEBUG_BINDING - Debug.WriteLine("Clear binding canceled for => " + b.ToString()); - #endif - continue; - } - #if DEBUG_BINDING - Debug.WriteLine("ClearBinding => " + b.ToString()); - #endif - if (string.IsNullOrEmpty (b.DynMethodId)) { - b.Resolved = false; - if (b.Source.Member.MemberType == MemberTypes.Event) - removeEventHandler (b); - //TODO:check if full reset is necessary - continue; - } - MemberReference mr = null; - if (b.Target == null) - mr = b.Source; - else - mr = b.Target; - Type dataSourceType = mr.Instance.GetType(); - EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged"); - FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged"); - MulticastDelegate multicastDelegate = evtFi.GetValue (mr.Instance) as MulticastDelegate; - if (multicastDelegate != null) { - foreach (Delegate d in multicastDelegate.GetInvocationList()) { - if (d.Method.Name == b.DynMethodId) - evtInfo.RemoveEventHandler (mr.Instance, d); - } - } - b.Reset (); - } catch (Exception ex) { - Debug.WriteLine("\t Error: " + ex.ToString()); - } - } - } - void removeEventHandler(Binding b){ - FieldInfo fiEvt = CompilerServices.GetEventHandlerField (b.Source.Instance.GetType(), b.Source.Member.Name); - MulticastDelegate multiDel = fiEvt.GetValue (b.Source.Instance) as MulticastDelegate; - if (multiDel != null) { - foreach (Delegate d in multiDel.GetInvocationList()) { - if (d.Method.Name == b.Target.Member.Name) - b.Source.Event.RemoveEventHandler (b.Source.Instance, d); - } - } - } - #endregion - #region IXmlSerializable public virtual System.Xml.Schema.XmlSchema GetSchema () { return null; } - void affectMember(string name, string value){ - Type thisType = this.GetType (); - - if (string.IsNullOrEmpty (value)) - return; - - MemberInfo mi = thisType.GetMember (name).FirstOrDefault(); - if (mi == null) { - Debug.WriteLine ("XML: Unknown attribute in " + thisType.ToString() + " : " + name); - return; - } - if (mi.MemberType == MemberTypes.Event) { - this.Bindings.Add (new Binding (new MemberReference(this, mi), value)); - return; - } - if (mi.MemberType == MemberTypes.Property) { - PropertyInfo pi = mi as PropertyInfo; - - if (pi.GetSetMethod () == null) { - Debug.WriteLine ("XML: Read only property in " + thisType.ToString() + " : " + name); - return; - } - - XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); - if (xaa != null) { - if (!string.IsNullOrEmpty (xaa.AttributeName)) - name = xaa.AttributeName; - } - if (value.StartsWith("{",StringComparison.Ordinal)) { - //binding - if (!value.EndsWith("}", StringComparison.Ordinal)) - throw new Exception (string.Format("XML:Malformed binding: {0}", value)); - - this.Bindings.Add (new Binding (new MemberReference(this, pi), value.Substring (1, value.Length - 2))); - return; - } - if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) - return; - if (xaa == null)//not define as xmlAttribute - return; - - if (pi.PropertyType == typeof(string)) { - pi.SetValue (this, value, null); - return; - } - - if (pi.PropertyType.IsEnum) { - pi.SetValue (this, Enum.Parse (pi.PropertyType, value), null); - } else { - MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); - pi.SetValue (this, me.Invoke (null, new string[] { value }), null); - } - } - } +// void affectMember(string name, string value){ +// Type thisType = this.GetType (); +// +// if (string.IsNullOrEmpty (value)) +// return; +// +// MemberInfo mi = thisType.GetMember (name).FirstOrDefault(); +// if (mi == null) { +// Debug.WriteLine ("XML: Unknown attribute in " + thisType.ToString() + " : " + name); +// return; +// } +// if (mi.MemberType == MemberTypes.Event) { +// this.Bindings.Add (new Binding (new MemberReference(this, mi), value)); +// return; +// } +// if (mi.MemberType == MemberTypes.Property) { +// PropertyInfo pi = mi as PropertyInfo; +// +// if (pi.GetSetMethod () == null) { +// Debug.WriteLine ("XML: Read only property in " + thisType.ToString() + " : " + name); +// return; +// } +// +// XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); +// if (xaa != null) { +// if (!string.IsNullOrEmpty (xaa.AttributeName)) +// name = xaa.AttributeName; +// } +// if (value.StartsWith("{",StringComparison.Ordinal)) { +// //binding +// if (!value.EndsWith("}", StringComparison.Ordinal)) +// throw new Exception (string.Format("XML:Malformed binding: {0}", value)); +// +// this.Bindings.Add (new Binding (new MemberReference(this, pi), value.Substring (1, value.Length - 2))); +// return; +// } +// if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) +// return; +// if (xaa == null)//not define as xmlAttribute +// return; +// +// if (pi.PropertyType == typeof(string)) { +// pi.SetValue (this, value, null); +// return; +// } +// +// if (pi.PropertyType.IsEnum) { +// pi.SetValue (this, Enum.Parse (pi.PropertyType, value), null); +// } else { +// MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); +// pi.SetValue (this, me.Invoke (null, new string[] { value }), null); +// } +// } +// } public virtual void ReadXml (System.Xml.XmlReader reader) { if (reader.HasAttributes) { @@ -1365,7 +1339,7 @@ namespace Crow if (reader.Name == "Style") continue; - affectMember (reader.Name, reader.Value); + //affectMember (reader.Name, reader.Value); } reader.MoveToElement (); }else @@ -1483,12 +1457,6 @@ namespace Crow /// <summary> /// full GraphicTree clone with binding definition /// </summary> - public virtual GraphicObject DeepClone(){ - GraphicObject tmp = Clone () as GraphicObject; - foreach (Binding b in this.bindings) - tmp.Bindings.Add (new Binding (new MemberReference (tmp, b.Source.Member), b.Expression)); - return tmp; - } public override string ToString () { diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index efe02d95..a285e282 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -40,7 +40,6 @@ namespace Crow lock (children) Children.Add(g); g.Parent = this; - g.ResolveBindings (); g.RegisteredLayoutings = LayoutingType.None; g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); g.LayoutChanged += OnChildLayoutChanges; @@ -48,7 +47,6 @@ namespace Crow public virtual void RemoveChild(GraphicObject child) { child.LayoutChanged -= OnChildLayoutChanges; - child.ClearBinding (); //child.Parent = null; lock (children) Children.Remove(child); @@ -65,7 +63,6 @@ namespace Crow while(Children.Count > 0){ GraphicObject g = Children[Children.Count-1]; g.LayoutChanged -= OnChildLayoutChanges; - g.ClearBinding (); g.Parent = null; Children.RemoveAt(Children.Count-1); } @@ -94,11 +91,12 @@ namespace Crow } #region GraphicObject overrides - public override void ResolveBindings () + public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) { - base.ResolveBindings (); - foreach (GraphicObject w in Children) - w.ResolveBindings (); + base.OnDataSourceChanged (this, e); + foreach (GraphicObject g in children) + if (g.localDataSourceIsNull & g.localLogicalParentIsNull) + g.OnDataSourceChanged (sender, e); } public override GraphicObject FindByName (string nameToFind) { @@ -365,17 +363,5 @@ namespace Crow #endregion - public override void ClearBinding(){ - foreach (GraphicObject c in Children) - c.ClearBinding (); - base.ClearBinding (); - } - public override GraphicObject DeepClone () - { - Group tmp = base.DeepClone () as Group; - foreach (GraphicObject c in Children) - tmp.AddChild (c.DeepClone ()); - return tmp; - } } } diff --git a/src/GraphicObjects/HueSelector.cs b/src/GraphicObjects/HueSelector.cs new file mode 100644 index 00000000..ec0a6f2c --- /dev/null +++ b/src/GraphicObjects/HueSelector.cs @@ -0,0 +1,143 @@ +// +// HueSelector.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; +using Cairo; + +namespace Crow +{ + public class HueSelector : ColorSelector + { + public HueSelector () : base() + { + } + + Orientation _orientation; + double hue; + + [XmlAttributeAttribute][DefaultValue(Orientation.Horizontal)] + public virtual Orientation Orientation + { + get { return _orientation; } + set { + if (_orientation == value) + return; + _orientation = value; + NotifyValueChanged ("Orientation", _orientation); + RegisterForGraphicUpdate (); + } + } + [XmlAttributeAttribute()] + public virtual double Hue { + get { return hue; } + set { + if (hue == value) + return; + hue = value; + + notifyHueChanged (); + updateMousePosFromHue (); + } + } + protected override void onDraw (Cairo.Context gr) + { + base.onDraw (gr); + + Rectangle r = ClientRectangle; + + Gradient.Type gt = Gradient.Type.Horizontal; + if (Orientation == Orientation.Vertical) + gt = Gradient.Type.Vertical; + + Crow.Gradient grad = new Gradient (gt); + + grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 0, 0, 1))); + grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1))); + grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1))); + grad.Stops.Add (new Gradient.ColorStop (0.5, new Color (0, 1, 1, 1))); + grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1))); + grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1))); + grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 0, 0, 1))); + + grad.SetAsSource (gr, r); + CairoHelpers.CairoRectangle (gr, r, CornerRadius); + gr.Fill(); + } + + public override void Paint (ref Context ctx) + { + base.Paint (ref ctx); + + Rectangle rb = Slot + Parent.ClientRectangle.Position; + ctx.Save (); + + ctx.Translate (rb.X, rb.Y); + + ctx.SetSourceColor (Color.White); + Rectangle r = ClientRectangle; + if (Orientation == Orientation.Horizontal) { + r.Width = 5; + r.X = mousePos.X; + } else { + r.Height = 5; + r.Y = mousePos.Y; + } + + CairoHelpers.CairoRectangle (ctx, r, 2); + ctx.SetSourceColor (Color.White); + ctx.LineWidth = 2.0; + ctx.Stroke(); + ctx.Restore (); + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + + if (Orientation == Orientation.Horizontal) { + if (layoutType == LayoutingType.Width) + updateMousePosFromHue (); + } else if (layoutType == LayoutingType.Height) + updateMousePosFromHue (); + } + protected override void updateMouseLocalPos (Point mPos) + { + base.updateMouseLocalPos (mPos); + if (Orientation == Orientation.Horizontal) + hue = (double)mousePos.X / (double)ClientRectangle.Width; + else + hue = (double)mousePos.Y / (double)ClientRectangle.Height; + notifyHueChanged (); + } + void updateMousePosFromHue(){ + if (Orientation == Orientation.Horizontal) + mousePos.X = (int)Math.Floor(hue * (double)ClientRectangle.Width); + else + mousePos.Y = (int)Math.Floor(hue * (double)ClientRectangle.Height); + CurrentInterface.EnqueueForRepaint (this); + } + void notifyHueChanged(){ + NotifyValueChanged ("Hue", hue); + NotifyValueChanged ("HueColor", new SolidColor (Color.FromHSV (hue))); + } + } +} + diff --git a/src/GraphicObjects/Label.cs b/src/GraphicObjects/Label.cs index 666f00a2..2f35c223 100644 --- a/src/GraphicObjects/Label.cs +++ b/src/GraphicObjects/Label.cs @@ -670,7 +670,7 @@ namespace Crow base.onMouseLeave (sender, e); CurrentInterface.MouseCursor = XCursor.Default; } - public override void onFocused (object sender, EventArgs e) + protected override void onFocused (object sender, EventArgs e) { base.onFocused (sender, e); @@ -680,7 +680,7 @@ namespace Crow SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1); RegisterForRedraw (); } - public override void onUnfocused (object sender, EventArgs e) + protected override void onUnfocused (object sender, EventArgs e) { base.onUnfocused (sender, e); diff --git a/src/GraphicObjects/Menu.cs b/src/GraphicObjects/Menu.cs index 765925e9..5726afdf 100644 --- a/src/GraphicObjects/Menu.cs +++ b/src/GraphicObjects/Menu.cs @@ -65,7 +65,7 @@ namespace Crow public override void onMouseLeave (object sender, MouseMoveEventArgs e) { base.onMouseLeave (sender, e); - IsOpened = false; + //IsOpened = false; } } } diff --git a/src/GraphicObjects/MenuItem.cs b/src/GraphicObjects/MenuItem.cs index 78162fbb..9fc0b226 100644 --- a/src/GraphicObjects/MenuItem.cs +++ b/src/GraphicObjects/MenuItem.cs @@ -50,8 +50,8 @@ namespace Crow if (isOpened) { onOpen (this, null); - if (MenuRoot != null) - MenuRoot.IsOpened = true; +// if (MenuRoot != null) +// MenuRoot.IsOpened = true; }else onClose (this, null); } @@ -102,7 +102,7 @@ namespace Crow Execute.Raise (this, null); } protected virtual void onOpen (object sender, EventArgs e){ - MenuRoot.IsOpened = true; + //MenuRoot.IsOpened = true; Open.Raise (this, null); } protected virtual void onClose (object sender, EventArgs e){ diff --git a/src/GraphicObjects/Popper.cs b/src/GraphicObjects/Popper.cs index 669b8d7f..1b8c0d95 100644 --- a/src/GraphicObjects/Popper.cs +++ b/src/GraphicObjects/Popper.cs @@ -175,21 +175,6 @@ namespace Crow _content.MinimumSize = new Size (this.Slot.Width, _content.MinimumSize.Height); } - public override void ClearBinding () - { - //ensure popped window is cleared - if (Content != null) { - if (Content.Parent != null) - CurrentInterface.DeleteWidget (Content); - } - base.ClearBinding (); - } - public override void ResolveBindings () - { - base.ResolveBindings (); - if (Content != null) - Content.ResolveBindings (); - } public override void onMouseClick (object sender, MouseButtonEventArgs e) { @@ -201,13 +186,11 @@ namespace Crow { if (!_isPopped || _content == null) { base.onMouseLeave (sender, e); - System.Diagnostics.Debug.WriteLine ("NotPopped***popper mouse leave:"+ this.ToString()); return; } if (!_content.MouseIsIn (e.Position)) { base.onMouseLeave (sender, e); - System.Diagnostics.Debug.WriteLine ("***popper mouse leave:"+ this.ToString()); IsPopped = false; return; } diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 2a5deeaa..9c65e935 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -47,7 +47,6 @@ namespace Crow { if (child != null) { - child.ClearBinding (); contentSize = new Size (0, 0); child.LayoutChanged -= OnChildLayoutChanges; child.Parent = null; @@ -66,16 +65,7 @@ namespace Crow } #region GraphicObject Overrides - public override void ResolveBindings () - { - base.ResolveBindings (); - if (child != null) - child.ResolveBindings (); - } - protected void ResolveBindingsWithNoRecurse () - { - base.ResolveBindings (); - } + public override GraphicObject FindByName (string nameToFind) { if (Name == nameToFind) @@ -88,6 +78,13 @@ namespace Crow return child == goToFind ? true : child == null ? false : child.Contains(goToFind); } + public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) + { + base.OnDataSourceChanged (this, e); + if (child != null) + if (child.localDataSourceIsNull & child.localLogicalParentIsNull) + child.OnDataSourceChanged (sender, e); + } public override bool UpdateLayout (LayoutingType layoutType) { if (child != null) { @@ -161,8 +158,10 @@ namespace Crow gr.Clip (); } - if (child != null) - child.Paint (ref gr); + if (child != null) { + if (child.Visible) + child.Paint (ref gr); + } gr.Restore (); } protected override void UpdateCache (Context ctx) @@ -197,19 +196,6 @@ namespace Crow } #endregion - public override void ClearBinding () - { - if (child != null) - child.ClearBinding (); - base.ClearBinding (); - } - public override GraphicObject DeepClone () - { - PrivateContainer tmp = base.DeepClone () as PrivateContainer; - if (child != null) - tmp.SetChild (child.DeepClone ()); - return tmp; - } } } diff --git a/src/GraphicObjects/SaturationValueSelector.cs b/src/GraphicObjects/SaturationValueSelector.cs new file mode 100644 index 00000000..b71fa7ef --- /dev/null +++ b/src/GraphicObjects/SaturationValueSelector.cs @@ -0,0 +1,129 @@ +// +// SaturationValueSelector.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using Cairo; +using System.Xml.Serialization; + +namespace Crow +{ + public class SaturationValueSelector : ColorSelector + { + public SaturationValueSelector () : base() + { + } + + double v, s; + + [XmlAttributeAttribute()] + public virtual double V { + get { return v; } + set { + if (v == value) + return; + v = value; + NotifyValueChanged ("V", v); + mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height); + + CurrentInterface.EnqueueForRepaint (this); + } + } + [XmlAttributeAttribute()] + public virtual double S { + get { return s; } + set { + if (s == value) + return; + s = value; + NotifyValueChanged ("S", s); + mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width); + CurrentInterface.EnqueueForRepaint (this); + } + } + protected override void onDraw (Cairo.Context gr) + { + base.onDraw (gr); + + Rectangle r = ClientRectangle; + Rectangle rGrad = r; + rGrad.Inflate (-1); + + if (Foreground != null) {//TODO:test if null should be removed + Foreground.SetAsSource (gr, r); + CairoHelpers.CairoRectangle (gr, r, CornerRadius); + gr.Fill (); + } + + Crow.Gradient grad = new Gradient (Gradient.Type.Horizontal); + grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 1, 1, 1))); + grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 1, 1, 0))); + grad.SetAsSource (gr, rGrad); + CairoHelpers.CairoRectangle (gr, r, CornerRadius); + gr.Fill(); + grad = new Gradient (Gradient.Type.Vertical); + grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, 0, 0, 0))); + grad.Stops.Add (new Gradient.ColorStop (1, new Color (0, 0, 0, 1))); + grad.SetAsSource (gr, rGrad); + CairoHelpers.CairoRectangle (gr, r, CornerRadius); + gr.Fill(); + } + + public override void Paint (ref Context ctx) + { + base.Paint (ref ctx); + + Rectangle rb = Slot + Parent.ClientRectangle.Position; + ctx.Save (); + + ctx.Translate (rb.X, rb.Y); + + ctx.SetSourceColor (Color.White); + ctx.Arc (mousePos.X, mousePos.Y, 3.0, 0, Math.PI * 2.0); + ctx.LineWidth = 1.0; + ctx.Stroke (); + + ctx.Restore (); + } + + protected override void updateMouseLocalPos (Point mPos) + { + base.updateMouseLocalPos (mPos); + + Rectangle cb = ClientRectangle; + s = (double)mousePos.X / (double)cb.Width; + v = 1.0 - (double)mousePos.Y / (double)cb.Height; + NotifyValueChanged ("S", s); + NotifyValueChanged ("V", v); + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + switch (layoutType) { + case LayoutingType.Width: + mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width); + break; + case LayoutingType.Height: + mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height); + break; + } + } + } +} + diff --git a/src/GraphicObjects/TabItem.cs b/src/GraphicObjects/TabItem.cs index e14a7815..cd57b221 100644 --- a/src/GraphicObjects/TabItem.cs +++ b/src/GraphicObjects/TabItem.cs @@ -46,15 +46,15 @@ namespace Crow return _contentContainer == null ? null : _contentContainer.Child; } set { + if (Content != null) { + Content.LogicalParent = null; + _contentContainer.SetChild (null); + } _contentContainer.SetChild(value); + if (value != null) + value.LogicalParent = this; } } - public override void ResolveBindings () - { - base.ResolveBindings (); - if (_contentContainer != null) - _contentContainer.ResolveBindings (); - } protected override void loadTemplate(GraphicObject template = null) { base.loadTemplate (template); diff --git a/src/GraphicObjects/TemplatedContainer.cs b/src/GraphicObjects/TemplatedContainer.cs index 7a4649a4..44c2ad08 100644 --- a/src/GraphicObjects/TemplatedContainer.cs +++ b/src/GraphicObjects/TemplatedContainer.cs @@ -34,19 +34,6 @@ namespace Crow [XmlIgnore]public abstract GraphicObject Content{ get; set;} #region GraphicObject overrides - public override void ClearBinding () - { - if (Content != null) - Content.ClearBinding (); - - base.ClearBinding (); - } -// public override void ResolveBindings () -// { -// base.ResolveBindings (); -// if (Content != null) -// Content.ResolveBindings (); -// } public override GraphicObject FindByName (string nameToFind) { if (Name == nameToFind) diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index 7f2e1b87..ba49f44f 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -94,8 +94,6 @@ namespace Crow this.SetChild (CurrentInterface.Load (Interface.DefaultTemplates[this.GetType ().FullName])); }else this.SetChild (template); - - this.ResolveBindings (); } //TODO:IXmlSerializable is not used anymore diff --git a/src/GraphicObjects/TemplatedGroup.cs b/src/GraphicObjects/TemplatedGroup.cs index 500e5ea6..3c1fed9e 100644 --- a/src/GraphicObjects/TemplatedGroup.cs +++ b/src/GraphicObjects/TemplatedGroup.cs @@ -36,13 +36,12 @@ namespace Crow #endregion protected Group items; - string _itemTemplate; + string _itemTemplate, _dataTest; #region events public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged; #endregion - Group _list; IList data; int _selectedIndex; Color selBackground, selForeground; @@ -56,6 +55,9 @@ namespace Crow //but then i should test if null in msil gen public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, Crow.ItemTemplate>(); + /// <summary> + /// Default item template + /// </summary> [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")] public string ItemTemplate { get { return _itemTemplate; } @@ -81,6 +83,24 @@ namespace Crow else NotifyValueChanged ("HasChildren", true); } + /// <summary> + /// Use to define condition on Data item for selecting among ItemTemplates. + /// Default value is 'TypeOf' for selecting Template depending on Type of Data. + /// Other possible values are properties of Data + /// </summary> + /// <value>The data property test.</value> + [XmlAttributeAttribute][DefaultValue("TypeOf")] + public string DataTest { + get { return _dataTest; } + set { + if (value == _dataTest) + return; + + _dataTest = value; + + NotifyValueChanged("DataTest", _dataTest); + } + } #endregion public virtual List<GraphicObject> Items{ get { return items.Children; }} @@ -100,7 +120,9 @@ namespace Crow [XmlIgnore]public virtual object SelectedItem{ get { return data == null ? null : _selectedIndex < 0 ? null : data[_selectedIndex]; } } - + [XmlIgnore]public bool HasItems { + get { return Items.Count > 0; } + } [XmlAttributeAttribute]public IList Data { get { return data; } set { @@ -113,7 +135,7 @@ namespace Crow NotifyValueChanged ("Data", data); - lock (CurrentInterface.UpdateMutex) + //lock (CurrentInterface.UpdateMutex) ClearItems (); if (data == null) @@ -127,6 +149,7 @@ namespace Crow NotifyValueChanged ("SelectedIndex", _selectedIndex); NotifyValueChanged ("SelectedItem", SelectedItem); SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem)); + NotifyValueChanged ("HasItems", HasItems); } } @@ -160,10 +183,12 @@ namespace Crow public virtual void AddItem(GraphicObject g){ items.AddChild (g); + g.LogicalParent = this; NotifyValueChanged ("HasChildren", true); } public virtual void RemoveItem(GraphicObject g) { + g.LogicalParent = null; items.RemoveChild (g); if (items.Children.Count == 0) NotifyValueChanged ("HasChildren", false); @@ -281,6 +306,7 @@ namespace Crow if (cancelLoading) return; loadPage (i); + Thread.Sleep (1); } } void cancelLoadingThread(){ @@ -299,20 +325,25 @@ namespace Crow loadingTime.Start (); #endif - Group page = items.Clone () as Group; + Group page; + if (typeof(Wrapper).IsAssignableFrom (items.GetType ())){ + page = items; + itemPerPage = int.MaxValue; + }else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) { + GenericStack gs = new GenericStack (); + gs.CurrentInterface = items.CurrentInterface; + gs.initialize (); + gs.Orientation = (items as GenericStack).Orientation; + gs.Width = items.Width; + gs.Height = items.Height; + gs.VerticalAlignment = items.VerticalAlignment; + gs.HorizontalAlignment = items.HorizontalAlignment; + page = gs; - page.Name = "page" + pageNum; + }else + page = Activator.CreateInstance (items.GetType ()) as Group; -// //reset size to fit in the dir of the stacking -// //because items total size is forced to approx size -// if (_gsList.Orientation == Orientation.Horizontal) { -// page.Width = Measure.Fit; - page.BindMember ("Height", "../HeightPolicy"); - page.BindMember ("Width", "../WidthPolicy"); -// } else { -// page.Height = Measure.Fit; -// page.BindMember ("Width", "../WidthPolicy"); -// } + page.Name = "page" + pageNum; for (int i = (pageNum - 1) * itemPerPage; i < pageNum * itemPerPage; i++) { if (i >= data.Count) @@ -321,10 +352,10 @@ namespace Crow return; loadItem (i, page); - - //g.LogicalParent = this; } + if (page == items) + return; lock (CurrentInterface.LayoutMutex) items.AddChild (page); @@ -335,27 +366,41 @@ namespace Crow loadingTime.ElapsedMilliseconds, this.ToString()); #endif } + string getItempKey(Type dataType, object o){ + try { + return dataType.GetProperty (_dataTest).GetGetMethod ().Invoke (o, null).ToString(); + } catch (Exception ex) { + return dataType.FullName; + } + } protected void loadItem(int i, Group page){ GraphicObject g = null; ItemTemplate iTemp = null; Type dataType = data [i].GetType (); + string itempKey = dataType.FullName; - if (ItemTemplates.ContainsKey (dataType.FullName)) - iTemp = ItemTemplates [dataType.FullName]; + if (_dataTest != "TypeOf") + itempKey = getItempKey (dataType, data [i]); + + if (ItemTemplates.ContainsKey (itempKey)) + iTemp = ItemTemplates [itempKey]; else iTemp = ItemTemplates ["default"]; lock (CurrentInterface.LayoutMutex) { g = iTemp.CreateInstance(CurrentInterface); page.AddChild (g); - g.DataSource = data [i]; + registerItemClick (g); } - registerItemClick (g); - if (iTemp.Expand != null && g is Expandable) { (g as Expandable).Expand += iTemp.Expand; - } + (g as Expandable).GetIsExpandable = iTemp.HasSubItems; + } + //g.LogicalParent = this; + + + g.DataSource = data [i]; } protected virtual void registerItemClick(GraphicObject g){ g.MouseClick += itemClick; diff --git a/src/GraphicObjects/Window.cs b/src/GraphicObjects/Window.cs index 9ef9e642..86f05d86 100644 --- a/src/GraphicObjects/Window.cs +++ b/src/GraphicObjects/Window.cs @@ -134,12 +134,6 @@ namespace Crow #endregion #region GraphicObject Overrides - public override void ResolveBindings () - { - base.ResolveBindings (); - if (Content != null) - Content.ResolveBindings (); - } public override void onMouseMove (object sender, MouseMoveEventArgs e) { base.onMouseMove (sender, e); |