|
|
|
|
|
Als nächstes soll es ermöglicht werden, den
aktuellen Bestand an Videos anzuzeigen. Außerdem sollen
sowohl Einkaufs-, als auch Verkaufspreise editiert werden
können. Es soll also der Katalog, in dem die Preise
verzeichnet sind, verändert werden. Somit liegt es nahe,
einen Prozeß zu verwenden.
|
|
|
Auf diese Weise kann dem Benutzer an einem UIGate der Stock zum
Editieren angezeigt werden und die veränderten Preise mit
einem Druck auf den "Ok"-Button
übernommen oder die alten Preise mit dem
"Cancel"-Button beibehalten werden.
|
|
|
Zum Darstellen der Tabelle ist natürlich ein TableEntryDescriptor notwendig. Dazu wird die
Klasse EditableVideoStockTED wie folgt erstellt:
|
EditableVideoStockTED
|
|
 |  |  |
 |
import sale.*;
import util.swing.*;
public class EditableVideoStockTED
extends AbstractTableEntryDescriptor
{
}
|  |
 |  |  |
|
|
|
Um die Preise editieren zu können, muß in der
Klasse der darzustellende Stock und der
zu verwendende DataBasket bekannt
sein. Dazu werden entsprechende Variablen deklariert:
|
|
|
 |  |  |
 |
private CountingStockImpl videoCountingStock;
private DataBasket db;
|  |
 |  |  |
|
|
|
Die Pakete, aus denen die verwendeten Klassen DataBasket und CountingStockImpl stammen, müssen
importiert werden:
|
|
|
 |  |  |
 |
import data.*;
import data.ooimpl.*;
|  |
 |  |  |
|
|
|
Die Variablen müssen initialisiert werden. Dazu werden
die notwendigen Werte dem Konstruktor als Parameter
übergeben und entsprechend zugewiesen:
|
Konstruktor
|
|
 |  |  |
 |
public EditableVideoStockTED(CountingStockImpl videoCountingStock,
DataBasket db)
{
super();
this.videoCountingStock = videoCountingStock;
this.db = db;
}
|  |
 |  |  |
|
|
|
Nun sollen zunächst die Eigenschaften des TableEntryDescriptors verändert werden,
die mit dem Aussehen, und nichts mit der Editierbarkeit der
Tabelle zu tun haben. Dies sind die Anzahl und die Namen der
Spalten. Die Anzahl der Spalten wird durch die Methode
getColumnCount bestimmt:
|
Eigenschaften des TED
|
|
 |  |  |
 |
public int getColumnCount()
{
return 5;
}
|  |
 |  |  |
|
Anzahl der Spalten
|
|
Mit Hilfe eines Arrays werden die Namen Spalten
wie folgt in der Methode getColumnName
festgelegt:
|
|
|
 |  |  |
 |
public String getColumnName(int index)
{
return (new String[]{"Name",
"Buy",
"Sell",
"Pieces in Stock",
"Rent Pieces"})[index];
}
|  |
 |  |  |
|
Namen der Spalten
|
|
Mit diesen zwei angepaßten Methoden ist die Klasse
bereits in der Lage, die für den Videobestand
darzustellende Tabelle korrekt zu beschreiben. Es kann eine
Instanz dieses TableEntryDescriptors
einer create -Methode aus SingleTableFormSheet übergeben
werden. Daher soll als nächstes der Prozeß
aufgebaut werden, der den noch vorhandenen Bestand
anzeigt. Dieser wird in der Klasse
SeeVideoStockProcess realisiert:
|
SeeVideoStockProcess
|
|
 |  |  |
 |
import sale.*;
public class SeeVideoStockProcess extends SaleProcess
{
}
|  |
 |  |  |
|
|
|
Der Konstruktor dieser Klasse ruft einfach den Konstruktor der
Oberklasse mit einem passenden Parameter auf:
|
Konstruktor
|
|
 |  |  |
 |
public SeeVideoStockProcess()
{
super("SeeVideoProcess");
}
|  |
 |  |  |
|
|
|
Es werden weitere Variablendeklarationen für das
benötigte Auswahl-Gate und die
Transitions zum Hinzufügen und
Entfernen von Videos gebraucht:
|
Gates und Transitions
|
|
 |  |  |
 |
protected UIGate selectionGate;
protected Transition newVideoTransition;
protected Transition removeVideoTransition;
|  |
 |  |  |
|
|
|
Die Oberfläche wird, wie im RentProcess , mit
der Methode setupMachine aufgebaut:
|
|
|
 |  |  |
 |
protected void setupMachine()
{
}
|  |
 |  |  |
|
|
|
In der Methode werden zuerst das Auswahl-Gate und das dort darzustellende FormSheet mit Hilfe des
EditableVideoStockTED erzeugt:
|
SingleTableFormSheet
|
|
 |  |  |
 |
selectionGate = new UIGate(null, null);
final SingleTableFormSheet stfs =
SingleTableFormSheet.create(
"See videos in stock and edit Process",
(CountingStockImpl)Shop.getTheShop().getStock(
"Video-Countingstock"),
selectionGate,
getBasket(),
true,
new EditableVideoStockTED((CountingStockImpl)
Shop.getTheShop().getStock("Video-Countingstock"),
getBasket()));
|  |
 |  |  |
|
|
|
Um SingleTableFormSheet und CountingStockImpl dem Compiler bekannt zu
machen, wird der Kopf der Klasse um folgende
import -Anweisungen ergänzt:
|
|
|
 |  |  |
 |
import data.ooimpl.*;
import data.stdforms.*;
|  |
 |  |  |
|
|
|
Die Transition zum Anlegen eines neuen
Videos wird erstellt und in ihr die Methode
perform implementiert:
|
newVideoTransition
|
|
 |  |  |
 |
newVideoTransition = new Transition()
{
public Gate perform(SaleProcess pOwner, User usr)
{
}
};
|  |
 |  |  |
|
|
|
Um User verwenden zu können, wird
folgendes Paket importiert:
|
|
|
|
|
|
Die Methode perform enthält alle notwendigen
Schritte, die zum Erzeugen eines neuen Videos notwendig
sind. Zuerst werden die Eingabefelder für alle relevanten
Daten eines neues Videos erstellt:
|
perform-Methode
|
|
 |  |  |
 |
JTextField jTextField1 = new JTextField();
JTextField jTextField2 = new JTextField();
JTextField jTextField3 = new JTextField();
JTextField jTextField4 = new JTextField();
|  |
 |  |  |
|
|
|
Um die swing -Klasse verwenden zu können,
muß das entsprechende Paket importiert werden.
|
|
|
|
|
|
Die Textfelder werden in ein JPanel eingebaut:
|
|
|
 |  |  |
 |
JPanel jTextPanel = new JPanel();
jTextPanel.setLayout(new BoxLayout(jTextPanel, BoxLayout.Y_AXIS));
jTextPanel.add(new JLabel("Name"));
jTextPanel.ass(jTextField1);
jTextPanel.add(new JLabel("Buy (in Pf)"));
jTextPanel.ass(jTextField2);
jTextPanel.add(new JLabel("Sell (in Pf)"));
jTextPanel.ass(jTextField3);
jTextPanel.add(new JLabel("Amount"));
jTextPanel.ass(jTextField4);
|  |
 |  |  |
|
|
|
Der Dialog muß anschließend dargestellt werden:
|
Dialog
|
|
 |  |  |
 |
JOptionPane.showMessageDialog(null,
jTextPanel,
"New Video-Cassette",
JOptionPane.QUESTION_MESSAGE);
|  |
 |  |  |
|
|
|
Zunächst müssen der Video-Katalog und der Video-Bestand
aus den globalen Listen des Shops geholt werden.
|
|
|
 |  |  |
 |
Catalog videoCatalog =
Shop.getTheShop().getCatalog("Video-Catalog");
CountingStock videoCountingStock =
(CountingStock)Shop.getTheShop().getStock(
"Video-Countingstock");
|  |
 |  |  |
|
|
|
Um Catalog und Stock benutzen zu können, wird eine
weitere import -Anweisung gebraucht:
|
|
|
|
|
|
Aus den vorhin erstellten Textfeldern werden die eingegebenen
Daten für das hinzuzufügende Video
ausgelesen. Einkaufs- und Verkauspreis, sowie die Anzahl sind
int -Werte. Fehlerhafte Eingaben resultieren in
einer NumberFormatException , die abgefangen
werden muß.
|
|
|
 |  |  |
 |
String name = jTextField1();
int buy = 0;
try {
buy = new Integer(jTextField2.getText()).intValue();
}
catch (NumberFormatException ne) {
}
int sell = 0;
try {
sell = new Integer(jTextField3.getText()).intValue();
}
catch (NumberFormatException ne) {
}
int amount = 0;
try {
amount = new Integer(jTextField4.getText()).intValue();
}
catch (NumberFormatException ne) {
}
|  |
 |  |  |
|
|
|
Bei korrekter Eingabe in allen Textfeldern kann das neue Video
mit seinen Daten in den Katalog übernommen
werden. Existiert ein Video mit diesem Namen bereits, wird
eine DuplicateKeyException erzeugt. Ist
die Eingabe fehlerhaft, erscheint ein Dialog mit der
entsprechenden Fehlermeldung.
|
VideoCassette hinzufügen
|
|
 |  |  |
 |
if (sell>0 && buy>0 && amount>0
&& !name.equals("")) {
try {
videoCatalog.add(new VideoCassette(
name,
new QuoteValue(new IntegerValue(buy),
new IntegerValue(sell))),
null);
videoCountingStock.add(name, amount, null);
}
catch (DuplicateKeyException dke) {
JOptionPane.showMessageDialog(null, "Element exists");
}
}
else {
JOptionPane.showMessageDialog(null,
"The given input was not correct!");
}
|  |
 |  |  |
|
|
|
Am Ende der perform -Methode wird das als
nächstes zu betretende Gate
zurückgegeben. In diesem Fall kehrt das Programm wieder
zum selectionGate zurück.
|
|
|
|
|
|
Die Transition zum Hinzufügen
neuer Videos ist vollständig implementiert. Es fehlt noch
die Transition zum Entfernen von Videos
aus dem Angebot des Videoautomaten:
|
removeVideoTransition
|
|
 |  |  |
 |
removeVideoTransition = new Transition()
{
public Gate perform(SaleProcess pOwner, User usr)
{
}
};
|  |
 |  |  |
|
|
|
Zuerst wird die markierte Zeile, die das zu entfernende Video
enthält, aus dem FormSheet in
einer Variable abgespeichert:
|
perform-Methode
|
|
 |  |  |
 |
Object record = stfs.getSelectedRecord();
VideoCassette videoCassette = (VideoCassette)
((CountingStockTableModel.Record)record).getDescriptor();
|  |
 |  |  |
|
|
|
CountingStockTableModel ist Bestandteil des
Pakets data.swing :
|
|
|
|
|
|
Bevor ein Video aus dem Angebot des Automaten genommen werden
kann, muß überprüft werden, ob Kunden
Exemplare dieses Videos entliehen haben. Es werden alle
Kundenkonten durchsucht und die Anzahl der ausgeliehenen
Exemplare ermittelt.
|
|
|
 |  |  |
 |
int rented = 0;
try {
Iterator i = VideoMachine.getAllCustomer().iterator();
while (i.hasNext()) {
rented = rented +
((Customer)i.next()).getStoringStock().countItems(
videoCassette.getName(), null);
}
}
catch (NullPointerException npe) {
}
|  |
 |  |  |
|
|
|
Um den Iterator verwenden zu können, bedarf
es einer weiteren import -Anweisung:
|
|
|
|
|
|
Wurden keine Exemplare des Videos entliehen, kann es entfernt
werden. Besitzt mindestens ein Kunde ein Exemplar des zu
löschenden Videos, kann der Manager dieses Video nicht
aus dem Katalog entfernen. Andernfalls führt das zu
(geschäftsschädigenden!) Dateninkosistenzen.
|
VideoCassette entfernen
|
|
 |  |  |
 |
if (rented <= 0) {
try {
Shop.getTheShop().getCatalog("Video-Catalog").remove(
videoCassette, null);
}
catch (VetoException ve) {
ve.printStackTrace();
JOptionPane.showMessageDialog(null,
"The selected item can't be removed!");
}
}
else {
JOptionPane.showMessageDialog(null,
"There are still rented videos!");
}
|  |
 |  |  |
|
|
|
Die VetoException ist Bestandteil von
data.events :
|
|
|
|
|
|
Am Ende der Transition wird ebenfalls
das selectionGate als nächstes zu
betretendes Gate angegeben:
|
|
|
|
|
|
Das Gate und die beiden Transitions sind fertig implementiert. Das
vorhin erstellte FormSheet
stfs wird am Auswahl-Gate
angemeldet. Zusätzlich werden in der createFormSheetContent -Methode die
entsprechenden Buttons festgelegt.
|
FormSheetContent festlegen
|
|
 |  |  |
 |
stfs.addContentCreator(new FormSheetContentCreator()
{
protected void createFormSheetContent(FormSheet fs)
{
}
});
|  |
 |  |  |
|
|
|
Es werden alle eventuell schon vorhandenen Buttons entfernt:
|
|
|
|
|
|
Zuerst wird ein "New"-Button benötigt,
der in seiner doAction -Methode die
newVideoTransition auslöst.
|
New-Button
|
|
 |  |  |
 |
fs.addButton("New", 100, new sale.Action()
{
public void doAction(SaleProcess p, SalesPoint sp)
{
selectionGate.setNextTransition(newVideoTransition);
}
});
|  |
 |  |  |
|
|
|
Analog dazu führt der "Remove"-Button
zur removeVideoTransition .
|
Remove-Button
|
|
 |  |  |
 |
fs.addButton("Remove", 101, new sale.Action()
{
public void doAction(SaleProcess p, SalesPoint sp)
{
selectionGate.setNextTransition(removeVideoTransition);
}
});
|  |
 |  |  |
|
|
|
Weiterhin wird ein "Ok"-Button erstellt, der
ein Commit ausführt, und ein
"Cancel"-Button, welcher ein
Rollback auslöst.
|
Ok- und Cancel-Button
|
|
 |  |  |
 |
fs.addButton("Ok", 102, new sale.Action()
{
public void doAction(SaleProcess p, SalesPoint sp)
{
selectionGate.setNextTransition(
GateChangeTransition.CHANGE_TO_COMMIT_GATE);
}
});
fs.addButton("Cancel", 103, new sale.Action()
{
public void doAction(SaleProcess p, SalesPoint sp)
{
selectionGate.setNextTransition(
GateChangeTransition.CHANGE_TO_ROLLBACK_GATE);
}
});
|  |
 |  |  |
|
|
|
Die setupMachine -Methode ist fertig
implementiert. Die Klasse SeeVideoStockProcess
wird durch die Methoden getInitialGate
und getLogGate
vervollständigt. Die erste Methode baut den Automaten auf
und setzt das Start-Gate . Die zweite
Methode übergibt das LogGate . Beim
Beenden des Prozesses soll kein Log-Eintrag geschrieben
werden, deshalb wird das StopGate
zurückgegeben.
|
InitialGate und LogGate festlegen
|
|
 |  |  |
 |
public Gate getInitialGate()
{
setupMachine();
return selectionGate;
}
public Gate getLogGate()
{
return getStopGate();
}
|  |
 |  |  |
|
|
|
Der so aufgebaute Prozeß kann an einem SalesPoint gestartet werden. Der Manager
erhält in seinem Menü einen neuen
Menüpunkt. Dazu wird am Ende der getDefaultMenuSheet -Methode der Klasse
Office folgendes eingefügt:
|
Prozeß starten
|
|
 |  |  |
 |
msSubMenu.add(new MenuSheetItem("Edit Video-Stock",
new sale.Action()
{
public void doAction(SaleProcess p, SalesPoint sp)
{
sp.runProcess(new SeeVideoStockProcess());
}
}));
|  |
 |  |  |
|
|
|
Jetzt ist es dem Manager möglich, Einsicht in den Bestand
des Automaten zu nehmen und ihn ggf. zu verändern. Um die
Preise der einzelnen Videos editieren zu können,
muß die Klasse EditableVideoStockTED um
weitere Methoden ergänzt werden. Im einzelnen sind das
die im Interface TableEntryDescriptor
definierten Methoden getCellRenderer ,
die die Darstellung der einzelnen Spalten festlegt, und getValueAt , die den Zellinhalt für das
übergebene Objekt und die angebene Spalte liefert,
desweiteren die Methoden istElementEditable , um zu
überprüfen, ob das Element überhaupt editiert
werden darf, getCellEditor , um ein
Objekt zu ermitteln, mit Hilfe dessen die Elemente einer
bestimmten Spalte editiert werden können und setValueAt , um einen bestimmten Wert in einem
Datensatz festzulegen.
|
EditableVideoStockTED erweitern
|
|
Für die Realisierung der getCellRenderer -Methode werden Variablen zur
Darstellung der einzelnen Formate benötigt. Es werden
über dem Konstruktor von
EditableVideoStockTED Variablen für
Spalteneinträge mit Währung und für
Einträge, die Namen und Mengenangaben
repräsentieren, angelegt:
|
Darstellungsformate festlegen
|
|
 |  |  |
 |
private TableCellRenderer tcrMoney;
private TableCellRenderer tcrName;
private TableCellRenderer tcrCount;
|  |
 |  |  |
|
|
|
Am Ende des Konstruktors der Klasse werden die Variablen dann
initialisiert. Die Ausrichtung für die Darstellung der
Anzahl wird auf zentriert festgelegt.
|
|
|
 |  |  |
 |
tcrMoney = new CurrencyRenderer(
(Currency)Shop.getTheShop().getCatalog("DM"));
tcrName = new DefaultTableCellRenderer();
tcrCount = new DefaultTableCellRenderer();
((DefaultTableCellRenderer)tcrCount).setHorizontalAlignment(
SwingConstants.CENTER);
|  |
 |  |  |
|
|
|
CurrencyRenderer verlangt folgende
import -Anweisung:
|
|
|
|
|
|
Die Methode getCellRenderer liefert
z.B. bei den Spalten
1 und 2 tcrMoney als CellRenderer
zurück. Mit Hilfe einer switch -Anweisung erfolgt
die jeweilge Zuweisung:
|
getCellRenderer-Methode
|
|
 |  |  |
 |
public TableCellRenderer getCellRenderer(int index)
{
switch (index) {
case 0 : return tcrName;
case 3 : return tcrCount;
case 4 : return tcrCount;
default: return tcrMoney;
}
}
|  |
 |  |  |
|
|
|
Die Methode ist damit abgeschlossen und die
getValueAt -Methode kann erstellt werden.
|
getValueAt-Methode
|
|
 |  |  |
 |
public Object getValueAt(Object record, int index)
{
}
|  |
 |  |  |
|
|
|
Zuerst wird die ausgewählte VideoCassette
bestimmt und in einer typgleichen Variable
abgespeichert. Danach wird die Anzahl der Videos, die sich von
dieser Sorte im Automaten befinden, ermittelt.
|
|
|
 |  |  |
 |
VideoCassette videoCassette =
(VideoCassette)((CountingStockTableModel.Record)
record).getDescriptor();
int count =
((CountingStockTableModel.Record)record).getCount();
|  |
 |  |  |
|
|
|
Der übergebende gewünschte Spalteneintrag wird mit
Hilfe einer switch -Anweisung zurückgegeben:
|
|
|
 |  |  |
 |
switch (index) {
case 0:
return videoCassette.getName();
case 1:
return ((QuoteValue)videoCassette.getValue()).getOffer;
case 2:
return ((QuoteValue)videoCassette.getValue()).getBid;
case 3:
return new IntegerValue(count);
}
|  |
 |  |  |
|
|
|
Die Anzahl der ausgeliehenen Videos läßt sich nicht
so einfach feststellen. Mit einem Iterator werden
alle Kundenkonten durchsucht und die Anzahl der Videos
darüber ermittelt. Für die Verwendung des
Iterators wird die Klasse um eine weitere
import -Anweisung ergänzt:
|
|
|
|
|
|
Der switch -Anweisung wird ein weiterer Fall
hinzugefügt:
|
|
|
 |  |  |
 |
case 4:
int rented = 0;
try {
Iterator i = VideoMachine.getAllCustomer().iterator();
while (i.hasNext()) {
rented = rented +
((Customer)i.next()).getStoringStock().countItems(
videoCassette.getName, null);
}
}
catch (NullPointerException npe) {
}
return new IntegerValue(rented);
|  |
 |  |  |
|
|
|
Tritt durch einen Fehler im Programm ein Wert kleiner null
oder größer vier auf, wird als
Standard-Wert null geliefert:
|
|
|
|
|
|
Die Methode ist damit vollständig implementiert, und die
weiteren Methoden können entwickelt werden.
|
|
|
isElementEditable ist in diesem Fall
sehr einfach: Alle Elemente, die in der zweiten oder dritten
Spalte stehen, also alle Einkaufs- und Verkaufspreise, sind
editierbar. Es ist zu beachten, daß die Zählung der
Spalten bei null beginnt.
|
isElementEditable-Methode
|
|
 |  |  |
 |
public boolean isElementEditable(Object record, int index)
{
return index==1 || index==2;
}
|  |
 |  |  |
|
|
|
Die Implementation von getCellEditor
ist schwieriger. Diese Methode soll einen
TableCellEditor , also ein Objekt zum Editieren
von Zellen einer Tabelle, zurückgeben, das in der Lage
ist, Geldbeträge korrekt verändern zu lassen. Das
Interface TableCellEditor ist im Paket
javax.swing.table definiert und besitzt lediglich
eine exisiterende Implementation:
DefaultCellEditor . Diese ist im Paket
javax.swing enthalten. Die Klasse ist in der
Lage, ein JTextField zum Editieren eines Wertes
einer Zelle zu verwenden. Es liegt also nahe, von
DefaultCellEditor eine neue Klasse abzuleiten und
an die eigenen Bedürfnisse anzupassen. Die Klasse
DMCellEditor wird angelegt:
|
getCellEditor-Methode
|
|
 |  |  |
 |
import javax.swing.*;
public class DMCellEditor extends DefaultCellEditor
{
}
|  |
 |  |  |
|
DMCellEditor
|
|
Zum Editieren soll eine Unterklasse von
JTextField , nämlich das im Framework
enthaltene JTextInput , verwendet
werden. Der Konstruktor dieser Klasse benötigt als
Parameter einen Array von Strings ,
in dessen ersten Feld zu jeder Zeit der in das Feld eingebene
Wert steht, und einen Initialwert. Diese beiden Werte werden
als Parameter des Konstruktors von JTextInput weitergereicht. Der Konstruktor
von DMCellEditor hat folgendes Aussehen:
|
|
|
 |  |  |
 |
public DMCellEditor(String[] result, String init)
{
super(new JTextInput(result, init));
}
|  |
 |  |  |
|
Konstruktor
|
|
Für JTextInput wird das Paket
util.swing importiert:
|
|
|
|
|
|
Da das Ergebnis der Eingabe später ausgewertet werden
muß, wird die an den Konstruktor übergebene
Variable in einer typgleichen Variable in der Klasse
gespeichert. Dazu muß sie zunächst vor dem
Konstruktor deklariert werden.
|
|
|
|
|
|
Dieser Variable wird im Konstruktor der entsprechende
Parameter unter dem super -Befehl zugewiesen.
|
|
|
|
|
|
Wenn man sich die in DefaultCellEditor
vorhandenen Methoden ansieht, wird deutlich, daß drei
Methoden angepasst werden müssen:
|
|
|
getTableCellEditor gibt die zum Editieren
verwendete Komponente, in diesem Fall also ein Objekt vom Typ
JTextInput , mit gesetztem Initialwert
zurück. Dazu wird die Komponente zunächst von der
entsprechenden Methode der Oberklasse geholt. An ihr wird mit
Hilfe der toString -Methode, der unter dem Namen
"DM" in der globalen Katalogliste
verzeichneten Währung, der Initialwert gesetzt und die
Komponente zurückgeben:
|
|
|
 |  |  |
 |
public Component getTableCellEditorComponent(
JTable jTable, Object value, boolean isSelected,
int row, int column)
{
Component component =
super.getTableCellEditorComponent(
jTable, value, isSelected, row, column);
((JTextInput)component).setText(((Currency)
Shop.getTheShop().getCatalog("DM")).toString(
(NumberValue)value));
return component;
}
|  |
 |  |  |
|
|
|
Für die in der Methode verwendeten Klassen werden weitere
Pakete importiert:
|
|
|
 |  |  |
 |
import data.*;
import sale.*;
import java.awt.*;
|  |
 |  |  |
|
|
|
Die nächste anzupassende Methode ist
getCellEditorValue . Diese muß einen, dem
Inhalt der Zelle entsprechenden, Geldbetrag
zurückgeben. Dazu wird versucht, das erste Feld von
result mit Hilfe der Währung
"DM" zu parsen und als Rückgabewert zu
verwenden.
|
getCellEditorValue-Methode
|
|
 |  |  |
 |
public Object getCellEditorValue()
{
try {
return ((Currency)Shop.getTheShop().getCatalog(
"DM").parse(result[0]);
}
catch(ParseException psex) {
return new IntegerValue(0);
}
}
|  |
 |  |  |
|
|
|
Die ParseException befindet sich im Paket
java.text :
|
|
|
|
|
|
Zuletzt muß stopCellEditing angepaßt
werden. Diese Methode versucht das Editieren der
Tabellenzellen zu beenden und liefert einen Booleschen Wert
zurück, der angibt, ob die Operation erfolgreich war. Mit
dieser Methode läßt sich verhindern, daß
ungültige Werte eingegeben werden. Im Fall der Klasse
DMCellEditor darf das Editieren nur beendet
werden, wenn der eingegebene Text als Geldbetrag der
Währung "DM" geparst werden
kann. Demzufolge wird genau das versucht und im Erfolgsfall
der Rückgabewert vom Urteil der entsprechenden Methode
der Oberklasse abhängig gemacht. Wurde beim Parsen eine
Exception erzeugt, wird false zurückgegeben.
|
stopCellEditing-Methode
|
|
 |  |  |
 |
public boolean stopCellEditing()
{
try {
((Currency)Shop.getTheShop().getCatalog(
"DM")).parse(result[0]);
}
catch(ParseException pexc) {
return false;
}
return super.stopCellEditing();
}
|  |
 |  |  |
|
|
|
Damit ist DMCellEditor fertiggestellt und kann in
EditableVideoStockTED verwendet werden. Dort ist
nun die Methode getCellEditor zu
implementieren. Sie deklariert ein Objekt vom Typ
TableCellEditor als Rückgabewert. Diese
Klasse muß dem Compiler über eine
import -Anweisung bekannt gemacht werden:
|
|
|
 |  |  |
 |
import javax.swing.table.*;
|  |
 |  |  |
|
|
|
Die zu implementierende Methode gibt für die zweite und dritte
Spalte ein Objekt des gerade erstellten DMCellEditors
zurück. Für alle anderen Spalten bleibt die entsprechende
Methode der Oberklasse AbstractTableEntryDescriptor
verantwortlich.
|
|
|
 |  |  |
 |
public TableCellEditor getCellEditor(int index)
{
if (index==1 || index==2)
return new DMCellEditor(new String[1], "");
else
return super.getCellEditor(index);
}
|  |
 |  |  |
|
|
|
Die letzte, für diese Klasse zu implementierende, Methode
ist setValueAt . Sie bekommt den aktuellen
Datensatz, die Spalte und den zu setzenden Wert
übergeben.
|
|
|
 |  |  |
 |
public void setValueAt(Object record, int index,
Object value)
{
}
|  |
 |  |  |
|
setValueAt-Methode
|
|
In dieser Methode wird zunächst die zu verändernde
VideoCassette aus dem Datensatz ermittelt.
|
|
|
 |  |  |
 |
VideoCassette videoCassette =
(VideoCassette)((CountingStockTableModel.Record)
record).getDescriptor();
|  |
 |  |  |
|
|
|
Die so ermittelte VideoCassette darf jedoch nicht
direkt verändert werden. Sie wurde nur zur Darstellung in
der Tabelle empfangen, aber nicht zum Editieren. Es besteht
Lese-, aber kein Schreibrecht. Um die
VideoCassette verändern zu können,
muß sie mit Schreibrecht empfangen werden. Dazu
muß der dafür zuständigen
get -Methode des Catalogs
explizit mitgeteilt werden, daß eine Veränderung
geplant ist. Das Item wird darauf speziell vorbereitet:
|
|
|
 |  |  |
 |
try {
Videocassette videoCassetteToEdit =
(VideoCassette)videoCountingStock.getCatalog(null).get(
videoCassette.getName(), db, true);
QuoteValue quoteValue =
(QuoteValue)videoCassetteToEdit.getValue();
if (index == 1)
videoCassetteToEdit.setValue(
new QuoteValue(quoteValue.getBid(), (Value)value));
if (index == 2)
videoCassetteToEdit.setValue(
new QuoteValue((Value)value, quoteValue.getOffer()));
}
catch(VetoException vexc) {
JOptionPane.showMessageDialog(null,
"The editing of that item was vetoed. It might be in use.");
}
|  |
 |  |  |
|
|
|
Die VetoException ist Bestandteil des
Pakets data.events und JOptionPane
von javax.swing .
|
|
|
 |  |  |
 |
import data.events.*;
import javax.swing.*;
|  |
 |  |  |
|
|
|
Zum Abschluß der Klasse EditableVideoStock
wird die Methode getColumnClass mit Code
gefüllt. Diese wird immer dann benötigt, wenn die
Methoden getCellRenderer und getCellEditor null
zurückgeben.
|
|
|
 |  |  |
 |
public Class getColumnClass(int index)
{
return null;
}
|  |
 |  |  |
|
getColumnClass-Methode
|
|
Die Entwicklung des Videoautomaten ist damit beendet. Viel
Spaß beim Betreiben des Automaten!!
|
|
|
|
Hier der Quelltext der in diesem Kapitel geänderten Klassen:
|
|
|
|
|