Unrealscript: how to add a weapon to the inventory only if your weapon's group is unique - unreal-development-kit

I have been trying to get a custom inventory script working in unrealscript. I need to check on weapon pickup if the weapon you are picking up has a weapon group that matches one you already have or not. If so it swaps the weapons of the given group. If not you gain the new weapon. Currently we have 4 weapon groups. What i have tried to no avail to find is how to find the weapon group of a weapon being picked up. and how to check that against the other weapons. I have been working with the add inventory function.
NewItem is the item you just interacted with. And i need to find the other weapons in your current inventory and their weapon groups.
simulated function bool AddInventory(Inventory NewItem, optional bool bDoNotActivate)
{
local Inventory Item, LastItem;
// The item should not have been destroyed if we get here.
if( (NewItem != None) && !NewItem.bDeleteMe )
{
// if we don't have an inventory list, start here
if( InventoryChain == None )
{
InventoryChain = newItem;
}
else
{
// Skip if already in the inventory.
for (Item = InventoryChain; Item != None; Item = Item.Inventory)
{
if( Item == NewItem )
{
return FALSE;
}
LastItem = Item;
}
LastItem.Inventory = NewItem;
}
//Edited by Matt Kerns
`LogInv("adding" # NewItem # "bDoNotActivate:" # bDoNotActivate);
`Log ("Added to inventory!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
NewItem.SetOwner( Instigator );
NewItem.Instigator = Instigator;
NewItem.InvManager = Self;
NewItem.GivenTo( Instigator, bDoNotActivate);
// Trigger inventory event
Instigator.TriggerEventClass(class'SeqEvent_GetInventory', NewItem);
return TRUE;
}
return FALSE;
}

If you want write all code in InventoryManager it will be look like
simulated function bool AddInventory(Inventory NewItem, optional bool bDoNotActivate){
local Inventory Item, LastItem;
// The item should not have been destroyed if we get here.
if( (NewItem != None) && !NewItem.bDeleteMe )
{
//if weapon - work in personal weapon function
if(Weapon(NewItem) != none)
return AddItemWeapon(NewItem, bDoNotActivate);
// if we don't have an inventory list, start here
if( InventoryChain == None )
{
InventoryChain = newItem;
}
else
{
// Skip if already in the inventory.
for (Item = InventoryChain; Item != None; Item = Item.Inventory)
{
if( Item == NewItem )
{
return FALSE;
}
LastItem = Item;
}
LastItem.Inventory = NewItem;
}
//Edited by Matt Kerns
`LogInv("adding" # NewItem # "bDoNotActivate:" # bDoNotActivate);
`Log ("Added to inventory!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
NewItem.SetOwner( Instigator );
NewItem.Instigator = Instigator;
NewItem.InvManager = Self;
NewItem.GivenTo( Instigator, bDoNotActivate);
// Trigger inventory event
Instigator.TriggerEventClass(class'SeqEvent_GetInventory', NewItem);
return TRUE;
}
return FALSE;
}
simulated function AddItemWeapon(Inventory NewItem, optional bool bDoNotActivate)
{
local Inventory Item, LastItem;
local Weapon WeaponNewItem;
WeaponNewItem= Weapon(NewItem);
// The item should not have been destroyed if we get here.
if( (NewItem != None) && !NewItem.bDeleteMe )
{
// if we don't have an inventory list, start here
if( InventoryChain == None )
{
InventoryChain = newItem;
}
else
{
//look for our group
for (Item = InventoryChain; Item != None; Item = Item.Inventory){
if(Weapon(Item) != none && Weapon(Item).Group == WeaponNewItem.Group){
RemoveFromInventory(Item);
break;
}
}
// Skip if already in the inventory.
for (Item = InventoryChain; Item != None; Item = Item.Inventory)
{
if( Item == NewItem )
{
return FALSE;
}
LastItem = Item;
}
LastItem.Inventory = NewItem;
}
//Edited by Matt Kerns
`LogInv("adding" # NewItem # "bDoNotActivate:" # bDoNotActivate);
`Log ("Added to inventory!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
NewItem.SetOwner( Instigator );
NewItem.Instigator = Instigator;
NewItem.InvManager = Self;
NewItem.GivenTo( Instigator, bDoNotActivate);
// Trigger inventory event
Instigator.TriggerEventClass(class'SeqEvent_GetInventory', NewItem);
return TRUE;
}
return FALSE;
}
This is best way if your game use network and replicate inventory. If not, you can simple write something like
simulated function AddItemWeapon(Inventory NewItem, optional bool bDoNotActivate){
local Inventory Item, LastItem;
local Weapon WeaponNewItem;
local bool bAddNewWeapon;
bAddNewWeapon = true;
WeaponNewItem = Weapon(NewItem);
// The item should not have been destroyed if we get here.
if( (NewItem != None) && !NewItem.bDeleteMe )
{
// if we don't have an inventory list, start here
if( InventoryChain == None )
{
InventoryChain = newItem;
}
else
{
//look for our group
for (Item = InventoryChain; Item != None; Item = Item.Inventory){
if(Weapon(Item) != none && Weapon(Item).Group == WeaponNewItem.Group){
NewItem.Inventory = Item.Inventory;
bAddNewWeapon = false;
RemoveFromInventory(Item);
break;
}
LastItem = Item;
}
if(bAddNewWeapon){
for (Item = InventoryChain; Item != None; Item = Item.Inventory){
LastItem = Item;
}
}
LastItem.Inventory = NewItem;
}
But im sure that this is bad way. You should write class which will save all used weapon groups and use InventoryManager only as storage

Related

Reusable search function javafx

I have a program that searches an observable list and displays all of the matching cases on the table. The search works fine, but I am only able to run this part of the program once. The search button stops responding after the program has returned to displaying the full observable list.
I have a separate class(Search.class) that handles all of the logic for searching the observable list.
The code for the search button and text field are below:
partSearchBtn.setOnAction(searchPartEvent ->{
ObservableList<Part> searchPartDisplay = FXCollections.observableArrayList();
String searchQuery = partSearchField.getText();
try{
searchPartDisplay = Search.searchPartByNumber(Integer.parseInt(searchQuery));
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
} catch(NumberFormatException hasText){
searchPartDisplay = Search.searchPartByText(searchQuery);
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
}
});
What changes would I need to make to re-run the search process?
Or should I turn this into a method as part of my Search class that I can reuse?
The search logic is below:
package inventorymngmnt;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Search {
public static ObservableList<Part> searchPartByNumber(int inNum){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchBin.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).contains(e.getName()))){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchPartByText(String inString){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchBin.add(e);
}
}
if(inString.equals(e.getName())){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchProdByNumber(int inNum){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchProd.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).equals(e.getName()))){
searchProd.add(e);
}
}
return searchProd;
}
public static ObservableList<Part> searchProdByText(String inString){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchProd.add(e);
}
}
if(inString.equals(e.getName())){
searchProd.add(e);
}
}
return searchProd;
}
}
It doesn't work, because when you clear the search, the action on the button is still set to clear the search...
Consider a different strategy entirely. You can use a FilteredList as the list for the table. Then just toggle the predicate on the list:
Predicate<Part> noFilter = part -> true;
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.partBin, noFilter);
partTable.setItems(filteredParts);
partSearchBtn.setOnAction(searchPartEvent -> {
if (filteredParts.getPredicate()==noFilter) {
String searchQuery = partSearchField.getText();
try {
int searchNumber = Integer.parseInt(searchQuery);
filteredParts.setPredicate(part -> Search.filterByNumber(part, searchNumber));
} catch (NumberFormatException exc) {
filteredParts.setPredicate(part -> Search.filterByText(part, searchQuery));
}
} else {
filteredParts.setPredicate(noFilter);
}
});
partSearchButton.textProperty().bind(Bindings
.when(filteredParts.predicateProperty().isEqualTo(noFilter))
.then("Search")
.otherwise("Clear"));
and
public class Search {
public static boolean filterByNumber(Part part, int number) {
if (part.getClass() == Inhouse.class) {
Inhouse testIn = (Inhouse) part ;
if (testIn.getMachineID() == number) {
return true ;
}
}
if((number == part.getPartID()) || (number == part.getInstock()) || (number == part.getMax())
|| ( number == part.getMin()) || ((double) number == part.getPrice())
|| (Integer.toString(number).contains(part.getName()))){
return true ;
}
return false ;
}
public static boolean filterByText(Part part, String text) {
//similarly...
}
}

Show ForbiddenCursor only when mouse is OnItem in QTreeWidget

I am trying to display the Qt::ForbiddenCursor when I move a mouse over an item in a custom QTreeWidget but only when drop position is QAbstractItemView::OnItem.
Here is the code
void XProjectTreeWidget::dragMoveEvent(QDragMoveEvent * event)
{
QTreeWidgetItem* pItem = itemAt(event->pos());
if (pItem == nullptr)
{
return;
}
XTreeItem* dropItem = dynamic_cast<XTreeItem*>(pItem);
if (dropItem == nullptr)
{
return;
}
XTreeItem::DropPosition drop;
if (!getDropPosition(drop))
{
return;
}
auto items = selectedItems();
if (items.count() == 0)
{
return;
}
auto dragItem = (XTreeItem*)items.first();
if (!dragItem->checkMoveItemPossible(dropItem, drop))
{
QGuiApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
event->setDropAction(Qt::IgnoreAction);
}
else
{
QGuiApplication::changeOverrideCursor(QCursor(Qt::ArrowCursor));
event->setDropAction(Qt::MoveAction);
}
QTreeWidget::dragMoveEvent(event);
}
bool XProjectTreeWidget::getDropPosition(XTreeItem::DropPosition& drop)
{
DropIndicatorPosition dropIndicator = dropIndicatorPosition();
switch (dropIndicator)
{
case QAbstractItemView::AboveItem: drop = XTreeItem::Above; break;
case QAbstractItemView::BelowItem: drop = XTreeItem::Below; break;
case QAbstractItemView::OnItem: drop = XTreeItem::Inside; break;
default: return false;
}
return true;
}
The problem is that the ignore action seems to be applied to all the items with the same type for AboveItem and BelowItem.
dragMoveEvent is called when the DropPosition is OnItem for the items with the same type while hovering the cursor above those items.
How can I show ForbiddenCursor only when mouse is OnItem?
Calling QTreeWidget::dragMoveEvent(event); before changing the cursors fixed the issue. Here is how the fixed code looks now:
void XProjectTreeWidget::dragMoveEvent(QDragMoveEvent * event)
{
// moved this call from the end of the method
QTreeWidget::dragMoveEvent(event);
QTreeWidgetItem* pItem = itemAt(event->pos());
if (pItem == nullptr)
{
return;
}
XTreeItem* dropItem = dynamic_cast<XTreeItem*>(pItem);
if (dropItem == nullptr)
{
return;
}
XTreeItem::DropPosition drop;
if (!getDropPosition(drop))
{
return;
}
auto items = selectedItems();
if (items.count() == 0)
{
return;
}
auto dragItem = (XTreeItem*)items.first();
if (!dragItem->checkMoveItemPossible(dropItem, drop))
{
QGuiApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
event->setDropAction(Qt::IgnoreAction);
}
else
{
QGuiApplication::changeOverrideCursor(QCursor(Qt::ArrowCursor));
event->setDropAction(Qt::MoveAction);
}
}

child nodes in treeview control automatically checked when parent node checked

I'm using TreeView control. Binding values from database with check box.
Nearly three children are there for parent node like
Parent1
child1
child2
child3
Parent2
child1
child2
child3
I can able to bind data which is from 3 tables all are working well. I want a facility when a parent node checks all its corresponding child automatically get checked.If I click on parent 1 ,child 123 get checked. If I check child1, child2 and child3 get checked. If I check child 2 all child 3 items get checked. How to do that?
Thanks in Advance
Amrutha
The javascript function below can be used to check all child nodes if the parent is checked and check parent node if at least one child node is checked otherwise it is unchecked:
function OnTreeClick(evt) {
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "checkbox");
var t = GetParentByTagName("table", src);
if (isChkBoxClick) {
var parentTable = GetParentByTagName("table", src);
var nxtSibling = parentTable.nextSibling;
if (nxtSibling && nxtSibling.nodeType == 1) {
if (nxtSibling.tagName.toLowerCase() == "div") {
CheckUncheckChildren(parentTable.nextSibling, src.checked);
}
}
CheckUncheckParents(src, src.checked);
}
}
function CheckUncheckChildren(childContainer, check) {
var childChkBoxes = childContainer.getElementsByTagName("input");
var childChkBoxCount = childChkBoxes.length;
for (var i = 0; i < childChkBoxCount; i++) {
childChkBoxes[i].checked = check;
}
}
function CheckUncheckParents(srcChild, check) {
var parentDiv = GetParentByTagName("div", srcChild);
var parentNodeTable = parentDiv.previousSibling;
if (parentNodeTable) {
var checkUncheckSwitch;
var isAllSiblingsChecked = AreAllSiblingsChecked(srcChild);
if (isAllSiblingsChecked) {
checkUncheckSwitch = true;
}
else {
checkUncheckSwitch = false;
}
var inpElemsInParentTable = parentNodeTable.getElementsByTagName("input");
if (inpElemsInParentTable.length > 0) {
var parentNodeChkBox = inpElemsInParentTable[0];
parentNodeChkBox.checked = checkUncheckSwitch;
CheckUncheckParents(parentNodeChkBox, checkUncheckSwitch);
}
}
}
function AreAllSiblingsChecked(chkBox) {
var parentDiv = GetParentByTagName("div", chkBox);
var childCount = parentDiv.childNodes.length;
var k = 0;
for (var i = 0; i < childCount; i++) {
if (parentDiv.childNodes[i].nodeType == 1) {
if (parentDiv.childNodes[i].tagName.toLowerCase() == "table") {
var prevChkBox = parentDiv.childNodes[i].getElementsByTagName("input")[0];
//if any of sibling nodes are not checked, return false
if (prevChkBox.checked) {
//add each selected node one value
k = k + 1;
}
}
}
}
//Finally check any one of child node is select if selected yes then return ture parent node check
if (k > 0) {
return true;
}
else {
return false;
}
}
function GetParentByTagName(parentTagName, childElementObj) {
var parent = childElementObj.parentNode;
while (parent.tagName.toLowerCase() != parentTagName.toLowerCase()) {
parent = parent.parentNode;
}
return parent;
}
I used this javascript to solve my problem.
A simple recursive function could do that.
private bool checkTreeNodes(TreeNodeCollection nodes, bool parentChecked)
{
var isChecked = parentChecked;
foreach (TreeNode node in nodes)
{
if (node.Checked || parentChecked)
{
checkTreeNodes(node.Nodes, true);
node.Checked = true;
isChecked = true;
}
else
{
node.Checked = checkTreeNodes(node.Nodes, false);
isChecked = isChecked || node.Checked;
}
}
return isChecked;
}
use it like:
checkTreeNodes(myTree.Nodes, false);

Drupal - Block visibility

I am using the below code in the block visibilty settings, to only show the block if the user is a member, and not the admin.
What can I add to further filter it down to type of Organic Group Node.
i.o.w Only display if the currnt group being viewed = Organic Group Node Type X
<?php
$in_og = FALSE;
if (module_exists('og')){
$in_og = FALSE;
$group_node = og_get_group_context();
$gid02 = $group_node->nid;
$gid = (int)$gid02;
if ($gid02 == null) $gid = 0;
if (og_is_group_member($group_node)) $in_og = TRUE;
if (og_is_group_admin($group_node)) $in_og = FALSE;
if ($gid == 0) $in_og = FALSE;
}
return $in_og;
thanks
Maybe something like"
<?php
$in_og = FALSE;
$right_group = FALSE;
if (module_exists('og')) {
// get OG $group_node
$group_node = og_get_group_context();
if ($group_node->type == 'type-x') {
// we have the correct group type
$right_group = TRUE;
}
$gid = $group_node->nid;
if (og_is_group_member($group_node)) {
// show to members
$in_og = TRUE;
}
if (og_is_group_admin($group_node)) {
// hide from admins
$in_og = FALSE;
}
}
return $in_og && $right_group;
?>

Is it possible to make an item in a Flex List control not selectable?

Is it possible to make an item in a List control not selectable? If so, how would this be accomplished?
I've tried one thing so far. What I did was use a custom item renderer that checks for a value in the data property upon a FlexEvent.DATA_CHANGE event. If that value is not set, I tried setting the item renderer's selectable property to false. This, unfortunately, does not seem to work.
Any ideas?
So I came upon a solution of my own. Its similar to yours, and seems to do the trick and cover all the bases apart from hacking the page up and page down keys. I say hack, because I'm not sure it handles the increase or decrease in the caretIndex the same way as the List control. Basically it just manually sets the caretIndex to an index before what the next selectable item is and changes the keycode to a simple up or down.
protected function disabledFilterFunction( data:Object ):Boolean
{
return ( data != null && data.data == null );
}
override protected function mouseEventToItemRenderer( event:MouseEvent ):IListItemRenderer
{
var item:IListItemRenderer = super.mouseEventToItemRenderer( event );
if( item && item.data && disabledFilterFunction( item.data ) )
return null;
return item;
}
override protected function moveSelectionVertically( code:uint, shiftKey:Boolean, ctrlKey:Boolean ):void
{
var i:int;
var newIndex:int;
switch( code )
{
case Keyboard.UP:
newIndex = getPreviousUnselectableIndex( caretIndex - 1 );
break;
case Keyboard.DOWN:
newIndex = getNextUnselectableIndex( caretIndex + 1 );
break;
case Keyboard.HOME:
newIndex = getFirstSelectableIndex();
code = Keyboard.UP;
break;
case Keyboard.END:
newIndex = getLastSelectableIndex();
code = Keyboard.DOWN;
break;
case Keyboard.PAGE_UP:
{
newIndex = Math.max( getFirstSelectableIndex(), getPreviousUnselectableIndex( caretIndex - ( rowCount - 2 ) ) );
code = Keyboard.UP;
break;
}
case Keyboard.PAGE_DOWN:
{
newIndex = Math.min( getLastSelectableIndex(), getNextUnselectableIndex( caretIndex + ( rowCount - 1 ) ) );
code = Keyboard.DOWN;
break;
}
}
if( newIndex > -1 && newIndex < collection.length )
{
caretIndex = newIndex;
super.moveSelectionVertically( code, shiftKey, ctrlKey );
}
}
private function getFirstSelectableIndex():int
{
var result:int = -1;
for( var i:int = 0; i < collection.length; i++ )
{
if( !disabledFilterFunction( collection[i] ) )
{
result = i + 1;
break;
}
}
return result;
}
private function getLastSelectableIndex():int
{
var result:int = -1;
for( var i:int = collection.length - 1; i > -1; i-- )
{
if( !disabledFilterFunction( collection[i] ) )
{
result = i - 1;
break;
}
}
return result;
}
private function getPreviousUnselectableIndex( startIndex:int ):int
{
var result:int = -1;
for( var i:int = startIndex; i > -1; i-- )
{
if( !disabledFilterFunction( collection[i] ) )
{
result = i + 1;
break;
}
}
return result;
}
private function getNextUnselectableIndex( startIndex:int ):int
{
var result:int = collection.length;
for( var i:int = startIndex; i < collection.length; i++ )
{
if( !disabledFilterFunction( collection[i] ) )
{
result = i - 1;
break;
}
}
return result;
}
I was able to fix the problem of first/last items being non-selectable by simply doing this verticalScrollPosition++ and verticalScrollPosition-- right before caretIndex++ and caretIndex-- respectively (in the example that Michael linked to up above) . I couldn't believe that the fix was so easy, but it was!
I was able to do this to add a separator component, following this ComboBox example. Here's an example with the renderer logic stripped out and the selectability logic left in:
package com.example.ui {
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import mx.controls.List;
import mx.controls.listClasses.IListItemRenderer;
public class MyList extends List
{
public function MyList()
{
super();
}
/** Override mouse navigation */
protected override function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer {
var row:IListItemRenderer = super.mouseEventToItemRenderer(event);
if (row != null && isSelectable(row.data)) {
return null;
}
return row;
}
/** Override keyboard navigation */
protected override function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void {
super.moveSelectionVertically(code, shiftKey, ctrlKey);
if (code == Keyboard.DOWN && isSeparatorData(selectedItem)) {
caretIndex++;
}
if (code == Keyboard.UP && isSeparatorData(selectedItem)) {
caretIndex--;
}
finishKeySelection();
}
/**
* Define this mechanism in a way that makes sense for your project.
*/
protected function isSelectable(data:Object):Boolean {
return data != null && data.hasOwnProperty("type") && data.type == "separator";
}
}
}
An alternative (still imperfect) that deals better with scrollable lists and consecutive separators:
protected override function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void {
super.moveSelectionVertically(code, shiftKey, ctrlKey);
var newCode:uint = singleLineCode(code);
var item:Object = selectedItem;
var itemChanged:Boolean = true;
while (!isNaN(newCode) && itemChanged && isSeparatorData(item)) {
super.moveSelectionVertically(newCode, shiftKey, ctrlKey);
itemChanged = (item === selectedItem);
item = selectedItem;
}
}
private function singleLineCode(code:uint):uint {
switch (code) {
case Keyboard.UP:
case Keyboard.PAGE_UP:
return Keyboard.UP;
break;
case Keyboard.DOWN:
case Keyboard.PAGE_DOWN:
return Keyboard.DOWN;
break;
default:
return NaN;
break;
}
return code;
}
Just thought I'd add my two sense. I was wondering the same thing (how to I set a list to not selectable) and I realized that the spark component datagroup would do exactly that. of course you need to be using flex 4, but if you are, and are wondering can I set my list to not selectable, I'd suggest using the datagroup.
I was looking for a solution myself and here's the solution I came up with. Note that I'm using a spark list. I hope someone finds this helpful.
Implement both event handlers for change and changing
Set the selection to -1 and requireSelection to false so that nothing is selected
When you build your dataprovider, enable/disable items as desired
Provide some logic in the changing handler to call 'preventDefault' on the event if it isn't enabled, or shouldn't be selected.
Example: cribbed from my implementation where I build my own items and use a Tile Layout
<s:List id="myListView"
itemRenderer="spark.skins.spark.DefaultComplexItemRenderer"
horizontalCenter="0"
verticalCenter="0"
borderVisible="false"
dataProvider="{myItems}"
change="changeHandler(event)" changing="changingHandler(event)"
requireSelection="false"
selectedIndex="-1" >
<s:layout>
<s:TileLayout verticalGap="0" />
</s:layout>
</s:List>
<fx:script>
<![CDATA[
import mx.collections.ArrayCollection;
import spark.events.IndexChangeEvent;
[Bindable]
public var myItems = new ArrayCollection;
protected function startup():void {
// Here's where you'd build up your items if they
// need to be built dynamically.
}
protected function changeHandler(event:IndexChangeEvent):void
{
var currentIndx:int = event.currentTarget.selectedIndex;
var selectedItem:UIComponent = event.currentTarget.selectedItem as UIComponent;
// Do whatever you need to do on selection here
}
protected function canMicrophoneChange(event:IndexChangeEvent):void
{
var currentIndx:int = event.currentTarget.selectedIndex;
var selectedItem:UIComponent = event.currentTarget.selectedItem as UIComponent;
// This will cancel the select if the item was not enabled.
if (selectedItem.enabled == false) event.preventDefault();
}
]]>
</fx:script>

Resources