#include "tkTreeCtrl.h"
static
int
EVENT_EXPAND,
DETAIL_EXPAND_BEFORE,
DETAIL_EXPAND_AFTER;
static
int
EVENT_COLLAPSE,
DETAIL_COLLAPSE_BEFORE,
DETAIL_COLLAPSE_AFTER;
static
int
EVENT_SELECTION;
static
int
EVENT_ACTIVEITEM;
static
int
EVENT_SCROLL,
DETAIL_SCROLL_X,
DETAIL_SCROLL_Y;
static
int
EVENT_ITEM_DELETE;
static
int
EVENT_ITEM_VISIBILITY;
static
void
ExpandItem(
TreeCtrl *tree,
int
id,
Tcl_DString *result
)
{
char
buf[10 + TCL_INTEGER_SPACE];
(
void
)
sprintf
(buf,
"%s%d"
,
(tree->itemPrefixLen ? tree->itemPrefix :
""
), id);
Tcl_DStringAppend(result, buf, -1);
}
static
void
ExpandItemList(
TreeCtrl *tree,
TreeItemList *itemList,
Tcl_DString *result
)
{
if
(itemList == NULL) {
Tcl_DStringAppend(result,
"{}"
, 2);
}
else
{
int
i, count;
char
buf[10 + TCL_INTEGER_SPACE];
Tcl_DStringStartSublist(result);
count = TreeItemList_Count(itemList);
for
(i = 0; i < count; i++) {
(
void
)
sprintf
(buf,
"%s%d"
,
(tree->itemPrefixLen ? tree->itemPrefix :
""
),
TreeItem_GetID(tree, TreeItemList_Nth(itemList, i)));
Tcl_DStringAppendElement(result, buf);
}
Tcl_DStringEndSublist(result);
}
}
static
void
DumpPercents(
QE_ExpandArgs *args,
QE_ExpandProc proc,
CONST
char
*chars
)
{
char
which = args->which;
char
buf[2];
int
i;
buf[1] =
'\0'
;
Tcl_DStringStartSublist(args->result);
for
(i = 0; chars[i]; i++) {
args->which = chars[i];
buf[0] = chars[i];
Tcl_DStringAppendElement(args->result, buf);
Tcl_DStringAppend(args->result,
" "
, 1);
(*proc)(args);
}
Tcl_DStringEndSublist(args->result);
args->which = which;
}
static
void
Percents_Any(
QE_ExpandArgs *args,
QE_ExpandProc proc,
CONST
char
*chars
)
{
struct
{
TreeCtrl *tree;
} *data = args->clientData;
char
chars2[64];
switch
(args->which) {
case
'd'
:
QE_ExpandDetail(args->bindingTable, args->event, args->detail,
args->result);
break
;
case
'e'
:
QE_ExpandEvent(args->bindingTable, args->event, args->result);
break
;
case
'P'
:
QE_ExpandPattern(args->bindingTable, args->event, args->detail, args->result);
break
;
case
'W'
:
QE_ExpandString((
char
*) args->object, args->result);
break
;
case
'T'
:
QE_ExpandString(Tk_PathName(data->tree->tkwin), args->result);
break
;
case
'?'
:
strcpy
(chars2,
"TWPed"
);
strcat
(chars2, chars);
DumpPercents(args, proc, chars2);
break
;
default
:
QE_ExpandUnknown(args->which, args->result);
break
;
}
}
static
void
Percents_Expand(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
int
id;
} *data = args->clientData;
switch
(args->which) {
case
'I'
:
ExpandItem(data->tree, data->id, args->result);
break
;
default
:
Percents_Any(args, Percents_Expand,
"I"
);
break
;
}
}
static
void
Percents_ItemVisibility(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
TreeItemList *v;
TreeItemList *h;
} *data = args->clientData;
TreeItemList *table;
switch
(args->which) {
case
'v'
:
case
'h'
:
table = (args->which ==
'v'
) ? data->v : data->h;
ExpandItemList(data->tree, table, args->result);
break
;
default
:
Percents_Any(args, Percents_ItemVisibility,
"vh"
);
break
;
}
}
static
void
Percents_Selection(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
TreeItemList *select;
TreeItemList *deselect;
int
count;
} *data = args->clientData;
TreeItemList *itemList;
switch
(args->which) {
case
'c'
:
QE_ExpandNumber(data->count, args->result);
break
;
case
'D'
:
case
'S'
:
itemList = (args->which ==
'D'
) ? data->deselect : data->select;
ExpandItemList(data->tree, itemList, args->result);
break
;
default
:
Percents_Any(args, Percents_Selection,
"cSD"
);
break
;
}
}
static
void
Percents_ActiveItem(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
int
prev;
int
current;
} *data = args->clientData;
switch
(args->which) {
case
'c'
:
ExpandItem(data->tree, data->current, args->result);
break
;
case
'p'
:
ExpandItem(data->tree, data->prev, args->result);
break
;
default
:
Percents_Any(args, Percents_ActiveItem,
"cp"
);
break
;
}
}
static
void
Percents_Scroll(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
double
lower;
double
upper;
} *data = args->clientData;
switch
(args->which) {
case
'l'
:
QE_ExpandDouble(data->lower, args->result);
break
;
case
'u'
:
QE_ExpandDouble(data->upper, args->result);
break
;
default
:
Percents_Any(args, Percents_Scroll,
"lu"
);
break
;
}
}
int
TreeNotifyCmd(
ClientData clientData,
Tcl_Interp *interp,
int
objc,
Tcl_Obj *CONST objv[]
)
{
TreeCtrl *tree = clientData;
static
CONST
char
*commandName[] = {
"bind"
,
"configure"
,
"detailnames"
,
"eventnames"
,
"generate"
,
"install"
,
"linkage"
,
"unbind"
,
"uninstall"
,
(
char
*) NULL };
enum
{
COMMAND_BIND, COMMAND_CONFIGURE, COMMAND_DETAILNAMES,
COMMAND_EVENTNAMES, COMMAND_GENERATE, COMMAND_INSTALL,
COMMAND_LINKAGE, COMMAND_UNBIND, COMMAND_UNINSTALL
};
int
index;
if
(objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv,
"command ?arg arg ...?"
);
return
TCL_ERROR;
}
if
(Tcl_GetIndexFromObj(interp, objv[2], commandName,
"command"
, 0,
&index) != TCL_OK) {
return
TCL_ERROR;
}
switch
(index) {
case
COMMAND_BIND: {
return
QE_BindCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_CONFIGURE: {
return
QE_ConfigureCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_DETAILNAMES: {
char
*eventName;
if
(objc != 4) {
Tcl_WrongNumArgs(interp, 3, objv,
"eventName"
);
return
TCL_ERROR;
}
eventName = Tcl_GetString(objv[3]);
return
QE_GetDetailNames(tree->bindingTable, eventName);
}
case
COMMAND_EVENTNAMES: {
if
(objc != 3) {
Tcl_WrongNumArgs(interp, 3, objv, (
char
*) NULL);
return
TCL_ERROR;
}
return
QE_GetEventNames(tree->bindingTable);
}
case
COMMAND_GENERATE: {
return
QE_GenerateCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_INSTALL: {
return
QE_InstallCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_LINKAGE: {
return
QE_LinkageCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_UNBIND: {
return
QE_UnbindCmd(tree->bindingTable, 2, objc, objv);
}
case
COMMAND_UNINSTALL: {
return
QE_UninstallCmd(tree->bindingTable, 2, objc, objv);
}
}
return
TCL_OK;
}
void
TreeNotify_OpenClose(
TreeCtrl *tree,
TreeItem item,
int
state,
int
before
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
int
id;
} data;
data.tree = tree;
data.id = TreeItem_GetID(tree, item);
if
(state & STATE_ITEM_OPEN) {
event.type = EVENT_EXPAND;
event.detail = before ? DETAIL_EXPAND_BEFORE : DETAIL_EXPAND_AFTER;
}
else
{
event.type = EVENT_COLLAPSE;
event.detail = before ? DETAIL_COLLAPSE_BEFORE : DETAIL_COLLAPSE_AFTER;
}
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
void
TreeNotify_Selection(
TreeCtrl *tree,
TreeItemList *select,
TreeItemList *deselect
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
TreeItemList *select;
TreeItemList *deselect;
int
count;
} data;
data.tree = tree;
data.select = select;
data.deselect = deselect;
data.count = tree->selectCount;
event.type = EVENT_SELECTION;
event.detail = 0;
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
void
TreeNotify_ActiveItem(
TreeCtrl *tree,
TreeItem itemPrev,
TreeItem itemCur
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
int
prev;
int
current;
} data;
data.tree = tree;
data.prev = TreeItem_GetID(tree, itemPrev);
data.current = TreeItem_GetID(tree, itemCur);
event.type = EVENT_ACTIVEITEM;
event.detail = 0;
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
void
TreeNotify_Scroll(
TreeCtrl *tree,
double
fractions[2],
int
vertical
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
double
lower;
double
upper;
} data;
data.tree = tree;
data.lower = fractions[0];
data.upper = fractions[1];
event.type = EVENT_SCROLL;
event.detail = vertical ? DETAIL_SCROLL_Y : DETAIL_SCROLL_X;
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
static
void
Percents_ItemDelete(
QE_ExpandArgs *args
)
{
struct
{
TreeCtrl *tree;
TreeItemList *items;
} *data = args->clientData;
switch
(args->which) {
case
'i'
:
ExpandItemList(data->tree, data->items, args->result);
break
;
default
:
Percents_Any(args, Percents_ItemDelete,
"i"
);
break
;
}
}
void
TreeNotify_ItemDeleted(
TreeCtrl *tree,
TreeItemList *items
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
TreeItemList *items;
} data;
data.tree = tree;
data.items = items;
event.type = EVENT_ITEM_DELETE;
event.detail = 0;
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
void
TreeNotify_ItemVisibility(
TreeCtrl *tree,
TreeItemList *v,
TreeItemList *h
)
{
QE_Event event;
struct
{
TreeCtrl *tree;
TreeItemList *v;
TreeItemList *h;
} data;
data.tree = tree;
data.v = v;
data.h = h;
event.type = EVENT_ITEM_VISIBILITY;
event.detail = 0;
event.clientData = (ClientData) &data;
(
void
) QE_BindEvent(tree->bindingTable, &event);
}
int
TreeNotify_InitWidget(
TreeCtrl *tree
)
{
tree->bindingTable = QE_CreateBindingTable(tree->interp);
EVENT_EXPAND = QE_InstallEvent(tree->bindingTable,
"Expand"
, Percents_Expand);
DETAIL_EXPAND_BEFORE = QE_InstallDetail(tree->bindingTable,
"before"
, EVENT_EXPAND, NULL);
DETAIL_EXPAND_AFTER = QE_InstallDetail(tree->bindingTable,
"after"
, EVENT_EXPAND, NULL);
EVENT_COLLAPSE = QE_InstallEvent(tree->bindingTable,
"Collapse"
, Percents_Expand);
DETAIL_COLLAPSE_BEFORE = QE_InstallDetail(tree->bindingTable,
"before"
, EVENT_COLLAPSE, NULL);
DETAIL_COLLAPSE_AFTER = QE_InstallDetail(tree->bindingTable,
"after"
, EVENT_COLLAPSE, NULL);
EVENT_SELECTION = QE_InstallEvent(tree->bindingTable,
"Selection"
, Percents_Selection);
EVENT_ACTIVEITEM = QE_InstallEvent(tree->bindingTable,
"ActiveItem"
, Percents_ActiveItem);
EVENT_SCROLL = QE_InstallEvent(tree->bindingTable,
"Scroll"
, Percents_Scroll);
DETAIL_SCROLL_X = QE_InstallDetail(tree->bindingTable,
"x"
, EVENT_SCROLL, NULL);
DETAIL_SCROLL_Y = QE_InstallDetail(tree->bindingTable,
"y"
, EVENT_SCROLL, NULL);
EVENT_ITEM_DELETE = QE_InstallEvent(tree->bindingTable,
"ItemDelete"
, Percents_ItemDelete);
EVENT_ITEM_VISIBILITY = QE_InstallEvent(tree->bindingTable,
"ItemVisibility"
, Percents_ItemVisibility);
return
TCL_OK;
}