import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
// N'oubliez pas qu'en Java il faut respecter les minuscules/MAJUSCULES.
/**
* Classe principale de la mobilette, celle-ci calcule la consommation
* d'un véhicule à partir de son kilométrage et de la quantité d'essence.
* Comme c'est une mobilette, c'est une classe dérivée de Midlet.
* Cette classe implémente les interfaces suivantes (elle définit les
* méthodes de ces interfaces) :
* - ItemStateListener pour être informé dès que le contenu des zones de
* saisies (TextField) est modifié par l'utilisateur. Ainsi nous pouvons
* mettre à jour le texte consommationSI sans action spéciale de l'utilisateur.
* Attention, sur certains téléphones l'usage des ItemStateListener n'est pas
* parfait : pour que la consommation soit prise en compte après saisie,
* l'utilisateur doit aller sur le kilométrage pur que le télphone appelle
* le listener. Ca ne conerne que quelques modèles, mais du coup il faut
* considérer que l'ItemStateListener est seulement un plus, la façon "normale"
* étant d'utiliser un CommandListener.
*
- CommandListener pour être informé quand l'utilisateur choisit une
* des commandes que nous avons ajouté à l'écran (calcul et quitter).
*
*
* @author Thibaut REGNIER, mobilette@club-java.com
*/
public class EcoLogic
extends MIDlet
implements ItemStateListener, CommandListener
{
/**
* Ecran sur lequel la mobilette est affichée.
* Vaut null au lancement (car non affectée), sera initialisée par notre
* code lors du premier appel à startApp() par le système.
* Attention! display ne pourrait pas être initialisée dans
* le constructeur de la classe, l'écran n'étant défini par le système
* qu'à partir du moment où startApp() est appelée pour la première fois.
* N'oubliez pas que certains téléphones ont 2 écrans
* (ex:Nokia Communicator) et le système décide au lancement sur quel
* écran on sera affiché.
*/
private Display display;
/**
* Formulaire affiché à l'écran contenant les textes et zones de saisies.
*/
private Form formulaire;
/**
* Zone de saisie contenant le nombre de kilomètres parcourus.
*/
private TextField kilometrageTF;
/**
* Zone de saisie contenant le nombre de litres d'essence consommés.
*/
private TextField litresEssenceTF;
/**
* Texte affichant le résultat de la consommation.
*/
private StringItem consommationSI;
/**
* Commande pour lancer le calcul quand l'utilisateur le décide.
*/
private Command calculerCommand;
/**
* Commande pour quitter la mobilette.
*/
private Command quitterCommand;
/**
* Prévient la mobilette qu'elle va être affichée, soit pour la
* première fois, soit après après été mise en pause (pendant la réception
* d'un appel téléphonique par exemple).
* Si c'est notre premier lancement (notre variable display est alors null)
* on initialise tout, y compris display qui du coup ne sera plus null
* si la même méthode est appelée après une pause.
* @see javax.microedition.midlet.MIDlet#startApp()
*/
protected void startApp() throws MIDletStateChangeException
{
// Teste si on vient de démarrer (null)
// ou si on est réveillé après une pause (non null)
if (display == null)
{ // on vient de démarrer => initialisations.
display= Display.getDisplay(this); // récupère l'écran
// construit un tableau qui contiendra tous les éléments de l'écran
Item[] item= new Item[3];
// Ajout des 2 zones de saisie
kilometrageTF=
new TextField("Kilométrage", "", 4, TextField.NUMERIC);
// "Kilométrage" est le nom de la zone affiché à l'écran
// "": la zone est initialement vide vide
// 4 : est le nombre de caractère maximum saisissables dans la zone
// TextField.NUMERIC : on ne peut saisir que des chiffres et
// éventuellement le signe '-' au début. Attention la zone peut
// être vide, ce qui n'est pas une valeur nuérique.
item[0]= kilometrageTF;
litresEssenceTF=
new TextField("Litres d'essence", "", 3, TextField.NUMERIC);
item[1]= litresEssenceTF;
// Ajout de l'affichage du résultat
consommationSI= new StringItem("Consommation (l/100km) ", "0");
// Le premier paramètre est le titre. Il est suivi de ':' sur
// certains mobiles, sur d'autres il est en gras. On peut
// utiliser null si on n'a pas besoin de titre.
// Le 2ème est le texte à afficher après le titre. On le mettra
// à jour plus tard avec la valeur calculée.
item[2]= consommationSI;
// Construit le formulaire
formulaire= new Form("EcoLogic", item);
// Nous voulons être prévenu quand il y a des saisies
formulaire.setItemStateListener(this);
// Construction et ajout des commandes à l'écran
calculerCommand= new Command("Calculer", Command.SCREEN, 1);
// "Calculer" : Texte apparaissant dans le menu du téléphone.
// Ne mettez pas des textes longs (+ de 10 caractères) ils
// pourraient être tronqués.
// Command.SCREEN est le type de la commande. Le téléphone placera
// la commande à un endroit logique suivant son type et peut
// changer son texte, voir ne pas en mettre du tout. Ainsi
// Command.BACK peut être affecté à une touche spéciale du
// téléphone, mais ne pas apparaître à l'écran. Donner
// un bon type vous garantira une ergonomie correcte sur tous les
// modèles. Tricher améliorera l'usage sur 2-3 modèles et rendra
// l'application non ergonomique sur des dizaines d'autres!
// Ici avec Command.SCREEN on informe que la commande est relative
// aux informations affichées à l'écran. Lisez la doc de la
// classe Command pour connaître tous les types.
// 1: c'est la priorité de la commande, 1 étant la plus importante.
// Une autre commande de même type et de priorité 2 sera placée
// en dessous dans les menus. Notez que les commandes peuvent
// être classées par type, puis par priorité sur certains modèles
// alors que d'autres calsseront seulement par priorité.
formulaire.addCommand(calculerCommand);
quitterCommand= new Command("Quitter", Command.EXIT, 2);
formulaire.addCommand(quitterCommand);
// Nous voulons être prévenu quand une commande est utilisée
formulaire.setCommandListener(this);
// Affiche le formulaire maintenant qu'il est configuré
display.setCurrent(formulaire);
}
}
/**
* Met la mobilette en pause. Dans notre cas on ne fait pas de traitement
* dans des threads en tâche de fond, donc cette méthode est vide.
* @see javax.microedition.midlet.MIDlet#pauseApp()
*/
protected void pauseApp()
{
}
/**
* Indique à la mobilette qu'elle va être arrêtée et qu'elle doit tout
* de suite libérer ses ressources (connexions réseau, fermer ses flux
* vers la mémoire flash,...). Ici on n'utilise aucune ressource qui
* doive être fermée donc on ne fait rien.
* @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
*/
protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
}
/**
* Appelée quand un des TextField est mis à jour par l'utilisateur,
* on met alors à jour la consommation affichée.
* C'est une méthode de l'interface ItemStateListener que nous implémentons.
* @param item Item dont le contenu a changé.
* @see javax.microedition.lcdui.ItemStateListener
*/
public void itemStateChanged(Item item)
{
// on ne tient pas compte de l'item à l'origine du changement,
// on raffraîchit dans tous les cas.
calculeConso();
}
/**
* Calcule la consommation à partir des 2 zones de saisie et met à jour
* le résultat à l'écran.
* @return String La consommation si le calcul a bien eu lieu, ou
* null en cas de problème (pas de saisie, division par 0).
*/
private String calculeConso()
{
String conso;
String resultat;
try
{
int km, litres;
km= Integer.parseInt(kilometrageTF.getString());
litres= Integer.parseInt(litresEssenceTF.getString());
// on utilise la valeur absolue, évite pb si saisie d'un négatif
// on arrondit en multipliant par 10, ajoutant 5 et divisant par 10.
int consoEnDeciLitres= Math.abs((10000 * litres / km + 5) / 10);
int consoEntiere= consoEnDeciLitres / 10;
// construit la chaîne de caractère avec le nombre à virgule
conso= consoEntiere + "," + (consoEnDeciLitres - consoEntiere * 10);
// Relarquez qu'on a pas de float en CLDC 1.0 mais qu'on peut
// se débrouiller sans et affciher des nombres à virgule.
resultat= conso;
}
catch (Exception e)
{ // En cas d'erreur (valeur non remplie, division par 0...)
// on affiche une consommation de 0;
conso= "0";
resultat= null;
}
// on met à jour le texte.
consommationSI.setText(conso);
return resultat;
}
/**
* Appelée quand l'utilisateur choisit une commande affichée à l'écran.
* @param commande Command choisie par l'utilisateur.
* @param ecran Displayable sur lequel la commande était présente. Dans
* cette application nous n'en avons pas besoin (un seul écran).
* @see javax.microedition.lcdui.CommandListener
*/
public void commandAction(Command commande, Displayable ecran)
{
if (commande == quitterCommand)
{
notifyDestroyed(); // on signale au système qu'on a fini
}
else if (commande == calculerCommand)
{ // on affiche une fenêtre d'information avec le résultat
// ou un message d'erreur si le calcul est impossible.
String conso= calculeConso();
String titre, texte;
AlertType type;
if (conso != null)
{
titre= "Résultat";
texte= "Vous avez consommé " + conso + "l/100km";
type= AlertType.INFO;
// la fenêtre ser une fenêtre d'information. Certaines marques
// ajoutent un bip spécial et une icône (un i vert par exemple)
// D'autres marques ne tiennent pas compte du type, toutes
// les fenêtres d'Alert ayant le même aspect.
}
else
{
titre= "Erreur";
texte=
"Calcul impossible! Saisissez un kilométrage non nul "
+ "et une quantité d'essence.";
type= AlertType.ERROR;
}
Alert alert= new Alert(titre, texte, null, type);
// on veut que la fenêtre reste affichée jusqu'à ce que
// l'utilisateur valide le message
alert.setTimeout(Alert.FOREVER);
// On demande l'affichage de l'alerte en indiquant quel écran
// sera affiché ensuite (ici notre formulaire de saisie)
display.setCurrent(alert, formulaire);
}
}
}