Skip to content

New features - #527

Open
zaum wants to merge 26 commits into
angryip:masterfrom
zaum:new-features
Open

zaum wants to merge 26 commits into
angryip:masterfrom
zaum:new-features

Conversation

@zaum

@zaum zaum commented Jul 22, 2026

Copy link
Copy Markdown

1. File-based Comments + Inline Editing

Commits: 16033af8, 7ade9ea5, 57747ca2

  • New: Inline comment editor — double-click a comment cell opens a Text widget; Enter/FocusOut saves, Escape cancels.
  • New: CommentsConfig persists to comments.txt instead of Java Preferences (survives restarts, flushed immediately).
  • New: Config.getConfigDir() — portable config directory next to the JAR, falls back to ~/.ipscan.
image
  • New: Add auto-start scan preference
image

2. Default Opener per IP

Commits: 219305eb, 4e8ac91e, 4c0efca0, 3e8f2333

  • New: OpenerColumnFetcher — column showing the configured opener name; double-click opens a radio-menu to pick one.
  • New: OpenerLaunchFetcher — centered triangle () icon column; click to launch the default opener for that IP.
  • New: DefaultOpenerConfig — per-IP opener assignment (persisted to file).
image

3. ColumnVisibilityMenu (removes SelectFetchersDialog)

Commits: ed77fc0c

  • New: ColumnVisibilityMenu — right-click on the table header toggles individual columns on/off inline.
  • Deleted: SelectFetchersDialog.java — old modal dialog removed.
  • Modified: MacApplicationMenu, MainWindow, ToolsActions, ColumnsActions, CommandsMenuActions, OpenerLauncher, AbstractModalDialog.
image

4. Column Order Persistence + Drag-Reorder

Commits: (Contained within ed77fc0c and 95c1f86e)

  • New: saveColumnOrder() — persists visual column order via guiConfig.setColumnOrder() after every drag.
  • New: IP column is pinned to visual position 0 and never movable.
  • New: Drag-to-reorder is disabled during scan, re-enabled when idle.
drag

6. Column Header Tooltip

Commits: 3a2f7eaa

  • New: HeaderTooltipPoller — polls cursor position every 100ms to show a width-capped (360px), wrapping tooltip over column headers.
  • New: 2-second delay before showing, instant hide on focus loss, auto-positions below the hovered header.
image

ResultTable Performance
Commits: 39b5cf1e

  • New: Precomputed columnFetcherIndexMap for $O(1)$ fetcher lookup during virtual-table rendering.
  • New: populateNewFetcher() — background thread that fills a newly added fetcher column in batches (100 rows per UI update) without freezing the table.
  • Modified: ScanningResultList.

Table Rebuild on Fetcher Change
Commits: (Contained within ed77fc0c)

  • New: handleUpdateOfSelectedFetchers() now preserves scanned results, re-aligns columns in saved order, and populates newly added fetchers with real data off the UI thread.

@angryziber

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes Angry IP Scanner’s UI layer by migrating from SWT to JavaFX, while adding several UX/features around comments, openers, and column management, plus moving some user settings from Java Preferences into plain files under a portable config directory.

Changes:

  • Replace the SWT GUI stack with a JavaFX-based GUI (net.azib.ipscan.gui.fx.*), updating app startup and DI registration accordingly.
  • Add file-backed persistence for user data/config (portable config/ dir near the app, comments stored in comments.txt, per-IP default openers stored in openers-defaults.txt).
  • Add “default opener per IP” functionality, including opener-related fetchers and UI hooks for setting/launching.

Reviewed changes

Copilot reviewed 124 out of 130 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/net/azib/ipscan/gui/SWTTestCase.java Removed SWT test base class as part of SWT deprecation.
test/net/azib/ipscan/gui/StatisticsDialogTest.java Removed SWT StatisticsDialog test (dialog removed).
test/net/azib/ipscan/gui/SelectFetchersDialogTest.java Removed test for removed SWT dialog.
test/net/azib/ipscan/gui/PreferencesDialogTest.java Removed SWT preferences dialog tests.
test/net/azib/ipscan/gui/InputDialogTest.java Removed SWT input dialog tests.
test/net/azib/ipscan/gui/GUITest.java Removed SWT GUI error-localization test (SWT GUI removed).
test/net/azib/ipscan/gui/fetchers/PortTextFetcherPrefsTest.java Removed tests tied to removed SWT fetcher prefs UI.
test/net/azib/ipscan/gui/feeders/FeederGUIRegistryTest.java Replaced SWT GUI registry tests with minimal RangeFeeder assertions (misnamed now).
test/net/azib/ipscan/gui/feeders/AbstractFeederGUITest.java Updated feeder GUI test to target FX feeder GUI base class.
test/net/azib/ipscan/gui/actions/StartStopScanningActionTest.java Removed SWT action test.
test/net/azib/ipscan/gui/actions/OpenerLauncherTest.java Removed SWT opener launcher tests (launcher removed/ported).
test/net/azib/ipscan/gui/actions/GotoActionsTest.java Removed SWT go-to actions tests.
test/net/azib/ipscan/fetchers/FetcherRegistryTest.java Updated for FetcherRegistry constructor signature changes.
test/net/azib/ipscan/exporters/TXTExporterTest.java Updated TXT import test API from GUI feeder to FeederCreator; improved resource path handling.
test/net/azib/ipscan/config/GUIConfigTest.java Updated to match GUIConfig’s new int[] sizing fields (no SWT Point).
test/net/azib/ipscan/config/ComponentRegistryTest.java Removed SWT-dependent DI instantiation test.
src/net/azib/ipscan/util/GoogleAnalytics.java Removed SWT-specific exception code handling from stack extraction.
src/net/azib/ipscan/Main.java Switched app startup to JavaFX (FXGUI) and simplified error fallback behavior.
src/net/azib/ipscan/gui/util/LayoutHelper.java Deleted SWT layout/icon helper.
src/net/azib/ipscan/gui/SWTAwareStateMachine.java Deleted SWT-thread marshalling state machine.
src/net/azib/ipscan/gui/StatusBar.java Deleted SWT status bar (replaced by FXStatusBar).
src/net/azib/ipscan/gui/StatisticsDialog.java Deleted SWT statistics dialog.
src/net/azib/ipscan/gui/Startup.java Deleted SWT startup flow (FX TODO remains).
src/net/azib/ipscan/gui/SelectFetchersDialog.java Deleted SWT fetcher selection dialog.
src/net/azib/ipscan/gui/menu/ToolsMenu.java Deleted SWT tools menu implementation.
src/net/azib/ipscan/gui/menu/ScanMenu.java Deleted SWT scan menu implementation.
src/net/azib/ipscan/gui/menu/ResultsContextMenu.java Deleted SWT results context menu wrapper.
src/net/azib/ipscan/gui/menu/OpenersMenu.java Deleted SWT openers menu wrapper.
src/net/azib/ipscan/gui/menu/OpenersContextMenu.java Deleted SWT openers context menu wrapper.
src/net/azib/ipscan/gui/menu/HelpMenu.java Deleted SWT help menu implementation.
src/net/azib/ipscan/gui/menu/GotoMenu.java Deleted SWT goto menu implementation.
src/net/azib/ipscan/gui/menu/FavoritesMenu.java Deleted SWT favorites menu implementation.
src/net/azib/ipscan/gui/menu/ExtendableMenu.java Deleted SWT menu base class.
src/net/azib/ipscan/gui/menu/CommandsMenu.java Deleted SWT commands menu implementation.
src/net/azib/ipscan/gui/menu/ColumnsMenu.java Deleted SWT columns menu implementation.
src/net/azib/ipscan/gui/menu/AbstractMenu.java Deleted SWT abstract menu base class.
src/net/azib/ipscan/gui/MainMenu.java Deleted SWT main menu wiring and enable/disable logic.
src/net/azib/ipscan/gui/MacApplicationMenu.java Deleted SWT Mac application menu integration.
src/net/azib/ipscan/gui/InputDialog.java Deleted SWT input dialog.
src/net/azib/ipscan/gui/InfoDialog.java Deleted SWT info dialog.
src/net/azib/ipscan/gui/GUI.java Deleted SWT GUI entrypoint/event loop.
src/net/azib/ipscan/gui/GettingStartedDialog.java Deleted SWT getting started dialog.
src/net/azib/ipscan/gui/fx/FXStatusBar.java Added JavaFX status bar replacement.
src/net/azib/ipscan/gui/fx/FXStateMachine.java Added JavaFX-thread marshalling state machine.
src/net/azib/ipscan/gui/fx/FXOpenersDialog.java Added JavaFX “Edit Openers” dialog.
src/net/azib/ipscan/gui/fx/FXGUI.java Added JavaFX Application entrypoint and window wiring.
src/net/azib/ipscan/gui/fx/FXFavoritesDialog.java Added JavaFX favorites management dialog.
src/net/azib/ipscan/gui/fx/FXDetailsDialog.java Added JavaFX details dialog with comment editing.
src/net/azib/ipscan/gui/fx/feeders/FXRandomFeederGUI.java Added JavaFX RandomFeeder UI.
src/net/azib/ipscan/gui/fx/feeders/FXFileFeederGUI.java Added JavaFX FileFeeder UI.
src/net/azib/ipscan/gui/fx/feeders/FXFeederGUIRegistry.java Added JavaFX feeder registry and persistence of feeder UI state.
src/net/azib/ipscan/gui/fx/feeders/FXAbstractFeederGUI.java Added JavaFX feeder GUI base class implementing FeederCreator.
src/net/azib/ipscan/gui/fetchers/PortTextFetcherPrefs.java Deleted SWT PortText fetcher preferences dialog.
src/net/azib/ipscan/gui/fetchers/PortsFetcherPrefs.java Deleted SWT Ports fetcher preferences shim.
src/net/azib/ipscan/gui/fetchers/PingFetcherPrefs.java Deleted SWT Ping fetcher preferences shim.
src/net/azib/ipscan/gui/fetchers/MACFetcherPrefs.java Deleted SWT MAC fetcher preferences dialog.
src/net/azib/ipscan/gui/feeders/RandomFeederGUI.java Deleted SWT RandomFeeder UI.
src/net/azib/ipscan/gui/feeders/FileFeederGUI.java Deleted SWT FileFeeder UI.
src/net/azib/ipscan/gui/feeders/FeederSelectionCombo.java Deleted SWT feeder selection combo wrapper.
src/net/azib/ipscan/gui/feeders/FeederGUIRegistry.java Deleted SWT feeder registry.
src/net/azib/ipscan/gui/feeders/FeederArea.java Deleted SWT feeder area composite.
src/net/azib/ipscan/gui/feeders/ControlsArea.java Deleted SWT controls area composite.
src/net/azib/ipscan/gui/feeders/AbstractFeederGUI.java Deleted SWT feeder GUI base.
src/net/azib/ipscan/gui/EditFavoritesDialog.java Deleted SWT favorites editor dialog.
src/net/azib/ipscan/gui/DetailsWindow.java Deleted SWT details window.
src/net/azib/ipscan/gui/actions/ToolsActions.java Deleted SWT tools actions (selection logic/UI hooks).
src/net/azib/ipscan/gui/actions/TerminalLauncher.java Deleted SWT-era terminal launcher.
src/net/azib/ipscan/gui/actions/OpenerLauncher.java Deleted SWT-era opener launcher.
src/net/azib/ipscan/gui/actions/HelpMenuActions.java Deleted SWT help actions.
src/net/azib/ipscan/gui/actions/GotoMenuActions.java Deleted SWT goto actions.
src/net/azib/ipscan/gui/actions/FeederActions.java Deleted SWT feeder helper actions.
src/net/azib/ipscan/gui/actions/FavoritesMenuActions.java Deleted SWT favorites menu actions.
src/net/azib/ipscan/gui/actions/ColumnsActions.java Deleted SWT column header actions.
src/net/azib/ipscan/gui/actions/BrowserLauncher.java Deleted SWT Program.launch-based browser launcher.
src/net/azib/ipscan/gui/AbstractModalDialog.java Deleted SWT modal dialog base.
src/net/azib/ipscan/gui/AboutDialog.java Deleted SWT about dialog.
src/net/azib/ipscan/fetchers/PortTextFetcher.java Removed SWT preferences editor binding (prefs class now null).
src/net/azib/ipscan/fetchers/PortsFetcher.java Removed SWT preferences editor binding (prefs class now null).
src/net/azib/ipscan/fetchers/PingFetcher.java Removed SWT preferences editor binding (prefs class now null).
src/net/azib/ipscan/fetchers/OpenerLaunchFetcher.java Added fetcher providing a clickable “open” indicator value.
src/net/azib/ipscan/fetchers/OpenerColumnFetcher.java Added fetcher that displays per-IP default opener label/placeholder.
src/net/azib/ipscan/fetchers/MACFetcher.java Removed SWT preferences editor binding (prefs class now null).
src/net/azib/ipscan/fetchers/FetcherRegistry.java Simplified prefs editor instantiation; updated default selected fetchers.
src/net/azib/ipscan/exporters/TXTExporter.java Updated TXT import API to consume FeederCreator instead of GUI type.
src/net/azib/ipscan/core/ScanningResultList.java Added helpers for result snapshots, safe removals, and fetcher/result re-alignment.
src/net/azib/ipscan/core/ScanningResultComparator.java Added fallback comparison when typed compare fails (ClassCastException).
src/net/azib/ipscan/config/OpenersConfig.java Ensured default openers are always present and removed legacy opener.* keys.
src/net/azib/ipscan/config/GUIRegistry.java Deleted SWT GUI DI registration.
src/net/azib/ipscan/config/GUIConfig.java Added startup preference + column order persistence + feeder data helpers; removed SWT Point APIs.
src/net/azib/ipscan/config/FXComponentRegistry.java Added minimal JavaFX DI registration (Stage).
src/net/azib/ipscan/config/DefaultOpenerConfig.java Added file-based per-IP default opener persistence.
src/net/azib/ipscan/config/ConfigModule.java Registered DefaultOpenerConfig in DI container.
src/net/azib/ipscan/config/Config.java Added portable config directory resolution and exposed favorites/default openers accessors.
src/net/azib/ipscan/config/ComponentRegistry.java Registered opener fetchers and moved pinger plugin loading outside GUI-only init.
src/net/azib/ipscan/config/CommentsConfig.java Migrated comment persistence from Java Preferences to comments.txt in config dir.
run-javafx.bat Added local developer convenience script (currently machine-specific).
run-ipscan.bat Added local developer convenience script (currently machine-specific/outdated).
resources/messages.properties Updated/added strings for opener columns, comments editing, startup options.
resources/messages_zh_TW.properties Updated translated button.ipUp text.
resources/messages_zh_CN.properties Updated translated button.ipUp text.
resources/messages_tr.properties Updated translated button.ipUp text.
resources/messages_pt_BR.properties Updated translated button.ipUp text.
resources/messages_it.properties Updated translated button.ipUp text.
resources/messages_hu.properties Added/updated opener/startup strings; updated button.ipUp.
resources/messages_ga_IE.properties Updated translated button.ipUp text.
resources/messages_fr.properties Updated translated button.ipUp text.
resources/messages_fi.properties Updated translated button.ipUp text.
ext/jna.pro Updated ProGuard config to suppress warnings for removed SWT + added JavaFX classes.
classpath.gradle Added helper task to print runtimeClasspath.
build.gradle Added JavaFX plugin/modules, removed SWT packaging, updated jar/jlink packaging logic.
AGENTS.md Added repository guidance for agent/dev workflow verification.
.gitignore Added bin/, *.jar, and hs_err_pid logs.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +60 to +64
public String get(String ip) {
var openerName = defaults.getProperty(ip);
if (openerName != null) return openerName;
return Labels.getInstance().get("opener.ping");
}
Comment on lines +151 to +155
var oldName = listView.getItems().get(currentSelectionIndex);
var opener = openersConfig.getOpener(oldName);
var workingDir = workingDirText.getText().length() > 0 ? new File(workingDirText.getText()) : null;
openersConfig.add(nameText.getText(), new OpenersConfig.Opener(stringText.getText(), inTerminalCheck.isSelected(), workingDir));
listView.getItems().set(currentSelectionIndex, nameText.getText());
Comment thread run-javafx.bat Outdated
Comment on lines +3 to +7
set JAVA_HOME=C:\Users\peter\scoop\apps\openjdk21\current
set PATH=%JAVA_HOME%\bin;%PATH%
cd /d "I:\Angry IP Scanner\ipscan"

set GRADLE_CACHE=%USERPROFILE%\.gradle\caches\modules-2\files-2.1
Comment thread run-ipscan.bat Outdated
Comment on lines +3 to +7
set JAVA_HOME=C:\Users\peter\scoop\apps\openjdk21\current
set PATH=%JAVA_HOME%\bin;%PATH%
cd /d "I:\Angry IP Scanner\ipscan"
set PLUGIN_JAR=..\ipscan-tasmota-plugin\build\libs\ipscan-tasmota-plugin-1.0.1.jar
set SWT=C:\Users\peter\.gradle\caches\modules-2\files-2.1\org.eclipse.platform\org.eclipse.swt.win32.win32.x86_64\3.134.0\978f1c41438ebab37caf2e8d8446b420bf61c2a\org.eclipse.swt.win32.win32.x86_64-3.134.0.jar
Comment on lines +10 to +14
public class FeederGUIRegistryTest {
private FeederArea parent;
private FeederGUIRegistry registry;
private FeederSelectionCombo feederSelectionCombo;
private RangeFeederGUI feederGUI;

@Before
public void createRegistry() {
parent = new FeederArea(new Shell());

feederSelectionCombo = mock(FeederSelectionCombo.class);

feederGUI = new RangeFeederGUI(parent);
feederGUI.initialize();
registry = new FeederGUIRegistry(Collections.singletonList(feederGUI), feederSelectionCombo, null);
}

@After
public void dispose() {
parent.dispose();
}

@Test
public void addFeederNamesToTheCombo() throws Exception {
reset(feederSelectionCombo);
new FeederGUIRegistry(Collections.singletonList(feederGUI), feederSelectionCombo, null);
verify(feederSelectionCombo).add(Labels.getLabel(feederGUI.getFeederId()));
}

@Test
public void lastFeederIsNeverNull() throws Exception {
assertNotNull(registry.lastFeeder);
assertNotNull(registry.lastFeeder.toString());
}

@Test
public void createFeederRemembersTheLastOne() throws Exception {
var lastFeeder = registry.createFeeder();
assertSame(lastFeeder, registry.lastFeeder);
assertNotSame(lastFeeder, registry.createFeeder());
public void rangeFeederIsNeverNull() throws Exception {
var feeder = new RangeFeeder("127.0.0.1", "127.0.0.2");
Comment thread src/net/azib/ipscan/gui/fx/FXGUI.java Outdated
Comment on lines +132 to +135
var stream = FXGUI.class.getResourceAsStream(path);
if (stream != null) {
javafx.scene.text.Font.loadFont(stream, -1);
}
zaum added 23 commits September 3, 2026 09:19
…for setting and opening with default openers
…alog

- Removed SelectFetchersDialog from MacApplicationMenu and MainWindow.
- Updated MacApplicationMenu constructor and initialization to exclude SelectFetchersDialog.
- Adjusted MainWindow to remove references to SelectFetchersDialog and its related listener.
- Cleaned up related code in ResultTable to handle fetcher visibility and interactions without SelectFetchersDialog.
- Introduced ColumnVisibilityMenu to manage column visibility directly from the header context menu.
- Enhanced ResultTable to support dynamic column visibility and reordering.
- Updated various actions and menu items to reflect the removal of SelectFetchersDialog.
…llback to text comparison; update ResultTable event handling for control-relative coordinates; refactor ColumnsActions to remove unused ColumnsMenu and improve column sorting logic.
…e updated getColumnOrder() yet when the Move event fires
Replace the MouseMove-based HeaderTooltipHandler with a HeaderTooltipPoller: on Windows the table header is a separate native SysHeader32 control, so Table-level mouse events never fire over it and the tooltip either showed in the wrong place or never at all. The poller checks the cursor position every 100ms via Display.timerExec, shows the width-capped (360px) wrapping fetcher info tooltip after a 2000ms hover delay, hides it on focus loss/outside-header/rows, and resolves the hovered column in visual order so drag-reordered columns map correctly.
TableItem.setText()/getTextBounds() index columns in MODEL (creation) order: write row values to modelCol instead of the visual position, and detect the clicked visual column by summing widths in visual (getColumnOrder) order in the double-click, opener-triangle and Details double-click handlers.
…nch cooldown (port 3e8f233, e120035)

Render the OpenerLaunch triangle only when an Opener is assigned to the row, update both opener columns atomically via updateOpenerAssignment(), run launches on a background thread guarded by a cooldown so rapid clicks cannot queue up many openers, and drop the first-opener fallback.
Set each header text immediately at column creation and rebuild the column set from scratch in updateColumnNames(): on Windows the native header may map setText() calls to stale positions after a drag-reorder.
…ateAutoFitButtonColumn to SWT)

Fixed 46px '<->' header button as the first model column (mirrors the JavaFX autofit button): clicking it packs every fetcher column to fit content. It carries no Fetcher, so rendering, column-order persistence, hit-testing, tooltips and moveability explicitly skip it; the status icon now follows the IP column's model slot.
- Precompute a column-to-fetcher index map to avoid repeated getFetcherIndex calls during virtual table rendering; batch UI updates in populateNewFetcher (100 rows per asyncExec instead of one per row); precompute fetcher positions in ScanningResultList.syncFetchers (port of new-features 39b5cf1)
- Shorter header tooltip delay (1s), tooltip for the leading autofit column, tooltip width now fits the text (capped as before)
- Size the autofit column via pack() after clearAll() so it keeps a fixed small width on column rebuilds (stale item text would otherwise be measured)
- Force a full repaint after column rebuilds: Win32 does not always invalidate the client area (blank results after closing a modal dialog such as Preferences)
- Refresh the table immediately before the first batch of network scans when populating a newly added column, and guarantee setRedraw(true) via try/finally
…nfig untouched

Edits are now applied to an in-memory working copy of the openers; the shared OpenersConfig is only updated when OK is pressed (port of new-features 9fc43b2). Deleted openers are dropped from the working copy too, so re-adding an opener with the same name starts fresh.
If the selection loop threw while redraw was disabled, the result table would stay blank until restarted. Also fixes indentation of the loop body.
- Config.getConfigDir: probe writability with a temp file (canWrite lies under Program Files); wire DefaultOpenerConfig as singleton, public forFavorites

- OpenersConfig: drop legacy opener.* keys before re-adding defaults

- GUIConfig: add get/setFeederData helpers (SWT Point APIs kept)

- ScanningResultList: add getResultsSnapshot + removeExcept (syncFetchers perf already ported in b6f2064)
zaum added 2 commits September 5, 2026 12:06
Plain jar builds lack the Version/Build-Date manifest entries, which left getVersion() null and crashed callers with NPE. Fall back to current/today.
…fault width logic, implement debounced saving on resize
- OpenerLauncher: fall back to the IP for missing fetcher values, but throw for typos in fetcher references (hybrid of the old and new behavior)
- OpenerLauncher: use double quotes on Windows (cmd.exe does not treat single quotes as quoting) - fixes openers like Ping failing with 'Unable to resolve target system name'
- FetcherRegistry: add isRegisteredFetcher() to distinguish unknown fetchers from unselected ones
- PluginLoader: decode percent-encoded resource paths so spaces in the installation path work
- TXTExporterTest: resolve test resources via toURI() (also fixes paths with spaces)
- AbstractPingerTest: ping a locally opened ServerSocket port to make pingAlive deterministic behind firewalls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants