Custom Itemrender in Datagrid with Datatip - apache-flex

I have a datagrid with one datagridcolumn in it. Without a custom itemrenderer I can use a datatipfunction for showing a custom datatip but now I want to have a custom item render for colouring the rows differently. Therefore I extended a label and changed the data method but now my datatipfunction does not work anymore.
Any ideas?
thanks in advance
Sebastian

I know this question is a wee bit old, however I just ran into the same problem and solved it by looking at how the standard DataGridItemRenderer class does it.
So basically I ended up copying that toolTipShowHandler() function into my class (without any modification), implementing the IDropInListItemRenderer interface and adding a few lines into my renderer's commitProperties() function, which were inspired by the DataGridItemRenderer, too.
Hope this helps.

I'm a little late to the party, but I ran into this issue with a custom DataGridItemRenderer for images. The solution described at the following link worked out nicely for me:
http://www.kalengibbons.com/blog/index.php/2008/12/displaying-datatips-when-using-an-itemrenderer/
The gist is that you override the item render's updateDisplayList() and set a tool tip by calling the dataTipFunction and/or using the dataTipField just like a built-in item renderer.

copying the content of link given by cbranch here. stackoverflow is more reliable for keeping code snippets
Displaying DataTips when using an itemRenderer
One of the bad things about using itemRenderers in a DataGridColumn is that you lose the dataTip functionality that it normally provides. Well, here is a way to fake that functionality.
First, add the dataTipField or dataTipFunction to the DataGridColumn like you normally would.
<mx:DataGridColumn headerText="DataTip"
dataField="name1"
showDataTips="true"
dataTipField="description1" />
Then, in your itemRenderer add the following code to be able to tap into that information and display a tooltip instead.
private function getToolTip():String{
var dg:DataGrid = listData.owner as DataGrid;
var func:Function = dg.columns[listData.columnIndex].dataTipFunction;
if(func != null){
return func.call(this, this.data);
}else if(dg.columns[listData.columnIndex].dataTipField.length){
return data[dg.columns[listData.columnIndex].dataTipField];
}else{
return "";
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
this.toolTip = getToolTip();
}
This works with both dataTipFields and dataTipFunctions and lets you treat the dataTips in your columns the same way, regardless of whether you’re using an itemRenderer or not. The only minor difference is the positioning of the label, but that can be easily modified with styles. You can download the full source code here, for a functional example of how this works.
source

Just off the top of my head, maybe make your custom item renderer extend DataGridColumn. This will give your item renderer all the functionality of a regular column.

Related

How to skin buttons in flex 3?

Just out of curiosity, I am making an effort to optimize every part of our flex app (which is a small part of our app in general). Currently, I am working on optimizing all of the buttons/skins. I have linked a few of the buttons that I use, and some sample code I am using to generate them.
Please advise on how to make this more efficient, usable, and just better overall. Thanks!
As you can see, our buttons can be pretty different, but have a similar look and feel. Currently, I am creating 'stateful skins,' by setting up something like this:
skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin');
Then, NavigationButtonSkin looks something like this:
public class NavigationButtonSkin extends UIComponent {
// imports, constructor, etc
protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
// initialize fillColors, fillAlphas, roundedCorners, etc
switch( name ){
case 'upSkin':
fillColors = [getStyle('backgroundColor'),getStyle('backgroundColor2')];
break;
// do the same for overSkin, downSkin, disabledSkin, etc
}
// use this.graphics to draw background
// use this.graphics to draw border on top of background
}
}
I commented out some of the straight forward parts, but let me know if this is a bad/inefficient way of doing this - and how to improve.
Thanks!
In terms of performances, it would be better that your skin inherits from ProgrammaticSkin instead of UIComponent.
ProgrammticSkin itself inherits from Shape and provides utility methods for skinning such as verticalGradientMatrix, drawRoundRect, ...
That's all I can say looking at your code.
Good point is you use programmatic skin instead of bitmap/swf based skins.
Okay, I'm not getting where you're getting at with this. You just want to know if you're doing it right? I'm assuming that your skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin'); is added to the css of a Button, which is good, however I don't see why you're doing it all in Actionscript. Seems inefficient and essentially you're losing all the ability of mxml layouts and support for Catalyst (if you'd ever need it in the future).
Try creating a skin in Flash Builder, it'll create an MXML with the default button skin where you can just edit it as you please. It's also A LOT easier to do state based design using mxml over actionscript. You should modify from there on and have a separate skin for each button types.
EDIT: oh crap, didn't see this was Flex 3... Get with the program ;) Just listen to what Florian said.

flex: cant edit item in Datagrid with override set data method

I've a custom itemRenderer for my datagrid. To set the actual data I use the following method:
override public function set data(side:Object):void{
...
}
As soon as I use this function the cell doesn't show up any item Editor anymore. Why is that? When I remove this function the itemEditor is working but with the wrong initialization data...
What's the proper way to handle this?
Thanks,
Markus
Have u called 'Super' on that method ?
Make sure that you also have an itemEditor that is correctly working or that you set the rendererIsEditor property to true and use the renderer as the editor.

Moving children of a container (defined in MXML) inside an "inner container"

I'm currently working on a custom component which extends Canvas (let's call it SuperCanvas) ; it's basically a container that let you zoom & pan its contents.
It would be too long to explain why, but I can't use scrollRect, so I was forced to declare a Canvas object (called innerCanvas)... inside my SuperCanvas (I know, not very nice =/)
I would like to know if there's a proper way to "redirect" the creation of my component's children in this canvas.
Let me explain:
<comp:SuperCanvas id="superCanvas">
<mx:Image id="img" source="image.jpg"/>
<mx:Label id="lbl" text="Sample"/>
</comp:SuperCanvas>
With this, img and lbl are added to my SuperCanvas. I want them to be added to superCanvas.innerCanvas instead.
I can't override the add/removeChild methods to do the "redirection", since I won't be able to add this innerCanvas...
So I tried this :
<comp:SuperCanvas>
<comp:innerCanvas>
<mx:Image id="img" source="image.jpg"/>
<mx:Label id="lbl" text="Sample"/>
</comp:innerCanvas>
</comp:SuperCanvas>
But Flex complains that "In initializer for 'contents': type mx.controls.Image is not assignable to target type mx.containers.Canvas". I read I could use an array of UIComponents with a [ArrayElementType] metatag, and manually instanciate objects, but I I'm looking for a simplier (and probably proper) solution.
I also saw the childDescriptor property (which contains descriptions for every child defined in the MXML file), but it's read-only, so I can't pass it to my innerCanvas.
If I'm not clear enough, do not hesitate to ask me precisions, english isn't my native tongue, so it's pretty hard to explain things well =/
Any help would be greatly appreciated, I'm totally stuck.
EDIT:
My SuperCanvas class (minus the imports and the zoom & pan logic that doesn't matter here) :
public class SuperCanvas extends Canvas
{
public innerCanvas:Canvas = new Canvas();
public function SuperCanvas()
{
super();
addChild( innerCanvas );
}
}
This blog entry details an approach where you add components to the SuperCanvas, but then move them all to the inner canvas after creation. So that's one workaround.
Alternatively, you could set the DefaultProperty to be a dataProvider-type object, and then add things to the inner canvas from there, rather than making them children of the SuperCanvas first.
Addition:
I ran across this blog entry which, among other things, talks about the Panel component and how it handles this problem. You might look at it and at the Panel source code.

flex3:How to override function set label of a button

Flex 3 question:
I trying here to avoid having to bind resources to all my components labels ( ie a button) and find a way to have this automated.
Problem:
It corrupts the layout in design mode to bind directly in the mxml label="{resourceManager.getString('myResources', 'submit')}" and makes the design view useless. but when declaring bindings elsewhere, in actionScript or via a bind tag, it is counter productive and prone to many errors and miss.
Proposition:
I would like to create my own button that automatically invoke resources to localize a button label. So the author puts "Submit" in the mxml description of my button, and when running it would take the value of the label ie "submit" and use resourceManager.getString('myResources', 'submit').
but I can't find the way to override the set label function, Is it possible if yes how? else how can I go about it?
Maybe I am missing an essential process here that would make the use of resources more elegant, as well as how to override such thing as a button's label.
Thanks for your advices.
Create a component called MyButton, extending Button. Then use this:
override public function set label(value:String):void {
super.label = resourceManager.getString('myResources', value) || value;
}
Assuming the resource manager returns "null" or "undefined" this will work, and will only replace the value if it exists in "myResources".
If you don't want to override every component you need to do this with, then you can add a FlexEvent.CREATION_COMPLETE event on every component. Then use a single generic function to do your label localization.

Flex Truncating Button Labels

First and foremost, I apologize for any vagueness in this question. At this point, I'm simply trying to get some new ideas of things to try in order to diagnose this bug.
Anyway, the problem I'm having is with an application that's using a custom moduleloader. That moduleloader has been compiled into an swc and the moduleloader is being instantiated via its namespace. This all works perfectly fine. The problem I'm encountering is specific to mx:button controls used within modules. For whatever reason, their labels are being truncated so, for example, Sign In is showing up with an ellipsis, as Sign ...
After quite a bit of fooling around I have been able to establish the following:
This problem only seems to occur within modules. If a button control is used in the main mxml, the label does not get truncated.
The button control whose label is being truncated does not have a width specified (setting its width to 100% or a specific pixel width doesn't fix the issue)
The button control is using the default padding (messing with the padding by setting left and right to 5 or any other value doesn't help matters either).
We are not using any embedded fonts so I've ruled that out as a possibility as well.
mx:CheckBox and mx:LinkButton are equally impacted by this problem although mx:CheckBox also seems to not want to show its checkbox, it just shows the truncated label.
A potential side affect of this is that attaching a dataprovider to mx:ComboBox causes the combobox control to throw a drawing error but I'm not entirely certain that it's related to the above problem.
One interesting thing I did find while perusing the net for an answer was a mention of fontContext and its relationship to IFlexModuleFactory. There's no specification for fontContext within our implementation of moduleloader so I'm not entirely certain if this could be the issue. In any case, if anyone has any ideas, it would be hugely appreciated. On the other hand, if you know exactly what ails me and can provide me with an answer, I might just wet myself with excitement. It's late. I'm tired. I NEED my Flex app to play nice.
Thanks in advance,
--Anne
Edit: To clarify what I'm looking for with this question, I really just need to know the following:
Could this issue be caused by a namespace conflict?
What else can potentially override the default behavior of labels if no CSS has been implemented?
Has anyone encountered a problem with inheritance being lost while using a custom implementation of moduleloader?
Has anyone encountered this problem or a similar problem with or without using moduleloader?
I'm not sharing any code with this question simply because I'd have to share the entire application and, unfortunately, I can't do that. Again, I'm not looking for the end all, be all solution, just some suggestions of things to look out for if anyone has any ideas.
I've been dealing with this issue myself, off and on and in various forms, for a year, and while I haven't figured out just what's causing it yet, there's clearly a mismeasurement happening somewhere along the line.
What I have been able to to, though, is work around it, essentially by subclassing button-type controls (in my case, Button, LinkButton, PopUpButton, et. al.) and assigning their textField members instances of a UITextField extension whose truncateToFit element simply returns false in all cases:
public class NonTruncatingUITextField extends UITextField
{
public function NonTruncatingUITextField ()
{
super();
}
override public function truncateToFit(s:String = null):Boolean
{
return false;
}
}
The custom component just extends Button (or whatever other button-type control is the culprit -- I've created a half-dozen or so of these myself, one for each type of control), but uses a NonTruncatingTextField as its label, where specified by the component user:
public class NonTruncatingButton extends Button
{
private var _truncateLabel:Boolean;
public function NonTruncatingButton()
{
super();
this._truncateLabel = true;
}
override protected function createChildren():void
{
if (!textField)
{
if (!_truncateLabel)
textField = new NonTruncatingUITextField();
else
textField = new UITextField();
textField.styleName = this;
addChild(DisplayObject(textField));
}
super.createChildren();
}
[Inspectable]
public function get truncateLabel():Boolean
{
return this._truncateLabel;
}
public function set truncateLabel(value:Boolean):void
{
this._truncateLabel = value;
}
}
... so then finally, in your MXML code, you'd reference the custom component thusly (in this case, I'm telling the control never to truncate its labels):
<components:NonTruncatingButton id="btn" label="Click This" truncateLabel="false" />
I agree it feels like a workaround, that the component architecture ought to handle all this more gracefully, and that it's probably something we're both overlooking, but it works; hopefully it'll solve your problem as you search for a more definitive solution. (Although personally, I'm using it as-is, and I've moved on to other things -- time's better spent elsewhere!)
Good luck -- let me know how it works out.
I've used the custom button and link button class solutions and still ran into problems - but found a workaround that's worked every time for me.
Create a css style that includes the font you'd like to use for you label. Be sure to check 'embed this font' right under the text selection dropdown. Go back and apply the style to your button (or your custom button, depending on how long you've been bashing your hear against this particular wall), and voila!
Or should be voila...
I just came across this issue and solve it this way:
<mx:LinkButton label="Some label"
updateComplete="event.target.mx_internal::getTextField().text = event.target.label"
/>;
I've had some success preventing Flex's erroneous button-label truncation by setting labelPlacement to "bottom", as in:
theButton.labelPlacement = ButtonLabelPlacement.BOTTOM;
Setting the label placement doesn't seem to help prevent truncation in some wider button sizes, but for many cases it works for me.
In cases where you can't use a bottom-aligned button label (such as when your button has a horizontally aligned icon), janusz's approach also seems to work. here's a version of janusz's .text reassignment technique in ActionScript rather than MXML:
theButton.addEventListener(FlexEvent.UPDATE_COMPLETE, function (e:FlexEvent):void {
e.target.mx_internal::getTextField().text = e.target.label;
});
The preceding code requires you to import mx_internal and FlexEvent first, as follows:
import mx.events.FlexEvent;
import mx.core.mx_internal;
And here are the results…
Before (note truncation despite ample horizontal space):
After:
The only downside to this approach is you lose the ellipsis, but in my case I considered that a welcome feature.

Resources