SysTableBrowser instant field navigator


Without any doubt AX SysTableBrowser is very useful tool which helps to watch on content of exploring table. Unfortunately as for me there is one essential fault. When table contains large number of fields using SysTableBrowser sometimes it's hard to find out
a. which column corresponds to particular field; and
b. using horizontal scroll bar it's difficult to "catch up" needed field. 
I must confess that using of scroll bar is inconvenient very match in case when table has a dozen and more fields.
Figure 1 demonstrates lack of information of column's headers (checkbox fields).
Figure 2 illustrates disambiguation between fields RemainSalesPhysical and RemainSalesFinancial (SalesLine Table).
The simpliest way to reach needed field is Tab button. Pressing Tab user may find needed field at the end. But if there is necessity to find another one field user has to repeat Tab-pressing another one time. And another one time. And another one time...
Take a look at Axapta Object Tree (AOT) especially at \Data Dictionary\Tables\Table\Fields node. It's easy to watch on full range of fields and move from one field to another, isn't it?
Let's combine SysTableBrowser and Table\Fields node into one window.
SysTableBrowser tool this is a conjunction of SysTableBrowser Class and SysTableBrowser Form. I decided not to touch SysTableBrowser Class and following modification this is a modification of SysTableBrowser Form only.
1. Open SysTableBrowser Form Design and add FormTreeControl TreeControl like this:
Set Left Property to Right edge.
Set Height Property to Column height.
2. We need to create new fillTree() method:
// GRR fields navigator -->
void fillTree()
{
    int _i;


    FormDesign              Ctrl = element.design();
    FormControl             _buildCtrl;

    FormControl             _formControl;
    TreeItemIdx             treeItemIdx;

    ImageListAppl_Aot       ImageListAppl_Aot;
    FormTreeItem            item;

    DictField                       dictField;

    fieldId                         fieldId;
    int                             i,j;

    int                             fieldCnt;
    #DictField
    #resAppl

    ImageRes findOverlayImage(Types _type)
    {

        ImageRes imageRes;
        switch(_type)
        {
            case Types::STRING, Types::VARSTRING :
                return #ImageOverlayString;

            case Types::ENUM:
                return #ImageOverlayEnum;

            case Types::REAL:
                return #ImageOverlayReal;

            case Types::DATE:
                return #ImageOverlayDate;

            case Types::INTEGER:
                return #ImageOverlayInteger;

            case Types::DATETIME:
                return #ImageOverlayTime;

            case Types::CONTAINER:
                return #ImageOverlayContainer;

            default:
                return 0;
        }
        return imageRes;
    }
    ;

    // Find 'Grid' object -->
    for(_i=1; _i<=Ctrl.controlCount(); _i++)
    {
        _buildCtrl = Ctrl.controlNum(_i);
        _formControl = element.control(_buildCtrl.id());


        if(_formControl.name() == 'Grid')
        {
            _formGridControl = _formControl;
        }
    }
    // Find 'Grid' object <--

    // Fill tree -->
    if((FormTreeControl.visible())&&(dictTable))
    {
        ImageListAppl_Aot = new ImageListAppl_Aot();
        formTreeControl.setImagelist(ImageListAppl_Aot.imageList());
        formTreeControl.deleteAll();
        fieldCnt = dictTable.fieldCnt();

        for (i=1; i<=fieldCnt; i++)
        {
            fieldId = dictTable.fieldCnt2Id(i);
            dictField = new DictField(dictTable.id(), fieldId);
            if (bitTest(dictField.flags(), #DBF_STORE))
            {
                for(j = 1;j <= dictField.arraySize(); j++)
                {
                    treeItemIdx = SysFormTreeControl::addTreeItem(formTreeControl, dictField.name(), 0, null, imageListAppl_Aot.image(#ImageField));
                    SysFormTreeControl::setOverlayImage(formTreeControl, treeItemIdx, imageListAppl_Aot.image(findOverlayImage(dictField.baseType())));

                    itemIdxContainer += treeItemIdx;
                }
            }
        }
        SysFormTreeControl::expandTree(formTreeControl, formTreeControl.getRoot(), 1);
        // Do predefined design width more wider
        element.design().width( element.design().widthValue()+FormTreeControl.widthValue() );
        if(_formGridControl)
            _formGridControl.topMode(FormTop::TopEdge);
    }
    // Fill tree <--
}
3. In run() method we'll run fillTree() method:
void run()
{
    super();

    dictTable = new DictTable(tableId);

    this.parmSQLStmt('SELECT * FROM '+tableId2name(tableId));

    // GRR fields navigator -->
    this.fillTree();
    // GRR fields navigator <--
}
4. In ClassDeclaration we need declare two variables itemIdxContainer and _formGridControl:
class FormRun extends ObjectRun
{
    TableId tableId;
    source sqlcmd;
    DictTable dictTable;

    // GRR fields navigator -->
    Container               itemIdxContainer;
    FormGridControl         _formGridControl;
    // GRR fields navigator <--
}
5. Override mouseDblClick() method of FormTreeControl TreeControl. Now by mouse double click we may move from one field to another:
// GRR fields navigator -->
public int mouseDblClick(int _x, int _y, int _button, boolean _Ctrl, boolean _Shift)
{
    TreeItemIdx             itemIdx;
    int ret;
    ;

    ret = super(_x, _y, _button, _Ctrl, _Shift);

    [itemIdx] = this.hitTest(_x, _y);


    if((_formGridControl)&&(itemIdx))
    {
        _formGridControl.controlNum( conFind(itemIdxContainer, itemIdx ) ).setFocus();
    }

    return ret;
}
Now we may enjoy our extra functionality.If we want to hide this functionality just set FormTreeControl Visible Property to No.
I'd like to notice that navigating tree would be very useful for another tool QueryBrowser which usually deals with huge number of fields.
Who interested in another modificated SysTableBrowser take a look at Kashperuk's DEV SysTableBrowser

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.