chiark / gitweb /
Forbid undo of new-game if it would change the params.
[sgt-puzzles.git] / PuzzleApplet.java
index ef7ca7e507ae52d5a08daa8ab3dcfba5bfe135ab..8455734dd128e734bbb4e16dd81cb6f077a8329e 100644 (file)
@@ -28,11 +28,15 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
     private JFrame mainWindow;
 
     private JMenu typeMenu;
+    private JMenuItem[] typeMenuItems;
+    private int customMenuItemIndex;
+
     private JMenuItem solveCommand;
     private Color[] colors;
     private JLabel statusBar;
     private PuzzlePanel pp;
     private Runtime runtime;
+    private String[] puzzle_args;
     private Graphics2D  gg;
     private Timer timer;
     private int xarg1, xarg2, xarg3;
@@ -57,19 +61,19 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
             JMenuBar menubar = new JMenuBar();
             JMenu jm;
             menubar.add(jm = new JMenu("Game"));
-            addMenuItemWithKey(jm, "New", 'n');
+            addMenuItemCallback(jm, "New", "jcallback_newgame_event");
             addMenuItemCallback(jm, "Restart", "jcallback_restart_event");
             addMenuItemCallback(jm, "Specific...", "jcallback_config_event", CFG_DESC);
             addMenuItemCallback(jm, "Random Seed...", "jcallback_config_event", CFG_SEED);
             jm.addSeparator();
-            addMenuItemWithKey(jm, "Undo", 'u');
-            addMenuItemWithKey(jm, "Redo", 'r');
+            addMenuItemCallback(jm, "Undo", "jcallback_undo_event");
+            addMenuItemCallback(jm, "Redo", "jcallback_redo_event");
             jm.addSeparator();
             solveCommand = addMenuItemCallback(jm, "Solve", "jcallback_solve_event");
             solveCommand.setEnabled(false);
             if (mainWindow != null) {
                 jm.addSeparator();
-                addMenuItemWithKey(jm, "Exit", 'q');
+                addMenuItemCallback(jm, "Exit", "jcallback_quit_event");
             }
             menubar.add(typeMenu = new JMenu("Type"));
             typeMenu.setVisible(false);
@@ -122,7 +126,12 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                     }
                 }
                 public void keyTyped(KeyEvent e) {
-                    runtimeCall("jcallback_key_event", new int[] {0, 0, e.getKeyChar()});
+                    int key = e.getKeyChar();
+                    if (key == 26 && e.isShiftDown() && e.isControlDown()) {
+                        runtimeCall("jcallback_redo_event", new int[0]);
+                        return;
+                    }
+                    runtimeCall("jcallback_key_event", new int[] {0, 0, key});
                 }
             });
             pp.addMouseListener(new MouseAdapter() {
@@ -172,9 +181,22 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                     runtimeCall("jcallback_timer_func", new int[0]);
                 }
             });
+           String gameid;
+           try {
+               gameid = getParameter("game_id");
+           } catch (java.lang.NullPointerException ex) {
+               gameid = null;
+           }
+           if (gameid == null) {
+               puzzle_args = null;
+           } else {
+               puzzle_args = new String[2];
+               puzzle_args[0] = "puzzle";
+               puzzle_args[1] = gameid;
+           }
             SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
-                    runtime.start();
+                    runtime.start(puzzle_args);
                     runtime.execute();
                 }
             });
@@ -200,22 +222,18 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
         runtimeCall("jcallback_resize", new int[] {pp.getWidth(), pp.getHeight()});
     }
 
-    private void addMenuItemWithKey(JMenu jm, String name, int key) {
-        addMenuItemCallback(jm, name, "jcallback_menu_key_event", key);
-    }
-
     private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int arg) {
-        return addMenuItemCallback(jm, name, callback, new int[] {arg});
+        return addMenuItemCallback(jm, name, callback, new int[] {arg}, false);
     }
 
     private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback) {
-        return addMenuItemCallback(jm, name, callback, new int[0]);
+        return addMenuItemCallback(jm, name, callback, new int[0], false);
     }
 
-    private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int[] args) {
+    private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int[] args, boolean checkbox) {
         JMenuItem jmi;
-        if (jm == typeMenu)
-            typeMenu.add(jmi = new JCheckBoxMenuItem(name));
+        if (checkbox)
+            jm.add(jmi = new JCheckBoxMenuItem(name));
         else
         jm.add(jmi = new JMenuItem(name));
         jmi.addActionListener(new ActionListener() {
@@ -247,12 +265,29 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
         } else {
             typeMenu.setVisible(true);
         }
-        addMenuItemCallback(typeMenu, "Custom...", "jcallback_config_event", CFG_SETTINGS);
+        typeMenuItems[customMenuItemIndex] =
+            addMenuItemCallback(typeMenu, "Custom...",
+                                "jcallback_config_event",
+                                new int[] {CFG_SETTINGS}, true);
     }
 
-    private void addTypeItem(String name, final int ptrGameParams) {
+    private void addTypeItem
+        (JMenu targetMenu, String name, int newId, final int ptrGameParams) {
+
         typeMenu.setVisible(true);
-        addMenuItemCallback(typeMenu, name, "jcallback_preset_event", ptrGameParams);
+        typeMenuItems[newId] =
+            addMenuItemCallback(targetMenu, name,
+                                "jcallback_preset_event",
+                                new int[] {ptrGameParams}, true);
+    }
+
+    private void addTypeSubmenu
+        (JMenu targetMenu, String name, int newId) {
+
+        JMenu newMenu = new JMenu(name);
+        newMenu.setVisible(true);
+        typeMenuItems[newId] = newMenu;
+        targetMenu.add(newMenu);
     }
 
     public int call(int cmd, int arg1, int arg2, int arg3) {
@@ -265,8 +300,20 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                 if ((arg2 & 4) != 0) solveCommand.setEnabled(true);
                 colors = new Color[arg3];
                 return 0;
-            case 1: // Type menu item
-                addTypeItem(runtime.cstring(arg1), arg2);
+            case 1: // configure Type menu
+                if (arg1 == 0) {
+                    // preliminary setup
+                    typeMenuItems = new JMenuItem[arg2 + 2];
+                    typeMenuItems[arg2] = typeMenu;
+                    customMenuItemIndex = arg2 + 1;
+                    return arg2;
+                } else if (xarg1 != 0) {
+                    addTypeItem((JMenu)typeMenuItems[arg2],
+                                runtime.cstring(arg1), arg3, xarg1);
+                } else {
+                    addTypeSubmenu((JMenu)typeMenuItems[arg2],
+                                   runtime.cstring(arg1), arg3);
+                }
                 return 0;
             case 2: // MessageBox
                 JOptionPane.showMessageDialog(this, runtime.cstring(arg2), runtime.cstring(arg1), arg3 == 0 ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.ERROR_MESSAGE);
@@ -282,24 +329,29 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                 case 0:
                    String text = runtime.cstring(arg2);
                    if (text.equals("")) text = " ";
-                   System.out.println("status '" + text + "'");
-                   statusBar.setText(text); break;
+                   statusBar.setText(text);
+                   break;
                 case 1:
                     gg = pp.backBuffer.createGraphics();
-                    if (arg2 != 0 || arg3 != 0) {
-                        gg.setColor(Color.black);
-                        gg.fillRect(0, 0, arg2, getHeight());
-                        gg.fillRect(0, 0, getWidth(), arg3);
-                        gg.fillRect(getWidth() - arg2, 0, arg2, getHeight());
-                        gg.fillRect(0, getHeight() - arg3, getWidth(), arg3);
-                        gg.setClip(arg2, arg3, getWidth()-2*arg2, getHeight()-2*arg3);
+                    if (arg2 != 0 || arg3 != 0 ||
+                       arg2 + xarg2 != getWidth() ||
+                       arg3 + xarg3 != getHeight()) {
+                       int left = arg2, right = arg2 + xarg2;
+                       int top = arg3, bottom = arg3 + xarg3;
+                       int width = getWidth(), height = getHeight();
+                        gg.setColor(colors != null ? colors[0] : Color.black);
+                        gg.fillRect(0, 0, left, height);
+                        gg.fillRect(right, 0, width-right, height);
+                        gg.fillRect(0, 0, width, top);
+                        gg.fillRect(0, bottom, width, height-bottom);
+                        gg.setClip(left, top, right-left, bottom-top);
                     }
                     break;
                 case 2: gg.dispose(); pp.repaint(); break;
                 case 3: gg.setClip(arg2, arg3, xarg1, xarg2); break;
                 case 4:
                     if (arg2 == 0 && arg3 == 0) {
-                        gg.fillRect(0, 0, getWidth(), getHeight());
+                        gg.setClip(0, 0, getWidth(), getHeight());
                     } else {
                         gg.setClip(arg2, arg3, getWidth()-2*arg2, getHeight()-2*arg3);
                     }
@@ -359,7 +411,7 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
             case 7: // string
                 gg.setColor(colors[arg2]);
                 {
-                    String text = runtime.cstring(arg3);
+                    String text = runtime.utfstring(arg3);
                     Font ft = new Font((xarg3 & 0x10) != 0 ? "Monospaced" : "Dialog",
                             Font.PLAIN, 100);
                     int height100 = this.getFontMetrics(ft).getHeight();
@@ -368,8 +420,6 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                     int asc = fm.getAscent(), desc = fm.getDescent();
                     if ((xarg3 & ALIGN_VCENTRE) != 0)
                         xarg2 += asc - (asc+desc)/2;
-                    else
-                        xarg2 += asc;
                     int wid = fm.stringWidth(text);
                     if ((xarg3 & ALIGN_HCENTRE) != 0)
                         xarg1 -= wid / 2;
@@ -415,10 +465,11 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                 dlg = null;
                 return 0;
             case 13: // tick a menu item
-                if (arg1 < 0) arg1 = typeMenu.getItemCount() - 1;
-                for (int i = 0; i < typeMenu.getItemCount(); i++) {
-                    if (typeMenu.getMenuComponent(i) instanceof JCheckBoxMenuItem) {
-                        ((JCheckBoxMenuItem)typeMenu.getMenuComponent(i)).setSelected(arg1 == i);
+                if (arg1 < 0) arg1 = customMenuItemIndex;
+                for (int i = 0; i < typeMenuItems.length; i++) {
+                    if (typeMenuItems[i] instanceof JCheckBoxMenuItem) {
+                        ((JCheckBoxMenuItem)typeMenuItems[i]).setSelected
+                            (arg1 == i);
                     }
                 }
                 return 0;
@@ -590,7 +641,7 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
                     break;
                 case C_CHOICES:
                     JComboBox jcm = (JComboBox)cc.component;
-                    runtimeCall("jcallback_config_set_boolean", new int[] {cc.configItemPointer, jcm.getSelectedIndex()});
+                    runtimeCall("jcallback_config_set_choice", new int[] {cc.configItemPointer, jcm.getSelectedIndex()});
                     break;
                 }
             }