Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages | Examples

Spider


Detailed Description

Introduction

The spider is a simple but powerful concept for generating complex user interfaces. It allows you to create complex flow of menu structures, where the menu items can be from PROGMEM, RAM, EEPROM and Memory Card.

spider.png

Spider menu structure is described by directed graph

The flow of menus is described by directed graph with possible cycles (i.e. it does not have to be tree). The graph consists of NODES and EDGES.

Node is described by:

Edge is described by:

The graph can be either static or dynamic.

Static graph means the structure that is described once forever, in case of dynamic graph it is possible to set up edges when spider enters the node, see Graph modification - dynamic graph.

Node structures

There are two structures describing nodes:

The main difference is the type of SNodeP::text and SNode::text. In case of SNodeP it points to localized string array while in case of SNode to pointer on simple string.

Note:
For Memory Card type node see Memory Card Node
Convenience pointer
Both structures have the p data field. We call it convenience pointer and it can be used to assocciate some data to the node. During the design it simply turned out to be convenient to have such possibility. It may simplify your code.

Edge structures

There are two structures desctibing edges:

The SEdgeP edges are used as a NULL terminated array.

Example of the graph on the top picture:

SEdgeP foo_edges[] = {
  {&node_1, &node_2},
  {&node_1, &node_3},
  {&node_2, &node_4},
  {&node_3, &node_4},
  {&node_3, &node_5},
  {&node_3, &node_6},
  NULL
};

void foo()
{
...
ctx->eP = &foo_edges;
ctx->n = &node_1;
...
}

The SEdge edges are used as a NULL terminated list.

Example of the graph on the top picture:

SEdge e_6 = {NULL, MEM_F_E|MEM_T_E, &node_3, &node_6};
SEdge e_5 = {&e_6, MEM_F_E|MEM_T_E, &node_3, &node_5};
SEdge e_4 = {&e_5, MEM_F_E|MEM_T_E, &node_3, &node_4};
SEdge e_3 = {&e_4, MEM_F_E|MEM_T_E, &node_2, &node_4};
SEdge e_2 = {&e_3, MEM_F_E|MEM_T_E, &node_1, &node_3};
SEdge e_1 = {&e_2, MEM_F_E|MEM_T_E, &node_1, &node_2};

In the case of RAM or EEPROM stored edges it is necessary to indicate the memory in which the FROM and TO nodes are stored (both are in EEPROM in this example). This indicator is necessary because nodes can be from RAM, EEPROM, PROGMEM or Memory Card - in case on SEdgeP both can be from PROGMEM only.

Note:
For Memory Card type edge see api_spider_mem_d

Context

Every spider function uses context - structure SCtx. This structure contains cuurent state of spider, path of previous nodes, pointer on current node. This structure is used to setup:

Context is created by spider_init() and destroyed by spider().

Example:

SNodeP foo_node = { lc_Node, NULL };
SNodeP foo_node_something = { lc_Somehing, foo_something };

SEdgeP foo_edges[] = {
  {&foo_node, &foo_node_somehing}, 
  NULL
};

void foo()
{
SCtx *c;
c = spider_init ();
c->eP = &foo_edges;
c->n = &foo_node;
spider(c);
}

Note:
If SCtx::n is not set then Memory Card initial node is assumed (i.e. SCtx::eD is used).

Menu items order

The order of edges is set by spider_set_order(). It has four paramters o1, o2, o3, o4 to be set to MEM_P, MEM_R, MEM_E, MEM_D. The order says which edges will be used in what order.

Example:

spider_set_order(ctx, MEM_P, MEM_R, MEM_E, MEM_D);
will display PROGMEM edges first, then RAM, EEPROM edges and Memory Card in the last.

Callback

Callback is used to:

Structure of callback:

u8 foo (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
        // return APP_OK or APP_END or APP_BACK
  }
  else 
  if (action == APP_LEAVE)
  {
  }
  return APP_OK;
}

In case of APP_ENTER the callback can return three possible values:

Memory Card Node

In case of memory card the node is inode, i.e. the name of the inode is used as the item text. Because there is no callback defined per se for memory card type of node, it is neccessary to set it up with SCtx::df_fnc. The start memory card of node is set up by SCtx::eD - inode pointer.

Example:

SCtx *c;
c = spider_init ();
c->df_fnc = foo;        // memory card node callback 
c->eD = root();         // initial memory card node
spider(c);

In this case the menu items will be list of files and directories in the "/" directory. In case user selects an item the foo() callback will be called.

Note:
If SCtx::n is not then Memory Card initial node is assumed (i.e. SCtx::eD is used).
For Memory Card browsing it is possible to use different style - way how are the files and directories displayed as menu items:

Dummy node - menu of Memory Card only nodes

There is a design constraint that node is displayed (its edges as menu items) only in the case there is at least one RAM, EEPROM or PROGMEM child node. In case you want to display only Memory Card nodes use the dummy node trick, i.e. define:
SNodeP dummy_node = { NULL, NULL };

u8 foo (SCtx * ctx, u8 action) // ctx->df_fnc - Memory Card node callback
{
  if (action == APP_ENTER)
  {
      spider_append_r (ctx, &dummy_node);
  }
  else 
  if (action == APP_LEAVE)
  {
    spider_clear_r (ctx);
  }
  return APP_OK;
}

So the previous example should be:

SNodeP dummy_node = { NULL, NULL };

SEdgeP dummy_edge[] = {
  {&dummy_node, &dummy_node}, 
  NULL
};

SCtx *c;
c = spider_init ();
c->eP = &dummy_edge;
c->df_fnc = foo;        // memory card node callback 
c->eD = root();         // initial memory card node
spider(c);

Graph modification - dynamic graph

It is possible to append edges to the current node with the help of spider_append_r() - appends RAM edge. Such appened edges have to be deleted with spider_clear_r() in the APP_LEAVE portion of callback.

Example:

SNodeP node_yes;
SNodeP node_no;

u8 foo (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    if(yes)
      spider_append_r (ctx, &node_yes);
    else
      spider_append_r (ctx, &node_no);
  }
  else 
  if (action == APP_LEAVE)
  {
    spider_clear_r (ctx);
  }
  return APP_OK;
}

Attention - RAM stored node
In case you malloced RAM stored node in APP_ENTER part of callback you must not freed it in APP_LEAVE part of callback. Free it in the previous node instead (this is because SNode::text can be used as alpha text).

Delete parent node - spider_back()

In some situation it is desired to delete the node you came from, i.e. parent node. For example you have some item, e.g. Contact, which can be viewed, edited or deleted, in the top picture node_3 would be Contact and node_6 is Delete, node_5 is Edit and node_4 is View. If you delete node_4 in node_6 spider cannot go back to node_4. For such situations there is the spider_back() function, example:
u8 node_6_delete (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    u8 res;
    SNode *n = ctx->parent->f;

    res = yesno (blabla, Q_YESNO_DELETE_QMARK, 0);
    if (res == APP_END)
      return APP_END;
    if (res == APP_YES)
    {
      delete_contact (n);       // free contact, etc.
      spider_back (ctx);
    }
    return APP_BACK;
  }
  return APP_OK;
}

Data Structures

Defines

Typedefs

Functions


Define Documentation

#define APP_BACK
 

User back

#define APP_END
 

User end of application

#define APP_ENTER
 

Spider node enter

#define APP_LEAVE
 

Spider node leave

#define APP_OK
 

User OK.

#define LC_DELETE
 

Constant denoting use of built-in localized "Delete". SNodeP only.

#define LC_EDIT
 

Constant denoting use of built-in localized "Edit". SNodeP only.

#define LC_HELP
 

Constant denoting use of built-in localized "Help". SNodeP only.

#define LC_NEW
 

Constant denoting use of built-in localized "New". SNodeP only.

#define LC_PROTECT
 

Constant denoting use of built-in localized "Protect". SNodeP only.

#define LC_UNPROTECT
 

Constant denoting use of built-in localized "Unprotect". SNodeP only.

#define LC_VIEW
 

Constant denoting use of built-in localized "View". SNodeP only.

#define MEM_F_D
 

Indicates that FROM node if from Memory Card.

#define MEM_F_E
 

Indicates that FROM node if from EEPROM.

#define MEM_F_P
 

Indicates that FROM node if from PROGMEM.

#define MEM_F_R
 

Indicates that FROM node if from RAM.

#define MEM_T_D
 

Indicates that TO node if from Memory Card.

#define MEM_T_E
 

Indicates that TO node if from EEPROM.

#define MEM_T_P
 

Indicates that TO node if from PROGMEM.

#define MEM_T_R
 

Indicates that TO node if from RAM.

#define ORDER_D
 

Indicates Memory Card edges.

See also:
spider_set_order()

#define ORDER_E
 

Indicated EEPROM edges.

See also:
spider_set_order()

#define ORDER_P
 

Indicates PROGMEM edges.

See also:
spider_set_order()

#define ORDER_R
 

Indicates RAM edges.

See also:
spider_set_order()

#define SPIDER_STYLE_LS
 

List attribute - name only. Entries starting with . are hidden.

#define SPIDER_STYLE_LS_AL
 

List attribute - name.type for file or name/ for dir. Entries starting with . are not hidden.

#define SPIDER_STYLE_LS_L
 

List attribute - name.type for file or name/ for dir. Entries starting with . are hidden.

#define SPIDER_STYLE_UCS2
 

Or'ed to inform spider that items can be in UCS2.


Typedef Documentation

typedef struct _SCtx SCtx
 

Spider context structure. Keeps internal state of spider.

typedef struct _SEdge SEdge
 

RAM and EEPROM stored spider edge. Compared to to PROGMEM stored SEdgeP there are two extra fields: next and source.

typedef struct _SEdgeP SEdgeP
 

Structure of PROGMEM stored edge. Such edges are stored as NULL terminated array.

typedef struct _SNode SNode
 

Spider node structure for RAM and EEPROM stored nodes.

Attention:
See the difference to SNodeP, where text is const lc_char *. Here it is just u8 *.

typedef struct _SNodeP SNodeP
 

PROGMEM stored spider node structure.

typedef struct _SParent SParent
 

Linked list of SParent structures keeps the spider path. f is useful to access the parent of the current node.

typedef u8( t_spider_cb)(struct _SCtx * ctx, u8 action)
 

Spider node callback, it handles APP_ENTER and APP_LEAVE actions.


Function Documentation

void spider SCtx ctx  ) 
 

The spider() starts the traversing of the menu structure and destroys the context at the end of application.

Warning:
SIM Toolkit function, usable only in stk_thread().
Parameters:
ctx context
Examples:
braled.c, braping.c, calc.c, certs.c, fake_sim.c, hello_world_ucs2.c, mc.c, reader.c, sysinfo.c, test_idle.c, test_prot_mem.c, and tsmsacl.c.

u8 spider_append_r SCtx ctx,
const SNode to
 

Append RAM edge to the current node.

Parameters:
ctx 
to TO node, can be from RAM, EEPROM, PROGMEM
Returns:
NO_ERROR if OK, ERR_NO_RAM if error.
Examples:
calc.c, certs.c, fake_sim.c, mc.c, reader.c, sysinfo.c, test_idle.c, and tsmsacl.c.

u8* spider_back SCtx ctx  ) 
 

Skip parent node - return to node previous to parent node.

Parameters:
ctx 
Returns:
NULL if no parent, ENULL if parent.
Examples:
tsmsacl.c.

void spider_clear_r SCtx ctx  ) 
 

Delete all RAM edges leading from the current node.

Parameters:
ctx 
Examples:
calc.c, certs.c, fake_sim.c, mc.c, reader.c, sysinfo.c, test_idle.c, and tsmsacl.c.

SCtx* spider_init  ) 
 

The spider_init() creates and initiates the spider context.

void foo()
{
SCtx *c;

c=spider_init();
if(c==NULL){perror(ERR_NO_RAM);return;}
... // modifications to c
spider(c);
}

Returns:
NULL if memory error
Examples:
braled.c, braping.c, calc.c, certs.c, fake_sim.c, hello_world_ucs2.c, mc.c, reader.c, sysinfo.c, test_idle.c, test_prot_mem.c, and tsmsacl.c.

void spider_set_order SCtx ctx,
u8  o1,
u8  o2,
u8  o3,
u8  o4
 

Set order in which edges are evaluated.

Parameters:
ctx 
o1 MEM_R or MEM_P or MEM_E or MEM_D
o2 MEM_R or MEM_P or MEM_E or MEM_D
o3 MEM_R or MEM_P or MEM_E or MEM_D
o4 MEM_R or MEM_P or MEM_E or MEM_D
Examples:
calc.c, and tsmsacl.c.


Copyright © 2004-2006 BLADOX
Turbo version 1.2