001package com.studentgui.app; 002 003import java.awt.BorderLayout; 004import java.awt.FlowLayout; 005import java.awt.Font; 006import java.awt.Frame; 007 008import javax.swing.JButton; 009import javax.swing.JCheckBox; 010import javax.swing.JDialog; 011import javax.swing.JLabel; 012import javax.swing.JPanel; 013import javax.swing.JTextField; 014 015import com.studentgui.apphelpers.Settings; 016 017/** 018 * Simple modal preferences dialog exposing a few runtime toggles that 019 * affect chart rendering. Preferences are persisted via 020 * {@link com.studentgui.apphelpers.Settings} and listeners are notified 021 * through {@link Main#notifySettingsChanged()}. 022 */ 023public final class PreferencesDialog { 024 private PreferencesDialog() { throw new AssertionError(); } 025 026 /** 027 * Show the modal preferences dialog. The dialog persists changes to 028 * {@link com.studentgui.apphelpers.Settings} and notifies runtime 029 * listeners via {@link Main#notifySettingsChanged()}. 030 * 031 * @param owner optional parent frame for dialog positioning 032 */ 033 public static void showDialog(final Frame owner) { 034 final JDialog dlg = new JDialog(owner, "Preferences", true); 035 dlg.setLayout(new BorderLayout()); 036 037 JPanel center = new JPanel(new FlowLayout(FlowLayout.LEFT)); 038 boolean jitterEnabled = Boolean.parseBoolean(Settings.get("jitter.enabled", "true")); 039 boolean deterministic = Boolean.parseBoolean(Settings.get("jitter.deterministic", "false")); 040 String seed = Settings.get("jitter.seed", ""); 041 boolean dumpsEnabled = Boolean.parseBoolean(Settings.get("dump.enabled", "false")); 042 043 final JCheckBox jitterCb = new JCheckBox("Enable jitter", jitterEnabled); 044 final JCheckBox detCb = new JCheckBox("Deterministic (seeded)", deterministic); 045 final JTextField seedField = new JTextField(seed == null ? "" : seed, 12); 046 final JCheckBox dumpsCb = new JCheckBox("Enable per-page data dumps", dumpsEnabled); 047 048 center.add(jitterCb); 049 center.add(detCb); 050 center.add(dumpsCb); 051 JLabel seedLabel = new JLabel("Seed:"); 052 seedLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 24)); 053 center.add(seedLabel); 054 center.add(seedField); 055 056 JPanel south = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 057 JButton save = new JButton("Save"); 058 JButton cancel = new JButton("Cancel"); 059 060 save.addActionListener(e -> { 061 Settings.put("jitter.enabled", String.valueOf(jitterCb.isSelected())); 062 Settings.put("jitter.deterministic", String.valueOf(detCb.isSelected())); 063 Settings.put("jitter.seed", seedField.getText().trim()); 064 Settings.put("dump.enabled", String.valueOf(dumpsCb.isSelected())); 065 // notify runtime listeners 066 Main.notifySettingsChanged(); 067 dlg.dispose(); 068 }); 069 070 cancel.addActionListener(e -> dlg.dispose()); 071 south.add(cancel); 072 south.add(save); 073 074 dlg.add(center, BorderLayout.CENTER); 075 dlg.add(south, BorderLayout.SOUTH); 076 dlg.pack(); 077 dlg.setLocationRelativeTo(owner); 078 dlg.setVisible(true); 079 } 080}