9 package micropolisj.gui;
11 import java.awt.BorderLayout;
12 import java.awt.Color;
13 import java.awt.Dimension;
14 import java.awt.GridBagConstraints;
15 import java.awt.GridBagLayout;
16 import java.awt.Insets;
17 import java.awt.KeyEventDispatcher;
18 import java.awt.KeyboardFocusManager;
19 import java.awt.Point;
20 import java.awt.Rectangle;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.KeyEvent;
24 import java.awt.event.MouseAdapter;
25 import java.awt.event.MouseEvent;
26 import java.awt.event.MouseWheelEvent;
27 import java.awt.event.WindowAdapter;
28 import java.awt.event.WindowEvent;
30 import java.io.IOException;
31 import java.io.PrintWriter;
32 import java.io.StringWriter;
34 import java.text.MessageFormat;
35 import java.text.NumberFormat;
36 import java.util.Calendar;
37 import java.util.EnumMap;
38 import java.util.Formatter;
39 import java.util.HashMap;
41 import java.util.ResourceBundle;
42 import java.util.prefs.Preferences;
44 import javax.sound.sampled.AudioInputStream;
45 import javax.sound.sampled.AudioSystem;
46 import javax.sound.sampled.Clip;
47 import javax.swing.AbstractAction;
48 import javax.swing.ActionMap;
49 import javax.swing.BorderFactory;
50 import javax.swing.Box;
51 import javax.swing.BoxLayout;
52 import javax.swing.ImageIcon;
53 import javax.swing.InputMap;
54 import javax.swing.JCheckBoxMenuItem;
55 import javax.swing.JComponent;
56 import javax.swing.JFileChooser;
57 import javax.swing.JFrame;
58 import javax.swing.JLabel;
59 import javax.swing.JMenu;
60 import javax.swing.JMenuBar;
61 import javax.swing.JMenuItem;
62 import javax.swing.JOptionPane;
63 import javax.swing.JPanel;
64 import javax.swing.JRadioButtonMenuItem;
65 import javax.swing.JScrollPane;
66 import javax.swing.JTextPane;
67 import javax.swing.JToggleButton;
68 import javax.swing.JToolBar;
69 import javax.swing.KeyStroke;
70 import javax.swing.Timer;
71 import javax.swing.WindowConstants;
72 import javax.swing.filechooser.FileNameExtensionFilter;
74 import micropolisj.engine.CityLocation;
75 import micropolisj.engine.CityRect;
76 import micropolisj.engine.Disaster;
77 import micropolisj.engine.EarthquakeListener;
78 import micropolisj.engine.GameLevel;
79 import micropolisj.engine.MapState;
80 import micropolisj.engine.Micropolis;
81 import micropolisj.engine.MicropolisMessage;
82 import micropolisj.engine.MicropolisTool;
83 import micropolisj.engine.Sound;
84 import micropolisj.engine.Speed;
85 import micropolisj.engine.TempelListener;
86 import micropolisj.engine.ToolResult;
87 import micropolisj.engine.ToolStroke;
88 import micropolisj.engine.ZoneStatus;
89 import micropolisj.network.ClientMicropolis;
90 import micropolisj.network.ServerMicropolis;
91 import micropolisj.util.MP3;
92 import micropolisj.util.TranslationTool;
93 import micropolisj.util.Utilities;
98 JScrollPane drawingAreaScroll;
109 JLabel currentToolLbl;
110 JLabel currentToolCostLbl;
111 public Map<MicropolisTool, JToggleButton>
toolBtns;
112 EnumMap<MapState, JMenuItem> mapStateMenuItems =
new EnumMap<MapState, JMenuItem>(
MapState.class);
117 boolean doSounds =
true;
118 boolean dirty1 =
false;
120 boolean dirty2 =
false;
122 long lastSavedTime = 0;
123 boolean autoBudgetPending;
127 static ImageIcon appIcon;
129 appIcon =
new ImageIcon(
MainWindow.class.getResource(
"/micropolism.png"));
132 static ResourceBundle strings = ResourceBundle.getBundle(
"micropolisj.GuiStrings");
133 static final String PRODUCT_NAME = strings.getString(
"PRODUCT");
140 setIconImage(appIcon.getImage());
143 backgroundMusic.play();
151 this.engine = engine;
154 JPanel mainArea =
new JPanel(
new BorderLayout());
155 add(mainArea, BorderLayout.CENTER);
158 drawingAreaScroll =
new JScrollPane(drawingArea);
159 mainArea.add(drawingAreaScroll);
163 mainArea.add(tb, BorderLayout.WEST);
168 Box evalGraphsBox =
new Box(BoxLayout.Y_AXIS);
169 mainArea.add(evalGraphsBox, BorderLayout.SOUTH);
172 graphsPane.setVisible(
false);
173 evalGraphsBox.add(graphsPane);
176 evaluationPane.setVisible(
false);
177 evalGraphsBox.add(evaluationPane, BorderLayout.SOUTH);
179 JPanel leftPane =
new JPanel(
new GridBagLayout());
180 add(leftPane, BorderLayout.WEST);
182 GridBagConstraints c =
new GridBagConstraints();
183 c.gridx = c.gridy = 0;
184 c.anchor = GridBagConstraints.SOUTHWEST;
185 c.insets =
new Insets(4, 4, 4, 4);
189 leftPane.add(demandInd, c);
193 c.fill = GridBagConstraints.BOTH;
194 c.insets =
new Insets(4, 20, 4, 4);
196 leftPane.add(makeDateFunds(), c);
202 c.anchor = GridBagConstraints.NORTH;
203 c.insets =
new Insets(0, 0, 0, 0);
205 JPanel mapViewContainer =
new JPanel(
new BorderLayout());
206 mapViewContainer.setBorder(BorderFactory.createLineBorder(Color.BLACK));
207 leftPane.add(mapViewContainer, c);
209 JMenuBar mapMenu =
new JMenuBar();
210 mapViewContainer.add(mapMenu, BorderLayout.NORTH);
212 JMenu zonesMenu =
new JMenu(strings.getString(
"menu.zones"));
214 mapMenu.add(zonesMenu);
222 JMenu overlaysMenu =
new JMenu(strings.getString(
"menu.overlays"));
223 setupKeys(overlaysMenu,
"menu.overlays");
224 mapMenu.add(overlaysMenu);
236 mapMenu.add(Box.createHorizontalGlue());
237 mapLegendLbl =
new JLabel();
238 mapMenu.add(mapLegendLbl);
241 mapView.
connectView(drawingArea, drawingAreaScroll);
242 mapViewContainer.add(mapView, BorderLayout.CENTER);
250 c.fill = GridBagConstraints.BOTH;
251 c.insets =
new Insets(0, 0, 0, 0);
254 JScrollPane scroll2 =
new JScrollPane(messagesPane);
255 scroll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
256 scroll2.setPreferredSize(
new Dimension(0, 0));
257 scroll2.setMinimumSize(
new Dimension(0, 0));
258 leftPane.add(scroll2, c);
263 leftPane.add(notificationPane, c);
266 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
267 setLocationRelativeTo(null);
269 InputMap inputMap = ((JComponent) getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
270 inputMap.put(KeyStroke.getKeyStroke(
"ADD"),
"zoomIn");
271 inputMap.put(KeyStroke.getKeyStroke(
"shift EQUALS"),
"zoomIn");
272 inputMap.put(KeyStroke.getKeyStroke(
"SUBTRACT"),
"zoomOut");
273 inputMap.put(KeyStroke.getKeyStroke(
"MINUS"),
"zoomOut");
274 inputMap.put(KeyStroke.getKeyStroke(
"ESCAPE"),
"escape");
276 ActionMap actionMap = ((JComponent) getContentPane()).getActionMap();
277 actionMap.put(
"zoomIn",
new AbstractAction() {
278 public void actionPerformed(ActionEvent evt) {
282 actionMap.put(
"zoomOut",
new AbstractAction() {
283 public void actionPerformed(ActionEvent evt) {
287 actionMap.put(
"escape",
new AbstractAction() {
288 public void actionPerformed(ActionEvent evt) {
293 MouseAdapter mouse =
new MouseAdapter() {
294 public void mousePressed(MouseEvent ev) {
303 public void mouseReleased(MouseEvent ev) {
312 public void mouseDragged(MouseEvent ev) {
321 public void mouseMoved(MouseEvent ev) {
330 public void mouseExited(MouseEvent ev) {
339 public void mouseWheelMoved(MouseWheelEvent evt) {
348 drawingArea.addMouseListener(mouse);
349 drawingArea.addMouseMotionListener(mouse);
350 drawingArea.addMouseWheelListener(mouse);
352 addWindowListener(
new WindowAdapter() {
353 public void windowClosing(WindowEvent ev) {
357 public void windowClosed(WindowEvent ev) {
362 Preferences prefs = Preferences.userNodeForPackage(
MainWindow.class);
363 doSounds = prefs.getBoolean(SOUNDS_PREF,
true);
366 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
367 manager.addKeyEventDispatcher(
this);
394 boolean timerEnabled = isTimerActive();
407 notificationPane.setVisible(
false);
414 boolean needsSaved() {
426 return (System.currentTimeMillis() - lastSavedTime > 30000);
429 boolean maybeSaveCity() {
431 boolean timerEnabled = isTimerActive();
437 int rv = JOptionPane.showConfirmDialog(
this, strings.getString(
"main.save_query"), PRODUCT_NAME,
438 JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
439 if(rv == JOptionPane.CANCEL_OPTION)
442 if(rv == JOptionPane.YES_OPTION) {
460 if(maybeSaveCity()) {
461 backgroundMusic.
close();
466 JComponent makeDateFunds() {
467 JPanel pane =
new JPanel(
new GridBagLayout());
468 GridBagConstraints c0 =
new GridBagConstraints();
469 GridBagConstraints c1 =
new GridBagConstraints();
473 c0.gridy = c1.gridy = 0;
475 c0.weighty = c1.weighty = 1.0;
476 c0.anchor = GridBagConstraints.WEST;
477 c1.anchor = GridBagConstraints.EAST;
479 pane.add(
new JLabel(strings.getString(
"main.date_label")), c0);
480 dateLbl =
new JLabel();
481 pane.add(dateLbl, c1);
483 c0.gridy = c1.gridy = 1;
485 pane.add(
new JLabel(strings.getString(
"main.funds_label")), c0);
486 fundsLbl =
new JLabel();
487 pane.add(fundsLbl, c1);
489 c0.gridy = c1.gridy = 2;
491 pane.add(
new JLabel(strings.getString(
"main.population_label")), c0);
492 popLbl =
new JLabel();
493 pane.add(popLbl, c1);
499 if(strings.containsKey(prefix +
".key")) {
500 String mnemonic = strings.getString(prefix +
".key");
501 menu.setMnemonic(KeyStroke.getKeyStroke(mnemonic).getKeyCode());
505 private void setupKeys(JMenuItem menuItem, String prefix) {
506 if(strings.containsKey(prefix +
".key")) {
507 String mnemonic = strings.getString(prefix +
".key");
508 menuItem.setMnemonic(KeyStroke.getKeyStroke(mnemonic).getKeyCode());
510 if(strings.containsKey(prefix +
".shortcut")) {
511 String shortcut = strings.getString(prefix +
".shortcut");
512 menuItem.setAccelerator(KeyStroke.getKeyStroke(shortcut));
517 JMenuBar menuBar =
new JMenuBar();
519 JMenu gameMenu =
new JMenu(strings.getString(
"menu.game"));
521 menuBar.add(gameMenu);
524 menuItem =
new JMenuItem(strings.getString(
"menu.game.new"));
526 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
527 public void actionPerformed(ActionEvent ev) {
531 gameMenu.add(menuItem);
533 menuItem =
new JMenuItem(strings.getString(
"menu.game.load"));
535 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
536 public void actionPerformed(ActionEvent ev) {
540 gameMenu.add(menuItem);
542 menuItem =
new JMenuItem(strings.getString(
"menu.game.save"));
544 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
545 public void actionPerformed(ActionEvent ev) {
549 gameMenu.add(menuItem);
551 menuItem =
new JMenuItem(strings.getString(
"menu.game.save_as"));
552 setupKeys(menuItem,
"menu.game.save_as");
553 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
554 public void actionPerformed(ActionEvent ev) {
558 gameMenu.add(menuItem);
560 menuItem =
new JMenuItem(strings.getString(
"menu.game.exit"));
562 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
563 public void actionPerformed(ActionEvent ev) {
567 gameMenu.add(menuItem);
569 JMenu optionsMenu =
new JMenu(strings.getString(
"menu.options"));
571 menuBar.add(optionsMenu);
573 JMenu levelMenu =
new JMenu(strings.getString(
"menu.difficulty"));
575 optionsMenu.add(levelMenu);
577 difficultyMenuItems =
new HashMap<Integer, JMenuItem>();
580 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.difficulty." + level));
581 setupKeys(menuItem,
"menu.difficulty." + level);
582 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
583 public void actionPerformed(ActionEvent evt) {
587 levelMenu.add(menuItem);
588 difficultyMenuItems.put(level, menuItem);
591 autoBudgetMenuItem =
new JCheckBoxMenuItem(strings.getString(
"menu.options.auto_budget"));
592 setupKeys(autoBudgetMenuItem,
"menu.options.auto_budget");
593 autoBudgetMenuItem.addActionListener(wrapActionListener(
new ActionListener() {
594 public void actionPerformed(ActionEvent ev) {
598 optionsMenu.add(autoBudgetMenuItem);
600 autoBulldozeMenuItem =
new JCheckBoxMenuItem(strings.getString(
"menu.options.auto_bulldoze"));
601 setupKeys(autoBulldozeMenuItem,
"menu.options.auto_bulldoze");
602 autoBulldozeMenuItem.addActionListener(wrapActionListener(
new ActionListener() {
603 public void actionPerformed(ActionEvent ev) {
607 optionsMenu.add(autoBulldozeMenuItem);
609 disastersMenuItem =
new JCheckBoxMenuItem(strings.getString(
"menu.options.disasters"));
610 setupKeys(disastersMenuItem,
"menu.options.disasters");
611 disastersMenuItem.addActionListener(wrapActionListener(
new ActionListener() {
612 public void actionPerformed(ActionEvent ev) {
616 optionsMenu.add(disastersMenuItem);
618 soundsMenuItem =
new JCheckBoxMenuItem(strings.getString(
"menu.options.sound"));
619 setupKeys(soundsMenuItem,
"menu.options.sound");
620 soundsMenuItem.addActionListener(wrapActionListener(
new ActionListener() {
621 public void actionPerformed(ActionEvent ev) {
625 optionsMenu.add(soundsMenuItem);
627 menuItem =
new JMenuItem(strings.getString(
"menu.options.zoom_in"));
628 setupKeys(menuItem,
"menu.options.zoom_in");
629 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
630 public void actionPerformed(ActionEvent ev) {
634 optionsMenu.add(menuItem);
636 menuItem =
new JMenuItem(strings.getString(
"menu.options.zoom_out"));
637 setupKeys(menuItem,
"menu.options.zoom_out");
638 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
639 public void actionPerformed(ActionEvent ev) {
643 optionsMenu.add(menuItem);
645 JMenu disastersMenu =
new JMenu(strings.getString(
"menu.disasters"));
646 setupKeys(disastersMenu,
"menu.disasters");
647 menuBar.add(disastersMenu);
649 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.MONSTER"));
650 setupKeys(menuItem,
"menu.disasters.MONSTER");
651 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
652 public void actionPerformed(ActionEvent ev) {
656 disastersMenu.add(menuItem);
658 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.FIRE"));
659 setupKeys(menuItem,
"menu.disasters.FIRE");
660 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
661 public void actionPerformed(ActionEvent ev) {
665 disastersMenu.add(menuItem);
667 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.FLOOD"));
668 setupKeys(menuItem,
"menu.disasters.FLOOD");
669 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
670 public void actionPerformed(ActionEvent ev) {
674 disastersMenu.add(menuItem);
676 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.MELTDOWN"));
677 setupKeys(menuItem,
"menu.disasters.MELTDOWN");
678 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
679 public void actionPerformed(ActionEvent ev) {
683 disastersMenu.add(menuItem);
685 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.TORNADO"));
686 setupKeys(menuItem,
"menu.disasters.TORNADO");
687 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
688 public void actionPerformed(ActionEvent ev) {
692 disastersMenu.add(menuItem);
694 menuItem =
new JMenuItem(strings.getString(
"menu.disasters.EARTHQUAKE"));
695 setupKeys(menuItem,
"menu.disasters.EARTHQUAKE");
696 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
697 public void actionPerformed(ActionEvent ev) {
701 disastersMenu.add(menuItem);
703 JMenu priorityMenu =
new JMenu(strings.getString(
"menu.speed"));
705 menuBar.add(priorityMenu);
707 priorityMenuItems =
new EnumMap<Speed, JMenuItem>(
Speed.class);
708 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.speed.SUPER_FAST"));
709 setupKeys(menuItem,
"menu.speed.SUPER_FAST");
710 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
711 public void actionPerformed(ActionEvent ev) {
715 priorityMenu.add(menuItem);
718 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.speed.FAST"));
720 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
721 public void actionPerformed(ActionEvent ev) {
725 priorityMenu.add(menuItem);
726 priorityMenuItems.put(
Speed.
FAST, menuItem);
728 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.speed.NORMAL"));
729 setupKeys(menuItem,
"menu.speed.NORMAL");
730 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
731 public void actionPerformed(ActionEvent ev) {
735 priorityMenu.add(menuItem);
738 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.speed.SLOW"));
740 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
741 public void actionPerformed(ActionEvent ev) {
745 priorityMenu.add(menuItem);
746 priorityMenuItems.put(
Speed.
SLOW, menuItem);
748 menuItem =
new JRadioButtonMenuItem(strings.getString(
"menu.speed.PAUSED"));
749 setupKeys(menuItem,
"menu.speed.PAUSED");
750 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
751 public void actionPerformed(ActionEvent ev) {
755 priorityMenu.add(menuItem);
758 JMenu windowsMenu =
new JMenu(strings.getString(
"menu.windows"));
760 menuBar.add(windowsMenu);
762 menuItem =
new JMenuItem(strings.getString(
"menu.windows.budget"));
763 setupKeys(menuItem,
"menu.windows.budget");
764 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
765 public void actionPerformed(ActionEvent ev) {
766 onViewBudgetClicked();
769 windowsMenu.add(menuItem);
771 menuItem =
new JMenuItem(strings.getString(
"menu.windows.evaluation"));
772 setupKeys(menuItem,
"menu.windows.evaluation");
773 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
774 public void actionPerformed(ActionEvent ev) {
775 onViewEvaluationClicked();
778 windowsMenu.add(menuItem);
780 menuItem =
new JMenuItem(strings.getString(
"menu.windows.research"));
781 setupKeys(menuItem,
"menu.windows.research");
782 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
783 public void actionPerformed(ActionEvent ev) {
784 onViewResearchClicked();
787 windowsMenu.add(menuItem);
789 menuItem =
new JMenuItem(strings.getString(
"menu.windows.graph"));
790 setupKeys(menuItem,
"menu.windows.graph");
791 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
792 public void actionPerformed(ActionEvent ev) {
793 onViewGraphClicked();
796 windowsMenu.add(menuItem);
798 JMenu helpMenu =
new JMenu(strings.getString(
"menu.help"));
800 menuBar.add(helpMenu);
802 menuItem =
new JMenuItem(strings.getString(
"menu.help.launch-translation-tool"));
803 setupKeys(menuItem,
"menu.help.launch-translation-tool");
804 menuItem.addActionListener(
new ActionListener() {
805 public void actionPerformed(ActionEvent evt) {
809 helpMenu.add(menuItem);
811 menuItem =
new JMenuItem(strings.getString(
"menu.help.about"));
813 menuItem.addActionListener(wrapActionListener(
new ActionListener() {
814 public void actionPerformed(ActionEvent ev) {
818 helpMenu.add(menuItem);
820 setJMenuBar(menuBar);
827 JMenuItem autoBudgetMenuItem;
828 JMenuItem autoBulldozeMenuItem;
829 JMenuItem disastersMenuItem;
830 JMenuItem soundsMenuItem;
831 Map<Speed, JMenuItem> priorityMenuItems;
832 Map<Integer, JMenuItem> difficultyMenuItems;
849 static final String SOUNDS_PREF =
"enable_sounds";
853 doSounds = !doSounds;
856 backgroundMusic.
play();
860 backgroundMusic.
close();
863 Preferences prefs = Preferences.userNodeForPackage(
MainWindow.class);
864 prefs.putBoolean(SOUNDS_PREF, doSounds);
871 lastSavedTime = System.currentTimeMillis();
872 if(currentFile != null) {
873 String fileName = currentFile.getName();
874 if(fileName.endsWith(
"." + EXTENSION)) {
875 fileName = fileName.substring(0, fileName.length() - 1 - EXTENSION.length());
878 setTitle(engine instanceof ServerMicropolis ?
"Methapolis - Server - " + fileName :
"Methapolis - Client - " + fileName);
882 setTitle(engine instanceof ServerMicropolis ?
"Methapolis - Server" :
"Methapolis - Client");
887 if(currentFile == null) {
897 catch(IOException e) {
898 e.printStackTrace(System.err);
899 JOptionPane.showMessageDialog(
this, e, strings.getString(
"main.error_caption"), JOptionPane.ERROR_MESSAGE);
904 static final String EXTENSION =
"cty";
907 boolean timerEnabled = isTimerActive();
912 JFileChooser fc =
new JFileChooser();
913 FileNameExtensionFilter filter1 =
new FileNameExtensionFilter(strings.getString(
"cty_file"), EXTENSION);
914 fc.setFileFilter(filter1);
915 int rv = fc.showSaveDialog(
this);
916 if(rv == JFileChooser.APPROVE_OPTION) {
917 currentFile = fc.getSelectedFile();
918 if(!currentFile.getName().endsWith(
"." + EXTENSION)) {
919 currentFile =
new File(currentFile.getPath() +
"." + EXTENSION);
928 e.printStackTrace(System.err);
929 JOptionPane.showMessageDialog(
this, e, strings.getString(
"main.error_caption"), JOptionPane.ERROR_MESSAGE);
941 if(!maybeSaveCity()) {
945 boolean timerEnabled = isTimerActive();
951 JFileChooser fc =
new JFileChooser();
952 FileNameExtensionFilter filter1 =
new FileNameExtensionFilter(strings.getString(
"cty_file"), EXTENSION);
953 fc.setFileFilter(filter1);
955 assert !isTimerActive();
957 int rv = fc.showOpenDialog(
this);
958 if(rv == JFileChooser.APPROVE_OPTION) {
959 File file = fc.getSelectedFile();
964 System.out.println(
"Creating new server");
965 ServerMicropolis oldServer = (ServerMicropolis) oldEngine;
969 newEngine =
new ClientMicropolis( ( (ClientMicropolis) oldEngine ).getPlayerIP() );
975 newEngine.
load(file);
982 e.printStackTrace(System.err);
983 JOptionPane.showMessageDialog(
this, e, strings.getString(
"main.error_caption"), JOptionPane.ERROR_MESSAGE);
994 String iconName = strings.containsKey(
"tool." + tool.name() +
".icon") ? strings.getString(
"tool." + tool.name()
995 +
".icon") :
"/graphics/tools/" + tool.name().toLowerCase() +
".png";
996 String iconSelectedName = strings.containsKey(
"tool." + tool.name() +
".selected_icon") ? strings.getString(
"tool."
997 + tool.name() +
".selected_icon") : iconName;
998 String tipText = strings.containsKey(
"tool." + tool.name() +
".tip") ? strings.getString(
"tool." + tool.name() +
".tip")
1001 JToggleButton btn =
new JToggleButton();
1003 btn.setIcon(
new ImageIcon(
MainWindow.class.getResource(iconName)));
1004 btn.setSelectedIcon(
new ImageIcon(
MainWindow.class.getResource(iconSelectedName)));
1005 btn.setToolTipText(tipText);
1006 btn.setMargin(
new Insets(0, 0, 0, 0));
1007 btn.setBorderPainted(
false);
1008 btn.addActionListener(
new ActionListener() {
1009 public void actionPerformed(ActionEvent ev) {
1020 JToolBar toolBar =
new JToolBar(strings.getString(
"main.tools_caption"), JToolBar.VERTICAL);
1021 toolBar.setFloatable(
false);
1022 toolBar.setRollover(
false);
1024 JPanel gridBox =
new JPanel(
new GridBagLayout());
1025 toolBar.add(gridBox);
1027 GridBagConstraints c =
new GridBagConstraints();
1028 c.gridx = c.gridy = 0;
1029 c.anchor = GridBagConstraints.NORTH;
1030 c.insets =
new Insets(8, 0, 0, 0);
1031 currentToolLbl =
new JLabel(
" ");
1032 gridBox.add(currentToolLbl, c);
1035 c.insets =
new Insets(0, 0, 12, 0);
1036 currentToolCostLbl =
new JLabel(
" ");
1037 gridBox.add(currentToolCostLbl, c);
1040 c.fill = GridBagConstraints.NONE;
1042 c.insets =
new Insets(0, 0, 0, 0);
1043 Box b0 =
new Box(BoxLayout.X_AXIS);
1051 Box b1 =
new Box(BoxLayout.X_AXIS);
1058 Box b2 =
new Box(BoxLayout.X_AXIS);
1066 Box b3 =
new Box(BoxLayout.X_AXIS);
1074 Box b4 =
new Box(BoxLayout.X_AXIS);
1082 Box b5 =
new Box(BoxLayout.X_AXIS);
1090 Box b6 =
new Box(BoxLayout.X_AXIS);
1096 Box b7 =
new Box(BoxLayout.X_AXIS);
1102 Box b8 =
new Box(BoxLayout.X_AXIS);
1109 gridBox.add(
new JLabel(), c);
1115 toolBtns.get(newTool).setSelected(
true);
1116 if(newTool == currentTool) {
1120 if(currentTool != null) {
1121 toolBtns.get(currentTool).setSelected(
false);
1124 currentTool = newTool;
1126 currentToolLbl.setText(strings.containsKey(
"tool." + currentTool.name() +
".name") ? strings.getString(
"tool."
1127 + currentTool.name() +
".name") : currentTool.name());
1130 currentToolCostLbl.setText(cost != 0 ?
formatFunds(cost) :
" ");
1134 if(maybeSaveCity()) {
1140 boolean timerEnabled = isTimerActive();
1145 new NewCityDialog(
this, !firstTime, engine).setVisible(
true);
1152 void doQueryTool(
int xpos,
int ypos) {
1160 private void doZoom(
int dir, Point mousePt) {
1162 int newZoom = dir < 0 ? (oldZoom / 2) : (oldZoom * 2);
1170 if(oldZoom != newZoom) {
1173 double f = (double) newZoom / (
double) oldZoom;
1174 Point pos = drawingAreaScroll.getViewport().getViewPosition();
1175 int newX = (int) Math.round(mousePt.x * f - (mousePt.x - pos.x));
1176 int newY = (int) Math.round(mousePt.y * f - (mousePt.y - pos.y));
1178 drawingAreaScroll.validate();
1179 drawingAreaScroll.getViewport().setViewPosition(
new Point(newX, newY));
1184 Rectangle rect = drawingAreaScroll.getViewport().getViewRect();
1185 doZoom(dir,
new Point(rect.x + rect.width / 2, rect.y + rect.height / 2));
1189 if(evt.getWheelRotation() < 0) {
1190 doZoom(1, evt.getPoint());
1193 doZoom(-1, evt.getPoint());
1205 if(ev.getButton() == MouseEvent.BUTTON3) {
1207 doQueryTool(loc.
x, loc.
y);
1211 if(ev.getButton() != MouseEvent.BUTTON1)
1214 if(currentTool == null)
1223 this.toolStroke = null;
1226 this.toolStroke = currentTool.
beginStroke(engine, x, y);
1235 if(toolStroke != null) {
1247 ((ClientMicropolis) engine).toolUsed(toolStroke);
1258 if(autoBudgetPending) {
1259 autoBudgetPending =
false;
1266 if(toolStroke != null) {
1274 notificationPane.setVisible(
false);
1278 void previewTool() {
1279 assert this.toolStroke != null;
1280 assert this.currentTool != null;
1292 if((ev.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
1298 if(x == lastX && y == lastY)
1301 if(toolStroke != null) {
1351 case INSUFFICIENT_FUNDS:
1362 return MessageFormat.format(strings.getString(
"funds"), funds);
1366 Calendar c = Calendar.getInstance();
1367 c.set(1900 + cityTime / 48, (cityTime % 48) / 4, (cityTime % 4) * 7 + 1);
1369 return MessageFormat.format(strings.getString(
"citytime"), c.getTime());
1375 NumberFormat nf = NumberFormat.getInstance();
1386 assert !isTimerActive();
1391 if(currentEarthquake != null) {
1393 shakeTimer =
new Timer(interval,
new ActionListener() {
1394 public void actionPerformed(ActionEvent evt) {
1395 currentEarthquake.oneStep();
1396 if(currentEarthquake.count == 0) {
1398 currentEarthquake = null;
1407 ActionListener taskPerformer =
new ActionListener() {
1408 public void actionPerformed(ActionEvent evt) {
1409 for(
int i = 0; i < count; i++) {
1420 taskPerformer = wrapActionListener(taskPerformer);
1422 assert simTimer == null;
1427 ActionListener wrapActionListener(
final ActionListener l) {
1428 return new ActionListener() {
1429 public void actionPerformed(ActionEvent evt) {
1431 l.actionPerformed(evt);
1433 catch(Throwable e) {
1441 StringWriter w =
new StringWriter();
1442 e.printStackTrace(
new PrintWriter(w));
1444 JTextPane stackTracePane =
new JTextPane();
1445 stackTracePane.setEditable(
false);
1446 stackTracePane.setText(w.toString());
1448 final JScrollPane detailsPane =
new JScrollPane(stackTracePane);
1449 detailsPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
1450 detailsPane.setPreferredSize(
new Dimension(480, 240));
1451 detailsPane.setMinimumSize(
new Dimension(0, 0));
1453 int rv = JOptionPane.showOptionDialog(
1456 strings.getString(
"main.error_unexpected"),
1457 JOptionPane.DEFAULT_OPTION,
1458 JOptionPane.ERROR_MESSAGE,
1461 strings.getString(
"main.error_show_stacktrace"), strings.getString(
"main.error_close"),
1462 strings.getString(
"main.error_shutdown")
1465 JOptionPane.showMessageDialog(
this, detailsPane, strings.getString(
"main.error_unexpected"),
1466 JOptionPane.ERROR_MESSAGE);
1469 rv = JOptionPane.showConfirmDialog(
this, strings.getString(
"error.shutdown_query"),
1470 strings.getString(
"main.error_unexpected"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
1471 if(rv == JOptionPane.OK_OPTION) {
1477 class EarthquakeStepper {
1482 drawingArea.shake(count);
1486 EarthquakeStepper currentEarthquake;
1490 if(isTimerActive()) {
1494 currentEarthquake =
new EarthquakeStepper();
1495 currentEarthquake.oneStep();
1499 void stopEarthquake() {
1500 drawingArea.shake(0);
1501 currentEarthquake = null;
1505 assert isTimerActive();
1507 if(simTimer != null) {
1511 if(shakeTimer != null) {
1517 boolean isTimerActive() {
1518 return simTimer != null || shakeTimer != null;
1522 if(isTimerActive()) {
1532 if(isTimerActive()) {
1592 autoBudgetMenuItem.setSelected(
getEngine().autoBudget);
1593 autoBulldozeMenuItem.setSelected(
getEngine().autoBulldoze);
1594 disastersMenuItem.setSelected(!
getEngine().noDisasters);
1595 soundsMenuItem.setSelected(doSounds);
1596 for(
Speed spd : priorityMenuItems.keySet()) {
1597 priorityMenuItems.get(spd).setSelected(
getEngine().simSpeed == spd);
1600 difficultyMenuItems.get(i).setSelected(
getEngine().gameLevel == i);
1613 System.out.println(afile);
1615 boolean isOnScreen = drawingAreaScroll.getViewport().getViewRect().contains(drawingArea.
getTileBounds(loc.
x, loc.
y));
1620 System.out.println(afile);
1621 Clip clip = AudioSystem.getClip();
1622 AudioInputStream audioStream = AudioSystem.getAudioInputStream(afile);
1623 System.out.println(audioStream.getFormat());
1624 clip.open(audioStream);
1627 catch(Exception e) {
1628 e.printStackTrace(System.err);
1642 void onViewBudgetClicked() {
1647 void onViewEvaluationClicked() {
1648 evaluationPane.setVisible(
true);
1651 void onViewResearchClicked() {
1657 void onViewGraphClicked() {
1658 graphsPane.setVisible(
true);
1662 if(toolStroke == null) {
1666 autoBudgetPending =
true;
1671 boolean timerEnabled = isTimerActive();
1678 dlg.setVisible(
true);
1686 String caption = strings.getString(stringPrefix);
1687 JMenuItem menuItem =
new JRadioButtonMenuItem(caption);
1689 menuItem.addActionListener(
new ActionListener() {
1690 public void actionPerformed(ActionEvent evt) {
1694 mapStateMenuItems.put(state, menuItem);
1699 mapStateMenuItems.get(mapView.
getMapState()).setSelected(
false);
1700 mapStateMenuItems.get(state).setSelected(
true);
1706 String k =
"legend_image." + state.name();
1707 java.net.URL iconUrl = null;
1708 if(strings.containsKey(k)) {
1709 String iconName = strings.getString(k);
1710 iconUrl =
MainWindow.class.getResource(iconName);
1712 if(iconUrl != null) {
1713 mapLegendLbl.setIcon(
new ImageIcon(iconUrl));
1716 mapLegendLbl.setIcon(null);
1721 if(maybeSaveCity()) {
1724 tt.setVisible(
true);
1729 String version = getClass().getPackage().getImplementationVersion();
1730 String versionStr = MessageFormat.format(strings.getString(
"main.version_string"), version);
1731 versionStr = versionStr.replace(
"%java.version%", System.getProperty(
"java.version"));
1732 versionStr = versionStr.replace(
"%java.vendor%", System.getProperty(
"java.vendor"));
1734 JLabel appNameLbl =
new JLabel(versionStr);
1735 JLabel appDetailsLbl =
new JLabel(strings.getString(
"main.about_text"));
1736 JComponent[] inputs =
new JComponent[] {
1737 appNameLbl, appDetailsLbl
1739 JOptionPane.showMessageDialog(
this, inputs, strings.getString(
"main.about_caption"), JOptionPane.PLAIN_MESSAGE, appIcon);
1747 if(e.getID() == KeyEvent.KEY_PRESSED) {
1749 if(e.getKeyCode() == KeyEvent.VK_ENTER) {
1750 if(this.isFocused()) {
1756 if(e.getKeyCode() == KeyEvent.VK_LEFT) {
1760 if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
1764 if(e.getKeyCode() == KeyEvent.VK_UP) {
1768 if(e.getKeyCode() == KeyEvent.VK_DOWN) {
1778 String msg = String.format(strings.getString(
"notification.alien_countdown"), count);
1779 this.messagesPane.appendMessageText(msg);
1785 endGamePane.setLocationRelativeTo(
this);