/*************** */
/* FILE Cgen.java */
/* ************** */

package conteggi;

import conteggi.*;
import java.awt.*;

public classCgen extends java.applet.Applet{
/* costanti */
public static final int MAXNUMCOUNTERS=3; // al max. posso creare MAXNUMCOUNTERS contatori

/* var. istanza */
private CounterWithDisplay[] cwda=new CounterWithDisplay[MAXNUMCOUNTERS];
private int num=0; //num. di istanze CounterWithDisplay attive
private Button newcounterbutton;

/* metodi */
public void init(){
newcounterbutton= new Button(" New Counter ");
newcounterbutton.addActionListener(new NewCounterListener(this));
add(newcounterbutton);
}

public void destroy(){
// cancella tutte le finestre
int i=0;
System.out.println("*null*= "+null);
for(; i<MAXNUMCOUNTERS; i++){
if (cwda[i]!=null){
CounterFrame f=cwda[i].getFrame();
boolean iss=f.isShowing();
System.out.println("Contatore "+i);
System.out.println(" Rif.alla fin: "+f.toString());
if (iss){
System.out.println(" La fin. di c"+i+" isShowing...quindi viene DISTRUTTA");
cwda[i].getFrame().dispose();
}
}else System.out.println("per i="+i+" non è stato creato nessun CWD");
}
//try{Thread.sleep(500000);}catch(Throwable t){}
}

public CounterWithDisplay[] getTheArray(){return cwda;}

public void incNumCWD(){num++;}

public void decNumCWD(){num--;}

public int getNumCWD(){return num;}
}

/* **************************** */
/* FILE NewCounterListener.java */
/* **************************** */

package conteggi;

import conteggi.*;
import java.awt.event.*;

public classNewCounterListener implements ActionListener{
private Cgen appletrif; //rifer. all'applet

public NewCounterListener(Cgen a){
appletrif=a;
}

public void actionPerformed(ActionEvent e){
/*
Devo fare una new per creare un nuovo C.W.D. (con un nome di default); passo
anche un rif. all'applet per fare le modifiche sull'array quando viene cancellato un cwd.
*/

int i=appletrif.getNumCWD(); //ins.in coda
if (i < appletrif.getTheArray().length){
appletrif.getTheArray()[i] = new CounterWithDisplay("c" + Integer.toString(CounterWithDisplay.getNumIstanze()), appletrif);
appletrif.incNumCWD();
System.out.println("posiz.nell'array del cont creato= numCWD-1 = "+ (appletrif.getNumCWD()-1));
}
else{
System.out.println("Non posso creare + di "+appletrif.getTheArray().length+" cont.");
}
}
}

/* **************************** */
/* FILE CounterWithDisplay.java */
/* **************************** */

package conteggi;

import conteggi.*;
import java.awt.*;

public classCounterWithDisplay extends Counter{
private CounterFrame fr;
private Object thecreator;

public CounterWithDisplay(String nome, Object oggetto_creatore_del_cwd){
super(nome);
thecreator=oggetto_creatore_del_cwd;
fr=new CounterFrame("Counter "+nome, this);
CounterFrameListener cfl=new CounterFrameListener(this);
fr.addWindowListener(cfl);
fr.show();
}

public CounterFrame getFrame(){return fr;}

public Object getTheCreator(){return thecreator;}
}

/* ******************* */
/* FILE Contatore.java */
/* ******************* */

package conteggi;

public interfaceContatore {
public static final int TOPVAL=1000;

public abstract void inc();
public abstract void dec();
public abstract int getValue();
public abstract void reset();
public abstract void simpleShow();
}

/* ***************** */
/* FILE Counter.java */
/* ***************** */

package conteggi;

import conteggi.*;

public classCounter implements Contatore{
/* costanti */
public static final String READY="Ready";
public static final String INFBOUNDERROR="Errore: limite inf. raggiunto";
public static final String SUPBOUNDERROR="Errore: limite sup. raggiunto";

/* var di classe */
private static int numIstanze=0;

/* var istanza */
private int val;
private String name;
private String status;

/* costruttori */
public Counter(String s){
name=s;
reset();
incNumIstanze();
//System.out.println("Costr.1 di " + name + ". this= " + this);
}

public Counter(String s, int v){
name=s;
val=v;
incNumIstanze();
setStatus(READY);
//System.out.println("Costr.2 di " + name + "; this= " + this);
}

/* metodi di classe */
protected static int getNumIstanze(){
return numIstanze;
}

private static final void incNumIstanze(){
numIstanze++;
}

/* metodi d'istanza */
private final void setStatus(String newstatus){
status=newstatus;
}

protected String getStatus(){
return status;
}

public void inc(){
if (val<TOPVAL) {
val++;
setStatus(READY);
}
else setStatus(SUPBOUNDERROR);
}

public void dec(){
if (val>0) {
val--;
setStatus(READY);
}
else setStatus(INFBOUNDERROR);
}

public int getValue(){
return val;
}

public void reset(){
val=0;
setStatus(READY);
}

public void simpleShow(){
System.out.println("Counter " + getName());
System.out.println(" Value: " + getValue());
System.out.println(" Status: " + getStatus());
}

public String getName(){
return name;
}
}

/* ********************** */
/* FILE CounterFrame.java */
/* ********************** */

package conteggi;

import conteggi.*;
import java.awt.*;

public classCounterFrame extends Frame{
private Button incbutton, decbutton, resetbutton;
private Label display, contname;
private Counter contrif;

/*
In un'organizzazione M.V.C. (Model,View,Control) questa classe è la parte View, il CounterWithDisplay è il Modello, e gli ascoltatori rappresentano il controllo. C'e totale indipendenza.
Specificando nel costruttore di CounterFrame un riferimento ad un Counter permetto inoltre la riusabilità del codice dell'interfaccia grafica (cioè la parte View) nel caso che invece il Modello non mi vada più bene: se cambio il modello (CounterWithDisplay2, ad es.) potrei usare la stessa GUI se questa mi piacesse ancora.
*/

public CounterFrame(String titolo, Counter cr){
super(titolo);
contrif=cr;
this.setBackground(Color.white);
this.setLayout(new BorderLayout(5,5));
this.setSize(150,140);
incbutton=new Button(" +1 ");
incbutton.addActionListener(new IncDecListener(this, contrif,IncDecListener.INC1LISTENER));
this.add(incbutton, BorderLayout.EAST);
decbutton=new Button(" -1 ");
decbutton.addActionListener(new IncDecListener(this, contrif,IncDecListener.DEC1LISTENER));
this.add(decbutton, BorderLayout.WEST);
resetbutton=new Button(" reset ");
resetbutton.addActionListener(new ResetListener(this, contrif));
this.add(resetbutton, BorderLayout.SOUTH);
contname= new Label(contrif.getName(),Label.CENTER);
this.add(contname, BorderLayout.NORTH);
display = new Label(Integer.toString(contrif.getValue()), Label.CENTER);
display.setBackground(Color.black);
display.setForeground(Color.green);
display.setFont(new Font("Monospaced",Font.BOLD,22));
this.add(display, BorderLayout.CENTER);
}

public void repaint(){
display.setText(Integer.toString(contrif.getValue()));
//display.setForeground(Color.green);
//display.repaint();
super.repaint();
}
}

/* ****************************** */
/* FILE CounterFrameListener.java */
/* ****************************** */

package conteggi;

import conteggi.*;
import java.awt.event.*;
import java.awt.*;

public classCounterFrameListener implements WindowListener{
/* ogni ascoltatore può intercettare solo gli eventi relativi alla sua finestra! */
private CounterWithDisplay cwdrif;

public CounterFrameListener(CounterWithDisplay c){
cwdrif=c;
}

public void windowActivated(WindowEvent e){ }
public void windowDeactivated(WindowEvent e){ }
public void windowIconified(WindowEvent e){ }
public void windowDeiconified(WindowEvent e){ }
public void windowOpened(WindowEvent e){ }
public void windowClosed(WindowEvent e){ }
public void windowClosing(WindowEvent e){
/*
qui devo chiudere la finestra e spostare l'ultimo cwd dell'array in questa posiz.
*/
cwdrif.getFrame().dispose();
int i=0;
Cgen ar=(Cgen) cwdrif.getTheCreator();
while((i<Cgen.MAXNUMCOUNTERS) && (!(cwdrif.equals(ar.getTheArray()[i])))){
i++;
}
ar.getTheArray()[i]=ar.getTheArray()[ar.getNumCWD()-1];
ar.decNumCWD();
}
}

/* ************************ */
/* FILE IncDecListener.java */
/* ************************ */

package conteggi;

import java.awt.*;
import java.awt.event.*;
import conteggi.*;

public classIncDecListener implements ActionListener{
/* costanti */
public static final int INC1LISTENER = 1;
public static final int DEC1LISTENER = -1;
public static final int INC2LISTENER = 2;
public static final int DEC2LISTENER = -2;

/* var. istanza */

/* _listenertype_ è anche il valore (<0 o >0) da sommare al valore del contatore. NB: queste sono caratteristiche dell'implementazione, ma non sono visibili all'esterno a patto di usare le costanti. */

private int listenertype;
private Counter counterrif;
private Container containerrif; //rif. al container dell'interf.graf.del counter

/* costruttori e metodi */
public IncDecListener(Container c, Counter cr, int lt){
listenertype=lt;
counterrif=cr;
containerrif=c;
}

public void actionPerformed(ActionEvent e){
/*
qui avrei potuto lasciare al CounterWithDisplay la briga di ridefinire i metodi inc() e dec() del Counter; era più logico (e immediato), forse. Tuttavia anche così l'aggiornamento della GUI è interamente interno al Controllo, e CounterWithDisplay non deve ridefinire niente. Inoltre ciò mi ha permesso di riusare lo stesso codice degli ascoltatori (IncDecListener e ResetListener) che già avevo creato per CounterApplet; ed infine questa soluzione mi permette di pensare a Contatori all'interno di altri Container: un Applet nel caso di CounterApplet, ma potrei avere Counter senza la loro finestra dedicata ma bensì inseriti in un'altra finestra (p.e. in un suo Panel) che magari ne contiene tanti: in tutti questi casi potrei (ri)usare sempre questi ascoltatori. Ovviamente il contenitore del contatore dovrà ridefinire il metodo repaint() !
*/

int i=listenertype;
while(i>0){
counterrif.inc();
i--;
}
i=listenertype;
while(i<0){
counterrif.dec();
i++;
}
containerrif.repaint();
}

public int getListenerType(){
return listenertype;
}

public Container getContainerRif(){
return containerrif;
}
}

/* *********************** */
/* FILE ResetListener.java */
/* *********************** */

package conteggi;

import java.awt.*;
import java.awt.event.*;
import conteggi.*;

public classResetListener implements ActionListener{
/* var. istanza */
private Container containerrif;
private Counter counterrif;

/* costruttori e metodi */
public ResetListener(Container ca, Counter cr){
containerrif= ca;
counterrif=cr;
}

public void actionPerformed(ActionEvent e){
counterrif.reset();
containerrif.repaint();
}
}


return