I would ultimately like to make .nativePath bindable or fire an event when it changes in Adobe Air. I figured I'd just extend the File class and be good.
But I cant find its source anywhere (so I know how to extend it). I've dug through http://opensource.adobe.com/svn/opensource/flex/sdk/ quite a bit and didnt see anything.
Is there a way to make .nativePath bindable or extend File?
alxx, your code was definitely close. Thank you - it gave me an idea on how to extend it. Working code:
public class FileEx extends File
{
public function FileEx(path:String=null)
{
super(path);
}
[Bindable("nativePathChanged")]
override public function get nativePath():String
{
return super.nativePath;
}
override public function set nativePath(value:String):void
{
super.nativePath=value;
dispatchEvent(new Event("nativePathChanged"));
}
}
The File Class is part of the Flash package, so it is not open source and you won't be able to get your hands on the code (unless you're deep in the inner circle of Adobe developers).
In theory you can extend the class, as it is not marked as final, and make the nativePath Bindable that way, but I'm not sure of the benefit. You'd have to expand on your use case to evaluate that.
You don't need source to subclass something. As long as it's not final, just extend it and override something you need:
public class BindableFile extends File {
[Bindable(event="nativePathChanged")]
override public function get nativePath():String {
return super.nativePath;
}
override public function set nativePath(value:String):void {
super.nativePath = value;
dispatchEvent("nativePathChanged");
}
}
Not tested, but looks realistic :)
Related
I'm strugling on this for quite a while now. I need to create a custom mvc3 html helper for easy filter and toolbar management.
All that helper should look something like this below or something similar. What i want to do is to have a helper where i could give toolbar buttons and filter fields and it generate a toolbar and filter form for me.
I just can't figure it out, because i'm quite new in asp.net mvc
#Html.Toolbar(x => {
x.AddFilterButton();
x.AddButton("Naujas");
x.AddDropDownList();
},
#<text>
#Html.EditorFor(Model.ListFilter.Name)
Filter
ResetFilter
</text>,
filterVisible: false)
How i could achieve this? Any help would be highly apreciated. Thanks indeed.
Something like this:
public static class ToolbarExtensions {
public static Toolbar Toolbar<T>(this HtmlHelper<T> html) {
return new Toolbar();
}
}
public class Toolbar : IHtmlString {
public string ToHtmlString() { /* build your HTML off the state here */ }
public Toolbar AddButton(string label) {
/* build up state here */
return this;
}
}
The syntax on this would be a little different, instead of a lambda, would look like this:
#Html.Toolbar().AddButton("Button 1").AddButton("Button 2")
But you could easily change it to use a chaining object in the lambda instead of on the Toolbar method call.
The IHtmlString interface tells the ViewEngine to output the object as raw HTML when its encountered. The chaining is just achieved by returning the current instance in your methods after modifying the object state.
I'm creating an application using Flex 4.
When the app is started, it reads a XML file and populate objects. The .send() call is asynchronous, so I would want to listen/watch to this populated object, and when it has finished, dispatch an event for other classes, so they can use it.
package model{
public class LectureService extends HTTPService{
[Bindable]
private var _lecture:Lecture;
...
}
The xml is parsed correctly and loaded inside the object lecture of the class Lecture.
If I use the MXML notation in the main.mxml app, it works fine (the object is used when the it is populated after the async request):
<mx:Image id="currentSlide" source={lectureService.lecture.slides.getItemAt(0).path} />
BUT, I have another ActionScript class and I'm not able to listen to this dispatched (by [Bindable]) event.
package components{
public class LectureSlideDisplay extends Image
{
public function LectureSlideDisplay()
{
super();
this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChangeTest);
}
private function onChangeTest(e:PropertyChangeEvent):void {
trace('test');
}
I have already tried:
using (like above) addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, methodName).
tried to change the [Bindable] to [Bindalbe("nameEvent")] and listen for this, nothing.
using CreateWatcher method, doesn't work.
tried to have a look to the generated code of the class, but didn't help me
if (this.hasEventListener("propertyChange")){
this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "lecture", oldValue, value));
}
How can I listen and have the populated object in another class?
Maybe the problem is that I'm listening from another class, but in this case how can I implement this?
It seems the event is dispatched, but I can't listen to it.
For who wants the answer, I have resolved changing the addEventListener object.
It is not right to use:
this.addEventListener(...)
Use instead:
lectureService.addEventListener(...)
I have changed my code to listen to this event in the main app MXML, and then inside the handler method, call the public method of your components to use the new data.
You can't solve all your problems by just extending the class. You should really look into Commands for your HTTP requests.
The change property event is used internally for watchers and won't dispatch in the overall component. What you want to do for your LectureSlideDisplay is to override the source setter. Every time it is called, a new value is being binded to it:
package components{
public class LectureSlideDisplay extends Image
{
override public function set source(value:Object):void
{
super.source = value;
// do whatever
}
public function LectureSlideDisplay()
{
super();
}
}
}
You should really read up on how Binding works.
Consider to use BindingUtils class. You can found documentation here. And a couple of usage samples: one, two.
I have a custom class that extends List which I am using as a container. However, the scroll speed is too fast on the mouse wheel, as in it scrolls loads even if you only move the wheel a tiny bit. I tried adding an event listener to my list for MouseEvent.MOUSE_WHEEL and setting the value of event.delta but this has had no effect. Does anyone know how I can make it slower?
My custom class is nothing special, I just created it so I could have a different itemRenders for different item types. It looks like:
public class MultipleRenderersList extends List
{
override public function createItemRenderer(data:Object):IListItemRenderer
{
if (data is IRenderable)
{
return data.getDiaryRenderer();
}
else if (data is Array)
{
if (data.length > 0)
{
if (data[0] is IRenderable)
{
return data[0].getDiaryRenderer(data);
}
}
}
return null;
}
}
The List class has a mouseWheelHandler function that you can override. Just override the function, update the delta property of the mouseevent, and call super. This example will quarter the delta, reducing the speed substantially:
package
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.Alert;
import mx.controls.List;
public class MyList extends List
{
override protected function mouseWheelHandler(event:MouseEvent):void {
event.delta = event.delta/4;
super.mouseWheelHandler(event);
}
}
}
However, in many cases the scroll speed / delta will be driven off of a system preference, so doing this may cause unexpected behavior for some users. The reason that adding the handler and updating the delta failed to work is that by that point mouseWheelHandler had already been called.
A very simple way to modify this is to change the verticalLineScrollSize property. This is a property of all containers and it defaults to 5. (for flex 3)
Actually, what HandOfCode said isn't relevant here. Because he made the same mistake as i did, which is to think that a List component or TileList component are containers. They aren't. So, they don't have verticalLineScrollSize property.
Sean solution is the only one that worked for my case. I would add that event.delta may have a positive or negative value depending of the direction of the wheel action. So you better do something like this if you plan to scroll, for example one line at a time :
override protected function mouseWheelHandler(event:MouseEvent):void
{
event.delta = (event.delta > 0) ? 1:-1;
super.mouseWheelHandler(event);
}
I'm trying to override a subclass's method but I think I need access to the superclass one higher up in the hierarchy. So I'd like to do something like super.super.methodName();
FYI, the actual problem I'm trying to solve should be explained by my code below:
public class A extends UIComponent{
override protected function keyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
if(event.keyCode==46)
remove();
}
}
public class B extends A{
override protected function keyDownHandler(event:KeyboardEvent):void{
if(event.keyCode==46 && removeable==true)
remove();
else
super.super.keyDownHandler(event);
}
}
If I use the class A's KeyDownHandler method, you will see that remove() is called regardless. However, the docs state that I need to call UIComponent.keyDownHandler whenever I subclass UIComponent. Of course this works for the first subclass, but not that subclass's subclasses.
I realise that I could put the functionality all into A with something like
if(this is B){...}
but that seems to me to be a hack.
You could add another method to class A, let's call it superKeyDownHandler whose only purpose would be to call some method from superclass.
protected function superKeyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
}
And then what you want to achieve would be as easy as calling
super.superKeyDownHandler(event);
This is just a way around however not the actual clean solution, so use it at your own risk :)
UPDATE:
Something maybe cleaner would involve overriding keyDownHandler content of class A. So in class A you would have:
public class A{
override protected function keyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
overridableContent();
}
protected function overridableContent(){
//do class A specific things here
if (event.keyCode==46)
remove();
}
}
public class B extends A{
override protected function overridableContent(){
//do class B specific things here
if (event.keyCode==46 && removeable==true)
remove();
}
}
Calling something like new B().keyDownHandler(event) now will cause calling keyDownHandler as it is defined in class A with content taken from class B.
What I gather from your question is that, you want to use the functionality given by the superclasses' superclass, and not by the superclass itself.
Am I right cammil?
I am going to aplogize in advance because I am really at the limits of my understanding on this so if I do not explain this well....well sorry...
Anyway I am trying to create an asp.net server control that has complex properties which can be set using intellisense. So as an example I will use cars, so the server control might be called car and when I actually implement the control on a webform I want to set complex, hierarchical properties so for example:
<Control:Car Color="Paint.Metalic.CandyRed"
Wheels="Forged.Aluminun.FiveSpoke.GunMetal" />
or
<Control:Car Color="Paint.Matte.Yellow"
Wheels="Forged.Steel.SevenSpoke.BareMetal" />
I have tried creating public properties in the server control that are just types/classes that point to the base class but intellisense doesn't come up with anything. I can use a straight forward enum and that will show up but I can't do anything hierarchical that way. I've been looking for examples but I can't seem to find anything. Any help would be greatly appreciated!!!!
Thank you!
How about a different example as it seems the relationship between items or their intended value, although completely unimportant, seems to be an issue.
Let's take the relationships between continent/ country / state / city / etc.... By this example, if my custom server control is called "Location" then I would like to be able to ...
<Control:Location CurrentLocation="UnitedStates.Nebraska.Lincoln" />
or
<Control:Location CurrentLocation="Europe.Italy.Napoli" />
Your problem is worse than the previous two answers suggest: you don't know what you're doing.
Sorry to sound so harsh, but where did you ever see something like "Paint.Metalic.CandyRed", and what did it mean there? Or "Forged.Aluminun.FiveSpoke.GunMetal"? What do you even want that to mean?
First, figure out what you want to represent. Then, create a class that can represent it. Then, add a property of that class to the server control. You may have to add a TypeConverter or other designer support in order for ASP.NET to convert your preferred textual representation into an instance of the class. Otherwise, you'll be able to get something like the properties of a Font.
I'm going to make a guess about what some of these values represent, and try to show you how to deal with them in a control. My guess could be far off, though.
I'll work with "Paint.Metalic.CandyRed". I'll assume this applies to the domain of automobile customization, and that the Color property is meant to represent the finish given to the car as a whole. In that case, "Paint" would probably be an enum referring to the type of finish (though I don't know what other sorts of finish apply to a car!). I know from building model cars when I was a kid that paints may be metallic, or gloss, or flat, so those three would be enum values of one enum. "CandyRed" would be one of many colors. This would give something like this:
public enum FinishType
{
Paint,
NotPaint // _I_ don't know!
}
public enum PaintFinish
{
Metallic,
Gloss,
Flat
}
public enum CarColor
{
CandyRed,
SilverMist,
DesertSandMica,
MagneticGray,
// etc.
}
public class CarFinish
{
public FinishType FinishType {get;set;}
public PaintFinish PaintFinish {get;set;}
public CarColor CarColor {get;set;}
}
public class Car : WebControl
{
public CarFinish Color {get;set;}
}
This would allow for something like this:
<Control:Car Color-FinishType="Paint"
Color-PaintFinish="Metallic"
Color-CarColor="CandyRed" .../>
or this:
<Control:Car ...>
<Color FinishType="Paint" PaintFinish="Metallic" CarColor="CandyRed"/>
</Control:Car>
These items would need to be enums as that is the only way that it is supported at least in everything I have seen. now, you can accomplish what you want with a few enums.
namespace Paint
{
public enum Metalic
{
CandyRed
}
public enum Matte
{
Yellow
}
}
Granted, not perfect, but easy to document and understand!
As Mitchel Sellers posted, they will need to be either Enum or Constants/Statics.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Paint
{
public class Metallic
{
public static Color CandyRed
{
get { return Color.Red; }
}
public static Color CandyGreen
{
get { return Color.Green; }
}
}
public class Matte
{
public static Color Red
{
get { return Color.Red; }
}
public static Color Green
{
get { return Color.Green; }
}
}
}