PuzzleApplet.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*
  2. * PuzzleApplet.java: NestedVM applet for the puzzle collection
  3. */
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.awt.image.BufferedImage;
  7. import java.util.*;
  8. import javax.swing.*;
  9. import javax.swing.border.BevelBorder;
  10. import javax.swing.Timer;
  11. import java.util.List;
  12. import org.ibex.nestedvm.Runtime;
  13. public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
  14. private static final long serialVersionUID = 1L;
  15. private static final int CFG_SETTINGS = 0, CFG_SEED = 1, CFG_DESC = 2,
  16. LEFT_BUTTON = 0x0200, MIDDLE_BUTTON = 0x201, RIGHT_BUTTON = 0x202,
  17. LEFT_DRAG = 0x203, MIDDLE_DRAG = 0x204, RIGHT_DRAG = 0x205,
  18. LEFT_RELEASE = 0x206, CURSOR_UP = 0x209, CURSOR_DOWN = 0x20a,
  19. CURSOR_LEFT = 0x20b, CURSOR_RIGHT = 0x20c, MOD_CTRL = 0x1000,
  20. MOD_SHFT = 0x2000, MOD_NUM_KEYPAD = 0x4000, ALIGN_VCENTRE = 0x100,
  21. ALIGN_HCENTRE = 0x001, ALIGN_HRIGHT = 0x002, C_STRING = 0,
  22. C_CHOICES = 1, C_BOOLEAN = 2;
  23. private JFrame mainWindow;
  24. private JMenu typeMenu;
  25. private JMenuItem[] typeMenuItems;
  26. private int customMenuItemIndex;
  27. private JMenuItem solveCommand;
  28. private Color[] colors;
  29. private JLabel statusBar;
  30. private PuzzlePanel pp;
  31. private Runtime runtime;
  32. private String[] puzzle_args;
  33. private Graphics2D gg;
  34. private Timer timer;
  35. private int xarg1, xarg2, xarg3;
  36. private int[] xPoints, yPoints;
  37. private BufferedImage[] blitters = new BufferedImage[512];
  38. private ConfigDialog dlg;
  39. static {
  40. try {
  41. UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  42. } catch (Exception ex) {
  43. ex.printStackTrace();
  44. }
  45. }
  46. public void init() {
  47. try {
  48. Container cp = getContentPane();
  49. cp.setLayout(new BorderLayout());
  50. runtime = (Runtime) Class.forName("PuzzleEngine").newInstance();
  51. runtime.setCallJavaCB(this);
  52. JMenuBar menubar = new JMenuBar();
  53. JMenu jm;
  54. menubar.add(jm = new JMenu("Game"));
  55. addMenuItemCallback(jm, "New", "jcallback_newgame_event");
  56. addMenuItemCallback(jm, "Restart", "jcallback_restart_event");
  57. addMenuItemCallback(jm, "Specific...", "jcallback_config_event", CFG_DESC);
  58. addMenuItemCallback(jm, "Random Seed...", "jcallback_config_event", CFG_SEED);
  59. jm.addSeparator();
  60. addMenuItemCallback(jm, "Undo", "jcallback_undo_event");
  61. addMenuItemCallback(jm, "Redo", "jcallback_redo_event");
  62. jm.addSeparator();
  63. solveCommand = addMenuItemCallback(jm, "Solve", "jcallback_solve_event");
  64. solveCommand.setEnabled(false);
  65. if (mainWindow != null) {
  66. jm.addSeparator();
  67. addMenuItemCallback(jm, "Exit", "jcallback_quit_event");
  68. }
  69. menubar.add(typeMenu = new JMenu("Type"));
  70. typeMenu.setVisible(false);
  71. menubar.add(jm = new JMenu("Help"));
  72. addMenuItemCallback(jm, "About", "jcallback_about_event");
  73. setJMenuBar(menubar);
  74. cp.add(pp = new PuzzlePanel(), BorderLayout.CENTER);
  75. pp.addKeyListener(new KeyAdapter() {
  76. public void keyPressed(KeyEvent e) {
  77. int key = -1;
  78. int shift = e.isShiftDown() ? MOD_SHFT : 0;
  79. int ctrl = e.isControlDown() ? MOD_CTRL : 0;
  80. switch (e.getKeyCode()) {
  81. case KeyEvent.VK_LEFT:
  82. case KeyEvent.VK_KP_LEFT:
  83. key = shift | ctrl | CURSOR_LEFT;
  84. break;
  85. case KeyEvent.VK_RIGHT:
  86. case KeyEvent.VK_KP_RIGHT:
  87. key = shift | ctrl | CURSOR_RIGHT;
  88. break;
  89. case KeyEvent.VK_UP:
  90. case KeyEvent.VK_KP_UP:
  91. key = shift | ctrl | CURSOR_UP;
  92. break;
  93. case KeyEvent.VK_DOWN:
  94. case KeyEvent.VK_KP_DOWN:
  95. key = shift | ctrl | CURSOR_DOWN;
  96. break;
  97. case KeyEvent.VK_PAGE_UP:
  98. key = shift | ctrl | MOD_NUM_KEYPAD | '9';
  99. break;
  100. case KeyEvent.VK_PAGE_DOWN:
  101. key = shift | ctrl | MOD_NUM_KEYPAD | '3';
  102. break;
  103. case KeyEvent.VK_HOME:
  104. key = shift | ctrl | MOD_NUM_KEYPAD | '7';
  105. break;
  106. case KeyEvent.VK_END:
  107. key = shift | ctrl | MOD_NUM_KEYPAD | '1';
  108. break;
  109. default:
  110. if (e.getKeyCode() >= KeyEvent.VK_NUMPAD0 && e.getKeyCode() <=KeyEvent.VK_NUMPAD9) {
  111. key = MOD_NUM_KEYPAD | (e.getKeyCode() - KeyEvent.VK_NUMPAD0+'0');
  112. }
  113. break;
  114. }
  115. if (key != -1) {
  116. runtimeCall("jcallback_key_event", new int[] {0, 0, key});
  117. }
  118. }
  119. public void keyTyped(KeyEvent e) {
  120. int key = e.getKeyChar();
  121. if (key == 26 && e.isShiftDown() && e.isControlDown()) {
  122. runtimeCall("jcallback_redo_event", new int[0]);
  123. return;
  124. }
  125. runtimeCall("jcallback_key_event", new int[] {0, 0, key});
  126. }
  127. });
  128. pp.addMouseListener(new MouseAdapter() {
  129. public void mouseReleased(MouseEvent e) {
  130. mousePressedReleased(e, true);
  131. }
  132. public void mousePressed(MouseEvent e) {
  133. pp.requestFocus();
  134. mousePressedReleased(e, false);
  135. }
  136. private void mousePressedReleased(MouseEvent e, boolean released) {
  137. int button;
  138. if ((e.getModifiers() & (InputEvent.BUTTON2_MASK | InputEvent.SHIFT_MASK)) != 0)
  139. button = MIDDLE_BUTTON;
  140. else if ((e.getModifiers() & (InputEvent.BUTTON3_MASK | InputEvent.ALT_MASK)) != 0)
  141. button = RIGHT_BUTTON;
  142. else if ((e.getModifiers() & (InputEvent.BUTTON1_MASK)) != 0)
  143. button = LEFT_BUTTON;
  144. else
  145. return;
  146. if (released)
  147. button += LEFT_RELEASE - LEFT_BUTTON;
  148. runtimeCall("jcallback_key_event", new int[] {e.getX(), e.getY(), button});
  149. }
  150. });
  151. pp.addMouseMotionListener(new MouseMotionAdapter() {
  152. public void mouseDragged(MouseEvent e) {
  153. int button;
  154. if ((e.getModifiers() & (InputEvent.BUTTON2_MASK | InputEvent.SHIFT_MASK)) != 0)
  155. button = MIDDLE_DRAG;
  156. else if ((e.getModifiers() & (InputEvent.BUTTON3_MASK | InputEvent.ALT_MASK)) != 0)
  157. button = RIGHT_DRAG;
  158. else
  159. button = LEFT_DRAG;
  160. runtimeCall("jcallback_key_event", new int[] {e.getX(), e.getY(), button});
  161. }
  162. });
  163. pp.addComponentListener(new ComponentAdapter() {
  164. public void componentResized(ComponentEvent e) {
  165. handleResized();
  166. }
  167. });
  168. pp.setFocusable(true);
  169. pp.requestFocus();
  170. timer = new Timer(20, new ActionListener() {
  171. public void actionPerformed(ActionEvent e) {
  172. runtimeCall("jcallback_timer_func", new int[0]);
  173. }
  174. });
  175. String gameid;
  176. try {
  177. gameid = getParameter("game_id");
  178. } catch (java.lang.NullPointerException ex) {
  179. gameid = null;
  180. }
  181. if (gameid == null) {
  182. puzzle_args = null;
  183. } else {
  184. puzzle_args = new String[2];
  185. puzzle_args[0] = "puzzle";
  186. puzzle_args[1] = gameid;
  187. }
  188. SwingUtilities.invokeLater(new Runnable() {
  189. public void run() {
  190. runtime.start(puzzle_args);
  191. runtime.execute();
  192. }
  193. });
  194. } catch (Exception ex) {
  195. ex.printStackTrace();
  196. }
  197. }
  198. public void destroy() {
  199. SwingUtilities.invokeLater(new Runnable() {
  200. public void run() {
  201. runtime.execute();
  202. if (mainWindow != null) {
  203. mainWindow.dispose();
  204. System.exit(0);
  205. }
  206. }
  207. });
  208. }
  209. protected void handleResized() {
  210. pp.createBackBuffer(pp.getWidth(), pp.getHeight(), colors[0]);
  211. runtimeCall("jcallback_resize", new int[] {pp.getWidth(), pp.getHeight()});
  212. }
  213. private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int arg) {
  214. return addMenuItemCallback(jm, name, callback, new int[] {arg}, false);
  215. }
  216. private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback) {
  217. return addMenuItemCallback(jm, name, callback, new int[0], false);
  218. }
  219. private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int[] args, boolean checkbox) {
  220. JMenuItem jmi;
  221. if (checkbox)
  222. jm.add(jmi = new JCheckBoxMenuItem(name));
  223. else
  224. jm.add(jmi = new JMenuItem(name));
  225. jmi.addActionListener(new ActionListener() {
  226. public void actionPerformed(ActionEvent e) {
  227. runtimeCall(callback, args);
  228. }
  229. });
  230. return jmi;
  231. }
  232. protected void runtimeCall(String func, int[] args) {
  233. if (runtimeCallWithResult(func, args) == 42 && mainWindow != null) {
  234. destroy();
  235. }
  236. }
  237. protected int runtimeCallWithResult(String func, int[] args) {
  238. try {
  239. return runtime.call(func, args);
  240. } catch (Runtime.CallException ex) {
  241. ex.printStackTrace();
  242. return 42;
  243. }
  244. }
  245. private void buildConfigureMenuItem() {
  246. if (typeMenu.isVisible()) {
  247. typeMenu.addSeparator();
  248. } else {
  249. typeMenu.setVisible(true);
  250. }
  251. typeMenuItems[customMenuItemIndex] =
  252. addMenuItemCallback(typeMenu, "Custom...",
  253. "jcallback_config_event",
  254. new int[] {CFG_SETTINGS}, true);
  255. }
  256. private void addTypeItem
  257. (JMenu targetMenu, String name, int newId, final int ptrGameParams) {
  258. typeMenu.setVisible(true);
  259. typeMenuItems[newId] =
  260. addMenuItemCallback(targetMenu, name,
  261. "jcallback_preset_event",
  262. new int[] {ptrGameParams}, true);
  263. }
  264. private void addTypeSubmenu
  265. (JMenu targetMenu, String name, int newId) {
  266. JMenu newMenu = new JMenu(name);
  267. newMenu.setVisible(true);
  268. typeMenuItems[newId] = newMenu;
  269. targetMenu.add(newMenu);
  270. }
  271. public int call(int cmd, int arg1, int arg2, int arg3) {
  272. try {
  273. switch(cmd) {
  274. case 0: // initialize
  275. if (mainWindow != null) mainWindow.setTitle(runtime.cstring(arg1));
  276. if ((arg2 & 1) != 0) buildConfigureMenuItem();
  277. if ((arg2 & 2) != 0) addStatusBar();
  278. if ((arg2 & 4) != 0) solveCommand.setEnabled(true);
  279. colors = new Color[arg3];
  280. return 0;
  281. case 1: // configure Type menu
  282. if (arg1 == 0) {
  283. // preliminary setup
  284. typeMenuItems = new JMenuItem[arg2 + 2];
  285. typeMenuItems[arg2] = typeMenu;
  286. customMenuItemIndex = arg2 + 1;
  287. return arg2;
  288. } else if (xarg1 != 0) {
  289. addTypeItem((JMenu)typeMenuItems[arg2],
  290. runtime.cstring(arg1), arg3, xarg1);
  291. } else {
  292. addTypeSubmenu((JMenu)typeMenuItems[arg2],
  293. runtime.cstring(arg1), arg3);
  294. }
  295. return 0;
  296. case 2: // MessageBox
  297. JOptionPane.showMessageDialog(this, runtime.cstring(arg2), runtime.cstring(arg1), arg3 == 0 ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.ERROR_MESSAGE);
  298. return 0;
  299. case 3: // Resize
  300. pp.setPreferredSize(new Dimension(arg1, arg2));
  301. if (mainWindow != null) mainWindow.pack();
  302. handleResized();
  303. if (mainWindow != null) mainWindow.setVisible(true);
  304. return 0;
  305. case 4: // drawing tasks
  306. switch(arg1) {
  307. case 0:
  308. String text = runtime.cstring(arg2);
  309. if (text.equals("")) text = " ";
  310. statusBar.setText(text);
  311. break;
  312. case 1:
  313. gg = pp.backBuffer.createGraphics();
  314. if (arg2 != 0 || arg3 != 0 ||
  315. arg2 + xarg2 != getWidth() ||
  316. arg3 + xarg3 != getHeight()) {
  317. int left = arg2, right = arg2 + xarg2;
  318. int top = arg3, bottom = arg3 + xarg3;
  319. int width = getWidth(), height = getHeight();
  320. gg.setColor(colors != null ? colors[0] : Color.black);
  321. gg.fillRect(0, 0, left, height);
  322. gg.fillRect(right, 0, width-right, height);
  323. gg.fillRect(0, 0, width, top);
  324. gg.fillRect(0, bottom, width, height-bottom);
  325. gg.setClip(left, top, right-left, bottom-top);
  326. }
  327. break;
  328. case 2: gg.dispose(); pp.repaint(); break;
  329. case 3: gg.setClip(arg2, arg3, xarg1, xarg2); break;
  330. case 4:
  331. if (arg2 == 0 && arg3 == 0) {
  332. gg.setClip(0, 0, getWidth(), getHeight());
  333. } else {
  334. gg.setClip(arg2, arg3, getWidth()-2*arg2, getHeight()-2*arg3);
  335. }
  336. break;
  337. case 5:
  338. gg.setColor(colors[xarg3]);
  339. gg.fillRect(arg2, arg3, xarg1, xarg2);
  340. break;
  341. case 6:
  342. gg.setColor(colors[xarg3]);
  343. gg.drawLine(arg2, arg3, xarg1, xarg2);
  344. break;
  345. case 7:
  346. xPoints = new int[arg2];
  347. yPoints = new int[arg2];
  348. break;
  349. case 8:
  350. if (arg3 != -1) {
  351. gg.setColor(colors[arg3]);
  352. gg.fillPolygon(xPoints, yPoints, xPoints.length);
  353. }
  354. gg.setColor(colors[arg2]);
  355. gg.drawPolygon(xPoints, yPoints, xPoints.length);
  356. break;
  357. case 9:
  358. if (arg3 != -1) {
  359. gg.setColor(colors[arg3]);
  360. gg.fillOval(xarg1-xarg3, xarg2-xarg3, xarg3*2, xarg3*2);
  361. }
  362. gg.setColor(colors[arg2]);
  363. gg.drawOval(xarg1-xarg3, xarg2-xarg3, xarg3*2, xarg3*2);
  364. break;
  365. case 10:
  366. for(int i=0; i<blitters.length; i++) {
  367. if (blitters[i] == null) {
  368. blitters[i] = new BufferedImage(arg2, arg3, BufferedImage.TYPE_3BYTE_BGR);
  369. return i;
  370. }
  371. }
  372. throw new RuntimeException("No free blitter found!");
  373. case 11: blitters[arg2] = null; break;
  374. case 12:
  375. timer.start(); break;
  376. case 13:
  377. timer.stop(); break;
  378. }
  379. return 0;
  380. case 5: // more arguments
  381. xarg1 = arg1;
  382. xarg2 = arg2;
  383. xarg3 = arg3;
  384. return 0;
  385. case 6: // polygon vertex
  386. xPoints[arg1]=arg2;
  387. yPoints[arg1]=arg3;
  388. return 0;
  389. case 7: // string
  390. gg.setColor(colors[arg2]);
  391. {
  392. String text = runtime.utfstring(arg3);
  393. Font ft = new Font((xarg3 & 0x10) != 0 ? "Monospaced" : "Dialog",
  394. Font.PLAIN, 100);
  395. int height100 = this.getFontMetrics(ft).getHeight();
  396. ft = ft.deriveFont(arg1 * 100 / (float)height100);
  397. FontMetrics fm = this.getFontMetrics(ft);
  398. int asc = fm.getAscent(), desc = fm.getDescent();
  399. if ((xarg3 & ALIGN_VCENTRE) != 0)
  400. xarg2 += asc - (asc+desc)/2;
  401. int wid = fm.stringWidth(text);
  402. if ((xarg3 & ALIGN_HCENTRE) != 0)
  403. xarg1 -= wid / 2;
  404. else if ((xarg3 & ALIGN_HRIGHT) != 0)
  405. xarg1 -= wid;
  406. gg.setFont(ft);
  407. gg.drawString(text, xarg1, xarg2);
  408. }
  409. return 0;
  410. case 8: // blitter_save
  411. Graphics g2 = blitters[arg1].createGraphics();
  412. g2.drawImage(pp.backBuffer, 0, 0, blitters[arg1].getWidth(), blitters[arg1].getHeight(),
  413. arg2, arg3, arg2 + blitters[arg1].getWidth(), arg3 + blitters[arg1].getHeight(), this);
  414. g2.dispose();
  415. return 0;
  416. case 9: // blitter_load
  417. gg.drawImage(blitters[arg1], arg2, arg3, this);
  418. return 0;
  419. case 10: // dialog_init
  420. dlg= new ConfigDialog(this, runtime.cstring(arg1));
  421. return 0;
  422. case 11: // dialog_add_control
  423. {
  424. int sval_ptr = arg1;
  425. int ival = arg2;
  426. int ptr = xarg1;
  427. int type=xarg2;
  428. String name = runtime.cstring(xarg3);
  429. switch(type) {
  430. case C_STRING:
  431. dlg.addTextBox(ptr, name, runtime.cstring(sval_ptr));
  432. break;
  433. case C_BOOLEAN:
  434. dlg.addCheckBox(ptr, name, ival != 0);
  435. break;
  436. case C_CHOICES:
  437. dlg.addComboBox(ptr, name, runtime.cstring(sval_ptr), ival);
  438. }
  439. }
  440. return 0;
  441. case 12:
  442. dlg.finish();
  443. dlg = null;
  444. return 0;
  445. case 13: // tick a menu item
  446. if (arg1 < 0) arg1 = customMenuItemIndex;
  447. for (int i = 0; i < typeMenuItems.length; i++) {
  448. if (typeMenuItems[i] instanceof JCheckBoxMenuItem) {
  449. ((JCheckBoxMenuItem)typeMenuItems[i]).setSelected
  450. (arg1 == i);
  451. }
  452. }
  453. return 0;
  454. default:
  455. if (cmd >= 1024 && cmd < 2048) { // palette
  456. colors[cmd-1024] = new Color(arg1, arg2, arg3);
  457. }
  458. if (cmd == 1024) {
  459. pp.setBackground(colors[0]);
  460. if (statusBar != null) statusBar.setBackground(colors[0]);
  461. this.setBackground(colors[0]);
  462. }
  463. return 0;
  464. }
  465. } catch (Throwable ex) {
  466. ex.printStackTrace();
  467. System.exit(-1);
  468. return 0;
  469. }
  470. }
  471. private void addStatusBar() {
  472. statusBar = new JLabel("test");
  473. statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED));
  474. getContentPane().add(BorderLayout.SOUTH,statusBar);
  475. }
  476. // Standalone runner
  477. public static void main(String[] args) {
  478. final PuzzleApplet a = new PuzzleApplet();
  479. JFrame jf = new JFrame("Loading...");
  480. jf.getContentPane().setLayout(new BorderLayout());
  481. jf.getContentPane().add(a, BorderLayout.CENTER);
  482. a.mainWindow=jf;
  483. a.init();
  484. a.start();
  485. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  486. jf.addWindowListener(new WindowAdapter() {
  487. public void windowClosing(WindowEvent e) {
  488. a.stop();
  489. a.destroy();
  490. }
  491. });
  492. jf.setVisible(true);
  493. }
  494. public static class PuzzlePanel extends JPanel {
  495. private static final long serialVersionUID = 1L;
  496. protected BufferedImage backBuffer;
  497. public PuzzlePanel() {
  498. setPreferredSize(new Dimension(100,100));
  499. createBackBuffer(100,100, Color.black);
  500. }
  501. public void createBackBuffer(int w, int h, Color bg) {
  502. if (w > 0 && h > 0) {
  503. backBuffer = new BufferedImage(w,h, BufferedImage.TYPE_3BYTE_BGR);
  504. Graphics g = backBuffer.createGraphics();
  505. g.setColor(bg);
  506. g.fillRect(0, 0, w, h);
  507. g.dispose();
  508. }
  509. }
  510. protected void paintComponent(Graphics g) {
  511. g.drawImage(backBuffer, 0, 0, this);
  512. }
  513. }
  514. public static class ConfigComponent {
  515. public int type;
  516. public int configItemPointer;
  517. public JComponent component;
  518. public ConfigComponent(int type, int configItemPointer, JComponent component) {
  519. this.type = type;
  520. this.configItemPointer = configItemPointer;
  521. this.component = component;
  522. }
  523. }
  524. public class ConfigDialog extends JDialog {
  525. private GridBagConstraints gbcLeft = new GridBagConstraints(
  526. GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, 1, 1,
  527. 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,
  528. new Insets(0, 0, 0, 0), 0, 0);
  529. private GridBagConstraints gbcRight = new GridBagConstraints(
  530. GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE,
  531. GridBagConstraints.REMAINDER, 1, 1.0, 0,
  532. GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
  533. new Insets(5, 5, 5, 5), 0, 0);
  534. private GridBagConstraints gbcBottom = new GridBagConstraints(
  535. GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE,
  536. GridBagConstraints.REMAINDER, GridBagConstraints.REMAINDER,
  537. 1.0, 1.0, GridBagConstraints.CENTER,
  538. GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
  539. private static final long serialVersionUID = 1L;
  540. private List components = new ArrayList();
  541. public ConfigDialog(JApplet parent, String title) {
  542. super(JOptionPane.getFrameForComponent(parent), title, true);
  543. getContentPane().setLayout(new GridBagLayout());
  544. }
  545. public void addTextBox(int ptr, String name, String value) {
  546. getContentPane().add(new JLabel(name), gbcLeft);
  547. JComponent c = new JTextField(value, 25);
  548. getContentPane().add(c, gbcRight);
  549. components.add(new ConfigComponent(C_STRING, ptr, c));
  550. }
  551. public void addCheckBox(int ptr, String name, boolean selected) {
  552. JComponent c = new JCheckBox(name, selected);
  553. getContentPane().add(c, gbcRight);
  554. components.add(new ConfigComponent(C_BOOLEAN, ptr, c));
  555. }
  556. public void addComboBox(int ptr, String name, String values, int selected) {
  557. getContentPane().add(new JLabel(name), gbcLeft);
  558. StringTokenizer st = new StringTokenizer(values.substring(1), values.substring(0,1));
  559. JComboBox c = new JComboBox();
  560. c.setEditable(false);
  561. while(st.hasMoreTokens())
  562. c.addItem(st.nextToken());
  563. c.setSelectedIndex(selected);
  564. getContentPane().add(c, gbcRight);
  565. components.add(new ConfigComponent(C_CHOICES, ptr, c));
  566. }
  567. public void finish() {
  568. JPanel buttons = new JPanel(new GridLayout(1, 2, 5, 5));
  569. getContentPane().add(buttons, gbcBottom);
  570. JButton b;
  571. buttons.add(b=new JButton("OK"));
  572. b.addActionListener(new ActionListener() {
  573. public void actionPerformed(ActionEvent e) {
  574. save();
  575. dispose();
  576. }
  577. });
  578. getRootPane().setDefaultButton(b);
  579. buttons.add(b=new JButton("Cancel"));
  580. b.addActionListener(new ActionListener() {
  581. public void actionPerformed(ActionEvent e) {
  582. dispose();
  583. }
  584. });
  585. setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  586. pack();
  587. setLocationRelativeTo(null);
  588. setVisible(true);
  589. }
  590. private void save() {
  591. for (int i = 0; i < components.size(); i++) {
  592. ConfigComponent cc = (ConfigComponent) components.get(i);
  593. switch(cc.type) {
  594. case C_STRING:
  595. JTextField jtf = (JTextField)cc.component;
  596. runtimeCall("jcallback_config_set_string", new int[] {cc.configItemPointer, runtime.strdup(jtf.getText())});
  597. break;
  598. case C_BOOLEAN:
  599. JCheckBox jcb = (JCheckBox)cc.component;
  600. runtimeCall("jcallback_config_set_boolean", new int[] {cc.configItemPointer, jcb.isSelected()?1:0});
  601. break;
  602. case C_CHOICES:
  603. JComboBox jcm = (JComboBox)cc.component;
  604. runtimeCall("jcallback_config_set_choice", new int[] {cc.configItemPointer, jcm.getSelectedIndex()});
  605. break;
  606. }
  607. }
  608. runtimeCall("jcallback_config_ok", new int[0]);
  609. }
  610. }
  611. }