V Cocoa můžeme každé instanci třídy NSView poslat zprávu animator, která vrátí objekt chovající se jako objekt původní, ale animující některé vlastnosti. Například setAlphaValue nastaví průhlednost prvku UI. Pokud použijeme setAlphaValue na animační objekt, nastaví se průhledost animovaně (s interpolovanými hodnotami). Protože více čtenářů zná pravděpodobně .NET než Cocoa, zde je jednoduchá ukázka, jak takový proxy objekt implementovat v C#.
Proxy třídu nazvěme prostě Animator. Ta bude dědit ze System.Dynamic.DynamicObject:
class Animator<T> : DynamicObject where T : Control {
Dále potřebujeme instanční proměnnou pro vlastní objekt, konstruktor, statickou metodu pro vytvoření proxy (abychom mohli použít při deklaraci var místo dynamic) a pro jistotu také implicitně přetížíme operátor přetypování, pokud by někdo předával proxy do nějaké metody jako parametr typu T (tedy typu původního objektu):
private T underlyingObject;
public Animator(T obj) { underlyingObject = obj; }
public static dynamic Wrap(T obj) { return new Animator<T>(obj); }
public static implicit operator T(Animator<T> animator) { return animator.underlyingObject; }
Pro práci s vlastnostmi nyní musíme implementovat metody Try…:
public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = underlyingObject.GetType().GetProperty(binder.Name).GetValue(underlyingObject, null);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
underlyingObject.GetType().GetProperty(binder.Name).SetValue(underlyingObject, value, null);
return true;
}
Tím máme hotové jádro proxy objektu a místo
var form = ...;
form.Opacity = 0.5;
můžeme použít
var form = Animator<Form>.Wrap(...);
form.Opacity = 0.5;
se stejným efektem. Každému alespoň průměrnému programátorovi je teď jistě zřejmé, jak přidat animaci. Do metody TrySetMember přidáme
if (binder.Name == "Opacity") { ... }
a nastavení vlastnosti Opacity ošetříme zvlášť. Abychom neblokovali vlákno pro UI, vytvoříme nové vlákno a v cyklu postupně nastavujeme interpolované hodnoty (protože kód poběží v jiném vlákně, je nutné použít Invoke a MethodInvoker). Aby byla tato třída obecně použitelná, musíme samozřejmě doplnit ostatní metody Try… a přidat alespoň metodu SetDuration, abychom mohli nastavit délku animace.
Každému je teď jistě zřejmé, že vlastnosti, pro které z nějakého důvodu nemáme kód pro animaci, fungují zcela stejně jako na původním objektu, například form.Size = new Size(100, 100).
"Každému alespoň průměrnému programátorovi..."
mňa fascinuje ako si autor tohto blogu neustále masíruje ego aký je on nadpriemerný programátor :D Trochu mi tým pripomína Rytmusa: http://www.youtube.com/watch?v=H-P3_H9YaIg
[1]: Tiez som na toto chcel poukazat :) V C# neprogramujem, ale rad citam tento blog, pretoze mi to rozsiruje obzory. Avsak to co velmi nemam rad na akomkolvek tutoriale alebo dokumentacii je to, ked autor predpoklada, ze citatel VIE... Citatel velakrat NEVIE a cita to kvoli tomu aby VEDEL. To nehovorim o tom, ze taka veta aka sa podarilo autorovi moje obzory nicim nerozsirila. Neviem aku ma informacnu hodnotu :D Tiez si myslim, ze je to svojim sposobom masaz ega.
4: je třeba rozlišit Objective-C jako jazyk a potom Applí knihovnu Fundation. V podstatě všechny manuály k Objective-C, které najdeš na webu, se týkají Fundation. Samotný jazyk Objective-C je rozšíření (opravdu rozšíření, ne jako C++) jazyka C o některé prvky, které jsou velmi snadno pochopitelné (po krátkém studiu souvislostí)
Jazyk Objective-C funguje i na jiných platformách (gcc ho umí), ale jelikož k tomu není ta Applí knihovna, tak je to trošku deprimující. Pro vážné použití je potřeba si napsat nějaký framework, aby se s tím dělalo aspoň trochu pohodlně (myslím, že v základu to nemá ani objekt string).
To "líbý" je taky pěkný.
Autor se zabývá vývojem kompilátorů a knihoven pro objektově-orientované programovací jazyky.
Přečteno 36 200×
Přečteno 25 361×
Přečteno 23 795×
Přečteno 20 177×
Přečteno 17 874×