├── .gitattributes
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── NuGet.Config
├── README.md
├── doc
├── Effects.gif
├── FluentTransitions.png
├── FluentTransitions.svg
├── Source FluentTransitions.url
├── button.gif
├── itv1.gif
├── itv2.gif
├── ripple.gif
└── text.gif
└── src
├── Directory.Build.props
├── FluentTransitions.sln
├── FluentTransitions.snk
├── FluentTransitions
├── FluentTransitions.csproj
├── InterpolationMethod.cs
├── ManagedTypes
│ ├── IManagedType.cs
│ ├── ManagedColor.cs
│ ├── ManagedDouble.cs
│ ├── ManagedFloat.cs
│ ├── ManagedInt.cs
│ └── ManagedString.cs
├── Methods
│ ├── Acceleration.cs
│ ├── Bounce.cs
│ ├── CriticalDamping.cs
│ ├── Deceleration.cs
│ ├── EaseInEaseOut.cs
│ ├── EaseWithFunction.cs
│ ├── EasingFunctions.cs
│ ├── Flash.cs
│ ├── IMethod.cs
│ ├── Linear.cs
│ ├── Rubberband.cs
│ ├── Sequence.cs
│ ├── Spring.cs
│ └── ThrowAndCatch.cs
├── Transition.cs
├── TransitionChain.cs
├── TransitionDefinition.cs
├── TransitionElement.cs
├── TransitionManager.cs
└── Utility.cs
└── TestApp
├── DemoForm.Designer.cs
├── DemoForm.cs
├── DemoForm.resx
├── KittenPuppyControl.Designer.cs
├── KittenPuppyControl.cs
├── KittenPuppyControl.resx
├── Program.cs
├── Properties
├── Resources.Designer.cs
└── Resources.resx
├── Resources
├── kitten.jpg
└── puppy.jpg
├── RippleControl.Designer.cs
├── RippleControl.cs
├── RippleControl.resx
├── TestApp.csproj
└── app.config
/.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 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: .NET Build, Test, and Publish Nuget Package
2 |
3 | on:
4 | push:
5 | branches: [ "main", "master" ]
6 | pull_request:
7 | branches: [ "main", "master" ]
8 |
9 | jobs:
10 |
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v4
17 |
18 | - name: Allow unsecure commands
19 | run: echo 'ACTIONS_ALLOW_UNSECURE_COMMANDS=true' >> $GITHUB_ENV
20 |
21 | - name: Fetch all history for all tags and branches
22 | run: |
23 | git config remote.origin.url https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
24 | git fetch --prune --unshallow
25 |
26 | - name: Install GitVersion
27 | uses: gittools/actions/gitversion/setup@v0.9.7
28 | with:
29 | versionSpec: '5.x'
30 |
31 | - name: Use GitVersion
32 | id: gitversion # step id used as reference for output values
33 | uses: gittools/actions/gitversion/execute@v0.9.7
34 |
35 | - name: Setup .NET
36 | uses: actions/setup-dotnet@v2
37 | with:
38 | dotnet-version: |
39 | 6.0.x
40 | 8.0.x
41 |
42 | - name: Restore dependencies
43 | run: dotnet restore src/FluentTransitions.sln
44 |
45 | - name: Build
46 | run: dotnet build src --no-restore --configuration=Release /p:Version=${{steps.gitversion.outputs.semVer}}
47 |
48 | - name: Test
49 | run: dotnet test src --no-build --configuration=Release --verbosity normal
50 |
51 | - name: pack nuget packages
52 | run: dotnet pack src --output nupkgs --configuration=Release --no-restore --no-build /p:PackageVersion=${{steps.gitversion.outputs.semVer}}
53 |
54 | - name: Create a GitHub release
55 | uses: ncipollo/release-action@v1
56 | with:
57 | tag: ${{steps.gitversion.outputs.semVer}}
58 | name: Release ${{steps.gitversion.outputs.semVer}}
59 | if: github.event_name != 'pull_request'
60 |
61 | - name: upload nuget package
62 | if: github.event_name != 'pull_request'
63 | run: dotnet nuget push nupkgs/FluentTransitions*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | **/.vs/
28 | # Uncomment if you have tasks that create the project's static files in wwwroot
29 | #wwwroot/
30 |
31 | # MSTest test Results
32 | [Tt]est[Rr]esult*/
33 | [Bb]uild[Ll]og.*
34 |
35 | # NUNIT
36 | *.VisualState.xml
37 | TestResult.xml
38 |
39 | # Build Results of an ATL Project
40 | [Dd]ebugPS/
41 | [Rr]eleasePS/
42 | dlldata.c
43 |
44 | # DNX
45 | project.lock.json
46 | project.fragment.lock.json
47 | artifacts/
48 |
49 | *_i.c
50 | *_p.c
51 | *_i.h
52 | *.ilk
53 | *.meta
54 | *.obj
55 | *.pch
56 | *.pdb
57 | *.pgc
58 | *.pgd
59 | *.rsp
60 | *.sbr
61 | *.tlb
62 | *.tli
63 | *.tlh
64 | *.tmp
65 | *.tmp_proj
66 | *.log
67 | *.vspscc
68 | *.vssscc
69 | .builds
70 | *.pidb
71 | *.svclog
72 | *.scc
73 |
74 | # Chutzpah Test files
75 | _Chutzpah*
76 |
77 | # Visual C++ cache files
78 | ipch/
79 | *.aps
80 | *.ncb
81 | *.opendb
82 | *.opensdf
83 | *.sdf
84 | *.cachefile
85 | *.VC.db
86 | *.VC.VC.opendb
87 |
88 | # Visual Studio profiler
89 | *.psess
90 | *.vsp
91 | *.vspx
92 | *.sap
93 |
94 | # TFS 2012 Local Workspace
95 | $tf/
96 |
97 | # Guidance Automation Toolkit
98 | *.gpState
99 |
100 | # ReSharper is a .NET coding add-in
101 | _ReSharper*/
102 | *.[Rr]e[Ss]harper
103 | *.DotSettings.user
104 |
105 | # JustCode is a .NET coding add-in
106 | .JustCode
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 | nCrunchTemp_*
118 |
119 | # MightyMoose
120 | *.mm.*
121 | AutoTest.Net/
122 |
123 | # Web workbench (sass)
124 | .sass-cache/
125 |
126 | # Installshield output folder
127 | [Ee]xpress/
128 |
129 | # DocProject is a documentation generator add-in
130 | DocProject/buildhelp/
131 | DocProject/Help/*.HxT
132 | DocProject/Help/*.HxC
133 | DocProject/Help/*.hhc
134 | DocProject/Help/*.hhk
135 | DocProject/Help/*.hhp
136 | DocProject/Help/Html2
137 | DocProject/Help/html
138 |
139 | # Click-Once directory
140 | publish/
141 |
142 | # Publish Web Output
143 | *.[Pp]ublish.xml
144 | *.azurePubxml
145 | # TODO: Comment the next line if you want to checkin your web deploy settings
146 | # but database connection strings (with potential passwords) will be unencrypted
147 | #*.pubxml
148 | *.publishproj
149 |
150 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
151 | # checkin your Azure Web App publish settings, but sensitive information contained
152 | # in these scripts will be unencrypted
153 | PublishScripts/
154 |
155 | # NuGet Packages
156 | *.nupkg
157 | # The packages folder can be ignored because of Package Restore
158 | **/packages/*
159 | # except build/, which is used as an MSBuild target.
160 | !**/packages/build/
161 | # Uncomment if necessary however generally it will be regenerated when needed
162 | #!**/packages/repositories.config
163 | # NuGet v3's project.json files produces more ignoreable files
164 | *.nuget.props
165 | *.nuget.targets
166 |
167 | # Microsoft Azure Build Output
168 | csx/
169 | *.build.csdef
170 |
171 | # Microsoft Azure Emulator
172 | ecf/
173 | rcf/
174 |
175 | # Windows Store app package directories and files
176 | AppPackages/
177 | BundleArtifacts/
178 | Package.StoreAssociation.xml
179 | _pkginfo.txt
180 |
181 | # Visual Studio cache files
182 | # files ending in .cache can be ignored
183 | *.[Cc]ache
184 | # but keep track of directories ending in .cache
185 | !*.[Cc]ache/
186 |
187 | # Others
188 | ClientBin/
189 | ~$*
190 | *~
191 | *.dbmdl
192 | *.dbproj.schemaview
193 | *.jfm
194 | *.pfx
195 | *.publishsettings
196 | node_modules/
197 | orleans.codegen.cs
198 |
199 | # Since there are multiple workflows, uncomment next line to ignore bower_components
200 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
201 | #bower_components/
202 |
203 | # RIA/Silverlight projects
204 | Generated_Code/
205 |
206 | # Backup & report files from converting an old project file
207 | # to a newer Visual Studio version. Backup files are not needed,
208 | # because we have git ;-)
209 | _UpgradeReport_Files/
210 | Backup*/
211 | UpgradeLog*.XML
212 | UpgradeLog*.htm
213 |
214 | # SQL Server files
215 | *.mdf
216 | *.ldf
217 |
218 | # Business Intelligence projects
219 | *.rdl.data
220 | *.bim.layout
221 | *.bim_*.settings
222 |
223 | # Microsoft Fakes
224 | FakesAssemblies/
225 |
226 | # GhostDoc plugin setting file
227 | *.GhostDoc.xml
228 |
229 | # Node.js Tools for Visual Studio
230 | .ntvs_analysis.dat
231 |
232 | # Visual Studio 6 build log
233 | *.plg
234 |
235 | # Visual Studio 6 workspace options file
236 | *.opt
237 |
238 | # Visual Studio LightSwitch build output
239 | **/*.HTMLClient/GeneratedArtifacts
240 | **/*.DesktopClient/GeneratedArtifacts
241 | **/*.DesktopClient/ModelManifest.xml
242 | **/*.Server/GeneratedArtifacts
243 | **/*.Server/ModelManifest.xml
244 | _Pvt_Extensions
245 |
246 | # Paket dependency manager
247 | .paket/paket.exe
248 | paket-files/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
254 | # CodeRush
255 | .cr/
256 |
257 | # Python Tools for Visual Studio (PTVS)
258 | __pycache__/
259 | *.pyc
260 | /tools
261 | /_output
262 |
263 | # Mac
264 | .DS_Store
265 |
266 | /build
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
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.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FluentTransitions
2 |
3 | [](https://www.nuget.org/packages/FluentTransitions/)
4 |
5 | FluentTransitions lets you create animated transitions of any property of user-interface elements in .NET. It provides a simple API to perform UI animations in a similar way to Apple's Core Animation library for iOS, iPadOS and macOS.
6 |
7 | 
8 |
9 | FluentTransitions powering [FluentDragDrop](https://github.com/awaescher/FluentDragDrop), a library to create stunning drag and drop effects with Windows Forms.
10 |
11 | ## What can it do for me?
12 |
13 | FluentTransitions allows smooth UI transitions with Windows Forms and GDI+. While the animation above shows several effects in combination, you will probably start with simpler things like the transition of a property of a Windows Forms control:
14 |
15 | ```csharp
16 | var maxTop = button1.Parent.Height - button1.Height;
17 |
18 | Transition
19 | .With(button1, nameof(Top), maxTop) // target, property, value
20 | .Bounce(TimeSpan.FromMilliseconds(500)); // method and duration
21 | ```
22 |
23 | 
24 |
25 | ### Multi targeting
26 |
27 | Transitions can manipulate multiple properties from one or multiple objects simultaneously just by chaining the `.With()` methods:
28 |
29 | ```csharp
30 | Transition
31 | .With(button1, nameof(Left), 300)
32 | .With(button2, nameof(Top), 200)
33 | .With(Form1, nameof(Opacity), 0.0)
34 | .EaseInEaseOut(TimeSpan.FromSeconds(2));
35 | ```
36 |
37 | This code animates the movement of two buttons while it fades out the whole form. All of this is running in parallel within two seconds.
38 |
39 | ### Chaining
40 |
41 | Some effects might require multiple transitions to be executed sequentially. FluentTransitions provides a concept called "Chaining". To use it, simply build your transitions and run them with `Transition.RunChain(...)`:
42 |
43 | ```csharp
44 | Transition.RunChain
45 | (
46 | Transition
47 | .With(button1, nameof(Left), 300)
48 | .With(button2, nameof(Top), 200)
49 | .Build(new Linear(TimeSpan.FromSeconds(1))),
50 | Transition
51 | .With(Form1, nameof(Opacity), 0.0)
52 | .Build(new Linear(TimeSpan.FromSeconds(1)))
53 | );
54 | ```
55 |
56 | This code animates the movement of two buttons first. Once this is done, it fades out the whole form. Both transitions are completed within two seconds.
57 |
58 | ### Completion
59 |
60 | Each transition raises an event once it is completed. This can be useful to run code after the UI is done with animating.
61 |
62 | ```csharp
63 | var t1 = Transition
64 | .With(button1, nameof(Left), 300)
65 | .With(button2, nameof(Top), 200)
66 | .HookOnCompletionInUiThread(SynchronizationContext.Current, () => this.Close())
67 | .Build(new EaseInEaseOut(TimeSpan.FromSeconds(1)));
68 |
69 | Transition.Run(t1);
70 | ```
71 |
72 | > Prefer `Transition.RunChain()` to run animations sequentially.
73 |
74 | # More Samples
75 |
76 | Back in the year 2011, I used these transitions to spice up two login forms for a customer project. Be kind to me, I was young and just wanted to make something fancy. Nevertheless, I think it's pretty special to WinForms.
77 |
78 | 
79 |
80 | 
81 |
82 | But FluentTransitions is more that just smoothly moving and sizing controls, you can do pretty much everything if you're creative enough.
83 |
84 | 
85 |
86 | 
87 |
88 | ## Acknowledgements
89 |
90 | Idea and initial implementation by [Richard S. Shepherd on Google Code](https://code.google.com/p/dot-net-transitions/).
91 |
92 | Dec 2020 [Andreas Wäscher](https://github.com/awaescher)
93 | - Added support for [Easing Functions](https://easings.net/)
94 | - Added built-in easing implementations by [Mauro Sampietro](https://www.codeproject.com/Articles/827808/Control-Animation-in-Winforms)
95 |
96 | Oct 2020 [Andreas Wäscher](https://github.com/awaescher)
97 | - Migrated to .NET Core 3.1 and .NET Framework 4.8
98 | - Updated namespaces, class names and the code itself to meet modern code standards
99 | - Added fluent syntax to build and run transitions
100 | - Switched from "dot-net-transitions" to "FluentTransitions"
101 |
102 | Apr 2020 [zhenyuan0502](https://github.com/zhenyuan0502)
103 | - Migrated to .NET Core 3.0
104 |
105 | Jul 2015 [Uwe Keim](https://github.com/UweKeim)
106 | - Copied this repository from [Google Code](https://code.google.com/p/dot-net-transitions/) to save it from disappearing when Google Code shuts down
107 |
108 | © 2009 Richard S. Shepherd.
109 |
--------------------------------------------------------------------------------
/doc/Effects.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/Effects.gif
--------------------------------------------------------------------------------
/doc/FluentTransitions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/FluentTransitions.png
--------------------------------------------------------------------------------
/doc/FluentTransitions.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/Source FluentTransitions.url:
--------------------------------------------------------------------------------
1 | [InternetShortcut]
2 | URL=https://www.flaticon.com/free-icon/website_1388665
3 |
--------------------------------------------------------------------------------
/doc/button.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/button.gif
--------------------------------------------------------------------------------
/doc/itv1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/itv1.gif
--------------------------------------------------------------------------------
/doc/itv2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/itv2.gif
--------------------------------------------------------------------------------
/doc/ripple.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/ripple.gif
--------------------------------------------------------------------------------
/doc/text.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/doc/text.gif
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | Andreas Wäscher
4 | Andreas Wäscher
5 | FluentTransitions.png
6 | https://github.com/awaescher/FluentTransitions
7 | git
8 | https://github.com/awaescher/FluentTransitions
9 | MIT
10 | latest
11 |
12 | true
13 |
14 | true
15 |
16 |
17 |
18 | true
19 |
20 |
21 |
22 | true
23 | true
24 |
25 |
26 |
27 | true
28 | ..\FluentTransitions.snk
29 | false
30 |
31 |
32 |
33 | false
34 | false
35 |
36 |
37 |
38 | DEBUG;TRACE
39 | True
40 | true
41 | embedded
42 | false
43 |
44 |
45 |
46 | True
47 | embedded
48 | True
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/FluentTransitions.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30011.22
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentTransitions", "FluentTransitions\FluentTransitions.csproj", "{95CDE461-0720-4C3B-B5E1-D188391FB7C0}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp", "TestApp\TestApp.csproj", "{E5B3CEE3-973B-4400-BF81-62EEC02625F4}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {95CDE461-0720-4C3B-B5E1-D188391FB7C0}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {E5B3CEE3-973B-4400-BF81-62EEC02625F4}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {D7684A7E-357C-4C91-BE60-920B654D6FB3}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/FluentTransitions.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/src/FluentTransitions.snk
--------------------------------------------------------------------------------
/src/FluentTransitions/FluentTransitions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | net48;net6.0-windows;net8.0-windows
5 | true
6 | true
7 | FluentTransitions lets you create animated transitions of any property of user-interface elements in .NET.
8 | It provides an easy way to perform UI animations in a similar way to Apple's Core Animation library for iOS, iPadOS and macOS.
9 |
10 | The app icon was made by Freepik from www.flaticon.com and is licensed by Creative Commons BY 3.0.
11 | Fluent;Transitions;Windows;Forms;WinForms;UI
12 | Andreas Wäscher, Richard S. Shepherd, Mauro Sampietro
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/FluentTransitions/InterpolationMethod.cs:
--------------------------------------------------------------------------------
1 | namespace FluentTransitions
2 | {
3 | ///
4 | /// Interpolation methods to
5 | ///
6 | public enum InterpolationMethod
7 | {
8 | ///
9 | /// Alters values in a linear way until they reach their destination values.
10 | ///
11 | Linear,
12 |
13 | ///
14 | /// Alters values to their destination values from a standing start with accelerating intervals.
15 | ///
16 | Accleration,
17 |
18 | ///
19 | /// Alters values starting from a high speed and decelerating to zero by the end of the transition.
20 | ///
21 | Deceleration,
22 |
23 | ///
24 | /// Alters values in an ease-in-ease-out transition.
25 | /// This accelerates during the first half of the transition, and then decelerates during the second half.
26 | ///
27 | EaseInEaseOut
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/IManagedType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.ManagedTypes
4 | {
5 | ///
6 | /// Interface for all types we can perform transitions on.
7 | /// Each type (e.g. int, double, Color) that we can perform a transition on
8 | /// needs to have its own class that implements this interface. These classes
9 | /// tell the transition system how to act on objects of that type.
10 | ///
11 | internal interface IManagedType
12 | {
13 | ///
14 | /// Returns the Type that the instance is managing.
15 | ///
16 | Type GetManagedType();
17 |
18 | ///
19 | /// Returns a deep copy of the object passed in. (In particular this is
20 | /// needed for types that are objects.)
21 | ///
22 | object Copy(object o);
23 |
24 | ///
25 | /// Returns an object holding the value between the start and end corresponding
26 | /// to the percentage passed in. (Note: the percentage can be less than 0% or
27 | /// greater than 100%.)
28 | ///
29 | object GetIntermediateValue(object start, object end, double percentage);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/ManagedColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 |
4 | namespace FluentTransitions.ManagedTypes
5 | {
6 | ///
7 | /// Class that manages transitions for Color properties. For these we
8 | /// need to transition the R, G, B and A sub-properties independently.
9 | ///
10 | internal class ManagedColor : IManagedType
11 | {
12 | ///
13 | /// Returns the type we are managing.
14 | ///
15 | public Type GetManagedType() => typeof(Color);
16 |
17 | ///
18 | /// Returns a copy of the color object passed in.
19 | ///
20 | public object Copy(object o) => Color.FromArgb(((Color)o).ToArgb());
21 |
22 | ///
23 | /// Creates an intermediate value for the colors depending on the percentage passed in.
24 | ///
25 | public object GetIntermediateValue(object start, object end, double percentage)
26 | {
27 | Color startColor = (Color)start;
28 | Color endColor = (Color)end;
29 |
30 | // We interpolate the R, G, B and A components separately...
31 | int start_R = startColor.R;
32 | int start_G = startColor.G;
33 | int start_B = startColor.B;
34 | int start_A = startColor.A;
35 |
36 | int end_R = endColor.R;
37 | int end_G = endColor.G;
38 | int end_B = endColor.B;
39 | int end_A = endColor.A;
40 |
41 | int new_R = Utility.Interpolate(start_R, end_R, percentage);
42 | int new_G = Utility.Interpolate(start_G, end_G, percentage);
43 | int new_B = Utility.Interpolate(start_B, end_B, percentage);
44 | int new_A = Utility.Interpolate(start_A, end_A, percentage);
45 |
46 | return Color.FromArgb(new_A, new_R, new_G, new_B);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/ManagedDouble.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.ManagedTypes
4 | {
5 | ///
6 | /// Manages transitions for double properties.
7 | ///
8 | internal class ManagedDouble : IManagedType
9 | {
10 | ///
11 | /// Returns the type managed by this class.
12 | ///
13 | public Type GetManagedType() => typeof(double);
14 |
15 | ///
16 | /// Returns a copy of the double passed in.
17 | ///
18 | public object Copy(object o) => (double)o;
19 |
20 | ///
21 | /// Returns the value between start and end for the percentage passed in.
22 | ///
23 | public object GetIntermediateValue(object start, object end, double percentage)
24 | {
25 | return Utility.Interpolate((double)start, (double)end, percentage);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/ManagedFloat.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.ManagedTypes
4 | {
5 | internal class ManagedFloat : IManagedType
6 | {
7 | ///
8 | /// Returns the type we're managing.
9 | ///
10 | public Type GetManagedType() => typeof(float);
11 |
12 | ///
13 | /// Returns a copy of the float passed in.
14 | ///
15 | public object Copy(object o) => (float)o;
16 |
17 | ///
18 | /// Returns the interpolated value for the percentage passed in.
19 | ///
20 | public object GetIntermediateValue(object start, object end, double percentage)
21 | {
22 | return Utility.Interpolate((float)start, (float)end, percentage);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/ManagedInt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.ManagedTypes
4 | {
5 | ///
6 | /// Manages transitions for int properties.
7 | ///
8 | internal class ManagedInt : IManagedType
9 | {
10 | ///
11 | /// Returns the type we are managing.
12 | ///
13 | public Type GetManagedType() => typeof(int);
14 |
15 | ///
16 | /// Returns a copy of the int passed in.
17 | ///
18 | public object Copy(object o) => (int)o;
19 |
20 | ///
21 | /// Returns the value between the start and end for the percentage passed in.
22 | ///
23 | public object GetIntermediateValue(object start, object end, double percentage)
24 | {
25 | return Utility.Interpolate((int)start, (int)end, percentage);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/FluentTransitions/ManagedTypes/ManagedString.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.ManagedTypes
4 | {
5 | ///
6 | /// Manages transitions for strings. This doesn't make as much sense as transitions
7 | /// on other types, but I like the way it looks!
8 | ///
9 | internal class ManagedString : IManagedType
10 | {
11 | ///
12 | /// Returns the type we're managing.
13 | ///
14 | public Type GetManagedType() => typeof(string);
15 |
16 | ///
17 | /// Returns a copy of the string passed in.
18 | ///
19 | public object Copy(object o) => new string(((string)o).ToCharArray());
20 |
21 | ///
22 | /// Returns an "interpolated" string.
23 | ///
24 | public object GetIntermediateValue(object start, object end, double percentage)
25 | {
26 | string startString = (string)start;
27 | string endString = (string)end;
28 |
29 | // We find the length of the interpolated string...
30 | int startLength = startString.Length;
31 | int endLength = endString.Length;
32 | int length = Utility.Interpolate(startLength, endLength, percentage);
33 | char[] result = new char[length];
34 |
35 | // Now we assign the letters of the results by interpolating the
36 | // letters from the start and end strings...
37 | for (int i = 0; i < length; ++i)
38 | {
39 | // We get the start and end chars at this position...
40 | char startChar = 'a';
41 | if (i < startLength)
42 | startChar = startString[i];
43 |
44 | char cEnd = 'a';
45 | if (i < endLength)
46 | cEnd = endString[i];
47 |
48 | // We interpolate them...
49 | char interpolatedChar;
50 | if (cEnd == ' ')
51 | {
52 | // If the end character is a space we just show a space
53 | // regardless of interpolation. It looks better this way...
54 | interpolatedChar = ' ';
55 | }
56 | else
57 | {
58 | // The end character is not a space, so we interpolate...
59 | int startCharValue = Convert.ToInt32(startChar);
60 | int endCharValue = Convert.ToInt32(cEnd);
61 | int interpolatedValue = Utility.Interpolate(startCharValue, endCharValue, percentage);
62 | interpolatedChar = Convert.ToChar(interpolatedValue);
63 | }
64 |
65 | result[i] = interpolatedChar;
66 | }
67 |
68 | return new string(result);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Acceleration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// Manages transitions under constant acceleration from a standing start.
7 | ///
8 | public class Acceleration : IMethod
9 | {
10 | private readonly double _duration = 0.0;
11 |
12 | ///
13 | /// Alters the property values to their destination values from a standing start with accelerating intervals.
14 | ///
15 | /// The duration until the properties should have reached their destination values
16 | public Acceleration(TimeSpan duration) : this((int)duration.TotalMilliseconds)
17 | {
18 | }
19 |
20 | ///
21 | /// Alters the property values to their destination values from a standing start with accelerating intervals.
22 | ///
23 | /// The duration in milliseconds until the properties should have reached their destination values
24 | public Acceleration(int duration)
25 | {
26 | if (duration <= 0)
27 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
28 |
29 | _duration = duration;
30 | }
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 0, and the acceleration to get to 1.0
37 | /// at t=1.0 is 2, so the formula just becomes:
38 | /// s = t^2
39 | ///
40 | public void OnTimer(int time, out double percentage, out bool completed)
41 | {
42 | // We find the percentage time elapsed...
43 | double elapsed = time / _duration;
44 | percentage = elapsed * elapsed;
45 | if (elapsed >= 1.0)
46 | {
47 | percentage = 1.0;
48 | completed = true;
49 | }
50 | else
51 | {
52 | completed = false;
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Bounce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace FluentTransitions.Methods
5 | {
6 | ///
7 | /// This transition bounces the property to a destination value and back to the
8 | /// original value. It is accelerated to the destination and then decelerated back
9 | /// as if being dropped with gravity and bouncing back against gravity.
10 | ///
11 | public class Bounce : Sequence
12 | {
13 | ///
14 | /// Bounces the property values to their destination values and back to the original ones.
15 | /// They are accelerated to the destination and then decelerated back as if being dropped with gravity and bouncing back against gravity.
16 | ///
17 | /// The duration until the properties should have reached their destination values
18 | public Bounce(TimeSpan duration) : this((int)duration.TotalMilliseconds)
19 | {
20 | }
21 |
22 | ///
23 | /// Bounces the property values to their destination values and back to the original ones.
24 | /// They are accelerated to the destination and then decelerated back as if being dropped with gravity and bouncing back against gravity.
25 | ///
26 | /// The duration in milliseconds until the properties should have reached their destination values
27 | public Bounce(int duration)
28 | {
29 | // We create a custom "user-defined" transition to do the work...
30 | var elements = new List
31 | {
32 | new TransitionElement(50, 100, InterpolationMethod.Accleration),
33 | new TransitionElement(100, 0, InterpolationMethod.Deceleration)
34 | };
35 | base.Setup(elements, duration);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/CriticalDamping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// This transition animates with an exponential decay. This has a damping effect
7 | /// similar to the motion of a needle on an electomagnetically controlled dial.
8 | ///
9 | public class CriticalDamping : IMethod
10 | {
11 | private readonly double _duration = 0.0;
12 |
13 | ///
14 | /// Alters the property values with an exponential decay.
15 | /// This has a damping effect similar to the motion of a needle on an electomagnetically controlled dial.
16 | ///
17 | /// The duration until the properties should have reached their destination values
18 | public CriticalDamping(TimeSpan duration) : this((int)duration.TotalMilliseconds)
19 | {
20 | }
21 |
22 | ///
23 | /// Alters the property values with an exponential decay.
24 | /// This has a damping effect similar to the motion of a needle on an electomagnetically controlled dial.
25 | ///
26 | /// The duration in milliseconds until the properties should have reached their destination values
27 | public CriticalDamping(int duration)
28 | {
29 | if (duration <= 0)
30 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
31 |
32 | _duration = duration;
33 | }
34 |
35 | ///
36 | /// Works out the percentage completed given the time passed in.
37 | ///
38 | public void OnTimer(int time, out double percentage, out bool completed)
39 | {
40 | // We find the percentage time elapsed...
41 | double elapsed = time / _duration;
42 | percentage = (1.0 - Math.Exp(-1.0 * elapsed * 5)) / 0.993262053;
43 |
44 | if (elapsed >= 1.0)
45 | {
46 | percentage = 1.0;
47 | completed = true;
48 | }
49 | else
50 | {
51 | completed = false;
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Deceleration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// Manages a transition starting from a high speed and decelerating to zero by
7 | /// the end of the transition.
8 | ///
9 | public class Deceleration : IMethod
10 | {
11 | private readonly double _duration = 0.0;
12 |
13 | ///
14 | /// Alters the property values starting from a high speed and decelerating to zero by the end of the transition.
15 | ///
16 | /// The duration until the properties should have reached their destination values
17 | public Deceleration(TimeSpan duration) : this((int)duration.TotalMilliseconds)
18 | {
19 | }
20 |
21 | ///
22 | /// Alters the property values starting from a high speed and decelerating to zero by the end of the transition.
23 | ///
24 | /// The duration in milliseconds until the properties should have reached their destination values
25 | public Deceleration(int duration)
26 | {
27 | if (duration <= 0)
28 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
29 |
30 | _duration = duration;
31 | }
32 |
33 | ///
34 | /// Works out the percentage completed given the time passed in.
35 | /// This uses the formula:
36 | /// s = ut + 1/2at^2
37 | /// The initial velocity is 2, and the acceleration to get to 1.0
38 | /// at t=1.0 is -2, so the formula becomes:
39 | /// s = t(2-t)
40 | ///
41 | public void OnTimer(int time, out double percentage, out bool completed)
42 | {
43 | // We find the percentage time elapsed...
44 | double elapsed = time / _duration;
45 | percentage = elapsed * (2.0 - elapsed);
46 | if (elapsed >= 1.0)
47 | {
48 | percentage = 1.0;
49 | completed = true;
50 | }
51 | else
52 | {
53 | completed = false;
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/EaseInEaseOut.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// Manages an ease-in-ease-out transition. This accelerates during the first
7 | /// half of the transition, and then decelerates during the second half.
8 | ///
9 | public class EaseInEaseOut : IMethod
10 | {
11 | private readonly double _duration = 0.0;
12 |
13 | ///
14 | /// Alters the property values in an ease-in-ease-out transition.
15 | /// This accelerates during the first half of the transition, and then decelerates during the second half.
16 | ///
17 | /// The duration until the properties should have reached their destination values
18 | public EaseInEaseOut(TimeSpan duration) : this((int)duration.TotalMilliseconds)
19 | {
20 | }
21 |
22 | ///
23 | /// Alters the property values in an ease-in-ease-out transition.
24 | /// This accelerates during the first half of the transition, and then decelerates during the second half.
25 | ///
26 | /// The duration in milliseconds until the properties should have reached their destination values
27 | public EaseInEaseOut(int duration)
28 | {
29 | if (duration <= 0)
30 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
31 |
32 | _duration = duration;
33 | }
34 |
35 | ///
36 | /// Works out the percentage completed given the time passed in.
37 | /// This uses the formula:
38 | /// s = ut + 1/2at^2
39 | /// We accelerate as at the rate needed (a=4) to get to 0.5 at t=0.5, and
40 | /// then decelerate at the same rate to end up at 1.0 at t=1.0.
41 | ///
42 | public void OnTimer(int time, out double percentage, out bool completed)
43 | {
44 | // We find the percentage time elapsed...
45 | double elapsed = time / _duration;
46 | percentage = Utility.ConvertLinearToEaseInEaseOut(elapsed);
47 |
48 | if (elapsed >= 1.0)
49 | {
50 | percentage = 1.0;
51 | completed = true;
52 | }
53 | else
54 | {
55 | completed = false;
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/EaseWithFunction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// Allows natural transitions with custom or predefined easing functions.
7 | /// Easing functions are mathematical functions that are used to interpolate values between two endpoints
8 | /// usually with non-linear results.
9 | /// Thanks to Mauro Sampietro for providing the easing functions on https://www.codeproject.com/Articles/827808/Control-Animation-in-Winforms.
10 | ///
11 | public class EaseWithFunction : IMethod
12 | {
13 | private readonly double _duration = 0.0;
14 |
15 | ///
16 | /// Allows natural transitions with custom or predefined easing functions.
17 | /// Easing functions are mathematical functions that are used to interpolate values between two endpoints
18 | /// usually with non-linear results.
19 | ///
20 | ///
21 | /// The function to interpolate values with. See "" for prebuilt easing functions.
22 | /// Powererd by Mauro Sampietro (https://www.codeproject.com/Articles/827808/Control-Animation-in-Winforms).
23 | ///
24 | /// The duration until the properties should have reached their destination values
25 | public EaseWithFunction(EasingFunction easingFunction, TimeSpan duration) : this(easingFunction, (int)duration.TotalMilliseconds)
26 | {
27 | EasingFunction = easingFunction ?? throw new ArgumentNullException(nameof(easingFunction));
28 | }
29 |
30 | ///
31 | /// Allows natural transitions with custom or predefined easing functions.
32 | /// Easing functions are mathematical functions that are used to interpolate values between two endpoints
33 | /// usually with non-linear results.
34 | ///
35 | ///
36 | /// The function to interpolate values with. See "" for prebuilt easing functions.
37 | /// Powererd by Mauro Sampietro (https://www.codeproject.com/Articles/827808/Control-Animation-in-Winforms).
38 | ///
39 | /// The duration in milliseconds until the properties should have reached their destination values
40 | public EaseWithFunction(EasingFunction easingFunction, int duration)
41 | {
42 | if (duration <= 0)
43 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
44 |
45 | EasingFunction = easingFunction ?? throw new ArgumentNullException(nameof(easingFunction));
46 |
47 | _duration = duration;
48 | }
49 |
50 | ///
51 | /// Works out the percentage completed given the time passed in.
52 | ///
53 | public void OnTimer(int time, out double percentage, out bool completed)
54 | {
55 | percentage = EasingFunction(time, 0, 100, _duration) / 100;
56 | completed = time >= _duration;
57 | }
58 |
59 | ///
60 | /// Gets the easing function to interpolate values with
61 | ///
62 | public EasingFunction EasingFunction { get; }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Flash.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace FluentTransitions.Methods
5 | {
6 | ///
7 | /// This transition type 'flashes' the properties a specified number of times, ending
8 | /// up by reverting them to their initial values. You specify the number of bounces and
9 | /// the length of each bounce.
10 | ///
11 | public class Flash : Sequence
12 | {
13 | ///
14 | /// Flashes the property values a specified number of times, ending up by reverting them to their initial values.
15 | ///
16 | /// The number of flashes to animate
17 | /// The duration of each flash
18 | public Flash(int numberOfFlashes, TimeSpan durationOfEachFlash) : this(numberOfFlashes, (int)durationOfEachFlash.TotalMilliseconds)
19 | {
20 | }
21 |
22 | ///
23 | /// Flashes the property values a specified number of times, ending up by reverting them to their initial values.
24 | ///
25 | /// The number of flashes to animate
26 | /// The duration of each flash in milliseconds
27 | public Flash(int numberOfFlashes, int durationOfEachFlash)
28 | {
29 | // This class is derived from the user-defined transition type.
30 | // Here we set up a custom "user-defined" transition for the
31 | // number of flashes passed in...
32 | double flashInterval = 100.0 / numberOfFlashes;
33 |
34 | // We set up the elements of the user-defined transition...
35 | IList elements = new List();
36 | for (int i = 0; i < numberOfFlashes; ++i)
37 | {
38 | // Each flash consists of two elements: one going to the destination value,
39 | // and another going back again...
40 | double flashStartTime = i * flashInterval;
41 | double flashEndTime = flashStartTime + flashInterval;
42 | double flashMidPoint = (flashStartTime + flashEndTime) / 2.0;
43 | elements.Add(new TransitionElement(flashMidPoint, 100, InterpolationMethod.EaseInEaseOut));
44 | elements.Add(new TransitionElement(flashEndTime, 0, InterpolationMethod.EaseInEaseOut));
45 | }
46 |
47 | base.Setup(elements, durationOfEachFlash * numberOfFlashes);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/IMethod.cs:
--------------------------------------------------------------------------------
1 | namespace FluentTransitions
2 | {
3 | ///
4 | /// Interface for all transition methods
5 | ///
6 | public interface IMethod
7 | {
8 | ///
9 | /// Called by the Transition framework when its timer ticks to pass in the
10 | /// time (in ms) since the transition started.
11 | ///
12 | /// You should return (in an out parameter) the percentage movement towards
13 | /// the destination value for the time passed in. Note: this does not need to
14 | /// be a smooth transition from 0% to 100%. You can overshoot with values
15 | /// greater than 100% or undershoot if you need to (for example, to have some
16 | /// form of "elasticity").
17 | ///
18 | /// The percentage should be returned as (for example) 0.1 for 10%.
19 | ///
20 | /// You should return (in an out parameter) whether the transition has completed.
21 | /// (This may not be at the same time as the percentage has moved to 100%.)
22 | ///
23 | /// The time that has passed
24 | /// Returns the percentage how far the transition has come
25 | /// Returns whether the transition has completed or not
26 | void OnTimer(int time, out double percentage, out bool completed);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Linear.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// This class manages a linear transition. The percentage complete for the transition
7 | /// increases linearly with time.
8 | ///
9 | public class Linear : IMethod
10 | {
11 | private readonly double _duration = 0.0;
12 |
13 | ///
14 | /// Alters the property values in a linear way until they reach their destination values.
15 | ///
16 | /// The duration until the properties should have reached their destination values
17 | public Linear(TimeSpan duration) : this((int)duration.TotalMilliseconds)
18 | {
19 | }
20 |
21 | ///
22 | /// Alters the property values in a linear way until they reach their destination values.
23 | ///
24 | /// The duration in milliseconds until the properties should have reached their destination values
25 | public Linear(int duration)
26 | {
27 | if (duration <= 0)
28 | throw new ArgumentOutOfRangeException(nameof(duration), "Transition time must be greater than zero.");
29 |
30 | _duration = duration;
31 | }
32 |
33 | ///
34 | /// Works out the percentage completed given the time passed in.
35 | ///
36 | public void OnTimer(int time, out double percentage, out bool completed)
37 | {
38 | percentage = (time / _duration);
39 | if (percentage >= 1.0)
40 | {
41 | percentage = 1.0;
42 | completed = true;
43 | }
44 | else
45 | {
46 | completed = false;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Rubberband.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// This transition interpolates values with EasingFunctions.BackEaseOut to mimic the behavior of a rubber band stopping a movement and pulling it back.
7 | ///
8 | public class Rubberband : EaseWithFunction
9 | {
10 | ///
11 | /// Interpolates values with EasingFunctions.BackEaseOut to mimic the behavior of a rubber band stopping a movement and pulling it back.
12 | ///
13 | /// The duration until the properties should have reached their destination values
14 | public Rubberband(TimeSpan duration) : this((int)duration.TotalMilliseconds)
15 | {
16 | }
17 |
18 | ///
19 | /// Interpolates values with EasingFunctions.BackEaseOut to mimic the behavior of a rubber band stopping a movement and pulling it back.
20 | ///
21 | /// The duration in milliseconds until the properties should have reached their destination values
22 | public Rubberband(int duration) : base(EasingFunctions.BackEaseOut, duration)
23 | {
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Sequence.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace FluentTransitions.Methods
5 | {
6 | ///
7 | /// Allows the creation of user-defined transition methods, specified by a list of individual transition elements.
8 | ///
9 | /// 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 Sequence : IMethod
40 | {
41 | // The collection of elements that make up the transition...
42 | private IList _elements = null;
43 |
44 | // The total transition time...
45 | private double _duration = 0.0;
46 |
47 | // The element that we are currently in (i.e. the current time within this element)...
48 | private int _currentElement = 0;
49 |
50 | ///
51 | /// Allows the creation of user-defined transition methods, specified by a list of individual transition elements.
52 | ///
53 | public Sequence()
54 | {
55 | }
56 |
57 | ///
58 | /// Allows the creation of user-defined transition methods, specified by a list of individual transition elements.
59 | ///
60 | /// The elements to process during the transition
61 | /// The duration until the properties should have reached their destination values
62 | public Sequence(IList elements, TimeSpan duration) : this(elements, (int)duration.TotalMilliseconds)
63 | {
64 | }
65 |
66 | ///
67 | /// Allows the creation of user-defined transition methods, specified by a list of individual transition elements.
68 | ///
69 | /// The elements to process during the transition
70 | /// The duration in milliseconds until the properties should have reached their destination values
71 | public Sequence(IList elements, int duration)
72 | {
73 | Setup(elements, duration);
74 | }
75 |
76 | ///
77 | /// Sets up the transitions.
78 | ///
79 | public void Setup(IList elements, int duration)
80 | {
81 | _elements = elements;
82 | _duration = duration;
83 |
84 | // We check that the elements list has some members...
85 | if (elements?.Count == 0)
86 | throw new ArgumentException($"The list of elements passed to the constructor of {nameof(Sequence)} had zero elements. It must have at least one element.");
87 | }
88 |
89 | ///
90 | /// Called to find the value for the movement of properties for the time passed in.
91 | ///
92 | public void OnTimer(int time, out double percentage, out bool completed)
93 | {
94 | double transitionTimeFraction = time / _duration;
95 |
96 | // We find the information for the element that we are currently processing...
97 | GetElementInfo(transitionTimeFraction, out double elementStartTime, out double elementEndTime, out double elementStartValue, out double elementEndValue, out InterpolationMethod interpolationMethod);
98 |
99 | // We find how far through this element we are as a fraction...
100 | double elementInterval = elementEndTime - elementStartTime;
101 | double elementElapsedTime = transitionTimeFraction - elementStartTime;
102 | double elementTimeFraction = elementElapsedTime / elementInterval;
103 |
104 | // We convert the time-fraction to an fraction of the movement within the
105 | // element using the interpolation method...
106 | double elementDistance;
107 | switch (interpolationMethod)
108 | {
109 | case InterpolationMethod.Linear:
110 | elementDistance = elementTimeFraction;
111 | break;
112 |
113 | case InterpolationMethod.Accleration:
114 | elementDistance = Utility.ConvertLinearToAcceleration(elementTimeFraction);
115 | break;
116 |
117 | case InterpolationMethod.Deceleration:
118 | elementDistance = Utility.ConvertLinearToDeceleration(elementTimeFraction);
119 | break;
120 |
121 | case InterpolationMethod.EaseInEaseOut:
122 | elementDistance = Utility.ConvertLinearToEaseInEaseOut(elementTimeFraction);
123 | break;
124 |
125 | default:
126 | throw new InvalidOperationException($"Interpolation method not handled: {interpolationMethod}");
127 | }
128 |
129 | // We now know how far through the transition we have moved, so we can interpolate
130 | // the start and end values by this amount...
131 | percentage = Utility.Interpolate(elementStartValue, elementEndValue, elementDistance);
132 |
133 | // Has the transition completed?
134 | if (time >= _duration)
135 | {
136 | // The transition has completed, so we make sure that
137 | // it is at its final value...
138 | completed = true;
139 | percentage = elementEndValue;
140 | }
141 | else
142 | {
143 | completed = false;
144 | }
145 | }
146 |
147 | ///
148 | /// Returns the element info for the time-fraction passed in.
149 | ///
150 | private void GetElementInfo(double timeFraction, out double startTime, out double endTime, out double startValue, out double endValue, out InterpolationMethod interpolationMethod)
151 | {
152 | // We need to return the start and end values for the current element. So this
153 | // means finding the element for the time passed in as well as the previous element.
154 |
155 | // We hold the 'current' element as a hint. This was in fact the
156 | // element used the last time this function was called. In most cases
157 | // it will be the same one again, but it may have moved to a subsequent
158 | // on (maybe even skipping elements if enough time has passed)...
159 | int count = _elements.Count;
160 | for (; _currentElement < count; ++_currentElement)
161 | {
162 | TransitionElement element = _elements[_currentElement];
163 | double elementEndTime = element.EndTime / 100.0;
164 | if (timeFraction < elementEndTime)
165 | {
166 | break;
167 | }
168 | }
169 |
170 | // If we have gone past the last element, we just use the last element...
171 | if (_currentElement == count)
172 | {
173 | _currentElement = count - 1;
174 | }
175 |
176 | // We find the start values. These come from the previous element, except in the
177 | // case where we are currently in the first element, in which case they are zeros...
178 | startTime = 0.0;
179 | startValue = 0.0;
180 | if (_currentElement > 0)
181 | {
182 | var previousElement = _elements[_currentElement - 1];
183 | startTime = previousElement.EndTime / 100.0;
184 | startValue = previousElement.EndValue / 100.0;
185 | }
186 |
187 | // We get the end values from the current element...
188 | var currentElement = _elements[_currentElement];
189 | endTime = currentElement.EndTime / 100.0;
190 | endValue = currentElement.EndValue / 100.0;
191 | interpolationMethod = currentElement.InterpolationMethod;
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/Spring.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FluentTransitions.Methods
4 | {
5 | ///
6 | /// This transition interpolates values with EasingFunctions.ElasticEaseOut to mimic the behavior of a loaded spring.
7 | ///
8 | public class Spring : EaseWithFunction
9 | {
10 | ///
11 | /// Interpolates values with EasingFunctions.ElasticEaseOut to mimic the behavior of a loaded spring.
12 | ///
13 | /// The duration until the properties should have reached their destination values
14 | public Spring(TimeSpan duration) : this((int)duration.TotalMilliseconds)
15 | {
16 | }
17 |
18 | ///
19 | /// Interpolates values with EasingFunctions.ElasticEaseOut to mimic the behavior of a loaded spring.
20 | ///
21 | /// The duration in milliseconds until the properties should have reached their destination values
22 | public Spring(int duration) : base(EasingFunctions.ElasticEaseOut, duration)
23 | {
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/FluentTransitions/Methods/ThrowAndCatch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace FluentTransitions.Methods
5 | {
6 | ///
7 | /// This transition bounces the property to a destination value and back to the
8 | /// original value. It is decelerated to the destination and then acclerated back
9 | /// as if being thrown against gravity and then descending back with gravity.
10 | ///
11 | public class ThrowAndCatch : Sequence
12 | {
13 | ///
14 | /// Bounces the property values to their destination values and back to the original ones.
15 | /// They are decelerated to the destination and then acclerated back as if being thrown against gravity and then descending back with gravity.
16 | ///
17 | /// The duration until the properties should have reached their destination values
18 | public ThrowAndCatch(TimeSpan duration) : this((int)duration.TotalMilliseconds)
19 | {
20 | }
21 |
22 | ///
23 | /// Bounces the property values to their destination values and back to the original ones.
24 | /// They are decelerated to the destination and then acclerated back as if being thrown against gravity and then descending back with gravity.
25 | ///
26 | /// The duration in milliseconds until the properties should have reached their destination values
27 | public ThrowAndCatch(int duration)
28 | {
29 | // We create a custom "user-defined" transition to do the work...
30 | var elements = new List
31 | {
32 | new TransitionElement(50, 100, InterpolationMethod.Deceleration),
33 | new TransitionElement(100, 0, InterpolationMethod.Accleration)
34 | };
35 | base.Setup(elements, duration);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Transition.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reflection;
4 | using System.Diagnostics;
5 | using System.ComponentModel;
6 | using System.Windows.Forms;
7 | using FluentTransitions.ManagedTypes;
8 |
9 | namespace FluentTransitions
10 | {
11 | ///
12 | /// Lets you perform animated transitions of properties on arbitrary objects. These
13 | /// will often be transitions of UI properties, for example an animated fade-in of
14 | /// a UI object, or an animated move of a UI object from one position to another.
15 | ///
16 | /// Each transition can simulataneously change multiple properties, including properties
17 | /// across multiple objects.
18 | ///
19 | /// Example transition
20 | /// ------------------
21 | /// a. var transition = new Transition(new Linear(500));
22 | /// b. transition.add(form1, nameof(Width), 500);
23 | /// c. transition.add(form1, nameof(BackColor), Color.Red);
24 | /// d. transition.run();
25 | ///
26 | /// Line a: Creates a new transition. You specify the transition method.
27 | ///
28 | /// Lines b. and c: Set the destination values of the properties you are animating.
29 | ///
30 | /// Line d: Starts the transition.
31 | ///
32 | /// Transition methods
33 | /// ------------------
34 | /// TransitionMethod objects specify how the transition is made. Examples include
35 | /// linear transition, ease-in-ease-out and so on. Different transition methods may
36 | /// need different parameters.
37 | ///
38 | ///
39 | public class Transition
40 | {
41 | ///
42 | /// Event raised when the transition hass completed.
43 | ///
44 | public event EventHandler TransitionCompleted;
45 |
46 | // Helps us find the time interval from the time the transition starts to each timer tick...
47 | private readonly Stopwatch _stopwatch = new Stopwatch();
48 |
49 | // A map of Type info to IManagedType objects. These are all the types that we
50 | // know how to perform transitions on...
51 | private static readonly IDictionary _mapManagedTypes = new Dictionary();
52 |
53 | // The transition method used by this transition...
54 | private readonly IMethod _method = null;
55 |
56 | ///
57 | /// You should register all managed-types here.
58 | ///
59 | static Transition()
60 | {
61 | RegisterType(new ManagedInt());
62 | RegisterType(new ManagedFloat());
63 | RegisterType(new ManagedDouble());
64 | RegisterType(new ManagedColor());
65 | RegisterType(new ManagedString());
66 | }
67 |
68 | ///
69 | /// Includes a target object and interpolates its property value to the destination value
70 | ///
71 | /// The target object to include to the transition
72 | /// The name of the property to animate
73 | /// The destination value which should be reached at the end of the transition
74 | ///
75 | public static TransitionDefinition With(object target, string propertyName, object destinationValue)
76 | {
77 | return new TransitionDefinition()
78 | .With(target, propertyName, destinationValue);
79 | }
80 |
81 | ///
82 | /// Constructor. You pass in the object that holds the properties
83 | /// that you are performing transitions on.
84 | ///
85 | public Transition(IMethod transitionMethod)
86 | {
87 | _method = transitionMethod;
88 | }
89 |
90 | ///
91 | /// Creates and immediately runs a transition on the property passed in.
92 | ///
93 | internal static void Run(object target, string propertyName, object destinationValue, IMethod transitionMethod)
94 | {
95 | var transition = new Transition(transitionMethod);
96 | transition.Add(target, propertyName, destinationValue);
97 | transition.Run();
98 | }
99 |
100 | ///
101 | /// Sets the property passed in to the initial value passed in, then creates and
102 | /// immediately runs a transition on it.
103 | ///
104 | internal static void Run(object target, string propertyName, object initialValue, object destinationValue, IMethod transitionMethod)
105 | {
106 | Utility.SetValue(target, propertyName, initialValue);
107 | Run(target, propertyName, destinationValue, transitionMethod);
108 | }
109 |
110 | ///
111 | /// Creates a TransitionChain and runs it.
112 | ///
113 | public static void RunChain(params Transition[] transitions)
114 | {
115 | _ = new TransitionChain(transitions);
116 | }
117 |
118 | ///
119 | /// Adds a property that should be animated as part of this transition.
120 | ///
121 | public Transition Add(object target, string propertyName, object destinationValue)
122 | {
123 | // We get the property info...
124 | var targetType = target.GetType();
125 | var propertyInfo = targetType.GetProperty(propertyName);
126 | if (propertyInfo == null)
127 | throw new InvalidOperationException($"Object: {target} does not have the property: {propertyName}");
128 |
129 | // We check that we support the property type...
130 | var propertyType = propertyInfo.PropertyType;
131 | if (!_mapManagedTypes.ContainsKey(propertyType))
132 | throw new InvalidOperationException($"Transition does not handle properties of type: {propertyType}");
133 |
134 | // We can only transition properties that are both getable and setable...
135 | if (!propertyInfo.CanRead || !propertyInfo.CanWrite)
136 | throw new InvalidOperationException($"Property is not both getable and setable: {propertyName}");
137 |
138 | var managedType = _mapManagedTypes[propertyType];
139 |
140 | // We can manage this type, so we store the information for the
141 | // transition of this property...
142 | var info = new TransitionedPropertyInfo
143 | {
144 | EndValue = destinationValue,
145 | Target = target,
146 | PropertyInfo = propertyInfo,
147 | ManagedType = managedType
148 | };
149 |
150 | lock (_lock)
151 | {
152 | TransitionedProperties.Add(info);
153 | }
154 |
155 | return this;
156 | }
157 |
158 | ///
159 | /// Starts the transition.
160 | ///
161 | public void Run()
162 | {
163 | // We find the current start values for the properties we
164 | // are animating...
165 | foreach (TransitionedPropertyInfo info in TransitionedProperties)
166 | {
167 | object value = info.PropertyInfo.GetValue(info.Target, null);
168 | info.StartValue = info.ManagedType.Copy(value);
169 | }
170 |
171 | // We start the stopwatch. We use this when the timer ticks to measure
172 | // how long the transition has been runnning for...
173 | _stopwatch.Reset();
174 | _stopwatch.Start();
175 |
176 | // We register this transition with the transition manager...
177 | TransitionManager.GetInstance().Register(this);
178 | }
179 |
180 | ///
181 | /// We remove the property with the info passed in from the transition.
182 | ///
183 | internal void RemoveProperty(TransitionedPropertyInfo info)
184 | {
185 | lock (_lock)
186 | {
187 | TransitionedProperties.Remove(info);
188 | }
189 | }
190 |
191 | ///
192 | /// Called when the transition timer ticks.
193 | ///
194 | internal void OnTimer()
195 | {
196 | // When the timer ticks we:
197 | // a. Find the elapsed time since the transition started.
198 | // b. Work out the percentage movement for the properties we're managing.
199 | // c. Find the actual values of each property, and set them.
200 |
201 | // a.
202 | var elapsedTime = (int)_stopwatch.ElapsedMilliseconds;
203 |
204 | // b.
205 | _method.OnTimer(elapsedTime, out double percentage, out bool completed);
206 |
207 | // We take a copy of the list of properties we are transitioning, as
208 | // they can be changed by another thread while this method is running...
209 | var listTransitionedProperties = new List();
210 | lock (_lock)
211 | {
212 | foreach (TransitionedPropertyInfo info in TransitionedProperties)
213 | {
214 | listTransitionedProperties.Add(info.Copy());
215 | }
216 | }
217 |
218 | // c.
219 | foreach (TransitionedPropertyInfo info in listTransitionedProperties)
220 | {
221 | // We get the current value for this property...
222 | object value = info.ManagedType.GetIntermediateValue(info.StartValue, info.EndValue, percentage);
223 |
224 | // We set it...
225 | var args = new PropertyUpdateEventArgs(info.Target, info.PropertyInfo, value);
226 | SetProperty(this, args);
227 | }
228 |
229 | // Has the transition completed?
230 | if (completed)
231 | {
232 | // We stop the stopwatch and the timer...
233 | _stopwatch.Stop();
234 |
235 | // We raise an event to notify any observers that the transition has completed...
236 | Utility.RaiseEvent(TransitionCompleted, this, EventArgs.Empty);
237 | }
238 | }
239 |
240 | ///
241 | /// Sets a property on the object passed in to the value passed in. This method
242 | /// invokes itself on the GUI thread if the property is being invoked on a GUI
243 | /// object.
244 | ///
245 | private void SetProperty(object sender, PropertyUpdateEventArgs args)
246 | {
247 | try
248 | {
249 | // If the target is a control that has been disposed then we don't
250 | // try to update its properties. This can happen if the control is
251 | // on a form that has been closed while the transition is running...
252 | if (IsDisposed(args.Target))
253 | return;
254 |
255 | if (args.Target is ISynchronizeInvoke invokeTarget && invokeTarget.InvokeRequired)
256 | {
257 | // There is some history behind the next two lines, which is worth
258 | // going through to understand why they are the way they are.
259 |
260 | // Initially we used BeginInvoke without the subsequent WaitOne for
261 | // the result. A transition could involve a large number of updates
262 | // to a property, and as this call was asynchronous it would send a
263 | // large number of updates to the UI thread. These would queue up at
264 | // the GUI thread and mean that the UI could be some way behind where
265 | // the transition was.
266 |
267 | // The line was then changed to the blocking Invoke call instead. This
268 | // meant that the transition only proceded at the pace that the GUI
269 | // could process it, and the UI was not overloaded with "old" updates.
270 |
271 | // However, in some circumstances Invoke could block and lock up the
272 | // Transitions background thread. In particular, this can happen if the
273 | // control that we are trying to update is in the process of being
274 | // disposed - for example, it is on a form that is being closed. See
275 | // here for details:
276 | // http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/7d2c941a-0016-431a-abba-67c5d5dac6a5
277 |
278 | // To solve this, we use a combination of the two earlier approaches.
279 | // We use BeginInvoke as this does not block and lock up, even if the
280 | // underlying object is being disposed. But we do want to wait to give
281 | // the UI a chance to process the update. So what we do is to do the
282 | // asynchronous BeginInvoke, but then wait (with a short timeout) for
283 | // it to complete.
284 | var asyncResult = invokeTarget.BeginInvoke(new EventHandler(SetProperty), new object[] { sender, args });
285 | asyncResult.AsyncWaitHandle.WaitOne(50);
286 | }
287 | else
288 | {
289 | // We are on the correct thread, so we update the property...
290 | args.PropertyInfo.SetValue(args.Target, args.Value, null);
291 | }
292 | }
293 | catch
294 | {
295 | // We silently catch any exceptions. These could be things like
296 | // bounds exceptions when setting properties.
297 | }
298 | }
299 |
300 | ///
301 | /// Returns true if the object passed in is a Control and is disposed
302 | /// or in the process of disposing. (If this is the case, we don't want
303 | /// to make any changes to its properties.)
304 | ///
305 | private bool IsDisposed(object target)
306 | {
307 | // Is the object passed in a Control?
308 | if (!(target is Control controlTarget))
309 | return false;
310 |
311 | // Is it disposed or disposing?
312 | return controlTarget.IsDisposed || controlTarget.Disposing;
313 | }
314 |
315 | ///
316 | /// Registers a transition-type. We hold them in a map.
317 | ///
318 | private static void RegisterType(IManagedType transitionType)
319 | {
320 | var type = transitionType.GetManagedType();
321 | _mapManagedTypes[type] = transitionType;
322 | }
323 |
324 | ///
325 | /// Property that returns a list of information about each property managed
326 | /// by this transition.
327 | ///
328 | internal IList TransitionedProperties { get; } = new List();
329 |
330 | // Holds information about one property on one taregt object that we are performing
331 | // a transition on...
332 | internal class TransitionedPropertyInfo
333 | {
334 | public object StartValue;
335 | public object EndValue;
336 | public object Target;
337 | public PropertyInfo PropertyInfo;
338 | public IManagedType ManagedType;
339 |
340 | public TransitionedPropertyInfo Copy()
341 | {
342 | return new TransitionedPropertyInfo
343 | {
344 | StartValue = StartValue,
345 | EndValue = EndValue,
346 | Target = Target,
347 | PropertyInfo = PropertyInfo,
348 | ManagedType = ManagedType
349 | };
350 | }
351 | }
352 |
353 | // Event args used for the event we raise when updating a property...
354 | private class PropertyUpdateEventArgs : EventArgs
355 | {
356 | public PropertyUpdateEventArgs(object t, PropertyInfo pi, object v)
357 | {
358 | Target = t;
359 | PropertyInfo = pi;
360 | Value = v;
361 | }
362 |
363 | public object Target;
364 |
365 | public PropertyInfo PropertyInfo;
366 |
367 | public object Value;
368 | }
369 |
370 | // An object used to lock the list of transitioned properties, as it can be
371 | // accessed by multiple threads...
372 | private readonly object _lock = new object();
373 | }
374 | }
375 |
--------------------------------------------------------------------------------
/src/FluentTransitions/TransitionChain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace FluentTransitions
5 | {
6 | internal class TransitionChain
7 | {
8 | // The list of transitions in the chain...
9 | private readonly LinkedList _listTransitions = new LinkedList();
10 |
11 | public TransitionChain(params Transition[] transitions)
12 | {
13 | // We store the list of transitions...
14 | foreach (Transition transition in transitions)
15 | _listTransitions.AddLast(transition);
16 |
17 | // We start running them...
18 | RunNextTransition();
19 | }
20 |
21 | ///
22 | /// Runs the next transition in the list.
23 | ///
24 | private void RunNextTransition()
25 | {
26 | if (_listTransitions.Count == 0)
27 | return;
28 |
29 | // We find the next transition and run it. We also register
30 | // for its completed event, so that we can start the next transition
31 | // when this one completes...
32 | var nextTransition = _listTransitions.First.Value;
33 | nextTransition.TransitionCompleted += OnTransitionCompleted;
34 | nextTransition.Run();
35 | }
36 |
37 | ///
38 | /// Called when the transition we have just run has completed.
39 | ///
40 | private void OnTransitionCompleted(object sender, EventArgs e)
41 | {
42 | // We unregister from the completed event...
43 | var transition = (Transition)sender;
44 | transition.TransitionCompleted -= OnTransitionCompleted;
45 |
46 | // We remove the completed transition from our collection, and
47 | // run the next one...
48 | _listTransitions.RemoveFirst();
49 | RunNextTransition();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/FluentTransitions/TransitionDefinition.cs:
--------------------------------------------------------------------------------
1 | using FluentTransitions.Methods;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Threading;
5 | using System.Windows.Forms;
6 |
7 | namespace FluentTransitions
8 | {
9 | ///
10 | /// The transition definition providing fluent syntax to build and run transitions
11 | ///
12 | public class TransitionDefinition
13 | {
14 | private readonly List _targetPropertyDestinations = new List();
15 | private Action _completionHook;
16 |
17 | ///
18 | /// Includes a target object and interpolates its property value to the destination value
19 | ///
20 | /// The target object to include to the transition
21 | /// The name of the property to animate
22 | /// The destination value which should be reached at the end of the transition
23 | ///
24 | public TransitionDefinition With(object target, string propertyName, object destinationValue)
25 | {
26 | _targetPropertyDestinations.Add(new TargetPropertyDestination
27 | {
28 | Target = target,
29 | PropertyName = propertyName,
30 | DestinationValue = destinationValue
31 | });
32 |
33 | return this;
34 | }
35 |
36 |
37 | ///
38 | /// Defines a hook that gets called as soon as the transition completes
39 | ///
40 | /// A delegate which gets called as soon as the transition did complete
41 | public TransitionDefinition HookOnCompletion(Action hookDelegate)
42 | {
43 | _completionHook = hookDelegate;
44 | return this;
45 | }
46 |
47 | ///
48 | /// Defines a hook that gets called as soon as the transition completes
49 | ///
50 | /// Any control to be used to invoke the hookDelegate to the UI thread
51 | /// A delegate which gets called as soon as the transition did complete
52 | public TransitionDefinition HookOnCompletionInUiThread(Control controlToInvoke, Action hookDelegate)
53 | {
54 | if (hookDelegate is object)
55 | _completionHook = () => controlToInvoke.BeginInvoke((Action)(() => hookDelegate.Invoke()));
56 | else
57 | _completionHook = null;
58 |
59 | return this;
60 | }
61 |
62 | ///
63 | /// Defines a hook that gets called as soon as the transition completes
64 | ///
65 | /// The synchronization context used to invoke the hookDelegate to the UI thread
66 | /// A delegate which gets called as soon as the transition did complete
67 | public TransitionDefinition HookOnCompletionInUiThread(SynchronizationContext synchronizationContext, Action hookDelegate)
68 | {
69 | if (hookDelegate is object)
70 | _completionHook = () => synchronizationContext.Post(_ => hookDelegate.Invoke(), null);
71 | else
72 | _completionHook = null;
73 |
74 | return this;
75 | }
76 |
77 | ///
78 | /// Alters the property values to their destination values from a standing start with accelerating intervals.
79 | ///
80 | /// The duration until the properties should have reached their destination values
81 | public void Accelerate(TimeSpan duration)
82 | {
83 | BuildAndRun(new Acceleration(duration));
84 | }
85 |
86 | ///
87 | /// Bounces the property values to their destination values and back to the original ones.
88 | /// They are accelerated to the destination and then decelerated back as if being dropped with gravity and bouncing back against gravity.
89 | ///
90 | /// The duration until the properties should have reached their destination values
91 | public void Bounce(TimeSpan duration)
92 | {
93 | BuildAndRun(new Bounce(duration));
94 | }
95 |
96 | ///
97 | /// Alters the property values with an exponential decay.
98 | /// This has a damping effect similar to the motion of a needle on an electomagnetically controlled dial.
99 | ///
100 | /// The duration until the properties should have reached their destination values
101 | public void CriticalDamp(TimeSpan duration)
102 | {
103 | BuildAndRun(new CriticalDamping(duration));
104 | }
105 |
106 | ///
107 | /// Alters the property values starting from a high speed and decelerating to zero by the end of the transition.
108 | ///
109 | /// The duration until the properties should have reached their destination values
110 | public void Decelerate(TimeSpan duration)
111 | {
112 | BuildAndRun(new Deceleration(duration));
113 | }
114 |
115 | ///
116 | /// Alters the property values in an ease-in-ease-out transition.
117 | /// This accelerates during the first half of the transition, and then decelerates during the second half.
118 | ///
119 | /// The duration until the properties should have reached their destination values
120 | public void EaseInEaseOut(TimeSpan duration)
121 | {
122 | BuildAndRun(new EaseInEaseOut(duration));
123 | }
124 |
125 | ///
126 | /// Flashes the property values a specified number of times, ending up by reverting them to their initial values.
127 | ///
128 | /// The number of flashes to animate
129 | /// The duration of each flash
130 | public void Flash(int numberOfFlashes, TimeSpan durationOfEachFlash)
131 | {
132 | BuildAndRun(new Flash(numberOfFlashes, durationOfEachFlash));
133 | }
134 |
135 | ///
136 | /// Alters the property values in a linear way until they reach their destination values.
137 | ///
138 | /// The duration until the properties should have reached their destination values
139 | public void Linear(TimeSpan duration)
140 | {
141 | BuildAndRun(new Linear(duration));
142 | }
143 |
144 | ///
145 | /// Bounces the property values to their destination values and back to the original ones.
146 | /// They are decelerated to the destination and then acclerated back as if being thrown against gravity and then descending back with gravity.
147 | ///
148 | /// The duration until the properties should have reached their destination values
149 | public void ThrowAndCatch(TimeSpan duration)
150 | {
151 | BuildAndRun(new ThrowAndCatch(duration));
152 | }
153 |
154 | ///
155 | /// Allows the creation of user-defined transition methods, specified by a list of individual transition elements.
156 | ///
157 | /// Each of these defines:
158 | /// End time, End value, Interpolation method
159 | ///
160 | /// For example, say you want to make a bouncing effect with a decay:
161 | ///
162 | /// EndTime% EndValue% Interpolation
163 | /// -------- --------- -------------
164 | /// 50 100 Acceleration
165 | /// 75 50 Deceleration
166 | /// 85 100 Acceleration
167 | /// 91 75 Deceleration
168 | /// 95 100 Acceleration
169 | /// 98 90 Deceleration
170 | /// 100 100 Acceleration
171 | ///
172 | /// The time values are expressed as a percentage of the overall transition time. This
173 | /// means that you can create a user-defined transition-type and then use it for transitions
174 | /// of different lengths.
175 | ///
176 | /// The values are percentages of the values between the start and end values of the properties
177 | /// being animated in the transitions. 0% is the start value and 100% is the end value.
178 | ///
179 | /// The interpolation is one of the values from the InterpolationMethod enum.
180 | ///
181 | /// So the example above accelerates to the destination (as if under gravity) by
182 | /// t=50%, then bounces back up to half the initial height by t=75%, slowing down
183 | /// (as if against gravity) before falling down again and bouncing to decreasing
184 | /// heights each time.
185 | ///
186 | ///
187 | /// The elements to process during the transition
188 | /// The duration until the properties should have reached their destination values
189 | public void Sequence(IList elements, TimeSpan duration)
190 | {
191 | BuildAndRun(new Sequence(elements, duration));
192 | }
193 |
194 | ///
195 | /// Interpolates values with EasingFunctions.BackEaseOut to mimic the behavior of a rubber band stopping a movement and pulling it back.
196 | ///
197 | /// The duration until the properties should have reached their destination values
198 | public void Rubberband(TimeSpan duration)
199 | {
200 | BuildAndRun(new Rubberband(duration));
201 | }
202 |
203 | ///
204 | /// Interpolates values with EasingFunctions.ElasticEaseOut to mimic the behavior of a loaded spring.
205 | ///
206 | /// The duration until the properties should have reached their destination values
207 | public void Spring(TimeSpan duration)
208 | {
209 | BuildAndRun(new Spring(duration));
210 | }
211 |
212 | ///
213 | /// Allows natural transitions with custom or predefined easing functions.
214 | /// Easing functions are mathematical functions that are used to interpolate values between two endpoints
215 | /// usually with non-linear results.
216 | ///
217 | ///
218 | /// The function to interpolate values with. See "" for prebuilt easing functions.
219 | /// Based on Mauro Sampietro's article on CodeProject: https://www.codeproject.com/Articles/827808/Control-Animation-in-Winforms
220 | ///
221 | /// The duration until the properties should have reached their destination values
222 | public void EaseWithFunction(EasingFunction easingFunction, TimeSpan duration)
223 | {
224 | BuildAndRun(new EaseWithFunction(easingFunction, duration));
225 | }
226 |
227 | ///
228 | /// Builds a transition with a given method and runs it immediately
229 | ///
230 | /// The method the transition should be built with
231 | private void BuildAndRun(IMethod method)
232 | {
233 | Build(method).Run();
234 | }
235 |
236 | ///
237 | /// Builds and returns a transition with a given method
238 | ///
239 | /// The method the transition should be built with
240 | public Transition Build(IMethod method)
241 | {
242 | var transition = new Transition(method);
243 |
244 | foreach (var item in _targetPropertyDestinations)
245 | transition.Add(item.Target, item.PropertyName, item.DestinationValue);
246 |
247 | if (_completionHook is object)
248 | {
249 | void SelfRemovingCompletionHandler(object s, EventArgs e)
250 | {
251 | transition.TransitionCompleted -= SelfRemovingCompletionHandler;
252 | _completionHook.Invoke();
253 | }
254 |
255 | transition.TransitionCompleted += SelfRemovingCompletionHandler;
256 | }
257 |
258 | return transition;
259 | }
260 |
261 | internal class TargetPropertyDestination
262 | {
263 | public object Target { get; set; }
264 |
265 | public string PropertyName { get; set; }
266 |
267 | public object DestinationValue { get; set; }
268 | }
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/src/FluentTransitions/TransitionElement.cs:
--------------------------------------------------------------------------------
1 | namespace FluentTransitions
2 | {
3 | ///
4 | /// An individual part of a transition defining the method to interpolate towards a desitination value and how log this should take.
5 | ///
6 | public class TransitionElement
7 | {
8 | ///
9 | /// Creates a new transition element
10 | ///
11 | /// The percentage of elapsed time, expressed as (for example) 75 for 75%.
12 | /// The value of the animated properties at the EndTime.
13 | /// This is the percentage movement of the properties between their start and end values.
14 | /// This should be expressed as (for example) 75 for 75%.
15 | /// The interpolation method to use when moving between the previous value and the current one.
16 | public TransitionElement(double endTime, double endValue, InterpolationMethod interpolationMethod)
17 | {
18 | EndTime = endTime;
19 | EndValue = endValue;
20 | InterpolationMethod = interpolationMethod;
21 | }
22 |
23 | ///
24 | /// The percentage of elapsed time, expressed as (for example) 75 for 75%.
25 | ///
26 | public double EndTime { get; set; }
27 |
28 | ///
29 | /// The value of the animated properties at the EndTime. This is the percentage
30 | /// movement of the properties between their start and end values. This should
31 | /// be expressed as (for example) 75 for 75%.
32 | ///
33 | public double EndValue { get; set; }
34 |
35 | ///
36 | /// The interpolation method to use when moving between the previous value
37 | /// and the current one.
38 | ///
39 | public InterpolationMethod InterpolationMethod { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/FluentTransitions/TransitionManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Timers;
4 |
5 | namespace FluentTransitions
6 | {
7 | ///
8 | /// This class is responsible for running transitions. It holds the timer that
9 | /// triggers transition animation.
10 | ///
11 | /// This class is a singleton.
12 | ///
13 | /// We manage the transition timer here so that we can have a single timer
14 | /// across all transitions. If each transition has its own timer, this creates
15 | /// one thread for each transition, and this can lead to too many threads in
16 | /// an application.
17 | ///
18 | /// This class essentially just manages the timer for the transitions. It calls
19 | /// back into the running transitions, which do the actual work of the transition.
20 | ///
21 | ///
22 | internal class TransitionManager
23 | {
24 | // The singleton instance...
25 | private static TransitionManager _instance = null;
26 |
27 | // The collection of transitions we're managing. (This should really be a set.)
28 | private readonly IDictionary _transitions = new Dictionary();
29 |
30 | // The timer that controls the transition animation...
31 | private readonly Timer _timer = null;
32 |
33 | // An object to lock on. This class can be accessed by multiple threads: the
34 | // user thread can add new transitions; and the timerr thread can be animating
35 | // them. As they access the same collections, the methods need to be protected
36 | // by a lock...
37 | private readonly object _lock = new object();
38 |
39 | ///
40 | /// Private constructor (for singleton).
41 | ///
42 | private TransitionManager()
43 | {
44 | _timer = new Timer(15);
45 | _timer.Elapsed += OnTimerElapsed;
46 | _timer.Enabled = true;
47 | }
48 |
49 | ///
50 | /// Singleton's getInstance method.
51 | ///
52 | public static TransitionManager GetInstance()
53 | {
54 | if (_instance == null)
55 | _instance = new TransitionManager();
56 |
57 | return _instance;
58 | }
59 |
60 | ///
61 | /// You register a transition with the manager here. This will start to run
62 | /// the transition as the manager's timer ticks.
63 | ///
64 | public void Register(Transition transition)
65 | {
66 | lock (_lock)
67 | {
68 | // We check to see if the properties of this transition
69 | // are already being animated by any existing transitions...
70 | RemoveDuplicates(transition);
71 |
72 | // We add the transition to the collection we manage, and
73 | // observe it so that we know when it has completed...
74 | _transitions[transition] = true;
75 | transition.TransitionCompleted += OnTransitionCompleted;
76 | }
77 | }
78 |
79 | ///
80 | /// Checks if any existing transitions are acting on the same properties as the
81 | /// transition passed in. If so, we remove the duplicated properties from the
82 | /// older transitions.
83 | ///
84 | private void RemoveDuplicates(Transition transition)
85 | {
86 | // We look through the set of transitions we're currently managing...
87 | foreach (KeyValuePair pair in _transitions)
88 | RemoveDuplicates(transition, pair.Key);
89 | }
90 |
91 | ///
92 | /// Finds any properties in the old-transition that are also in the new one,
93 | /// and removes them from the old one.
94 | ///
95 | private void RemoveDuplicates(Transition newTransition, Transition oldTransition)
96 | {
97 | // Note: This checking might be a bit more efficient if it did the checking
98 | // with a set rather than looking through lists. That said, it is only done
99 | // when transitions are added (which isn't very often) rather than on the
100 | // timer, so I don't think this matters too much.
101 |
102 | // We get the list of properties for the old and new transitions...
103 | var newProperties = newTransition.TransitionedProperties;
104 | var oldProperties = oldTransition.TransitionedProperties;
105 |
106 | // We loop through the old properties backwards (as we may be removing
107 | // items from the list if we find a match)...
108 | for (int i = oldProperties.Count - 1; i >= 0; i--)
109 | {
110 | // We get one of the properties from the old transition...
111 | var oldProperty = oldProperties[i];
112 |
113 | // Is this property part of the new transition?
114 | foreach (var newProperty in newProperties)
115 | {
116 | if (oldProperty.Target == newProperty.Target
117 | && oldProperty.PropertyInfo == newProperty.PropertyInfo)
118 | {
119 | // The old transition contains the same property as the new one,
120 | // so we remove it from the old transition...
121 | oldTransition.RemoveProperty(oldProperty);
122 | }
123 | }
124 | }
125 | }
126 |
127 | ///
128 | /// Called when the timer ticks.
129 | ///
130 | private void OnTimerElapsed(object sender, ElapsedEventArgs e)
131 | {
132 | // We turn the timer off while we process the tick, in case the
133 | // actions take longer than the tick itself...
134 | if (_timer == null)
135 | return;
136 |
137 | _timer.Enabled = false;
138 |
139 | IList listTransitions;
140 | lock (_lock)
141 | {
142 | // We take a copy of the collection of transitions as elements
143 | // might be removed as we iterate through it...
144 | listTransitions = new List();
145 | foreach (KeyValuePair pair in _transitions)
146 | listTransitions.Add(pair.Key);
147 | }
148 |
149 | // We tick the timer for each transition we're managing...
150 | foreach (var transition in listTransitions)
151 | transition.OnTimer();
152 |
153 | // We restart the timer...
154 | _timer.Enabled = true;
155 | }
156 |
157 | ///
158 | /// Called when a transition has completed.
159 | ///
160 | private void OnTransitionCompleted(object sender, EventArgs e)
161 | {
162 | // We stop observing the transition...
163 | var transition = (Transition)sender;
164 | transition.TransitionCompleted -= OnTransitionCompleted;
165 |
166 | // We remove the transition from the collection we're managing...
167 | lock (_lock)
168 | {
169 | _transitions.Remove(transition);
170 | }
171 | }
172 | }
173 | }
174 |
175 |
176 |
--------------------------------------------------------------------------------
/src/FluentTransitions/Utility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace FluentTransitions
5 | {
6 | ///
7 | /// A class holding static utility functions.
8 | ///
9 | internal static class Utility
10 | {
11 | ///
12 | /// Returns the value of the property passed in.
13 | ///
14 | public static object GetValue(object target, string propertyName)
15 | {
16 | var targetType = target.GetType();
17 | var propertyInfo = targetType.GetProperty(propertyName);
18 | if (propertyInfo == null)
19 | throw new InvalidOperationException($"Object: {target} does not have the property: {propertyName}");
20 |
21 | return propertyInfo.GetValue(target, null);
22 | }
23 |
24 | ///
25 | /// Sets the value of the property passed in.
26 | ///
27 | public static void SetValue(object target, string propertyName, object value)
28 | {
29 | var targetType = target.GetType();
30 | var propertyInfo = targetType.GetProperty(propertyName);
31 | if (propertyInfo == null)
32 | throw new InvalidOperationException($"Object: {target} does not have the property: {propertyName}");
33 |
34 | propertyInfo.SetValue(target, value, null);
35 | }
36 |
37 | ///
38 | /// Returns a value between d1 and d2 for the percentage passed in.
39 | ///
40 | public static double Interpolate(double value1, double value2, double percentage)
41 | {
42 | double difference = value2 - value1;
43 | double distance = difference * percentage;
44 | double result = value1 + distance;
45 |
46 | return result;
47 | }
48 |
49 | ///
50 | /// Returns a value betweeen i1 and i2 for the percentage passed in.
51 | ///
52 | public static int Interpolate(int value1, int value2, double percentage)
53 | {
54 | return (int)Interpolate((double)value1, (double)value2, percentage);
55 | }
56 |
57 | ///
58 | /// Returns a value betweeen f1 and f2 for the percentage passed in.
59 | ///
60 | public static float Interpolate(float value1, float value2, double percentage)
61 | {
62 | return (float)Interpolate((double)value1, (double)value2, percentage);
63 | }
64 |
65 | ///
66 | /// Converts a fraction representing linear time to a fraction representing
67 | /// the distance traveled under an ease-in-ease-out transition.
68 | ///
69 | public static double ConvertLinearToEaseInEaseOut(double elapsed)
70 | {
71 | // The distance traveled is made up of two parts: the initial acceleration,
72 | // and then the subsequent deceleration...
73 | double firstHalfTime = (elapsed > 0.5) ? 0.5 : elapsed;
74 | double secondHalfTime = (elapsed > 0.5) ? elapsed - 0.5 : 0.0;
75 | double result = 2 * firstHalfTime * firstHalfTime + 2 * secondHalfTime * (1.0 - secondHalfTime);
76 | return result;
77 | }
78 |
79 | ///
80 | /// Converts a fraction representing linear time to a fraction representing
81 | /// the distance traveled under a constant acceleration transition.
82 | ///
83 | public static double ConvertLinearToAcceleration(double elapsed)
84 | {
85 | return elapsed * elapsed;
86 | }
87 |
88 | ///
89 | /// Converts a fraction representing linear time to a fraction representing
90 | /// the distance traveled under a constant deceleration transition.
91 | ///
92 | public static double ConvertLinearToDeceleration(double elapsed)
93 | {
94 | return elapsed * (2.0 - elapsed);
95 | }
96 |
97 | ///
98 | /// Fires the event passed in in a thread-safe way.
99 | ///
100 | /// This method loops through the targets of the event and invokes each in turn. If the
101 | /// target supports ISychronizeInvoke (such as forms or controls) and is set to run
102 | /// on a different thread, then we call BeginInvoke to marshal the event to the target
103 | /// thread. If the target does not support this interface (such as most non-form classes)
104 | /// or we are on the same thread as the target, then the event is fired on the same
105 | /// thread as this is called from.
106 | ///
107 | public static void RaiseEvent(EventHandler theEvent, object sender, T args) where T : System.EventArgs
108 | {
109 | if (theEvent == null)
110 | return;
111 |
112 | // We loop through each of the delegate handlers for this event. For each of
113 | // them we need to decide whether to invoke it on the current thread or to
114 | // make a cross-thread invocation...
115 | foreach (EventHandler handler in theEvent.GetInvocationList())
116 | {
117 | try
118 | {
119 | if (!(handler.Target is ISynchronizeInvoke target) || !target.InvokeRequired)
120 | {
121 | // Either the target is not a form or control, or we are already
122 | // on the right thread for it. Either way we can just fire the
123 | // event as normal...
124 | handler(sender, args);
125 | }
126 | else
127 | {
128 | // The target is most likely a form or control that needs the
129 | // handler to be invoked on its own thread...
130 | target.BeginInvoke(handler, new object[] { sender, args });
131 | }
132 | }
133 | catch
134 | {
135 | // The event handler may have been detached while processing the events.
136 | // We just ignore this and invoke the remaining handlers.
137 | }
138 | }
139 | }
140 | }
141 | }
--------------------------------------------------------------------------------
/src/TestApp/DemoForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace TestApp
2 | {
3 | partial class DemoForm
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 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DemoForm));
32 | this.cmdRipple = new System.Windows.Forms.Button();
33 | this.cmdThrowAndCatch = new System.Windows.Forms.Button();
34 | this.groupBox1 = new System.Windows.Forms.GroupBox();
35 | this.lblTextTransition2 = new System.Windows.Forms.Label();
36 | this.lblTextTransition1 = new System.Windows.Forms.Label();
37 | this.cmdTextTransition = new System.Windows.Forms.Button();
38 | this.gbThrowAndCatch = new System.Windows.Forms.GroupBox();
39 | this.gbRipple = new System.Windows.Forms.GroupBox();
40 | this.cmdMore = new System.Windows.Forms.Button();
41 | this.groupBox2 = new System.Windows.Forms.GroupBox();
42 | this.cmdSwapPictures = new System.Windows.Forms.Button();
43 | this.groupBox3 = new System.Windows.Forms.GroupBox();
44 | this.label1 = new System.Windows.Forms.Label();
45 | this.txtPassword = new System.Windows.Forms.TextBox();
46 | this.buttonDemo = new System.Windows.Forms.Button();
47 | this.gpEasing = new System.Windows.Forms.GroupBox();
48 | this.label9 = new System.Windows.Forms.Label();
49 | this.label8 = new System.Windows.Forms.Label();
50 | this.label6 = new System.Windows.Forms.Label();
51 | this.buttonThrowAndCatch = new System.Windows.Forms.Button();
52 | this.buttonLinear = new System.Windows.Forms.Button();
53 | this.buttonFlash = new System.Windows.Forms.Button();
54 | this.buttonEaseInEaseOut = new System.Windows.Forms.Button();
55 | this.buttonDecelerate = new System.Windows.Forms.Button();
56 | this.buttonCriticalDamp = new System.Windows.Forms.Button();
57 | this.buttonBounce = new System.Windows.Forms.Button();
58 | this.buttonAccelerate = new System.Windows.Forms.Button();
59 | this.buttonSineEaseOut = new System.Windows.Forms.Button();
60 | this.buttonQuintEaseOut = new System.Windows.Forms.Button();
61 | this.buttonQuartEaseOut = new System.Windows.Forms.Button();
62 | this.buttonQuadEaseOut = new System.Windows.Forms.Button();
63 | this.buttonExpoEaseOut = new System.Windows.Forms.Button();
64 | this.buttonElasticEaseOut = new System.Windows.Forms.Button();
65 | this.buttonCubicEaseOut = new System.Windows.Forms.Button();
66 | this.buttonCircEaseOut = new System.Windows.Forms.Button();
67 | this.buttonBounceEaseOut = new System.Windows.Forms.Button();
68 | this.buttonBackEaseOut = new System.Windows.Forms.Button();
69 | this.label5 = new System.Windows.Forms.Label();
70 | this.label4 = new System.Windows.Forms.Label();
71 | this.label3 = new System.Windows.Forms.Label();
72 | this.label2 = new System.Windows.Forms.Label();
73 | this.label7 = new System.Windows.Forms.Label();
74 | this.lblTargetLine = new System.Windows.Forms.Label();
75 | this.buttonSprings = new System.Windows.Forms.Button();
76 | this.ctrlPictures = new TestApp.KittenPuppyControl();
77 | this.ctrlRipple = new TestApp.RippleControl();
78 | this.groupBox1.SuspendLayout();
79 | this.gbThrowAndCatch.SuspendLayout();
80 | this.gbRipple.SuspendLayout();
81 | this.groupBox2.SuspendLayout();
82 | this.groupBox3.SuspendLayout();
83 | this.gpEasing.SuspendLayout();
84 | this.SuspendLayout();
85 | //
86 | // cmdRipple
87 | //
88 | this.cmdRipple.Location = new System.Drawing.Point(9, 29);
89 | this.cmdRipple.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
90 | this.cmdRipple.Name = "cmdRipple";
91 | this.cmdRipple.Size = new System.Drawing.Size(290, 57);
92 | this.cmdRipple.TabIndex = 9;
93 | this.cmdRipple.Text = "Ripple";
94 | this.cmdRipple.UseVisualStyleBackColor = true;
95 | this.cmdRipple.Click += new System.EventHandler(this.cmdRipple_Click);
96 | //
97 | // cmdThrowAndCatch
98 | //
99 | this.cmdThrowAndCatch.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
100 | this.cmdThrowAndCatch.Location = new System.Drawing.Point(9, 1226);
101 | this.cmdThrowAndCatch.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
102 | this.cmdThrowAndCatch.Name = "cmdThrowAndCatch";
103 | this.cmdThrowAndCatch.Size = new System.Drawing.Size(298, 52);
104 | this.cmdThrowAndCatch.TabIndex = 11;
105 | this.cmdThrowAndCatch.Text = "Throw and Catch";
106 | this.cmdThrowAndCatch.UseVisualStyleBackColor = true;
107 | this.cmdThrowAndCatch.Click += new System.EventHandler(this.cmdThrowAndCatch_Click);
108 | //
109 | // groupBox1
110 | //
111 | this.groupBox1.Controls.Add(this.lblTextTransition2);
112 | this.groupBox1.Controls.Add(this.lblTextTransition1);
113 | this.groupBox1.Controls.Add(this.cmdTextTransition);
114 | this.groupBox1.Location = new System.Drawing.Point(1020, 478);
115 | this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
116 | this.groupBox1.Name = "groupBox1";
117 | this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
118 | this.groupBox1.Size = new System.Drawing.Size(316, 155);
119 | this.groupBox1.TabIndex = 13;
120 | this.groupBox1.TabStop = false;
121 | this.groupBox1.Text = "Text transition";
122 | //
123 | // lblTextTransition2
124 | //
125 | this.lblTextTransition2.AutoSize = true;
126 | this.lblTextTransition2.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
127 | this.lblTextTransition2.ForeColor = System.Drawing.Color.Crimson;
128 | this.lblTextTransition2.Location = new System.Drawing.Point(10, 115);
129 | this.lblTextTransition2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
130 | this.lblTextTransition2.Name = "lblTextTransition2";
131 | this.lblTextTransition2.Size = new System.Drawing.Size(286, 22);
132 | this.lblTextTransition2.TabIndex = 15;
133 | this.lblTextTransition2.Text = "A longer piece of text.";
134 | //
135 | // lblTextTransition1
136 | //
137 | this.lblTextTransition1.AutoSize = true;
138 | this.lblTextTransition1.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
139 | this.lblTextTransition1.ForeColor = System.Drawing.Color.Blue;
140 | this.lblTextTransition1.Location = new System.Drawing.Point(9, 91);
141 | this.lblTextTransition1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
142 | this.lblTextTransition1.Name = "lblTextTransition1";
143 | this.lblTextTransition1.Size = new System.Drawing.Size(166, 22);
144 | this.lblTextTransition1.TabIndex = 14;
145 | this.lblTextTransition1.Text = "Hello, World!";
146 | //
147 | // cmdTextTransition
148 | //
149 | this.cmdTextTransition.Location = new System.Drawing.Point(9, 29);
150 | this.cmdTextTransition.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
151 | this.cmdTextTransition.Name = "cmdTextTransition";
152 | this.cmdTextTransition.Size = new System.Drawing.Size(290, 57);
153 | this.cmdTextTransition.TabIndex = 13;
154 | this.cmdTextTransition.Text = "Text Transition";
155 | this.cmdTextTransition.UseVisualStyleBackColor = true;
156 | this.cmdTextTransition.Click += new System.EventHandler(this.cmdTextTransition_Click);
157 | //
158 | // gbThrowAndCatch
159 | //
160 | this.gbThrowAndCatch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
161 | | System.Windows.Forms.AnchorStyles.Left)));
162 | this.gbThrowAndCatch.Controls.Add(this.cmdThrowAndCatch);
163 | this.gbThrowAndCatch.Location = new System.Drawing.Point(-316, 77);
164 | this.gbThrowAndCatch.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
165 | this.gbThrowAndCatch.Name = "gbThrowAndCatch";
166 | this.gbThrowAndCatch.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
167 | this.gbThrowAndCatch.Size = new System.Drawing.Size(316, 1287);
168 | this.gbThrowAndCatch.TabIndex = 15;
169 | this.gbThrowAndCatch.TabStop = false;
170 | this.gbThrowAndCatch.Text = "Throw and Catch";
171 | //
172 | // gbRipple
173 | //
174 | this.gbRipple.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
175 | | System.Windows.Forms.AnchorStyles.Left)));
176 | this.gbRipple.Controls.Add(this.cmdRipple);
177 | this.gbRipple.Controls.Add(this.ctrlRipple);
178 | this.gbRipple.Location = new System.Drawing.Point(1020, 643);
179 | this.gbRipple.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
180 | this.gbRipple.Name = "gbRipple";
181 | this.gbRipple.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
182 | this.gbRipple.Size = new System.Drawing.Size(316, 713);
183 | this.gbRipple.TabIndex = 18;
184 | this.gbRipple.TabStop = false;
185 | this.gbRipple.Text = "Ripple";
186 | //
187 | // cmdMore
188 | //
189 | this.cmdMore.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
190 | this.cmdMore.Location = new System.Drawing.Point(1242, 25);
191 | this.cmdMore.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
192 | this.cmdMore.Name = "cmdMore";
193 | this.cmdMore.Size = new System.Drawing.Size(120, 41);
194 | this.cmdMore.TabIndex = 21;
195 | this.cmdMore.Text = "More »";
196 | this.cmdMore.UseVisualStyleBackColor = true;
197 | this.cmdMore.Click += new System.EventHandler(this.cmdMore_Click);
198 | //
199 | // groupBox2
200 | //
201 | this.groupBox2.Controls.Add(this.cmdSwapPictures);
202 | this.groupBox2.Controls.Add(this.ctrlPictures);
203 | this.groupBox2.Location = new System.Drawing.Point(1020, 278);
204 | this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
205 | this.groupBox2.Name = "groupBox2";
206 | this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
207 | this.groupBox2.Size = new System.Drawing.Size(316, 191);
208 | this.groupBox2.TabIndex = 22;
209 | this.groupBox2.TabStop = false;
210 | this.groupBox2.Text = "Picture transition";
211 | //
212 | // cmdSwapPictures
213 | //
214 | this.cmdSwapPictures.Location = new System.Drawing.Point(15, 29);
215 | this.cmdSwapPictures.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
216 | this.cmdSwapPictures.Name = "cmdSwapPictures";
217 | this.cmdSwapPictures.Size = new System.Drawing.Size(110, 138);
218 | this.cmdSwapPictures.TabIndex = 1;
219 | this.cmdSwapPictures.Text = "Swap Pictures";
220 | this.cmdSwapPictures.UseVisualStyleBackColor = true;
221 | this.cmdSwapPictures.Click += new System.EventHandler(this.cmdSwapPictures_Click);
222 | //
223 | // groupBox3
224 | //
225 | this.groupBox3.Controls.Add(this.label1);
226 | this.groupBox3.Controls.Add(this.txtPassword);
227 | this.groupBox3.Location = new System.Drawing.Point(1020, 86);
228 | this.groupBox3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
229 | this.groupBox3.Name = "groupBox3";
230 | this.groupBox3.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
231 | this.groupBox3.Size = new System.Drawing.Size(316, 183);
232 | this.groupBox3.TabIndex = 23;
233 | this.groupBox3.TabStop = false;
234 | this.groupBox3.Text = "macOS like password box";
235 | //
236 | // label1
237 | //
238 | this.label1.AutoSize = true;
239 | this.label1.Location = new System.Drawing.Point(36, 55);
240 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
241 | this.label1.Name = "label1";
242 | this.label1.Size = new System.Drawing.Size(195, 40);
243 | this.label1.TabIndex = 1;
244 | this.label1.Text = "Enter the secret password\r\nand hit [Return]";
245 | //
246 | // txtPassword
247 | //
248 | this.txtPassword.Location = new System.Drawing.Point(40, 112);
249 | this.txtPassword.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
250 | this.txtPassword.Name = "txtPassword";
251 | this.txtPassword.PasswordChar = '●';
252 | this.txtPassword.Size = new System.Drawing.Size(235, 26);
253 | this.txtPassword.TabIndex = 0;
254 | this.txtPassword.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtPassword_KeyDown);
255 | //
256 | // buttonDemo
257 | //
258 | this.buttonDemo.Location = new System.Drawing.Point(18, 25);
259 | this.buttonDemo.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
260 | this.buttonDemo.Name = "buttonDemo";
261 | this.buttonDemo.Size = new System.Drawing.Size(195, 41);
262 | this.buttonDemo.TabIndex = 24;
263 | this.buttonDemo.Text = "Animate all && get back";
264 | this.buttonDemo.UseVisualStyleBackColor = true;
265 | this.buttonDemo.Click += new System.EventHandler(this.buttonDemo_Click);
266 | //
267 | // gpEasing
268 | //
269 | this.gpEasing.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
270 | | System.Windows.Forms.AnchorStyles.Left)));
271 | this.gpEasing.Controls.Add(this.label9);
272 | this.gpEasing.Controls.Add(this.label8);
273 | this.gpEasing.Controls.Add(this.buttonThrowAndCatch);
274 | this.gpEasing.Controls.Add(this.buttonLinear);
275 | this.gpEasing.Controls.Add(this.buttonFlash);
276 | this.gpEasing.Controls.Add(this.buttonEaseInEaseOut);
277 | this.gpEasing.Controls.Add(this.buttonDecelerate);
278 | this.gpEasing.Controls.Add(this.buttonCriticalDamp);
279 | this.gpEasing.Controls.Add(this.buttonBounce);
280 | this.gpEasing.Controls.Add(this.buttonAccelerate);
281 | this.gpEasing.Controls.Add(this.buttonSineEaseOut);
282 | this.gpEasing.Controls.Add(this.buttonQuintEaseOut);
283 | this.gpEasing.Controls.Add(this.buttonQuartEaseOut);
284 | this.gpEasing.Controls.Add(this.buttonQuadEaseOut);
285 | this.gpEasing.Controls.Add(this.buttonExpoEaseOut);
286 | this.gpEasing.Controls.Add(this.buttonElasticEaseOut);
287 | this.gpEasing.Controls.Add(this.buttonCubicEaseOut);
288 | this.gpEasing.Controls.Add(this.buttonCircEaseOut);
289 | this.gpEasing.Controls.Add(this.buttonBounceEaseOut);
290 | this.gpEasing.Controls.Add(this.buttonBackEaseOut);
291 | this.gpEasing.Controls.Add(this.label5);
292 | this.gpEasing.Controls.Add(this.label3);
293 | this.gpEasing.Controls.Add(this.label2);
294 | this.gpEasing.Controls.Add(this.label7);
295 | this.gpEasing.Controls.Add(this.lblTargetLine);
296 | this.gpEasing.Controls.Add(this.label6);
297 | this.gpEasing.Controls.Add(this.label4);
298 | this.gpEasing.Location = new System.Drawing.Point(18, 86);
299 | this.gpEasing.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
300 | this.gpEasing.Name = "gpEasing";
301 | this.gpEasing.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
302 | this.gpEasing.Size = new System.Drawing.Size(994, 1270);
303 | this.gpEasing.TabIndex = 24;
304 | this.gpEasing.TabStop = false;
305 | this.gpEasing.Text = "Animation showcase";
306 | //
307 | // label9
308 | //
309 | this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
310 | | System.Windows.Forms.AnchorStyles.Left)));
311 | this.label9.BackColor = System.Drawing.Color.NavajoWhite;
312 | this.label9.Location = new System.Drawing.Point(19, 484);
313 | this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
314 | this.label9.Name = "label9";
315 | this.label9.Size = new System.Drawing.Size(8, 772);
316 | this.label9.TabIndex = 32;
317 | //
318 | // label8
319 | //
320 | this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
321 | | System.Windows.Forms.AnchorStyles.Left)));
322 | this.label8.BackColor = System.Drawing.Color.LightSteelBlue;
323 | this.label8.Location = new System.Drawing.Point(19, 46);
324 | this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
325 | this.label8.Name = "label8";
326 | this.label8.Size = new System.Drawing.Size(8, 405);
327 | this.label8.TabIndex = 31;
328 | //
329 | // label6
330 | //
331 | this.label6.AutoSize = true;
332 | this.label6.Location = new System.Drawing.Point(224, 650);
333 | this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
334 | this.label6.Name = "label6";
335 | this.label6.Size = new System.Drawing.Size(115, 20);
336 | this.label6.TabIndex = 30;
337 | this.label6.Text = "= Rubber band";
338 | //
339 | // buttonThrowAndCatch
340 | //
341 | this.buttonThrowAndCatch.Location = new System.Drawing.Point(44, 416);
342 | this.buttonThrowAndCatch.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
343 | this.buttonThrowAndCatch.Name = "buttonThrowAndCatch";
344 | this.buttonThrowAndCatch.Size = new System.Drawing.Size(172, 35);
345 | this.buttonThrowAndCatch.TabIndex = 25;
346 | this.buttonThrowAndCatch.Text = "ThrowAndCatch";
347 | this.buttonThrowAndCatch.UseVisualStyleBackColor = true;
348 | this.buttonThrowAndCatch.Click += new System.EventHandler(this.buttonThrowAndCatch_Click);
349 | //
350 | // buttonLinear
351 | //
352 | this.buttonLinear.Location = new System.Drawing.Point(44, 371);
353 | this.buttonLinear.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
354 | this.buttonLinear.Name = "buttonLinear";
355 | this.buttonLinear.Size = new System.Drawing.Size(172, 35);
356 | this.buttonLinear.TabIndex = 25;
357 | this.buttonLinear.Text = "Linear";
358 | this.buttonLinear.UseVisualStyleBackColor = true;
359 | this.buttonLinear.Click += new System.EventHandler(this.buttonLinear_Click);
360 | //
361 | // buttonFlash
362 | //
363 | this.buttonFlash.Location = new System.Drawing.Point(44, 326);
364 | this.buttonFlash.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
365 | this.buttonFlash.Name = "buttonFlash";
366 | this.buttonFlash.Size = new System.Drawing.Size(172, 35);
367 | this.buttonFlash.TabIndex = 25;
368 | this.buttonFlash.Text = "Flash";
369 | this.buttonFlash.UseVisualStyleBackColor = true;
370 | this.buttonFlash.Click += new System.EventHandler(this.buttonFlash_Click);
371 | //
372 | // buttonEaseInEaseOut
373 | //
374 | this.buttonEaseInEaseOut.Location = new System.Drawing.Point(44, 282);
375 | this.buttonEaseInEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
376 | this.buttonEaseInEaseOut.Name = "buttonEaseInEaseOut";
377 | this.buttonEaseInEaseOut.Size = new System.Drawing.Size(172, 35);
378 | this.buttonEaseInEaseOut.TabIndex = 25;
379 | this.buttonEaseInEaseOut.Text = "EaseInEaseOut";
380 | this.buttonEaseInEaseOut.UseVisualStyleBackColor = true;
381 | this.buttonEaseInEaseOut.Click += new System.EventHandler(this.buttonEaseInEaseOut_Click);
382 | //
383 | // buttonDecelerate
384 | //
385 | this.buttonDecelerate.Location = new System.Drawing.Point(44, 237);
386 | this.buttonDecelerate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
387 | this.buttonDecelerate.Name = "buttonDecelerate";
388 | this.buttonDecelerate.Size = new System.Drawing.Size(172, 35);
389 | this.buttonDecelerate.TabIndex = 25;
390 | this.buttonDecelerate.Text = "Decelerate";
391 | this.buttonDecelerate.UseVisualStyleBackColor = true;
392 | this.buttonDecelerate.Click += new System.EventHandler(this.buttonDecelerate_Click);
393 | //
394 | // buttonCriticalDamp
395 | //
396 | this.buttonCriticalDamp.Location = new System.Drawing.Point(44, 193);
397 | this.buttonCriticalDamp.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
398 | this.buttonCriticalDamp.Name = "buttonCriticalDamp";
399 | this.buttonCriticalDamp.Size = new System.Drawing.Size(172, 35);
400 | this.buttonCriticalDamp.TabIndex = 25;
401 | this.buttonCriticalDamp.Text = "CriticalDamp";
402 | this.buttonCriticalDamp.UseVisualStyleBackColor = true;
403 | this.buttonCriticalDamp.Click += new System.EventHandler(this.buttonCriticalDamp_Click);
404 | //
405 | // buttonBounce
406 | //
407 | this.buttonBounce.Location = new System.Drawing.Point(44, 148);
408 | this.buttonBounce.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
409 | this.buttonBounce.Name = "buttonBounce";
410 | this.buttonBounce.Size = new System.Drawing.Size(172, 35);
411 | this.buttonBounce.TabIndex = 25;
412 | this.buttonBounce.Text = "Bounce";
413 | this.buttonBounce.UseVisualStyleBackColor = true;
414 | this.buttonBounce.Click += new System.EventHandler(this.buttonBounce_Click);
415 | //
416 | // buttonAccelerate
417 | //
418 | this.buttonAccelerate.Location = new System.Drawing.Point(44, 103);
419 | this.buttonAccelerate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
420 | this.buttonAccelerate.Name = "buttonAccelerate";
421 | this.buttonAccelerate.Size = new System.Drawing.Size(172, 35);
422 | this.buttonAccelerate.TabIndex = 25;
423 | this.buttonAccelerate.Text = "Accelerate";
424 | this.buttonAccelerate.UseVisualStyleBackColor = true;
425 | this.buttonAccelerate.Click += new System.EventHandler(this.buttonAccelerate_Click);
426 | //
427 | // buttonSineEaseOut
428 | //
429 | this.buttonSineEaseOut.Location = new System.Drawing.Point(44, 1044);
430 | this.buttonSineEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
431 | this.buttonSineEaseOut.Name = "buttonSineEaseOut";
432 | this.buttonSineEaseOut.Size = new System.Drawing.Size(172, 35);
433 | this.buttonSineEaseOut.TabIndex = 25;
434 | this.buttonSineEaseOut.Text = "SineEaseOut";
435 | this.buttonSineEaseOut.UseVisualStyleBackColor = true;
436 | this.buttonSineEaseOut.Click += new System.EventHandler(this.buttonSineEaseOut_Click);
437 | //
438 | // buttonQuintEaseOut
439 | //
440 | this.buttonQuintEaseOut.Location = new System.Drawing.Point(44, 1000);
441 | this.buttonQuintEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
442 | this.buttonQuintEaseOut.Name = "buttonQuintEaseOut";
443 | this.buttonQuintEaseOut.Size = new System.Drawing.Size(172, 35);
444 | this.buttonQuintEaseOut.TabIndex = 25;
445 | this.buttonQuintEaseOut.Text = "QuintEaseOut";
446 | this.buttonQuintEaseOut.UseVisualStyleBackColor = true;
447 | this.buttonQuintEaseOut.Click += new System.EventHandler(this.buttonQuintEaseOut_Click);
448 | //
449 | // buttonQuartEaseOut
450 | //
451 | this.buttonQuartEaseOut.Location = new System.Drawing.Point(44, 955);
452 | this.buttonQuartEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
453 | this.buttonQuartEaseOut.Name = "buttonQuartEaseOut";
454 | this.buttonQuartEaseOut.Size = new System.Drawing.Size(172, 35);
455 | this.buttonQuartEaseOut.TabIndex = 25;
456 | this.buttonQuartEaseOut.Text = "QuartEaseOut";
457 | this.buttonQuartEaseOut.UseVisualStyleBackColor = true;
458 | this.buttonQuartEaseOut.Click += new System.EventHandler(this.buttonQuartEaseOut_Click);
459 | //
460 | // buttonQuadEaseOut
461 | //
462 | this.buttonQuadEaseOut.Location = new System.Drawing.Point(44, 911);
463 | this.buttonQuadEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
464 | this.buttonQuadEaseOut.Name = "buttonQuadEaseOut";
465 | this.buttonQuadEaseOut.Size = new System.Drawing.Size(172, 35);
466 | this.buttonQuadEaseOut.TabIndex = 25;
467 | this.buttonQuadEaseOut.Text = "QuadEaseOut";
468 | this.buttonQuadEaseOut.UseVisualStyleBackColor = true;
469 | this.buttonQuadEaseOut.Click += new System.EventHandler(this.buttonQuadEaseOut_Click);
470 | //
471 | // buttonExpoEaseOut
472 | //
473 | this.buttonExpoEaseOut.Location = new System.Drawing.Point(44, 866);
474 | this.buttonExpoEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
475 | this.buttonExpoEaseOut.Name = "buttonExpoEaseOut";
476 | this.buttonExpoEaseOut.Size = new System.Drawing.Size(172, 35);
477 | this.buttonExpoEaseOut.TabIndex = 25;
478 | this.buttonExpoEaseOut.Text = "ExpoEaseOut";
479 | this.buttonExpoEaseOut.UseVisualStyleBackColor = true;
480 | this.buttonExpoEaseOut.Click += new System.EventHandler(this.buttonExpoEaseOut_Click);
481 | //
482 | // buttonElasticEaseOut
483 | //
484 | this.buttonElasticEaseOut.Location = new System.Drawing.Point(44, 821);
485 | this.buttonElasticEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
486 | this.buttonElasticEaseOut.Name = "buttonElasticEaseOut";
487 | this.buttonElasticEaseOut.Size = new System.Drawing.Size(172, 35);
488 | this.buttonElasticEaseOut.TabIndex = 25;
489 | this.buttonElasticEaseOut.Text = "ElasticEaseOut";
490 | this.buttonElasticEaseOut.UseVisualStyleBackColor = true;
491 | this.buttonElasticEaseOut.Click += new System.EventHandler(this.buttonElasticEaseOut_Click);
492 | //
493 | // buttonCubicEaseOut
494 | //
495 | this.buttonCubicEaseOut.Location = new System.Drawing.Point(44, 777);
496 | this.buttonCubicEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
497 | this.buttonCubicEaseOut.Name = "buttonCubicEaseOut";
498 | this.buttonCubicEaseOut.Size = new System.Drawing.Size(172, 35);
499 | this.buttonCubicEaseOut.TabIndex = 25;
500 | this.buttonCubicEaseOut.Text = "CubicEaseOut";
501 | this.buttonCubicEaseOut.UseVisualStyleBackColor = true;
502 | this.buttonCubicEaseOut.Click += new System.EventHandler(this.buttonCubicEaseOut_Click);
503 | //
504 | // buttonCircEaseOut
505 | //
506 | this.buttonCircEaseOut.Location = new System.Drawing.Point(44, 732);
507 | this.buttonCircEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
508 | this.buttonCircEaseOut.Name = "buttonCircEaseOut";
509 | this.buttonCircEaseOut.Size = new System.Drawing.Size(172, 35);
510 | this.buttonCircEaseOut.TabIndex = 25;
511 | this.buttonCircEaseOut.Text = "CircEaseOut";
512 | this.buttonCircEaseOut.UseVisualStyleBackColor = true;
513 | this.buttonCircEaseOut.Click += new System.EventHandler(this.buttonCircEaseOut_Click);
514 | //
515 | // buttonBounceEaseOut
516 | //
517 | this.buttonBounceEaseOut.Location = new System.Drawing.Point(44, 688);
518 | this.buttonBounceEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
519 | this.buttonBounceEaseOut.Name = "buttonBounceEaseOut";
520 | this.buttonBounceEaseOut.Size = new System.Drawing.Size(172, 35);
521 | this.buttonBounceEaseOut.TabIndex = 25;
522 | this.buttonBounceEaseOut.Text = "BounceEaseOut";
523 | this.buttonBounceEaseOut.UseVisualStyleBackColor = true;
524 | this.buttonBounceEaseOut.Click += new System.EventHandler(this.buttonBounceEaseOut_Click);
525 | //
526 | // buttonBackEaseOut
527 | //
528 | this.buttonBackEaseOut.Location = new System.Drawing.Point(44, 643);
529 | this.buttonBackEaseOut.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
530 | this.buttonBackEaseOut.Name = "buttonBackEaseOut";
531 | this.buttonBackEaseOut.Size = new System.Drawing.Size(172, 35);
532 | this.buttonBackEaseOut.TabIndex = 25;
533 | this.buttonBackEaseOut.Text = "BackEaseOut";
534 | this.buttonBackEaseOut.UseVisualStyleBackColor = true;
535 | this.buttonBackEaseOut.Click += new System.EventHandler(this.buttonBackEaseOut_Click);
536 | //
537 | // label5
538 | //
539 | this.label5.AutoSize = true;
540 | this.label5.Location = new System.Drawing.Point(40, 1096);
541 | this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
542 | this.label5.Name = "label5";
543 | this.label5.Size = new System.Drawing.Size(654, 160);
544 | this.label5.TabIndex = 29;
545 | this.label5.Text = resources.GetString("label5.Text");
546 | //
547 | // label4
548 | //
549 | this.label4.AutoSize = true;
550 | this.label4.Location = new System.Drawing.Point(224, 828);
551 | this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
552 | this.label4.Name = "label4";
553 | this.label4.Size = new System.Drawing.Size(68, 20);
554 | this.label4.TabIndex = 28;
555 | this.label4.Text = "= Spring";
556 | //
557 | // label3
558 | //
559 | this.label3.AutoSize = true;
560 | this.label3.Location = new System.Drawing.Point(40, 483);
561 | this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
562 | this.label3.Name = "label3";
563 | this.label3.Size = new System.Drawing.Size(756, 140);
564 | this.label3.TabIndex = 27;
565 | this.label3.Text = resources.GetString("label3.Text");
566 | //
567 | // label2
568 | //
569 | this.label2.AutoSize = true;
570 | this.label2.Location = new System.Drawing.Point(40, 46);
571 | this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
572 | this.label2.Name = "label2";
573 | this.label2.Size = new System.Drawing.Size(936, 40);
574 | this.label2.TabIndex = 2;
575 | this.label2.Text = resources.GetString("label2.Text");
576 | //
577 | // label7
578 | //
579 | this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
580 | | System.Windows.Forms.AnchorStyles.Left)));
581 | this.label7.BackColor = System.Drawing.Color.DarkGray;
582 | this.label7.Location = new System.Drawing.Point(619, 643);
583 | this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
584 | this.label7.Name = "label7";
585 | this.label7.Size = new System.Drawing.Size(1, 436);
586 | this.label7.TabIndex = 26;
587 | //
588 | // lblTargetLine
589 | //
590 | this.lblTargetLine.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
591 | | System.Windows.Forms.AnchorStyles.Left)));
592 | this.lblTargetLine.BackColor = System.Drawing.Color.DarkGray;
593 | this.lblTargetLine.Location = new System.Drawing.Point(619, 103);
594 | this.lblTargetLine.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
595 | this.lblTargetLine.Name = "lblTargetLine";
596 | this.lblTargetLine.Size = new System.Drawing.Size(1, 348);
597 | this.lblTargetLine.TabIndex = 26;
598 | //
599 | // buttonSprings
600 | //
601 | this.buttonSprings.Location = new System.Drawing.Point(0, 0);
602 | this.buttonSprings.Name = "buttonSprings";
603 | this.buttonSprings.Size = new System.Drawing.Size(75, 23);
604 | this.buttonSprings.TabIndex = 0;
605 | //
606 | // ctrlPictures
607 | //
608 | this.ctrlPictures.Location = new System.Drawing.Point(142, 29);
609 | this.ctrlPictures.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8);
610 | this.ctrlPictures.Name = "ctrlPictures";
611 | this.ctrlPictures.Size = new System.Drawing.Size(154, 138);
612 | this.ctrlPictures.TabIndex = 0;
613 | //
614 | // ctrlRipple
615 | //
616 | this.ctrlRipple.Location = new System.Drawing.Point(9, 95);
617 | this.ctrlRipple.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8);
618 | this.ctrlRipple.Name = "ctrlRipple";
619 | this.ctrlRipple.Size = new System.Drawing.Size(290, 215);
620 | this.ctrlRipple.TabIndex = 8;
621 | //
622 | // DemoForm
623 | //
624 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
625 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
626 | this.BackColor = System.Drawing.Color.White;
627 | this.ClientSize = new System.Drawing.Size(1377, 1373);
628 | this.Controls.Add(this.gpEasing);
629 | this.Controls.Add(this.groupBox3);
630 | this.Controls.Add(this.groupBox2);
631 | this.Controls.Add(this.cmdMore);
632 | this.Controls.Add(this.gbRipple);
633 | this.Controls.Add(this.gbThrowAndCatch);
634 | this.Controls.Add(this.groupBox1);
635 | this.Controls.Add(this.buttonDemo);
636 | this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
637 | this.Name = "DemoForm";
638 | this.Text = "FluentTransitions TestApp";
639 | this.groupBox1.ResumeLayout(false);
640 | this.groupBox1.PerformLayout();
641 | this.gbThrowAndCatch.ResumeLayout(false);
642 | this.gbRipple.ResumeLayout(false);
643 | this.groupBox2.ResumeLayout(false);
644 | this.groupBox3.ResumeLayout(false);
645 | this.groupBox3.PerformLayout();
646 | this.gpEasing.ResumeLayout(false);
647 | this.gpEasing.PerformLayout();
648 | this.ResumeLayout(false);
649 |
650 | }
651 |
652 | #endregion
653 | private RippleControl ctrlRipple;
654 | private System.Windows.Forms.Button cmdRipple;
655 | private System.Windows.Forms.Button cmdThrowAndCatch;
656 | private System.Windows.Forms.GroupBox groupBox1;
657 | private System.Windows.Forms.Label lblTextTransition2;
658 | private System.Windows.Forms.Label lblTextTransition1;
659 | private System.Windows.Forms.Button cmdTextTransition;
660 | private System.Windows.Forms.GroupBox gbThrowAndCatch;
661 | private System.Windows.Forms.GroupBox gbRipple;
662 | private System.Windows.Forms.Button cmdMore;
663 | private System.Windows.Forms.GroupBox groupBox2;
664 | private System.Windows.Forms.Button cmdSwapPictures;
665 | private KittenPuppyControl ctrlPictures;
666 | private System.Windows.Forms.GroupBox groupBox3;
667 | private System.Windows.Forms.Label label1;
668 | private System.Windows.Forms.TextBox txtPassword;
669 | private System.Windows.Forms.Button buttonDemo;
670 | private System.Windows.Forms.GroupBox gpEasing;
671 | private System.Windows.Forms.Button buttonBackEaseOut;
672 | private System.Windows.Forms.Label lblTargetLine;
673 | private System.Windows.Forms.Button buttonSprings;
674 | private System.Windows.Forms.Button buttonLinear;
675 | private System.Windows.Forms.Button buttonFlash;
676 | private System.Windows.Forms.Button buttonEaseInEaseOut;
677 | private System.Windows.Forms.Button buttonDecelerate;
678 | private System.Windows.Forms.Button buttonCriticalDamp;
679 | private System.Windows.Forms.Button buttonAccelerate;
680 | private System.Windows.Forms.Button buttonThrowAndCatch;
681 | private System.Windows.Forms.Button buttonBounce;
682 | private System.Windows.Forms.Button buttonExpoEaseOut;
683 | private System.Windows.Forms.Button buttonElasticEaseOut;
684 | private System.Windows.Forms.Button buttonCubicEaseOut;
685 | private System.Windows.Forms.Button buttonCircEaseOut;
686 | private System.Windows.Forms.Button buttonBounceEaseOut;
687 | private System.Windows.Forms.Button buttonQuintEaseOut;
688 | private System.Windows.Forms.Button buttonQuartEaseOut;
689 | private System.Windows.Forms.Button buttonQuadEaseOut;
690 | private System.Windows.Forms.Button buttonSineEaseOut;
691 | private System.Windows.Forms.Label label3;
692 | private System.Windows.Forms.Label label2;
693 | private System.Windows.Forms.Label label4;
694 | private System.Windows.Forms.Label label5;
695 | private System.Windows.Forms.Label label6;
696 | private System.Windows.Forms.Label label7;
697 | private System.Windows.Forms.Label label9;
698 | private System.Windows.Forms.Label label8;
699 | }
700 | }
701 |
702 |
--------------------------------------------------------------------------------
/src/TestApp/DemoForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows.Forms;
4 | using FluentTransitions;
5 | using System.Drawing;
6 | using System.Threading.Tasks;
7 | using FluentTransitions.Methods;
8 |
9 | namespace TestApp
10 | {
11 | ///
12 | /// This form demonstrates a number of animated transitions using the Transitions
13 | /// library. Each event handler (form-load, button click) demonstrates a different
14 | /// transition.
15 | ///
16 | public partial class DemoForm : Form
17 | {
18 | // Colors used by the change-form-color transition...
19 | private readonly Color BACKCOLOR_GRAY = Color.FromArgb(80, 80, 80);
20 | private readonly Color BACKCOLOR_WHITE = Color.FromArgb(255, 255, 255);
21 |
22 | // The left point of the 'bounce' and 'throw-and-catch' group boxes...
23 | private const int GROUP_BOX_LEFT = 12;
24 |
25 | // Strings used for the text transition...
26 | private const string STRING_SHORT1 = "I've got two tickets";
27 | private const string STRING_LONG1 = "to Iron Maiden, baby.";
28 | private const string STRING_SHORT2 = "Come with me friday";
29 | private const string STRING_LONG2 = "don't say maybe!";
30 |
31 | private bool _moving = false;
32 | private int _initialEasingButtonLeft;
33 |
34 | ///
35 | /// Constructor.
36 | ///
37 | public DemoForm()
38 | {
39 | InitializeComponent();
40 |
41 | Width = CollapsedFormWidth;
42 | }
43 |
44 | protected override void OnShown(EventArgs e)
45 | {
46 | base.OnShown(e);
47 |
48 | _initialEasingButtonLeft = buttonAccelerate.Left;
49 | Center();
50 | }
51 |
52 | protected override void OnResizeEnd(EventArgs e)
53 | {
54 | base.OnResizeEnd(e);
55 |
56 | Center();
57 | }
58 |
59 | private void Center()
60 | {
61 | if (_moving)
62 | return;
63 |
64 | _moving = true;
65 |
66 | Task.Delay(10).ContinueWith(_ =>
67 | {
68 | BeginInvoke(new MethodInvoker(() =>
69 | {
70 | var area = Screen.FromControl(this).WorkingArea;
71 | var targetX = (area.Width / 2) - (Width / 2);
72 | var targetY = (area.Height / 2) - (Height / 2);
73 |
74 | Transition
75 | .With(this, nameof(Left), targetX)
76 | .With(this, nameof(Top), targetY)
77 | .HookOnCompletionInUiThread(this, () =>
78 | {
79 | _moving = false;
80 | if (Width <= CollapsedFormWidth)
81 | cmdMore.Text = "More »";
82 | else
83 | cmdMore.Text = "« Less";
84 | })
85 | .Spring(TimeSpan.FromSeconds(0.75));
86 | }));
87 | });
88 | }
89 |
90 | ///
91 | /// Called when the "Throw and Catch" button is pressed.
92 | ///
93 | private void cmdThrowAndCatch_Click(object sender, EventArgs e)
94 | {
95 | // The button is 'thrown' up to the top of the group-box it is in
96 | // and then falls back down again.
97 |
98 | // The throw-and-catch transition starts the animation at a high rate and
99 | // decelerates to zero (as if against gravity) at the destination value. It
100 | // then accelerates the value (as if with gravity) back to the original value.
101 |
102 | Transition
103 | .With(cmdThrowAndCatch, nameof(Top), 12)
104 | .ThrowAndCatch(TimeSpan.FromSeconds(1.5));
105 | }
106 |
107 | ///
108 | /// Called when the "Ripple" button is pressed.
109 | ///
110 | private void cmdRipple_Click(object sender, EventArgs e)
111 | {
112 | // The ripple is handled by the RippleControl user-control.
113 | // This performs 100 simultaneous animations to create the
114 | // ripple effect...
115 | ctrlRipple.Ripple();
116 | }
117 |
118 | ///
119 | /// Called when the "Swap Pictures" button is pressed.
120 | ///
121 | private void cmdSwapPictures_Click(object sender, EventArgs e)
122 | {
123 | // The transition is handled by the KittenPuppyControl...
124 | ctrlPictures.TransitionPictures();
125 | }
126 |
127 | ///
128 | /// Called when the "Text Transition" button is pressed.
129 | ///
130 | private void cmdTextTransition_Click(object sender, EventArgs e)
131 | {
132 | // We transition four properties simulataneously here:
133 | // - The two labels' text is changed.
134 | // - The two labels' colors are changed.
135 |
136 | // We work out the new text and colors to transition to...
137 | string text1, text2;
138 | Color color1, color2;
139 | if (lblTextTransition1.Text == STRING_SHORT1)
140 | {
141 | text1 = STRING_SHORT2;
142 | color1 = Color.Red;
143 | text2 = STRING_LONG2;
144 | color2 = Color.Blue;
145 | }
146 | else
147 | {
148 | text1 = STRING_SHORT1;
149 | color1 = Color.Blue;
150 | text2 = STRING_LONG1;
151 | color2 = Color.Red;
152 | }
153 |
154 | // We create a transition to animate all four properties at the same time...
155 | Transition
156 | .With(lblTextTransition1, nameof(Text), text1)
157 | .With(lblTextTransition1, nameof(ForeColor), color1)
158 | .With(lblTextTransition2, nameof(Text), text2)
159 | .With(lblTextTransition2, nameof(ForeColor), color2)
160 | .EaseInEaseOut(TimeSpan.FromSeconds(1));
161 | }
162 |
163 | ///
164 | /// Called when the "Change Form Color" button is pressed.
165 | ///
166 | private void ctrlChangeFormColor_Click(object sender, EventArgs e)
167 | {
168 | // We alternate the form's background color...
169 | var destination = (BackColor == BACKCOLOR_GRAY) ? BACKCOLOR_WHITE : BACKCOLOR_GRAY;
170 | Transition
171 | .With(this, nameof(BackColor), destination)
172 | .Linear(TimeSpan.FromSeconds(1));
173 | }
174 |
175 | ///
176 | /// Called when the "More" or "Less" button is pressed.
177 | ///
178 | private void cmdMore_Click(object sender, EventArgs e)
179 | {
180 | // We either show more screen or less screen depending on the current state.
181 | // We find out whether we need to make the screen wider or narrower...
182 | int formWidth;
183 | if (Width > CollapsedFormWidth)
184 | formWidth = CollapsedFormWidth;
185 | else
186 | formWidth = ExpandedFormWidth;
187 | _moving = true;
188 | // We animate it with an ease-in-ease-out transition...
189 | Transition
190 | .With(this, nameof(Width), formWidth)
191 | .HookOnCompletion(() =>
192 | {
193 | _moving = false;
194 | Center();
195 | })
196 | .Spring(TimeSpan.FromSeconds(1));
197 | }
198 |
199 | private void txtPassword_KeyDown(object sender, KeyEventArgs e)
200 | {
201 | if (e.KeyCode == Keys.Return)
202 | {
203 | Transition
204 | .With(txtPassword, nameof(Left), txtPassword.Left - 15)
205 | .Flash(4, TimeSpan.FromMilliseconds(120));
206 | }
207 | }
208 |
209 | private void buttonDemo_Click(object sender, EventArgs e)
210 | {
211 | var buttons = new[] { buttonAccelerate, buttonBounce, buttonCriticalDamp, buttonDecelerate, buttonEaseInEaseOut, buttonFlash, buttonLinear,
212 | buttonThrowAndCatch, buttonBackEaseOut, buttonBounceEaseOut, buttonCircEaseOut, buttonCubicEaseOut, buttonElasticEaseOut, buttonExpoEaseOut,
213 | buttonQuadEaseOut, buttonQuartEaseOut, buttonQuintEaseOut, buttonSineEaseOut };
214 |
215 | if (buttons.Any(b => b.Left != _initialEasingButtonLeft))
216 | EaseBack();
217 | else
218 | Ease();
219 | }
220 |
221 | private void Ease()
222 | {
223 | buttonAccelerate_Click(null, null);
224 | buttonBounce_Click(null, null);
225 | buttonCriticalDamp_Click(null, null);
226 | buttonDecelerate_Click(null, null);
227 | buttonEaseInEaseOut_Click(null, null);
228 | buttonFlash_Click(null, null);
229 | buttonLinear_Click(null, null);
230 | buttonThrowAndCatch_Click(null, null);
231 |
232 | // easing functions
233 |
234 | buttonBackEaseOut_Click(null, null);
235 | buttonBounceEaseOut_Click(null, null);
236 | buttonCircEaseOut_Click(null, null);
237 | buttonCubicEaseOut_Click(null, null);
238 | buttonElasticEaseOut_Click(null, null);
239 | buttonExpoEaseOut_Click(null, null);
240 | buttonQuadEaseOut_Click(null, null);
241 | buttonQuartEaseOut_Click(null, null);
242 | buttonQuintEaseOut_Click(null, null);
243 | buttonSineEaseOut_Click(null, null);
244 | }
245 |
246 | private void EaseBack()
247 | {
248 | Transition
249 | .With(buttonAccelerate, nameof(Left), _initialEasingButtonLeft)
250 | .With(buttonBounce, nameof(Left), _initialEasingButtonLeft)
251 | .With(buttonCriticalDamp, nameof(Left), _initialEasingButtonLeft)
252 | .With(buttonDecelerate, nameof(Left), _initialEasingButtonLeft)
253 | .With(buttonEaseInEaseOut, nameof(Left), _initialEasingButtonLeft)
254 | .With(buttonFlash, nameof(Left), _initialEasingButtonLeft)
255 | .With(buttonLinear, nameof(Left), _initialEasingButtonLeft)
256 | .With(buttonThrowAndCatch, nameof(Left), _initialEasingButtonLeft)
257 | .With(buttonBackEaseOut, nameof(Left), _initialEasingButtonLeft)
258 | .With(buttonBounceEaseOut, nameof(Left), _initialEasingButtonLeft)
259 | .With(buttonCircEaseOut, nameof(Left), _initialEasingButtonLeft)
260 | .With(buttonCubicEaseOut, nameof(Left), _initialEasingButtonLeft)
261 | .With(buttonElasticEaseOut, nameof(Left), _initialEasingButtonLeft)
262 | .With(buttonExpoEaseOut, nameof(Left), _initialEasingButtonLeft)
263 | .With(buttonQuadEaseOut, nameof(Left), _initialEasingButtonLeft)
264 | .With(buttonQuartEaseOut, nameof(Left), _initialEasingButtonLeft)
265 | .With(buttonQuintEaseOut, nameof(Left), _initialEasingButtonLeft)
266 | .With(buttonSineEaseOut, nameof(Left), _initialEasingButtonLeft)
267 | .EaseInEaseOut(EaseDuration);
268 | }
269 |
270 | private void buttonAccelerate_Click(object sender, EventArgs e)
271 | {
272 | Transition
273 | .With(buttonAccelerate, nameof(Left), lblTargetLine.Left)
274 | .Accelerate(EaseDuration);
275 | }
276 |
277 | private void buttonBounce_Click(object sender, EventArgs e)
278 | {
279 | Transition
280 | .With(buttonBounce, nameof(Left), lblTargetLine.Left)
281 | .Bounce(EaseDuration);
282 | }
283 |
284 | private void buttonCriticalDamp_Click(object sender, EventArgs e)
285 | {
286 | Transition
287 | .With(buttonCriticalDamp, nameof(Left), lblTargetLine.Left)
288 | .CriticalDamp(EaseDuration);
289 | }
290 |
291 | private void buttonDecelerate_Click(object sender, EventArgs e)
292 | {
293 | Transition
294 | .With(buttonDecelerate, nameof(Left), lblTargetLine.Left)
295 | .Decelerate(EaseDuration);
296 | }
297 |
298 | private void buttonEaseInEaseOut_Click(object sender, EventArgs e)
299 | {
300 | Transition
301 | .With(buttonEaseInEaseOut, nameof(Left), lblTargetLine.Left)
302 | .EaseInEaseOut(EaseDuration);
303 | }
304 |
305 | private void buttonFlash_Click(object sender, EventArgs e)
306 | {
307 | Transition
308 | .With(buttonFlash, nameof(Left), lblTargetLine.Left)
309 | .Flash(2, TimeSpan.FromMilliseconds(EaseDuration.TotalMilliseconds / 5));
310 | }
311 |
312 | private void buttonLinear_Click(object sender, EventArgs e)
313 | {
314 | Transition
315 | .With(buttonLinear, nameof(Left), lblTargetLine.Left)
316 | .Linear(EaseDuration);
317 | }
318 |
319 | private void buttonThrowAndCatch_Click(object sender, EventArgs e)
320 | {
321 | Transition
322 | .With(buttonThrowAndCatch, nameof(Left), lblTargetLine.Left)
323 | .ThrowAndCatch(EaseDuration);
324 | }
325 |
326 | private void buttonBackEaseOut_Click(object sender, EventArgs e)
327 | {
328 | Transition
329 | .With(buttonBackEaseOut, nameof(Left), lblTargetLine.Left)
330 | .EaseWithFunction(EasingFunctions.BackEaseOut, EaseDuration);
331 | }
332 |
333 | private void buttonBounceEaseOut_Click(object sender, EventArgs e)
334 | {
335 | Transition
336 | .With(buttonBounceEaseOut, nameof(Left), lblTargetLine.Left)
337 | .EaseWithFunction(EasingFunctions.BounceEaseOut, EaseDuration);
338 | }
339 |
340 | private void buttonCircEaseOut_Click(object sender, EventArgs e)
341 | {
342 | Transition
343 | .With(buttonCircEaseOut, nameof(Left), lblTargetLine.Left)
344 | .EaseWithFunction(EasingFunctions.CircEaseOut, EaseDuration);
345 | }
346 |
347 | private void buttonCubicEaseOut_Click(object sender, EventArgs e)
348 | {
349 | Transition
350 | .With(buttonCubicEaseOut, nameof(Left), lblTargetLine.Left)
351 | .EaseWithFunction(EasingFunctions.CubicEaseOut, EaseDuration);
352 | }
353 |
354 | private void buttonElasticEaseOut_Click(object sender, EventArgs e)
355 | {
356 | Transition
357 | .With(buttonElasticEaseOut, nameof(Left), lblTargetLine.Left)
358 | .EaseWithFunction(EasingFunctions.ElasticEaseOut, EaseDuration);
359 | }
360 |
361 | private void buttonExpoEaseOut_Click(object sender, EventArgs e)
362 | {
363 | Transition
364 | .With(buttonExpoEaseOut, nameof(Left), lblTargetLine.Left)
365 | .EaseWithFunction(EasingFunctions.ExpoEaseOut, EaseDuration);
366 | }
367 |
368 | private void buttonQuadEaseOut_Click(object sender, EventArgs e)
369 | {
370 | Transition
371 | .With(buttonQuadEaseOut, nameof(Left), lblTargetLine.Left)
372 | .EaseWithFunction(EasingFunctions.QuadEaseOut, EaseDuration);
373 | }
374 |
375 | private void buttonQuartEaseOut_Click(object sender, EventArgs e)
376 | {
377 | Transition
378 | .With(buttonQuartEaseOut, nameof(Left), lblTargetLine.Left)
379 | .EaseWithFunction(EasingFunctions.QuartEaseOut, EaseDuration);
380 | }
381 |
382 | private void buttonQuintEaseOut_Click(object sender, EventArgs e)
383 | {
384 | Transition
385 | .With(buttonQuintEaseOut, nameof(Left), lblTargetLine.Left)
386 | .EaseWithFunction(EasingFunctions.QuintEaseOut, EaseDuration);
387 | }
388 |
389 | private void buttonSineEaseOut_Click(object sender, EventArgs e)
390 | {
391 | Transition
392 | .With(buttonSineEaseOut, nameof(Left), lblTargetLine.Left)
393 | .EaseWithFunction(EasingFunctions.SineEaseOut, EaseDuration);
394 | }
395 |
396 | private TimeSpan EaseDuration { get; } = TimeSpan.FromSeconds(1);
397 |
398 | private int CollapsedFormWidth => gpEasing.Right + gpEasing.Left + ((Width - ClientSize.Width) / 2);
399 |
400 | private int ExpandedFormWidth => groupBox1.Right + gpEasing.Left + ((Width - ClientSize.Width) / 2);
401 | }
402 | }
403 |
--------------------------------------------------------------------------------
/src/TestApp/DemoForm.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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | For this demo, only the EaseOut functions are shown.
122 | However, each easing function is available as EaseIn, EaseOut, EaseInOut and EaseOutIn.
123 |
124 | To use Mauro's built-in easing functions, simpy use EaseWithFunction():
125 |
126 | Transition
127 | .With(...)
128 | .EaseWithFunction(EasingFunctions.YOURCHOICE, duration);
129 |
130 |
131 | These are transitions implemented with easing functions. Easing functions are mathematical functions
132 | defining "how things change over time".
133 |
134 | Mauro Sampietro published an article on easing functions on CodeProject in 2014.
135 |
136 | FluentTransitions fully supports easing functions starting with version 2.0 and provides
137 | Mauro's easing implementations as built-in functions (see below). It is also possible to use custom easings.
138 |
139 |
140 | These are the animations of the original project Richard S. Shepherd uploaded to Google Code back in 2009.
141 | After using this project for a long time, I (Andreas Wäscher) decided to modernize the code and migrate it to modern .NET platforms.
142 |
143 |
--------------------------------------------------------------------------------
/src/TestApp/KittenPuppyControl.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace TestApp
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::TestApp.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::TestApp.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 |
--------------------------------------------------------------------------------
/src/TestApp/KittenPuppyControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using FluentTransitions;
4 |
5 | namespace TestApp
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 | private PictureBox _activePicture = null;
15 | private PictureBox _inactivePicture = null;
16 | private readonly Random _random = new Random();
17 |
18 | ///
19 | /// Constructor.
20 | ///
21 | public KittenPuppyControl()
22 | {
23 | InitializeComponent();
24 | _activePicture = ctrlPuppy;
25 | _inactivePicture = ctrlKitten;
26 | }
27 |
28 | ///
29 | /// Performs a random tarnsition between the two pictures.
30 | ///
31 | public void TransitionPictures()
32 | {
33 | // We randomly choose where the current image is going to
34 | // slide off to (and where we are going to slide the inactive
35 | // image in from)...
36 | int destinationLeft = (_random.Next(2) == 0) ? Width : -Width;
37 | int destinationTop = (_random.Next(3) - 1) * Height;
38 |
39 | // We move the inactive image to this location...
40 | SuspendLayout();
41 | _inactivePicture.Top = destinationTop;
42 | _inactivePicture.Left = destinationLeft;
43 | _inactivePicture.BringToFront();
44 | ResumeLayout();
45 |
46 | // We perform the transition which moves the active image off the
47 | // screen, and the inactive one onto the screen...
48 | Transition
49 | .With(_inactivePicture, nameof(Left), 0)
50 | .With(_inactivePicture, nameof(Top), 0)
51 | .With(_activePicture, nameof(Left), destinationLeft)
52 | .With(_activePicture, nameof(Top), destinationTop)
53 | .EaseInEaseOut(TimeSpan.FromSeconds(1));
54 |
55 | // We swap over which image is active and inactive for next time
56 | // the function is called...
57 | var temp = _activePicture;
58 | _activePicture = _inactivePicture;
59 | _inactivePicture = temp;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/TestApp/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 |
--------------------------------------------------------------------------------
/src/TestApp/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace TestApp
5 | {
6 | static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | static void Main()
13 | {
14 | Application.EnableVisualStyles();
15 | Application.SetCompatibleTextRenderingDefault(false);
16 | Application.Run(new DemoForm());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/TestApp/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 TestApp.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", "16.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("TestApp.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 |
--------------------------------------------------------------------------------
/src/TestApp/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 |
--------------------------------------------------------------------------------
/src/TestApp/Resources/kitten.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/src/TestApp/Resources/kitten.jpg
--------------------------------------------------------------------------------
/src/TestApp/Resources/puppy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awaescher/FluentTransitions/8d2a72cbee7c69e81522cb76b2b297ba7718ca79/src/TestApp/Resources/puppy.jpg
--------------------------------------------------------------------------------
/src/TestApp/RippleControl.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace TestApp
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 |
--------------------------------------------------------------------------------
/src/TestApp/RippleControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 | using FluentTransitions;
6 |
7 | namespace TestApp
8 | {
9 | ///
10 | /// This control shows a color-rippling effect when you call its ripple()
11 | /// method. It holds a grid of 10x10 label controls with an initial white
12 | /// background color. The ripple method uses a separate transition on each
13 | /// label to move it to pink and back again.
14 | ///
15 | /// The code to set up the labels (in the Load method) is a bit complicated,
16 | /// but the ripple transition itself is very simple.
17 | ///
18 | public partial class RippleControl : UserControl
19 | {
20 | // A collection of cell-infos, i.e. info on each label on the control...
21 | private readonly IList _cellInfos = new List();
22 |
23 | ///
24 | /// Constructor.
25 | ///
26 | public RippleControl()
27 | {
28 | InitializeComponent();
29 | }
30 |
31 | ///
32 | /// Starts the ripple effect.
33 | ///
34 | public void Ripple()
35 | {
36 | // We run a transition on each of the labels shown on the control.
37 | // This means that we will be running 100 simulataneous transitions...
38 | foreach (var info in _cellInfos)
39 | {
40 | Transition
41 | .With(info.Control, nameof(BackColor), Color.Pink)
42 | .Flash(1, TimeSpan.FromMilliseconds(info.TransitionInterval));
43 | }
44 | }
45 |
46 | ///
47 | /// Called when the control is first loaded.
48 | ///
49 | private void RippleControl_Load(object sender, EventArgs e)
50 | {
51 | double cellWidth = Width / 10.0;
52 | double cellHeight = Height / 10.0;
53 |
54 | // We set up a 10x10 grid of labels...
55 | double top = 0;
56 | for (int row = 0; row < 10; ++row)
57 | {
58 | double left = 0;
59 | double bottom = top + cellHeight;
60 |
61 | for (int col = 0; col < 10; ++col)
62 | {
63 | // We work out the size of this label...
64 | double right = left + cellWidth;
65 | int leftInt = (int)left;
66 | int topInt = (int)top;
67 | int rightInt = (int)right;
68 | int bottomInt = (int)bottom;
69 | int width = rightInt - leftInt;
70 | int height = bottomInt - topInt;
71 |
72 | // We create the label...
73 | var label = new Label
74 | {
75 | Left = leftInt,
76 | Top = topInt,
77 | Width = width,
78 | Height = height,
79 | BackColor = Color.White
80 | };
81 |
82 | // And add it to the control...
83 | Controls.Add(label);
84 |
85 | // We work out a transition time for it, and store the information
86 | // to use when we do the ripple effect...
87 | int transitionInterval = row * 100 + col * 100;
88 | _cellInfos.Add(new CellInfo { Control = label, TransitionInterval = transitionInterval });
89 |
90 | // The left for the next column is the right for this one...
91 | left = right;
92 | }
93 |
94 | // The top of the next row is the bottom of this one...
95 | top = bottom;
96 | }
97 | }
98 |
99 | // A small class that holds information about one of the labels on the control.
100 | private class CellInfo
101 | {
102 | public Control Control { get; set; }
103 |
104 | public int TransitionInterval { get; set; }
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/TestApp/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 |
--------------------------------------------------------------------------------
/src/TestApp/TestApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net48;net6.0-windows;net8.0-windows
6 | true
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | true
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/TestApp/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------