1   package kerhoswing;
2   
3   import java.awt.Color;
4   import java.awt.event.ActionEvent;
5   import java.awt.event.ActionListener;
6   import java.awt.event.KeyAdapter;
7   import java.awt.event.KeyEvent;
8   import java.util.Collection;
9   import javax.swing.JComboBox;
10  
11  import javax.swing.JList;
12  import javax.swing.JTextField;
13  import javax.swing.DefaultListModel;
14  import javax.swing.JLabel;
15  import javax.swing.JOptionPane;
16  import javax.swing.JPanel;
17  import javax.swing.event.ListSelectionEvent;
18  import javax.swing.event.ListSelectionListener;
19  import kerho.Jasen;
20  import kerho.Kerho;
21  import kerho.SailoException;
22  import static javax.swing.SwingConstants.*;
23  
24  /**
25   * Luokka joka käsittelee kerhoa Swing-komponenteilla.
26   * Luokan käyttö:
27   * <pre>
28   * 1) Tee jollakin tavalla lomake, jossa on muodostajan vaatimat komponentit
29   * 2) Laita lomakkeelle myös Lisää ja Talleta -napit niin halutessasi
30   * 3) Luo koodissa lomakkeella KerhoSwing-olio
31   *        kerhoswing = new KerhoSwing(cbKentat,editHaku,listJasenet,panelJasen);
32   *        String virhe = kerhoswing.lueTiedosto("kelmit");
33   *        if ( virhe != null ) JOptionPane.showMessageDialog(null, virhe);
34   * 4) Kutsu nappien tapahtumista olion lisaa ja talleta -metodeja.
35   *         kerhoswing.lisaa();
36   *         kerhoswing.talleta();
37   * 5) Jotta kaikki tulee talletettua, kutsu ohjelmasta poistuvissa paikoissa
38   *         kerhoswing.tarkistaMuutos();        
39   * </pre>
40   * @author vesal
41   * @version 10.4.2009
42   */
43  public class KerhoSwing {
44  
45      private static Color virheVari = new Color(255, 0, 0);
46      private static Color normaaliVari = new Color(255, 255, 255);
47      private final static Jasen apujasen = new Jasen();
48      private final JComboBox cbKentat;
49      private final JTextField editHaku;
50      private final JList listJasenet;
51      private final JPanel panelJasen;
52      private final Kerho kerho;
53      private final DefaultListModel listModel = new DefaultListModel();
54      private Jasen jasen;        // Kohdalla oleva jäsen
55      private Jasen editJasen;    // Kohdalla oleva jäsen jos tehty muutoksia
56      private JTextField edits[]; // Jäsenen kenttiä vastaavat edit-kentät
57  
58      /**
59       * Alustaa luokan niin, että se voi käyttää  Swing-komponentteja
60       * @param cbKentat  alasvetolista, johon kenttien nimet laitetaan
61       * @param editHaku  edit-ikkunan johon kirjoitetana hakuehto
62       * @param listJasenet lista, johon tulee hakuehdon täyttävät jäsenet
63       * @param panelJasen paneeli johon lisätään jäsentietoja
64       */
65      public KerhoSwing(JComboBox cbKentat, JTextField editHaku, JList listJasenet, JPanel panelJasen) {
66          kerho = new Kerho();
67          this.cbKentat = cbKentat;
68          this.editHaku = editHaku;
69          this.listJasenet = listJasenet;
70          this.panelJasen = panelJasen;
71  
72  
73          cbKentat.removeAllItems();
74          listJasenet.setModel(listModel);
75  
76          for (int k = apujasen.ekaKentta(); k < apujasen.getKenttia(); k++) {
77              cbKentat.addItem(apujasen.getKysymys(k));
78          }
79  
80          editHaku.addKeyListener(new KeyAdapter() {
81              @Override  public void keyReleased(KeyEvent e) { hae(); }
82          });
83  
84          cbKentat.addActionListener(new ActionListener() {
85              public void actionPerformed(ActionEvent e) { hae();}
86          });
87  
88          listJasenet.addListSelectionListener(new ListSelectionListener() {
89              public void valueChanged(ListSelectionEvent e) { nayta(); }
90          });
91  
92          luoNaytto();
93          hae();
94      }
95  
96      
97      /**
98       * Asetetaan editoitava jäsen
99       * @param j uusi viite editJasenelle
100      */
101     private void setEditJasen(Jasen j) {
102         editJasen = j;
103     }
104     
105     
106     /**
107      * Tekee uuden tyhjän jäsenen editointia varten
108      */
109     public void lisaa() {
110         tarkistaMuutos();
111         jasen = new Jasen();
112         jasen.rekisteroi();
113         setEditJasen(null);
114         laitaJasen();
115     }
116 
117 
118     /**
119      * Lukee kerhon tiedot tiedostosta
120      * @param s tiedoston nimi
121      * @return null jos onnistuu, muuten virheilmoitus
122      */
123     public String lueTiedosto(String s) {
124         try {
125             kerho.lueTiedostosta(s);
126             hae();
127             return null;
128         } catch (SailoException e) {
129             hae();
130             return e.getMessage();
131         }
132 
133     }
134     
135     
136     /**
137      * Tutkii onko editoitavaan jäseneen tehty muutoksia, jotka kannattaa
138      * tallettaa.
139      * @return false jos ei muutoksia
140      */
141     private boolean muuttunut() {
142         if ( jasen == null ) return false;
143         if ( editJasen == null ) return false;
144         return !jasen.equals(editJasen);
145     }
146     
147     
148     /**
149      * Tallettaa nykyisen mahdollisesti muutetun jäsenen ja sitten koko tiedoston
150      * @return null jos menee hyvin, muuten virheteksti
151      */
152     public String talleta() {
153         try {
154             if ( muuttunut() ) { kerho.korvaa(editJasen); jasen = editJasen; }
155             setEditJasen(null);
156             hae();
157             kerho.talleta();
158             return null;
159         } catch (SailoException ex) {
160             JOptionPane.showMessageDialog(null, "Talletuksessa ongelmia! " + ex.getMessage());
161             return ex.getMessage();
162         }
163     }
164 
165 
166     /**
167      * Luokka johon talletetaan listaan laitettavat alkiot.
168      * Ainoa tehtävä on pitää kiinni jäsenestä ja palauttaa jäsenen nimi merkkijonona  
169      */
170     private static class JasenList {
171         private final Jasen jasen;
172         public JasenList(Jasen jasen) {
173             this.jasen = jasen;
174         }
175 
176         public Jasen getJasen() {
177             return jasen;
178         }
179 
180         @Override
181         public String toString() {
182             return jasen.anna(jasen.ekaKentta());
183         }
184 
185     }
186 
187     /**
188      * Suorittaa niiden jäsenten hakemisen, joiden valittu kenttä täyttää hakuehdon
189      */
190     private void hae() {
191         int k = cbKentat.getSelectedIndex() + apujasen.ekaKentta();
192         String ehto = editHaku.getText();
193         if (ehto.indexOf('*') < 0) {
194             ehto = "*" + ehto + "*";
195         }
196         Collection<Jasen> tulos = kerho.etsi(ehto, k);
197         listModel.removeAllElements();
198 
199         for (Jasen j : tulos) {
200             listModel.addElement(new JasenList(j)); // NOPMD
201         }
202     }
203 
204 
205     /**
206      * Laittaa jäsenen tiedot edit-kenttiin
207      */
208     private void laitaJasen() {
209         if ( jasen == null ) return;
210         for (int i = 0, k = jasen.ekaKentta(); k < jasen.getKenttia(); k++, i++) {
211             edits[i].setText(jasen.anna(k));
212             edits[i].setBackground(normaaliVari);
213             edits[i].setToolTipText("");
214         }
215     }
216 
217 
218     /**
219      * Tarkitetaan onko jäsenen tiedot muuttuneet ja jos on, kysytään halutaanko tallentaa
220      */
221     public void tarkistaMuutos() {
222         if ( muuttunut() ) {
223             int vastaus = JOptionPane.showConfirmDialog(null, "Talletetaanko?", "Jäsen muuttunut!", JOptionPane.YES_NO_OPTION);
224             if ( vastaus == JOptionPane.YES_OPTION ) talleta();
225          }
226     }
227 
228 
229     /**
230      * Näyttää listasta valitun jäsenen tiedot
231      */
232     private void nayta() {
233         int ind = listJasenet.getSelectedIndex();
234         if (ind < 0) return;
235         tarkistaMuutos();
236         jasen = ((JasenList)listModel.get(ind)).getJasen();
237         setEditJasen(null); 
238         laitaJasen();
239     }
240 
241      
242     /**
243      * Käsittelee edit-kenttään tulleen muutoksen jäseneen.
244      * Mikäli jäsentä ei vielä ole editoitu, luodaan jäsenestä
245      * kopioi editJasen-olioon ja muutokset kohdistetaan tähän
246      * jäseneen.  Näin voidaan muutoksia verrata jasen-olioon
247      * ja tunnistetaan muutostarpeet.  Jos muutosta ei voida
248      * sijoittaa jäseneen, muutetaan taustaväri punaiseksi.
249      * @param edit muuttunut kenttä
250      */
251     private void kasitteleMuutos(JTextField edit) {
252         if (jasen == null) {
253             jasen = new Jasen();
254             jasen.rekisteroi();
255             setEditJasen(null);
256         }
257         if ( editJasen == null ) setEditJasen(jasen.clone());
258         String s = edit.getText();
259         int k = Integer.parseInt(edit.getName().substring(1));
260         String virhe = editJasen.aseta(k, s);
261         if (virhe == null) {
262             edit.setToolTipText("");
263             edit.setBackground(normaaliVari);
264         } else {
265             edit.setToolTipText(virhe);
266             edit.setBackground(virheVari);
267         }
268     }
269 
270     
271     /**
272      * Luo panelJasen:een jäsenen kenttiä vastaavat labelit ja edit-kentät
273      */
274     private void luoNaytto() {
275         int n = apujasen.getKenttia() - apujasen.ekaKentta();
276         edits = new JTextField[n];
277         panelJasen.setLayout(new java.awt.GridLayout(n, 2, 10, 2));
278 
279         for (int i = 0, k = apujasen.ekaKentta(); k < apujasen.getKenttia(); k++, i++) {
280             JLabel jLabel = new JLabel(apujasen.getKysymys(k)); // NOPMD
281             jLabel.setName("jLabel" + k);
282             jLabel.setHorizontalAlignment(TRAILING);
283             panelJasen.add(jLabel);
284             JTextField edit = new JTextField(""); // NOPMD
285             edits[i] = edit;
286             edit.setName("e" + k);
287             panelJasen.add(edit);
288             edit.addKeyListener(new KeyAdapter() { // NOPMD
289                 @Override
290                 public void keyReleased(KeyEvent e) {
291                     kasitteleMuutos((JTextField) e.getComponent());
292                 }
293             });
294         }
295     }
296 }
297