/*
 *	(c) Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
 *	See LEGAL_NOTICE file for terms and restrictions.
 */

#ifndef lint
#ifdef sccs
static char	sccsid[] = "@(#)util.c 1.7 91/05/06";
#endif
#endif

#include <xview/frame.h>
#include <xview/panel.h>
#include <sspkg/rectobj.h>
#include <sspkg/drawobj.h>
#include <sspkg/canshell.h>
#include <sspkg/tree.h>
#include <sspkg/grip.h>

static void by_id();
static void by_class();
static void re_evaluate();
static void free_remove_proc();
static void start_rectobj_destroyed();

typedef struct {
	char 		*pkg_name;
	Xv_opaque 	id;
	Tree 		tree;
} Node_info;

typedef struct {
	Frame		frame;
	Canvas_shell	shell;
	Panel		panel;
	Panel_item	pb1;
	Panel_item	pb2;
	Panel_item	pb3;
	Tree		tree;
	Rectobj		start_rectobj;
} UI_info;
	
static int info_key = 0;
static int ui_info_key = 0;

static void
traverse_rectobj_hierarchy(rectobj, tree2, link_to)
	Rectobj rectobj;
	Tree	tree2;
	Rectobj link_to;
{
	Rectobj_list *list;
	Rectobj child;
	Rectobj new_rectobj;
	Node_info *info;

	info = (Node_info*) malloc(sizeof(Node_info));
	info->pkg_name = ((Xv_base*)rectobj)->pkg->name;
	info->id = rectobj;
	info->tree = tree2;

	new_rectobj = xv_create(tree2, DRAWTEXT,
			XV_SHOW, FALSE,
			DRAWTEXT_STRING, info->pkg_name,
			XV_KEY_DATA, info_key, info,
			XV_KEY_DATA_REMOVE_PROC, info_key, free_remove_proc,
			NULL);

	list = (Rectobj_list *) xv_get(rectobj, RECTOBJ_CHILDREN);

	list_for(list) {
		child = RECTOBJ_LIST_HANDLE(list);
		traverse_rectobj_hierarchy(child, tree2,  new_rectobj);
	}
	xv_set(tree2, TREE_ADD_LINK, link_to, new_rectobj, NULL);
}


show_rectobj_hierarchy(rectobj, frame_owner)
	Rectobj rectobj;
	Frame frame_owner;
{
	UI_info *uii;

	if(info_key == 0) {
		info_key = xv_unique_key();
		ui_info_key = xv_unique_key();
	}

	uii = (UI_info*)malloc(sizeof(UI_info));

	uii->frame = xv_create(frame_owner, FRAME_CMD, 
		FRAME_CMD_PUSHPIN_IN, TRUE,
		FRAME_SHOW_RESIZE_CORNER, TRUE,
		XV_KEY_DATA, ui_info_key, uii,
		XV_KEY_DATA_REMOVE_PROC, ui_info_key, free_remove_proc,
		NULL);

	uii->panel = xv_get(uii->frame, FRAME_CMD_PANEL);

	xv_set(uii->panel, 
		PANEL_LAYOUT, PANEL_HORIZONTAL,
		XV_KEY_DATA, ui_info_key, uii,
		NULL);

	uii->pb1 = xv_create(uii->panel, PANEL_BUTTON, 
		PANEL_LABEL_STRING, "by class",
		PANEL_NOTIFY_PROC, by_class,
		XV_KEY_DATA, ui_info_key, uii,
		NULL);

	uii->pb2 = xv_create(uii->panel, PANEL_BUTTON, 
		PANEL_LABEL_STRING, "by id",
		PANEL_NOTIFY_PROC, by_id,
		XV_KEY_DATA, ui_info_key, uii,
		NULL);

	uii->pb3 = xv_create(uii->panel, PANEL_BUTTON, 
		PANEL_LABEL_STRING, "re-evaluate",
		PANEL_NOTIFY_PROC, re_evaluate,
		XV_KEY_DATA, ui_info_key, uii,
		NULL);

	window_fit(xv_get(uii->frame, FRAME_CMD_PANEL));

	uii->shell = xv_create(uii->frame, CANVAS_SHELL,
		XV_KEY_DATA, ui_info_key, uii,
		WIN_BELOW, uii->panel,
		XV_X, 0,
		NULL);

	uii->tree = xv_create(uii->shell, TREE,
		XV_WIDTH, 450,
		XV_HEIGHT, 650,
		TREE_PARENT_DISTANCE, 20,
		XV_SHOW, FALSE,
		XV_KEY_DATA, ui_info_key, uii,
		NULL);

	uii->start_rectobj = rectobj;

	traverse_rectobj_hierarchy(rectobj, uii->tree, uii->tree);

	xv_set(rectobj,
		XV_KEY_DATA, uii,
		XV_KEY_DATA_REMOVE_PROC, ui_info_key, start_rectobj_destroyed,
		NULL);

	window_fit(uii->frame);
	xv_set(uii->panel, XV_WIDTH, WIN_EXTEND_TO_EDGE, NULL);
	xv_set(uii->frame, XV_SHOW, TRUE, NULL);
	xv_set(uii->tree, XV_SHOW, TRUE, NULL);

}


static void
by_class(item, event)
	Panel_item item;
	Event	*event;
{
	Rectobj_list 	*list;
	Rectobj 	child;
	Node_info 	*info;
	UI_info 	*uii;

	uii = (UI_info*) xv_get(item, XV_KEY_DATA, ui_info_key);
	if(!uii)
		return;
	list = (Rectobj_list *) xv_get(uii->tree, RECTOBJ_CHILDREN);

	list_for(list) {
		child = RECTOBJ_LIST_HANDLE(list);
		if(info = (Node_info*)xv_get(child, XV_KEY_DATA, info_key))
		  xv_set(child, DRAWTEXT_STRING, info->pkg_name, NULL);
	}
}


static void
by_id(item, event)
	Panel_item item;
	Event	*event;
{
	Rectobj_list 	*list;
	char 		buf[10];
	Node_info 	*info;
	UI_info 	*uii;
	Rectobj		child;

	uii = (UI_info*) xv_get(item, XV_KEY_DATA, ui_info_key);
	if(!uii)
		return;
	list = (Rectobj_list *) xv_get(uii->tree, RECTOBJ_CHILDREN);

	list_for(list) {
		child = RECTOBJ_LIST_HANDLE(list);
		if(info = (Node_info*)xv_get(child, XV_KEY_DATA, info_key))
		  sprintf(buf, "%6d", info->id);
		  xv_set(child, DRAWTEXT_STRING, buf, NULL);
	}
}


static void
re_evaluate(item, event)
	Panel_item item;
	Event	*event;
{
	Rectobj_list *list;
	Node_info *info;
	Rectobj child;
	Rectobj rectobj;
	UI_info 	*uii;

	uii = (UI_info*) xv_get(item, XV_KEY_DATA, ui_info_key);
	if(!uii)
		return;
	xv_set(uii->shell, CANVAS_SHELL_DELAY_REPAINT, TRUE, NULL);
	list = (Rectobj_list *) xv_get(uii->tree, RECTOBJ_CHILDREN);

	/*
	 * only nodes have XV_KEY_DATA attached, so these are the only
	 * ones we call destroy on
	 */
	list_for(list) {
		child = RECTOBJ_LIST_HANDLE(list);
		if(xv_get(child, XV_KEY_DATA, info_key))
			xv_destroy(child);
	}

	traverse_rectobj_hierarchy(uii->start_rectobj, uii->tree, uii->tree);

	xv_set(uii->shell, CANVAS_SHELL_DELAY_REPAINT, FALSE, NULL);
}


static void
free_remove_proc(object, key, data)
	Xv_object object;
	Attr_attribute key;
	Xv_opaque data;
{
	free(data);
	xv_set(object, XV_KEY_DATA, key, 0, NULL);
}


static void
start_rectobj_destroyed(object, key, data)
	Xv_object object;
	Attr_attribute key;
	Xv_opaque data;
{
	UI_info *uii = (UI_info*) data;

	xv_set(uii->pb3, PANEL_INACTIVE, TRUE, NULL);
}


