5 Replies Latest reply on Jun 13, 2010 10:53 AM by Shongrunden

    MXML Custom Compent Child Overriding it's Parent's Content Group?

    boneitis Level 1

      Hello all, I am creating a custom component using Flex 4 SDK  in MXML and running in to an error. Here is the situation:

       

      I have 2 Classes, MyContainer.mxml and ChatView.mxml.  MyContainer does some nice scaling, resizing, site wide announcements, and ChatView holds the core functionality for sending and receiving various chat message.  Below are the 2 classes

       

       

       

      MyContainer.mxml:

      <?xml version="1.0" encoding="utf-8"?>
      <s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                                 xmlns:s="library://ns.adobe.com/flex/spark"
                                 xmlns:mx="library://ns.adobe.com/flex/mx" 
                                 minHeight="200" minWidth="300"
                                 creationComplete="init()">
           <fx:Script>
                <![CDATA[
                     private function init():void{
                          addListeners();
                     }
                    
                     public function addListeners():void{
                          westBtn.addEventListener(MouseEvent.MOUSE_DOWN, function(_e:Event){trace("do stuff");});
                     }
                              
                ]]>
           </fx:Script>
               
           <s:Group height="100%" width="100%" >         
                <s:BorderContainer id="westHitArea" alpha="0" top="0" left="0" height="10" width="10" backgroundColor="0x00FF00"/>
                <s:Button id="westBtn" alpha="0" hitArea="{westHitArea}"/>
           </s:Group>

       

      </s:SkinnableContainer>

       

       

       

      ChatView:

      <?xml version="1.0" encoding="utf-8"?>

      <components:MyContainer xmlns:fx="http://ns.adobe.com/mxml/2009"

                                            xmlns:s="library://ns.adobe.com/flex/spark"

                                            xmlns:mx="library://ns.adobe.com/flex/mx" >

       

                <s:HGroup>

                     <s:Label text="Location:" />

                     <s:Label id="chatRoomLocation" text="---" />

                </s:HGroup>

      </components:MyContainer>

       

       

       

      As you can see this isn't terribly complex, however 100% of the time i am getting errors in 'addListeners' of SkinnableContainer.  It doesn't seem to be a race condition, as a timer does not help.

       

      If run by itself, MyContainer works as expected with no errors.

       

      After doing some research it looks like the ContentGroup in MyContainer is getting overwritten by ChatView. Has anyone run to this before?  The basic type of overriding custom MXML components that we use to do in SDk3.5 now seem to be broken, and fills me with rage. I realize Adobe didn't 'just break it then release' so if this is a 'feature' if someone could explain the rationale, or how to fix it, that would be awesome.

       

      Thank you.

        • 1. Re: MXML Custom Compent Child Overriding it's Parent's Content Group?
          David_F57 Level 5

          hi,

           

          why have you got a button that is made invisble then the click to the container which is invisible, its not exactly simple, I am actually more confused by this code than I have been by anything else ever, I'm surprised you ever get a click event raised. You have no layout control what ever, the component is filling the whole parent and under it is a hgroup, You have eventlisteners on invisible surfaces you have uicomponent declared as a hit area, hitarea is a sprite. This code wouldn't even compile.

           

           

          David.

          • 2. Re: MXML Custom Compent Child Overriding it's Parent's Content Group?
            boneitis Level 1

            HAHAHA, I am glad I have such confusing code for you

             

            The code above was just a snipped of code from a much larger class.  And yes, despite your thoughts, it does compile.

             

            As stated above, this is just a bit of the code, the entire code creates a series of BorderContainer set with alpha to 0 all around the border of a Skinnable container.  As a result, with each borderContainer being placed as hit area for a button (must be alphaed out so back ground can show throw, and visible will automatically turn the .enabled state to false) the user is able to do a mouse over on any border, and then click and drag the border to resize a window.

             

            "But why don't you just put listeners for click /mouse over/ mouse down / mouse move directly on the borderContainer?" Because that throws off items in other components.  I guess in my attempt to simplify it, I have just confused you.  Hopefully the code at the bottom helps you understand.

             

             

            Now, all that being said, any idea about my actual problem?

             

             

            If you wish the code in it's entirety is below:

            <?xml version="1.0" encoding="utf-8"?>
            <s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                                  xmlns:s="library://ns.adobe.com/flex/spark"
                                  xmlns:mx="library://ns.adobe.com/flex/mx" 
                                  minHeight="200" minWidth="300"
                                  creationComplete="init()">

             

                <fx:Script>
                    <![CDATA[
                        import mx.core.FlexGlobals;
                        import mx.managers.CursorManager;
                                   
                        [Embed(source='some/cursor/source.swf')]
                        private var CursorResizeVertical:Class;
                        [Embed(source='some/cursor/source.swf')]
                        private var CursorResizeHorizontal:Class;
                        [Embed(source='some/cursor/source.swf')]
                        private var CursorResizePositive:Class;
                        [Embed(source='some/cursor/source.swf')]
                        private var CursorResizeNegative:Class;
                       
                        private var iCursorID:int;
                        private var nBorderHeight:Number = 7;
                        private var nBorderWidth:Number = 7;
                        private var nDraggableBarHeight:Number=30;
                       
                        private function init():void{
                            trace("in containter init");
                            addListeners();
                        }
                       
                        public function destroy():void{
                            removeListeners();
                        }
                       
                        public function addListeners():void{
                           
                            //mouse over on borders
                            northWestBtn.addEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            northBtn.addEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            northEastBtn.addEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            eastBtn.addEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southEastBtn.addEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southBtn.addEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southWestBtn.addEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            westBtn.addEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                           
                            //Mouse out on border
                            northWestBtn.addEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            northBtn.addEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            northEastBtn.addEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            eastBtn.addEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southEastBtn.addEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southBtn.addEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southWestBtn.addEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            westBtn.addEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                           
                            //Mouse down on Borders
                            northWestBtn.addEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            northBtn.addEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            northEastBtn.addEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            eastBtn.addEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southEastBtn.addEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southBtn.addEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southWestBtn.addEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            westBtn.addEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                           
                            //drag bar used
                            topDragBar.addEventListener(    MouseEvent.MOUSE_DOWN,     handleDragBarDown);
                            topDragBar.addEventListener(    MouseEvent.MOUSE_UP,     handleDragBarUp);
                        }
                       
                        public function removeListeners():void{
                            northWestBtn.removeEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            northBtn.removeEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            northEastBtn.removeEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            eastBtn.removeEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southEastBtn.removeEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southBtn.removeEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            southWestBtn.removeEventListener(    MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                            westBtn.removeEventListener(        MouseEvent.MOUSE_OVER, handleHotSpotMouseOver);
                           
                            //Mouse out on border
                            northWestBtn.removeEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            northBtn.removeEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            northEastBtn.removeEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            eastBtn.removeEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southEastBtn.removeEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southBtn.removeEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            southWestBtn.removeEventListener(    MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                            westBtn.removeEventListener(        MouseEvent.MOUSE_OUT, handleHotSpotMouseOut);
                           
                            //Mouse down on Borders
                            northWestBtn.removeEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            northBtn.removeEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            northEastBtn.removeEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            eastBtn.removeEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southEastBtn.removeEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southBtn.removeEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            southWestBtn.removeEventListener(    MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                            westBtn.removeEventListener(        MouseEvent.MOUSE_DOWN, handleBorderMouseDown);
                           
                            //drag bar used
                            topDragBar.removeEventListener(    MouseEvent.MOUSE_DOWN,     handleDragBarDown);
                            topDragBar.removeEventListener(    MouseEvent.MOUSE_UP,     handleDragBarUp);
                           
                            FlexGlobals.topLevelApplication.removeEventListener(MouseEvent.MOUSE_MOVE, handleBorderMouseMove);
                            FlexGlobals.topLevelApplication.removeEventListener(MouseEvent.MOUSE_UP, handleBorderMouseUp);
                        }
                       
                        private function handleDragBarDown( _event:MouseEvent ):void{
                            this.startDrag();
                        }
                       
                        private function handleDragBarUp( _event:MouseEvent ):void{
                            this.stopDrag();
                        }
                       
                        private function handleHotSpotMouseOver( _event:MouseEvent):void{
                            var btn:Button = _event.target as Button;
                            var cursorClass:Class;
                            clearCurrentCursor();
                            switch(btn){
                                case northWestBtn:
                                    cursorClass = CursorResizeNegative;
                                    break;
                                case northBtn:
                                    cursorClass = CursorResizeVertical;
                                    break;
                                case northEastBtn:
                                    cursorClass = CursorResizePositive;
                                    break;
                                case eastBtn:
                                    cursorClass = CursorResizeHorizontal;
                                    break;
                                case southEastBtn:
                                    cursorClass = CursorResizeNegative;
                                    break;
                                case southBtn:
                                    cursorClass = CursorResizeVertical;
                                    break;
                                case southWestBtn:
                                    cursorClass = CursorResizePositive;
                                    break;
                                case westBtn:
                                    cursorClass = CursorResizeHorizontal;
                                    break;
                            }
                            if(cursorClass)
                                iCursorID = CursorManager.setCursor(cursorClass);
                           
                        }
                       
                        private function handleHotSpotMouseOut( _event:MouseEvent):void{
                            clearCurrentCursor();
                        }
                       
                        public function clearCurrentCursor():void{
                            if(iCursorID)
                                CursorManager.removeCursor(iCursorID);
                        }
                       
                        private var origMouseX:Number;
                        private var origMouseY:Number;
                        private var origX:Number;
                        private var origY:Number;
                        private var origHeight:Number;
                        private var origWidth:Number;
                        private var currBorder:Button;
                       
                        private function handleBorderMouseDown( _event:MouseEvent):void{
                            currBorder = _event.target as Button;
                            FlexGlobals.topLevelApplication.addEventListener(MouseEvent.MOUSE_MOVE, handleBorderMouseMove);
                            FlexGlobals.topLevelApplication.addEventListener(MouseEvent.MOUSE_UP, handleBorderMouseUp);
                            origMouseX = mouseX;
                            origMouseY = mouseY;
                            origWidth = this.width;
                            origHeight = this.height;
                            origX = this.x;
                            origY = this.y;
                            origWidth = this.width;
                            origHeight = this.height;
                        }
                       
                        private function handleBorderMouseMove( _event:MouseEvent ):void{
                            var newX:Number = mouseX;
                            var newY:Number = mouseY;
                            var proposedHeight:Number = origHeight;
                            var proposedWidth:Number = origWidth;
                            var proposedX:Number = origX;
                            var proposedY:Number = origY;
                            switch(currBorder){
                                case northWestBtn:
                                    proposedX = origX + ( newX - origMouseX);
                                    proposedY = origY + ( newY - origMouseY);
                                    proposedHeight = origHeight + (( newY - origMouseY) * -1 );
                                    proposedWidth = origWidth + (( newX - origMouseX) * -1);
                                    break;
                                case northBtn:
                                    proposedY = origY + ( newY - origMouseY);
                                    proposedHeight = origHeight + (( newY - origMouseY) * -1 );
                                    break;
                                case northEastBtn:
                                    proposedY = origY + ( newY - origMouseY);
                                    proposedHeight = origHeight + (( newY - origMouseY) * -1 );
                                    proposedWidth = origWidth + ( newX - origMouseX) ;
                                    break;
                                case eastBtn:
                                    proposedWidth = origWidth +( newX - origMouseX);
                                    break;
                                case southEastBtn:
                                    proposedHeight = origHeight +( newY - origMouseY);
                                    proposedWidth = origWidth +( newX - origMouseX);
                                    break;
                                case southBtn:
                                    proposedHeight = origHeight +( newY - origMouseY);
                                    break;
                                case southWestBtn:
                                    proposedX = origX + ( newX - origMouseX);
                                    proposedHeight = origHeight + ( newY - origMouseY) ;
                                    proposedWidth = origWidth + (( newX - origMouseX) * -1);
                                    break;
                                case westBtn:
                                    proposedX = origX + ( newX - origMouseX);
                                    proposedWidth = origWidth + (( newX - origMouseX) * -1);
                                    break;
                            }
                           
                            if(proposedHeight >= this.minHeight){
                                this.y = proposedY;
                                this.height = proposedHeight;
                            }
                            if(proposedWidth >= this.minWidth){
                                this.width = proposedWidth;
                                this.x = proposedX;
                            }
                           
                        }
                       
                        private function handleBorderMouseUp( _event:MouseEvent ):void{
                            FlexGlobals.topLevelApplication.removeEventListener(MouseEvent.MOUSE_MOVE, handleBorderMouseMove);
                            FlexGlobals.topLevelApplication.removeEventListener(MouseEvent.MOUSE_UP, handleBorderMouseUp);
                        }
                       
                    ]]>
                </fx:Script>
                    <s:Group height="100%" width="100%" >
                        <s:BorderContainer id="topDragBar"            alpha="0"    top="{nBorderHeight}"    left="{nBorderWidth}"    height="{nDraggableBarHeight}"    width="{(this.width-(northWestHitArea.width + northEastHitArea.width))}"    backgroundColor="0x234561" buttonMode="true"/>
                        <s:BorderContainer id="northWestHitArea"    alpha="0"    top="0"                    left="0"                height="{nBorderHeight}"    width="{nBorderWidth}"    backgroundColor="0xFF0000"/>
                        <s:BorderContainer id="northHitArea"         alpha="0"    top="0"                    left="{nBorderWidth}"    height="{nBorderHeight}"    width="{(this.width-(northWestHitArea.width + northEastHitArea.width))}"    backgroundColor="0xFFFF00"/>
                        <s:BorderContainer id="northEastHitArea"    alpha="0"     top="0"                    right="0"                 height="{nBorderHeight}" width="{nBorderWidth}" backgroundColor="0xFFFFFF"/>
                        <s:BorderContainer id="eastHitArea"         alpha="0"    top="{nBorderHeight}"    right="0"                 height="{( this.height - (northEastHitArea.height + southEastHitArea.height))}" width="{nBorderWidth}" backgroundColor="0x0000FF"/>
                        <s:BorderContainer id="southEastHitArea"    alpha="0"     bottom="0"                right="0"                 height="{nBorderHeight}" width="{nBorderWidth}" backgroundColor="0x00FFFF"/>
                        <s:BorderContainer id="southHitArea"         alpha="0"    bottom="0"                left="{nBorderWidth}"    height="{nBorderHeight}"    width="{(this.width-(southEastHitArea.width + southWestHitArea.width))}" backgroundColor="0xFFFFFF"/>
                        <s:BorderContainer id="southWestHitArea"    alpha="0"     bottom="0"                left="0"                 height="{nBorderHeight}" width="{nBorderWidth}" backgroundColor="0xFF00FF"/>
                        <s:BorderContainer id="westHitArea"             alpha="0"    top="{nBorderHeight}"    left="0"                 height="{( this.height - (northWestHitArea.height + southWestHitArea.height))}" width="{nBorderWidth}" backgroundColor="0x00FF00"/>
                        <s:Button id="northWestBtn"     alpha="0" hitArea="{northWestHitArea}"/>
                        <s:Button id="northBtn"         alpha="0" hitArea="{northHitArea}"/>
                        <s:Button id="northEastBtn"     alpha="0" hitArea="{northEastHitArea}"/>
                        <s:Button id="eastBtn"             alpha="0" hitArea="{eastHitArea}"/>
                        <s:Button id="southEastBtn"     alpha="0" hitArea="{southEastHitArea}"/>
                        <s:Button id="southBtn"         alpha="0" hitArea="{southHitArea}"/>
                        <s:Button id="southWestBtn"     alpha="0" hitArea="{southWestHitArea}"/>
                        <s:Button id="westBtn"             alpha="0" hitArea="{westHitArea}"/>
                    </s:Group>

             

            </s:SkinnableContainer>

            • 3. Re: MXML Custom Compent Child Overriding it's Parent's Content Group?
              David_F57 Level 5

              hi,

               

              I'll have a look in the morning, well later in the morning (3am here), just for fun here is a sample of a resizable container component, just add some images into the listbox drag something into the main area then hover over it for the action markers.

               

               

              http://gumbo.flashhub.net/pagedrop/  source included (its really boggie at the moment never got around to 'perfecting' it).

               

              http://gumbo.flashhub.net/sizer/  resize from 1 corner.

               

               

              David.

              • 4. Re: MXML Custom Compent Child Overriding it's Parent's Content Group?
                boneitis Level 1

                I have seen other components similar to this along with creating my own, however I need to be able to grab any border / corner and drag it for resizing, very similarly to how windows in the Windows OS react to mouse overs on the borders.  Also, the upper left hand corner must have the capability for not being static during re-sizing.

                 

                However, this logic works fine, and I feel we are going off topic.  I could just create the following class:

                 

                 

                CLASSA

                <?xml version="1.0" encoding="utf-8"?>
                <s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                                           xmlns:s="library://ns.adobe.com/flex/spark"
                                           xmlns:mx="library://ns.adobe.com/flex/mx" 
                                           minHeight="200" minWidth="300"
                                           creationComplete="init()">
                     <fx:Script>
                          <![CDATA[
                               private function init():void{
                                    moveItem();
                               }
                              
                               public function moveItem():void{
                                    myLabel.x += 100;
                               }
                                        
                          ]]>
                     </fx:Script>
                    <s:Label text="Hello" id='myLabel'/>

                </s:SkinnableContainer>

                 

                And then create CLASSB to extend CLASSA, and just add 1 label, I still get the same error.

                <?xml version="1.0" encoding="utf-8"?>

                <components:CLASSA xmlns:fx="http://ns.adobe.com/mxml/2009"

                                                      xmlns:s="library://ns.adobe.com/flex/spark"

                                                      xmlns:mx="library://ns.adobe.com/flex/mx" >

                               <s:Label text=" world" />

                </components:CLASSA >

                 

                 

                This is the error that I am trying to resolve.  I appreciate you taking a look in the AM, Good night!

                • 5. Re: MXML Custom Compent Child Overriding it's Parent's Content Group?
                  Shongrunden Adobe Employee

                  Looks like you are trying to extend a custom component written in MXML.  You might want to read this post and the comments: http://www.tink.ws/blog/extending-your-own-mxml-components/