Custom list adaptor

Rotorz ReorderableList

Custom list adaptor

This example demonstrates how to implement a custom list adaptor which can contain caption items which cannot be dragged or removed. List items can however be dragged around the stationary caption items.

custom-list-adaptor

Since in this example we are working with a straightforward list of strings it makes sense to subclass GenericListAdaptorT.

A simple naming convention will be assumed to differentiate between regular entries and captions. String entries which are enclosed between curly brackets will be presented differently and cannot be reordered or removed using the list control interface. A simple function can be created to test whether a list entry is a caption like IsCaption below.

using Rotorz.ReorderableList;
using System.Collections.Generic;
using UnityEditor;

public class SpecialAdaptor : GenericListAdaptor<string> {

    public SpecialAdaptor(List<string> list, ReorderableListControl.ItemDrawer<string> itemDrawer, float itemHeight)
        : base(list, itemDrawer, itemHeight) {
    }

    public override void DrawItem(Rect position, int index) {
        string item = this[index];
        if (IsCaption(item))
            GUI.Label(position, item.Substring(1, item.Length - 2));
        else
            base.DrawItem(position, index);
    }

    public override bool CanDrag(int index) {
        return !IsCaption(this[index]);
    }
    public override bool CanRemove(int index) {
        return !IsCaption(this[index]);
    }

    public override float GetItemHeight(int index) {
        return IsCaption(this[index]) ? 28 : fixedItemHeight;
    }

    private bool IsCaption(string item) {
        return item != null && item.Length > 0
            && item[0] == '{' && item[item.Length - 1] == '}';
    }

}
#pragma strict
import Rotorz.ReorderableList;
import System.Collections.Generic;

class SpecialAdaptor extends GenericListAdaptor.<String> {

    function SpecialAdaptor(list:List.<String>, itemDrawer:ReorderableListControl.ItemDrawer.<String>, itemHeight:float) {
        super(list, itemDrawer, itemHeight);
    }

    function CanDrag(index:int):boolean {
        return !IsCaption(this[index]);
    }

    function CanRemove(index:int):boolean {
        return !IsCaption(this[index]);
    }

    function DrawItem(position:Rect, index:int) {
        var item:String = this[index];
        if (IsCaption(item))
            GUI.Label(position, item.Substring(1, item.Length - 2));
        else
            super.DrawItem(position, index);
    }

    function GetItemHeight(index:int):float {
        return IsCaption(this[index]) ? 28 : fixedItemHeight;
    }

    function IsCaption(item:String):boolean {
        return item != null && item.Length > 0
            && item[0] == '{' && item[item.Length - 1] == '}';
    }

}

Our custom adaptor must then be instantiated before it can be used; this instance can be cached if desired. The adaptor instance can then be passed to ReorderableListGUIListField or even a custom list control using ReorderableListControlDraw.

var adaptor = new SpecialAdaptor(list, itemDrawer, 22);
ReorderableListGUI.ListField(adaptor);
var adaptor = new SpecialAdaptor(list, itemDrawer, 22);
ReorderableListGUI.ListField(adaptor);