emview_component.c from EmStar at Krugle
Show emview_component.c syntax highlighted
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "emview_i.h"
char emview_component_c_id[] = "$Id: emview_component.c,v 1.18 2004/03/02 01:13:41 girod Exp $";
QUEUE_INLINE_INSTANTIATIONS(emview_component, ptrs, components, component_t, component_list_t);
QUEUE_FUNCTION_INSTANTIATIONS(emview_component, ptrs, components, component_t, component_list_t);
component_t *emview_component_lookup_q(component_list_t *cl, GQuark component);
void emview_component_set_check(component_t *c);
component_t *emview_component_create_q(GQuark qname, emview_component_type_t type)
{
component_t *retval = NULL;
if (_core.components.vtbl[type].create)
retval = _core.components.vtbl[type].create();
else
elog(LOG_WARNING, "No method found for type %d", type);
if (retval) {
retval->name = qname;
retval->type = type;
}
return retval;
}
component_t *emview_component_create(char *name, emview_component_type_t type)
{
return emview_component_create_q(g_quark_from_string(name), type);
}
component_t *emview_component_copy(component_t *src)
{
component_t *retval = NULL;
if (_core.components.vtbl[src->type].copy) {
retval = _core.components.vtbl[src->type].copy(src);
emview_component_el_init(retval);
}
else
elog(LOG_WARNING, "No method found for type %d", src->type);
return retval;
}
/*
* component registration
*/
int emview_component_register(GQuark comp_name, node_id_t id, emview_component_type_t type)
{
component_t *c;
node_t *n = emview_node_lookup_nocreate(id);
if (n == NULL) {
elog(LOG_WARNING, "Registering component for nonexistent node id=%d", id);
return -1;
}
/* lookup / create a new component */
c = emview_component_lookup_q(&(n->display.components), comp_name);
if (c == NULL) {
component_t *c = emview_component_create_q(comp_name, type);
if (type == EMVIEW_COMP_TYPE_NODE) ((node_component_t *)c)->id = id;
c->visible = 1;
emview_component_push(&(n->display.components), c);
}
else
c->mark = 0;
return 0;
}
/*
* Component lookup
*/
static
component_t *emview_get_component_aux(node_id_t target, char *c_name)
{
component_t *c = NULL;
if (target == EMVIEW_NODE_GLOBAL)
c = emview_component_lookup(&(_core.components), c_name);
else {
node_t *n = emview_node_lookup_nocreate(target);
if (n == NULL) {
elog(LOG_WARNING, "Modifying component of nonexistent node id=%d", target);
goto out;
}
c = emview_component_lookup(&(n->display.components), c_name);
}
out:
return c;
}
/*
* mark and prune
*/
void emview_component_list_mark(component_list_t *cl)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr;
ptr = emview_component_next(ptr))
ptr->mark = 1;
}
void emview_component_list_prune_marked(component_list_t *cl)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr; ) {
component_t *ptr2 = emview_component_next(ptr);
if (ptr->mark) {
emview_component_remove(cl, ptr);
if (_core.components.vtbl[ptr->type].destroy) {
_core.components.vtbl[ptr->type].destroy(ptr);
}
else
elog(LOG_CRIT, "Component is missing destroy method!");
}
ptr = ptr2;
}
}
/*
* laying out and drawing components
*/
void emview_component_clear_refs(component_list_t *cl)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr;
ptr = emview_component_next(ptr))
ptr->referenced = 0;
}
/* returns true if some part of this node is referenced */
int emview_component_layout_type(node_t *n,
emview_component_type_t type)
{
component_t *ptr;
int retval = 0;
for (ptr = emview_component_top(&(n->display.components)); ptr;
ptr = emview_component_next(ptr))
if (ptr->type == type) {
elog(LOG_DEBUG(17), "laying out component %d type %d at [%d,%d] v=%d,a=%d, disp1=%d,%d",
ptr->name, ptr->type, ptr->px, ptr->py, ptr->visible, ptr->active,
n->display.bx2, n->display.by1);
ptr->disp = &(n->display);
_core.components.vtbl[type].checkrefs(ptr);
/* set active flag */
if (n->active)
ptr->active = ptr->referenced;
else
ptr->active = 0;
/* return whether something was ref'd */
if (ptr->referenced) retval = 1;
/* now layout */
if (ptr->visible && (ptr->referenced || ptr->active))
_core.components.vtbl[type].layout(ptr);
}
return retval;
}
void emview_components_draw(component_list_t *cl)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr;
ptr = emview_component_next(ptr)) {
if (ptr->visible && (ptr->referenced || ptr->active)) {
elog(LOG_DEBUG(17), "drawing component %d type %d at [%d,%d] v=%d,a=%d",
ptr->name, ptr->type, ptr->px, ptr->py, ptr->visible, ptr->active);
_core.components.vtbl[ptr->type].draw(ptr);
}
}
}
void emview_component_extend_upper_right(component_t *c, int width, int height)
{
/* upper left corner at upper right of current bbox */
c->px = c->disp->bx2;
c->py = c->disp->by1;
/* node bbox */
c->w = width;
c->h = height;
/* extend bbox */
c->disp->bx2 += (width-1);
c->disp->by2 = i_max((c->disp->by1+height-1), c->disp->by2);
}
/*
* setting visibility for components
*/
int emview_component_set_visible(node_id_t id, char *c_name, int visible)
{
component_t *c = emview_get_component_aux(id, c_name);
if (c) {
/* set and note change */
c->visible = visible;
#if 0
if (id == EMVIEW_NODE_GLOBAL)
emview_component_set_check(c);
else
c->override = 1;
// $$$ this gets handled by node reconfig..
//emview_component_note_config_change(id);
#endif
return 0;
}
return -1;
}
int emview_component_get_visible(node_id_t id, char *c_name)
{
component_t *c = emview_get_component_aux(id, c_name);
if (c) {
return boolify(c->visible);
}
return -1;
}
int emview_component_set_active(node_id_t id, char *c_name, int set)
{
component_t *c = emview_get_component_aux(id, c_name);
if (c) {
c->active = set;
return 0;
}
return -1;
}
int emview_component_get_active(node_id_t id, char *c_name)
{
component_t *c = emview_get_component_aux(id, c_name);
if (c) return boolify(c->active);
return -1;
}
/*
* Internal API
*/
component_t *emview_component_lookup_q(component_list_t *cl, GQuark component)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr; ptr = emview_component_next(ptr))
if (ptr->name == component) return ptr;
return NULL;
}
component_t *emview_component_lookup(component_list_t *cl, char *c_name)
{
return emview_component_lookup_q(cl, g_quark_from_string(c_name));
}
void emview_component_list_append_copy(component_list_t *dst, component_list_t *src)
{
component_t *c;
for (c = emview_component_top(src); c; c=emview_component_next(c)) {
component_t *nc = emview_component_copy(c);
emview_component_push(dst, nc);
}
}
void emview_component_list_set_active(component_list_t *cl, int active)
{
component_t *ptr;
for (ptr = emview_component_top(cl); ptr;
ptr = emview_component_next(ptr))
ptr->active = active;
}
void emview_component_list_clear_refs(component_list_t *cl)
{
component_t *c;
for (c = emview_component_top(cl); c; c=emview_component_next(c))
c->referenced = 0;
}
/*
* given a node's component list, clears all links and resets them from the
* slot list provided
*/
void emview_component_assign_low(component_t *c, int field, source_data_t *d)
{
if (field) {
if (d) emview_source_activate_deps(d->parent_source);
_core.components.vtbl[c->type].assign(c, field, d);
}
}
void emview_component_relink(component_list_t *cl, node_id_t id, slot_list_t *slots)
{
component_t *c;
elog(LOG_DEBUG(5), "Relinking components for node %d", id);
for (c = emview_component_top(cl); c; c=emview_component_next(c)) {
if (_core.components.vtbl[c->type].assign) {
_core.components.vtbl[c->type].clear(c, 0, NULL);
emview_slot_list_assign_low(slots, c, id);
}
else
elog(LOG_WARNING, "No assign method for type %d", c->type);
}
}
int emview_component_is_exclusive_q(component_list_t *cl, GQuark component, int field)
{
int retval = -1;
/* lookup component */
component_t *c = emview_component_lookup_q(cl, component);
if (c == NULL) goto out;
/* check exclusivity */
if (_core.components.vtbl[c->type].is_exclusive)
retval = (_core.components.vtbl[c->type].is_exclusive(field)) ? 1 : 0;
else {
elog(LOG_WARNING, "No method found for type %d", c->type);
goto out;
}
out:
return retval;
}
/*
* handle storing and clearing the non-exclusive slots
*/
void component_nonexcl_clear(GPtrArray **arr, source_data_t *d)
{
if (*arr == NULL) return;
if (d)
g_ptr_array_remove(*arr, d);
else {
g_ptr_array_free(*arr, 0);
*arr = NULL;
}
}
void component_nonexcl_append(GPtrArray **arr, source_data_t *d)
{
if (*arr == NULL)
*arr = g_ptr_array_new();
g_ptr_array_add(*arr, d);
}
void component_nonexcl_check_referenced(component_t *c, GPtrArray *ne)
{
int i;
if (ne)
for (i=0; i<ne->len; i++)
component_check_referenced(c, (source_data_t*)g_ptr_array_index(ne, i));
}
void component_check_referenced(component_t *c, source_data_t *data)
{
if (emview_source_data_valid(data)) c->referenced = 1;
}
void emview_reconfig()
{
g_event_destroy(_core.components.config_timeout);
/* $$$ could do per-node reconfig. */
_core.components.config_change = 0;
emview_node_global_relink_display();
/* force next redraw to be full */
emview_next_redraw_full();
}
static
int emview_component_force_update(void *data, int interval, g_event_t *event)
{
elog(LOG_WARNING, "Config timer fired! Missing emview_reconfig?");
emview_reconfig();
return TIMER_DONE;
}
void emview_component_note_config_change(node_id_t target)
{
/* $$$ ignores target for now, could do per-node reconfig */
_core.components.config_change = 1;
if (!g_timer_isset(_core.components.config_timeout)) {
g_timer_add(EMVIEW_NODE_CONFIG_UPDATE, emview_component_force_update,
NULL, NULL, &(_core.components.config_timeout));
}
}
/*
* status info
*/
int emview_component_list_status_printable(component_list_t *cl, buf_t *buf)
{
component_t *c;
for (c = emview_component_top(cl); c; c = emview_component_next(c)) {
bufprintf(buf, " %s: (%d,%d)%s, %s, %s%s\n",
g_quark_to_string(c->name), c->px, c->py,
c->override ? ", overriding" : "",
c->visible ? "visible" : "hidden",
c->active ? "active" : "inactive",
c->referenced ? ", referenced" : "");
if (_core.components.vtbl[c->type].print)
_core.components.vtbl[c->type].print(c, buf);
}
return STATUS_MSG_COMPLETE;
}
/*
* init call
*
* instantiates base Node component
*/
void emview_components_init()
{
/* sub inits to different component implementations */
emview_node_component_init();
emview_box_component_init();
}
See more files for this project here