observer.c

Go to the documentation of this file.
00001 /*                      O B S E R V E R . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1997-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup butcl */
00023 /*@{*/
00024 
00025 /** @file observer.c
00026  * @brief Routines for implementing the observer pattern.
00027  *
00028  * @par Source
00029  *      SLAD CAD Team
00030  * @n   The U. S. Army Research Laboratory
00031  * @n   Aberdeen Proving Ground, Maryland  21005
00032  *
00033  * @author
00034  *      Robert G. Parker
00035  */
00036 
00037 
00038 #include "common.h"
00039 
00040 
00041 #ifdef HAVE_STRING_H
00042 #include <string.h>
00043 #endif
00044 
00045 #include "tcl.h"
00046 #include "machine.h"
00047 #include "cmd.h"                  /* includes bu.h */
00048 
00049 static int bu_observer_attach_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00050 static int bu_observer_detach_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00051 static int bu_observer_show_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00052 
00053 struct bu_cmdtab bu_observer_cmds[] = {
00054         {"attach",      bu_observer_attach_tcl},
00055         {"detach",      bu_observer_detach_tcl},
00056         {"show",        bu_observer_show_tcl},
00057         {(char *)0,     (int (*)())0}
00058 };
00059 
00060 /**
00061  * Attach observer.
00062  *
00063  * Usage:
00064  *        attach observer [cmd]
00065  *
00066  */
00067 static int
00068 bu_observer_attach_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00069 {
00070         struct bu_observer *headp = (struct bu_observer *)clientData;
00071         struct bu_observer *op;
00072 
00073         if (argc < 2 || 3 < argc) {
00074                 struct bu_vls vls;
00075 
00076                 bu_vls_init(&vls);
00077                 bu_vls_printf(&vls, "helplib bu_observer_attach");
00078                 Tcl_Eval(interp, bu_vls_addr(&vls));
00079                 bu_vls_free(&vls);
00080                 return TCL_ERROR;
00081         }
00082 
00083         /* see if it already exists, if so, modify it */
00084         for (BU_LIST_FOR(op, bu_observer, &headp->l))
00085                 if (strcmp(bu_vls_addr(&op->observer), argv[1]) == 0) {
00086                         if (argc == 2)
00087                                 /* clobber cmd */
00088                                 bu_vls_init(&op->cmd);
00089                         else
00090                                 /* overwrite cmd */
00091                                 bu_vls_strcpy(&op->cmd, argv[2]);
00092 
00093                         return TCL_OK;
00094                 }
00095 
00096         /* acquire bu_observer struct */
00097         BU_GETSTRUCT(op, bu_observer);
00098 
00099         /* initialize observer */
00100         bu_vls_init(&op->observer);
00101         bu_vls_strcpy(&op->observer, argv[1]);
00102         bu_vls_init(&op->cmd);
00103 
00104         if (argc == 3)
00105                 bu_vls_strcpy(&op->cmd, argv[2]);
00106 
00107         /* append to list of bu_observer's */
00108         BU_LIST_APPEND(&headp->l, &op->l);
00109 
00110         return TCL_OK;
00111 }
00112 
00113 /**
00114  * Detach observer.
00115  *
00116  * Usage:
00117  *        detach observer
00118  *
00119  */
00120 static int
00121 bu_observer_detach_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00122 {
00123         struct bu_observer *headp = (struct bu_observer *)clientData;
00124         struct bu_observer *op;
00125 
00126         if (argc != 2) {
00127                 struct bu_vls vls;
00128 
00129                 bu_vls_init(&vls);
00130                 bu_vls_printf(&vls, "helplib bu_observer_attach");
00131                 Tcl_Eval(interp, bu_vls_addr(&vls));
00132                 bu_vls_free(&vls);
00133                 return TCL_ERROR;
00134         }
00135 
00136         /* search for observer and remove from list */
00137         for (BU_LIST_FOR(op, bu_observer, &headp->l))
00138                 if (strcmp(bu_vls_addr(&op->observer), argv[1]) == 0) {
00139                         BU_LIST_DEQUEUE(&op->l);
00140                         bu_vls_free(&op->observer);
00141                         bu_vls_free(&op->cmd);
00142                         bu_free((genptr_t)op, "bu_observer_detach_tcl: op");
00143 
00144                         return TCL_OK;
00145                 }
00146 
00147         Tcl_AppendResult(interp, "detach: ", argv[1], " not found", (char *)NULL);
00148         return TCL_ERROR;
00149 }
00150 
00151 /**
00152  * Show/list observers.
00153  *
00154  * Usage:
00155  *        show
00156  *
00157  */
00158 static int
00159 bu_observer_show_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00160 {
00161         struct bu_observer *headp = (struct bu_observer *)clientData;
00162         struct bu_observer *op;
00163 
00164         for (BU_LIST_FOR(op, bu_observer, &headp->l)) {
00165                 Tcl_AppendResult(interp, bu_vls_addr(&op->observer), " - ",
00166                                  bu_vls_addr(&op->cmd), "\n", (char *)NULL);
00167         }
00168 
00169         return TCL_OK;
00170 }
00171 
00172 /**
00173  * Notify observers.
00174  */
00175 void
00176 bu_observer_notify(Tcl_Interp *interp, struct bu_observer *headp, char *this)
00177 {
00178         struct bu_observer *op;
00179         struct bu_vls vls;
00180 
00181         bu_vls_init(&vls);
00182         for (BU_LIST_FOR(op, bu_observer, &headp->l)) {
00183                 if (bu_vls_strlen(&op->cmd) > 0) {
00184                         /* Execute cmd */
00185                         bu_vls_strcpy(&vls, bu_vls_addr(&op->cmd));
00186                         Tcl_Eval(interp, bu_vls_addr(&vls));
00187                 } else {
00188                         /* Assume that observer is some object that has an update method */
00189                         bu_vls_trunc(&vls, 0);
00190                         bu_vls_printf(&vls, "%s update %s", bu_vls_addr(&op->observer), this);
00191                         Tcl_Eval(interp, bu_vls_addr(&vls));
00192                 }
00193         }
00194         bu_vls_free(&vls);
00195 }
00196 
00197 /**
00198  * Free observers.
00199  */
00200 void
00201 bu_observer_free(struct bu_observer *headp)
00202 {
00203         struct bu_observer *op;
00204         struct bu_observer *nop;
00205 
00206         op = BU_LIST_FIRST(bu_observer, &headp->l);
00207         while (BU_LIST_NOT_HEAD(op, &headp->l)) {
00208                 nop = BU_LIST_PNEXT(bu_observer, op);
00209                 BU_LIST_DEQUEUE(&op->l);
00210                 bu_vls_free(&op->observer);
00211                 bu_vls_free(&op->cmd);
00212                 bu_free((genptr_t)op, "bu_observer_free: op");
00213                 op = nop;
00214         }
00215 }
00216 
00217 /*@}*/
00218 /*
00219  * Local Variables:
00220  * mode: C
00221  * tab-width: 8
00222  * c-basic-offset: 4
00223  * indent-tabs-mode: t
00224  * End:
00225  * ex: shiftwidth=4 tabstop=8
00226  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6