package elte.java2_utikalauz5.gui;
/**
Példaprogram az elrendezési stratégiák szemléltetésére.

Alapértelmezett esetben a {@code TesztLayout} stratégiát szemlélteti nyomógombok
segítségével, melyeket megnyomvva a felület újrarendezését (az első töröl, az
utolsó bővít) lehet kérni.
Az indítási paraméterekkel a felület elrendezési irányát befolyásolhatjuk (horizontális}, vertikális, balróljobbra és jobbrólbalra, illetve ezek prefixének megadásával), valamint a keret méretének fixen tartását és a komponensek közt alkalmazandó térköz nagyságát (negatív számként, de csak ha a bemutatott elrendezési stratégia ezt támogatja) írhatjuk elő.
A program elindulásakor a kimeneten megjelenik az alkalmazott elrendezési irány, valamint a stratégia megvalósításának neve és alkalmazott paraméterei.
@link.forrásfájl {@docRoot}/../data/gui/src LayoutTeszt.java
@link.letöltés {@docRoot}/../data/gui LayoutTeszt.jar
@see TesztLayout
@since Java 2 Útikalauz programozóknak 5.0
*/
class LayoutTeszt implements java.awt.event.ActionListener {
/***************************************************************************
Százalékos méretarányú és igazítású nyomógomb. A gombra jellemző arányszám
feliratként látszik, az igazítási pont mentén pedig egy vonal látható.
*/
class Gomb extends java.awt.Button {
/** Verziószám. */
private final static long serialVersionUID = 15L;
/** Igazítási és méretarány szám. */
private float arány;
/**
Konstruktor az arányszámmal.
@param arány Igazítási és méretarány szám [0-1]
*/
private Gomb( float arány ) {
setArány( arány );
}
/**
Arányszám beállítása.
@param arány Igazítási és méretarány szám [0-1]
@throws IllegalArgumentException ha nem megfelelő az arányszám
*/
void setArány( float arány ) {
if (arány<0||arány>1) throw new IllegalArgumentException(//ellenőriz
"Érvénytelen arány: "+arány+"\nCsak 0-1 tartomány megengedett!");
this.arány = arány; //arányszám eltárolása
alapFelirat(); //feliratozás
}
/** Alapértelmezett felirat beállítása a százalékos arányszámmal */
public void alapFelirat() {
setLabel(Math.round(arány*100)+"%"); //felirat beállítása
}
/**
Függőleges igazítási pont lekérdezése.
@return a gomb arányszáma
*/
@Override
public float getAlignmentX() {
return arány;
}
/**
Vízszintes igazítási pont lekérdezése.
@return a gomb arányszáma
*/
@Override
public float getAlignmentY() {
return arány;
}
/** Igazítási vonal kirajzolása, ha igaz */
private boolean vonalaz = true;
/**
Igazítási vonal kirajzolásának beállítása.
@param vonalaz Igazítási vonal kirajzolása, ha igaz
*/
public void setVonalaz( boolean vonalaz ) {
this.vonalaz = vonalaz;
}
/**
Gomb megjelenítésekor ha kell az igazítási vonal kirajzolása.
@param g a megjelenítés rajzolási környezete
*/
@Override
public void paint( java.awt.Graphics g ) {
super.paint( g ); //gomb megjelenítése
if (!vonalaz) return;
if (getParent().getComponentOrientation().isHorizontal()
&& !függőleges) {
int y = Math.round(arány * getHeight()); //vízszintes igazítási
g.drawLine(0, y, getWidth() - 1, y); //vonal meghúzása
} else {
int x = Math.round(arány * getWidth()); //függőleges igazítása
g.drawLine(x, 0, x, getHeight() - 1); //vonal meghúzása
}
}
/**
Gomb optimális méretének lekérdezése. Az eredeti optimális méret arány-
számmal megnövelt értékét adja vissza.
@return a gomb új optimális mérete
*/
@Override
public java.awt.Dimension getPreferredSize() {
java.awt.Dimension méret = super.getPreferredSize(); //eredeti méret
méret.width = Math.round((1+arány)*méret.width); //arányos növelés
méret.height = Math.round((1+arány)*méret.height);
return méret; //új méret visszaadása
}
}//*************************************************************************
/** Véletlenszámgenerátor a gombméretekhez */
java.util.Random véletlen = new java.util.Random();
/**
Új gomb felvétele a megadott felületre
@param felület cél konténer
*/
void újgomb(java.awt.Container felület) {
float arány = véletlen.nextFloat(); //véletlen arányszám
Gomb gomb = new Gomb(arány); //új arányos gomb létrehozása
Object jellemző = újgomb( felület, gomb ); //elrendezési jellemző
gomb.addActionListener( this ); //gombnyomás figyelése
if (jellemző==null) felület.add( gomb ); //gomb felvétele a felületre
else felület.add( gomb, jellemző );
feliratoz(gomb); //új gomb feliratozása
}
/**
Újonnan felkerülő nyomógombhoz tartozó elrendezési jellemző lekérdezése.
@param gomb az új nyomógomb
@param felület cél konténer
@return a nyomógombhoz tartozó elrendezési jellemző, vagy {@code null}
*/
Object újgomb( java.awt.Container felület, Gomb gomb ) { //alapértelmezett
return new TesztLayout.Constraints( //arányos jellemző visszaadása
gomb.getAlignmentX(), gomb.getAlignmentY());
}
/**
Gomb feliratának beállítása. Az eredeti százalékos feliratot a komponens
mélységi sorszámával, mint előtaggal egészíti ki.
@param gomb a feliratozandó gomb
*/
void feliratoz( Gomb gomb ) {
gomb.setLabel((gomb.getParent().getComponentZOrder(gomb)+1)+". ("+
gomb.getLabel()+")");
}
/**
Törölhető nyomógomb lekérdezése.
@param gomb az ellenőrzött nyomógomb
@return igaz érték esetén a megnyomott gomb törlődik a felületről
*/
boolean törlőgomb( Gomb gomb ) { //alapértelmezetten az első gomb törlődik
return gomb==gomb.getParent().getComponent(0);
}
/**
Új gombbal bővítést végző nyomógomb lekérdezése.
@param gomb az ellenőrzött nyomógomb
@return igaz érték esetén új nyomógomb kerül a felületre
*/
boolean bővítőgomb( Gomb gomb ) { //alapértelmezetten az utolsó gomb bővít
return gomb==gomb.getParent().getComponent(
gomb.getParent().getComponentCount()-1);
}
/**
Nyomógomb elrendezési jellemzőinek megváltoztatása. Meghívása előtt a
paraméterként kapott gombon már beállításra került egy új arányszám.
@param gomb a megváltoztatott nyomógomb
*/
void változógomb( Gomb gomb ) { //alapértelmezés szerint az arányos
TesztLayout.Constraints jellemző = //elrendezési jellemző
((TesztLayout)elrendezés).getConstraints(gomb);
jellemző.setXarány(gomb.getAlignmentX()); //módosítása
jellemző.setYarány(gomb.getAlignmentY());
}
/**
Gombnyomás kezelése. Adott gombot megnyomva új gomb kerül felvételre, vagy
az törlődik, a többi megnyomása pedig új arányok kiosztását eredményezi
@param gombnyomás a gombnyomás eseményobjektuma
*/
public void actionPerformed( java.awt.event.ActionEvent gombnyomás ) {
Gomb gomb = (Gomb)gombnyomás.getSource(); //megnyomott gomb
java.awt.Container felület = gomb.getParent();
if (bővítőgomb(gomb)) újgomb(felület); //új gomb felvétele
else if (törlőgomb(gomb)) { //vagy adott gomb törlése
felület.remove(gomb);
for (java.awt.Component komponens : felület.getComponents()) {
gomb = (Gomb)komponens; //a megmaradt gombok újrafeliratozása
gomb.alapFelirat();
feliratoz(gomb);
}
} else { //a többi gomb új arányokat és elrendezési jellemzőket oszt ki
for (java.awt.Component komponens : felület.getComponents()) {
gomb = (Gomb)komponens;
float arány = véletlen.nextFloat(); //új arány
gomb.setArány(arány); //gombigazítás és feliratásnak módosítása
változógomb(gomb);
feliratoz(gomb);
}
} //új elrendezés elvégzése és igény esetén az optimális méret felvétele
if (mindigpack && felület instanceof java.awt.Frame)
((java.awt.Frame)felület).pack();
else felület.validate();
}
/** Az elrendezendő konténer */
private java.awt.Container felület;
/**
Grafikus felületet tartalmazó konténer felkészítése a teszthez.
@param felület az eredeti konténer
@return a felkészített konténer
*/
java.awt.Container felület(java.awt.Container felület) {
this.felület = felület;
return felület;
}
/** A tesztelendő elrendezési stratégia */
java.awt.LayoutManager elrendezés;
/**
Konstruktor az elrendezési stratégia megadásával.
@param elrendezés az alkalmazandó elrendezési stratégia
*/
LayoutTeszt(java.awt.LayoutManager elrendezés) {
this.elrendezés = elrendezés;
}
/** igaz értéke esetén változáskor az ablak mindig újraméreteződik */
static boolean mindigpack = true;
/** igaz értéke esetén az elrendezési irány függőleges lesz */
static boolean függőleges;
/** a komponensek elrendezési iránya */
static java.awt.ComponentOrientation irány;
/** Komponensek közti helykihagyás */
static int helykihagyás;
/**
A program indítási paramétereinek feldolgozása. Alapértelmezetten támogatott
paraméterek:
horizontális
vagy vertikális
elrendezés
balróljobbra
vagy jobbrólbalra
irány
fix
méret esetén az ablak nem méreteződik át automatikusan
- -szám a komponensek közti helykihagyás mérete
*/
static void argumentumKezelés( String[] argumentumok ) {
if (irány!=null) return; //a paramétereket már kiértékeltük
irány = java.awt.ComponentOrientation.getOrientation( //alapértelmezett
java.util.Locale.getDefault() ); //elrendezési irány
függőleges = !irány.isHorizontal();
for (String argumentum : argumentumok) { //paraméterek feldolgozása
if (argumentum.startsWith("v")) függőleges = true;
else if (argumentum.startsWith("j"))
irány = java.awt.ComponentOrientation.RIGHT_TO_LEFT;
else if (argumentum.startsWith("h")) függőleges = false;
else if (argumentum.startsWith("b"))
irány = java.awt.ComponentOrientation.LEFT_TO_RIGHT;
else if (argumentum.startsWith("f")) mindigpack = false;
else if (argumentum.startsWith("-")) try {
helykihagyás = Integer.parseInt( argumentum.substring(1) );
} catch (NumberFormatException nfe) {}
}
}
/**
A grafikus felhasználói felület felépítése {@code TesztLayout}-ot használva.
Indítási paraméterként a csoportigazítás (Elejére, Középre, véGére) adható.
@param felület A felhasználói felületet tartalmazó konténer.
@param argumentumok Az indításkor megadott paraméterek.
*/
public static void felépít(java.awt.Container felület,
String argumentumok[]) {
int csoportigazítás = -1; //igazítás a csoport elejére
for (String argumentum : argumentumok) { //paraméterek feldolgozása
if (argumentum.startsWith("e")) csoportigazítás = -1;
else if (argumentum.startsWith("k")) csoportigazítás = 0;
else if (argumentum.startsWith("g")) csoportigazítás = 1;
}
argumentumKezelés( argumentumok );
felépít( new LayoutTeszt(new TesztLayout(függőleges, csoportigazítás,
helykihagyás, helykihagyás)), felület, argumentumok );
}
/**
A grafikus felhasználói felület felépítése.
@param teszt A végrehajtandó tesztprogram
@param felület A felhasználói felületet tartalmazó konténer.
{@code null} esetén egy külön ablak kerül megnyitásra.
@param argumentumok Az indításkor megadott paraméterek.
@return A felhasználói felületet tartalmazó konténer.
*/
static java.awt.Container felépít( final LayoutTeszt teszt,
java.awt.Container felület, String argumentumok[]) {
argumentumKezelés( argumentumok ); //indítási paraméterek kezelése
java.awt.Frame keret = null; //szükség esetén külön ablak
if (felület==null) {
felület = keret = new AblakTeszt.Ablak(null) {
@Override
public void validate() { //Elrendezéskor a konténer elemszámának
super.validate(); //megjelenítése a fejlécben
setTitle(teszt.getClass().getSimpleName()+" - "+
teszt.felület.getComponentCount()+" komponens");
}
private final static long serialVersionUID = 15L; //verziószám
};
}
felület.setMinimumSize(new java.awt.Dimension(400, 300)); //minimálméret
felület.setMaximumSize(felület.getToolkit().getScreenSize()); //maximum
felület = teszt.felület( felület ); //konténer felkészítése
felület.setComponentOrientation(irány); //a megadott irány beállítása
felület.setLayout(teszt.elrendezés); //elrendezési stratégia beállítása
for (int i=5; --i>=0;) teszt.újgomb(felület); //kezdőfelület 5 gombból
if (keret!=null) { //saját ablak megjelenítése
keret.pack(); //kezdőméret beállítása
keret.setVisible(true); //felület megjelenítése
}
System.out.println(teszt.getClass().getSimpleName()+" elrendezés: "+
(függőleges?"függőlegesen":"vízszintesen")+" "+(irány.isLeftToRight()
? "balról jobbra" : "jobbról balra")+"\n"+teszt.elrendezés);
return felület;
}
/**
A tesztprogram indítása külön ablakban.
@param argumentumok Az indításkor megadott paraméterek.
*/
public static void main( String[] argumentumok ) {
felépít( null, argumentumok );
}
}