]> git.llucax.com Git - mecon/meconlib.git/blobdiff - lib/MECON/HTML/TablaDB.php
Clarifico el codigo de MECON_PDF_Imagen.
[mecon/meconlib.git] / lib / MECON / HTML / TablaDB.php
index ba5c00f9e8b9524e6fc2a8f60c58638c2f9cf7ef..6852ba91936ce4fade804d4a041a15ee1c52e65d 100644 (file)
@@ -26,10 +26,15 @@ $Id$
 
 require_once 'DB.php';
 require_once 'MECON/DB/Pager.php';
 
 require_once 'DB.php';
 require_once 'MECON/DB/Pager.php';
+require_once 'MECON/Array/Pager.php';
 require_once 'MECON/HTML/Error.php';
 require_once 'MECON/HTML/Link.php';
 require_once 'MECON/HTML/Error.php';
 require_once 'MECON/HTML/Link.php';
+require_once 'MECON/HTML/Icon.php';
 require_once 'MECON/HTML/Tabla.php';
 
 require_once 'MECON/HTML/Tabla.php';
 
+/// Prefijo a usar para las variables GET que genera la tabla.
+define('MECON_HTML_TABLADB_GET_VAR_PREFIX', '_');
+
 /**
  * Libreria para le manejo de las tablas de los sistemas de intranet.
  *
 /**
  * Libreria para le manejo de las tablas de los sistemas de intranet.
  *
@@ -42,6 +47,22 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
      */
     var $_desc = 'resultados';
 
      */
     var $_desc = 'resultados';
 
+    /**
+     * Datos a agregar delante de cada fila que se agregue desde una base de datos.
+     * Cada elemento del array es a su vez un array cuyo primer elemento es el
+     * formato del texto a agregar (tipo printf()) y el segundo es un array con los
+     * campos de la DB a utilizar para ese formato en una fila dada.
+     * Cuando se utiliza una callback para "dibujar" el campo, el campo puede
+     * ser un array de campos de la base que se quiere pasar a la callback.
+     */
+    var $_prependRowsData = array();
+
+    /**
+     * Datos a agregar al final de cada fila que se agregue desde una base de datos.
+     * El formato es el mismo que el de _prependRowsData.
+     */
+    var $_appendRowsData = array();
+
     /**
      * Constructor. 
      * Puede recibir como parametro un string con los atributos que se 
     /**
      * Constructor. 
      * Puede recibir como parametro un string con los atributos que se 
@@ -62,25 +83,38 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
         parent::MECON_HTML_Tabla($attrs, $estilo);
     }    
 
         parent::MECON_HTML_Tabla($attrs, $estilo);
     }    
 
+    /**
+     * Establece el prefijo usado para las variables de GET que genera la tabla.
+     * @deprecated No se puede cambiar el prefijo hasta que tengamos variables
+     * estaticas en las clases.
+     */
+    #function setGetVarPrefix($prefix) {
+    #    $this->_getVarPrefix = $prefix;
+    #}
+
+    /**
+     * Obtiene el prefijo usado para las variables de GET que genera la tabla.
+     */
+    function getGetVarPrefix() {
+        return MECON_HTML_TABLADB_GET_VAR_PREFIX;
+    }
+
     /**
      * Agrega un páginador a la tabla, basado en un resultado de una base de datos.
      * Ejemplo:
      * @code
     /**
      * Agrega un páginador a la tabla, basado en un resultado de una base de datos.
      * Ejemplo:
      * @code
-     * $tabla = new MECON_HTML_Tabla();
-     * $result = $db->query('SELECT * FROM tabla');
+     * $tabla = new MECON_HTML_TablaDB('personas', array('width' => '100%'));
+     * $result = $db->query('SELECT nombre, apellido FROM tabla');
      * if (DB::isError($result)) {
      * if (DB::isError($result)) {
-     *      die('Error');
+     *      trigger_error('Error', E_USER_ERROR);
      * }
      * }
+     * // Agrega el paginador por defecto y lo guarda para mostrar solo los
+     * // resultados paginados después.
      * $pager = $tabla->addPager($result);
      * $pager = $tabla->addPager($result);
+     * // Agrega cabecera con los nombres de las columnas.
      * $tabla->addRow(array('Nombre', 'Apellido'), 'cabecera');
      * $tabla->addRow(array('Nombre', 'Apellido'), 'cabecera');
-     * if ($pager->numRows()) {
-     *      while ($row = $pager->fetchRow(DB_FETCHMODE_ASSOC)) {
-     *          $tabla->addRow(array($row['nombre'], $row['apellido']));
-     *      }       
-     * } else {
-     *      $tabla->addRow(array(new MECON_HTML_Error('No se encontraron agentes.')),
-     *          array('colspan' => 2));
-     * }   
+     * // Agrega los resultados paginados de la DB.
+     * $tabla->addRows($pager, array('nombre', 'apellido'));
      * $tabla->display();
      * @endcode
      *
      * $tabla->display();
      * @endcode
      *
@@ -102,15 +136,20 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
      *                    GET) o un string.
      * @param int $limit Parámetro usado para crear el MECON_DB_Pager.
      * @param int $maxpages Parámetro usado para crear el MECON_DB_Pager.
      *                    GET) o un string.
      * @param int $limit Parámetro usado para crear el MECON_DB_Pager.
      * @param int $maxpages Parámetro usado para crear el MECON_DB_Pager.
+     * @param string $getvar Nombre de la variable GET a usar para indicar el número
+     *               de página actual (se le pone el \ref setGetPrefix prefijo)
      *
      * @return MECON_DB_Pager Pager que se puede usar para realizar los fetch de
      *         los resultados de la página actual.
      *
      *
      * @return MECON_DB_Pager Pager que se puede usar para realizar los fetch de
      *         los resultados de la página actual.
      *
-     * @see MECON_DB_Pager.
+     * @see MECON_DB_Pager, addRows().
      */
      */
-    function addPager($result, $tipo = null, $link = null, $limit = 10, $maxpages = 21) {
+    function addPager($result, $tipo = null, $link = null, $limit = 10, $maxpages = 21, $getvar = 'from') {
         // Creo el pager con el resultado.
         // Creo el pager con el resultado.
-        $pager = new MECON_DB_Pager($result, @$_GET['pager_from'], $limit, $maxpages);
+        $pager = (is_array($result))?
+                new MECON_Array_Pager($result, @$_GET[$this->getGetVarPrefix().$getvar], $limit, $maxpages):
+                new MECON_DB_Pager($result, @$_GET[$this->getGetVarPrefix().$getvar], $limit, $maxpages);
+
         // Obtengo un link válido.
         if (!$link) {
             $link = @$_SERVER['PHP_SELF'];
         // Obtengo un link válido.
         if (!$link) {
             $link = @$_SERVER['PHP_SELF'];
@@ -132,22 +171,22 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
         }
         // Me fijo si tiene cada uno de los elementos y los agrego.
         if (in_array('anterior', $tipo) and $pager->numRows() and $pager->currentpage != 1) {
         }
         // Me fijo si tiene cada uno de los elementos y los agrego.
         if (in_array('anterior', $tipo) and $pager->numRows() and $pager->currentpage != 1) {
-            $link->setGetVar('pager_from', $pager->prev);
+            $link->setGetVar($this->getGetVarPrefix().$getvar, $pager->prev);
             $this->addLink('anterior', $link);
         }
         if (in_array('siguiente', $tipo) and $pager->numRows() and $pager->currentpage != $pager->numpages) {
             $this->addLink('anterior', $link);
         }
         if (in_array('siguiente', $tipo) and $pager->numRows() and $pager->currentpage != $pager->numpages) {
-            $link->setGetVar('pager_from', $pager->next);
+            $link->setGetVar($this->getGetVarPrefix().$getvar, $pager->next);
             $this->addLink('siguiente', $link);
         }
         if (in_array('paginas', $tipo) and $pager->numRows() and $pager->numpages > 1) {
             $this->addLink('siguiente', $link);
         }
         if (in_array('paginas', $tipo) and $pager->numRows() and $pager->numpages > 1) {
-            $from = @$_GET['pager_from'];
+            $from = @$_GET[$this->getGetVarPrefix().$getvar];
             $pags = '';
             $lnk = $link->getContents();
             foreach ($pager->pages as $page => $start_row) {
                 if ($start_row == $from) {
                     $pags .= $page;
                 } else {
             $pags = '';
             $lnk = $link->getContents();
             foreach ($pager->pages as $page => $start_row) {
                 if ($start_row == $from) {
                     $pags .= $page;
                 } else {
-                    $link->setGetVar('pager_from', $start_row);
+                    $link->setGetVar($this->getGetVarPrefix().$getvar, $start_row);
                     $link->setContents($page);
                     $pags .= $link->toHtml();
                 }
                     $link->setContents($page);
                     $pags .= $link->toHtml();
                 }
@@ -173,19 +212,13 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
      * Si no hay resultados, muestra un mensaje. Dependiendo de si es se pasa
      * un objeto a usar o no, llama a addRowsObject() o addRowsResult()
      * respectivamente.
      * Si no hay resultados, muestra un mensaje. Dependiendo de si es se pasa
      * un objeto a usar o no, llama a addRowsObject() o addRowsResult()
      * respectivamente.
-     * Ejemplo:
-     * @code
-     * $tabla = new MECON_HTML_TablaDB('agentes', array('width' => '100%'));
-     * $tabla->addRow(array('Nombre', 'Apellido'));
-     * // Supongo que $result tiene un DB_Result.
-     * $tabla->addRows($result, array('nombre', 'cuil'));
-     * $tabla->display();
-     * @endcode
      *
      * @param DB_Result $result Resultados de una consulta.
      * @param array $campos Propiedades del objeto a mostrar.
      * @param mixed $obj Objeto a usar. Puede ser un objeto instanciado o un
      *                   string con el nombre de la clase.
      *
      * @param DB_Result $result Resultados de una consulta.
      * @param array $campos Propiedades del objeto a mostrar.
      * @param mixed $obj Objeto a usar. Puede ser un objeto instanciado o un
      *                   string con el nombre de la clase.
+     *
+     * @see addRowsData(), addRowsIcon(), ejemplo en addPager().
      */
     function addRows($result, $campos, $obj = null) {
         if ($result->numRows()) {
      */
     function addRows($result, $campos, $obj = null) {
         if ($result->numRows()) {
@@ -195,8 +228,12 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
                 $this->addRowsResult($result, $campos, $obj);
             }
         } else {
                 $this->addRowsResult($result, $campos, $obj);
             }
         } else {
-            $id = $this->addRow(array(new MECON_HTML_Error("No se encontraron {$this->_desc}.")));
-            $this->updateCellAttributes($id, 0, array('colspan' => count($campos)));
+            $id = $this->addRow(array(
+                new MECON_HTML_Error("No se encontraron {$this->_desc}.")));
+            $this->updateCellAttributes($id, 0,
+                array('colspan' => count($campos)
+                    + count($this->_prependRowsData)
+                    + count($this->_appendRowsData)));
         }
     }
 
         }
     }
 
@@ -208,11 +245,17 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
      */
     function addRowsResult($result, $campos) {
         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
      */
     function addRowsResult($result, $campos) {
         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
-            $datos = array();
+            $columnas = array();
+            foreach ($this->_prependRowsData as $data) {
+                $columnas[] = $this->_buildCustomColumn($data, $row);
+            }
             foreach ($campos as $campo) {
             foreach ($campos as $campo) {
-                $datos[] = $row[$campo];
+                $columnas[] = $row[$campo];
             }
             }
-            $this->addRow($datos);
+            foreach ($this->_appendRowsData as $data) {
+                $columnas[] = $this->_buildCustomColumn($data, $row);
+            }
+            $this->addRow($columnas);
         }
     }
 
         }
     }
 
@@ -237,14 +280,420 @@ class MECON_HTML_TablaDB extends MECON_HTML_Tabla {
             $this->raiseError('La clase ' . get_class($obj) . ' no tiene un metodo cargar().');
         }
         while ($obj->cargar($result)) {
             $this->raiseError('La clase ' . get_class($obj) . ' no tiene un metodo cargar().');
         }
         while ($obj->cargar($result)) {
-            $datos = array();
+            foreach ($this->_prependRowsData as $data) {
+                $columnas[] = $this->_buildCustomColumn($data, $row);
+            }
+            foreach ($campos as $campo) {
+                $columnas[] = $obj->$campo;
+            }
+            foreach ($this->_appendRowsData as $data) {
+                $columnas[] = $this->_buildCustomColumn($data, $row);
+            }
+            $this->addRow($columnas);
+        }
+    }
+
+    /**
+     * Agrega una columna arbitraria a la tabla basado en valores de una fila.
+     * Ejemplo:
+     * @code
+     * $tabla = new MECON_HTML_TablaDB('personas', array('width' => '100%'));
+     * $result = $db->query('SELECT nombre, apellido, activo FROM tabla');
+     * if (DB::isError($result)) {
+     *      trigger_error('Error', E_USER_ERROR);
+     * }
+     * $tabla->addRow(
+     *      array('Col1', 'Nombre', 'Apellido', 'Activo', 'PopUp1', 'PopUp2'),
+     *      'cabecera');
+     * // Agrega una columna con una leyenda 'El nombre es: {nombre}' al principio.
+     * $tabla->addRowsData('Me llamo %s.', 'nombre', 'prepend');
+     * // Agrega una columna al final con checkbox para seleccionar filas. El
+     * // segundo elemento será procesado por la callback checked_callback().
+     * $tabla->addRowsData('<input type="checkbox" name="datos[%s]" value="1" %s />',
+     *          array('nombre', array('activo', 'checked_callback')));
+     * // Agrega el nombre con un link a un popup (sin javascript).
+     * $tabla->addRowsData(
+     *      new MECON_HTML_Link('popup.php', '%s', array('nombre' => null),
+     *          array('target' => '_blank')),
+     *      'nombre',
+     *      'prepend');
+     * // Agrega el nombre con un link a un popup (con javascript).
+     * $tabla->addRowsData('<a href="popup.php?nombre=%s" '
+     *          . 'onclick="'."javascript:window.open('popup.php?nombre=%s',"
+     *          . "'win_id','width=400,height=400,scrollbars=no');"
+     *          . 'return false;">%s</a>',
+     *      array('nombre', 'nombre', 'apellido'));
+     * // Agrega resultados de la tabla.
+     * $tabla->addRows($result, array('nombre', 'apellido'));
+     * 
+     * 
+     * //Ejemplo utilizando una funcion callback con varios parametros obtenidos
+     * //de la DB y otros argumentos arbitrarios.
+     * $tabla->addRowsData (
+     *      'Mi nombre es: %s, por lo tanto %s', //Formato de la columna a agregar.
+     *      array(                               //Array de campos a incluir en el formato
+     *          'nombre',                        //El dato de este campo reemplazara el primer %s
+     *          //El resultado de la llamada a la funcion nombre_callback que tomo
+     *          //como paramteros los campos de la db que estan dentro del array
+     *          //reemplazara al segundo %s
+     *          array(array('nombre', 'apellido'), 'nombre_callback', array('Sr.', 'Junior'))
+     *      )
+     *  );
+     * 
+     * $tabla->display();
+     *
+     * // Funcion callback para darle formato al campo 'activo'.
+     * // En este caso devuelve 'checked' para indicar que el checkbox está
+     * // activado si activo es true.
+     * function checked_callback($activo) {
+     *      return $activo ? 'checked' : '';
+     * }
+     *
+     * //Funcion callback que acepta mas de un parametro en un array
+     * function nombre_callback($parametros, $argumentos_arbitrarios) {
+     *      list($prefijo, $posfijo) = $argumentos_arbitrarios;
+     *      if ($parametros['nombre'] == 'Juan Carlos' && $parametros['apellido'] == 'Gomez') {
+     *          return "soy el $prefijo Charly $posfijo";
+     *      }
+     *      else {
+     *          return "no soy el $prefijo Charly $posfijo";
+     *      }
+     * }
+     * 
+     * @endcode
+     *
+     * @param mixed $format Si es un string, especifica el formato a usar al
+     *                      estilo de sprintf. Si es un MECON_HTML_Link, se
+     *                      traduce cada variable por GET que empiece con el
+     *                      \ref getGetVarPrefix "prefijo" y cuyo valor sea null
+     *                      al campo correspondiente de la DB:
+     * @code $tabla->addRowsData(new MECON_HTML_Link('abm.php', 'Ver %s',
+     *      array($tabla->getGetVarPrefix().'id' => null), 'nombre'); @endcode
+     *                      Si el valor en vez de ser null es un string, se
+     *                      fija si existe una función con ese nombre para llamar
+     *                      con el campo de la DB como argumento para
+     *                      formatearlo:
+     * @code $tabla->addRowsData(new MECON_HTML_Link('print.php', 'Mostrar',
+     *      array($tabla->getGetVarPrefix().'campo1' => 'callback_campo1'));
+     * function callback_campo1($campo1) {
+     *      return 'El campo1 es '.strtoupper($campo3);
+     * } @endcode
+     *                      Si no existe la función, se toma el string como
+     *                      formato para sprintf para darle formato:
+     * @code $tabla->addRowsData(new MECON_HTML_Link('print.php', 'Ver',
+     *      array($tabla->getGetVarPrefix().'campo1' => 'campo1: %s')); @endcode
+     * @param mixed $campos Campos de la DB a usar como argumentos del sprintf.
+     *                      Puede ser un string para pasar un solo campo sin
+     *                      formato:
+     *                      @code $tabla->addRowsData('%s', 'campo1'); @endcode
+     *                      Si es un array, cada elemento es un campo
+     *                      que puede ser un string representando el nombre de
+     *                      un campo a usar:
+     *                      @code $tabla->addRowsData('%s',
+     *      array('campo1', 'campo2'); @endcode
+     *                      o un array cuyo primer elemento es un string o un
+     *                      array con los nombres de los campos de la db a utilizar
+     *                      y el segundo argumento es una funcion
+     *                      callback a llamar con el valor del campo (o los
+     *                      campos si se paso un array de campos) como
+     *                      argumento para darle formato (si hay un tercer
+     *                      elemento en el array se le pasa como segundo
+     *                      parametro a la callback):
+     *                      @code $tabla->addRowsData('%s',
+     *      array('campo1', array(array('campo2', 'campo3'), 'callback_campo_2_3', 'arg_campo_2_3'))));
+     * function callback_campo_2_3($campos, $arg) {
+     *      return strtoupper($campos['campo2']) . ', ' . strtolower($campos['campo3']) . $arg;
+     * } @endcode
+     *                      Para ver un ejemplo de una callback con muchos
+     *                      parametros ver la descripcion detallada de esta funcion.
+     *                      Si no se encuentra la funcion callback, se toma como
+     *                      un string para formatear el campo con sprintf():
+     *                      @code $tabla->addRowsData('%s', array('campo1',
+     *      array('campo2', 'campo2 = %s')); @endcode
+     * @param string $lugar Indica donde hay que agregar la columna. Puede ser:
+     *                      <tt>'prepend'</tt> o <tt>'append'</tt>:
+     *                      @code $tabla->addRowsData('Hola %s!', 'nombre',
+     *      'prepend'); @endcode
+     *
+     * @warning Este método debe ser llamado antes de llamar a addRows().
+     * @note Las funciones callback toman todas un argumento (el valor del
+     *       campo a formatear) como mínimo. Si se pasa un parametro arbitrario
+     *       recibe un segundo argumento con este parametro extra. Deben devolver
+     *       un string con el campo formateado.
+     */
+    function addRowsData($format, $campos = array(), $lugar = 'append') {
+        if (!is_array($campos)) {
+            $campos = array($campos);
+        }
+        switch (strtolower($lugar)) {
+            case 'prepend':
+                $this->_prependRowsData[] = array($format, $campos);
+                break;
+            case 'append':
+                $this->_appendRowsData[] = array($format, $campos);
+                break;
+            default:
+                $this->raiseError('Lugar incorrecto. Lugares soportados: append, prepend.');
+        }
+    }
+
+    /**
+     * Contruye una columna personalizada.
+     *
+     * @param array $data Datos sobre la columna, en el formato especificado
+     *                    para un elemento del array usado en _prependRowsData.
+     * @param mixed $row Fila de un resultado de una base de datos. Puede ser un
+     *                   array asociativo o un objeto (en cuyo caso cada campo
+     *                   debe ser un atributo del mismo).
+     *
+     * @return mixed Columna formateada para agregar a la tabla.
+     *
+     * @protected
+     */
+    function _buildCustomColumn($data, $row) {
+        list($format, $campos) = $data;
+        // Si tiene formatos y argumentos.
+        if ($campos) {
+            // Si el formato es un MECON_HTML_Link, uso como formato a
+            // su contenido.
+            if (is_a($format, 'mecon_html_link')) {
+                $args = array($format->getContents());
+            } else {
+                $args = array($format);
+            }
+            // Proceso cada agumento.
+            foreach ($campos as $campo) {
+                // Si el agumento es un array, usa una callback para
+                // darle formato.
+                if (is_array($campo)) {
+                    @list($campo, $callback, $callback_args) = $campo;
+                }
+                if (is_array($row)) {
+                    if (is_array($campo)) {
+                        foreach ($campo as $c) {
+                            $tmp[$c] = $row[$c];
+                        }
+                        $campo = $tmp;
+                    }
+                    else {
+                        $campo = $row[$campo]; // Es un campo de un array.
+                    }
+                } else { //$row es un objeto
+                    if (is_array($campo)) {
+                        foreach ($campo as $c) {
+                            $tmp[$c] = $row->$c;
+                        }
+                        $campo = $tmp;
+                    }
+                    else {
+                        $campo = $row->$campo; // Es un atributo de un objeto.
+                    }
+                }
+                // Si usa callback, cambio el campo por el resultado del
+                // llamado a su callback.
+                if (isset($callback)) {
+                    if(function_exists($callback)) {
+                        $campo = $callback($campo, $callback_args);
+                    } else {
+                        //Si no existe la funcion de callback usa el callback como
+                        //formato y los campos como argumentos para el sprintf
+                        array_unshift($campo, $callback);
+                        $campo = call_user_func_array('sprintf', $campo);
+                    }
+                }
+                unset($callback);
+                // Agrego argumento procesado a la lista de argumentos.
+                $args[] = $campo;
+            }
+            // Si es un link, le seteo los contenidos procesados.
+            if (is_a($format, 'mecon_html_link')) {
+                $format->setContents(call_user_func_array('sprintf', $args));
+            // Si no formateo la cadena con los argumentos procesados.
+            } else {
+                $format = call_user_func_array('sprintf', $args);
+            }
+        }
+        // Si es un link, traduce las variables GET.
+        if (is_a($format, 'mecon_html_link')) {
+            $format = $this->_translateGetVars($format, $row);
+        }
+        // devuelve la columna.
+        return $format;
+    }
+
+    /**
+     * Traduce las variables GET de un link.
+     * Puede formatearlas con printf() o llamando una callback.
+     *
+     * @param MECON_HTML_Link $link Link con las variables GET a formatear.
+     * @param mixed $row Fila de un resultado de una base de dotos. Puede ser un
+     *                   array asociativo o un objeto (en cuyo caso cada campo
+     *                   debe ser un atributo del mismo).
+     *
+     * @return MECON_HTML_Link Link con las variables GET traducidas.
+     *
+     * @protected
+     */
+    function _translateGetVars($link, $row) {
+        $vars = $link->getGetVars();
+        $prefix = $this->getGetVarPrefix();
+        foreach ($vars as $var => $val) {
+            if (preg_match("/^$prefix(.+)$/", $var, $m)) {
+                $campo = $m[1];
+                $campo = is_array($row) ? $row[$campo] : $row->$campo;
+                // Si no tiene valor, se lo reemplaza por el
+                // valor del campo.
+                if ($val === null) {
+                    $link->setGetVar($var, $campo);
+                // Si existe una funcion, se la usa para obtener
+                // el formato.
+                } elseif (function_exists($val)) {
+                    $link->setGetVar($var, $val($campo));
+                // Si no es ni null ni link, lo toma como
+                // formato para el sprintf
+                } else {
+                    $link->setGetVar($var, sprintf($val, $campo));
+                }
+            }
+        }
+        return $link;
+    }
+
+    /**
+     * Agrega un ícono predefinido a la tabla.
+     * Ejemplo:
+     * @code
+     * $tabla = new MECON_HTML_TablaDB('personas', array('width' => '100%'));
+     * $result = $db->query('SELECT id, nombre, apellido, activo FROM tabla');
+     * if (DB::isError($result)) {
+     *      trigger_error('Error', E_USER_ERROR);
+     * }
+     * $tabla->addRow(array('Col1', 'Nombre', 'Apellido', 'Modificar', 'Borrar',
+     *      'Agregar'), 'cabecera');
+     * // Agrega ícono de modificar que apunta a modificar.php y pasa el 'id'.
+     * $tabla->addRowsIcon('modificar', 'id', 'modificar.php');
+     * // Agrega ícono de eliminar desactivado.
+     * $tabla->addRowsIcon('eliminar', 'id', 'borrar.php', false);
+     * // Agrega ícono con una flecha que apunta a agregar.php, pasa 2 campos
+     * // por GET y se activa o desactiva segun el campo de la DB 'activo'.
+     * $tabla->addRowsIcon('ir', array('id', 'nombre'), 'ver.php', 'activo');
+     * // Agrega resultados de la tabla.
+     * $tabla->addRows($result, array('nombre', 'apellido'));
+     * $tabla->display();
+     * @endcode
+     *
+     * @param string $id Identificador del tipo de ícono a agregar. Puede ser:
+     *                   <ul>
+     *                     <li><tt>'modificar'</tt>: Ícono de modificar.</li>
+     *                     <li><tt>'eliminar'</tt>: Ícono de eliminar.</li>
+     *                     <li><tt>'ir'</tt>: Flecha hacia la derecha.</li>
+     *                   </ul>
+     * @param mixed $campos Campos de la DB a usar para generar el link. Estos
+     *                      campos serán pasados por GET a la página destino.
+     *                      Cada campo es pasado como la variable GET compuesta
+     *                      por el @ref getGetVarPrefix "prefijo" más el nombre
+     *                      del campo (ver parámetro $campos de addRowsData()
+     *                      para conocer de que formas se puede formatear un
+     *                      campo).
+     * @param mixed $link Si es un string, se usa como URL del link a generar.
+     *                    Si es un MECON_HTML_Link, se usa como base para el
+     *                    link a generar y se le va agregando las variables de
+     *                    GET generadas por el parámetro $campos (el link es
+     *                    procesado de la misma forma en que es procesado el
+     *                    parámetro $formato en addRowsData() con la excepción
+     *                    de que el contenido del Link no es tomado en cuenta).
+     * @param mixed $activo Si es una variable booleana, si es true, se pone el
+     *                      ícono activado (con un link), si es false se pone el
+     *                      ícono desactivado (sin link). Si es un string se lo
+     *                      utiliza como el nombre de un campo de la DB y se
+     *                      activa o desactiva el ícono según este campo evalue
+     *                      a true o false respectivamente.
+     * @param string $lugar Indica donde hay que agregar la columna. Puede ser:
+     *                      <tt>'prepend'</tt> o <tt>'append'</tt>.
+     *
+     * @warning Este método debe ser llamado antes de llamar a addRows().
+     */
+    function addRowsIcon($id, $campos = array(), $link = null, $activo = true,
+            $lugar = 'append') {
+        if (!$campos) {
+            $campos = array();
+        }
+        if (is_string($campos)) {
+            $campos = array($campos);
+        }
+        if (!$link) {
+            $link = @$_SERVER['PHP_SELF'];
+        }
+        if (is_string($link)) {
+            $link = new MECON_HTML_Link($link, '');
+        }
+        // Traducción para compatibilidad para atrás.
+        switch ($id) {
+            case 'no_modificar':
+                $id = 'modificar';
+                $activo = false;
+                break;
+            case 'borrar':
+                $id = 'eliminar';
+                break;
+            case 'no_borrar':
+                $id = 'eliminar';
+                $activo = false;
+                break;
+        }
+        if ($activo === true) {
+            $img = new MECON_HTML_Icon($id, $link, null,
+                array('title' => ucfirst($id)));
+            $l = $img->getLink();
             foreach ($campos as $campo) {
             foreach ($campos as $campo) {
-                $datos[] = $obj->$campo;
+                $format = null;
+                if (is_array($campo)) {
+                    list($campo, $format) = $campo;
+                }
+                $l->setGetVar($this->getGetVarPrefix().$campo, $format);
             }
             }
-            $this->addRow($datos);
+            $this->addRowsData($l, array(), $lugar);
+        } elseif ($activo === false) {
+            $img = new MECON_HTML_Icon($id.'_des', null, '-',
+                array('title' => ucfirst($id)));
+            $this->addRowsData($img, array(), $lugar);
+        } else {
+            $campos[] = $activo;
+            $this->addRowsData('%s', array(array($campos,
+                'MECON_HTML_TablaDB_callback_addRowsIcon',
+                array($id, $link, $activo))), $lugar);
         }
     }
 
 }
 
         }
     }
 
 }
 
+/**
+ * Callback para activar o desactivar un ícono según un campo de la DB.
+ *
+ * @param $campos Array asociativo con los datos de la DB para la fila actual.
+ * @param $args   Array de pámetros arbitrarios: 'tipo', 'link', 'activo'.
+ *                tipo:   tipo de link: 'modificar', 'eliminar', 'ir'.
+ *                link:   link a donde apunta el ícono si está activo.
+ *                activo: indica el nombre del campo a evaluar para mostrar
+ *                        el ícono activo o inactivo.
+ * @return Campo formateado.
+ * @protected
+ */
+function MECON_HTML_TablaDB_callback_addRowsIcon($campos, $args) {
+    list($tipo, $link, $activo) = $args;
+    if ($campos[$activo]) {
+        $img = new MECON_HTML_Icon($tipo, $link, null,
+            array('title' => ucfirst($tipo)));
+        $l = $img->getLink();
+        foreach ($campos as $campo => $valor) {
+            $l->setGetVar(MECON_HTML_TablaDB::getGetVarPrefix().$campo, $valor);
+        }
+        return $l->toHtml();
+    } else {
+        $img = new MECON_HTML_Icon($tipo.'_des', null, '-',
+            array('title' => ucfirst($tipo)));
+        return $img->toHtml();
+    }
+}
+
 ?>
 ?>