From 015624ae55520d18cdcf5f0c456b1a49fb50f7c3 Mon Sep 17 00:00:00 2001 From: Alberto Date: Sat, 17 Feb 2024 22:27:18 +0100 Subject: [PATCH] Find events in the same area dialog. --- .../eqbulletin/gui/EarthquakeBulletinGui.java | 3 +- .../FindSameAreaEventsSelectionListener.java | 13 +- .../gui/listener/ScaleInputDialog.java | 239 ++++++++++++++++++ .../eqbulletin/gui/preference/Preference.java | 2 +- .../eqbulletin/resources/messages.properties | 7 +- .../resources/messages_it.properties | 8 +- 6 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 src/main/java/io/github/albertus82/eqbulletin/gui/listener/ScaleInputDialog.java diff --git a/src/main/java/io/github/albertus82/eqbulletin/gui/EarthquakeBulletinGui.java b/src/main/java/io/github/albertus82/eqbulletin/gui/EarthquakeBulletinGui.java index e82d32de..7262fa3f 100644 --- a/src/main/java/io/github/albertus82/eqbulletin/gui/EarthquakeBulletinGui.java +++ b/src/main/java/io/github/albertus82/eqbulletin/gui/EarthquakeBulletinGui.java @@ -14,6 +14,7 @@ import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.window.ApplicationWindow; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.graphics.Point; @@ -105,6 +106,7 @@ public static void main(final String... args) { try { Display.setAppName(getApplicationName()); Display.setAppVersion(BuildInfo.getProperty("project.version")); + Window.setDefaultImages(Images.getAppIconArray()); start(); } catch (final RuntimeException | Error e) { // NOSONAR Catch Exception instead of Error. Throwable and Error should not be caught (java:S1181) @@ -152,7 +154,6 @@ private static void loop(@NonNull final Shell shell) { @Override protected void configureShell(final Shell shell) { super.configureShell(shell); - shell.setImages(Images.getAppIconArray()); shell.setText(getApplicationName()); } diff --git a/src/main/java/io/github/albertus82/eqbulletin/gui/listener/FindSameAreaEventsSelectionListener.java b/src/main/java/io/github/albertus82/eqbulletin/gui/listener/FindSameAreaEventsSelectionListener.java index 491b6f4b..c3f66377 100644 --- a/src/main/java/io/github/albertus82/eqbulletin/gui/listener/FindSameAreaEventsSelectionListener.java +++ b/src/main/java/io/github/albertus82/eqbulletin/gui/listener/FindSameAreaEventsSelectionListener.java @@ -3,6 +3,7 @@ import java.util.function.Supplier; import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -13,6 +14,7 @@ import io.github.albertus82.eqbulletin.gui.SearchForm; import io.github.albertus82.eqbulletin.gui.preference.Preference; import io.github.albertus82.eqbulletin.model.Earthquake; +import io.github.albertus82.eqbulletin.resources.Messages; import io.github.albertus82.jface.maps.MapBounds; import io.github.albertus82.jface.preference.IPreferencesConfiguration; import lombok.AccessLevel; @@ -25,6 +27,9 @@ @RequiredArgsConstructor public class FindSameAreaEventsSelectionListener extends SelectionAdapter { + public static final byte LATITUDE_INTERVAL_MIN = 1; + public static final byte LATITUDE_INTERVAL_MAX = 5; + private static final double AUTHALIC_RADIUS = 6371.0072; @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -47,7 +52,13 @@ public void widgetSelected(final SelectionEvent se) { final Table table = tableViewer.getTable(); if (selection != null && table != null && !table.isDisposed()) { final SearchForm form = searchFormSupplier.get(); - final float offset = configuration.getByte(Preference.SAME_AREA_EVENTS_LATITUDE_INTERVAL, Defaults.SAME_AREA_EVENTS_LATITUDE_INTERVAL); + + // Ask user for latitude interval + final ScaleInputDialog modal = new ScaleInputDialog(table.getShell(), Messages.get("label.sameareaevents.title"), Messages.get("label.sameareaevents.message"), configuration.getByte(Preference.SAME_AREA_EVENTS_LATITUDE_INTERVAL, Defaults.SAME_AREA_EVENTS_LATITUDE_INTERVAL), LATITUDE_INTERVAL_MIN, LATITUDE_INTERVAL_MAX, 1, 1); + if (Window.OK != modal.open()) { + return; + } + final float offset = modal.getValue().floatValue(); // Latitude (parallels) final float lat = Math.min(MapBounds.LATITUDE_MAX_VALUE - offset, Math.max(MapBounds.LATITUDE_MIN_VALUE + offset, selection.getLatitude().getValue())); diff --git a/src/main/java/io/github/albertus82/eqbulletin/gui/listener/ScaleInputDialog.java b/src/main/java/io/github/albertus82/eqbulletin/gui/listener/ScaleInputDialog.java new file mode 100644 index 00000000..a14b17c2 --- /dev/null +++ b/src/main/java/io/github/albertus82/eqbulletin/gui/listener/ScaleInputDialog.java @@ -0,0 +1,239 @@ +package io.github.albertus82.eqbulletin.gui.listener; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Scale; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.albertus82.jface.Formatter; +import io.github.albertus82.jface.JFaceMessages; +import io.github.albertus82.jface.listener.IntegerVerifyListener; + +/** + * A simple input dialog for soliciting an input string from the user. + *

+ * This concrete dialog class can be instantiated as is, or further subclassed + * as required. + *

+ */ +public class ScaleInputDialog extends Dialog { + + private static final Logger log = LoggerFactory.getLogger(ScaleInputDialog.class); + + /** + * The title of the dialog. + */ + private String title; + + /** + * The message to display, or null if none. + */ + private String message; + + /** + * The input value; the empty string by default. + */ + private int value; + + private final int minimum; + private final int maximum; + private final int increment; + private final int pageIncrement; + + /** + * Ok button widget. + */ + private Button okButton; + + private Scale scale; + + /** + * Input text widget. + */ + private Text text; + + /** + * Creates an input dialog with OK and Cancel buttons. Note that the dialog will + * have no visual representation (no widgets) until it is told to open. + *

+ * Note that the open method blocks for input dialogs. + *

+ * + * @param parentShell the parent shell, or null to create a + * top-level shell + * @param dialogTitle the dialog title, or null if none + * @param dialogMessage the dialog message, or null if none + * @param initialValue the initial input value, or null if none + * (equivalent to the empty string) + * @param validator an input validator, or null if none + */ + public ScaleInputDialog(final Shell parentShell, final String dialogTitle, final String dialogMessage, final int initialValue, final int minimum, final int maximum, final int increment, final int pageIncrement) { + super(parentShell); + this.title = dialogTitle; + message = dialogMessage; + value = initialValue; + this.minimum = minimum; + this.maximum = maximum; + this.increment = increment; + this.pageIncrement = pageIncrement; + } + + @Override + protected void buttonPressed(int buttonId) { + if (buttonId == IDialogConstants.OK_ID) { + value = scale.getSelection(); + } + super.buttonPressed(buttonId); + } + + @Override + protected void configureShell(final Shell shell) { + super.configureShell(shell); + if (title != null) { + shell.setText(title); + } + } + + @Override + protected void createButtonsForButtonBar(final Composite parent) { + // create OK and Cancel buttons by default + okButton = createButton(parent, IDialogConstants.OK_ID, JFaceMessages.get("lbl.button.ok"), true); + createButton(parent, IDialogConstants.CANCEL_ID, JFaceMessages.get("lbl.button.cancel"), false); + //do this here because setting the text will set enablement on the ok + // button + scale.setFocus(); + scale.setSelection(value); + } + + @Override + protected Control createDialogArea(final Composite parent) { + // create composite + final Composite composite = (Composite) super.createDialogArea(parent); + if (composite.getLayout() instanceof GridLayout) { + ((GridLayout) composite.getLayout()).numColumns += 3; + } + // create message + if (message != null) { + Label label = new Label(composite, SWT.WRAP); + label.setText(message); + final GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.ENTRY_FIELD_WIDTH); + data.horizontalSpan += 3; + label.setLayoutData(data); + label.setFont(parent.getFont()); + } + scale = new Scale(composite, getScaleStyle()); + scale.setMinimum(minimum); + scale.setMaximum(maximum); + scale.setIncrement(increment); + scale.setPageIncrement(pageIncrement); + final GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.verticalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + scale.setLayoutData(data); + scale.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(final SelectionEvent e) { + text.setText(Integer.toString(scale.getSelection())); + } + }); + + Label label = new Label(composite, SWT.NONE); + label.setText("\u00B1"); + GridDataFactory.swtDefaults().applyTo(label); + label.setFont(parent.getFont()); + + text = new Text(composite, SWT.BORDER | SWT.TRAIL); + final int widthHint = new Formatter(getClass()).computeWidth(text, Integer.toString(maximum).length(), SWT.NORMAL); + GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).hint(widthHint, SWT.DEFAULT).applyTo(text); + text.setTextLimit(Integer.toString(maximum).length()); + text.setText(Integer.toString(value)); + text.addFocusListener(new TextFocusListener()); + text.addVerifyListener(new IntegerVerifyListener(false)); + + Label label2 = new Label(composite, SWT.NONE); + label2.setText("\u00B0"); + GridDataFactory.swtDefaults().applyTo(label2); + label2.setFont(parent.getFont()); + + applyDialogFont(composite); + return composite; + } + + /** + * Returns the ok button. + * + * @return the ok button + */ + protected Button getOkButton() { + return okButton; + } + + /** + * Returns the text area. + * + * @return the text area + */ + protected Scale getScale() { + return scale; + } + + /** + * Returns the string typed into this input dialog. + * + * @return the input string + */ + public Integer getValue() { + return value; + } + + /** + * Returns the style bits that should be used for the input text field. Defaults + * to a single line entry. Subclasses may override. + * + * @return the integer style bits that should be used when creating the input + * text + * + * @since 3.4 + */ + protected int getScaleStyle() { + return SWT.HORIZONTAL; + } + + protected class TextFocusListener extends FocusAdapter { + @Override + public void focusLost(final FocusEvent fe) { + try { + int textValue = Integer.parseInt(text.getText()); + if (textValue > maximum) { + textValue = maximum; + } + if (textValue < minimum) { + textValue = minimum; + } + text.setText(Integer.toString(textValue)); + scale.setSelection(textValue); + } + catch (final RuntimeException e) { + log.debug("Cannot update the selection (which is the value) of the scale:", e); + text.setText(Integer.toString(scale.getSelection())); + } + } + } + +} diff --git a/src/main/java/io/github/albertus82/eqbulletin/gui/preference/Preference.java b/src/main/java/io/github/albertus82/eqbulletin/gui/preference/Preference.java index c1053e52..f6fdf07e 100644 --- a/src/main/java/io/github/albertus82/eqbulletin/gui/preference/Preference.java +++ b/src/main/java/io/github/albertus82/eqbulletin/gui/preference/Preference.java @@ -96,7 +96,7 @@ public enum Preference implements IPreference { CRITERIA_FORMAT(new PreferenceDetailsBuilder(CRITERIA).label(() -> Messages.get("label.form.format")).defaultValue(SearchForm.Defaults.FORMAT.getValue()).build(), new FieldEditorDetailsBuilder(DefaultRadioGroupFieldEditor.class).labelsAndValues(getFormatRadioOptions()).radioNumColumns(2).radioUseGroup(true).build()), CRITERIA_LIMIT(new PreferenceDetailsBuilder(CRITERIA).label(() -> Messages.get("label.form.limit") + " " + Messages.get("label.form.limit.note")).build(), new FieldEditorDetailsBuilder(EnhancedIntegerFieldEditor.class).emptyStringAllowed(true).numberValidRange(SearchForm.RESULTS_MIN_VALUE, SearchForm.RESULTS_MAX_VALUE).build()), CRITERIA_RESTRICT(new PreferenceDetailsBuilder(CRITERIA).defaultValue(SearchForm.Defaults.CRITERIA_RESTRICT).label(() -> Messages.get("label.form.criteria.restrict")).build(), new FieldEditorDetailsBuilder(DefaultBooleanFieldEditor.class).build()), - SAME_AREA_EVENTS_LATITUDE_INTERVAL(new PreferenceDetailsBuilder(CRITERIA).defaultValue(FindSameAreaEventsSelectionListener.Defaults.SAME_AREA_EVENTS_LATITUDE_INTERVAL).build(), new FieldEditorDetailsBuilder(ScaleIntegerFieldEditor.class).scaleMinimum(1).scaleMaximum(5).scalePageIncrement(1).build()), + SAME_AREA_EVENTS_LATITUDE_INTERVAL(new PreferenceDetailsBuilder(CRITERIA).defaultValue(FindSameAreaEventsSelectionListener.Defaults.SAME_AREA_EVENTS_LATITUDE_INTERVAL).build(), new FieldEditorDetailsBuilder(ScaleIntegerFieldEditor.class).scaleMinimum(FindSameAreaEventsSelectionListener.LATITUDE_INTERVAL_MIN).scaleMaximum(FindSameAreaEventsSelectionListener.LATITUDE_INTERVAL_MAX).scalePageIncrement(1).build()), AUTOREFRESH_ENABLED(new PreferenceDetailsBuilder(CRITERIA).defaultValue(SearchForm.Defaults.AUTOREFRESH_ENABLED).build(), new FieldEditorDetailsBuilder(DefaultBooleanFieldEditor.class).build()), AUTOREFRESH_MINS(new PreferenceDetailsBuilder(CRITERIA).parent(AUTOREFRESH_ENABLED).label(() -> Messages.get("label.form.button.autorefresh")).build(), new FieldEditorDetailsBuilder(EnhancedIntegerFieldEditor.class).numberMinimum(SearchForm.AUTOREFRESH_MIN_VALUE).emptyStringAllowed(true).textLimit(SearchForm.AUTOREFRESH_TEXT_LIMIT).build()), diff --git a/src/main/resources/io/github/albertus82/eqbulletin/resources/messages.properties b/src/main/resources/io/github/albertus82/eqbulletin/resources/messages.properties index e2eb1910..1a775eea 100644 --- a/src/main/resources/io/github/albertus82/eqbulletin/resources/messages.properties +++ b/src/main/resources/io/github/albertus82/eqbulletin/resources/messages.properties @@ -51,6 +51,11 @@ label.about.license.gpl.a.href=https://www.gnu.org/licenses/gpl.html label.about.license.gpl.a.text=GNU General Public License label.about.title=About ${project.name} label.about.version=Version {0} ({1}) + +label.sameareaevents.title=Find events in the same area +label.sameareaevents.message=Latitude interval + + label.button.cancel=&Cancel label.button.close=&Close label.button.confirm=&Confirm @@ -113,7 +118,7 @@ label.menu.item.export.csv=Export &CSV... label.menu.item.feregion=&Flinn-Engdahl regionalization label.menu.item.google.maps.browser=View map in &browser label.menu.item.open.browser=&Open event in browser -label.menu.item.find.events.same.area=Find &events in the same area +label.menu.item.find.events.same.area=Find &events in the same area... label.menu.item.preferences=&Configuration label.menu.item.save.map=&Save map as... label.menu.item.show.map=&Show map diff --git a/src/main/resources/io/github/albertus82/eqbulletin/resources/messages_it.properties b/src/main/resources/io/github/albertus82/eqbulletin/resources/messages_it.properties index f4108607..6528c7c4 100644 --- a/src/main/resources/io/github/albertus82/eqbulletin/resources/messages_it.properties +++ b/src/main/resources/io/github/albertus82/eqbulletin/resources/messages_it.properties @@ -55,6 +55,12 @@ label.button.cancel=&Annulla label.button.close=&Chiudi label.button.confirm=&Conferma label.button.ok=&OK + +label.sameareaevents.title=Trova eventi nella stessa area +label.sameareaevents.message=Intervallo di latitudine + + + label.error=Errore label.feregion.dialog.coordinates=Coordinate label.feregion.dialog.latitude=Latitudine @@ -113,7 +119,7 @@ label.menu.item.export.csv=Esporta &CSV... label.menu.item.feregion=&Regionalizzazione Flinn-Engdahl label.menu.item.google.maps.browser=Visualizza mappa nel &browser label.menu.item.open.browser=&Apri evento nel browser -label.menu.item.find.events.same.area=Trova &eventi nella stessa area +label.menu.item.find.events.same.area=Trova &eventi nella stessa area... label.menu.item.preferences=&Configurazione label.menu.item.save.map=&Salva mappa con nome... label.menu.item.show.map=&Visualizza mappa