[hyena/canvas] [Hyena.Gui.Canvas] Revamp properties and animation



commit 5003dd5f1140613ee8e0a7361cc5ad52cf435856
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Fri Oct 22 16:31:31 2010 -0500

    [Hyena.Gui.Canvas] Revamp properties and animation
    
    Instead of having certain properties automatically trigger invalidates,
    have animations and other setters call the Invalidate* functions
    explicitly.
    
    Also add back prelight support, with a PrelightRenderer delegate
    settable for any CanvasItem.

 Hyena.Gui/Hyena.Gui.Canvas/AnimationManager.cs |  260 +++---------------
 Hyena.Gui/Hyena.Gui.Canvas/CanvasItem.cs       |  350 +++++++++---------------
 Hyena.Gui/Hyena.Gui.Canvas/Prelight.cs         |   55 ++++
 Hyena.Gui/Hyena.Gui.Canvas/Rect.cs             |    4 +
 Hyena.Gui/Hyena.Gui.Canvas/TextBlock.cs        |   88 +-----
 Hyena.Gui/Makefile.am                          |    1 +
 6 files changed, 237 insertions(+), 521 deletions(-)
---
diff --git a/Hyena.Gui/Hyena.Gui.Canvas/AnimationManager.cs b/Hyena.Gui/Hyena.Gui.Canvas/AnimationManager.cs
index 1646adf..123fd4d 100644
--- a/Hyena.Gui/Hyena.Gui.Canvas/AnimationManager.cs
+++ b/Hyena.Gui/Hyena.Gui.Canvas/AnimationManager.cs
@@ -29,253 +29,69 @@ using Hyena.Gui.Theatrics;
 
 namespace Hyena.Gui.Canvas
 {
-    public abstract class Animation
+    public class Animation
     {
-        private Stage<Animation> stage;
-        internal protected Stage<Animation> Stage {
-            get { return stage; }
-            set { stage = value; }
-        }
+        //private int iterations;
 
-        private Actor<Animation> actor;
-        internal protected Actor<Animation> Actor {
-            get { return actor; }
-            set { actor = value; }
-        }
+        internal protected Stage<Animation> Stage { get; set; }
+        internal protected Actor<Animation> Actor { get; set; }
 
-        private uint duration = 1000;
-        public uint Duration {
-            get { return duration; }
-            set {
-                duration = value;
-                if (Actor != null) {
-                    Actor.Reset (duration);
-                }
-            }
-        }
+        public Easing Easing { get; set; }
+        public CanvasItem Item { get; set; }
+        public int Repeat { get; set; }
+        public uint Duration { get; set; }
+        public Action<Animation> Update { get; set; }
+        public Action<Animation> Finished { get; set; }
 
-        private CanvasItem item;
-        public CanvasItem Item {
-            get { return item; }
-            set { item = value; }
-        }
+        public double Percent { get; private set; }
 
-        private string property;
-        public string Property {
-            get { return property; }
-            set { property = value; }
-        }
-
-        private bool is_expired;
-        public bool IsExpired {
-            get { return is_expired; }
-            set {
-                is_expired = value;
-                iterations = 0;
-            }
+        public Animation ()
+        {
+            Duration = 1000;
+            Easing = Easing.Linear;
+            AnimationManager.Instance.Animate (this);
         }
 
-        private int iterations;
-
-        private int repeat_times;
-        public int RepeatTimes {
-            get { return repeat_times; }
-            set { repeat_times = value; }
+        public Animation (double from, double to, Action<double> set) : this ()
+        {
+            Update = animation => set (from + animation.Percent * (to - from));
         }
 
-        public virtual void Start ()
+        public void Start ()
         {
             if (Stage.Contains (this)) {
-                Actor.Reset (Duration);
+                Actor.Reset ();
                 return;
             }
 
             Actor = Stage.Add (this, Duration);
-            IsExpired = false;
+            Percent = 0;
+            //iterations = 0;
             Actor.CanExpire = false;
         }
 
-        public virtual bool Step (Actor<Animation> actor)
+        internal bool Step (Actor<Animation> actor)
         {
-            if (RepeatTimes > 0 && actor.Percent == 1) {
-                if (++iterations >= RepeatTimes) {
-                    IsExpired = true;
+            bool is_expired = actor.Percent == 1;
+            //bool is_expired = false;
+            /*if (Repeat > 0 && actor.Percent == 1) {
+                if (++iterations >= Repeat) {
+                    is_expired = true;
                 }
-            }
-
-            return !IsExpired;
-        }
-    }
-
-    public delegate T AnimationComposeHandler<T> (Animation<T> animation, double percent);
-
-    public abstract class Animation<T> : Animation
-    {
-        private AnimationComposeHandler<T> compose_handler;
-        protected AnimationComposeHandler<T> ComposeHandler {
-            get { return compose_handler; }
-        }
-
-        private Easing easing = Easing.Linear;
-        protected Easing Easing {
-            get { return easing; }
-        }
+            }*/
 
-        private bool from_set;
-        protected bool FromSet {
-            get { return from_set; }
-        }
+            Percent = Choreographer.Compose (actor.Percent, Easing);
+            Update (this);
 
-        private T from_value;
-        public T FromValue {
-            get { return from_value; }
-            set {
-                from_set = true;
-                from_value = value;
+            if (is_expired && Finished != null) {
+                Finished (this);
             }
-        }
-
-        private T to_value;
-        public T ToValue {
-            get { return to_value; }
-            set { to_value = value; }
-        }
-
-        private T start_state;
-        public T StartState {
-            get { return start_state; }
-            protected set { start_state = value; }
-        }
 
-        public override void Start ()
-        {
-            T check_state = FromSet ? FromValue : (T)Item[Property];
-
-            if (!check_state.Equals (ToValue)) {
-                base.Start ();
+            if (Item != null) {
+                Item.InvalidateRender ();
             }
-        }
-
-        public Animation<T> ClearFromValue ()
-        {
-            from_set = false;
-            from_value = default (T);
-            return this;
-        }
-
-        public Animation<T> Animate ()
-        {
-            StartState = FromSet ? FromValue : (T)Item[Property];
-            return this;
-        }
-
-        public Animation<T> Animate (T toValue)
-        {
-            ClearFromValue ();
-            ToValue = toValue;
-            return Animate ();
-        }
-
-        public Animation<T> Animate (T fromValue, T toValue)
-        {
-            FromValue = fromValue;
-            ToValue = toValue;
-            return Animate ();
-        }
-
-        public Animation<T> Animate (string property, T toValue)
-        {
-            Property = property;
-            return Animate (toValue);
-        }
-
-        public Animation<T> Animate (string property, T fromValue, T toValue)
-        {
-            Property = property;
-            return Animate (fromValue, toValue);
-        }
-
-        public Animation<T> Compose (AnimationComposeHandler<T> handler)
-        {
-            compose_handler = handler;
-            return this;
-        }
-
-        public Animation<T> ClearCompose ()
-        {
-            compose_handler = null;
-            return this;
-        }
-
-        public Animation<T> To (T toValue)
-        {
-            ToValue = toValue;
-            return Animate ();
-        }
-
-        public Animation<T> From (T fromValue)
-        {
-            FromValue = fromValue;
-            return Animate ();
-        }
-
-        public Animation<T> Reverse ()
-        {
-            T from = FromValue;
-            FromValue = ToValue;
-            ToValue = from;
-            return Animate ();
-        }
-
-        public Animation<T> Ease (Easing easing)
-        {
-            this.easing = easing;
-            return this;
-        }
-
-        public Animation<T> Throttle (uint duration)
-        {
-            Duration = duration;
-            return this;
-        }
-
-        public Animation<T> Repeat (int count)
-        {
-            RepeatTimes = count;
-            return this;
-        }
-
-        public Animation<T> Expire ()
-        {
-            IsExpired = true;
-            return this;
-        }
-    }
-
-    public class DoubleAnimation : Animation<double>
-    {
-        public DoubleAnimation ()
-        {
-        }
-
-        public DoubleAnimation (string property)
-        {
-            Property = property;
-        }
-
-        public override bool Step (Actor<Animation> actor)
-        {
-            double result = ComposeHandler == null
-                ? StartState + (ToValue * actor.Percent)
-                : ComposeHandler (this, actor.Percent);
-
-            result = Easing == Easing.Linear
-                ? result
-                : Choreographer.Compose (result, Easing);
-
-            Item.SetValue<double> (Property, result);
 
-            return base.Step (actor);
+            return !is_expired;
         }
     }
 
@@ -294,7 +110,7 @@ namespace Hyena.Gui.Canvas
             stage.ActorStep += (actor) => actor.Target.Step (actor);
         }
 
-        public void Animate (Animation animation)
+        internal void Animate (Animation animation)
         {
             animation.Stage = stage;
         }
diff --git a/Hyena.Gui/Hyena.Gui.Canvas/CanvasItem.cs b/Hyena.Gui/Hyena.Gui.Canvas/CanvasItem.cs
index b2dbd80..55781cb 100644
--- a/Hyena.Gui/Hyena.Gui.Canvas/CanvasItem.cs
+++ b/Hyena.Gui/Hyena.Gui.Canvas/CanvasItem.cs
@@ -34,36 +34,28 @@ namespace Hyena.Gui.Canvas
     public class CanvasItem
     {
         private CanvasManager manager;
-        private CanvasItem parent;
+        private Hyena.Data.IDataBinder binder;
         private Theme theme;
-        private Size desired_size;
-        private Dictionary<string, object> properties;
-        private Rect allocation;
-        private bool visible = true;
 
-        public event EventHandler<EventArgs> SizeChanged;
-        public event EventHandler<EventArgs> LayoutUpdated;
+        private bool prelight_in;
+        private double prelight_opacity;
 
-        private class MemoryDataBinder : Hyena.Data.IDataBinder
-        {
-            public void Bind (object o)
-            {
-                BoundObject = o;
-            }
+        #region Public API
 
-            public object BoundObject { get; set; }
-        }
+        public event EventHandler<EventArgs> SizeChanged;
+        public event EventHandler<EventArgs> LayoutUpdated;
 
         public CanvasItem ()
         {
-            InstallProperty<double> ("Opacity", 1.0);
-            InstallProperty<double> ("Width", Double.NaN);
-            InstallProperty<double> ("Height", Double.NaN);
-            InstallProperty<Thickness> ("Margin", new Thickness (0));
-            InstallProperty<Thickness> ("Padding", new Thickness (0));
-            InstallProperty<Brush> ("Foreground", Brush.Black);
-            InstallProperty<Brush> ("Background", Brush.White);
-            InstallProperty<MarginStyle> ("MarginStyle", MarginStyle.None);
+            Visible = true;
+            Opacity = 1.0;
+            Width = Double.NaN;
+            Height = Double.NaN;
+            Margin = new Thickness (0);
+            Padding = new Thickness (0);
+            Foreground = Brush.Black;
+            Background = Brush.White;
+            MarginStyle = MarginStyle.None;
         }
 
         public void InvalidateArrange ()
@@ -82,7 +74,7 @@ namespace Hyena.Gui.Canvas
             }
         }
 
-        protected void InvalidateRender ()
+        public void InvalidateRender ()
         {
             InvalidateRender (InvalidationRect);
         }
@@ -92,32 +84,8 @@ namespace Hyena.Gui.Canvas
             InvalidateRender (area);
         }
 
-        protected void InvalidateRender (Rect area)
-        {
-            if (Parent == null) {
-                OnInvalidate (area);
-            } else {
-                var alloc = Parent.ContentAllocation;
-                area.Offset (alloc.X, alloc.Y);
-                Parent.Invalidate (area);
-            }
-        }
-
-        private void OnInvalidate (Rect area)
-        {
-            CanvasItem root = RootAncestor;
-            if (root != null && root.Manager != null) {
-                root.Manager.QueueRender (this, area);
-            } else {
-                Hyena.Log.WarningFormat ("Asked to invalidate {0} for {1} but no CanvasManager!", area, this);
-            }
-        }
-
-        private Hyena.Data.IDataBinder binder;
         public Hyena.Data.IDataBinder Binder {
-            get {
-                return binder ?? (binder = new MemoryDataBinder ());
-            }
+            get { return binder ?? (binder = new MemoryDataBinder ()); }
             set { binder = value; }
         }
 
@@ -126,15 +94,12 @@ namespace Hyena.Gui.Canvas
             Binder.Bind (o);
         }
 
-        protected object BoundObject {
-            get { return Binder.BoundObject; }
-            set { Binder.BoundObject = value; }
-        }
-
         public virtual void Arrange ()
         {
         }
 
+        public Action<Cairo.Context, Theme, Rect, double> PrelightRenderer { get; set; }
+
         public virtual Size Measure (Size available)
         {
             double m_x = Margin.X;
@@ -183,6 +148,10 @@ namespace Hyena.Gui.Canvas
 
             ClippedRender (context);
 
+            if (PrelightRenderer != null && prelight_opacity > 0) {
+                PrelightRenderer (context.Context, context.Theme, new Rect (0, 0, ContentAllocation.Width, ContentAllocation.Height), prelight_opacity);
+            }
+
             cr.ResetClip ();
 
             if (opacity < 1.0) {
@@ -193,49 +162,6 @@ namespace Hyena.Gui.Canvas
             cr.Restore ();
         }
 
-        /*protected Rect TopLevelAllocation {
-            get {
-                var alloc = ContentAllocation;
-                var top = this;
-                while (top.Parent != null) {
-                    alloc.Offset (top.Parent.Allocation);
-                    top = top.Parent;
-                }
-
-                return alloc;
-            }
-        }*/
-
-        protected virtual void ClippedRender (Cairo.Context cr)
-        {
-        }
-
-        protected virtual void ClippedRender (Hyena.Data.Gui.CellContext context)
-        {
-            ClippedRender (context.Context);
-        }
-
-        protected virtual void OnSizeChanged ()
-        {
-            EventHandler<EventArgs> handler = SizeChanged;
-            if (handler != null) {
-                handler (this, EventArgs.Empty);
-            }
-        }
-
-        protected virtual void OnLayoutUpdated ()
-        {
-            EventHandler<EventArgs> handler = LayoutUpdated;
-            if (handler != null) {
-                handler (this, EventArgs.Empty);
-            }
-        }
-
-        internal CanvasManager Manager {
-            get { return manager ?? (Parent != null ? Parent.Manager : null); }
-            set { manager = value; }
-        }
-
         public CanvasItem RootAncestor {
             get {
                 CanvasItem root = this;
@@ -246,65 +172,50 @@ namespace Hyena.Gui.Canvas
             }
         }
 
-        public CanvasItem Parent {
-            get { return parent; }
-            set { parent = value; }
-        }
+        public CanvasItem Parent { get; set; }
 
         public Theme Theme {
             get { return theme ?? (Parent != null ? Parent.Theme : null); }
             set { theme = value; }
         }
 
-        public Size DesiredSize {
-            get { return desired_size; }
-            protected set { desired_size = value; }
-        }
-
-        public Thickness Padding {
-            get { return GetValue<Thickness> ("Padding"); }
-            set { SetValue<Thickness> ("Padding", value); }
-        }
-
-        public Thickness Margin {
-            get { return GetValue<Thickness> ("Margin"); }
-            set { SetValue<Thickness> ("Margin", value); }
-        }
-
-        public MarginStyle MarginStyle {
-            get { return GetValue<MarginStyle> ("MarginStyle"); }
-            set { SetValue<MarginStyle> ("MarginStyle", value); }
-        }
-
-        public double Width {
-            get { return GetValue<double> ("Width"); }
-            set { SetValue<double> ("Width", value); }
-        }
+        public bool Visible { get; set; }
+        public double Opacity { get; set; }
+        public Brush Foreground { get; set; }
+        public Brush Background { get; set; }
 
-        public double Height {
-            get { return GetValue<double> ("Height"); }
-            set { SetValue<double> ("Height", value); }
-        }
+        public Thickness Padding { get; set; }
+        public Thickness Margin { get; set; }
+        public MarginStyle MarginStyle { get; set; }
 
-        public double Opacity {
-            get { return GetValue<double> ("Opacity"); }
-            set { SetValue<double> ("Opacity", value); }
-        }
+        public Size DesiredSize { get; protected set; }
+        public Rect Allocation { get; set; }
+        // FIXME need this?
+        public Rect VirtualAllocation { get; set; }
 
-        public Brush Foreground {
-            get { return GetValue<Brush> ("Foreground"); }
-            set { SetValue<Brush> ("Foreground", value); }
+        private double min_width, max_width;
+        public double MinWidth {
+            get { return min_width; }
+            set {
+                min_width = value;
+                if (value > max_width) {
+                    max_width = value;
+                }
+            }
         }
 
-        public Brush Background {
-            get { return GetValue<Brush> ("Background"); }
-            set { SetValue<Brush> ("Background", value); }
+        public double MaxWidth {
+            get { return max_width; }
+            set {
+                max_width = value;
+                if (value < min_width) {
+                    min_width = value;
+                }
+            }
         }
 
-        public Rect Allocation {
-            get { return allocation; }
-            set { allocation = value; }
-        }
+        public double Width { get; set; }
+        public double Height { get; set; }
 
         public Rect ContentAllocation {
             get {
@@ -317,9 +228,6 @@ namespace Hyena.Gui.Canvas
             }
         }
 
-        // FIXME need this?
-        public Rect VirtualAllocation { get; set; }
-
         protected virtual Rect InvalidationRect {
             //get { return Rect.Empty; }
             get { return Allocation; }
@@ -333,110 +241,75 @@ namespace Hyena.Gui.Canvas
             get { return new Size (Math.Round (ContentAllocation.Width), Math.Round (ContentAllocation.Height)); }
         }
 
-        public bool Visible {
-            get { return visible; }
-            set { visible = value; }
-        }
-
-        protected void InstallProperty<T> (string property)
-        {
-            InstallProperty (property, default (T));
-        }
+        #endregion
 
-        protected void InstallProperty<T> (string property, T defaultValue)
+        protected void InvalidateRender (Rect area)
         {
-            if (properties == null) {
-                properties = new Dictionary<string, object> ();
-            }
-
-            if (properties.ContainsKey (property)) {
-                throw new InvalidOperationException ("Property is already installed: " + property);
+            if (Parent == null) {
+                OnInvalidate (area);
+            } else {
+                var alloc = Parent.ContentAllocation;
+                area.Offset (alloc.X, alloc.Y);
+                Parent.Invalidate (area);
             }
-
-            properties.Add (property, defaultValue);
         }
 
-        protected virtual bool OnPropertyChange (string property, object value)
+        private void OnInvalidate (Rect area)
         {
-            switch (property) {
-                case "Foreground":
-                case "Background":
-                case "MarginStyle":
-                case "Opacity":
-                    InvalidateRender ();
-                    return true;
-                /* case "Width":
-                case "Height":
-                case "Margin":
-                    InvalidateArrange ();
-                    InvalidateMeasure ();
-                    return true; */
+            CanvasItem root = RootAncestor;
+            if (root != null && root.Manager != null) {
+                root.Manager.QueueRender (this, area);
+            } else {
+                Hyena.Log.WarningFormat ("Asked to invalidate {0} for {1} but no CanvasManager!", area, this);
             }
+        }
 
-            return false;
+        protected object BoundObject {
+            get { return Binder.BoundObject; }
+            set { Binder.BoundObject = value; }
         }
 
-        public object this[string property] {
+        /*protected Rect TopLevelAllocation {
             get {
-                object result;
-                if (properties != null && properties.TryGetValue (property, out result)) {
-                    return result;
-                }
-
-                return result;
-            }
-
-            set {
-                if (properties == null || !properties.ContainsKey (property)) {
-                    throw new InvalidOperationException ("Property does not exist: " + property);
-                }
-
-                object existing = properties[property];
-
-                Type existing_type = existing.GetType ();
-                Type new_type = value.GetType ();
-
-                if (existing_type != new_type && !new_type.IsSubclassOf (existing_type)) {
-                    throw new InvalidOperationException ("Invalid value type " +
-                        value.GetType () + " for property: " + property);
+                var alloc = ContentAllocation;
+                var top = this;
+                while (top.Parent != null) {
+                    alloc.Offset (top.Parent.Allocation);
+                    top = top.Parent;
                 }
 
-                if (existing != value) {
-                    properties[property] = value;
-                    OnPropertyChange (property, value);
-                }
+                return alloc;
             }
-        }
+        }*/
 
-        public T GetValue<T> (string property)
+        protected virtual void ClippedRender (Cairo.Context cr)
         {
-            return GetValue (property, default (T));
         }
 
-        public T GetValue<T> (string property, T fallback)
+        protected virtual void ClippedRender (Hyena.Data.Gui.CellContext context)
         {
-            object result = this[property];
-            if (result == null) {
-                return fallback;
-            }
-            return (T)result;
+            ClippedRender (context.Context);
         }
 
-        public void SetValue<T> (string property, T value)
+        protected virtual void OnSizeChanged ()
         {
-            this[property] = value;
+            EventHandler<EventArgs> handler = SizeChanged;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
         }
 
-        public T Animate<T> (T animation) where T : Animation
+        protected virtual void OnLayoutUpdated ()
         {
-            animation.Item = this;
-            AnimationManager.Instance.Animate (animation);
-            return animation;
+            EventHandler<EventArgs> handler = LayoutUpdated;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
         }
 
-        public DoubleAnimation AnimateDouble (string property)
-        {
-            return Animate (new DoubleAnimation (property));
+        internal CanvasManager Manager {
+            get { return manager ?? (Parent != null ? Parent.Manager : null); }
+            set { manager = value; }
         }
 
 #region Input Events
@@ -477,14 +350,36 @@ namespace Hyena.Gui.Canvas
 
         public virtual bool CursorEnterEvent ()
         {
+            if (PrelightRenderer != null) {
+                prelight_in = true;
+                prelight_stage.AddOrReset (this);
+            }
             return false;
         }
 
         public virtual bool CursorLeaveEvent ()
         {
+            if (PrelightRenderer != null) {
+                prelight_in = false;
+                prelight_stage.AddOrReset (this);
+            }
             return false;
         }
 
+        private static Hyena.Gui.Theatrics.Stage<CanvasItem> prelight_stage = new Hyena.Gui.Theatrics.Stage<CanvasItem> (250);
+        static CanvasItem ()
+        {
+            prelight_stage.ActorStep += actor => {
+                var alpha = actor.Target.prelight_opacity;
+                alpha += actor.Target.prelight_in
+                    ? actor.StepDeltaPercent
+                    : -actor.StepDeltaPercent;
+                actor.Target.prelight_opacity = alpha = Math.Max (0.0, Math.Min (1.0, alpha));
+                actor.Target.InvalidateRender ();
+                return alpha > 0 && alpha < 1;
+            };
+        }
+
         /*protected virtual void OnClicked ()
         {
             var handler = Clicked;
@@ -495,5 +390,14 @@ namespace Hyena.Gui.Canvas
 
 #endregion
 
+        private class MemoryDataBinder : Hyena.Data.IDataBinder
+        {
+            public void Bind (object o)
+            {
+                BoundObject = o;
+            }
+
+            public object BoundObject { get; set; }
+        }
     }
 }
diff --git a/Hyena.Gui/Hyena.Gui.Canvas/Prelight.cs b/Hyena.Gui/Hyena.Gui.Canvas/Prelight.cs
new file mode 100644
index 0000000..01c4e38
--- /dev/null
+++ b/Hyena.Gui/Hyena.Gui.Canvas/Prelight.cs
@@ -0,0 +1,55 @@
+// 
+// Prelight.cs
+//  
+// Author:
+//       Aaron Bockover <abockover novell com>
+// 
+// Copyright 2009 Aaron Bockover
+// 
+// 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 Hyena.Gui.Theming;
+using Hyena.Gui.Theatrics;
+using Hyena.Gui.Canvas;
+
+namespace Hyena.Gui.Canvas
+{
+    public static class Prelight
+    {
+        public static void Gradient (Cairo.Context cr, Theme theme, Rect rect, double opacity)
+        {
+            cr.Save ();
+            cr.Translate (rect.X, rect.Y);
+
+            var x = rect.Width / 2.0;
+            var y = rect.Height / 2.0;
+            var grad = new Cairo.RadialGradient (x, y, 0, x, y, rect.Width / 2.0);
+            grad.AddColorStop (0, new Cairo.Color (0, 0, 0, 0.1 * opacity));
+            grad.AddColorStop (1, new Cairo.Color (0, 0, 0, 0.35 * opacity));
+            cr.Pattern = grad;
+            CairoExtensions.RoundedRectangle (cr, rect.X, rect.Y, rect.Width, rect.Height, theme.Context.Radius);
+            cr.Fill ();
+            grad.Destroy ();
+
+            cr.Restore ();
+        }
+    }
+}
diff --git a/Hyena.Gui/Hyena.Gui.Canvas/Rect.cs b/Hyena.Gui/Hyena.Gui.Canvas/Rect.cs
index 0a1b406..f25e2ce 100644
--- a/Hyena.Gui/Hyena.Gui.Canvas/Rect.cs
+++ b/Hyena.Gui/Hyena.Gui.Canvas/Rect.cs
@@ -145,6 +145,10 @@ namespace Hyena.Gui.Canvas
             get { return IsEmpty ? Double.NegativeInfinity : y + h; }
         }
 
+        public Size Size {
+            get { return new Size (Width, Height); }
+        }
+
         public void Intersect (Rect rect)
         {
             if (IsEmpty || rect.IsEmpty) {
diff --git a/Hyena.Gui/Hyena.Gui.Canvas/TextBlock.cs b/Hyena.Gui/Hyena.Gui.Canvas/TextBlock.cs
index c5ddcad..41464ca 100644
--- a/Hyena.Gui/Hyena.Gui.Canvas/TextBlock.cs
+++ b/Hyena.Gui/Hyena.Gui.Canvas/TextBlock.cs
@@ -40,14 +40,8 @@ namespace Hyena.Gui.Canvas
 
         public TextBlock ()
         {
-            InstallProperty<string> ("Text", String.Empty);
-            InstallProperty<string> ("TextFormat", "");
-            InstallProperty<bool> ("UseMarkup", false);
-            InstallProperty<double> ("HorizontalAlignment", 0.0);
-            InstallProperty<double> ("VerticalAlignment", 0.0);
-            InstallProperty<FontWeight> ("FontWeight", FontWeight.Normal);
-            InstallProperty<TextWrap> ("TextWrap", TextWrap.None);
-            InstallProperty<bool> ("ForceSize", false);
+            FontWeight = FontWeight.Normal;
+            TextWrap = TextWrap.None;
             EllipsizeMode = Pango.EllipsizeMode.End;
         }
 
@@ -120,7 +114,7 @@ namespace Hyena.Gui.Canvas
         private static char[] lfcr = new char[] {'\n', '\r'};
         private void UpdateLayout (Pango.Layout layout, string text)
         {
-            string final_text = GetFormattedText (text);
+            string final_text = GetFormattedText (text) ?? "";
             if (TextWrap == TextWrap.None && final_text.IndexOfAny (lfcr) >= 0) {
                 final_text = final_text.Replace ("\r\n", "\x20").Replace ('\n', '\x20').Replace ('\r', '\x20');
             }
@@ -240,79 +234,21 @@ namespace Hyena.Gui.Canvas
             }
         }
 
-        protected override bool OnPropertyChange (string property, object value)
-        {
-            switch (property) {
-                case "FontWeight":
-                case "TextWrap":
-                case "Text":
-                case "TextFormat":
-                case "UseMarkup":
-                case "ForceSize":
-                    if (layout != null) {
-                        InvalidateMeasure ();
-                        InvalidateArrange ();
-                    }
-                    return true;
-                case "HorizontalAlignment":
-                case "VerticalAlignment":
-                    if (layout != null) {
-                        InvalidateArrange ();
-                    }
-                    return true;
-            }
-
-            return base.OnPropertyChange (property, value);
-        }
-
         protected override Rect InvalidationRect {
             get { return invalidation_rect; }
         }
 
-        public string Text {
-            get { return GetValue<string> ("Text"); }
-            set { SetValue<string> ("Text", value); }
-        }
-
-        public string TextFormat {
-            get { return GetValue<string> ("TextFormat"); }
-            set { SetValue<string> ("TextFormat", value); }
-        }
-
-        public FontWeight FontWeight {
-            get { return GetValue<FontWeight> ("FontWeight"); }
-            set { SetValue<FontWeight> ("FontWeight", value); }
-        }
-
-        public TextWrap TextWrap {
-            get { return GetValue<TextWrap> ("TextWrap"); }
-            set { SetValue<TextWrap> ("TextWrap", value); }
-        }
-
+        public string Text { get; set; }
+        public string TextFormat { get; set; }
+        public FontWeight FontWeight { get; set; }
+        public TextWrap TextWrap { get; set; }
         public bool Fade { get; set; }
-
-        public bool ForceSize {
-            get { return GetValue<bool> ("ForceSize"); }
-            set { SetValue<bool> ("ForceSize", value); }
-        }
-
-        public virtual Pango.EllipsizeMode EllipsizeMode { get; set; }
-
+        public bool ForceSize { get; set; }
+        public Pango.EllipsizeMode EllipsizeMode { get; set; }
         public Func<object, string> TextGenerator { get; set; }
+        public bool UseMarkup { get; set; }
 
-        public bool UseMarkup {
-            get { return GetValue<bool> ("UseMarkup"); }
-            set { SetValue<bool> ("UseMarkup", value); }
-        }
-
-        public double HorizontalAlignment {
-            get { return GetValue<double> ("HorizontalAlignment", 0.0); }
-            set { SetValue<double> ("HorizontalAlignment", value); }
-        }
-
-        public double VerticalAlignment {
-            get { return GetValue<double> ("VerticalAlignment", 0.0); }
-            set { SetValue<double> ("VerticalAlignment", value); }
-        }
+        public double HorizontalAlignment { get; set; }
+        public double VerticalAlignment { get; set; }
     }
 }
diff --git a/Hyena.Gui/Makefile.am b/Hyena.Gui/Makefile.am
index 5341d0f..62b8801 100644
--- a/Hyena.Gui/Makefile.am
+++ b/Hyena.Gui/Makefile.am
@@ -43,6 +43,7 @@ SOURCES =  \
 	Hyena.Data.Gui/SortableColumn.cs \
     Hyena.Gui.Canvas/AnimationManager.cs \
     Hyena.Gui.Canvas/Brush.cs \
+    Hyena.Gui.Canvas/Prelight.cs \
     Hyena.Gui.Canvas/CanvasHost.cs \
     Hyena.Gui.Canvas/CanvasItem.cs \
     Hyena.Gui.Canvas/CanvasItemCollection.cs \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]