/* * ImageDisplay.cs * * Copyright 2007 Novell Inc. * * Author * Larry Ewing * * See COPYING for license information. * */ using Gtk; using Gdk; using System; using Cairo; using FSpot; namespace FSpot.Widgets { [Binding(Gdk.Key.Up, "Up")] [Binding(Gdk.Key.Down, "Down")] [Binding(Gdk.Key.Left, "TiltImage", 0.05)] [Binding(Gdk.Key.Right, "TiltImage", -0.05)] [Binding(Gdk.Key.space, "Pan")] [Binding(Gdk.Key.Q, "Vingette")] [Binding(Gdk.Key.R, "RevealImage")] [Binding(Gdk.Key.P, "PushImage")] public class ImageDisplay : Gtk.EventBox { ImageInfo current; ImageInfo next; BrowsablePointer item; ITransition transition; IEffect effect; Delay delay; int index = 0; int block_size = 256; ITransition Transition { get { return transition; } set { if (transition != null) transition.Dispose (); transition = value; if (transition != null) delay.Start (); else delay.Stop (); } } public ImageDisplay (BrowsablePointer item) { this.item = item; CanFocus = true; current = new ImageInfo (item.Current.DefaultVersionUri); if (item.Collection.Count > item.Index + 1) { next = new ImageInfo (item.Collection [item.Index + 1].DefaultVersionUri); } delay = new Delay (30, new GLib.IdleHandler (DrawFrame)); } protected override void OnDestroyed () { if (current != null) { current.Dispose (); current = null; } if (next != null) { next.Dispose (); next = null; } Transition = null; if (effect != null) effect.Dispose (); base.OnDestroyed (); } public bool Up () { Console.WriteLine ("Up"); Transition = new Dissolve (current, next); return true; } public bool Down () { Console.WriteLine ("down"); Transition = new Dissolve (next, current); return true; } public bool Vingette () { SoftFocus f = effect as SoftFocus; if (f == null) { f = new SoftFocus (current); effect = f; } QueueDraw (); return true; } public bool TiltImage (double radians) { Tilt t = effect as Tilt; if (t == null) { t = new Tilt (current); effect = t; } t.Angle += radians; QueueDraw (); return true; } public bool Pan () { Console.WriteLine ("space"); Transition = new Wipe (current, next); return true; } public bool RevealImage () { Console.WriteLine ("r"); Transition = new Reveal (current, next); return true; } public bool PushImage () { Console.WriteLine ("p"); Transition = new Push (current, next); return true; } public bool DrawFrame () { if (Transition != null) Transition.OnEvent (this); return true; } private static void SetClip (Context ctx, Gdk.Rectangle area) { ctx.MoveTo (area.Left, area.Top); ctx.LineTo (area.Right, area.Top); ctx.LineTo (area.Right, area.Bottom); ctx.LineTo (area.Left, area.Bottom); ctx.ClosePath (); ctx.Clip (); } private static void SetClip (Context ctx, Region region) { foreach (Gdk.Rectangle area in region.GetRectangles ()) { ctx.MoveTo (area.Left, area.Top); ctx.LineTo (area.Right, area.Top); ctx.LineTo (area.Right, area.Bottom); ctx.LineTo (area.Left, area.Bottom); ctx.ClosePath (); } ctx.Clip (); } private void OnExpose (Context ctx, Region region) { SetClip (ctx, region); if (Transition != null) { bool done = false; foreach (Gdk.Rectangle area in GetRectangles (region)) { BlockProcessor proc = new BlockProcessor (area, block_size); Gdk.Rectangle subarea; while (proc.Step (out subarea)) { ctx.Save (); SetClip (ctx, subarea); done = ! Transition.OnExpose (ctx, Allocation); ctx.Restore (); } } if (done) { System.Console.WriteLine ("frames = {0}", Transition.Frames); Transition = null; } } else if (effect != null) { foreach (Gdk.Rectangle area in GetRectangles (region)) { BlockProcessor proc = new BlockProcessor (area, block_size); Gdk.Rectangle subarea; while (proc.Step (out subarea)) { ctx.Save (); SetClip (ctx, subarea); effect.OnExpose (ctx, Allocation); ctx.Restore (); } } } else { ctx.Operator = Operator.Source; SurfacePattern p = new SurfacePattern (current.Surface); p.Filter = Filter.Fast; SetClip (ctx, region); ctx.Matrix = current.Fill (Allocation); ctx.Source = p; ctx.Paint (); p.Destroy (); } } private static Gdk.Rectangle [] GetRectangles (Gdk.Region region) { #if true return new Gdk.Rectangle [] { region.Clipbox }; #else return region.GetRectangles (); #endif } protected override bool OnExposeEvent (EventExpose args) { bool double_buffer = false; base.OnExposeEvent (args); Context ctx = CairoUtils.CreateContext (GdkWindow); //Surface glitz = CairoUtils.CreateGlitzSurface (GdkWindow); //Context ctx = new Context (glitz); if (double_buffer) { ImageSurface cim = new ImageSurface (Format.RGB24, Allocation.Width, Allocation.Height); Context buffer = new Context (cim); OnExpose (buffer, args.Region); SurfacePattern sur = new SurfacePattern (cim); sur.Filter = Filter.Fast; ctx.Source = sur; SetClip (ctx, args.Region); ctx.Paint (); ((IDisposable)buffer).Dispose (); ((IDisposable)cim).Dispose (); sur.Destroy (); } else { OnExpose (ctx, args.Region); } //glitz.Flush (); ((IDisposable)ctx).Dispose (); return true; } } }