dimarts, 19 de juliol del 2011

BeanShell, scripting per a Java

BeanShell (bsh) és un interpret de Java estès amb característiques de llenguatge d'scripting. BeanShell està desenvolupat en Java i s'entrega i es pot executar com aplicació standalone des del jar, però també es pot afegir com a llibreria en una aplicació standalone Java que incorporaria d'aquesta forma un llenguatge d'scripting per a fer macros, per exemple.

A tall d'exemple, BeanShell és un dels llenguatges de macros que incorpora OpenOffice.org/LibreOffice (OOo/LO). També és el llenguatge de macros de l'editor JEdit, també es pot trobar com a llenguatge de macros a l'IDE de Java NetBeans.

Encastat a una aplicació Java, i pel fet d'executar-se en la mateixa JVM de l'aplicació hoste, és capaç d'interactuar amb els objectes de l'aplicació. Com que és interpretat i no cal compilar els scripts de bsh obre una porta a l'extensió de l'aplicació hoste. I amb tota la potència de Java, doncs BeanShell és capaç d'importar packages java.

BeanShell és un jar que ocupa menys de 300KB. És considerablement més petit, doncs, que alternatives més potents com Groovy (De fet, Groovy va molt més enllà del que seria un llenguatge d'scripting. Per exemple, el framework  Grails  està basat en Groovy).

Els punts forts de BeanShell són aquests: és java, ofereix facilitats per a l'scripting, és petit, és encastable i és fa servir a OOo/LO, entre d'altres.

Punts dèbils? malgrat que la llista de correu de desenvolupadors i d'usuaris de BeanShell a SourceForge mostra certa activitat enguany, la llista d'anuncis de noves versions resta aturada des de 2005 (justament quan el JCP aprovava la creació d'una JSR per al BeanShell). El punt dèbil és, doncs, que no ha evolucionat des de fa massa temps.

En tot cas, el fet de ser un interpret de Java fa que sigui immediatament utilitzable per programadors d'aquest llenguatge.

L'escenari d'us de BeanShell seria, doncs, aquell en el que cal incorporar un llenguatge de macros a una aplicació java que sigui lleuger i, a la vegada, d'aplicació immediata.

La sintaxi del llenguatge és la de Java. Res a descobrir, doncs. Tanmateix, hi han afegides característiques orientades a l'scripting, com el "tipatge relaxat", o comandes específiques  per a entrada sortida per consola

Les referències són, per una banda el manual d'usuari; i per l'altre, el javadoc de beanshell. També és recomanable veure la presentació amb diapositives (en format .pdf) Un punt d'entrada és l'anàlisi dels exemples que també es poden trobar a la web.

Si hem instal·lat bsh des del Centre de Programari de l'Ubuntu, o si tenim instal·lat l'OpenOffice.org/LibreOffice, és possible que trobem el bsh.jar a les ubicacions següents:

/usr/share/java/bsh-2.0b4.jar
/usr/share/java/bsh.jar
/usr/lib/openoffice/basis3.2/program/classes/bsh.jar

Per engegar l'interpret n'hi ha prou amb escriure bsh a la línia de comandes. Però també el podem engegar com la aplicació Java que és:

java -jar /usr/share/java/bsh.jar bsh.

en aquest punt ja podem introduir ordres. tanmateix és més pràctic fer un script:

Fem la prova canònica. Creo l'script hello.bsh

a = "hola ";
b = " món!";
print (a + b);

i l'executo

bsh ./hello.bsh

hola  món!

Com era d'esperar... L'script anterior en bsh és indistingible d'altres llenguatges d'script que disposen de la comanda print.

Haviem dit que bsh és java amb característiques d'script. Vet aquí la primera: no ha calgut definir el tipus de les variables.

Hauria pogut ser més rigurós. Amplio l'script amb línies que són Java inequívocament:

a = "hola ";
b = " món!";
print (a + b);

String s_Nom = "Serveix TIC i Programari Lliure";
String s_llocweb = " (http://apuntstecnologia.blogspot.com/)";

System.out.println(s_Nom + ", " + s_llocweb);

System.out.println("Variable no inicialitzada: " + sNom + ", " + s_LlocWeb);

i el resultat és:

albert@atenea:~$ bsh ./hello.bsh
hola  món!
Serveix TIC i Programari Lliure,  (http://apuntstecnologia.blogspot.com/)
Variable no inicialitzada: void, void


void, en comptes de null o "". A bsh es pot verificar si una variable està inicialitzada comparant-la amb "void".

Més coses: els "scripted objects", una forma de definir objectes a l'estil de com ho fan altres llenguatges d'scripts (recorda Javascript) que aprofiten les estructures de blocs.

ClasseBsh() {
   propietat1 = 1;
   propietat2 = "un text";  
   
   Metode1() {
      print("Aquest és el mètode 1");
   }

   Metode2() {
      print("Aquest és el mètode 2");
   }

   Metode3() {
       cbsh2 = ClasseBsh2();
       print("cbsh2.propietat1: " + cbsh2.propietat1);
       print("cbsh2.propietat2: " + cbsh2.propietat2);
       cbsh2.Metode1();
       cbsh2.Metode2();
   }

   
   ClasseBsh2() {
       propietat1 = 1;
       propietat2 = "un altre text";   
       
       Metode1() {
           print("Aquest és el mètode 1 intern");
       }

       Metode2() {
           print("Aquest és el mètode 2 intern");
       }

      return this;
    }

    return this;
}

cbsh1 = ClasseBsh();

print("cbsh1.propietat1: " + cbsh1.propietat1);
print("cbsh1.propietat2: " + cbsh1.propietat2);
cbsh1.Metode1();
cbsh1.Metode2();
cbsh1.Metode3();

El resultat és:

albert@atenea:~$ bsh ./classes.bsh
cbsh1.propietat1: 1
cbsh1.propietat2: un text
Aquest és el mètode 1
Aquest és el mètode 2
cbsh2.propietat1: 1
cbsh2.propietat2: un altre text
Aquest és el mètode 1 intern
Aquest és el mètode 2 intern

Remarcar la sintaxi simplificada, i també com es poden fer classes dins de classes sense ĺímit de nivell.

Com encastar BeanShell a una aplicació Java?

Res més senzill. Podem fer una petita classe java que carrega un interpret de BeanShell que executa un script:

package com.sticipl.proves;

public class ProvaBshRun {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ProvaBshRun();
    }

    public ProvaBshRun() {
        try {
            // carrega script i l'executa
            System.out.println("carrega script i l'executa");
            Interpreter beanshellInterpret = new Interpreter();
            beanshellInterpret.source("/home/albert/hello.bsh"); 
      
        } catch(Exception e) {
            System.out.println("Error: " + e.toString());
        }
    }
}

 

Per a fer l'execució més senzilla, empaqueto la classe anterior en un jar. Faig servir el següent build.xml per a l'ant















<project name="provabsh" default="build" basedir=".">
  <description>
  proves amb beanshell
  </description>

  <!-- estableix propietats globals -->
  <property name="src" location="src"/>
  <property name="bin" location="bin"/>
  <property name="build" location="build"/>
  <property name="lib"  location="lib"/>


  <target name="init">
    <!-- time stap -->
    <tstamp/>
    <!-- Crea el directory bin utilitzat en la compilació -->
    <mkdir dir="${bin}"/>
  </target>


  <target name="compile" depends="init" description="compila els fitxers font" >
    <!-- Compila les fonts java de ${src} en ${build} -->
    <javac srcdir="${src}" destdir="${bin}">
      <classpath>
       <pathelement location="${lib}/bsh-2.0b4.jar"/>
      </classpath>
   </javac>
  </target>

  <target name="build" depends="compile" description="genera el jar">
    <!-- Crea el directori de distribució -->
    <mkdir dir="${build}"/>

    <jar jarfile="${build}/provabsh.jar" basedir="${bin}">
      <include name="**/*.class"/>
      <manifest>
        <attribute name="Main-Class" value="com.sticipl.proves.ProvaBshRun"/>
          <attribute name="Class-Path" value="bsh-2.0b4.jar"/>
      </manifest>
    </jar>
     
      <copy file="${lib}/bsh-2.0b4.jar" todir="${build}" />
  </target>

</project>


Amb el build.xml anterior obtinc una carpeta build on he deixat el jar provabsj.jar que conté la classe ProvaBshRun. El manifest del jar indica que cal fer servir la llibreria bsh-2.0b4.jar.

Puc executar la classe amb:

albert@atenea:~/wk-java/ProvaBsh/build$ java -jar ./provabsh.jar

o bé amb:

albert@atenea:~/wk-java/ProvaBsh/build$ java -jar -cp ./bsh-2.0b4.jar ./provabsh.jar

i el resultat de l'execució és:

carrega script i l'executa
hola  món!
Serveis TIC i Programari Lliure,  (http://apuntstecnologia.blogspot.com/)
Variable no inicialitzada: void, void
data: Tue Jul 19 18:38:08 CEST 2011


Un cop carregat l'script també es poden manipular-ne els mètodes i propietats. Per exemple, carrego l'script classes.bsh i n'executo mètodes i en canvio propietats:

package com.sticipl.proves;

import bsh.Interpreter;
import java.util.Date;

public class ProvaBshRun {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ProvaBshRun();
    }

    public ProvaBshRun() {
        Interpreter beanshellInterpret = new Interpreter();

        try {
            // Avaluació d'instruccions i expressions
            // Carrega script i en modifica propietats
            System.out.println("Carrega script");
            beanshellInterpret.source("/home/albert/classes.bsh");    
          
            int  iPropietat1 = ((Integer) beanshellInterpret.get("cbsh1.propietat1")).intValue();
            String sPropietat2 = (String) beanshellInterpret.get("cbsh1.propietat2");
            System.out.println("iPropietat1: " + iPropietat1);
            System.out.println("sPropietat2: " + sPropietat2);
           
           
            iPropietat1 = 25;
            beanshellInterpret.set("cbsh1.propietat1", iPropietat1);
            sPropietat2 = "aquest és el text canviat des de l'aplicació";
            beanshellInterpret.set("cbsh1.propietat2", sPropietat2);
            System.out.println("des de l'aplicació");
            System.out.println("iPropietat1: " + iPropietat1);
            System.out.println("sPropietat2: " + sPropietat2);   
            System.out.println("des de beanshell");
            beanshellInterpret.eval("print(\"cbsh1.propietat1: \" + cbsh1.propietat1);");
            beanshellInterpret.eval("print(\"cbsh1.propietat2: \" + cbsh1.propietat2);");
           
            System.out.println("Executa mètode 1:" );
            beanshellInterpret.eval("cbsh1.Metode1();");
            System.out.println("Executa mètode 2:" );
            beanshellInterpret.eval("cbsh1.Metode2();");
            System.out.println("Executa mètode 3:" );
            beanshellInterpret.eval("cbsh1.Metode3();");
        } catch(Exception e) {
            System.out.println("Error: " + e.toString());
        }
    }
}







El resultat de l'anterior és

Carrega script
cbsh1.propietat1: 1
cbsh1.propietat2: un text
Aquest és el mètode 1
Aquest és el mètode 2
cbsh2.propietat1: 1
cbsh2.propietat2: un altre text
Aquest és el mètode 1 intern
Aquest és el mètode 2 intern
iPropietat1: 1
sPropietat2: un altre text
des de l'aplicació
iPropietat1: 25
sPropietat2: aquest és el text canviat des de l'aplicació
des de beanshell
cbsh1.propietat1: 25
cbsh1.propietat2: aquest és el text canviat des de l'aplicació
Executa mètode 1:
Aquest és el mètode 1
Executa mètode 2:
Aquest és el mètode 2
Executa mètode 3:
cbsh2.propietat1: 1
cbsh2.propietat2: un altre text
Aquest és el mètode 1 intern
Aquest és el mètode 2 intern



En el jar de BeanShell es poden trobar classes per a l'execució remota d'scripts, i també per l'execució en mode servlet. Deixo per a futurs posts la revisió d'aquestes opcions.

En resum s'ha presentat l'aplicació BeanShell i les seves característiques que més immediatament es poden utilitzar en aplicacions java.

dissabte, 16 de juliol del 2011

Fer servir zenity per a construir scripts bash amb interfície gràfica

La creació d'scripts de shell és una tasca habitual en l'administració i explotació de sistemes Unix. En algunes ocasions pot ser que calgui la interacció amb l'usuari. Per exemple, la presentació de menús d'opcions o l'usuari ha de triar què vol fer.

A Linux Ubuntu hom pot trobar eines com el programa Dialog que permet crear elements de interfície gràfica com caixes de text, llistes, botons de sel·lecció... en mode de text. Dialog es feia servir, per exemple, en els instal·ladors de moltes distribucions.

Una opció alternativa és fer servir Zenity. Zenity és la re-escriptura de GDialog, que al seu torn era la versió GNOME de Dialog. Zenity proporciona una forma senzilla de crear interfícies gràfiques per a scripts.

Zenity es pot instal·lar des del Centre de Programari de l'Ubuntu, si cal.

Anem a fer alguns experiments amb aquesta eina. Primer de tot cal conéixer la versió que tenim instal·lada i les opcions.

La versió s'obté amb zenity --version. En el meu cas és la 2.30.

Les diferents opcions s'obtenen amb: zenity --help-all a la línia d'ordres i el resultat és:

Forma d'ús:
  zenity [OPCIÓ...]

Opcions d'ajuda:
  -h, --help                            Mostra les opcions d'ajuda
  --help-all                            Mostra totes les opcions d'ajuda
  --help-general                        Mostra les opcions generals
  --help-calendar                       Mostra les opcions del calendari
  --help-entry                          Mostra les opcions de l'entrada de text
  --help-error                          Mostra les opcions d'error
  --help-info                           Mostra les opcions d'informació
  --help-file-selection                 Mostra les opcions del selector de fitxers
  --help-list                           Mostra les opcions de llistes
  --help-notification                   Mostra les opcions de la icona de notificació
  --help-progress                       Mostra les opcions del progrés
  --help-question                       Mostra les opcions de preguntes
  --help-warning                        Mostra les opcions d'avisos
  --help-scale                          Mostra les opcions de l'escala
  --help-text-info                      Mostra les opcions de text informatiu
  --help-misc                           Mostra les opcions miscel·lànies
  --help-gtk                            Mostra les opcions del GTK+

General options
  --title=TÍTOL                         Estableix el títol del diàleg
  --window-icon=CAMÍ D'ICONA            Estableix la icona de la finestra
  --width=AMPLADA                       Estableix l'amplada
  --height=ALÇADA                       Estableix l'alçada
  --timeout=TEMPS D'ESPERA              Estableix el temps d'espera del diàleg (en segons)

Calendar options
  --text=TEXT                           Estableix el text del diàleg
  --day=DIA                             Estableix el dia del calendari
  --month=MES                           Estableix el mes del calendari
  --year=ANY                            Estableix l'any del calendari
  --date-format=PATRÓ                   Estableix el format de la data de tornada

Text entry options
  --text=TEXT                           Estableix el text del diàleg
  --entry-text=TEXT                     Estableix el text de l'entrada
  --hide-text                           Amaga el text de l'entrada

Error options
  --text=TEXT                           Estableix el text del diàleg
  --no-wrap                             No habilites l'ajustament del text

Info options
  --text=TEXT                           Estableix el text del diàleg
  --no-wrap                             No habilites l'ajustament del text

File selection options
  --filename=NOM DE FITXER              Estableix el nom del fitxer
  --multiple                            Permet la selecció de múltiples fitxers
  --directory                           Activa la selecció de només directoris
  --save                                Activa el mode d'estalvi
  --separator=SEPARADOR                 Estableix el caràcter de separació de la sortida
  --confirm-overwrite                   Confirmeu la selecció del fitxer si el nom del fitxer ja existeix
  --file-filter=PATRÓ 1 PATRÓ 2 ...     Estableix un filtre per al nom de fitxer

List options
  --text=TEXT                           Estableix el text del diàleg
  --column=COLUMNA                      Estableix la capçalera de la columna
  --checklist                           Utilitza quadres de verificació per a la primera columna
  --radiolist                           Utilitza botons de grup per a la primera columna
  --separator=SEPARADOR                 Estableix el caràcter de separació de la sortida
  --multiple                            Permet la selecció de múltiples files
  --editable                            Permet canvis al text
  --print-column=NOMBRE                 Imprimeix una columna específica (el valor per defecte és 1. Es pot usar 'ALL' per a imprimir totes les columnes)
  --hide-column=NOMBRE                  Amaga una columna específica
  --hide-header                         Oculta les capçaleres de la columna

Notification icon options
  --text=TEXT                           Estableix el text de la notificació
  --listen                              Espera ordres de l'entrada estàndard

Progress options
  --text=TEXT                           Estableix el text del diàleg
  --percentage=PERCENTATGE              Estableix el percentatge inicial
  --pulsate                             Barra de progrés parpellejant
  --auto-close                          Tanca el diàleg quan s'arribi al 100%
  --auto-kill                           Mata el procés para si es prem el botó de cancel·lar

Question options
  --text=TEXT                           Estableix el text del diàleg
  --ok-label=TEXT                       Estableix l'etiqueta del botó D'acord
  --cancel-label=TEXT                   Estableix l'etiqueta del botó Cancel·la
  --no-wrap                             No habilites l'ajustament del text

Warning options
  --text=TEXT                           Estableix el text del diàleg
  --no-wrap                             No habilites l'ajustament del text

Scale options
  --text=TEXT                           Estableix el text del diàleg
  --value=VALOR                         Estableix un valor inicial
  --min-value=VALOR                     Estableix el valor mínim
  --max-value=VALOR                     Estableix el valor màxim
  --step=VALOR                          Estableix el valor dels augments
  --print-partial                       Imprimeix valors parcials
  --hide-value                          Amaga el valor

Text information options
  --filename=NOM DE FITXER              Obre un fitxer
  --editable                            Permet canvis al text

Miscellaneous options
  --about                               Quant a zenity
  --version                             Imprimeix la versió

Opcions del GTK+
  --class=CLASS                         Program class as used by the window manager
  --name=NAME                           Program name as used by the window manager
  --screen=SCREEN                       X screen to use
  --sync                                Make X calls synchronous
  --gtk-module=MODULES                  Load additional GTK+ modules
  --g-fatal-warnings                    Make all warnings fatal

Opcions de l'aplicació:
  --calendar                            Mostra el diàleg de calendari
  --entry                               Mostra el diàleg d'entrada de text
  --error                               Mostra el diàleg d'error
  --info                                Mostra el diàleg d'informació
  --file-selection                      Mostra el diàleg de selecció de fitxers
  --list                                Mostra el diàleg de llista
  --notification                        Mostra una notificació
  --progress                            Mostra el diàleg d'indicació de progrés
  --question                            Mostra el diàleg de pregunta
  --warning                             Mostra el diàleg d'avís
  --scale                               Mostra el diàleg d'escala
  --text-info                           Mostra el diàleg de text informatiu
  --display=DISPLAY                     X display to use


Anem a provar-los un per un:

Mostrar el diàleg de calendari:
zenity --calendar




Mostrar una caixa d'entrada de text
zenity --entry --text="Entra un text de prova"



El següent script mostra com obtenir el text introduït

#!/bin/bash

textPregunta="Text de la pregunta"
textPredet="Text predeterminat a l'entrada"
textTitol="Títol de la finestra"

resp=$(/usr/bin/zenity --entry --text="$textPregunta" --entry-text="$textPredet" --title="$textTitol" --width=400 --height=200)

echo "la meva resposta ha estat: $resp"



Mostrar una finestra de missatge d'error
zenity --error --text="Descripció de l'error"



Mostrar el diàleg de sel·lecció de fitxers
zenity --file-selection


Mostrar una finestra amb un text informatiu
zenity --info --text="Aquest és el text informatiu"


Mostrar una llista de sel·lecció
zenity --list --text="Llista de prova" \
       --column="ID" --column="Nom" --column="Valor" \
       "1" "nom1" "valor1" \
       "2" "nom2" "valor2" \
       "3" "nom3" "valor3" \
       "4" "nom4" "valor4"



Mostrar una icona de notificació al quadre del Gnome
zenity --notification  --text="Text de la notificació"



Mostrar una barra de progrés. El truc per a que funcioni és el tub (pipe) que alimenta la progressió de la barra.

(
for i in {1..100}
do
   echo $i
done
) | zenity --progress --text="Exemple de barra de progrés" --auto-close --percentage=0



Demanar a l'usuari si sí o si no a una pregunta.

if zenity --question --text="Vols continuar?" --ok-label="Sí, està molt interessant" --cancel-label="No, m'avorreixo com una ostra"
then
    zenity --info --text="Ok, doncs seguim."
else
    zenity --error --text="Cap problema, un altre dia serà."
fi

Mostrar un fitxer de text
zenity --text-info --filename="help.txt" --height=400 --width=500



Mostrar un text d'alerta. Adonem-nos que zenity ens proporciona caixes de notificació específiques de info, warning i error, que són els tres nivells que es fan servir més habitualment per a classificar per importància o gravetat els missatges de les aplicacions.
zenity --warning --text="Aquest és un text d'alerta"



Finalment, obtenir un valor numèric dins un rang
zenity --scale --text="Quants anys tens?" --min-value=0 --max-value=150

divendres, 15 de juliol del 2011

Taules amb cantonades rodones (reprise)

En un post anterior vaig explicar com  fer caixes amb els cantons rodons amb HTML.

En aquella ocasió la solució es basava en taules HTML aplicant estils a etiquetes <table> <tr> i <td>.

En ocasions , un enfocament com l'anterior pot ser necessari, perquè hi han un munt de pàgines web que fan servir, o han fet servir, les taules per a maquetar-ne la presentació, i pot ser que ens calgui retocar-les.

Des de fa temps, però, la solució amb taules es considera inadequada. Les taules HTML només haurien de fer-se servir per presentar dades en format tabular, i formatar-les amb css.

Per a maquetar, la recomanació general és fer servir capes (etiquetes <div>). Per al cas concret de taules amb cantons rodons, vet aquí solucions possibles.

Si em cal crear els gràfics corresponents a les caixes amb els cantons rodons, faig servir la combinació de Inkscape i Gimp. Inkscape permet crear caixes amb cantons rodons, especificant mides i radis dels cantons,  aplicar diferents efectes i exportar les caixes a format png. Després, per retallar les diferents cantonades, les o tapes, o els costats, es pot fer servir el Gimp, per exemple.

OpenOffice.org/LibreOffice Draw també permet crear caixes amb els cantons rodons amb l'eina de dibuix caixa i fent, després Format-Posició i Mida i ajustant el radi a la pestanya Inclinació i Radi de la Cantonada. La pega de fer servir aquesta eina és que no disposa de la unitat "píxel", d'us comú al disseny web. Si la fem servir segurament ens caldrà fer una conversió prèvia a les unitats de treball OOo/LO. Per exemple, fer servir punts, la conversió és 3pt aprox. igual a  4px.

El cas trivial és que coneixem d'antuvi la mida que tindrà la taula. En aquest cas, n'hi ha prou amb fer-servir la caixa de background d'un div:

<div class="caixa">Compte amb no sortir-se'n dels
marges pre-establerts.<br>
<ul>
  <li>ítem 1</li>
  <li>ítem 2</li>
  <li>ítem 3</li>
  <li>ítem 4</li>
  <li>ítem 5</li>
  <li>ítem 6</li>
  <li>ítem 7</li>
</ul>
</div>

i tindré la següent definició per a la class caixa:

.caixa {
  border-style: none;
  margin: 0px;
  padding: 5px;
  width: 401px;
  background-image: url(http://localhost/albert/prova01/img/quadre401x201px.gif);
  background-repeat: no-repeat;
  height: 201px;
  font-family: Arial,Helvetica,sans-serif;
  color: #000099;
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
}

On la imatge és aquesta:


Pot ser útil  crear caixes que es redimensionin automàticament:

Aquesta és una caixa que pot  créixer en vertical. Cal fer tres capes: una capa per la tapa superior, una capa central, i una capa per a la tapa inferior.

<div class="topbox">&nbsp;</div>

<div class="midbox">exemple de caixa que port créixer en
vertical. Només cal anar afegint text per veure com creix sense haver
de fer res més.<br>
</div>

<div class="bottombox">&nbsp;</div>

Les css corresponents:

.topbox {
  background-image: url(img/top-quadre301x12px.png);
  width: 301px;
  height: 12px;
  background-repeat: no-repeat;
}
.midbox {
  padding: 5px;
  background-image: url(img/bg-quadre301x1px.png);
  width: 301px;
  font-family: Arial,Helvetica,sans-serif;
  font-size: 25px;
  background-repeat: repeat-y;
}
.bottombox {
  width: 301px;
  background-repeat: no-repeat;
  background-image: url(img/bottom-quadre301x12px.png);
  height: 12px;

Les mides de les imatges han de coincidir amb les dels div.

Les imatges de les tapes superior i inferior:

i la imatge central que és d'1 pixel d'amplada i que aconsegueix emplenar la capa en vertical amb el background-repeat: repeat-y
 

De forma similar, es pot crear una caixa capaç d'adaptar-se, fins un tamany màxim, a divrerents llargades horitzontals. Em cal una tapa a l'esquerra, una capa central i la tapa de la dreta. Aleshores cal indicar que la imatge central ha de repetir-se en horitzontal.
Com cal posar les capes una a continuació de l'altre, cal indicar que "floten":

<div class="leftbox">&nbsp;</div>

<div class="midbox2">exemple de caixa que pot créixer en
horitzontal fins un màxim de 900px. Cal vigilar perquè tindrà un màxim
de línies útils.<br>
</div>

<div class="rightbox">&nbsp;</div>

Els css corresponents són:

.leftbox {
  background-image: url(img/left-quadre12x151px.png);
  background-repeat: no-repeat;
  height: 151px;
  width: 12px;
  float: left;
}
.midbox2 {
  padding: 5px;
  background-repeat: repeat-x;
  float: left;
  font-family: Arial,Helvetica,sans-serif;
  background-image: url(img/bg-quadre1x151px.png);
  height: 151px;
  max-width: 900px;
  font-size: 40px;
}
.rightbox {
  background-image: url(img/right-quadre12x151px.png);
  background-repeat: no-repeat;
  width: 12px;
  height: 151px;
  float: left;
}

Les imatges són:




En aquest últim cas,  caldrà tenir en compte que les dimensions de la pantalla poden provocar que alguna capa passi a la fila inferior, desmuntant l'efecte de caixa. Es pot prendre la precaució d'agrupar les tres capes anteriors en una capa de dimensions suficients i que forçaria l'aparició de la barra d'scroll horitzontal si calgués.

Finalment, pot ser interessant disposar d'un mètode general per a fer caixes de mida ajustable.

El següent és una tècnica adaptada de http://www.neuroticweb.com/recursos/css-rounded-box/. Amb aquesta tècnica només cal fixar la mida horitzontal.

Com en els casos anteriors tindrem una tapa superior, una capa central i una capa de tapa inferior.  Però les tapes tindran, a més sengles capes addicionals per a fer cada una la cantonada dreta corresponent.

Vet aquí el codi. Podem ampliar el text o posar i treure <br> per veure'n els resultats.

<div class="rbbox">

    <div class="rbltop">
        <div class="rbrtop">&nbsp;</div>
    </div>

    <div class="rbcontent">
        <p>aquesta és una prova de caixa que s'adapta de forma<br>
        automàtica a la mida del seu contingut.<br>
        Adaptat de 

        <a href="http://www.neuroticweb.com/recursos/css-rounded-box/">
        http://www.neuroticweb.com/recursos/css-rounded-box/</a></p>
    </div>

    <div class="rblbot">
        <div class="rbrbot">&nbsp;</div>
    </div>
</div>


Els css són aquests:

.rbbox { background: url(img/rbbg.gif) repeat; width: 300px; margin: 0 100px; }
.rbltop { background: url(img/rbtl.gif) no-repeat top left; }
.rbrtop { background: url(img/rbtr.gif) no-repeat top right; }
.rblbot { background: url(img/rbbl.gif) no-repeat bottom left; }
.rbrbot { background: url(img/rbbr.gif) no-repeat bottom right; }
.rbcontent { margin: 5px 5px; }


I les imatges:






Finalment, dir que de tècniques per a fer cantonades rodones amb HTML i CSS  n'hi han moltes. A aquest enllaç (http://www.devwebpro.com/25-rounded-corners-techniques-with-css/) en podem trobar un bon grapat.

dimecres, 29 de juny del 2011

Com fer servir wget per a descarregar llocs web sencers

Un "truc" amb Linux. Com descarregar-se una web sencera?

En general, la resposta és amb una aranya web (o web crawler): un programa que es dedica a recorrer els enllaços d'una pàgina web de forma recursiva fins a un determinat nivell de profunditat.

Ara bé, a Linux hi ha una petita aplicació de línia de comandes que permet fer exactament això mateix: wget

Per a descarregar una web "sencera" podem fer-ho amb:

wget -r -l 0 http://www.undomini.cat/

Si fem wget --help a un terminal obtenim la llista d'opcions. En particular es veu que:

Descàrrega recursiva:
-r, --recursive       baixa de forma recursiva.
-l, --level=NOMBRE    nivell màxim de recursió (inf o 0 per infinit)

Al manual de GNU Wget trobem tota la informació sobre aquest programa.

diumenge, 26 de juny del 2011

X Jornades de Programari Lliure

Els propers 30 de juny i 1 de juliol es celebraran les X Jornades de Programari Lliure a l'Escola Tècnica Superior d'Enginyers Industrials de Barcelona. Vet aquí la informació que publiquen a la web:


X Jornades de programari Lliure

JPL - La teva trobada anual - Free Software, Open Source i Coneixement Lliure.

Informació general

Benvinguts a la desena edició de les Jornades de Programari Lliure, les X-JPL. Fidels al compromís dels organitzadors per fer d'aquestes jornades les jornades de tothom, en aquesta edició l'esdeveniment se celebrarà a l'Escola Tècnica Superior d'Enginyeria Industrial de Barcelona de la  Universitat Politècnica de Catalunya.
Les JPL tenen com a principal objectiu la difusió del programari lliure. Es debat com potenciar el seu ús a la societat en general i a la recerca, desenvolupament i docència en particular, així com donar a conèixer les activitats on intervé el programari lliure que actualment es porten a terme a les diverses universitats catalanes i també a altres sectors del país inclosa l'administració.

Desè aniversari

En ocasió d'aquests 10 anys d'existència, la temàtica de les jornades girarà al voltant de 2 eixos bàsics:
  • Repàs històric: d'alguna manera o altra volem oferir un balanç de les fites més rellevants assolides pel Programari Lliure en aquest període
  • Tendències de futur en el programari lliure: Portarem reconeguts experts en la matèria per tal que ens ajudin a discernir l'esdevenidor del programari lliure en els seus diversos àmbits (escriptori, dispositius mòbils, bases de dades, ofimàtica, temes legals, societat, educació, etc.)

Inscripció

Per assistir a les jornades és imprescindible inscriure-us-hi tot i que el registre és gratuït. Per formalitzar-lo només cal que us doneu d'alta en aquest portal a través d'aquest formulari (a partir de l'1 de juny). Recordeu que cal que passeu pel taulell de recepció per tal d'acreditar-vos.

Dates importants

  • Jornades: 30 de juny i 1 de juliol de 2011.

Si voleu estar informats

En aquests moments el programa detallat d'activitats està en preparació. Si voleu estar al dia de les darreres novetats que es vagin produïnt, teniu a la vostra disposició els següents mecanismes:
  • Us podeu subscriure (recomanable) a la llista de distribució de les jornades. Des de la llista us mantindrem informats de les darreres novetats referents a les jornades. Aquesta llista és moderada i de baix tràfic (vuit missatges l'any com a molt).
  • Podeu estar subscrits a les notícies d'aquest portal mitjançant RSS.

Informació de contacte

Envieu un correu a la secretaria de les jornades.

Organització

La X edició de les JPL està organitzada per la  Càtedra de Programari Lliure de la UPC. Els membres de l'organització podeu trobar-los aqui.

divendres, 24 de juny del 2011

CSS Box model. quirks mode vs. w3c mode

Recentment he estat involucrat en la creació de pàgines web amb crossbrowsing per a Internet Explorer 6,7,8 i FireFox 3,3.6 i 4.

Per crossbrowsing s'entén la creació de pàgines web que es vegin igual amb tots els navegadors.

És, doncs,  l'art d'eliminar les diferències de visualització que hi han entre dieferents navegadors, entre versions d'un mateix navegador o entre un mateix navegador  a diferents sistemes operatius.

Per exemple: les diferències de visualització entre Internet Explorer, FireFox i Chrome; les diferències de visualització entre Internet Explorer 6, 7,8 i 9; o les diferències de visualització entre Windows i Unix.


Un dels aspectes que dificulten el crossbrowsing és el model de caixes del CSS.

El model de caixes aplica a les capes i a un  munt d'etiquetes. El model de caixes especifica els marges, el padding o espai entre els límits  de la caixa i l'espai útil de la caixa, especifica la forma i mida de les vores de la caixa...

 
El model de caixes està definit en una especificació del WWW Consortium i l'honoren tots els navegadors importants, si més no en les seves versions actuals. És l'standard model. Ara bé, les versions antigues de l'Internet Explorer feien servir un model de caixes propi. I les versions modernes han optat per mantenir aquest model per a totes aquelles pàgines HTML que no tinguin DOCTYPE, o que el DOCTYPE defineixi la pàgina com HTML 3, com HTML 4 Transitional, o es tracti d'un document de framesets. El que es coneix com Quirqs mode.

Això ens parla de la importància de donar un DOCTYPE adequat a les pàgines que tinguem que crear.

A Internet n'hi han un munt de pàgines que provoquen que l'Internet Explorer les visualitzi en quirks mode.

Per això, cal tenir present les diferències entre el model de caixes del quirks mode i el model de caixes estàndar.

La següent imatge, agafada de http://www.456bereastreet.com/archive/200612/internet_explorer_and_the_css_box_model/, il·lustra aquestes diferències. Aquesta és una imatge clau que cal tenir present a l'hora de desenvolupar

La tècnica de desenvolupament tenint el cross-browsing en ment seguiria els següents principis:

1. desenvolupar per a un navegador base, per exemple Firefox.
2. separar tots els estils en un document css.
3. examinar el resultat en els navegadors per als que es vol garantir el crossbrowsing, per exemple Internet Explorer
4. fent us de condicionals. En el cas de Internet Explorer es disposa de les etiquetes <!--[IF IE nn ]>   .....    <![END IF] --> (amb nn versió de IE).

 Un bon motiu per a desenvolupar primer amb FireFox és que després és molt senzill associar uns CSS específics per al cross browsing amb IE fent servir les etiquetes condicionals de l'IE. En canvi, si es pren IE com navegador base, aleshores cal utilitzar condicionals amb javascript per a associar CSS a Firefox.

El codi dels condicionals amb FireFox quedaria així

<link rel="stylesheet" type="text/css" href="/css/ff_css.css"/>
<!--[IF IE 7 ]>
<link rel="stylesheet" type="text/css" href="/css/ie7_css.css"/>
<![END IF] -->
<!--[IF IE 8 ]>
<link rel="stylesheet" type="text/css" href="/css/ie8_css.css"/>
<![END IF] -->