source: josm/trunk/src/org/openstreetmap/josm/gui/MainFrame.java@ 19050

Last change on this file since 19050 was 19050, checked in by taylor.smock, 14 months ago

Revert most var changes from r19048, fix most new compile warnings and checkstyle issues

Also, document why various ErrorProne checks were originally disabled and fix
generic SonarLint issues.

  • Property svn:eol-style set to native
File size: 9.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Component;
8import java.awt.ComponentOrientation;
9import java.awt.Frame;
10import java.awt.Image;
11import java.awt.Rectangle;
12import java.awt.Toolkit;
13import java.awt.event.ComponentEvent;
14import java.awt.event.ComponentListener;
15import java.awt.event.WindowAdapter;
16import java.awt.event.WindowEvent;
17import java.beans.PropertyChangeListener;
18import java.util.List;
19import java.util.Locale;
20import java.util.Objects;
21import java.util.stream.Collectors;
22import java.util.stream.Stream;
23
24import javax.swing.ImageIcon;
25import javax.swing.JFrame;
26import javax.swing.JPanel;
27import javax.swing.WindowConstants;
28
29import org.openstreetmap.josm.data.UserIdentityManager;
30import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
31import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
32import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
33import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
34import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
35import org.openstreetmap.josm.gui.layer.OsmDataLayer;
36import org.openstreetmap.josm.gui.layer.OsmDataLayer.LayerStateChangeListener;
37import org.openstreetmap.josm.gui.util.WindowGeometry;
38import org.openstreetmap.josm.spi.preferences.Config;
39import org.openstreetmap.josm.tools.ImageProvider;
40import org.openstreetmap.josm.tools.Logging;
41
42/**
43 * This is the JOSM main window. It updates it's title.
44 * @author Michael Zangl
45 * @since 10340
46 */
47public class MainFrame extends JFrame {
48 private final transient LayerStateChangeListener updateTitleOnLayerStateChange = (layer, newValue) -> onLayerChange(layer);
49
50 private final transient PropertyChangeListener updateTitleOnSaveChange = evt -> {
51 if (evt.getPropertyName().equals(AbstractModifiableLayer.REQUIRES_SAVE_TO_DISK_PROP)
52 || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
53 AbstractModifiableLayer layer = (AbstractModifiableLayer) evt.getSource();
54 onLayerChange(layer);
55 }
56 };
57
58 protected transient WindowGeometry geometry;
59 protected int windowState = Frame.NORMAL;
60 private final MainPanel panel;
61 private MainMenu menu;
62
63 /**
64 * Create a new main window.
65 */
66 public MainFrame() {
67 this(new WindowGeometry(new Rectangle(10, 10, 500, 500)));
68 }
69
70 /**
71 * Create a new main window. The parameter will be removed in the future.
72 * @param geometry The initial geometry to use.
73 * @since 12127
74 */
75 public MainFrame(WindowGeometry geometry) {
76 super();
77 this.geometry = geometry;
78 this.panel = new MainPanel(MainApplication.getLayerManager());
79 setContentPane(new JPanel(new BorderLayout()));
80 setComponentOrientation();
81 }
82
83 private void setComponentOrientation() {
84 ComponentOrientation orientation = ComponentOrientation.getOrientation(Locale.getDefault());
85 if (orientation == ComponentOrientation.RIGHT_TO_LEFT) {
86 Logging.info(tr("Setting component orientation to right-to-left"));
87 }
88 applyComponentOrientation(orientation);
89 }
90
91 /**
92 * Initializes the content of the window and get the current status panel.
93 */
94 public void initialize() {
95 menu = new MainMenu();
96 addComponentListener(new WindowPositionSizeListener());
97 addWindowStateListener(new WindowPositionSizeListener());
98
99 setJMenuBar(menu);
100 geometry.applySafe(this);
101 List<Image> l = Stream.of(
102 /* ICON */ "logo_16x16x32",
103 /* ICON */ "logo_16x16x8",
104 /* ICON */ "logo_32x32x32",
105 /* ICON */ "logo_32x32x8",
106 /* ICON */ "logo_48x48x32",
107 /* ICON */ "logo_48x48x8",
108 /* ICON */ "logo")
109 .map(ImageProvider::getIfAvailable)
110 .filter(Objects::nonNull)
111 .map(ImageIcon::getImage)
112 .collect(Collectors.toList());
113 setIconImages(l);
114 addWindowListener(new ExitWindowAdapter());
115 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
116
117 // This listener is never removed, since the main frame exists forever.
118 MainApplication.getLayerManager().addActiveLayerChangeListener(e -> refreshTitle());
119 MainApplication.getLayerManager().addAndFireLayerChangeListener(new ManageLayerListeners());
120 UserIdentityManager.getInstance().addListener(this::refreshTitle);
121 Config.getPref().addKeyPreferenceChangeListener("draw.show-user", e -> refreshTitle());
122 refreshTitle();
123
124 getContentPane().add(panel, BorderLayout.CENTER);
125 menu.initialize();
126 }
127
128 /**
129 * Stores the current state of the main frame.
130 */
131 public void storeState() {
132 if (geometry != null) {
133 geometry.remember(WindowGeometry.PREF_KEY_GUI_GEOMETRY);
134 }
135 Config.getPref().putBoolean("gui.maximized", (windowState & Frame.MAXIMIZED_BOTH) != 0);
136 }
137
138 /**
139 * Gets the main menu used for this window.
140 * @return The main menu.
141 * @throws IllegalStateException if the main frame has not been initialized yet
142 * @see #initialize
143 */
144 public MainMenu getMenu() {
145 if (menu == null) {
146 throw new IllegalStateException("Not initialized.");
147 }
148 return menu;
149 }
150
151 /**
152 * Gets the main panel.
153 * @return The main panel.
154 * @since 12125
155 */
156 public MainPanel getPanel() {
157 return panel;
158 }
159
160 /**
161 * Sets this frame to be maximized.
162 * @param maximized <code>true</code> if the window should be maximized.
163 */
164 public void setMaximized(boolean maximized) {
165 if (maximized) {
166 if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
167 windowState = Frame.MAXIMIZED_BOTH;
168 setExtendedState(windowState);
169 } else {
170 Logging.debug("Main window: maximizing not supported");
171 }
172 } else {
173 throw new UnsupportedOperationException("Unimplemented.");
174 }
175 }
176
177 /**
178 * Update the title of the window to reflect the current content.
179 */
180 public void refreshTitle() {
181 OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer();
182 boolean dirty = editLayer != null && editLayer.isDirty();
183 String userInfo = UserIdentityManager.getInstance().getUserName();
184 if (userInfo != null && Config.getPref().getBoolean("draw.show-user", false))
185 userInfo = tr(" ({0})", "@" + userInfo);
186 else
187 userInfo = "";
188 setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor") + userInfo);
189 getRootPane().putClientProperty("Window.documentModified", dirty);
190 }
191
192 private void onLayerChange(AbstractModifiableLayer layer) {
193 if (layer == MainApplication.getLayerManager().getEditLayer()) {
194 refreshTitle();
195 }
196 }
197
198 static final class ExitWindowAdapter extends WindowAdapter {
199 @Override
200 public void windowClosing(final WindowEvent evt) {
201 MainApplication.exitJosm(true, 0, null);
202 }
203 }
204
205 /**
206 * Manages the layer listeners, adds them to every layer.
207 */
208 private final class ManageLayerListeners implements LayerChangeListener {
209 @Override
210 public void layerAdded(LayerAddEvent e) {
211 if (e.getAddedLayer() instanceof OsmDataLayer) {
212 OsmDataLayer osmDataLayer = (OsmDataLayer) e.getAddedLayer();
213 osmDataLayer.addLayerStateChangeListener(updateTitleOnLayerStateChange);
214 }
215 e.getAddedLayer().addPropertyChangeListener(updateTitleOnSaveChange);
216 }
217
218 @Override
219 public void layerRemoving(LayerRemoveEvent e) {
220 if (e.getRemovedLayer() instanceof OsmDataLayer) {
221 OsmDataLayer osmDataLayer = (OsmDataLayer) e.getRemovedLayer();
222 osmDataLayer.removeLayerStateChangeListener(updateTitleOnLayerStateChange);
223 }
224 e.getRemovedLayer().removePropertyChangeListener(updateTitleOnSaveChange);
225 }
226
227 @Override
228 public void layerOrderChanged(LayerOrderChangeEvent e) {
229 // not used
230 }
231 }
232
233 private final class WindowPositionSizeListener extends WindowAdapter implements ComponentListener {
234 @Override
235 public void windowStateChanged(WindowEvent e) {
236 windowState = e.getNewState();
237 }
238
239 @Override
240 public void componentHidden(ComponentEvent e) {
241 // Do nothing
242 }
243
244 @Override
245 public void componentMoved(ComponentEvent e) {
246 handleComponentEvent(e);
247 }
248
249 @Override
250 public void componentResized(ComponentEvent e) {
251 handleComponentEvent(e);
252 }
253
254 @Override
255 public void componentShown(ComponentEvent e) {
256 // Do nothing
257 }
258
259 private void handleComponentEvent(ComponentEvent e) {
260 Component c = e.getComponent();
261 if (c instanceof JFrame && c.isVisible()) {
262 if (windowState == Frame.NORMAL) {
263 geometry = new WindowGeometry((JFrame) c);
264 } else {
265 geometry.fixScreen((JFrame) c);
266 }
267 }
268 }
269 }
270
271}
Note: See TracBrowser for help on using the repository browser.