New test.
[mono.git] / mcs / class / System.Drawing / System.Drawing / ImageAnimator.cs
index 36c8dac80813d33762e855e3c5cc83076cba1d0f..3f403c6acd9a365924efc1bb06ed0e9b04c9357f 100644 (file)
@@ -6,22 +6,89 @@
 //   Sanjay Gupta (gsanjay@novell.com)
 //
 // (C) 2002 Ximian, Inc
+// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
 //
-using System;
+// 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.Drawing.Imaging;
 using System.Threading;
+using System.Collections;
 
 namespace System.Drawing
 {
+       //AnimateEventArgs class
+       class AnimateEventArgs : EventArgs 
+       {  
+               private int frameCount;
+               private int activeFrameCount = 0;
+               private Thread thread;
+      
+               //Constructor.
+               //
+               public AnimateEventArgs(Image img)
+               {
+                       Guid[] dimensionList = img.FrameDimensionsList;
+                       int length = dimensionList.Length;
+                       for (int i=0; i<length; i++) {
+                               if (dimensionList [i].Equals(FrameDimension.Time.Guid))
+                                       this.frameCount = img.GetFrameCount (FrameDimension.Time);
+                       }                       
+               }
+      
+               public int FrameCount {     
+                       get { 
+                               return frameCount;
+                       }      
+               }
+      
+               public int ActiveFrameCount {
+                       get {
+                               return activeFrameCount;
+                       }
+
+                       set {
+                               activeFrameCount = value;
+                       }
+               }
+
+               public Thread RunThread{
+                       get {
+                               return thread;
+                       }
+
+                       set {
+                               thread = value;
+                       }
+               }
+       }
+
        /// <summary>
        /// Summary description for ImageAnimator.
        /// </summary>
+       /// 
+       [MonoTODO]
        public sealed class ImageAnimator
        {
-               static private bool isAnimating = false;
-               static private Thread thread;
-               static private int activeFrame;
-
+               static Hashtable ht = new Hashtable (); 
+               
                private ImageAnimator ()
                {
                        //
@@ -33,23 +100,27 @@ namespace System.Drawing
                {
                        if (img == null)
                                throw new System.NullReferenceException ("Object reference not set to an instance of an object.");
-
-                       if (!isAnimating) {
-                               int frameCount = img.GetFrameCount (FrameDimension.Time);
-                               if (frameCount>1){
-                                       isAnimating = true;
-                                       //Start a new thread for looping within multiple frames of the image
-                                       WorkerThread WT = new WorkerThread(img, new ActiveFrameCountCallBack(ResultCallback));
-                                       ThreadStart TS = new ThreadStart(WT.LoopHandler);       
-                                       thread = new Thread(TS);
-                                       //Console.WriteLine ("Starting Thread");
-                                       //MessageBox.Show ("Starting Thread");
-                                       thread.Start();                                 
+                       
+                       if (!ht.ContainsKey (img)) {
+                               AnimateEventArgs evtArgs = new AnimateEventArgs (img);
+                               int delay;
+                               try {
+                                       PropertyItem item = img.GetPropertyItem (0x5100); // FrameDelay in libgdiplus
+                                       // Time is in 1/100th of a second
+                                       delay = (item.Value [0] + item.Value [1] * 256) * 10;
+                               } catch {
+                                       delay = 200;
                                }
-                                                       
+
+                               WorkerThread WT = new WorkerThread (onFrameChangeHandler, evtArgs, delay);
+                               ThreadStart TS = new ThreadStart(WT.LoopHandler);       
+                               Thread thread = new Thread(TS);
+                               thread.IsBackground = true;
+                               evtArgs.RunThread = thread;
+                               ht.Add (img, evtArgs);
+                               
+                               thread.Start();                         
                        }
-                       //Console.WriteLine ("Started Thread");
-                       //MessageBox.Show ("Started Thread");
                }
 
                public static bool CanAnimate (Image img)
@@ -66,110 +137,82 @@ namespace System.Drawing
                        //with parameter FrameDimension.Time
                        Guid[] dimensionList = img.FrameDimensionsList;
                        int length = dimensionList.Length;
-                       for (int i=0; i<length; i++){
-                               if (dimensionList [i].Equals(FrameDimension.Time.Guid)){
-                                       int frameCount = img.GetFrameCount (FrameDimension.Time);
+                       int frameCount;
+                       for (int i=0; i<length; i++) 
+                       {
+                               if (dimensionList [i].Equals(FrameDimension.Time.Guid)) 
+                               {
+                                       frameCount = img.GetFrameCount (FrameDimension.Time);
                                        if (frameCount > 1)
                                                return true;
                                }
                        }                       
 
-                       return false; 
+                       return false;           
                }
 
                public static void StopAnimate (Image img, EventHandler onFrameChangeHandler)
                {
                        if (img == null)
-                               throw new System.NullReferenceException ("Object reference not set to an instance of an object.");
-                       //Console.WriteLine ("Stopping animation");
-                       //MessageBox.Show ("Stopping animation");
-                       if (isAnimating) {
-                               isAnimating = false;
-                               thread.Abort ();
-                               //Thread.CurrentThread.Join ();
-                               //Console.WriteLine ("Thread Joined");
-                               //MessageBox.Show ("Thread Joined");
-                       }
-                       
+                               throw new System.NullReferenceException ("Object reference not set to an instance of an object.");                      
+
+                       if (ht.ContainsKey (img)) {
+                               AnimateEventArgs evtArgs = (AnimateEventArgs) ht [img];
+                               evtArgs.RunThread.Abort ();
+                               ht.Remove (img);
+                       }                               
                }
 
-               [MonoTODO ("Implement")]
                public static void UpdateFrames ()
                {
-                       throw new NotImplementedException (); 
+                       foreach (Image img in ht.Keys) {
+                               UpdateFrames (img);
+                       }
                }
                
-               [MonoTODO ("Implement")]
                public static void UpdateFrames (Image img)
                {
-                       /* Not sure as to what else needs to be done here.
-                         I have updated the frame thats what i can think of
-                         It surely requires something else also, as my application
-                         shows only a static image */
-
-                       throw new NotImplementedException();
-               }       
-
-               // The callback method must match the signature of the\r
-               // callback delegate.\r
-               //\r
-               static void ResultCallback(int activeFrameCount) \r
-               {\r
-                       activeFrame = activeFrameCount;\r
-               }\r
+                       if (img == null)
+                               throw new System.NullReferenceException ("Object reference not set to an instance of an object.");
 
+                       if (ht.ContainsKey (img)){
+                               //Need a way to get the delay during animation
+                               AnimateEventArgs evtArgs = (AnimateEventArgs) ht [img];
+                               if (evtArgs.ActiveFrameCount < evtArgs.FrameCount-1){
+                                       evtArgs.ActiveFrameCount ++;
+                                       img.SelectActiveFrame (FrameDimension.Time, evtArgs.ActiveFrameCount);
+                               } 
+                               else
+                                       evtArgs.ActiveFrameCount = 0;
+                               ht [img] = evtArgs;
+                       }                       
+               }
        }
 
-       // Delegate that defines the signature for the callback method.\r
-       //\r
-       delegate void ActiveFrameCountCallBack(int lineCount);\r
-
        class WorkerThread
        {
-               private Image image;
-               private int activeFrameCount;
-               private int frameCount;
-               private ActiveFrameCountCallBack afc;\r
+               EventHandler frameChangeHandler;
+               AnimateEventArgs animateEventArgs;
+               int delay;
                                
-               public WorkerThread(Image img, ActiveFrameCountCallBack afCount)
+               public WorkerThread (EventHandler frmChgHandler, AnimateEventArgs aniEvtArgs, int delay)
                {
-                       //Console.WriteLine ("Worker Thread Constructor");
-                       //MessageBox.Show ("Worker Thread Constructor");
-                       image = img;                    
-                       frameCount = img.GetFrameCount (FrameDimension.Time);
-                       afc = afCount;
+                       frameChangeHandler = frmChgHandler;
+                       animateEventArgs = aniEvtArgs;
+                       this.delay = delay;
                }
     
                public void LoopHandler()
                {
-                       try
-                       {
-                               //Console.WriteLine ("Came in loop handler");
-                               //MessageBox.Show ("Came in loop handler");
-                               while (true)
-                               {
-                                       //Need a way to get the delay during animation
-                                       Thread.Sleep (100);
-                                       activeFrameCount++;
-                                       if (activeFrameCount > frameCount)
-                                               activeFrameCount = 0;
-                                       if (afc != null)\r
-                                               afc (activeFrameCount);\r
-
-                               }
-                               //Console.WriteLine ("Exiting loop handler");
-                               //MessageBox.Show ("Exiting loop handler");
-                       }
-                       catch(ThreadAbortException tae)
-                       { 
-                               //lets not bother ourselves with tae
-                               //it will be thrown anyway
-                       }
-                       catch(Exception er)
-                       {
-                               throw er;
+                       try {
+                               while (true) {
+                                       Thread.Sleep (delay);
+                                       frameChangeHandler (null, animateEventArgs);
+                               }                               
+                       } catch (ThreadAbortException) { 
+                               Thread.ResetAbort (); // we're going to finish anyway
                        }
-
                }
        }
 }
+