using System; using Gtk; using Tao.OpenGl; using Cairo; using System.Runtime.InteropServices; using FSpot; using FSpot.Widgets; namespace FSpot { public class TransitionList { GlTransition [] transitions = new GlTransition [] { new GlTransition.Dissolve (), new GlTransition.Flip (), new GlTransition.Push (), new GlTransition.Reveal (), new GlTransition.Cover () }; int current_transition = 0; public TransitionList () { } public event EventHandler Changed; public GlTransition Transition { get { return transitions [current_transition]; } } public int Index { get { return current_transition; } set { current_transition = value; if (Changed != null) Changed (this, EventArgs.Empty); } } public ComboBox GetCombo () { ComboBox combo = ComboBox.NewText (); combo.HasFrame = false; foreach (GlTransition t in transitions) { combo.AppendText (t.Name); } combo.Active = current_transition; combo.Changed += HandleComboChanged; combo.Show (); return combo; } private void HandleComboChanged (object sender, EventArgs args) { ComboBox combo = sender as ComboBox; string name = null; if (combo == null) return; TreeIter iter; if (combo.GetActiveIter (out iter)) name = (string) combo.Model.GetValue (iter, 0); for (int i = 0; i < transitions.Length; i++) if (name == transitions[i].Name) Index = i; } } //[Binding(Gdk.Key.Up, "Spin", 1)] //[Binding(Gdk.Key.Down, "Spin", -1)] [Binding(Gdk.Key.Left, "Scale", .05f)] [Binding(Gdk.Key.Right, "Scale", -.05f)] public class TextureDisplay : Gtk.DrawingArea { BrowsablePointer item; GdkGlx.Context glx; float angle = 0.0f; Animator flip; public TextureDisplay (BrowsablePointer item) { this.item = item; DoubleBuffered = false; AppPaintable = true; CanFocus = true; item.Changed += HandleItemChanged; flip = new Animator (6000, 6000, delegate { flip.Start (); item.MoveNext (true); }); flip.RunWhenStarted = false; } GlTransition [] transitions = new GlTransition [] { new GlTransition.Dissolve (), new GlTransition.Flip (), new GlTransition.Push (), new GlTransition.Reveal (), new GlTransition.Cover () }; int current_transition = 0; public GlTransition Transition { get { return transitions [current_transition]; } } public bool Spin (int amount) { current_transition += amount; if (current_transition >= transitions.Length) current_transition = 0; if (current_transition < 0) current_transition = transitions.Length -1; QueueDraw (); return true; } public bool Scale (float amount) { if (Transition != null) Transition.Percent += amount; QueueDraw (); return true; } private Texture CreateTexture () { if (glx == null || GdkWindow == null) return null; glx.MakeCurrent (GdkWindow); Texture tex; try { using (ImageFile img = ImageFile.Create (item.Current.DefaultVersionUri)) { using (Gdk.Pixbuf pixbuf = img.Load ()) { tex = new Texture (pixbuf); } } } catch (Exception) { tex = new Texture (PixbufUtils.ErrorPixbuf); } return tex; } Animator animator; private void HandleItemChanged (BrowsablePointer p, BrowsablePointerChangedArgs args) { Animator = new Animator (3000, 20, HandleTick); if (glx == null) return; //Console.WriteLine ("Begin previous = {0} texture = {1}", // previous != null ? previous.Id.ToString () : "null", // next != null ? next.Id.ToString () : "null"); if (!item.IsValid || item.Collection.Count < 0) return; Next = null; PreloadNext (); //Console.WriteLine ("End previous = {0} texture = {1}", // previous != null ? previous.Id.ToString () : "null", // next != null ? next.Id.ToString () : "null"); if (IsRealized) Animator.Start (); } private Animator Animator { get { return animator; } set { if (animator != null) animator.Stop (); if (value == null) flip.Start (); else flip.Stop (); animator = value; } } public ComboBox GetCombo () { ComboBox combo = ComboBox.NewText (); combo.HasFrame = false; foreach (GlTransition t in transitions) combo.AppendText (t.Name); combo.Active = current_transition; combo.Changed += HandleComboChanged; combo.Show (); return combo; } private void HandleComboChanged (object sender, EventArgs args) { ComboBox combo = sender as ComboBox; string name = null; if (combo == null) return; TreeIter iter; if (combo.GetActiveIter (out iter)) name = (string) combo.Model.GetValue (iter, 0); for (int i = 0; i < transitions.Length; i++) if (name == transitions[i].Name) current_transition = i; QueueDraw (); } public void HandleTick (object sender, EventArgs args) { if (!IsRealized) { System.Console.WriteLine ("animation running without active window"); return; } if (Animator.Percent >= 1.0) { Transition.Percent = 1.0f; Animator = null; } else { Transition.Percent = Animator.Percent; } QueueDraw (); GdkWindow.ProcessUpdates (false); } protected override void OnRealized () { #if FALSE if (CompositeUtils.IsComposited (Screen) && CompositeUtils.SetRgbaColormap (this)) Console.WriteLine ("Set Rba"); #endif if (glx != null) glx.Destroy (); int [] attr = new int [] { (int) GdkGlx.GlxAttribute.Rgba, (int) GdkGlx.GlxAttribute.DepthSize, 16, (int) GdkGlx.GlxAttribute.DoubleBuffer, (int) GdkGlx.GlxAttribute.None }; glx = new GdkGlx.Context (Screen, attr); Colormap = glx.GetColormap (); base.OnRealized (); } protected override void OnMapped () { base.OnMapped (); if (Animator != null) Animator.Start (); } protected override void OnUnrealized () { Animator = null; flip.Stop (); base.OnUnrealized (); if (glx != null) glx.Destroy (); glx = null; } protected override void OnDestroyed () { item.Changed -= HandleItemChanged; base.OnDestroyed (); } Texture previous; public Texture Previous { get { if (previous == null) previous = Next; return previous; } set { if (previous != next) previous.Dispose (); previous = value; } } Texture next; public Texture Next { get { PreloadNext (); return next; } set { Texture tmp = next; next = value; Previous = tmp; } } private void PreloadNext () { if (next == null) next = CreateTexture (); } GlTransition transition; private void DrawTransition () { Transition.Draw (Allocation, Next, Previous); } private void DrawPixels () { Gl.glClear (Gl.GL_COLOR_BUFFER_BIT); Gl.glPixelStorei (Gl.GL_UNPACK_ALIGNMENT, 1); Gl.glRasterPos2i (0, Allocation.Height); Gl.glPixelZoom (Allocation.Width / (float) next.Width, - Allocation.Height / (float) next.Height); /* Gl.glDrawPixels (texture.Width, texture.Height, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, texture.Pixels); */ } protected override void OnSizeAllocated (Gdk.Rectangle allocation) { base.OnSizeAllocated (allocation); QueueDraw (); } public void PrintVersions () { IntPtr version = Gl.glGetString (Gl.GL_VERSION); System.Console.WriteLine ("Version = {0}", Marshal.PtrToStringAnsi (version)); IntPtr vendor = Gl.glGetString (Gl.GL_VENDOR); System.Console.WriteLine ("Vendor = {0}", Marshal.PtrToStringAnsi (vendor)); IntPtr ext = Gl.glGetString (Gl.GL_EXTENSIONS); System.Console.WriteLine ("Extensions = {0}", Marshal.PtrToStringAnsi (ext)); } void CheckError (string msg) { int error = Gl.glGetError (); if (error != Gl.GL_NO_ERROR) Console.WriteLine ("OpenGL error {0}: {1}", msg, Glu.gluErrorString (error)); } protected override bool OnExposeEvent (Gdk.EventExpose args) { glx.MakeCurrent (GdkWindow); CheckError ("entering expose"); Gdk.Color c = Style.Background (State); Gl.glClearColor (c.Red / (float) ushort.MaxValue, c.Blue / (float) ushort.MaxValue, c.Green / (float) ushort.MaxValue, 1.0f); Gl.glShadeModel(Gl.GL_FLAT); //Gl.glMatrixMode(Gl.GL_MODELVIEW); //Gl.glClear(Gl.GL_COLOR_BUFFER_BIT); Gl.glColor3f(1.0f, 1.0f, 1.0f); Gl.glEnable (Gl.GL_DEPTH_TEST); Gl.glEnable (Gl.GL_NORMALIZE); //Gl.glEnable (Gl.GL_BLEND); //Gl.glBlendFunc (Gl.GL_ONE, Gl.GL_ONE); Gl.glShadeModel (Gl.GL_FLAT); Gl.glEnable (Gl.GL_TEXTURE_RECTANGLE_ARB); //Gl.glPolygonMode (Gl.GL_FRONT_AND_BACK, Gl.GL_FILL); //Gl.glDisable (Gl.GL_CULL_FACE); //Gl.glLightModelf (Gl.GL_LIGHT_MODEL_TWO_SIDE, 0); //Gl.glEnable (Gl.GL_LIGHTING); //Gl.glEnable (Gl.GL_LIGHT0); //Gl.glLightfv (Gl.GL_LIGHT0, Gl.GL_DIFFUSE, new float [] { 1.0f, 1.0f, 0.0f, 1.0f }); //Gl.glTexEnvi (Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_MODULATE); //Gl.glTexParameteri (Gl.GL_TEXTURE_RECTANGLE_ARB, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); //Gl.glTexParameteri (Gl.GL_TEXTURE_RECTANGLE_ARB, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); // Viewing transformation Gl.glClear (Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); //Gl.glMaterialfv (Gl.GL_FRONT, Gl.GL_DIFFUSE, new float [] { 1f, 1f, 1f, 1f}); //Gl.glMaterialfv (Gl.GL_BACK, Gl.GL_DIFFUSE, new float [] { 1f, 1f, 1f, 1f}); //Gl.glRotatef (35, 0, 1, 0); DrawTransition (); //DrawTextureSplit (); Gl.glFlush (); glx.SwapBuffers (GdkWindow); CheckError ("leaving expose"); return true; } } }