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

Last change on this file was 19050, checked in by taylor.smock, 5 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.