Progettino
L'obiettivo del progettino è implementare un piccolo
formattatore automatico (Pretty Printer).
Il progettino è individuale e dovrà essere consegnato
prima di sostenere la prova scritta.
Il compito del formattatore è di posizionare nel migliore dei modi gli elementi da stampare.
Questi elementi sono rappresentati dalla class abstract Box:
public abstract class Box {
private Point entryPoint;
private Point getExitPoint;
private Rectangle boundingBox;
}
dove la class Point rappresenta un punto nel piano cartesiano:
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
e dove la class Rectangle rappresenta un rettangolo nel piano cartesiano:
public class Rectangle {
private Point upperLeftCorner;
private int width;
private int height;
public Rectangle(Point upperLeftCorner, int width, int height) {
this.upperLeftCorner = upperLeftCorner;
this.width = width;
this.height = height;
}
}
definito dal suo angolo sinistro superiore (upperLeftCorner),
dalla sua larghezza (width) e dalla sua altezza (height).
Nella class Box:
- Il punto d'entrata (entry point) rappresenta la posizione alla quale la scatola
può attaccarsi con una scatola precedente.
- Il punto d'uscita (exit point) rappresenta la posizione alla quale la scatola
può attaccarsi con una scatola successiva.
- Il rettangolo di delimitazione (bounding box)
rappresenta la regione che copre la scatola.
Le coordinate del punto d'uscita e il rettangolo di delimitazione sono
relativi al punto d'entrata. Dunque, in coordinate assolute, una scatola
composta di un punto d'entrata (0,1), punto d'uscita (6,1) e
un rettangolo ((0,0),7,2) è rappresentato nella nostra rappresentazione
con un punto d'entrata (0,1) un punto d'uscita (6,0) e un rettangolo
((0,-1),7,2).
Una scatola può essere o atomica o composita. La class Atom rappresenta una scatola atomica che contiene
una sola stringa:
public class Atom extends Box {
private String value;
private int fontSize;
public Atom (String value, int fontSize) {
this.value = value;
this.fontSize = fonSize;
}
}
Per formattare un scatola atomica, le regole sono le seguenti:
- Il valore di default del punto d'entrata è (0,0).
- Il suo punto di uscita si trova spostato orizzontalmente rispetto
al punto d'entrata di un valore uguale al numero di caratteri della stringa
per la dimensione del font.
- Il suo rettangolo ha il suo angolo sinistro-superiore spostato
verticalmente in alto rispetto al punto d'entrata della metà della
dimensione del font
e il suo angolo destro-inferiore spostato verticalmente in basso
rispetto al punto d'entrata della metà della dimensione del font.
Per esempio, una scatola atomica che contiene la stringa "Hello" con
un font di dimensione 12 ha un punto d'uscita (60, 0) e
un rettangolo ((0,-6), 60, 12).
Una scatola può essere composita, cioé contenere
altre scatole (boxes):
public abstract class Composite extends Box {
private Box[] boxes;
protected Composite(Box[] boxes) {
this.boxes = boxes;
}
}
Quando si formatta,
è compito della scatola composita di settare i punti
d'entrata delle sue sotto-scatole.
Tre sotto-class composite saranno considerate in questo progettino.
public class Horizontal extends Composite {
private int interword;
public Horizontal(int interword, Box[] boxes) {
super(boxes);
this.interword = interword;
}
}
e
public class Vertical extends Composite {
private int indentation;
private int interline;
public Vertical(int indentation, int interline, Box[] boxes) {
super(boxes);
this.indentation = indentation;
this.interline = interline;
}
}
e
public class Paragraph extends Composite {
private int interword;
private int interline;
public Paragraph(int interword, int interline, Box[] boxes) {
super(boxes);
this.interword = interword;
this.interline = interline;
}
}
Per formattare un scatola composita, le regole sono le seguenti:
-
Il punto d'entrata della scatola composita corrisponde al punto d'entrata della
sua prima scatola;
-
Il punto d'uscita della scatola composita corrisponde al punto d'uscita dell'ultima scatola;
-
Per un Horizontal, le sotto-scatole sono disposte in
modo tale che il punto d'uscita della scatola i e il punto d'entrata
della scatola i+1 sono separate orizzontalmente di un valore
uguale a interword;
-
Per un Vertical, le sotto-scatole sono disposte in
modo tale che orizzontalmente il punto d'entrata della scatola 0 e il punto
d'entrata della scatola i+1 sono separate di un valore
uguale a indentation e verticalmente in modo tale che il
rettangolo di delimitazione della scatola i e il rettangolo
di delimitazione della scatola i+1 sono separate verticalmente di un valore
uguale a interline;
-
Per un Paragraph, le sotto-scatole sono disposte in modo tale
che se c'è spazio la scatola i+1 è disposta in modo orizzontale
rispetto alla scatola i con una separazione di interword.
Se non c'è orizzontalment, la scatola i+1 è messa a capo.
Orizzontalmente il punto d'entrata della scatola 0 e il punto
d'entrata della scatola i+1 sono separati di un valore
uguale a indentation e verticalmente il
rettangolo di delimitazione della scatola i e il rettangolo
di delimitazione della scatola i+1 sono separati verticalmente di un valore
uguale a interline;
- Il rettangolo di delimitazione di una scatola composita è il più piccolo
rettangolo che contiene tutti i rettangoli delle sotto-scatole.
Esempi
Horizontal:
Vertical:
Paragraph:
Compito
Aggiungere alla class Box
- Un metodo pubblico isAtomic che indica se una scatola è
atomica.
- Un metodo pubblico isComposite che indica se una scatola è
composita.
- Un metodo pubblico numberOfAtomic che ritorna il numero di
scatole atomiche contenute dentro una scatola.
- Un metodo pubblico getStrings che ritorna
un array composto di tutte le stringhe contenute dentro una scatola.
- Un metodo pubblico format che formatta una scatola.
Tale metodo prende come parametro un intero che indica la larghezza
della pagina (questo parametro serve per il comportamento di Paragraph). Per esempio, b.format(500) formatta la scatola b
con una larghezza di pagine di 500 unità.
- Un metodo pubblico toString che ritorna sotto forma di una stringa
tutte le indicazioni (in coordinate assolute) sulla scatola.
- Un metodo pubblico contains che prende come parametro un punto
p tale che b.contains(p) ritorna la più piccola scatola
di b che contiene il punto p. Se il punto non è
contenuto in nessuna scatola si solleva l'eccezione OutsideException.
- Una sovrascrittura del metodo precedente contains che prende come parametro un rettangolo r tale che b.contains(r) ritorna la più piccola scatola
di b che contiene il rettangolo r.
Se il rettangolo non è
contenuto in nessuna scatola si solleva l'eccezione OutsideException.
Per questo lavoro, si prenderà particolarmente cura di completare le classi
Point e Rectangle con i metodi d'appoggio necessari.
Lo studente dovrebbe seguire le convenzioni di codifica
date durante il corso. Per verificare la conformità del progetto, si può
usare l'archivio checkstyle.jar.
Eseguendo
java -jar checkstyle.jar File.java
si genera un file report che indica la conformità del codice.
Laurent Théry
Laurent
Théry
Last modified: Thu Feb 19
12:54:05 MET
2004