Search code examples
actionscript-3headercontextmenuadvanceddatagrid

Flex: Disable ContextMenu customItems on AdvancedDataGrid headers


How can I disable or hide ContextMenu customItems when a user right-clicks on a header? I tried to set customItems to an empty array:

class MyAdvancedDataGridHeaderRenderer
     extends AdvancedDataGridHeaderRenderer {
  protected function onComplete(event:FlexEvent) {
    contextMenu.customItems = [];
  }
}

...but the contextMenu for the header is null.


Solution

  • Figured it out. I just disabled the predetermined menu items when the header is moused-over. The ContextMenuItems are disabled if their caption exists in the hiddenContextItems Array.

    I have provided an example that uses my ExtendedAdvancedDataGridHeaderRenderer object that I created in case anyone is interested.

    The example below generates a chart with three columns: Red, Green, and Blue. The first row is the highest contrast for that color and every row after that contrast level is decreased. This produces a gradient effect on the grid. You can copy the hex value of the color to your clipboard by right-clicking on the cell.

    ExtendedAdvancedDataGridHeaderRenderer.as

    package components {
      import flash.events.MouseEvent;
      import flash.ui.ContextMenuItem;
    
      import mx.controls.AdvancedDataGrid;
      import mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderRenderer;
    
      public class ExtendedAdvancedDataGridHeaderRenderer extends AdvancedDataGridHeaderRenderer {
    
        private var _hiddenContextMenuItems:Array; // of String
    
        public function get hiddenContextMenuItems():Array {
          return _hiddenContextMenuItems;
        }
    
        public function set hiddenContextMenuItems(value:Array):void {
          _hiddenContextMenuItems = value;
        }
    
        public function ExtendedAdvancedDataGridHeaderRenderer() {
          super();
          hiddenContextMenuItems = [ExtendedAdvancedDataGrid.MENU_COPY];
          this.addEventListener(MouseEvent.MOUSE_OVER, onRollOver);
          this.addEventListener(MouseEvent.MOUSE_OUT, onRollOut);
        }
    
        protected function onRollOver(event:MouseEvent):void {
          disableMenuItems(hiddenContextMenuItems);
        }
    
        protected function onRollOut(event:MouseEvent):void {
          disableMenuItems([]);
        }
    
        private function disableMenuItems(arr:Array):void {
          if (arr != null && this.owner is AdvancedDataGrid) {
            var adg:AdvancedDataGrid = this.owner as AdvancedDataGrid;
            if (adg.contextMenu != null && adg.contextMenu.customItems != null) {
              for each (var item:ContextMenuItem in adg.contextMenu.customItems) {
                item.enabled = !arrContainsStr(arr, item.caption);
              }
            }
          }
        }
    
        private function arrContainsStr(arr:Array, str:String):Boolean {
          for each (var arrStr:String in arr)
            if (arrStr == str)
              return true;
          return false;
        }
      }
    }
    

    ExtendedAdvancedDataGridItemRenderer.as

    package components {
      import mx.controls.advancedDataGridClasses.AdvancedDataGridItemRenderer;
    
      public class ExtendedAdvancedDataGridItemRenderer
          extends AdvancedDataGridItemRenderer {
        public function ExtendedAdvancedDataGridItemRenderer() {
          super();
        }
    
        override public function set data(value:Object):void {
          super.data = value;
          this.background = true;
          var bgColor:uint = parseInt(listData.label, 16);
          var fgColor:uint = bgColor ^ 0xFFFFFF;
          this.backgroundColor = bgColor;
          this.setStyle('color', fgColor);
          this.setStyle('textRollOverColor', 0xFFFFFF);
        }
      }
    }
    

    ExtendedAdvancedDataGridColumn.as

    package components {
      import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
      import mx.core.ClassFactory;
    
      public class ExtendedAdvancedDataGridColumn extends AdvancedDataGridColumn {
        public function ExtendedAdvancedDataGridColumn(columnName:String=null) {
          super(columnName);
          headerRenderer = new ClassFactory(ExtendedAdvancedDataGridHeaderRenderer);
          itemRenderer = new ClassFactory(ExtendedAdvancedDataGridItemRenderer);
        }
      }
    }
    

    ExtendedAdvancedDataGrid.as

    package components {
      import flash.display.Sprite;
      import flash.events.ContextMenuEvent;
      import flash.system.System;
      import flash.ui.ContextMenu;
      import flash.ui.ContextMenuItem;
    
      import mx.controls.AdvancedDataGrid;
      import mx.controls.advancedDataGridClasses.AdvancedDataGridItemRenderer;
      import mx.events.FlexEvent;
      import mx.utils.StringUtil;
    
      public class ExtendedAdvancedDataGrid extends AdvancedDataGrid {
    
        public static const MENU_COPY:String = 'Copy Hex Value';
    
        public function ExtendedAdvancedDataGrid() {
          super();
          this.addEventListener(FlexEvent.INITIALIZE, onInitialize);
        }
    
        protected function onInitialize(event:FlexEvent):void {
          contextMenu = new ContextMenu();
          contextMenu.hideBuiltInItems();
          var item:ContextMenuItem = new ContextMenuItem(MENU_COPY);
          item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, copyCellContents);
          contextMenu.customItems.push(item);
        }
    
        protected function copyCellContents(event:ContextMenuEvent):void {
          if (event.mouseTarget is AdvancedDataGridItemRenderer) {
            var text:String = (event.mouseTarget as AdvancedDataGridItemRenderer).text;
            System.setClipboard(StringUtil.substitute('#{0}', text));
          }
        }
      }
    }
    

    App.mxml

    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   minWidth="955" minHeight="600"
                   xmlns:components="components.*"
                   initialize="onInitialize(event)">
      <fx:Script>
        <![CDATA[
          import mx.collections.ArrayCollection;
          import mx.events.FlexEvent;
          import mx.utils.StringUtil;
    
          [Bindable] protected var gridData:ArrayCollection;
    
          protected function onInitialize(event:FlexEvent):void {
            gridData = new ArrayCollection();
            for (var i:uint = 15; i >= 0; i--) {
              var hexVal:String = intVal.toString(i)
              var red:String = StringUtil.substitute('{0}{0}0000', hexVal); 
              var green:String = StringUtil.substitute('00{0}{0}00', hexVal); 
              var blue:String = StringUtil.substitute('0000{0}{0}', hexVal); 
              gridData.addItem({'red': red, 'green': green, 'blue': blue});
            }
            grid.invalidateDisplayList();
          }
        ]]>
      </fx:Script>
      <s:BorderContainer horizontalCenter="0">
        <components:ExtendedAdvancedDataGrid id="grid" dataProvider="{gridData}"
          rowCount="{gridData.length + 1}">
        <components:columns>
          <components:ExtendedAdvancedDataGridColumn dataField="red" headerText="Red"/>
          <components:ExtendedAdvancedDataGridColumn dataField="green" headerText="Green"/>
          <components:ExtendedAdvancedDataGridColumn dataField="blue" headerText="Blue"/>
        </components:columns>
      </components:ExtendedAdvancedDataGrid>
      </s:BorderContainer>
    </s:Application>