├── .gitattributes ├── .gitignore ├── .travis.yml ├── Bin └── Transitions │ ├── Transitions.dll │ └── Transitions.pdb ├── Downloads ├── TransitionsCode_1_2.zip ├── TransitionsLibrary_1_2.zip └── TransitionsSample_1_2.zip ├── LICENSE.txt ├── NuGet ├── dot-net-transitions.1.2.1.0.nupkg ├── dot-net-transitions.1.2.1.0.nuspec ├── dot-net-transitions.1.2.2.0.nupkg └── dot-net-transitions.1.2.2.0.nuspec ├── README.md ├── TestSample ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── KittenPuppyControl.Designer.cs ├── KittenPuppyControl.cs ├── KittenPuppyControl.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── kitten.jpg │ └── puppy.jpg ├── RippleControl.Designer.cs ├── RippleControl.cs ├── RippleControl.resx ├── TestSample.csproj └── app.config ├── Transitions.sln └── Transitions ├── IManagedType.cs ├── ITransitionType.cs ├── ManagedType_Color.cs ├── ManagedType_Double.cs ├── ManagedType_Float.cs ├── ManagedType_Int.cs ├── ManagedType_String.cs ├── Properties └── AssemblyInfo.cs ├── Transition.cs ├── TransitionChain.cs ├── TransitionElement.cs ├── TransitionManager.cs ├── TransitionType_Acceleration.cs ├── TransitionType_Bounce.cs ├── TransitionType_CriticalDamping.cs ├── TransitionType_Deceleration.cs ├── TransitionType_EaseInEaseOut.cs ├── TransitionType_Flash.cs ├── TransitionType_Linear.cs ├── TransitionType_ThrowAndCatch.cs ├── TransitionType_UserDefined.cs ├── Transitions.csproj ├── Transitions.csproj.user └── Utility.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Dot Net Transitions - project specific. 3 | ################# 4 | 5 | .svn/ 6 | Deploy/ 7 | 8 | NuGet/Build/ 9 | Bin/TestSample/ 10 | 11 | 12 | ################# 13 | ## Eclipse 14 | ################# 15 | 16 | *.pydevproject 17 | .project 18 | .metadata 19 | tmp/ 20 | *.tmp 21 | *.bak 22 | *.swp 23 | *~.nib 24 | local.properties 25 | .classpath 26 | .settings/ 27 | .loadpath 28 | 29 | # External tool builders 30 | .externalToolBuilders/ 31 | 32 | # Locally stored "Eclipse launch configurations" 33 | *.launch 34 | 35 | # CDT-specific 36 | .cproject 37 | 38 | # PDT-specific 39 | .buildpath 40 | 41 | 42 | ################# 43 | ## Visual Studio 44 | ################# 45 | 46 | ## Ignore Visual Studio temporary files, build results, and 47 | ## files generated by popular Visual Studio add-ons. 48 | 49 | # User-specific files 50 | *.suo 51 | *.user 52 | *.sln.docstates 53 | /.vs 54 | # Build results 55 | 56 | [Dd]ebug/ 57 | x64/ 58 | build/ 59 | [Oo]bj/ 60 | 61 | # MSTest test Results 62 | [Tt]est[Rr]esult*/ 63 | [Bb]uild[Ll]og.* 64 | 65 | *_i.c 66 | *_p.c 67 | *.ilk 68 | *.meta 69 | *.obj 70 | *.pch 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.log 86 | *.scc 87 | 88 | # Visual C++ cache files 89 | ipch/ 90 | *.aps 91 | *.ncb 92 | *.opensdf 93 | *.sdf 94 | *.cachefile 95 | 96 | # Visual Studio profiler 97 | *.psess 98 | *.vsp 99 | *.vspx 100 | 101 | # Guidance Automation Toolkit 102 | *.gpState 103 | 104 | # ReSharper is a .NET coding add-in 105 | _ReSharper*/ 106 | *.[Rr]e[Ss]harper 107 | 108 | # TeamCity is a build add-in 109 | _TeamCity* 110 | 111 | # DotCover is a Code Coverage Tool 112 | *.dotCover 113 | 114 | # NCrunch 115 | *.ncrunch* 116 | .*crunch*.local.xml 117 | 118 | # Installshield output folder 119 | [Ee]xpress/ 120 | 121 | # DocProject is a documentation generator add-in 122 | DocProject/buildhelp/ 123 | DocProject/Help/*.HxT 124 | DocProject/Help/*.HxC 125 | DocProject/Help/*.hhc 126 | DocProject/Help/*.hhk 127 | DocProject/Help/*.hhp 128 | DocProject/Help/Html2 129 | DocProject/Help/html 130 | 131 | # Click-Once directory 132 | publish/ 133 | 134 | # Publish Web Output 135 | *.Publish.xml 136 | *.pubxml 137 | 138 | # NuGet Packages Directory 139 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 140 | #packages/ 141 | 142 | # Windows Azure Build Output 143 | csx 144 | *.build.csdef 145 | 146 | # Windows Store app package directory 147 | AppPackages/ 148 | 149 | # Others 150 | sql/ 151 | *.Cache 152 | ClientBin/ 153 | [Ss]tyle[Cc]op.* 154 | ~$* 155 | *~ 156 | *.dbmdl 157 | *.[Pp]ublish.xml 158 | *.pfx 159 | *.publishsettings 160 | 161 | # RIA/Silverlight projects 162 | Generated_Code/ 163 | 164 | # Backup & report files from converting an old project file to a newer 165 | # Visual Studio version. Backup files are not needed, because we have git ;-) 166 | _UpgradeReport_Files/ 167 | Backup*/ 168 | UpgradeLog*.XML 169 | UpgradeLog*.htm 170 | 171 | # SQL Server files 172 | App_Data/*.mdf 173 | App_Data/*.ldf 174 | 175 | ############# 176 | ## Windows detritus 177 | ############# 178 | 179 | # Windows image file caches 180 | Thumbs.db 181 | ehthumbs.db 182 | 183 | # Folder config file 184 | Desktop.ini 185 | 186 | # Recycle Bin used on file shares 187 | $RECYCLE.BIN/ 188 | 189 | # Mac crap 190 | .DS_Store 191 | 192 | 193 | ############# 194 | ## Python 195 | ############# 196 | 197 | *.py[co] 198 | 199 | # Packages 200 | *.egg 201 | *.egg-info 202 | dist/ 203 | build/ 204 | eggs/ 205 | parts/ 206 | var/ 207 | sdist/ 208 | develop-eggs/ 209 | .installed.cfg 210 | 211 | # Installer logs 212 | pip-log.txt 213 | 214 | # Unit test / coverage reports 215 | .coverage 216 | .tox 217 | 218 | #Translations 219 | *.mo 220 | 221 | #Mr Developer 222 | .mr.developer.cfg 223 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | solution: Transitions.sln -------------------------------------------------------------------------------- /Bin/Transitions/Transitions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/Bin/Transitions/Transitions.dll -------------------------------------------------------------------------------- /Bin/Transitions/Transitions.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/Bin/Transitions/Transitions.pdb -------------------------------------------------------------------------------- /Downloads/TransitionsCode_1_2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/Downloads/TransitionsCode_1_2.zip -------------------------------------------------------------------------------- /Downloads/TransitionsLibrary_1_2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/Downloads/TransitionsLibrary_1_2.zip -------------------------------------------------------------------------------- /Downloads/TransitionsSample_1_2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/Downloads/TransitionsSample_1_2.zip -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2009 Richard S. Shepherd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NuGet/dot-net-transitions.1.2.1.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/NuGet/dot-net-transitions.1.2.1.0.nupkg -------------------------------------------------------------------------------- /NuGet/dot-net-transitions.1.2.1.0.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dot-net-transitions 5 | https://github.com/UweKeim/dot-net-transitions 6 | 1.2.1.0 7 | dot-net-transitions 8 | Uwe Keim 9 | 10 | false 11 | A library for animated UI transitions for .NET. 12 | A library for animated UI transitions for .NET. 13 | http://i.imgur.com/l5hbo5s.png 14 | en-US 15 | winforms, transition, windows forms, transitions 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /NuGet/dot-net-transitions.1.2.2.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/NuGet/dot-net-transitions.1.2.2.0.nupkg -------------------------------------------------------------------------------- /NuGet/dot-net-transitions.1.2.2.0.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dot-net-transitions 5 | https://github.com/UweKeim/dot-net-transitions 6 | 1.2.2.0 7 | dot-net-transitions 8 | Uwe Keim 9 | 10 | false 11 | A library for animated UI transitions for .NET. 12 | A library for animated UI transitions for .NET. 13 | http://i.imgur.com/l5hbo5s.png 14 | en-US 15 | winforms, transition, windows forms, transitions 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dotnet Transitions 2 | 3 | A library for animated UI transitions for .NET. 4 | 5 | [![Build state](https://travis-ci.org/UweKeim/dot-net-transitions.svg?branch=master)](https://travis-ci.org/UweKeim/dot-net-transitions "Travis CI build status") 6 | 7 | ## Overview 8 | 9 | The Transitions library lets you create animated transitions of any properties of user-interface elements for .NET. It provides an easy way to perform UI animations in .NET in a similar way to the Core Animation library for Apple and the iPhone. 10 | 11 | The Transitions library is built with Visual Studio 2008 but targets version 2 of the .NET runtime, so it can be used with projects built with VS2005. 12 | 13 | ## Downloads 14 | 15 | - [**Get it on NuGet**](https://www.nuget.org/packages/dot-net-transitions/) 16 | - [Download latest DLL](https://github.com/UweKeim/dot-net-transitions/blob/master/Bin/Transitions/Transitions.dll?raw=true) 17 | - [Download sample 1.2](https://github.com/UweKeim/dot-net-transitions/blob/master/Downloads/TransitionsSample_1_2.zip?raw=true) 18 | - [Download code 1.2](https://github.com/UweKeim/dot-net-transitions/blob/master/Downloads/TransitionsCode_1_2.zip?raw=true) 19 | 20 | ## Getting started 21 | 22 | You can animate a single property of an object with a single line of code like this: 23 | 24 | ```csharp 25 | Transition.run(this, "BackColor", Color.Red, new TransitionType_Linear(1000)); 26 | ``` 27 | 28 | If this code is in a Form class, it animates the background color from its initial color to red over the course of 1000ms. 29 | 30 | You can animate multiple properties (maybe across multiple objects) simultaneously with code like this: 31 | 32 | ```csharp 33 | Transition t = new Transition(new TransitionType_EaseInEaseOut(2000)); 34 | t.add(pictureBox1, "Left", 300); 35 | t.add(pictureBox1, "Top", 200); 36 | t.run(); 37 | ``` 38 | 39 | This animates the movement of pictureBox1 from its initial location to (300, 200) over the course of 2000ms. 40 | 41 | ## Coding with Transitions 42 | 43 | The TestSample project (which is part of the code download) demonstrates a number of different transitions. It is fairly well commented, and can act as a tutorial to help get you started. 44 | 45 | For more information on how to code with the Transitions library see the coding reference. 46 | 47 | ## Version History 48 | 49 | Transitions is currently at version 1.2. See the VersionHistory page for details of previous version. 50 | 51 | ## Acknowledgements 52 | 53 | Thanks to Maxim Gready for writing the critical-damping transition-type. 54 | 55 | © 2009 Richard S. Shepherd. 56 | 57 | 2015-07-16, Uwe Keim: I've copied this repository from [Google Code](https://code.google.com/p/dot-net-transitions/) to save it from disappearing when Google Code shuts down. 58 | -------------------------------------------------------------------------------- /TestSample/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace TestSample 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.cmdBounceMe = new System.Windows.Forms.Button(); 32 | this.cmdFlashMe = new System.Windows.Forms.Button(); 33 | this.cmdRipple = new System.Windows.Forms.Button(); 34 | this.cmdDropAndBounce = new System.Windows.Forms.Button(); 35 | this.cmdThrowAndCatch = new System.Windows.Forms.Button(); 36 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 37 | this.lblTextTransition2 = new System.Windows.Forms.Label(); 38 | this.lblTextTransition1 = new System.Windows.Forms.Label(); 39 | this.cmdTextTransition = new System.Windows.Forms.Button(); 40 | this.gbBounce = new System.Windows.Forms.GroupBox(); 41 | this.gbThrowAndCatch = new System.Windows.Forms.GroupBox(); 42 | this.cmdSwap = new System.Windows.Forms.Button(); 43 | this.ctrlChangeFormColor = new System.Windows.Forms.Button(); 44 | this.gbRipple = new System.Windows.Forms.GroupBox(); 45 | this.gbFlash = new System.Windows.Forms.GroupBox(); 46 | this.gbDropAndBounce = new System.Windows.Forms.GroupBox(); 47 | this.cmdMore = new System.Windows.Forms.Button(); 48 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 49 | this.cmdSwapPictures = new System.Windows.Forms.Button(); 50 | this.ctrlPictures = new TestSample.KittenPuppyControl(); 51 | this.ctrlRipple = new TestSample.RippleControl(); 52 | this.groupBox1.SuspendLayout(); 53 | this.gbBounce.SuspendLayout(); 54 | this.gbThrowAndCatch.SuspendLayout(); 55 | this.gbRipple.SuspendLayout(); 56 | this.gbFlash.SuspendLayout(); 57 | this.gbDropAndBounce.SuspendLayout(); 58 | this.groupBox2.SuspendLayout(); 59 | this.SuspendLayout(); 60 | // 61 | // cmdBounceMe 62 | // 63 | this.cmdBounceMe.Anchor = System.Windows.Forms.AnchorStyles.Top; 64 | this.cmdBounceMe.BackColor = System.Drawing.SystemColors.ButtonFace; 65 | this.cmdBounceMe.Location = new System.Drawing.Point(6, 19); 66 | this.cmdBounceMe.Name = "cmdBounceMe"; 67 | this.cmdBounceMe.Size = new System.Drawing.Size(199, 34); 68 | this.cmdBounceMe.TabIndex = 5; 69 | this.cmdBounceMe.Text = "Bounce Me!"; 70 | this.cmdBounceMe.UseVisualStyleBackColor = false; 71 | this.cmdBounceMe.Click += new System.EventHandler(this.cmdBounceMe_Click); 72 | // 73 | // cmdFlashMe 74 | // 75 | this.cmdFlashMe.BackColor = System.Drawing.SystemColors.ButtonFace; 76 | this.cmdFlashMe.Location = new System.Drawing.Point(6, 19); 77 | this.cmdFlashMe.Name = "cmdFlashMe"; 78 | this.cmdFlashMe.Size = new System.Drawing.Size(193, 37); 79 | this.cmdFlashMe.TabIndex = 6; 80 | this.cmdFlashMe.Text = "Flash Me!"; 81 | this.cmdFlashMe.UseVisualStyleBackColor = false; 82 | this.cmdFlashMe.Click += new System.EventHandler(this.cmdFlashMe_Click); 83 | // 84 | // cmdRipple 85 | // 86 | this.cmdRipple.Location = new System.Drawing.Point(6, 19); 87 | this.cmdRipple.Name = "cmdRipple"; 88 | this.cmdRipple.Size = new System.Drawing.Size(193, 37); 89 | this.cmdRipple.TabIndex = 9; 90 | this.cmdRipple.Text = "Ripple"; 91 | this.cmdRipple.UseVisualStyleBackColor = true; 92 | this.cmdRipple.Click += new System.EventHandler(this.cmdRipple_Click); 93 | // 94 | // cmdDropAndBounce 95 | // 96 | this.cmdDropAndBounce.Location = new System.Drawing.Point(6, 19); 97 | this.cmdDropAndBounce.Name = "cmdDropAndBounce"; 98 | this.cmdDropAndBounce.Size = new System.Drawing.Size(193, 37); 99 | this.cmdDropAndBounce.TabIndex = 10; 100 | this.cmdDropAndBounce.Text = "Drop and bounce"; 101 | this.cmdDropAndBounce.UseVisualStyleBackColor = true; 102 | this.cmdDropAndBounce.Click += new System.EventHandler(this.cmdDropAndBounce_Click); 103 | // 104 | // cmdThrowAndCatch 105 | // 106 | this.cmdThrowAndCatch.Anchor = System.Windows.Forms.AnchorStyles.Bottom; 107 | this.cmdThrowAndCatch.Location = new System.Drawing.Point(6, 475); 108 | this.cmdThrowAndCatch.Name = "cmdThrowAndCatch"; 109 | this.cmdThrowAndCatch.Size = new System.Drawing.Size(199, 34); 110 | this.cmdThrowAndCatch.TabIndex = 11; 111 | this.cmdThrowAndCatch.Text = "Throw and Catch"; 112 | this.cmdThrowAndCatch.UseVisualStyleBackColor = true; 113 | this.cmdThrowAndCatch.Click += new System.EventHandler(this.cmdThrowAndCatch_Click); 114 | // 115 | // groupBox1 116 | // 117 | this.groupBox1.Controls.Add(this.lblTextTransition2); 118 | this.groupBox1.Controls.Add(this.lblTextTransition1); 119 | this.groupBox1.Controls.Add(this.cmdTextTransition); 120 | this.groupBox1.Location = new System.Drawing.Point(229, 397); 121 | this.groupBox1.Name = "groupBox1"; 122 | this.groupBox1.Size = new System.Drawing.Size(211, 101); 123 | this.groupBox1.TabIndex = 13; 124 | this.groupBox1.TabStop = false; 125 | this.groupBox1.Text = "Text transition"; 126 | // 127 | // lblTextTransition2 128 | // 129 | this.lblTextTransition2.AutoSize = true; 130 | this.lblTextTransition2.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 131 | this.lblTextTransition2.ForeColor = System.Drawing.Color.Crimson; 132 | this.lblTextTransition2.Location = new System.Drawing.Point(7, 75); 133 | this.lblTextTransition2.Name = "lblTextTransition2"; 134 | this.lblTextTransition2.Size = new System.Drawing.Size(192, 16); 135 | this.lblTextTransition2.TabIndex = 15; 136 | this.lblTextTransition2.Text = "A longer piece of text."; 137 | // 138 | // lblTextTransition1 139 | // 140 | this.lblTextTransition1.AutoSize = true; 141 | this.lblTextTransition1.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 142 | this.lblTextTransition1.ForeColor = System.Drawing.Color.Blue; 143 | this.lblTextTransition1.Location = new System.Drawing.Point(6, 59); 144 | this.lblTextTransition1.Name = "lblTextTransition1"; 145 | this.lblTextTransition1.Size = new System.Drawing.Size(112, 16); 146 | this.lblTextTransition1.TabIndex = 14; 147 | this.lblTextTransition1.Text = "Hello, World!"; 148 | // 149 | // cmdTextTransition 150 | // 151 | this.cmdTextTransition.Location = new System.Drawing.Point(6, 19); 152 | this.cmdTextTransition.Name = "cmdTextTransition"; 153 | this.cmdTextTransition.Size = new System.Drawing.Size(193, 37); 154 | this.cmdTextTransition.TabIndex = 13; 155 | this.cmdTextTransition.Text = "Text Transition"; 156 | this.cmdTextTransition.UseVisualStyleBackColor = true; 157 | this.cmdTextTransition.Click += new System.EventHandler(this.cmdTextTransition_Click); 158 | // 159 | // gbBounce 160 | // 161 | this.gbBounce.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 162 | | System.Windows.Forms.AnchorStyles.Left))); 163 | this.gbBounce.Controls.Add(this.cmdBounceMe); 164 | this.gbBounce.Location = new System.Drawing.Point(12, 50); 165 | this.gbBounce.Name = "gbBounce"; 166 | this.gbBounce.Size = new System.Drawing.Size(211, 515); 167 | this.gbBounce.TabIndex = 14; 168 | this.gbBounce.TabStop = false; 169 | this.gbBounce.Text = "Bounce"; 170 | // 171 | // gbThrowAndCatch 172 | // 173 | this.gbThrowAndCatch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 174 | | System.Windows.Forms.AnchorStyles.Left))); 175 | this.gbThrowAndCatch.Controls.Add(this.cmdThrowAndCatch); 176 | this.gbThrowAndCatch.Location = new System.Drawing.Point(-211, 50); 177 | this.gbThrowAndCatch.Name = "gbThrowAndCatch"; 178 | this.gbThrowAndCatch.Size = new System.Drawing.Size(211, 515); 179 | this.gbThrowAndCatch.TabIndex = 15; 180 | this.gbThrowAndCatch.TabStop = false; 181 | this.gbThrowAndCatch.Text = "Throw and Catch"; 182 | // 183 | // cmdSwap 184 | // 185 | this.cmdSwap.Location = new System.Drawing.Point(12, 10); 186 | this.cmdSwap.Name = "cmdSwap"; 187 | this.cmdSwap.Size = new System.Drawing.Size(83, 34); 188 | this.cmdSwap.TabIndex = 16; 189 | this.cmdSwap.Text = "<< Swap"; 190 | this.cmdSwap.UseVisualStyleBackColor = true; 191 | this.cmdSwap.Click += new System.EventHandler(this.cmdSwap_Click); 192 | // 193 | // ctrlChangeFormColor 194 | // 195 | this.ctrlChangeFormColor.Location = new System.Drawing.Point(101, 10); 196 | this.ctrlChangeFormColor.Name = "ctrlChangeFormColor"; 197 | this.ctrlChangeFormColor.Size = new System.Drawing.Size(122, 34); 198 | this.ctrlChangeFormColor.TabIndex = 17; 199 | this.ctrlChangeFormColor.Text = "Change Form Color"; 200 | this.ctrlChangeFormColor.UseVisualStyleBackColor = true; 201 | this.ctrlChangeFormColor.Click += new System.EventHandler(this.ctrlChangeFormColor_Click); 202 | // 203 | // gbRipple 204 | // 205 | this.gbRipple.Controls.Add(this.cmdRipple); 206 | this.gbRipple.Controls.Add(this.ctrlRipple); 207 | this.gbRipple.Location = new System.Drawing.Point(229, 50); 208 | this.gbRipple.Name = "gbRipple"; 209 | this.gbRipple.Size = new System.Drawing.Size(211, 211); 210 | this.gbRipple.TabIndex = 18; 211 | this.gbRipple.TabStop = false; 212 | this.gbRipple.Text = "Ripple"; 213 | // 214 | // gbFlash 215 | // 216 | this.gbFlash.Controls.Add(this.cmdFlashMe); 217 | this.gbFlash.Location = new System.Drawing.Point(229, 504); 218 | this.gbFlash.Name = "gbFlash"; 219 | this.gbFlash.Size = new System.Drawing.Size(211, 61); 220 | this.gbFlash.TabIndex = 19; 221 | this.gbFlash.TabStop = false; 222 | this.gbFlash.Text = "Flash the Button"; 223 | // 224 | // gbDropAndBounce 225 | // 226 | this.gbDropAndBounce.Controls.Add(this.cmdDropAndBounce); 227 | this.gbDropAndBounce.Location = new System.Drawing.Point(446, 50); 228 | this.gbDropAndBounce.Name = "gbDropAndBounce"; 229 | this.gbDropAndBounce.Size = new System.Drawing.Size(523, 515); 230 | this.gbDropAndBounce.TabIndex = 20; 231 | this.gbDropAndBounce.TabStop = false; 232 | this.gbDropAndBounce.Text = "Drop and Bounce"; 233 | // 234 | // cmdMore 235 | // 236 | this.cmdMore.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 237 | this.cmdMore.Location = new System.Drawing.Point(360, 10); 238 | this.cmdMore.Name = "cmdMore"; 239 | this.cmdMore.Size = new System.Drawing.Size(80, 34); 240 | this.cmdMore.TabIndex = 21; 241 | this.cmdMore.Text = "More >>"; 242 | this.cmdMore.UseVisualStyleBackColor = true; 243 | this.cmdMore.Click += new System.EventHandler(this.cmdMore_Click); 244 | // 245 | // groupBox2 246 | // 247 | this.groupBox2.Controls.Add(this.cmdSwapPictures); 248 | this.groupBox2.Controls.Add(this.ctrlPictures); 249 | this.groupBox2.Location = new System.Drawing.Point(229, 267); 250 | this.groupBox2.Name = "groupBox2"; 251 | this.groupBox2.Size = new System.Drawing.Size(211, 124); 252 | this.groupBox2.TabIndex = 22; 253 | this.groupBox2.TabStop = false; 254 | this.groupBox2.Text = "Picture transition"; 255 | // 256 | // cmdSwapPictures 257 | // 258 | this.cmdSwapPictures.Location = new System.Drawing.Point(10, 19); 259 | this.cmdSwapPictures.Name = "cmdSwapPictures"; 260 | this.cmdSwapPictures.Size = new System.Drawing.Size(73, 90); 261 | this.cmdSwapPictures.TabIndex = 1; 262 | this.cmdSwapPictures.Text = "Swap Pictures"; 263 | this.cmdSwapPictures.UseVisualStyleBackColor = true; 264 | this.cmdSwapPictures.Click += new System.EventHandler(this.cmdSwapPictures_Click); 265 | // 266 | // ctrlPictures 267 | // 268 | this.ctrlPictures.Location = new System.Drawing.Point(95, 19); 269 | this.ctrlPictures.Name = "ctrlPictures"; 270 | this.ctrlPictures.Size = new System.Drawing.Size(103, 90); 271 | this.ctrlPictures.TabIndex = 0; 272 | // 273 | // ctrlRipple 274 | // 275 | this.ctrlRipple.Location = new System.Drawing.Point(6, 62); 276 | this.ctrlRipple.Name = "ctrlRipple"; 277 | this.ctrlRipple.Size = new System.Drawing.Size(193, 140); 278 | this.ctrlRipple.TabIndex = 8; 279 | // 280 | // Form1 281 | // 282 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 283 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 284 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(220))))); 285 | this.ClientSize = new System.Drawing.Size(445, 571); 286 | this.Controls.Add(this.groupBox2); 287 | this.Controls.Add(this.cmdMore); 288 | this.Controls.Add(this.gbDropAndBounce); 289 | this.Controls.Add(this.gbFlash); 290 | this.Controls.Add(this.gbRipple); 291 | this.Controls.Add(this.ctrlChangeFormColor); 292 | this.Controls.Add(this.cmdSwap); 293 | this.Controls.Add(this.gbThrowAndCatch); 294 | this.Controls.Add(this.gbBounce); 295 | this.Controls.Add(this.groupBox1); 296 | this.Name = "Form1"; 297 | this.Text = "Transitions sample"; 298 | this.groupBox1.ResumeLayout(false); 299 | this.groupBox1.PerformLayout(); 300 | this.gbBounce.ResumeLayout(false); 301 | this.gbThrowAndCatch.ResumeLayout(false); 302 | this.gbRipple.ResumeLayout(false); 303 | this.gbFlash.ResumeLayout(false); 304 | this.gbDropAndBounce.ResumeLayout(false); 305 | this.groupBox2.ResumeLayout(false); 306 | this.ResumeLayout(false); 307 | 308 | } 309 | 310 | #endregion 311 | 312 | private System.Windows.Forms.Button cmdBounceMe; 313 | private System.Windows.Forms.Button cmdFlashMe; 314 | private RippleControl ctrlRipple; 315 | private System.Windows.Forms.Button cmdRipple; 316 | private System.Windows.Forms.Button cmdDropAndBounce; 317 | private System.Windows.Forms.Button cmdThrowAndCatch; 318 | private System.Windows.Forms.GroupBox groupBox1; 319 | private System.Windows.Forms.Label lblTextTransition2; 320 | private System.Windows.Forms.Label lblTextTransition1; 321 | private System.Windows.Forms.Button cmdTextTransition; 322 | private System.Windows.Forms.GroupBox gbBounce; 323 | private System.Windows.Forms.GroupBox gbThrowAndCatch; 324 | private System.Windows.Forms.Button cmdSwap; 325 | private System.Windows.Forms.Button ctrlChangeFormColor; 326 | private System.Windows.Forms.GroupBox gbRipple; 327 | private System.Windows.Forms.GroupBox gbFlash; 328 | private System.Windows.Forms.GroupBox gbDropAndBounce; 329 | private System.Windows.Forms.Button cmdMore; 330 | private System.Windows.Forms.GroupBox groupBox2; 331 | private System.Windows.Forms.Button cmdSwapPictures; 332 | private KittenPuppyControl ctrlPictures; 333 | } 334 | } 335 | 336 | -------------------------------------------------------------------------------- /TestSample/Form1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using Transitions; 4 | using System.Drawing; 5 | using System.Collections.Generic; 6 | 7 | namespace TestSample 8 | { 9 | /// 10 | /// This form demonstrates a number of animated transitions using the Transitions 11 | /// library. Each event handler (form-load, button click) demonstrates a different 12 | /// transition. 13 | /// 14 | public partial class Form1 : Form 15 | { 16 | #region Public methods 17 | 18 | /// 19 | /// Constructor. 20 | /// 21 | public Form1() 22 | { 23 | InitializeComponent(); 24 | } 25 | 26 | #endregion 27 | 28 | #region Form event handlers 29 | 30 | /// 31 | /// Called when the "Swap" button is pressed. 32 | /// 33 | private void cmdSwap_Click(object sender, EventArgs e) 34 | { 35 | // We swap over the group-boxes that show the "Bounce" and 36 | // "Throw and Catch" transitions. The active one is animated 37 | // left off the screen and the inactive one is animated right 38 | // onto the screen... 39 | 40 | // We work out which box is currently on screen and 41 | // which is off screen... 42 | Control ctrlOnScreen, ctrlOffScreen; 43 | if (gbBounce.Left == GROUP_BOX_LEFT) 44 | { 45 | ctrlOnScreen = gbBounce; 46 | ctrlOffScreen = gbThrowAndCatch; 47 | } 48 | else 49 | { 50 | ctrlOnScreen = gbThrowAndCatch; 51 | ctrlOffScreen = gbBounce; 52 | } 53 | ctrlOnScreen.SendToBack(); 54 | ctrlOffScreen.BringToFront(); 55 | 56 | // We create a transition to animate the two boxes simultaneously. One is 57 | // animated onto the screen, the other off the screen. 58 | 59 | // The ease-in-ease-out transition acclerates the rate of change for the 60 | // first half of the animation, and decelerates during the second half. 61 | 62 | Transition t = new Transition(new TransitionType_EaseInEaseOut(1000)); 63 | t.add(ctrlOnScreen, "Left", -1 * ctrlOnScreen.Width); 64 | t.add(ctrlOffScreen, "Left", GROUP_BOX_LEFT); 65 | t.run(); 66 | } 67 | 68 | /// 69 | /// Called when the "Bounce Me!" button is pressed. 70 | /// 71 | private void cmdBounceMe_Click(object sender, EventArgs e) 72 | { 73 | // We bounce the button down to the bottom of the group box it is in, and 74 | // back up again. 75 | 76 | // The Bounce transition accelerates the property to its destination value 77 | // (as if with gravity) and decelerates it back to its original value (as 78 | // if against gravity). 79 | 80 | int iDestination = gbBounce.Height - cmdBounceMe.Height; 81 | Transition.run(cmdBounceMe, "Top", iDestination, new TransitionType_Bounce(1500)); 82 | } 83 | 84 | /// 85 | /// Called when the "Throw and Catch" button is pressed. 86 | /// 87 | private void cmdThrowAndCatch_Click(object sender, EventArgs e) 88 | { 89 | // The button is 'thrown' up to the top of the group-box it is in 90 | // and then falls back down again. 91 | 92 | // The throw-and-catch transition starts the animation at a high rate and 93 | // decelerates to zero (as if against gravity) at the destination value. It 94 | // then accelerates the value (as if with gravity) back to the original value. 95 | 96 | Transition.run(cmdThrowAndCatch, "Top", 12, new TransitionType_ThrowAndCatch(1500)); 97 | } 98 | 99 | /// 100 | /// Called when the "Flash Me!" button is pressed. 101 | /// 102 | private void cmdFlashMe_Click(object sender, EventArgs e) 103 | { 104 | // The Flash transition animates the property to the destination value 105 | // and back again. You specify how many flashes to show and the length 106 | // of each flash... 107 | Transition.run(cmdFlashMe, "BackColor", Color.Pink, new TransitionType_Flash(2, 300)); 108 | } 109 | 110 | /// 111 | /// Called when the "Ripple" button is pressed. 112 | /// 113 | private void cmdRipple_Click(object sender, EventArgs e) 114 | { 115 | // The ripple is handled by the RippleControl user-control. 116 | // This performs 100 simultaneous animations to create the 117 | // ripple effect... 118 | ctrlRipple.ripple(); 119 | } 120 | 121 | /// 122 | /// Called when the "Swap Pictures" button is pressed. 123 | /// 124 | private void cmdSwapPictures_Click(object sender, EventArgs e) 125 | { 126 | // The transition is handled by the KittenPuppyControl... 127 | ctrlPictures.transitionPictures(); 128 | } 129 | 130 | /// 131 | /// Called when the "Text Transition" button is pressed. 132 | /// 133 | private void cmdTextTransition_Click(object sender, EventArgs e) 134 | { 135 | // We transition four properties simulataneously here: 136 | // - The two labels' text is changed. 137 | // - The two labels' colors are changed. 138 | 139 | // We work out the new text and colors to transition to... 140 | string strText1, strText2; 141 | Color color1, color2; 142 | if (lblTextTransition1.Text == STRING_SHORT) 143 | { 144 | strText1 = STRING_LONG; 145 | color1 = Color.Red; 146 | strText2 = STRING_SHORT; 147 | color2 = Color.Blue; 148 | } 149 | else 150 | { 151 | strText1 = STRING_SHORT; 152 | color1 = Color.Blue; 153 | strText2 = STRING_LONG; 154 | color2 = Color.Red; 155 | } 156 | 157 | // We create a transition to animate all four properties at the same time... 158 | Transition t = new Transition(new TransitionType_Linear(1000)); 159 | t.add(lblTextTransition1, "Text", strText1); 160 | t.add(lblTextTransition1, "ForeColor", color1); 161 | t.add(lblTextTransition2, "Text", strText2); 162 | t.add(lblTextTransition2, "ForeColor", color2); 163 | t.run(); 164 | } 165 | 166 | /// 167 | /// Called when the "Change Form Color" button is pressed. 168 | /// 169 | private void ctrlChangeFormColor_Click(object sender, EventArgs e) 170 | { 171 | // We alternate the form's background color... 172 | Color destination = (BackColor == BACKCOLOR_PINK) ? BACK_COLOR_YELLOW : BACKCOLOR_PINK; 173 | Transition.run(this, "BackColor", destination, new TransitionType_Linear(1000)); 174 | } 175 | 176 | /// 177 | /// Called when the "More" or "Less" button is pressed. 178 | /// 179 | private void cmdMore_Click(object sender, EventArgs e) 180 | { 181 | // We either show more screen or less screen depending on the current state. 182 | // We find out whether we need to make the screen wider or narrower... 183 | int iFormWidth; 184 | if (cmdMore.Text == "More >>") 185 | { 186 | iFormWidth = 984; 187 | cmdMore.Text = "<< Less"; 188 | } 189 | else 190 | { 191 | iFormWidth = 452; 192 | cmdMore.Text = "More >>"; 193 | } 194 | 195 | // We animate it with an ease-in-ease-out transition... 196 | Transition.run(this, "Width", iFormWidth, new TransitionType_EaseInEaseOut(1000)); 197 | } 198 | 199 | /// 200 | /// Called when the "Drop and Bounce" button is pressed. 201 | /// 202 | private void cmdDropAndBounce_Click(object sender, EventArgs e) 203 | { 204 | // We animate the button to drop and bounce twice with bounces 205 | // of diminishing heights. While it does this, it is moving to 206 | // the right, as if thrown to the right. When this animation has 207 | // finished, the button moves back to its original position. 208 | 209 | // The diminishing-bounce is not one of the built-in transition types, 210 | // so we create it here as a user-defined transition type. You define 211 | // these as a collection of TransitionElements. These define how far the 212 | // animated properties will have moved at various times, and how the 213 | // transition between different elements is to be done. 214 | 215 | // So in the example below: 216 | // 0% - 40% The button acclerates to 100% distance (i.e. the bottom of the screen) 217 | // 40% - 65% The button bounces back (decelerating) to 70% distance. 218 | // etc... 219 | 220 | IList elements = new List(); 221 | elements.Add(new TransitionElement(40, 100, InterpolationMethod.Accleration)); 222 | elements.Add(new TransitionElement(65, 70, InterpolationMethod.Deceleration)); 223 | elements.Add(new TransitionElement(80, 100, InterpolationMethod.Accleration)); 224 | elements.Add(new TransitionElement(90, 92, InterpolationMethod.Deceleration)); 225 | elements.Add(new TransitionElement(100, 100, InterpolationMethod.Accleration)); 226 | 227 | int iDestination = gbDropAndBounce.Height - cmdDropAndBounce.Height - 10; 228 | Transition.run(cmdDropAndBounce, "Top", iDestination, new TransitionType_UserDefined(elements, 2000)); 229 | 230 | // The transition above just animates the vertical bounce of the button, but not 231 | // the left-to-right movement. This can't use the same transition, as otherwise the 232 | // left-to-right movement would bounce back and forth. 233 | 234 | // We run the left-to-right animation as a second, simultaneous transition. 235 | // In fact, we run a transition chain, with the animation of the button back 236 | // to its starting position as the second item in the chain. The second 237 | // transition starts as soon as the first is complete... 238 | 239 | Transition t1 = new Transition(new TransitionType_Linear(2000)); 240 | t1.add(cmdDropAndBounce, "Left", cmdDropAndBounce.Left + 400); 241 | 242 | Transition t2 = new Transition(new TransitionType_EaseInEaseOut(2000)); 243 | t2.add(cmdDropAndBounce, "Top", 19); 244 | t2.add(cmdDropAndBounce, "Left", 6); 245 | 246 | Transition.runChain(t1, t2); 247 | } 248 | 249 | #endregion 250 | 251 | #region Private data 252 | 253 | // Colors used by the change-form-color transition... 254 | private Color BACKCOLOR_PINK = Color.FromArgb(255, 220, 220); 255 | private Color BACK_COLOR_YELLOW = Color.FromArgb(255, 255, 220); 256 | 257 | // The left point of the 'bounce' and 'throw-and-catch' group boxes... 258 | private const int GROUP_BOX_LEFT = 12; 259 | 260 | // Strings used for the text transition... 261 | private const string STRING_SHORT = "Hello, World!"; 262 | private const string STRING_LONG = "A longer piece of text."; 263 | 264 | #endregion 265 | 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /TestSample/Form1.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /TestSample/KittenPuppyControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace TestSample 2 | { 3 | partial class KittenPuppyControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.ctrlPuppy = new System.Windows.Forms.PictureBox(); 32 | this.ctrlKitten = new System.Windows.Forms.PictureBox(); 33 | ((System.ComponentModel.ISupportInitialize)(this.ctrlPuppy)).BeginInit(); 34 | ((System.ComponentModel.ISupportInitialize)(this.ctrlKitten)).BeginInit(); 35 | this.SuspendLayout(); 36 | // 37 | // ctrlPuppy 38 | // 39 | this.ctrlPuppy.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 40 | | System.Windows.Forms.AnchorStyles.Left) 41 | | System.Windows.Forms.AnchorStyles.Right))); 42 | this.ctrlPuppy.Image = global::TestSample.Properties.Resources.puppy; 43 | this.ctrlPuppy.Location = new System.Drawing.Point(0, 0); 44 | this.ctrlPuppy.Name = "ctrlPuppy"; 45 | this.ctrlPuppy.Size = new System.Drawing.Size(150, 150); 46 | this.ctrlPuppy.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 47 | this.ctrlPuppy.TabIndex = 1; 48 | this.ctrlPuppy.TabStop = false; 49 | // 50 | // ctrlKitten 51 | // 52 | this.ctrlKitten.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 53 | | System.Windows.Forms.AnchorStyles.Left) 54 | | System.Windows.Forms.AnchorStyles.Right))); 55 | this.ctrlKitten.Image = global::TestSample.Properties.Resources.kitten; 56 | this.ctrlKitten.Location = new System.Drawing.Point(0, 0); 57 | this.ctrlKitten.Name = "ctrlKitten"; 58 | this.ctrlKitten.Size = new System.Drawing.Size(150, 150); 59 | this.ctrlKitten.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 60 | this.ctrlKitten.TabIndex = 0; 61 | this.ctrlKitten.TabStop = false; 62 | // 63 | // KittenPuppyControl 64 | // 65 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 66 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 67 | this.Controls.Add(this.ctrlPuppy); 68 | this.Controls.Add(this.ctrlKitten); 69 | this.Name = "KittenPuppyControl"; 70 | ((System.ComponentModel.ISupportInitialize)(this.ctrlPuppy)).EndInit(); 71 | ((System.ComponentModel.ISupportInitialize)(this.ctrlKitten)).EndInit(); 72 | this.ResumeLayout(false); 73 | 74 | } 75 | 76 | #endregion 77 | 78 | private System.Windows.Forms.PictureBox ctrlKitten; 79 | private System.Windows.Forms.PictureBox ctrlPuppy; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /TestSample/KittenPuppyControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using Transitions; 4 | 5 | namespace TestSample 6 | { 7 | /// 8 | /// This is a simple user-control that hosts two picture-boxes (one showing 9 | /// a kitten and the other showing a puppy). The transitionPictures method 10 | /// performs a random animated transition between the two pictures. 11 | /// 12 | public partial class KittenPuppyControl : UserControl 13 | { 14 | #region Public methods 15 | 16 | /// 17 | /// Constructor. 18 | /// 19 | public KittenPuppyControl() 20 | { 21 | InitializeComponent(); 22 | m_ActivePicture = ctrlPuppy; 23 | m_InactivePicture = ctrlKitten; 24 | } 25 | 26 | /// 27 | /// Performs a random tarnsition between the two pictures. 28 | /// 29 | public void transitionPictures() 30 | { 31 | // We randomly choose where the current image is going to 32 | // slide off to (and where we are going to slide the inactive 33 | // image in from)... 34 | int iDestinationLeft = (m_Random.Next(2) == 0) ? Width : -Width; 35 | int iDestinationTop = (m_Random.Next(3) - 1) * Height; 36 | 37 | // We move the inactive image to this location... 38 | SuspendLayout(); 39 | m_InactivePicture.Top = iDestinationTop; 40 | m_InactivePicture.Left = iDestinationLeft; 41 | m_InactivePicture.BringToFront(); 42 | ResumeLayout(); 43 | 44 | // We perform the transition which moves the active image off the 45 | // screen, and the inactive one onto the screen... 46 | Transition t = new Transition(new TransitionType_EaseInEaseOut(1000)); 47 | t.add(m_InactivePicture, "Left", 0); 48 | t.add(m_InactivePicture, "Top", 0); 49 | t.add(m_ActivePicture, "Left", iDestinationLeft); 50 | t.add(m_ActivePicture, "Top", iDestinationTop); 51 | t.run(); 52 | 53 | // We swap over which image is active and inactive for next time 54 | // the function is called... 55 | PictureBox tmp = m_ActivePicture; 56 | m_ActivePicture = m_InactivePicture; 57 | m_InactivePicture = tmp; 58 | } 59 | 60 | #endregion 61 | 62 | #region Private data 63 | 64 | private PictureBox m_ActivePicture = null; 65 | private PictureBox m_InactivePicture = null; 66 | private Random m_Random = new Random(); 67 | 68 | #endregion 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /TestSample/KittenPuppyControl.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /TestSample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | 5 | namespace TestSample 6 | { 7 | static class Program 8 | { 9 | /// 10 | /// The main entry point for the application. 11 | /// 12 | [STAThread] 13 | static void Main() 14 | { 15 | Application.EnableVisualStyles(); 16 | Application.SetCompatibleTextRenderingDefault(false); 17 | Application.Run(new Form1()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TestSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f267124e-d001-429b-8247-f32e1acc1b2f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestSample/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TestSample.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TestSample.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap kitten { 67 | get { 68 | object obj = ResourceManager.GetObject("kitten", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap puppy { 77 | get { 78 | object obj = ResourceManager.GetObject("puppy", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /TestSample/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\puppy.jpg;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\kitten.jpg;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | -------------------------------------------------------------------------------- /TestSample/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TestSample.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TestSample/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestSample/Resources/kitten.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/TestSample/Resources/kitten.jpg -------------------------------------------------------------------------------- /TestSample/Resources/puppy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UweKeim/dot-net-transitions/fc8bbcfca2a31b4cc787340f442fddc57c4e62aa/TestSample/Resources/puppy.jpg -------------------------------------------------------------------------------- /TestSample/RippleControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace TestSample 2 | { 3 | partial class RippleControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // RippleControl 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.Name = "RippleControl"; 38 | this.Load += new System.EventHandler(this.RippleControl_Load); 39 | this.ResumeLayout(false); 40 | 41 | } 42 | 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TestSample/RippleControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using Transitions; 9 | 10 | namespace TestSample 11 | { 12 | /// 13 | /// This control shows a color-rippling effect when you call its ripple() 14 | /// method. It holds a grid of 10x10 label controls with an initial white 15 | /// background color. The ripple method uses a separate transition on each 16 | /// label to move it to pink and back again. 17 | /// 18 | /// The code to set up the labels (in the Load method) is a bit complicated, 19 | /// but the ripple transition itself is very simple. 20 | /// 21 | public partial class RippleControl : UserControl 22 | { 23 | #region Public methods 24 | 25 | /// 26 | /// Constructor. 27 | /// 28 | public RippleControl() 29 | { 30 | InitializeComponent(); 31 | } 32 | 33 | /// 34 | /// Starts the ripple effect. 35 | /// 36 | public void ripple() 37 | { 38 | // We run a transition on each of the labels shown on the control. 39 | // This means that we will be running 100 simulataneous transitions... 40 | foreach (CellInfo info in m_CellInfos) 41 | { 42 | Transition.run(info.Control, "BackColor", Color.Pink, new TransitionType_Flash(1, info.TransitionInterval)); 43 | } 44 | } 45 | 46 | #endregion 47 | 48 | #region Private functions 49 | 50 | /// 51 | /// Called when the control is first loaded. 52 | /// 53 | private void RippleControl_Load(object sender, EventArgs e) 54 | { 55 | double dCellWidth = Width / 10.0; 56 | double dCellHeight = Height / 10.0; 57 | 58 | // We set up a 10x10 grid of labels... 59 | double dTop = 0; 60 | for (int iRow = 0; iRow <10; ++iRow) 61 | { 62 | double dLeft = 0; 63 | double dBottom = dTop + dCellHeight; 64 | 65 | for (int iCol = 0; iCol < 10; ++iCol) 66 | { 67 | // We work out the size of this label... 68 | double dRight = dLeft + dCellWidth; 69 | int iLeft = (int)dLeft; 70 | int iTop = (int)dTop; 71 | int iRight = (int)dRight; 72 | int iBottom = (int)dBottom; 73 | int iWidth = iRight - iLeft; 74 | int iHeight = iBottom - iTop; 75 | 76 | // We create the label... 77 | Label label = new Label(); 78 | label.Left = iLeft; 79 | label.Top = iTop; 80 | label.Width = iWidth; 81 | label.Height = iHeight; 82 | label.BackColor = Color.White; 83 | 84 | // And add it to the control... 85 | Controls.Add(label); 86 | 87 | // We work out a transition time for it, and store the information 88 | // to use when we do the ripple effect... 89 | int iTransitionInterval = iRow * 100 + iCol * 100; 90 | m_CellInfos.Add(new CellInfo { Control = label, TransitionInterval = iTransitionInterval }); 91 | 92 | // The left for the next column is the right for this one... 93 | dLeft = dRight; 94 | } 95 | 96 | // The top of the next row is the bottom of this one... 97 | dTop = dBottom; 98 | } 99 | } 100 | 101 | #endregion 102 | 103 | #region Private data 104 | 105 | // A small class that holds information about one of the labels on the control. 106 | private class CellInfo 107 | { 108 | public Control Control { get; set; } 109 | public int TransitionInterval { get; set; } 110 | } 111 | 112 | // A collection of cell-infos, i.e. info on each label on the control... 113 | private IList m_CellInfos = new List(); 114 | 115 | #endregion 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /TestSample/RippleControl.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /TestSample/TestSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4} 9 | WinExe 10 | Properties 11 | TestSample 12 | TestSample 13 | v2.0 14 | 512 15 | 16 | 17 | 18 | 19 | 3.5 20 | publish\ 21 | true 22 | Disk 23 | false 24 | Foreground 25 | 7 26 | Days 27 | false 28 | false 29 | true 30 | 0 31 | 1.0.0.%2a 32 | false 33 | false 34 | true 35 | 36 | 37 | 38 | pdbonly 39 | true 40 | ..\Bin\TestSample\ 41 | TRACE 42 | prompt 43 | 4 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Form 56 | 57 | 58 | Form1.cs 59 | 60 | 61 | UserControl 62 | 63 | 64 | KittenPuppyControl.cs 65 | 66 | 67 | 68 | 69 | Form1.cs 70 | 71 | 72 | KittenPuppyControl.cs 73 | 74 | 75 | ResXFileCodeGenerator 76 | Resources.Designer.cs 77 | Designer 78 | 79 | 80 | RippleControl.cs 81 | 82 | 83 | True 84 | Resources.resx 85 | True 86 | 87 | 88 | 89 | SettingsSingleFileGenerator 90 | Settings.Designer.cs 91 | 92 | 93 | True 94 | Settings.settings 95 | True 96 | 97 | 98 | UserControl 99 | 100 | 101 | RippleControl.cs 102 | 103 | 104 | 105 | 106 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0} 107 | Transitions 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | False 119 | .NET Framework 3.5 SP1 120 | true 121 | 122 | 123 | 124 | 131 | -------------------------------------------------------------------------------- /TestSample/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Transitions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22823.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Transitions", "Transitions\Transitions.csproj", "{95CDE461-0720-4C3B-B5E1-D188391FB7C0}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSample", "TestSample\TestSample.csproj", "{E5B3CEE3-973B-4400-BF81-62EEC02625F4}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Release|Any CPU.Build.0 = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(SolutionProperties) = preSolution 21 | HideSolutionNode = FALSE 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /Transitions/IManagedType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | 6 | namespace Transitions 7 | { 8 | /// 9 | /// Interface for all types we can perform transitions on. 10 | /// Each type (e.g. int, double, Color) that we can perform a transition on 11 | /// needs to have its own class that implements this interface. These classes 12 | /// tell the transition system how to act on objects of that type. 13 | /// 14 | internal interface IManagedType 15 | { 16 | /// 17 | /// Returns the Type that the instance is managing. 18 | /// 19 | Type getManagedType(); 20 | 21 | /// 22 | /// Returns a deep copy of the object passed in. (In particular this is 23 | /// needed for types that are objects.) 24 | /// 25 | object copy(object o); 26 | 27 | /// 28 | /// Returns an object holding the value between the start and end corresponding 29 | /// to the percentage passed in. (Note: the percentage can be less than 0% or 30 | /// greater than 100%.) 31 | /// 32 | object getIntermediateValue(object start, object end, double dPercentage); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Transitions/ITransitionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | public interface ITransitionType 8 | { 9 | /// 10 | /// Called by the Transition framework when its timer ticks to pass in the 11 | /// time (in ms) since the transition started. 12 | /// 13 | /// You should return (in an out parameter) the percentage movement towards 14 | /// the destination value for the time passed in. Note: this does not need to 15 | /// be a smooth transition from 0% to 100%. You can overshoot with values 16 | /// greater than 100% or undershoot if you need to (for example, to have some 17 | /// form of "elasticity"). 18 | /// 19 | /// The percentage should be returned as (for example) 0.1 for 10%. 20 | /// 21 | /// You should return (in an out parameter) whether the transition has completed. 22 | /// (This may not be at the same time as the percentage has moved to 100%.) 23 | /// 24 | void onTimer(int iTime, out double dPercentage, out bool bCompleted); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Transitions/ManagedType_Color.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Drawing; 5 | 6 | namespace Transitions 7 | { 8 | /// 9 | /// Class that manages transitions for Color properties. For these we 10 | /// need to transition the R, G, B and A sub-properties independently. 11 | /// 12 | internal class ManagedType_Color : IManagedType 13 | { 14 | #region IManagedType Members 15 | 16 | /// 17 | /// Returns the type we are managing. 18 | /// 19 | public Type getManagedType() 20 | { 21 | return typeof(Color); 22 | } 23 | 24 | /// 25 | /// Returns a copy of the color object passed in. 26 | /// 27 | public object copy(object o) 28 | { 29 | Color c = (Color)o; 30 | Color result = Color.FromArgb(c.ToArgb()); 31 | return result; 32 | } 33 | 34 | /// 35 | /// Creates an intermediate value for the colors depending on the percentage passed in. 36 | /// 37 | public object getIntermediateValue(object start, object end, double dPercentage) 38 | { 39 | Color startColor = (Color)start; 40 | Color endColor = (Color)end; 41 | 42 | // We interpolate the R, G, B and A components separately... 43 | int iStart_R = startColor.R; 44 | int iStart_G = startColor.G; 45 | int iStart_B = startColor.B; 46 | int iStart_A = startColor.A; 47 | 48 | int iEnd_R = endColor.R; 49 | int iEnd_G = endColor.G; 50 | int iEnd_B = endColor.B; 51 | int iEnd_A = endColor.A; 52 | 53 | int new_R = Utility.interpolate(iStart_R, iEnd_R, dPercentage); 54 | int new_G = Utility.interpolate(iStart_G, iEnd_G, dPercentage); 55 | int new_B = Utility.interpolate(iStart_B, iEnd_B, dPercentage); 56 | int new_A = Utility.interpolate(iStart_A, iEnd_A, dPercentage); 57 | 58 | return Color.FromArgb(new_A, new_R, new_G, new_B); 59 | } 60 | 61 | #endregion 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Transitions/ManagedType_Double.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages transitions for double properties. 9 | /// 10 | internal class ManagedType_Double : IManagedType 11 | { 12 | #region IManagedType Members 13 | 14 | /// 15 | /// Returns the type managed by this class. 16 | /// 17 | public Type getManagedType() 18 | { 19 | return typeof(double); 20 | } 21 | 22 | /// 23 | /// Returns a copy of the double passed in. 24 | /// 25 | public object copy(object o) 26 | { 27 | double d = (double)o; 28 | return d; 29 | } 30 | 31 | /// 32 | /// Returns the value between start and end for the percentage passed in. 33 | /// 34 | public object getIntermediateValue(object start, object end, double dPercentage) 35 | { 36 | double dStart = (double)start; 37 | double dEnd = (double)end; 38 | return Utility.interpolate(dStart, dEnd, dPercentage); 39 | } 40 | 41 | #endregion 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Transitions/ManagedType_Float.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | internal class ManagedType_Float : IManagedType 8 | { 9 | #region IManagedType Members 10 | 11 | /// 12 | /// Returns the type we're managing. 13 | /// 14 | public Type getManagedType() 15 | { 16 | return typeof(float); 17 | } 18 | 19 | /// 20 | /// Returns a copy of the float passed in. 21 | /// 22 | public object copy(object o) 23 | { 24 | float f = (float)o; 25 | return f; 26 | } 27 | 28 | /// 29 | /// Returns the interpolated value for the percentage passed in. 30 | /// 31 | public object getIntermediateValue(object start, object end, double dPercentage) 32 | { 33 | float fStart = (float)start; 34 | float fEnd = (float)end; 35 | return Utility.interpolate(fStart, fEnd, dPercentage); 36 | } 37 | 38 | #endregion 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Transitions/ManagedType_Int.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages transitions for int properties. 9 | /// 10 | internal class ManagedType_Int : IManagedType 11 | { 12 | #region IManagedType Members 13 | 14 | /// 15 | /// Returns the type we are managing. 16 | /// 17 | public Type getManagedType() 18 | { 19 | return typeof(int); 20 | } 21 | 22 | /// 23 | /// Returns a copy of the int passed in. 24 | /// 25 | public object copy(object o) 26 | { 27 | int value = (int)o; 28 | return value; 29 | } 30 | 31 | /// 32 | /// Returns the value between the start and end for the percentage passed in. 33 | /// 34 | public object getIntermediateValue(object start, object end, double dPercentage) 35 | { 36 | int iStart = (int)start; 37 | int iEnd = (int)end; 38 | return Utility.interpolate(iStart, iEnd, dPercentage); 39 | } 40 | 41 | #endregion 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Transitions/ManagedType_String.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages transitions for strings. This doesn't make as much sense as transitions 9 | /// on other types, but I like the way it looks! 10 | /// 11 | internal class ManagedType_String : IManagedType 12 | { 13 | #region IManagedType Members 14 | 15 | /// 16 | /// Returns the type we're managing. 17 | /// 18 | public Type getManagedType() 19 | { 20 | return typeof(string); 21 | } 22 | 23 | /// 24 | /// Returns a copy of the string passed in. 25 | /// 26 | public object copy(object o) 27 | { 28 | string s = (string)o; 29 | return new string(s.ToCharArray()); 30 | } 31 | 32 | /// 33 | /// Returns an "interpolated" string. 34 | /// 35 | public object getIntermediateValue(object start, object end, double dPercentage) 36 | { 37 | string strStart = (string)start; 38 | string strEnd = (string)end; 39 | 40 | // We find the length of the interpolated string... 41 | int iStartLength = strStart.Length; 42 | int iEndLength = strEnd.Length; 43 | int iLength = Utility.interpolate(iStartLength, iEndLength, dPercentage); 44 | char[] result = new char[iLength]; 45 | 46 | // Now we assign the letters of the results by interpolating the 47 | // letters from the start and end strings... 48 | for (int i = 0; i < iLength; ++i) 49 | { 50 | // We get the start and end chars at this position... 51 | char cStart = 'a'; 52 | if(i < iStartLength) 53 | { 54 | cStart = strStart[i]; 55 | } 56 | char cEnd = 'a'; 57 | if(i < iEndLength) 58 | { 59 | cEnd = strEnd[i]; 60 | } 61 | 62 | // We interpolate them... 63 | char cInterpolated; 64 | if (cEnd == ' ') 65 | { 66 | // If the end character is a space we just show a space 67 | // regardless of interpolation. It looks better this way... 68 | cInterpolated = ' '; 69 | } 70 | else 71 | { 72 | // The end character is not a space, so we interpolate... 73 | int iStart = Convert.ToInt32(cStart); 74 | int iEnd = Convert.ToInt32(cEnd); 75 | int iInterpolated = Utility.interpolate(iStart, iEnd, dPercentage); 76 | cInterpolated = Convert.ToChar(iInterpolated); 77 | } 78 | 79 | result[i] = cInterpolated; 80 | } 81 | 82 | return new string(result); 83 | } 84 | 85 | #endregion 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Transitions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Transitions")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Transitions")] 13 | [assembly: AssemblyCopyright("Copyright © 2009")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("419d7efe-7b63-4286-8730-546f530ec91a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.2.2.0")] 36 | [assembly: AssemblyFileVersion("1.2.2.0")] 37 | -------------------------------------------------------------------------------- /Transitions/Transition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | using System.Timers; 6 | using System.Diagnostics; 7 | using System.Windows.Forms; 8 | using System.ComponentModel; 9 | 10 | namespace Transitions 11 | { 12 | /// 13 | /// Lets you perform animated transitions of properties on arbitrary objects. These 14 | /// will often be transitions of UI properties, for example an animated fade-in of 15 | /// a UI object, or an animated move of a UI object from one position to another. 16 | /// 17 | /// Each transition can simulataneously change multiple properties, including properties 18 | /// across multiple objects. 19 | /// 20 | /// Example transition 21 | /// ------------------ 22 | /// a. Transition t = new Transition(new TransitionMethod_Linear(500)); 23 | /// b. t.add(form1, "Width", 500); 24 | /// c. t.add(form1, "BackColor", Color.Red); 25 | /// d. t.run(); 26 | /// 27 | /// Line a: Creates a new transition. You specify the transition method. 28 | /// 29 | /// Lines b. and c: Set the destination values of the properties you are animating. 30 | /// 31 | /// Line d: Starts the transition. 32 | /// 33 | /// Transition methods 34 | /// ------------------ 35 | /// TransitionMethod objects specify how the transition is made. Examples include 36 | /// linear transition, ease-in-ease-out and so on. Different transition methods may 37 | /// need different parameters. 38 | /// 39 | /// 40 | public class Transition 41 | { 42 | #region Registration 43 | 44 | /// 45 | /// You should register all managed-types here. 46 | /// 47 | static Transition() 48 | { 49 | registerType(new ManagedType_Int()); 50 | registerType(new ManagedType_Float()); 51 | registerType(new ManagedType_Double()); 52 | registerType(new ManagedType_Color()); 53 | registerType(new ManagedType_String()); 54 | } 55 | 56 | #endregion 57 | 58 | #region Events 59 | 60 | /// 61 | /// Args passed with the TransitionCompletedEvent. 62 | /// 63 | public class Args : EventArgs 64 | { 65 | } 66 | 67 | /// 68 | /// Event raised when the transition hass completed. 69 | /// 70 | public event EventHandler TransitionCompletedEvent; 71 | 72 | #endregion 73 | 74 | #region Public static methods 75 | 76 | /// 77 | /// Creates and immediately runs a transition on the property passed in. 78 | /// 79 | public static void run(object target, string strPropertyName, object destinationValue, ITransitionType transitionMethod) 80 | { 81 | Transition t = new Transition(transitionMethod); 82 | t.add(target, strPropertyName, destinationValue); 83 | t.run(); 84 | } 85 | 86 | /// 87 | /// Sets the property passed in to the initial value passed in, then creates and 88 | /// immediately runs a transition on it. 89 | /// 90 | public static void run(object target, string strPropertyName, object initialValue, object destinationValue, ITransitionType transitionMethod) 91 | { 92 | Utility.setValue(target, strPropertyName, initialValue); 93 | run(target, strPropertyName, destinationValue, transitionMethod); 94 | } 95 | 96 | /// 97 | /// Creates a TransitionChain and runs it. 98 | /// 99 | public static void runChain(params Transition[] transitions) 100 | { 101 | TransitionChain chain = new TransitionChain(transitions); 102 | } 103 | 104 | #endregion 105 | 106 | #region Public methods 107 | 108 | /// 109 | /// Constructor. You pass in the object that holds the properties 110 | /// that you are performing transitions on. 111 | /// 112 | public Transition(ITransitionType transitionMethod) 113 | { 114 | m_TransitionMethod = transitionMethod; 115 | } 116 | 117 | /// 118 | /// Adds a property that should be animated as part of this transition. 119 | /// 120 | public void add(object target, string strPropertyName, object destinationValue) 121 | { 122 | // We get the property info... 123 | Type targetType = target.GetType(); 124 | PropertyInfo propertyInfo = targetType.GetProperty(strPropertyName); 125 | if (propertyInfo == null) 126 | { 127 | throw new Exception("Object: " + target.ToString() + " does not have the property: " + strPropertyName); 128 | } 129 | 130 | // We check that we support the property type... 131 | Type propertyType = propertyInfo.PropertyType; 132 | if (m_mapManagedTypes.ContainsKey(propertyType) == false) 133 | { 134 | throw new Exception("Transition does not handle properties of type: " + propertyType.ToString()); 135 | } 136 | 137 | // We can only transition properties that are both getable and setable... 138 | if (propertyInfo.CanRead == false || propertyInfo.CanWrite == false) 139 | { 140 | throw new Exception("Property is not both getable and setable: " + strPropertyName); 141 | } 142 | 143 | IManagedType managedType = m_mapManagedTypes[propertyType]; 144 | 145 | // We can manage this type, so we store the information for the 146 | // transition of this property... 147 | TransitionedPropertyInfo info = new TransitionedPropertyInfo(); 148 | info.endValue = destinationValue; 149 | info.target = target; 150 | info.propertyInfo = propertyInfo; 151 | info.managedType = managedType; 152 | 153 | lock (m_Lock) 154 | { 155 | m_listTransitionedProperties.Add(info); 156 | } 157 | } 158 | 159 | /// 160 | /// Starts the transition. 161 | /// 162 | public void run() 163 | { 164 | // We find the current start values for the properties we 165 | // are animating... 166 | foreach (TransitionedPropertyInfo info in m_listTransitionedProperties) 167 | { 168 | object value = info.propertyInfo.GetValue(info.target, null); 169 | info.startValue = info.managedType.copy(value); 170 | } 171 | 172 | // We start the stopwatch. We use this when the timer ticks to measure 173 | // how long the transition has been runnning for... 174 | m_Stopwatch.Reset(); 175 | m_Stopwatch.Start(); 176 | 177 | // We register this transition with the transition manager... 178 | TransitionManager.getInstance().register(this); 179 | } 180 | 181 | #endregion 182 | 183 | #region Internal methods 184 | 185 | /// 186 | /// Property that returns a list of information about each property managed 187 | /// by this transition. 188 | /// 189 | internal IList TransitionedProperties 190 | { 191 | get { return m_listTransitionedProperties; } 192 | } 193 | 194 | /// 195 | /// We remove the property with the info passed in from the transition. 196 | /// 197 | internal void removeProperty(TransitionedPropertyInfo info) 198 | { 199 | lock (m_Lock) 200 | { 201 | m_listTransitionedProperties.Remove(info); 202 | } 203 | } 204 | 205 | /// 206 | /// Called when the transition timer ticks. 207 | /// 208 | internal void onTimer() 209 | { 210 | // When the timer ticks we: 211 | // a. Find the elapsed time since the transition started. 212 | // b. Work out the percentage movement for the properties we're managing. 213 | // c. Find the actual values of each property, and set them. 214 | 215 | // a. 216 | int iElapsedTime = (int)m_Stopwatch.ElapsedMilliseconds; 217 | 218 | // b. 219 | double dPercentage; 220 | bool bCompleted; 221 | m_TransitionMethod.onTimer(iElapsedTime, out dPercentage, out bCompleted); 222 | 223 | // We take a copy of the list of properties we are transitioning, as 224 | // they can be changed by another thread while this method is running... 225 | IList listTransitionedProperties = new List(); 226 | lock (m_Lock) 227 | { 228 | foreach (TransitionedPropertyInfo info in m_listTransitionedProperties) 229 | { 230 | listTransitionedProperties.Add(info.copy()); 231 | } 232 | } 233 | 234 | // c. 235 | foreach (TransitionedPropertyInfo info in listTransitionedProperties) 236 | { 237 | // We get the current value for this property... 238 | object value = info.managedType.getIntermediateValue(info.startValue, info.endValue, dPercentage); 239 | 240 | // We set it... 241 | PropertyUpdateArgs args = new PropertyUpdateArgs(info.target, info.propertyInfo, value); 242 | setProperty(this, args); 243 | } 244 | 245 | // Has the transition completed? 246 | if (bCompleted == true) 247 | { 248 | // We stop the stopwatch and the timer... 249 | m_Stopwatch.Stop(); 250 | 251 | // We raise an event to notify any observers that the transition has completed... 252 | Utility.raiseEvent(TransitionCompletedEvent, this, new Args()); 253 | } 254 | } 255 | 256 | #endregion 257 | 258 | #region Private functions 259 | 260 | /// 261 | /// Sets a property on the object passed in to the value passed in. This method 262 | /// invokes itself on the GUI thread if the property is being invoked on a GUI 263 | /// object. 264 | /// 265 | private void setProperty(object sender, PropertyUpdateArgs args) 266 | { 267 | try 268 | { 269 | // If the target is a control that has been disposed then we don't 270 | // try to update its properties. This can happen if the control is 271 | // on a form that has been closed while the transition is running... 272 | if (isDisposed(args.target) == true) 273 | { 274 | return; 275 | } 276 | 277 | ISynchronizeInvoke invokeTarget = args.target as ISynchronizeInvoke; 278 | if (invokeTarget != null && invokeTarget.InvokeRequired) 279 | { 280 | // There is some history behind the next two lines, which is worth 281 | // going through to understand why they are the way they are. 282 | 283 | // Initially we used BeginInvoke without the subsequent WaitOne for 284 | // the result. A transition could involve a large number of updates 285 | // to a property, and as this call was asynchronous it would send a 286 | // large number of updates to the UI thread. These would queue up at 287 | // the GUI thread and mean that the UI could be some way behind where 288 | // the transition was. 289 | 290 | // The line was then changed to the blocking Invoke call instead. This 291 | // meant that the transition only proceded at the pace that the GUI 292 | // could process it, and the UI was not overloaded with "old" updates. 293 | 294 | // However, in some circumstances Invoke could block and lock up the 295 | // Transitions background thread. In particular, this can happen if the 296 | // control that we are trying to update is in the process of being 297 | // disposed - for example, it is on a form that is being closed. See 298 | // here for details: 299 | // http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/7d2c941a-0016-431a-abba-67c5d5dac6a5 300 | 301 | // To solve this, we use a combination of the two earlier approaches. 302 | // We use BeginInvoke as this does not block and lock up, even if the 303 | // underlying object is being disposed. But we do want to wait to give 304 | // the UI a chance to process the update. So what we do is to do the 305 | // asynchronous BeginInvoke, but then wait (with a short timeout) for 306 | // it to complete. 307 | IAsyncResult asyncResult = invokeTarget.BeginInvoke(new EventHandler(setProperty), new object[] { sender, args }); 308 | asyncResult.AsyncWaitHandle.WaitOne(50); 309 | } 310 | else 311 | { 312 | // We are on the correct thread, so we update the property... 313 | args.propertyInfo.SetValue(args.target, args.value, null); 314 | } 315 | } 316 | catch (Exception) 317 | { 318 | // We silently catch any exceptions. These could be things like 319 | // bounds exceptions when setting properties. 320 | } 321 | } 322 | 323 | /// 324 | /// Returns true if the object passed in is a Control and is disposed 325 | /// or in the process of disposing. (If this is the case, we don't want 326 | /// to make any changes to its properties.) 327 | /// 328 | private bool isDisposed(object target) 329 | { 330 | // Is the object passed in a Control? 331 | Control controlTarget = target as Control; 332 | if (controlTarget == null) 333 | { 334 | return false; 335 | } 336 | 337 | // Is it disposed or disposing? 338 | if (controlTarget.IsDisposed == true || controlTarget.Disposing) 339 | { 340 | return true; 341 | } 342 | else 343 | { 344 | return false; 345 | } 346 | } 347 | 348 | #endregion 349 | 350 | #region Private static functions 351 | 352 | /// 353 | /// Registers a transition-type. We hold them in a map. 354 | /// 355 | private static void registerType(IManagedType transitionType) 356 | { 357 | Type type = transitionType.getManagedType(); 358 | m_mapManagedTypes[type] = transitionType; 359 | } 360 | 361 | #endregion 362 | 363 | #region Private static data 364 | 365 | // A map of Type info to IManagedType objects. These are all the types that we 366 | // know how to perform transitions on... 367 | private static IDictionary m_mapManagedTypes = new Dictionary(); 368 | 369 | #endregion 370 | 371 | #region Private data 372 | 373 | // The transition method used by this transition... 374 | private ITransitionType m_TransitionMethod = null; 375 | 376 | // Holds information about one property on one taregt object that we are performing 377 | // a transition on... 378 | internal class TransitionedPropertyInfo 379 | { 380 | public object startValue; 381 | public object endValue; 382 | public object target; 383 | public PropertyInfo propertyInfo; 384 | public IManagedType managedType; 385 | 386 | public TransitionedPropertyInfo copy() 387 | { 388 | TransitionedPropertyInfo info = new TransitionedPropertyInfo(); 389 | info.startValue = startValue; 390 | info.endValue = endValue; 391 | info.target = target; 392 | info.propertyInfo = propertyInfo; 393 | info.managedType = managedType; 394 | return info; 395 | } 396 | } 397 | 398 | // The collection of properties that the current transition is animating... 399 | private IList m_listTransitionedProperties = new List(); 400 | 401 | // Helps us find the time interval from the time the transition starts to each timer tick... 402 | private Stopwatch m_Stopwatch = new Stopwatch(); 403 | 404 | // Event args used for the event we raise when updating a property... 405 | private class PropertyUpdateArgs : EventArgs 406 | { 407 | public PropertyUpdateArgs(object t, PropertyInfo pi, object v) 408 | { 409 | target = t; 410 | propertyInfo = pi; 411 | value = v; 412 | } 413 | public object target; 414 | public PropertyInfo propertyInfo; 415 | public object value; 416 | } 417 | 418 | // An object used to lock the list of transitioned properties, as it can be 419 | // accessed by multiple threads... 420 | private object m_Lock = new object(); 421 | 422 | #endregion 423 | } 424 | } 425 | -------------------------------------------------------------------------------- /Transitions/TransitionChain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | internal class TransitionChain 8 | { 9 | #region Public methods 10 | 11 | public TransitionChain(params Transition[] transitions) 12 | { 13 | // We store the list of transitions... 14 | foreach (Transition transition in transitions) 15 | { 16 | m_listTransitions.AddLast(transition); 17 | } 18 | 19 | // We start running them... 20 | runNextTransition(); 21 | } 22 | 23 | #endregion 24 | 25 | #region Private functions 26 | 27 | /// 28 | /// Runs the next transition in the list. 29 | /// 30 | private void runNextTransition() 31 | { 32 | if (m_listTransitions.Count == 0) 33 | { 34 | return; 35 | } 36 | 37 | // We find the next transition and run it. We also register 38 | // for its completed event, so that we can start the next transition 39 | // when this one completes... 40 | Transition nextTransition = m_listTransitions.First.Value; 41 | nextTransition.TransitionCompletedEvent += onTransitionCompleted; 42 | nextTransition.run(); 43 | } 44 | 45 | /// 46 | /// Called when the transition we have just run has completed. 47 | /// 48 | private void onTransitionCompleted(object sender, Transition.Args e) 49 | { 50 | // We unregister from the completed event... 51 | Transition transition = (Transition)sender; 52 | transition.TransitionCompletedEvent -= onTransitionCompleted; 53 | 54 | // We remove the completed transition from our collection, and 55 | // run the next one... 56 | m_listTransitions.RemoveFirst(); 57 | runNextTransition(); 58 | } 59 | 60 | #endregion 61 | 62 | #region Private data 63 | 64 | // The list of transitions in the chain... 65 | private LinkedList m_listTransitions = new LinkedList(); 66 | 67 | #endregion 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Transitions/TransitionElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | public enum InterpolationMethod 8 | { 9 | Linear, 10 | Accleration, 11 | Deceleration, 12 | EaseInEaseOut 13 | } 14 | 15 | public class TransitionElement 16 | { 17 | /// 18 | /// Constructor. 19 | /// 20 | public TransitionElement(double endTime, double endValue, InterpolationMethod interpolationMethod) 21 | { 22 | EndTime = endTime; 23 | EndValue = endValue; 24 | InterpolationMethod = interpolationMethod; 25 | } 26 | 27 | /// 28 | /// The percentage of elapsed time, expressed as (for example) 75 for 75%. 29 | /// 30 | public double EndTime { get; set; } 31 | 32 | /// 33 | /// The value of the animated properties at the EndTime. This is the percentage 34 | /// movement of the properties between their start and end values. This should 35 | /// be expressed as (for example) 75 for 75%. 36 | /// 37 | public double EndValue { get; set; } 38 | 39 | /// 40 | /// The interpolation method to use when moving between the previous value 41 | /// and the current one. 42 | /// 43 | public InterpolationMethod InterpolationMethod { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Transitions/TransitionManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Timers; 5 | 6 | namespace Transitions 7 | { 8 | /// 9 | /// This class is responsible for running transitions. It holds the timer that 10 | /// triggers transition animation. 11 | /// 12 | /// This class is a singleton. 13 | /// 14 | /// We manage the transition timer here so that we can have a single timer 15 | /// across all transitions. If each transition has its own timer, this creates 16 | /// one thread for each transition, and this can lead to too many threads in 17 | /// an application. 18 | /// 19 | /// This class essentially just manages the timer for the transitions. It calls 20 | /// back into the running transitions, which do the actual work of the transition. 21 | /// 22 | /// 23 | internal class TransitionManager 24 | { 25 | #region Public methods 26 | 27 | /// 28 | /// Singleton's getInstance method. 29 | /// 30 | public static TransitionManager getInstance() 31 | { 32 | if (m_Instance == null) 33 | { 34 | m_Instance = new TransitionManager(); 35 | } 36 | return m_Instance; 37 | } 38 | 39 | /// 40 | /// You register a transition with the manager here. This will start to run 41 | /// the transition as the manager's timer ticks. 42 | /// 43 | public void register(Transition transition) 44 | { 45 | lock (m_Lock) 46 | { 47 | // We check to see if the properties of this transition 48 | // are already being animated by any existing transitions... 49 | removeDuplicates(transition); 50 | 51 | // We add the transition to the collection we manage, and 52 | // observe it so that we know when it has completed... 53 | m_Transitions[transition] = true; 54 | transition.TransitionCompletedEvent += onTransitionCompleted; 55 | } 56 | } 57 | 58 | #endregion 59 | 60 | #region Private functions 61 | 62 | /// 63 | /// Checks if any existing transitions are acting on the same properties as the 64 | /// transition passed in. If so, we remove the duplicated properties from the 65 | /// older transitions. 66 | /// 67 | private void removeDuplicates(Transition transition) 68 | { 69 | // We look through the set of transitions we're currently managing... 70 | foreach (KeyValuePair pair in m_Transitions) 71 | { 72 | removeDuplicates(transition, pair.Key); 73 | } 74 | } 75 | 76 | /// 77 | /// Finds any properties in the old-transition that are also in the new one, 78 | /// and removes them from the old one. 79 | /// 80 | private void removeDuplicates(Transition newTransition, Transition oldTransition) 81 | { 82 | // Note: This checking might be a bit more efficient if it did the checking 83 | // with a set rather than looking through lists. That said, it is only done 84 | // when transitions are added (which isn't very often) rather than on the 85 | // timer, so I don't think this matters too much. 86 | 87 | // We get the list of properties for the old and new transitions... 88 | IList newProperties = newTransition.TransitionedProperties; 89 | IList oldProperties = oldTransition.TransitionedProperties; 90 | 91 | // We loop through the old properties backwards (as we may be removing 92 | // items from the list if we find a match)... 93 | for (int i = oldProperties.Count - 1; i >= 0; i--) 94 | { 95 | // We get one of the properties from the old transition... 96 | Transition.TransitionedPropertyInfo oldProperty = oldProperties[i]; 97 | 98 | // Is this property part of the new transition? 99 | foreach (Transition.TransitionedPropertyInfo newProperty in newProperties) 100 | { 101 | if (oldProperty.target == newProperty.target 102 | && 103 | oldProperty.propertyInfo == newProperty.propertyInfo) 104 | { 105 | // The old transition contains the same property as the new one, 106 | // so we remove it from the old transition... 107 | oldTransition.removeProperty(oldProperty); 108 | } 109 | } 110 | } 111 | } 112 | 113 | /// 114 | /// Private constructor (for singleton). 115 | /// 116 | private TransitionManager() 117 | { 118 | m_Timer = new Timer(15); 119 | m_Timer.Elapsed += onTimerElapsed; 120 | m_Timer.Enabled = true; 121 | } 122 | 123 | /// 124 | /// Called when the timer ticks. 125 | /// 126 | private void onTimerElapsed(object sender, ElapsedEventArgs e) 127 | { 128 | // We turn the timer off while we process the tick, in case the 129 | // actions take longer than the tick itself... 130 | if (m_Timer == null) 131 | { 132 | return; 133 | } 134 | m_Timer.Enabled = false; 135 | 136 | IList listTransitions; 137 | lock (m_Lock) 138 | { 139 | // We take a copy of the collection of transitions as elements 140 | // might be removed as we iterate through it... 141 | listTransitions = new List(); 142 | foreach (KeyValuePair pair in m_Transitions) 143 | { 144 | listTransitions.Add(pair.Key); 145 | } 146 | } 147 | 148 | // We tick the timer for each transition we're managing... 149 | foreach (Transition transition in listTransitions) 150 | { 151 | transition.onTimer(); 152 | } 153 | 154 | // We restart the timer... 155 | m_Timer.Enabled = true; 156 | } 157 | 158 | /// 159 | /// Called when a transition has completed. 160 | /// 161 | private void onTransitionCompleted(object sender, Transition.Args e) 162 | { 163 | // We stop observing the transition... 164 | Transition transition = (Transition)sender; 165 | transition.TransitionCompletedEvent -= onTransitionCompleted; 166 | 167 | // We remove the transition from the collection we're managing... 168 | lock (m_Lock) 169 | { 170 | m_Transitions.Remove(transition); 171 | } 172 | } 173 | 174 | #endregion 175 | 176 | #region Private data 177 | 178 | // The singleton instance... 179 | private static TransitionManager m_Instance = null; 180 | 181 | // The collection of transitions we're managing. (This should really be a set.) 182 | private IDictionary m_Transitions = new Dictionary(); 183 | 184 | // The timer that controls the transition animation... 185 | private Timer m_Timer = null; 186 | 187 | // An object to lock on. This class can be accessed by multiple threads: the 188 | // user thread can add new transitions; and the timerr thread can be animating 189 | // them. As they access the same collections, the methods need to be protected 190 | // by a lock... 191 | private object m_Lock = new object(); 192 | 193 | #endregion 194 | } 195 | } 196 | 197 | 198 | -------------------------------------------------------------------------------- /Transitions/TransitionType_Acceleration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages transitions under constant acceleration from a standing start. 9 | /// 10 | public class TransitionType_Acceleration : ITransitionType 11 | { 12 | #region Public methods 13 | 14 | /// 15 | /// Constructor. You pass in the time that the transition 16 | /// will take (in milliseconds). 17 | /// 18 | public TransitionType_Acceleration(int iTransitionTime) 19 | { 20 | if (iTransitionTime <= 0) 21 | { 22 | throw new Exception("Transition time must be greater than zero."); 23 | } 24 | m_dTransitionTime = iTransitionTime; 25 | } 26 | 27 | #endregion 28 | 29 | #region ITransitionMethod Members 30 | 31 | /// 32 | /// Works out the percentage completed given the time passed in. 33 | /// This uses the formula: 34 | /// s = ut + 1/2at^2 35 | /// The initial velocity is 0, and the acceleration to get to 1.0 36 | /// at t=1.0 is 2, so the formula just becomes: 37 | /// s = t^2 38 | /// 39 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 40 | { 41 | // We find the percentage time elapsed... 42 | double dElapsed = iTime / m_dTransitionTime; 43 | dPercentage = dElapsed * dElapsed; 44 | if (dElapsed >= 1.0) 45 | { 46 | dPercentage = 1.0; 47 | bCompleted = true; 48 | } 49 | else 50 | { 51 | bCompleted = false; 52 | } 53 | } 54 | 55 | #endregion 56 | 57 | #region Private data 58 | 59 | private double m_dTransitionTime = 0.0; 60 | 61 | #endregion 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Transitions/TransitionType_Bounce.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// This transition bounces the property to a destination value and back to the 9 | /// original value. It is accelerated to the destination and then decelerated back 10 | /// as if being dropped with gravity and bouncing back against gravity. 11 | /// 12 | public class TransitionType_Bounce : TransitionType_UserDefined 13 | { 14 | #region Public methods 15 | 16 | /// 17 | /// Constructor. You pass in the total time taken for the bounce. 18 | /// 19 | public TransitionType_Bounce(int iTransitionTime) 20 | { 21 | // We create a custom "user-defined" transition to do the work... 22 | IList elements = new List(); 23 | elements.Add(new TransitionElement(50, 100, InterpolationMethod.Accleration)); 24 | elements.Add(new TransitionElement(100, 0, InterpolationMethod.Deceleration)); 25 | base.setup(elements, iTransitionTime); 26 | } 27 | 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Transitions/TransitionType_CriticalDamping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// This transition animates with an exponential decay. This has a damping effect 9 | /// similar to the motion of a needle on an electomagnetically controlled dial. 10 | /// 11 | public class TransitionType_CriticalDamping : ITransitionType 12 | { 13 | #region Public methods 14 | 15 | /// 16 | /// Constructor. You pass in the time that the transition 17 | /// will take (in milliseconds). 18 | /// 19 | public TransitionType_CriticalDamping(int iTransitionTime) 20 | { 21 | if (iTransitionTime <= 0) 22 | { 23 | throw new Exception("Transition time must be greater than zero."); 24 | } 25 | m_dTransitionTime = iTransitionTime; 26 | } 27 | 28 | #endregion 29 | 30 | #region ITransitionMethod Members 31 | 32 | /// 33 | /// 34 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 35 | { 36 | // We find the percentage time elapsed... 37 | double dElapsed = iTime / m_dTransitionTime; 38 | dPercentage = (1.0 - Math.Exp(-1.0 * dElapsed * 5)) / 0.993262053; 39 | 40 | if (dElapsed >= 1.0) 41 | { 42 | dPercentage = 1.0; 43 | bCompleted = true; 44 | } 45 | else 46 | { 47 | bCompleted = false; 48 | } 49 | } 50 | 51 | #endregion 52 | 53 | #region Private data 54 | 55 | private double m_dTransitionTime = 0.0; 56 | 57 | #endregion 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Transitions/TransitionType_Deceleration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages a transition starting from a high speed and decelerating to zero by 9 | /// the end of the transition. 10 | /// 11 | public class TransitionType_Deceleration : ITransitionType 12 | { 13 | #region Public methods 14 | 15 | /// 16 | /// Constructor. You pass in the time that the transition 17 | /// will take (in milliseconds). 18 | /// 19 | public TransitionType_Deceleration(int iTransitionTime) 20 | { 21 | if (iTransitionTime <= 0) 22 | { 23 | throw new Exception("Transition time must be greater than zero."); 24 | } 25 | m_dTransitionTime = iTransitionTime; 26 | } 27 | 28 | #endregion 29 | 30 | #region ITransitionMethod Members 31 | 32 | /// 33 | /// Works out the percentage completed given the time passed in. 34 | /// This uses the formula: 35 | /// s = ut + 1/2at^2 36 | /// The initial velocity is 2, and the acceleration to get to 1.0 37 | /// at t=1.0 is -2, so the formula becomes: 38 | /// s = t(2-t) 39 | /// 40 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 41 | { 42 | // We find the percentage time elapsed... 43 | double dElapsed = iTime / m_dTransitionTime; 44 | dPercentage = dElapsed * (2.0 - dElapsed); 45 | if (dElapsed >= 1.0) 46 | { 47 | dPercentage = 1.0; 48 | bCompleted = true; 49 | } 50 | else 51 | { 52 | bCompleted = false; 53 | } 54 | } 55 | 56 | #endregion 57 | 58 | #region Private data 59 | 60 | private double m_dTransitionTime = 0.0; 61 | 62 | #endregion 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Transitions/TransitionType_EaseInEaseOut.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// Manages an ease-in-ease-out transition. This accelerates during the first 9 | /// half of the transition, and then decelerates during the second half. 10 | /// 11 | public class TransitionType_EaseInEaseOut : ITransitionType 12 | { 13 | #region Public methods 14 | 15 | /// 16 | /// Constructor. You pass in the time that the transition 17 | /// will take (in milliseconds). 18 | /// 19 | public TransitionType_EaseInEaseOut(int iTransitionTime) 20 | { 21 | if (iTransitionTime <= 0) 22 | { 23 | throw new Exception("Transition time must be greater than zero."); 24 | } 25 | m_dTransitionTime = iTransitionTime; 26 | } 27 | 28 | #endregion 29 | 30 | #region ITransitionMethod Members 31 | 32 | /// 33 | /// Works out the percentage completed given the time passed in. 34 | /// This uses the formula: 35 | /// s = ut + 1/2at^2 36 | /// We accelerate as at the rate needed (a=4) to get to 0.5 at t=0.5, and 37 | /// then decelerate at the same rate to end up at 1.0 at t=1.0. 38 | /// 39 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 40 | { 41 | // We find the percentage time elapsed... 42 | double dElapsed = iTime / m_dTransitionTime; 43 | dPercentage = Utility.convertLinearToEaseInEaseOut(dElapsed); 44 | 45 | if (dElapsed >= 1.0) 46 | { 47 | dPercentage = 1.0; 48 | bCompleted = true; 49 | } 50 | else 51 | { 52 | bCompleted = false; 53 | } 54 | } 55 | 56 | #endregion 57 | 58 | #region Private data 59 | 60 | private double m_dTransitionTime = 0.0; 61 | 62 | #endregion 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Transitions/TransitionType_Flash.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// This transition type 'flashes' the properties a specified number of times, ending 9 | /// up by reverting them to their initial values. You specify the number of bounces and 10 | /// the length of each bounce. 11 | /// 12 | public class TransitionType_Flash : TransitionType_UserDefined 13 | { 14 | #region Public methods 15 | 16 | /// 17 | /// You specify the number of bounces and the time taken for each bounce. 18 | /// 19 | public TransitionType_Flash(int iNumberOfFlashes, int iFlashTime) 20 | { 21 | // This class is derived from the user-defined transition type. 22 | // Here we set up a custom "user-defined" transition for the 23 | // number of flashes passed in... 24 | double dFlashInterval = 100.0 / iNumberOfFlashes; 25 | 26 | // We set up the elements of the user-defined transition... 27 | IList elements = new List(); 28 | for(int i=0; i 8 | /// This class manages a linear transition. The percentage complete for the transition 9 | /// increases linearly with time. 10 | /// 11 | public class TransitionType_Linear : ITransitionType 12 | { 13 | #region Public methods 14 | 15 | /// 16 | /// Constructor. You pass in the time (in milliseconds) that the 17 | /// transition will take. 18 | /// 19 | public TransitionType_Linear(int iTransitionTime) 20 | { 21 | if (iTransitionTime <= 0) 22 | { 23 | throw new Exception("Transition time must be greater than zero."); 24 | } 25 | m_dTransitionTime = iTransitionTime; 26 | } 27 | 28 | #endregion 29 | 30 | #region ITransitionMethod Members 31 | 32 | /// 33 | /// We return the percentage completed. 34 | /// 35 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 36 | { 37 | dPercentage = (iTime / m_dTransitionTime); 38 | if (dPercentage >= 1.0) 39 | { 40 | dPercentage = 1.0; 41 | bCompleted = true; 42 | } 43 | else 44 | { 45 | bCompleted = false; 46 | } 47 | } 48 | 49 | #endregion 50 | 51 | #region Private data 52 | 53 | private double m_dTransitionTime = 0.0; 54 | 55 | #endregion 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Transitions/TransitionType_ThrowAndCatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// This transition bounces the property to a destination value and back to the 9 | /// original value. It is decelerated to the destination and then acclerated back 10 | /// as if being thrown against gravity and then descending back with gravity. 11 | /// 12 | public class TransitionType_ThrowAndCatch : TransitionType_UserDefined 13 | { 14 | #region Public methods 15 | 16 | /// 17 | /// Constructor. You pass in the total time taken for the bounce. 18 | /// 19 | public TransitionType_ThrowAndCatch(int iTransitionTime) 20 | { 21 | // We create a custom "user-defined" transition to do the work... 22 | IList elements = new List(); 23 | elements.Add(new TransitionElement(50, 100, InterpolationMethod.Deceleration)); 24 | elements.Add(new TransitionElement(100, 0, InterpolationMethod.Accleration)); 25 | base.setup(elements, iTransitionTime); 26 | } 27 | 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Transitions/TransitionType_UserDefined.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Transitions 6 | { 7 | /// 8 | /// This class allows you to create user-defined transition types. You specify these 9 | /// as a list of TransitionElements. Each of these defines: 10 | /// End time , End value, Interpolation method 11 | /// 12 | /// For example, say you want to make a bouncing effect with a decay: 13 | /// 14 | /// EndTime% EndValue% Interpolation 15 | /// -------- --------- ------------- 16 | /// 50 100 Acceleration 17 | /// 75 50 Deceleration 18 | /// 85 100 Acceleration 19 | /// 91 75 Deceleration 20 | /// 95 100 Acceleration 21 | /// 98 90 Deceleration 22 | /// 100 100 Acceleration 23 | /// 24 | /// The time values are expressed as a percentage of the overall transition time. This 25 | /// means that you can create a user-defined transition-type and then use it for transitions 26 | /// of different lengths. 27 | /// 28 | /// The values are percentages of the values between the start and end values of the properties 29 | /// being animated in the transitions. 0% is the start value and 100% is the end value. 30 | /// 31 | /// The interpolation is one of the values from the InterpolationMethod enum. 32 | /// 33 | /// So the example above accelerates to the destination (as if under gravity) by 34 | /// t=50%, then bounces back up to half the initial height by t=75%, slowing down 35 | /// (as if against gravity) before falling down again and bouncing to decreasing 36 | /// heights each time. 37 | /// 38 | /// 39 | public class TransitionType_UserDefined : ITransitionType 40 | { 41 | #region Public methods 42 | 43 | /// 44 | /// Constructor. 45 | /// 46 | public TransitionType_UserDefined() 47 | { 48 | } 49 | 50 | /// 51 | /// Constructor. You pass in the list of TransitionElements and the total time 52 | /// (in milliseconds) for the transition. 53 | /// 54 | public TransitionType_UserDefined(IList elements, int iTransitionTime) 55 | { 56 | setup(elements, iTransitionTime); 57 | } 58 | 59 | /// 60 | /// Sets up the transitions. 61 | /// 62 | public void setup(IList elements, int iTransitionTime) 63 | { 64 | m_Elements = elements; 65 | m_dTransitionTime = iTransitionTime; 66 | 67 | // We check that the elements list has some members... 68 | if (elements.Count == 0) 69 | { 70 | throw new Exception("The list of elements passed to the constructor of TransitionType_UserDefined had zero elements. It must have at least one element."); 71 | } 72 | } 73 | 74 | #endregion 75 | 76 | #region ITransitionMethod Members 77 | 78 | /// 79 | /// Called to find the value for the movement of properties for the time passed in. 80 | /// 81 | public void onTimer(int iTime, out double dPercentage, out bool bCompleted) 82 | { 83 | double dTransitionTimeFraction = iTime / m_dTransitionTime; 84 | 85 | // We find the information for the element that we are currently processing... 86 | double dElementStartTime; 87 | double dElementEndTime; 88 | double dElementStartValue; 89 | double dElementEndValue; 90 | InterpolationMethod eInterpolationMethod; 91 | getElementInfo(dTransitionTimeFraction, out dElementStartTime, out dElementEndTime, out dElementStartValue, out dElementEndValue, out eInterpolationMethod); 92 | 93 | // We find how far through this element we are as a fraction... 94 | double dElementInterval = dElementEndTime - dElementStartTime; 95 | double dElementElapsedTime = dTransitionTimeFraction - dElementStartTime; 96 | double dElementTimeFraction = dElementElapsedTime / dElementInterval; 97 | 98 | // We convert the time-fraction to an fraction of the movement within the 99 | // element using the interpolation method... 100 | double dElementDistance; 101 | switch (eInterpolationMethod) 102 | { 103 | case InterpolationMethod.Linear: 104 | dElementDistance = dElementTimeFraction; 105 | break; 106 | 107 | case InterpolationMethod.Accleration: 108 | dElementDistance = Utility.convertLinearToAcceleration(dElementTimeFraction); 109 | break; 110 | 111 | case InterpolationMethod.Deceleration: 112 | dElementDistance = Utility.convertLinearToDeceleration(dElementTimeFraction); 113 | break; 114 | 115 | case InterpolationMethod.EaseInEaseOut: 116 | dElementDistance = Utility.convertLinearToEaseInEaseOut(dElementTimeFraction); 117 | break; 118 | 119 | default: 120 | throw new Exception("Interpolation method not handled: " + eInterpolationMethod.ToString()); 121 | } 122 | 123 | // We now know how far through the transition we have moved, so we can interpolate 124 | // the start and end values by this amount... 125 | dPercentage = Utility.interpolate(dElementStartValue, dElementEndValue, dElementDistance); 126 | 127 | // Has the transition completed? 128 | if (iTime >= m_dTransitionTime) 129 | { 130 | // The transition has completed, so we make sure that 131 | // it is at its final value... 132 | bCompleted = true; 133 | dPercentage = dElementEndValue; 134 | } 135 | else 136 | { 137 | bCompleted = false; 138 | } 139 | } 140 | 141 | /// 142 | /// Returns the element info for the time-fraction passed in. 143 | /// 144 | private void getElementInfo(double dTimeFraction, out double dStartTime, out double dEndTime, out double dStartValue, out double dEndValue, out InterpolationMethod eInterpolationMethod) 145 | { 146 | // We need to return the start and end values for the current element. So this 147 | // means finding the element for the time passed in as well as the previous element. 148 | 149 | // We hold the 'current' element as a hint. This was in fact the 150 | // element used the last time this function was called. In most cases 151 | // it will be the same one again, but it may have moved to a subsequent 152 | // on (maybe even skipping elements if enough time has passed)... 153 | int iCount = m_Elements.Count; 154 | for (; m_iCurrentElement < iCount; ++m_iCurrentElement) 155 | { 156 | TransitionElement element = m_Elements[m_iCurrentElement]; 157 | double dElementEndTime = element.EndTime / 100.0; 158 | if (dTimeFraction < dElementEndTime) 159 | { 160 | break; 161 | } 162 | } 163 | 164 | // If we have gone past the last element, we just use the last element... 165 | if (m_iCurrentElement == iCount) 166 | { 167 | m_iCurrentElement = iCount - 1; 168 | } 169 | 170 | // We find the start values. These come from the previous element, except in the 171 | // case where we are currently in the first element, in which case they are zeros... 172 | dStartTime = 0.0; 173 | dStartValue = 0.0; 174 | if (m_iCurrentElement > 0) 175 | { 176 | TransitionElement previousElement = m_Elements[m_iCurrentElement - 1]; 177 | dStartTime = previousElement.EndTime / 100.0; 178 | dStartValue = previousElement.EndValue / 100.0; 179 | } 180 | 181 | // We get the end values from the current element... 182 | TransitionElement currentElement = m_Elements[m_iCurrentElement]; 183 | dEndTime = currentElement.EndTime / 100.0; 184 | dEndValue = currentElement.EndValue / 100.0; 185 | eInterpolationMethod = currentElement.InterpolationMethod; 186 | } 187 | 188 | #endregion 189 | 190 | #region Private data 191 | 192 | // The collection of elements that make up the transition... 193 | private IList m_Elements = null; 194 | 195 | // The total transition time... 196 | private double m_dTransitionTime = 0.0; 197 | 198 | // The element that we are currently in (i.e. the current time within this element)... 199 | private int m_iCurrentElement = 0; 200 | 201 | #endregion 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /Transitions/Transitions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0} 9 | Library 10 | Properties 11 | Transitions 12 | Transitions 13 | v2.0 14 | 512 15 | 16 | 17 | 18 | 19 | 3.5 20 | publish\ 21 | true 22 | Disk 23 | false 24 | Foreground 25 | 7 26 | Days 27 | false 28 | false 29 | true 30 | 0 31 | 1.0.0.%2a 32 | false 33 | false 34 | true 35 | 36 | 37 | 38 | pdbonly 39 | true 40 | ..\Bin\Transitions\ 41 | TRACE 42 | prompt 43 | 4 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | False 79 | .NET Framework 3.5 SP1 80 | true 81 | 82 | 83 | 84 | 91 | -------------------------------------------------------------------------------- /Transitions/Transitions.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /Transitions/Utility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | using System.ComponentModel; 6 | 7 | namespace Transitions 8 | { 9 | /// 10 | /// A class holding static utility functions. 11 | /// 12 | internal class Utility 13 | { 14 | /// 15 | /// Returns the value of the property passed in. 16 | /// 17 | public static object getValue(object target, string strPropertyName) 18 | { 19 | Type targetType = target.GetType(); 20 | PropertyInfo propertyInfo = targetType.GetProperty(strPropertyName); 21 | if (propertyInfo == null) 22 | { 23 | throw new Exception("Object: " + target.ToString() + " does not have the property: " + strPropertyName); 24 | } 25 | return propertyInfo.GetValue(target, null); 26 | } 27 | 28 | /// 29 | /// Sets the value of the property passed in. 30 | /// 31 | public static void setValue(object target, string strPropertyName, object value) 32 | { 33 | Type targetType = target.GetType(); 34 | PropertyInfo propertyInfo = targetType.GetProperty(strPropertyName); 35 | if (propertyInfo == null) 36 | { 37 | throw new Exception("Object: " + target.ToString() + " does not have the property: " + strPropertyName); 38 | } 39 | propertyInfo.SetValue(target, value, null); 40 | } 41 | 42 | /// 43 | /// Returns a value between d1 and d2 for the percentage passed in. 44 | /// 45 | public static double interpolate(double d1, double d2, double dPercentage) 46 | { 47 | double dDifference = d2 - d1; 48 | double dDistance = dDifference * dPercentage; 49 | double dResult = d1 + dDistance; 50 | return dResult; 51 | } 52 | 53 | /// 54 | /// Returns a value betweeen i1 and i2 for the percentage passed in. 55 | /// 56 | public static int interpolate(int i1, int i2, double dPercentage) 57 | { 58 | return (int)interpolate((double)i1, (double)i2, dPercentage); 59 | } 60 | 61 | /// 62 | /// Returns a value betweeen f1 and f2 for the percentage passed in. 63 | /// 64 | public static float interpolate(float f1, float f2, double dPercentage) 65 | { 66 | return (float)interpolate((double)f1, (double)f2, dPercentage); 67 | } 68 | 69 | /// 70 | /// Converts a fraction representing linear time to a fraction representing 71 | /// the distance traveled under an ease-in-ease-out transition. 72 | /// 73 | public static double convertLinearToEaseInEaseOut(double dElapsed) 74 | { 75 | // The distance traveled is made up of two parts: the initial acceleration, 76 | // and then the subsequent deceleration... 77 | double dFirstHalfTime = (dElapsed > 0.5) ? 0.5 : dElapsed; 78 | double dSecondHalfTime = (dElapsed > 0.5) ? dElapsed - 0.5 : 0.0; 79 | double dResult = 2 * dFirstHalfTime * dFirstHalfTime + 2 * dSecondHalfTime * (1.0 - dSecondHalfTime); 80 | return dResult; 81 | } 82 | 83 | /// 84 | /// Converts a fraction representing linear time to a fraction representing 85 | /// the distance traveled under a constant acceleration transition. 86 | /// 87 | public static double convertLinearToAcceleration(double dElapsed) 88 | { 89 | return dElapsed * dElapsed; 90 | } 91 | 92 | /// 93 | /// Converts a fraction representing linear time to a fraction representing 94 | /// the distance traveled under a constant deceleration transition. 95 | /// 96 | public static double convertLinearToDeceleration(double dElapsed) 97 | { 98 | return dElapsed * (2.0 - dElapsed); 99 | } 100 | 101 | /// 102 | /// Fires the event passed in in a thread-safe way. 103 | /// 104 | /// This method loops through the targets of the event and invokes each in turn. If the 105 | /// target supports ISychronizeInvoke (such as forms or controls) and is set to run 106 | /// on a different thread, then we call BeginInvoke to marshal the event to the target 107 | /// thread. If the target does not support this interface (such as most non-form classes) 108 | /// or we are on the same thread as the target, then the event is fired on the same 109 | /// thread as this is called from. 110 | /// 111 | public static void raiseEvent(EventHandler theEvent, object sender, T args) where T : System.EventArgs 112 | { 113 | // Is the event set up? 114 | if (theEvent == null) 115 | { 116 | return; 117 | } 118 | 119 | // We loop through each of the delegate handlers for this event. For each of 120 | // them we need to decide whether to invoke it on the current thread or to 121 | // make a cross-thread invocation... 122 | foreach (EventHandler handler in theEvent.GetInvocationList()) 123 | { 124 | try 125 | { 126 | ISynchronizeInvoke target = handler.Target as ISynchronizeInvoke; 127 | if (target == null || target.InvokeRequired == false) 128 | { 129 | // Either the target is not a form or control, or we are already 130 | // on the right thread for it. Either way we can just fire the 131 | // event as normal... 132 | handler(sender, args); 133 | } 134 | else 135 | { 136 | // The target is most likely a form or control that needs the 137 | // handler to be invoked on its own thread... 138 | target.BeginInvoke(handler, new object[] { sender, args }); 139 | } 140 | } 141 | catch (Exception) 142 | { 143 | // The event handler may have been detached while processing the events. 144 | // We just ignore this and invoke the remaining handlers. 145 | } 146 | } 147 | } 148 | 149 | } 150 | } 151 | --------------------------------------------------------------------------------