/**
 * MinDialog.java  - "Programmering i Java", 4.utgave - 2009-07-01
 *
 * Klassen ligger i pakken mittBibliotek.
 * Dialog med OK- og Avbryt-knapp. Til bruk når man skal lage egne dialogvinduer.
 *
 * En subklasse kan definere sin egen okData()-metode for kontroll av data.
 * Dersom vinduet lukkes ved å trykke i øverste høyre hjørne, blir brukeren spurt
 * om eventuelle registrerte data skal lagres.
 *
 * OK-knappen er satt som standardknapp, og den reagerer dermed på
 * Enter-tasten. Avbryt-knappen er knyttet til Escape-tasten.
 */

package mittBibliotek;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JOptionPane.*;

public class MinDialog extends JDialog {
  private boolean ok = false; // har brukeren trykket OK-knappen?
  private JButton okKnapp  = new JButton("OK");
  private KnappePanel knappepanelet = new KnappePanel();

  protected MinDialog(JFrame foreldre, String tittel) {
    super(foreldre, tittel, true);
    addWindowListener(new Vinduslytter());

    /* Vi vil programmere lukking av vinduet selv: */
    setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

    /* Setter OK-knappen til standardknappen. Reagerer på Enter-tasten. */
    JRootPane tavle = getRootPane();
    tavle.setDefaultButton(okKnapp);
  }

  /**
   * Til bruk for subklasser som kan kontrollere verdien til ok
   */
  protected boolean isOk() {
    return ok;
  }

  /**
   * Til bruk for subklasser som kan sette verdien til ok
   */
  protected void setOk(boolean verdi) {
    ok = verdi;
  }

  /**
   * Returnerer en referanse til knappepanelet.
   * Subklassen må plassere dette panelet riktig i vinduet.
   */
  protected JPanel getKnappepanel() {
    return knappepanelet;
  }

  /**
   * Subklasser kan ha sin egen utgave av metoden okData() dersom det er
   * ønskelig at dataene skal kontrolleres før de eventuelt godtas.
   */
  protected boolean okData() {
    return true;
  }

  /* Privat klasse med panelet som inneholder de to knappene, OK og Avbryt. */
  private class KnappePanel extends JPanel {
    public KnappePanel() {
      JButton avbrytKnapp = new JButton("Avbryt");
      Kommandolytter knappelytter = new Kommandolytter();
      add(okKnapp);
      add(avbrytKnapp);
      okKnapp.addActionListener(knappelytter);
      avbrytKnapp.addActionListener(knappelytter);

      /* Definerer akselerasjonstast til Avbryt-knappen */
    KeyStroke escapeTasten = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
      InputMap tastekart =
             avbrytKnapp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
      tastekart.put(escapeTasten, "Avbryt"); // knytter en kommando til escape-tasten
      ActionMap aksjonskart = avbrytKnapp.getActionMap();
      aksjonskart.put("Avbryt", knappelytter); // definerer en aksjon
    }
  }

  /*
   * Privat klasse som beskriver hva som skal skje når brukeren trykker OK og Avbryt.
   * Metoden put() i klassen ActionMap (se over) krever Action som andre
   * argument. Action er et sub-interface til ActionListener. Interfacet
   * inneholder mange metoder; klassen AbstractAction implementerer
   * disse metodene, og vi kan bruke den som en adapterklasse.
   */
  private class Kommandolytter extends AbstractAction {
    public void actionPerformed(ActionEvent hendelse) {
      String kommando = hendelse.getActionCommand();
      if (kommando.equals("OK")){
        if (okData()) {  // skal bare lukke vinduet dersom ok data
          ok = true;
          setVisible(false);
        }
      } else {  // brukeren har trykket på Avbryt, lukker vinduet
        ok = false;
        setVisible(false);
      }
    }
  }

  /*
   * Privat klasse som beskriver hva som skal skje når brukeren prøver å lukke
   * vinduet. Vi spør vi om eventuelle data skal lagres. Hvis ja, blir de lagret
   * dersom okData() returnerer true.
   */
  private class Vinduslytter extends WindowAdapter {
    public void windowClosing(WindowEvent hendelse) {
      int svar = showConfirmDialog(MinDialog.this,
                 "Skal eventuelle registrerte data lagres? ",
                 "Lukking av dialogvindu", YES_NO_OPTION);
      if (svar == YES_OPTION) {
        if (okData()) {  // skal bare lukke vinduet dersom ok data
          ok = true;
          setVisible(false);
        }
      } else {  // data skal ikke lagres, lukker vinduet
        ok = false;
        setVisible(false);
      }
    }
  }
}