in Flex/AS3 how can I highlight a datagrid row? - actionscript-3

I am writing an application, using a datagrid. Various rows are differing colors based on the data. When the user selects a row the color becomes a few shades lighter.
Unfortunately one of the users doesn't think it is enough of a contrast and would like a more noticeable visual indicator. My two thoughts are to either;
A) Draw a rectangle around the entire row selected.
B) Add a column with an image that I hide or make visible based on whether the row is selected.
I went down path A. for a while and got to the point where in the function;
override protected function drawHighlightIndicator
I was able to identify when I was looking at the specific row, but I couldn't determine how to draw the rectangle.
So I backtracked and looked into B. I am able to create an Item renderer with an arrow, but I can't figure out how to turn it on & off when selected. I have a click event in the main module, but no way to reference back to the Item renderer component.
I could set a value in the array collection, and do a refresh, which will probably work, but that tends to move the selected row to the top of the datagrid display area.
So if anyone can help I on A or B would appreciate it. This is a DataGrid, not an AdvancedDataGrid.

Since you're using mx.controls.DataGrid, overriding drawHighlightIndicator could look like following example, which draws 1px red border around selection marker:
protected function drawHighlightIndicator(
indicator:Sprite, x:Number, y:Number,
width:Number, height:Number, color:uint,
itemRenderer:IListItemRenderer):void
{
var width:int = unscaledWidth - viewMetrics.left - viewMetrics.right;
var borderColor:uint = 0xff0000;
var g:Graphics = Sprite(indicator).graphics;
g.clear();
g.beginFill(borderColor);
g.drawRect(0, 0, width, height);
g.beginFill(color);
g.drawRect(1, 1, width - 2, height - 2);
g.endFill();
indicator.x = x;
indicator.y = y;
}

Related

Dynamically draw rectangle between the Dragable objects in AS3

My aim is to highlight the area between the two dragable objects inpoint_mc and scrub_outpoint_mc, so i had created a rectangle between these points, i need to resize this rectangle based on the dragpoints, which indicates the distance between Inpoint and Outpoint, i tried my level best unfortunately i can acheive it
private function startScrubbingIN(_arg1:MouseEvent){
trace("scrubBarIsMovingIN");
this.cueCard.stage.addEventListener(MouseEvent.MOUSE_UP, this.stopScrubbingIN);
this.cueCard.stage.addEventListener(MouseEvent.MOUSE_MOVE, this.scrubBarIsMovingIN);
this.scrubbing = true;
var _local2:Rectangle = new Rectangle(this.controls_mc.progressBar_mc.x, this.controls_mc.inpoint_mc.y,
this.controls_mc.scrub_outpoint_mc.x-this.controls_mc.progressBar_mc.x, 0);
// now we're limiting in point to current position of out point
this.controls_mc.inpoint_mc.startDrag(false, _local2);
this.controls_mc.addChild(_seekIndicator);
_seekIndicator.graphics.beginFill(0x990000);
_seekIndicator.graphics.drawRect(this.controls_mc.inpoint_mc.x, this.controls_mc.progressBar_mc.y,
this.controls_mc.scrub_outpoint_mc.x-this.controls_mc.progressBar_mc.x, 12);
trace("_seekIndicator"+ _seekIndicator);
// _seekIndicator.width = this.controls_mc.scrub_outpoint_mc.x+ this.controls_mc.inpoint_mc.y;
}
it giving me the result as like the attached image
but the red rectangle need to be shrink itself between the 2 Points
The rectangle should be redrawn only after you stop dragging, or when you move mouse while dragging. Don't forget to call _seekIndicator.graphics.clear() to delete old rectangle. And finally, use this.controls_mc.scrub_outpoint_mc.x and this.controls_mc.inpoint_mc.x for borders, because you're saying the rectangle should be between the in and out point MCs, while you use this.controls_mc.progressBar_mc.x in width.
private function scrubBarIsMovingIN(e:MouseEvent):void {
// the startDrag dragged one of the sliders already
// existing code skipped, if any
_seekIndicator.graphics.clear();
_seekIndicator.graphics.beginFill(0x990000);
_seekIndicator.graphics.drawRect(this.controls_mc.inpoint_mc.x, this.controls_mc.progressBar_mc.y,
this.controls_mc.scrub_outpoint_mc.x-this.controls_mc.inpoint_mc.x, 12);
}
Should do.

AS3 Clicking in "zones" of a picture

I have searched and simply cannot find what I need (if it exists).
A window will have a large picture.
The picture will be divided into zones (such as border lines that separate states on a map).
When a person clicks within a zone, then I will raise the appropriate event.
I've used AS3 with MXML to create a database program. All is working great except for this last step. I cannot figure out how the user is within a particular area of the picture when he clicks or when he touches.
I've read and tried to come up with an approach, and there must be (hopefully so) an easier way than the muddled nonsense I'm coming up with.
Thanks
VL
Are you drawing it in flash professional CS6? If so then why can't you just have the picture as a symbol and then just self divide the lines and make those divided areas into symbols that are children of the picture symbol. You could keep the individual state symbols right where they so that they stay true to the overall picture.
A first thought would be to make an instance of this picture symbol through the code, and then loop though all the children of that picture and add a click event to each one.
var picture:Picture=new Picture();
for(var i:int=0; i<picture.numChildren-1; i++){
picture.getChildAt(i).addEventListener(MouseEvent.CLICK, mouseEventHandler);
}
Please comment if I am missing something, or this does not work.
EDIT
Well, if you know the dimensions of the image, you could divide its width and height by 3(your number of rows and columns) and this is your zone dimensions. You then could take the mouse's click point relative to the top left of your picture and then divide its width by the zone with, and its height by the zone height, and then get its integer floor value, you could get which region it is. Code it below:
//This is all for a constat region list (like a window, or floor tiles, not things irregular)
import flash.display.Sprite;
var regionsX:int = 3; //Your number of windows across the row
var regionsY:int = 3; // across the column
var regions:Array = new Array(); // an array to hold the values that you will get from where the user clicks
// All of this used a 2D array method
for(var x:int = 0; x < regionX; x++) {
regions[regionsX] = new Array();
for(var y:int = 0; y < regionY; y++) {
regions[regionsX][regionsY] = "region(".concat(x).concat(",").concat(y);
// Here you make this equal to anything you want to get a value of,
//once the correct region is found (I just have a string version here for an example)
}
}
... // other stuff..
var picture:Picture = new Picture(); // your window picture
var regionWidth:Number = picture.width / regionsX; // Gets each region's width
var regionHeight:Number = picture.height / regionsY; // Get each regoin's height
...
picture.addEventListener(MouseEvent.CLICK, mouseEventListener); // add a click listener to the picture
function mouseEventListener(event:MouseEvent):void{
var mouseX:Number = picture.globalToLocal(event.stageX); // gets where the user clicked, and then converts it
//to the picture's cordinate space. ( 50,100 acording to the stage, could be (25,200) to the picture)
var mouseY:Number = picture.globalToLocal(event.stageY); // same for the Y
var regionIntX:Number = Math.floor(mouseX / regionWidth); // Dives the point by each region's width, and then
// converts it to a while integer. (For instance, if a region's width is 100 and you click at 288, then if you do the
// math, you clicked in the 3rd region, but it returns 2... why? (becaue the array counter starts at 0, so 0 is the 1st
// region, 1 is the second and so on...
var regionIntY:Number = Math.floor(mouseY / regionHeight); // Same for Y
var yourValue:String = regions[regionIntX][regionIntY]; // This returns that you initialy put into your 2d array
// by using the regionIntX and regionIntY for the array values. You have to decide what is stored in this array...
}
The simplest solution would be to add an event listener for MouseEvent.CLICK to the picture and in the handler check properties mouseX and mouseY of the picture. Define the bounds of each area in an XML or similar and check against current mouseX/Y to see which area has been clicked.

move in move out tween animation for group of movieclips using as3

I have set of 6 movieclips as array_0 and another set of 6 movieclips as array_1. It is like two choices for different screens. Both these arrays are nested in another array as all_array. all 12 movieclips are positioned to a same x and y at initial load and that is outside the visible stage. I would like to use two different global variables for indexing. for example, cCat_Sel which ranges from 0-5 and another cScr_Sel ranges from 0-1. cCat_Sel will be changed on a click event of six buttons separate objects on stage (each button for each category).
so it will show the content for each category as per the value of cScr_Sel. if cScr_Sel is 0 then it will use all_array[0][cCat_Sel] to access the current target and similarly respective array for value of 1 as all_array[1][cCat_Sel]
I have done all the work including all tween animations to move current target and make it visible. But the tween does not bring the second set of mcs to visible area. I have two functions one for movein and one for move out by using tween animation for mc.x property. every relevant click event; I have to move current mc out and make alpha 0 and once that is finished, move in new current target and make alpha 1.
Somehow I have to combine these two tweens in one function. This is the part that I am stuck. or may be putting these mcs in two different arrays not a correct approach. I can easily achieve what I want on Enter Frame event of the root to check for cCat_Sel and cScr_Sel variables and do both animations one after the other but it seems like enter frame uses too much of cpu and makes it slower and probably not preferable.
willing to try anybody's suggestions or guidance. Thanks in advance.
I do not have any formal or informal programming education at all but I make things work by reading and trying out few things as per stackoverflow question and answers and sometime google. because most of my answers I have found from stack overflow.
Update:
function fnSlideInOut(cMc:Object, pMc:Object){
var HideX:Number =650;
var ShowX:Number = 0;
if(cMc != null){
if(cMc.x != ShowX){
//cMc.alpha = 1;
var SlideMcIn:Tween = new Tween(cMc, "x", Strong.easeOut, 650, ShowX, 0.5, true);
SlideMcIn.addEventListener(TweenEvent.MOTION_FINISH, fnSlideInFinish);
SlideMcIn.start();
}
}
if(pMc != null){
if(pMc.x != HideX){
//pMc.alpha = 1;
var SlideMcOut:Tween = new Tween(pMc, "x", Strong.easeOut, 0, HideX, 0.5, true);
SlideMcOut.addEventListener(TweenEvent.MOTION_FINISH, fnSlideOutFinish);
SlideMcOut.start();
}
}
function fnSlideOutFinish(e:TweenEvent){
//SlideMcOut.obj.alpha = 0;
SlideMcOut.removeEventListener(TweenEvent.MOTION_FINISH, fnSlideOutFinish);
}
function fnSlideInFinish(e:TweenEvent){
//SlideMcIn.obj.alpha = 1;
SlideMcIn.removeEventListener(TweenEvent.MOTION_FINISH, fnSlideInFinish);
}
}//End Function
fnSlideInOut(cScr_Sel, pScr_Sel);
I would like expert like you to comment on any kind of errors for the above code. It works 99 times but 1 time the movieclip either does not reach the destination or current and previous both targets showing and that too not where they are suppose to. This only happens when button click event happens in a quick succession. Thanks again
A option could be to use a third party library like TweenLite. It will then make it easy for you to run your second animation right after the first one is complete:
private function startAnimation():void
{
var mcToHide:MovieClip = all_array[cScr_Sel][cCat_Sel];
TweenLite.to(mcToHide, 1, {x: HIDDEN_X_POSITION, y:HIDDEN_Y_POSITION, alpha:0, onComplete:finishAnimation});
}
private function finishAnimation():void
{
var mcToShow:MovieClip = all_array[(cScr_Sel + 1) % 2][cCat_Sel];
TweenLite.to(mcToShow, 1, {x: VISIBLE_X_POSITION, y:VISIBLE_Y_POSITION, alpha:1});
}
You can then call startAnimation() on a relevant mouse click event and after having set cScr_Sel and cCat_Sel accordingly to your needs.

Setting multiple depth layers in AS3

I get how to set depth in as3 - but with as2 i could begin multiple 'depth points' using numbers - where in as3 all i can seem to do is set this object to a higher/lower depth than that object. The problem is (when dealing with a stack of isometric boxes, which can be placed by the user on a grid in any order) i don't want to deal with the added complexity of having every element know where every other element is, then adjust appropriately.
What I'm trying to do is set up 6 total depth numbers/positions, one for each column in a 6 x 6 grid. So anything in column 1 will begin it's depth placement at say 500, anything in column 2 will begin its depth at 1000, column 3 would be 1500 and so on.
That way, the second i place an object on a particular column, it would tuck itself under, or place itself above all surrounding items in other columns, this to me is much much easier than somehow figuring out where 15 different sized boxes are, how they relate to one another, then figure out what depth order they need to go in.
Any ideas? as3 seems to have removed the ability to set a depth to a specific number :p
The approach can be simplified. You basically want to create 3 'container' clips and add them in order. The last one added is the top-most.
Bonus: if you want to rearrange, you can call addChild() on any clip (even already added ones) and that one will go to the top.
//// IMPORTANT STUFF ////
import flash.display.Sprite;
var top:Sprite = new Sprite;
var mid:Sprite = new Sprite;
var bot:Sprite = new Sprite;
addChild(bot);
addChild(mid);
addChild(top);
//// END IMPORTANT STUFF ////
// Move Stuff so we can visualize how this works.
// Then add some boxes so we can see what's going on.
mid.x = 20;
mid.y = 20;
bot.x = 40;
bot.y = 40;
// Add Top box
var t:Sprite = new Sprite;
t.graphics.beginFill(0xFF0000);
t.graphics.drawRect(0,0,100,100);
top.addChild(t);
// Add Middle box
var m:Sprite = new Sprite;
m.graphics.beginFill(0x00FF00);
m.graphics.drawRect(0,0,100,100);
mid.addChild(m);
// Add Bottom box
var b:Sprite = new Sprite;
b.graphics.beginFill(0x0000FF);
b.graphics.drawRect(0,0,100,100);
bot.addChild(b);

Actionscript 3.0 problem - Why is it giving an error even when I've re-checked the code?

I'm using Adobe Flash CS4 professional for this Actionscript 3.0 project
(http://tutorials.flashmymind.com/2009/02/rotating-menu-via-actionscript-3/)
I even tried following the suggestions in the comments as well but this error always shows up:
TypeError: Error #1010: A term is undefined and has no properties.
at rotating_menu_fla::MainTimeline/frame1()
(for complete details, kindly click the link - http://i429.photobucket.com/albums/qq19/tsujzpie/screenshot_03.jpg)
I've been following every step of the tutorial but I'm stumped over the coding...
Here's the code by the way...
//Save the center coordinates of the stage
var centerX:Number=stage.stageWidth/2;
var centerY:Number=stage.stageHeight/2;
//The number of items we will have (feel free to change!)
var NUMBER_OF_ITEMS:uint=5;
//Radius of the menu circle (horizontal and vertical)
var radiusX:Number=200;
var radiusY:Number=100;
//Angle difference between the items (in radians)
var angleDifference:Number = Math.PI * (360 / NUMBER_OF_ITEMS) / 180;
//How fast a single circle moves (we calculate the speed
//according to the mouse position later on...)
var angleSpeed:Number=0;
//Scaling speed of a single circle
var scaleSpeed:Number=0.0002;
//This vector holds all the items
//(this could also be an array...)
var itemVector:Array = new Array ('1', '2', '3', '4','5');
//This loop creates the items and positions them
//on the stage
for (var i:uint = 0; i < NUMBER_OF_ITEMS; i++) {
//Create a new menu item
var item:Item = new Item();
//Get the angle for the item (we space the items evenly)
var startingAngle:Number=angleDifference*i;
//Set the x and y coordinates
item.x=centerX+radiusX*Math.cos(startingAngle);
item.y=centerY+radiusY*Math.sin(startingAngle);
//Save the starting angle of the item.
//(We have declared the Item class to be dynamic. Therefore,
//we can create new properties dynamically.)
item.angle=startingAngle;
//Add an item number to the item's text field
item.itemText.text=i.toString();
//Allow no mouse children
item.mouseChildren=false;
//Add the item to the vector
itemVector.push(item);
//Add the item to the stage
addChild(item);
}
//We use ENTER_FRAME to animate the items
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
//This function is called in each frame
function enterFrameHandler(e:Event):void {
//Calculate the angle speed according to mouse position
angleSpeed = -(mouseX - centerX) / 5000;
//Loop through the vector
for (var i:uint = 0; i < NUMBER_OF_ITEMS; i++) {
//Save the item to a local variable
var item:Item=itemVector[i];
//Update the angle
item.angle+=angleSpeed;
//Set the new coordinates
item.x=centerX+radiusX*Math.cos(item.angle);
item.y=centerY+radiusY*Math.sin(item.angle);
//Calculate the vertical distance from centerY to the item
var dy:Number=centerY-item.y;
//Scale the item according to vertical distance
item.scaleY = (dy / radiusY)+2;
//Set the x scale to be the same as y scale
item.scaleX=item.scaleY;
//Adjust the alpha according to y scale
item.alpha=item.scaleY+1.1;
}
}
I find it odd - it may be that the code is right but I don't know if these steps has messed up the project...
3 - Convert the circle into a movie clip...
4 - In the “Item” movie clip, create a dynamic text field in the center of the circle (in a new layer).
5 - Set the text to align center. Type some number in the text field. Give the text field an instance name of “itemText”. Embed numerals...
6 - Remove the Item movie clip from the stage. We will create all the items dynamically via ActionScript 3.
I could've given more screenshots but since I'm a new user, I'm only allowed a max of two - and contrary to this tag, I'm not doing an Android app.
(I'll give you added info once any of you would reply to this question...)
I have to admit that the steps 3 to 6 is confusing and didn't made sense to me - especially with step six, when you have to remove the movie clip from the stage. For me, if I were to do that, what would the script work on then?
Any idea what I did wrong?
EDIT:
Thanks, I realized my mistake - thanks for the tip :-)
But now, I tried to modify the code of this tutorial a bit to have words appear inside the circles (like "Home", "About", etc....) like what I've typed in the line in the screenschot - http://i429.photobucket.com/albums/qq19/tsujzpie/modifiedlineincode_00.jpg
But inspite of what I believe are the appropriate changes I've done, an error showed up still - (kindly see here - http://i429.photobucket.com/albums/qq19/tsujzpie/newerrorincode_00.jpg)
Why is that happening? Before I forget, in what section of the code must I insert a line that will make a clicked button display the info corresponding to it? (that is, if I click on the "Contact" or any of the buttons a window will appear beneath the menu on the stage...)
That errors means ActionScript has no clue what an Item is. Make sure you've ticked Export for ActionScript on your Item MovieClip in library and that the class is named Item also.
Update:
The tutorial you're following mentions itemVector is a Vector of Item instances, not an array of Strings like you're code suggests. This why you're getting the error displayed in your screenshot. It means ActionScript can not convert an Item to a String.
An easy fix is to create another array for the menu item labels:
var itemVector:Array = [];// = new Array ('1', '2', '3', '4','5');
var itemLabels:Array = ["Home","About","Contact","Gallery"];
NUMBER_OF_ITEMS = itemLabels.length;
and in the for loop swap this item.itemText.text=i.toString(); for this tem.itemText.text=itemLabels[i];
It seems that you don't fully grasp the difference between variable types. I would suggest getting familiar with the basics of as3 before moving forward. Also paying more attention to your code and fully understanding code you use written by others will keep you out of trouble. However you will still encounter errors. You might find explanations for those errors on the Flash Error Database.
Regarding the Carosel tutorial, also have a look at this video. It might help explain things better.
The compiler can not find the Item class.
Go into your library and open up the properties for the "Item" MovieClip.
Verify that is is set for export to actionscript.